www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Time from timestamp?

reply "Chris Williams" <yoreanon-chrisw yahoo.co.jp> writes:
I'm attempting to print a human-readable version of a timestamp. 
The timestamp is coming from an external service, via JSON. An 
example is:

1421865781342

Which I know to be:

2015-01-21T18:43:01.342Z

The only method I see which takes an epoch-style timestamp, so 
that I can convert it to something printable, is the SysTime 
constructor:

pure nothrow  safe this(long stdTime, immutable TimeZone tz = 
null);

According to the reference, this seems to take the value in 
hnsecs. My expectation would be that this means multiplying my 
initial value by 1_000_000. But if I do that, I get a random date 
2500 years in the future.

I created this sample code:

void main() {
     long time = 1421865781342L;
     writefln("%s", SysTime(time));
     writefln("%s", SysTime(time * 10L));
     writefln("%s", SysTime(time * 100L));
     writefln("%s", SysTime(time * 1_000L));
     writefln("%s", SysTime(time * 10_000L));
     writefln("%s", SysTime(time * 100_000L));
     writefln("%s", SysTime(time * 1_000_000L));

     writefln("%s", Clock.currTime.stdTime);
}

Outputs:

0001-Jan-02 07:36:48.5781342
0001-Jan-17 03:04:47.781342
0001-Jun-14 05:44:39.81342
0005-Jul-04 08:23:20.1342
0046-Jan-21 10:50:03.342
0451-Jul-28 11:17:15.42
4506-Sep-18 16:42:14.2
635582516

My expectation would be that the final line would be something 
beginning with "14" at least. Playing around with possible 
multipliers, there doesn't even seem to be any integer value that 
would allow conversion between the timestamp I received and 
whatever SysTime expects.

I'm using:

DMD64 D Compiler v2.066.1
Ubuntu from .deb package

Is this a bug, or am I doing something wrong?
Jan 30 2015
next sibling parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
On 31/01/2015 11:18 a.m., Chris Williams wrote:
 I'm attempting to print a human-readable version of a timestamp. The
 timestamp is coming from an external service, via JSON. An example is:

 1421865781342

 Which I know to be:

 2015-01-21T18:43:01.342Z

 The only method I see which takes an epoch-style timestamp, so that I
 can convert it to something printable, is the SysTime constructor:

 pure nothrow  safe this(long stdTime, immutable TimeZone tz = null);

 According to the reference, this seems to take the value in hnsecs. My
 expectation would be that this means multiplying my initial value by
 1_000_000. But if I do that, I get a random date 2500 years in the future.

 I created this sample code:

 void main() {
      long time = 1421865781342L;
      writefln("%s", SysTime(time));
      writefln("%s", SysTime(time * 10L));
      writefln("%s", SysTime(time * 100L));
      writefln("%s", SysTime(time * 1_000L));
      writefln("%s", SysTime(time * 10_000L));
      writefln("%s", SysTime(time * 100_000L));
      writefln("%s", SysTime(time * 1_000_000L));

      writefln("%s", Clock.currTime.stdTime);
 }

 Outputs:

 0001-Jan-02 07:36:48.5781342
 0001-Jan-17 03:04:47.781342
 0001-Jun-14 05:44:39.81342
 0005-Jul-04 08:23:20.1342
 0046-Jan-21 10:50:03.342
 0451-Jul-28 11:17:15.42
 4506-Sep-18 16:42:14.2
 635582516

 My expectation would be that the final line would be something beginning
 with "14" at least. Playing around with possible multipliers, there
 doesn't even seem to be any integer value that would allow conversion
 between the timestamp I received and whatever SysTime expects.

 I'm using:

 DMD64 D Compiler v2.066.1
 Ubuntu from .deb package

 Is this a bug, or am I doing something wrong?
On a slightly related note, I have code for UTC+0 to unix time stamp. https://github.com/Devisualization/util/blob/b9ab5758e755c4e33832ac4aed0a5d7f2c728faf/source/core/devisualization/util/core/time.d
Jan 30 2015
parent reply "Chris Williams" <yoreanon-chrisw yahoo.co.jp> writes:
On Friday, 30 January 2015 at 22:22:27 UTC, Rikki Cattermole 
wrote:
 On a slightly related note, I have code for UTC+0 to unix time 
 stamp.
 https://github.com/Devisualization/util/blob/b9ab5758e755c4e33832ac4aed0a5d7f2c728faf/source/core/devisualization/util/core/time.d
Unix timestamps can be negative, so you should probably be using longs instead of ulongs.
Jan 30 2015
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 30 Jan 2015 22:38:20 +0000, Chris Williams wrote:

 Unix timestamps can be negative
