Thread overview
Clock.currTime differs from SysTime
Aug 25, 2018
Ivo
Aug 25, 2018
Jonathan M Davis
Aug 25, 2018
Ivo
August 25, 2018
I am using Clock.currTime.stdTime to get a unique timestamp in my program.
Now I need to produce something similar in a different programming language; so I'm trying to understand how Clock.currTime works.

According the the documentation Clock.currTime.stdTime should return the number of hnseconds since 00:00 of 01/01/0001 A.D. UTC. However it seems that it returns less than what claimed.

Consider the following code:

import std.stdio;
import std.datetime.date : DateTime;
import std.datetime.timezone : UTC;
import std.datetime.systime;

void main() {

auto now = Clock.currTime;
auto date = DateTime(2018, 8, 25, 14, 42, 0); //this is changed manually
auto st = SysTime(date, UTC());
writeln(st.stdTime);
writeln(st.toISOExtString);
writeln(now.stdTime);
writeln(now.toISOExtString);

}

I'm done a few tries and here is an output:
636708049200000000 //this is st.stdTime
2018-08-25T14:42:00Z
636707977205129550 //this is now.stdTime
2018-08-25T14:42:00.512955

So here is the problem: the difference in time is less than 0.6 seconds (according to the strings), nevertheless the difference of the 2 numbers is 71994870450.
71994870450 hnsecs = 71994870450 x 10^{-7} secs = 7199,487045 secs (unless my maths is wrong)

So what actually is Clock.currTime.stdTime counting?

August 25, 2018
On Saturday, August 25, 2018 6:53:24 AM MDT Ivo via Digitalmars-d-learn wrote:
> I am using Clock.currTime.stdTime to get a unique timestamp in my
> program.
> Now I need to produce something similar in a different
> programming language; so I'm trying to understand how
> Clock.currTime works.
>
> According the the documentation Clock.currTime.stdTime should return the number of hnseconds since 00:00 of 01/01/0001 A.D. UTC. However it seems that it returns less than what claimed.
>
> Consider the following code:
>
> import std.stdio;
> import std.datetime.date : DateTime;
> import std.datetime.timezone : UTC;
> import std.datetime.systime;
>
> void main() {
>
> auto now = Clock.currTime;
> auto date = DateTime(2018, 8, 25, 14, 42, 0); //this is changed
> manually
> auto st = SysTime(date, UTC());
> writeln(st.stdTime);
> writeln(st.toISOExtString);
> writeln(now.stdTime);
> writeln(now.toISOExtString);
>
> }
>
> I'm done a few tries and here is an output:
> 636708049200000000 //this is st.stdTime
> 2018-08-25T14:42:00Z
> 636707977205129550 //this is now.stdTime
> 2018-08-25T14:42:00.512955
>
> So here is the problem: the difference in time is less than 0.6
> seconds (according to the strings), nevertheless the difference
> of the 2 numbers is 71994870450.
> 71994870450 hnsecs = 71994870450 x 10^{-7} secs = 7199,487045
> secs (unless my maths is wrong)
>
> So what actually is Clock.currTime.stdTime counting?

By default, Clock.currTime returns a SysTime with LocalTime as the TimeZone. stdTime is always in UTC. So, now's TimeZone is LocalTime, and when you print it out as a string, you get the date and time in your local time zone (which you can tell by the lack of time zone information on the end of the string), whereas when you then construct a SysTime using the same date and time as your local time zone but tell it that it's in UTC, then the two values are going to be off by the offset between your local time zone and UTC - and of course, casting to DateTime strips off the fractional seconds.

If you want to cast a SysTime to DateTime and then construct a SysTime from it again, then you need to construct the SysTime with the same TimeZone, or they won't be the same.

And sadly, even if you _do_ do that, and the time was right on the second (so that there are no fractional seconds), they _still_ might not be the same if the date and time are near a DST switch. Even though it _usually_ works to convert between a time zone and UTC, in the general case, it's impossible - with some DST switches you get times that are completely skipped and thus technically aren't valid, whereas at other DST switches, you have times that happen twice, resulting in ambiguity. That's why SysTime always holds the time internally in UTC rather than in whatever time zone it's set to. The TimeZone object is just used when a function on SysTime requires that it be converted out of UTC (e.g. when printing out a string or using a property like year). Unfortunately, that still leaves a problem of what to do when constructing a SysTime from date and time during a DST switch, and SysTime does it's best, but unfortunately, trying to convert from a time zone to UTC is inherently a buggy process.

In this particular case, DST almost certainly was not a factor, but you still ran into problems, because you used a different time zone when constructing the new object. So, while it's certainly sometimes necessary to construct a SysTime from a DateTime (or separate numbers), it's almost always better to leave the result of Clock.currTime as a SysTime rather than doing something like casting to DateTime and then constructing another SysTime from it. Done "correctly," it will work most of the time, but you'll still be screwed around DST switches.

- Jonathan M Davis



August 25, 2018
Thanks a lot.
The issue was indeed the time zone.