This is caused by daylight saving time not being returned correctly in the duration instant.
Use milliseconds instead.
I don't understand, what does UTC have to do with it? From 08:00 to 9:00 it is always an hour ... but if I subtract 1 hour, the result doesn't change or does it change when the daylight saving time changes? could you post an example? thanks
And this is exactly the reason why I created the extension:
From my extension description:
"Hence this extension (some of it can also be implemented with the on-board methods, but I want to simplify it:)"
Exactly.....
I don't know. We have done this before
I just know that once you get down to doing durations of milliseconds that calculation/format adds an hour - sometimes....
Yes, see also the grayed out blocks in my extension description.
To understand this behavior, we have to be rigorous about the definitions of the terms
- Instant
- Duration
An Instant is a milestone on the road of time. The road starts in the year 1970.
Some Instants are Milestones in today's section of the road, starting at midnight, depending on where you got them (DatePicker vs TimePicker, etc.)
You can tell you have an Instant when you try to display it as text and you get a lot of labelled details you did not expect.
A Duration is a pure number of milliseconds, usually gotten by a Clock block of that name or by subtracting instances of Clock1.SystemTime.
Now let's examine the OP's blocks ...
I circled the fatal assignment. (The Blocks Editor occasionally saves you from linking incompatible blocks, but apparently not here.)
The FormatTime block was asking for an Instant.
You did not give it an Instant.
You gave it a Duration.
I did not check the documentation for the FormatTime block to see how it should respond to such abuse. I would be surprised to see if it has an explicit response to this.
As the old motto goes,
Garbage In
Garbage Out.
P.S. Here is a copy of the Clock docs, for Yandex to translate for you ...
Clock
Non-visible component that provides the instant in time using the internal clock on the phone. It can fire a timer at regularly set intervals and perform time calculations, manipulations, and conversions.
Operations on dates and times, such as from DatePicker
and TimePicker
, are accomplished through methods in Clock. Date and Time are represented as InstantInTime and Duration.
-
Instant : consists of Year, Month, DayOfMnoth, Hour, Minute, and SEcond. An instant can be created using the
MakeInstant
,MakeInstantFromMillis
andMakeInstantFromParts
methods. -
Duration : time in milliseconds elapsed between instants. Duration can be obtained by the
Duration
method.
Instants are assumed to be in the device’s local time zone. When they are converted to or from milliseconds, the milliseconds for a given Instance are calculated from January 1, 1970 in UTC (Greenwich Mean Time).
Methods to convert an Instant to text are also available. Acceptable patterns are empty string, MM/dd/YYYY HH:mm:ss a
, or MMM d, yyyy HH:mm
. The empty string will provide the default format, which is "MMM d, yyyy HH:mm:ss a"
for FormatDateTime
, "MMM d, yyyy"
for FormatDate
. To see all possible formats, please see here.
A note on combining date and time: In order to combine the date from one Instant and the time from another, for example from a DatePicker
and TimePicker
, extract the parts as text and use the text to create a new Instant. For example:
Properties
TimerAlwaysFires
Will fire even when application is not showing on the screen if true
TimerEnabled
Specifies whether the Timer
event should run.
TimerInterval
Specifies the interval between subsequent Timer
events.
Note : Drift may occur over time and that the system may not honor the timing specified here if the app or another process on the phone is busy.
Events
Timer()
The Timer event runs when the timer has gone off.
Methods
AddDays( instant , quantity )
Returns an instant in time some days after the given instant.
AddDuration( instant , quantity )
Returns an instant in time some duration after the argument
AddHours( instant , quantity )
Returns an instant in time some hours after the given instant.
AddMinutes( instant , quantity )
Returns an instant in time some minutes after the given instant.
AddMonths( instant , quantity )
Returns an instant in time some months after the given instant.
AddSeconds( instant , quantity )
Returns an instant in time some seconds after the given instant.
AddWeeks( instant , quantity )
Returns An instant in time some weeks after the given instant.
AddYears( instant , quantity )
Returns an instant in time some years after the given instant.
DayOfMonth( instant )
Returns the day of the month.
Duration( start , end )
Returns the milliseconds by which end follows start (+ or -)
DurationToDays( duration )
Returns the duration converted from milliseconds to days.
DurationToHours( duration )
Returns the duration converted from milliseconds to hours.
DurationToMinutes( duration )
Returns the duration converted from milliseconds to minutes.
DurationToSeconds( duration )
Returns the duration converted from milliseconds to seconds.
DurationToWeeks( duration )
Returns the duration converted from milliseconds to weeks.
FormatDate( instant , pattern )
Converts and formats an instant into a string of date with the specified pattern. To learn more about valid patterns, please see SimpleDateFormat.
FormatDateTime( instant , pattern )
Converts and formats an instant into a string of date and time with the specified pattern. To learn more about valid patterns, please see SimpleDateFormat.
FormatTime( instant )
Converts and formats the given instant into a string with the specified pattern. To learn more about valid patterns, please see SimpleDateFormat.
GetMillis( instant )
Returns the instant in time measured as milliseconds since 1970.
Hour( instant )
Returns the hours for the given date.
MakeDate( year , month , day )
Returns an instant in time specified by year, month, date in UTC. Valid values for the month field are 1-12 and 1-31 for the day field.
MakeInstant( from )
Returns an instant in time specified by MM/dd/YYYY hh:mm:ss or MM/dd/YYYY or hh:mm.
MakeInstantFromMillis( millis )
Returns an instant in time specified by the milliseconds since 1970 in UTC.
MakeInstantFromParts( year , month , day , hour , minute , second )
Returns an instant in time specified by year, month, date, hour, minute, second in UTC.
MakeTime( hour , minute , second )
Returns an instant in time specified by hour, minute, second in UTC.
Minute( instant )
Returns the minutes for the given date.
Month( instant )
Returns the number of the month for the given instant.
MonthName( instant )
Returns the name of the month for the given instant.
Now()
Returns the current instant in time read from phone’s clock.
Second( instant )
Returns the seconds for the given instant.
SystemTime()
Returns the phone’s internal time.
Weekday( instant )
Returns the weekday for the given instant.
WeekdayName( instant )
Returns the name of the weekday for the given instant.
Year( instant )
Returns the year of the given instant.
I neglected to define Milliseconds with a Capital M before, when I defined Instants and Duration. In the Clock component, Milliseconds mean the number of milliseconds of a given Instant after a certain point in 1970. In other words milliseconds is not a Duration, but instead is the expression of an Instant in time by its offset from the zero Instant in 1970.
New let's examine the latest bogus calculation closely:
Like stomping on a lump under the rug, the type mismatch has moved to a new socket.
All that had been happening so far is not the measurement of a Duration, but instead it has been taking a stab at determination of the hour of the day when the measurement of time started, at 1 AM on a certain day in 1970.
But is shows that format time block just gets the millisecond value from the instant, or accepts a millisecond value
This is what causes the problem:
(in my locale....?)
Here's some more experimental evidence ...
It's not time, it's space!
My MemuPlay emulator was born in China, in a different time zone than your test devices, which likely return different values to these blocks.
The answer was in the Instant expansions from further back in this thread ...
The zone offset is geographically based.
It's bonkers!!
Here's my zone offset, as extra evidence.