WUT?! O_O=
Jan 30 2015
parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
On 31/01/2015 12:06 p.m., ketmar wrote:
 On Fri, 30 Jan 2015 22:38:20 +0000, Chris Williams wrote:

 Unix timestamps can be negative
WUT?! O_O
Looks like we are both thinking the usual case. The standard Unix time_t (data type representing a point in time) is a signed integer data type, traditionally of 32 bits (but see below), directly encoding the Unix time number as described in the preceding section. Being 32 bits means that it covers a range of about 136 years in total. The minimum representable time is 1901-12-13, and the maximum representable time is 2038-01-19. The second after 03:14:07 UTC 2038-01-19 this representation overflows. This milestone is anticipated with a mixture of amusement and dread; see year 2038 problem. From wikipedia. https://github.com/D-Programming-Language/druntime/blob/master/src/core/stdc/time.d#L68 Looks like I got to modify it.
Jan 30 2015
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Sat, 31 Jan 2015 12:12:08 +1300, Rikki Cattermole wrote:

 On 31/01/2015 12:06 p.m., ketmar wrote:
 On Fri, 30 Jan 2015 22:38:20 +0000, Chris Williams wrote:

 Unix timestamps can be negative
WUT?! O_O
=20 Looks like we are both thinking the usual case. =20 The standard Unix time_t (data type representing a point in time) is a signed integer data type, traditionally of 32 bits (but see below), directly encoding the Unix time number as described in the preceding section. Being 32 bits means that it covers a range of about 136 years in total. The minimum representable time is 1901-12-13, and the maximum representable time is 2038-01-19. The second after 03:14:07 UTC 2038-01-19 this representation overflows. This milestone is anticipated with a mixture of amusement and dread; see year 2038 problem. =20 From wikipedia. =20 https://github.com/D-Programming-Language/druntime/blob/master/src/core/
stdc/time.d#L68
=20
 Looks like I got to modify it.
nobody ever planned "negative timestamps". using signed time_t was just a=20 design error (nobody cares at the time). unix timestamps are timestamps=20 for things created in unix. i can't imagine how you can create something=20 BEFORE the unix itself (hence 1970 as a starting point -- with some gap=20 to allow older files). there is no such thing as "negative timestamp", any negative timestamp is=20 a bug.=
Jan 30 2015
prev sibling parent reply "Chris Williams" <yoreanon-chrisw yahoo.co.jp> writes:
On Friday, 30 January 2015 at 22:38:21 UTC, Chris Williams wrote:
 On Friday, 30 January 2015 at 22:22:27 UTC, Rikki Cattermole 
 wrote:
 On a slightly related note, I have code for UTC+0 to unix time 
 stamp.
 https://github.com/Devisualization/util/blob/b9ab5758e755c4e33832ac4aed0a5d7f2c728faf/source/core/devisualization/util/core/time.d
Unix timestamps can be negative, so you should probably be using longs instead of ulongs.
Yup, there was a world before January 1st, 1970.
Jan 30 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Fri, 30 Jan 2015 23:42:04 +0000, Chris Williams wrote:

 On Friday, 30 January 2015 at 22:38:21 UTC, Chris Williams wrote:
 On Friday, 30 January 2015 at 22:22:27 UTC, Rikki Cattermole wrote:
 On a slightly related note, I have code for UTC+0 to unix time stamp.
 https://github.com/Devisualization/util/blob/
b9ab5758e755c4e33832ac4aed0a5d7f2c728faf/source/core/devisualization/util/ core/time.d
 Unix timestamps can be negative, so you should probably be using longs
 instead of ulongs.
=20 Yup, there was a world before January 1st, 1970.
not for unix timestamps. please, stop that, unix timestamp was not=20 designed to present any dates before 1970. "negative timestamp" is a bug=20 in code.=
Jan 30 2015
parent reply "Chris Williams" <yoreanon-chrisw yahoo.co.jp> writes:
On Friday, 30 January 2015 at 23:50:53 UTC, ketmar wrote:
 On Fri, 30 Jan 2015 23:42:04 +0000, Chris Williams wrote:

 On Friday, 30 January 2015 at 22:38:21 UTC, Chris Williams 
 wrote:
 On Friday, 30 January 2015 at 22:22:27 UTC, Rikki Cattermole 
 wrote:
 On a slightly related note, I have code for UTC+0 to unix 
 time stamp.
 https://github.com/Devisualization/util/blob/
