www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Clock.currTime differs from SysTime

reply Ivo <ivo asdasdl.com> writes:
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?
Aug 25 2018
parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
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
Aug 25 2018
parent Ivo <ivo asdasdl.com> writes:
Thanks a lot.
The issue was indeed the time zone.
Aug 25 2018