b9ab5758e755c4e33832ac4aed0a5d7f2c728faf/source/core/devisualization/util/ core/time.d
 Unix timestamps can be negative, so you should probably be 
 using longs
 instead of ulongs.
Yup, there was a world before January 1st, 1970.
not for unix timestamps. please, stop that, unix timestamp was not designed to present any dates before 1970. "negative timestamp" is a bug in code.
Unless you know something I don't, everything I've ever read says that a negative unix timestamp is meant to refer to a time before 1970. It may not have been intentional, but since most database software probably stores birthdates (many of which are pre-1970) in this format, having a library be unable to support them just makes the library useless for many situations.
Jan 30 2015
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sat, 31 Jan 2015 00:03:43 +0000, Chris Williams wrote:

 since most database software probably
 stores birthdates (many of which are pre-1970) in this format
O_O a perfectly broken software.=
Jan 30 2015
parent "Chris Williams" <yoreanon-chrisw yahoo.co.jp> writes:
On Saturday, 31 January 2015 at 00:20:07 UTC, ketmar wrote:
 On Sat, 31 Jan 2015 00:03:43 +0000, Chris Williams wrote:

 since most database software probably
 stores birthdates (many of which are pre-1970) in this format
O_O a perfectly broken software.
And stdc: http://h50146.www5.hp.com/products/software/oe/tru64unix/manual/v51a_ref/HTML/MAN/MAN3/3955____.HTM And UNIX: http://www.lehman.cuny.edu/cgi-bin/man-cgi?mktime+3
Jan 30 2015
prev sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/30/15 5:18 PM, Chris Williams wrote:
 I'm attempting to print a human-readable version of a timestamp. The
 timestamp is coming from an external service, via JSON. An example is:

 1421865781342

 Which I know to be:

 2015-01-21T18:43:01.342Z
http://dlang.org/phobos/std_datetime.html#.unixTimeToStdTime It's kind of convoluted because there is no epoch, but you can make one: import std.datetime; import std.stdio; void main(string[] args) { // can't make this enum because of time zone... auto epoch = SysTime(unixTimeToStdTime(0), UTC()); writeln(epoch + 1_421_865_781_342.msecs); } output: 2015-Jan-21 18:43:01.342Z Note the reason your code didn't work is because SysTime uses 1/1/1 as the epoch. -Steve
Jan 30 2015
next sibling parent "Chris Williams" <yoreanon-chrisw yahoo.co.jp> writes:
On Saturday, 31 January 2015 at 00:14:37 UTC, Steven 
Schveighoffer wrote:
 On 1/30/15 5:18 PM, Chris Williams wrote:
 I'm attempting to print a human-readable version of a 
 timestamp. The
 timestamp is coming from an external service, via JSON. An 
 example is:

 1421865781342

 Which I know to be:

 2015-01-21T18:43:01.342Z
http://dlang.org/phobos/std_datetime.html#.unixTimeToStdTime It's kind of convoluted because there is no epoch, but you can make one: import std.datetime; import std.stdio; void main(string[] args) { // can't make this enum because of time zone... auto epoch = SysTime(unixTimeToStdTime(0), UTC()); writeln(epoch + 1_421_865_781_342.msecs); } output: 2015-Jan-21 18:43:01.342Z Note the reason your code didn't work is because SysTime uses 1/1/1 as the epoch. -Steve
D'oh, I missed that in the description: "and convert it to hnsecs in UTC since midnight, January 1st, 1 A.D. UTC" That does explain it. I also didn't spot the declaration of unixTimeToStdTime(), which assuredly helps. Thank you!
Jan 30 2015
prev sibling next sibling parent Jonathan M Davis via Digitalmars-d-learn writes:
On Friday, January 30, 2015 19:14:37 Steven Schveighoffer via
Digitalmars-d-learn wrote:
 On 1/30/15 5:18 PM, Chris Williams wrote:
 I'm attempting to print a human-readable version of a timestamp. The
 timestamp is coming from an external service, via JSON. An example is:

 1421865781342

 Which I know to be:

 2015-01-21T18:43:01.342Z
http://dlang.org/phobos/std_datetime.html#.unixTimeToStdTime It's kind of convoluted because there is no epoch, but you can make one: import std.datetime; import std.stdio; void main(string[] args) { // can't make this enum because of time zone... auto epoch = SysTime(unixTimeToStdTime(0), UTC()); writeln(epoch + 1_421_865_781_342.msecs); } output: 2015-Jan-21 18:43:01.342Z Note the reason your code didn't work is because SysTime uses 1/1/1 as the epoch.
Yeah. I really should add a unixTimeToSysTime function, but when I originally wrote std.datetime, I wasn't thinking about getting times from C stuff and converting them to D, just the other way around (a stupid oversight in retrospect). The functionality is there, but it's more convoluted than it should be. And the term "std time" was stupid on my part too, since there's nothing standard about it except that it uses midnight of 1/1/1 as the epoch like the ISO standard says (but that has nothing to do with hnsecs). Oh well, too late now, and I still don't know what a good name for it would have been. I'll have to put adding unixTimeToSysTime on the list of things to do after finish splitting std.datetime (which I started again the other day but is going more slowly than I'd like, since I've been rather busy). I also need to update the "Introduction to std.datetime" article so that it talks more about stuff like that than the now defunct std.date. When Walter was dealing with some of that recently, he thought that it should focus more on interacting with C than std.date, which makes sense at this point (though, since he was porting something old from std.date, it's current state was presumably useful to him). Too much to do, too little time... - Jonathan M Davis
Jan 30 2015
prev sibling parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Friday, January 30, 2015 22:03:02 Jonathan M Davis via Digitalmars-d-learn
wrote:
 Yeah. I really should add a unixTimeToSysTime function,
Actually, maybe it should be a static function on SysTime called fromUnixTime to go with toUnixTime. I don't know. Regardless, it's a nicety that should be there, and I botched things by not having it. - Jonathan M Davis
Jan 30 2015
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 1/31/15 1:07 AM, Jonathan M Davis via Digitalmars-d-learn wrote:
 On Friday, January 30, 2015 22:03:02 Jonathan M Davis via Digitalmars-d-learn
wrote:
 Yeah. I really should add a unixTimeToSysTime function,
Actually, maybe it should be a static function on SysTime called fromUnixTime to go with toUnixTime. I don't know. Regardless, it's a nicety that should be there, and I botched things by not having it.
Might I suggest that you simply define an enum for UnixEpoch that's a SysTime. Then you can do whatever you want. Note that unixTimeToSysTime doesn't help the OP, his timestamp is in milliseconds since 1/1/1970. -Steve
Feb 02 2015
parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Monday, February 02, 2015 08:49:58 Steven Schveighoffer via
Digitalmars-d-learn wrote:
 On 1/31/15 1:07 AM, Jonathan M Davis via Digitalmars-d-learn wrote:
 On Friday, January 30, 2015 22:03:02 Jonathan M Davis via Digitalmars-d-learn
wrote:
 Yeah. I really should add a unixTimeToSysTime function,
Actually, maybe it should be a static function on SysTime called fromUnixTime to go with toUnixTime. I don't know. Regardless, it's a nicety that should be there, and I botched things by not having it.
Might I suggest that you simply define an enum for UnixEpoch that's a SysTime. Then you can do whatever you want. Note that unixTimeToSysTime doesn't help the OP, his timestamp is in milliseconds since 1/1/1970.
Then I should probably just do both - declare a function to do the conversion (since that's more user-friendly for the common case) and supply an enum for the unix epoch if someone is converting to something like milliseconds instead of seconds for the unix epoch. - Jonathan M Davis
Feb 02 2015
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 2/2/15 10:06 AM, Jonathan M Davis via Digitalmars-d-learn wrote:
 On Monday, February 02, 2015 08:49:58 Steven Schveighoffer via
Digitalmars-d-learn wrote:
 On 1/31/15 1:07 AM, Jonathan M Davis via Digitalmars-d-learn wrote:
 On Friday, January 30, 2015 22:03:02 Jonathan M Davis via Digitalmars-d-learn
wrote:
 Yeah. I really should add a unixTimeToSysTime function,
Actually, maybe it should be a static function on SysTime called fromUnixTime to go with toUnixTime. I don't know. Regardless, it's a nicety that should be there, and I botched things by not having it.
Might I suggest that you simply define an enum for UnixEpoch that's a SysTime. Then you can do whatever you want. Note that unixTimeToSysTime doesn't help the OP, his timestamp is in milliseconds since 1/1/1970.
Then I should probably just do both - declare a function to do the conversion (since that's more user-friendly for the common case) and supply an enum for the unix epoch if someone is converting to something like milliseconds instead of seconds for the unix epoch.
You already have various unixTimeToXXX functions, so it's probably moot, but with an epoch, such operations are dead simple: auto t = UnixEpoch + time().seconds; I see very little value in a wrapper function to do this. But it's already there, so... BTW, I think with UFCS, having the 'seconds' etc. functions is one of the coolest parts of D's time library. I love that part :) -Steve
Feb 02 2015