www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - std.date

reply Steve Teale <steve.teale britseyeview.com> writes:
I have moaned several times about the fact that this module does not have a
method for creating a date from the system clock.

It provides a parse method to convert a string in a limited number of formats.
In the course of doing that, it calls the OS primitive to get the time zone
offset.

So why the omission? If it's going to use the OS, why not go the whole hog.

It also strikes me as odd that it does not include a table of leap seconds. As
it stands, some of its methods could return values that were out by a year for
up to four or five seconds on January 1 2011. I'm no expert on UTC, Gregorian
Calendar and such, so I could well be wrong, but ....

Phobos doesn't really need the burden of such tasks. Most OS's provide regular
upgrades that cover this stuff.

Steve
Nov 16 2010
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 16 Nov 2010 14:11:05 -0500, Steve Teale  
<steve.teale britseyeview.com> wrote:

 I have moaned several times about the fact that this module does not  
 have a method for creating a date from the system clock.

 It provides a parse method to convert a string in a limited number of  
 formats. In the course of doing that, it calls the OS primitive to get  
 the time zone offset.

 So why the omission? If it's going to use the OS, why not go the whole  
 hog.

 It also strikes me as odd that it does not include a table of leap  
 seconds. As it stands, some of its methods could return values that were  
 out by a year for up to four or five seconds on January 1 2011. I'm no  
 expert on UTC, Gregorian Calendar and such, so I could well be wrong,  
 but ....

 Phobos doesn't really need the burden of such tasks. Most OS's provide  
 regular upgrades that cover this stuff.
Jonathan Davis has been creating a date/time library that will replace std.time. See earlier posts on this newsgroup about std.datetime updates Please comment if you think there are problems with it. -Steve
Nov 16 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, November 16, 2010 11:11:05 Steve Teale wrote:
 I have moaned several times about the fact that this module does not have a
 method for creating a date from the system clock.
 
 It provides a parse method to convert a string in a limited number of
 formats. In the course of doing that, it calls the OS primitive to get the
 time zone offset.
 
 So why the omission? If it's going to use the OS, why not go the whole hog.
 
 It also strikes me as odd that it does not include a table of leap seconds.
 As it stands, some of its methods could return values that were out by a
 year for up to four or five seconds on January 1 2011. I'm no expert on
 UTC, Gregorian Calendar and such, so I could well be wrong, but ....
 
 Phobos doesn't really need the burden of such tasks. Most OS's provide
 regular upgrades that cover this stuff.
As Steven points out, I've been working on a date/time module which will become std.datetime once its review process is finished. It's far more advanced than std.date. However, I would point out though that virtually nothing computer-wise cares about leap seconds. Posix even specifically ignores them. This currently means that UTC according to your typical computer is technically 24 seconds off of UTC. But for the most part, since they all ignore leap seconds, it's not an issue. However, with the future std.datetime, if you use PosixTimeZone with a time zone which has leap seconds (which are generally the ones whose names start with "right/"), you can have leap seconds. In any case, feel free to try out the code and comment on it. The most recent thread on it is "datetime review part 2," so please post any comments that you have on it there. The most recent code which I've posted can be found here: http://is.gd/gSwDv HTML documentation for it can be found in the Doc folder while the source is in Src. It should be a huge step up from using std.date (which is highly buggy at present regardless of whether the design as any good or not). - Jonathan M Davis
Nov 16 2010
prev sibling next sibling parent reply Kagamin <spam here.lot> writes:
Steve Teale Wrote:

 It also strikes me as odd that it does not include a table of leap seconds. As
it stands, some of its methods could return values that were out by a year for
up to four or five seconds on January 1 2011. I'm no expert on UTC, Gregorian
Calendar and such, so I could well be wrong, but ....
This depends on how the library imports time from system. If it imports in nominal form: receives actual hours, minutes and seconds as separate values, it will precisely represent the time point in nominal and string forms. Only time intervals will be off by leap seconds that were introduces during the intervals.
Nov 16 2010
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, November 16, 2010 13:00:17 Kagamin wrote:
 Steve Teale Wrote:
 It also strikes me as odd that it does not include a table of leap
 seconds. As it stands, some of its methods could return values that were
 out by a year for up to four or five seconds on January 1 2011. I'm no
 expert on UTC, Gregorian Calendar and such, so I could well be wrong,
 but ....
This depends on how the library imports time from system. If it imports in nominal form: receives actual hours, minutes and seconds as separate values, it will precisely represent the time point in nominal and string forms. Only time intervals will be off by leap seconds that were introduces during the intervals.
Of course, the annoying thing about leap seconds is that because they're unpredictable, it's _impossible_ to give correct interval lengths (with regards to leap seconds) for intervals which cover future dates. Right now, leap seconds introduce a difference of 24 seconds, and a new leap second has generally been added about once every two years, but that could easily change. A year or two from now, it could be pretty much any number within a few seconds of 24 (even numbers less than 24 like 22 or 23). So, only intervals entirely in the past can be completely correct with regards to leap seconds (or ones so near in the future that there's no way that a leap second would have been added or removed between now and then). Honestly, leap seconds are complete stupidity with regards to computers. They just complicate things. Of course, time in general has various issues when it comes to computers (DST is one of the stupidest ideas even IMHO; I don't even want to _think_ about how many bugs it's created), but leap seconds are definitely on my list of time-related stuff that should be abolished (and there are those lobbying for it, so it may happen eventually). On the bright side, computers generally ignore them, so you don't have to care (unless you're one of those extremely rare people who do, at which point, you have my condolences). - Jonathan M Davis
Nov 16 2010
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 16 Nov 2010 20:17:53 -0500, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 (DST is one of the stupidest ideas even IMHO; I don't even
 want to _think_ about how many bugs it's created)
No, the stupidest idea was to *change* DST a few years ago. That had absolutely no purpose, I can't even believe we wasted tax dollars on pushing that through congress. -Steve
Nov 16 2010
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday 16 November 2010 21:08:48 Steven Schveighoffer wrote:
 On Tue, 16 Nov 2010 20:17:53 -0500, Jonathan M Davis <jmdavisProg gmx.com>
 
 wrote:
 (DST is one of the stupidest ideas even IMHO; I don't even
 want to _think_ about how many bugs it's created)
No, the stupidest idea was to *change* DST a few years ago. That had absolutely no purpose, I can't even believe we wasted tax dollars on pushing that through congress.
Granted, that was definitely stupid, but DST does cause bugs all over the place. Of course, for getting rid of it to help, you'd have to get rid of it globally, and even then, it wouldn't really help except in apps that didn't care about historic dates at all, because we've had DST in the past. Not to mention, many programs which work properly with DST would probably break if it were abolished. So, getting rid of it at this point probably wouldn't help anywhere near as much as it would seem (though it still wouldn't hurt my feelings any if they did). Regardless, its existence has caused all kinds of bugs for computers over the years. Now, changing it just causes bugs without fixing _anything_ as far as software is concerned, so that was just stupid, but I can dream of a world without DST... - Jonathan M Davis
Nov 16 2010
prev sibling parent reply Kagamin <spam here.lot> writes:
Jonathan M Davis Wrote:

 Honestly, leap seconds are complete stupidity with regards to computers. They 
 just complicate things.
I think, it's ok, computers work with nominal time and synchronize with world as needed. Hardly you can catch a bug with leap seconds.
Nov 16 2010
parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Kagamin schrieb:
 Jonathan M Davis Wrote:
 
 Honestly, leap seconds are complete stupidity with regards to computers. They 
 just complicate things.
I think, it's ok, computers work with nominal time and synchronize with world as needed. Hardly you can catch a bug with leap seconds.
As long as you're not Oracle and your enterprise clusterware crap reboots: http://www.theregister.co.uk/2009/01/07/oracle_leap_second/
Nov 17 2010
parent reply Kagamin <spam here.lot> writes:
Daniel Gibson Wrote:

 I think, it's ok, computers work with nominal time and synchronize with world
as needed. Hardly you can catch a bug with leap seconds.
As long as you're not Oracle and your enterprise clusterware crap reboots: http://www.theregister.co.uk/2009/01/07/oracle_leap_second/
Synchronization can fail if the code asserts that number of seconds is not greater than 59 (Jonathan's lib does the same, I think). Is it the cause?
Nov 17 2010
parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Kagamin schrieb:
 Daniel Gibson Wrote:
 
 I think, it's ok, computers work with nominal time and synchronize with world
as needed. Hardly you can catch a bug with leap seconds.
As long as you're not Oracle and your enterprise clusterware crap reboots: http://www.theregister.co.uk/2009/01/07/oracle_leap_second/
Synchronization can fail if the code asserts that number of seconds is not greater than 59 (Jonathan's lib does the same, I think). Is it the cause?
How are leap seconds handled on a computer anyway? Does the clock really count to 60 seconds (instead of 59) before the next minute starts, or is the clock just slowed down a bit (like it's - IIRC - done when changing the time with NTP or such)?
Nov 17 2010
parent reply Kagamin <spam here.lot> writes:
Daniel Gibson Wrote:

 Synchronization can fail if the code asserts that number of seconds is not
greater than 59 (Jonathan's lib does the same, I think). Is it the cause?
How are leap seconds handled on a computer anyway? Does the clock really count to 60 seconds (instead of 59) before the next minute starts, or is the clock just slowed down a bit (like it's - IIRC - done when changing the time with NTP or such)?
This is how it looked on linux: Thu Jan 1 00:59:58 CET 2009 Thu Jan 1 00:59:59 CET 2009 Thu Jan 1 00:59:60 CET 2009 Thu Jan 1 01:00:00 CET 2009 Thu Jan 1 01:00:01 CET 2009
Nov 17 2010
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, November 17, 2010 04:15:52 Kagamin wrote:
 Daniel Gibson Wrote:
 Synchronization can fail if the code asserts that number of seconds is
 not greater than 59 (Jonathan's lib does the same, I think). Is it the
 cause?
How are leap seconds handled on a computer anyway? Does the clock really count to 60 seconds (instead of 59) before the next minute starts, or is the clock just slowed down a bit (like it's - IIRC - done when changing the time with NTP or such)?
This is how it looked on linux: Thu Jan 1 00:59:58 CET 2009 Thu Jan 1 00:59:59 CET 2009 Thu Jan 1 00:59:60 CET 2009 Thu Jan 1 01:00:00 CET 2009 Thu Jan 1 01:00:01 CET 2009
That's the standard, but supposedly it varies a bit in how it's handled - at least if you read it up on Wikipedia. I'd have to go digging in std.datetime again to see exactly what would happen on a leap second, but IIRC you end up with either 59 twice or 00 twice. Unix time specifically ignores leap seconds, and in 99.9999999999% of situations, if you have a 60th second, it's a programming error, so TimeOfDay considers 60 to be outside of its range and throws if you try and set its second to 60. SysTime is really the only type where it would make much sense to worry about leap seconds, but since the only way that you're going to get them is if you go out of your way by using a PosixTimeZone which starts with "right/" for your time zone, it seemed silly to worry about it overly much. The _system time_ ignores leap seconds after all, _even_ if you use one of the time zones that starts with "right/" as your system's time zone. So, the result is that if you use one of the PosixTimeZones with leap seconds, it will correctly adjust for leap seconds except when adding or removing a leap second, at which point, you'd get a duplicate time for two seconds in a row in the case of an addition and probably would skip a second in the case of subtraction (though that's actually probably the correct behavior for a subtraction - not that they've ever subtracted an leap seconds yet). It might be less than ideal if you _really_ care about leap seconds, but allowing for a 60th second could really mess with calculations and allow for bugs to go uncaught in user code. So, allowing for a 60th second when adding a leap second would help an extreme corner case at the cost of harming the normal case, and I decided against it. - Jonathan M Davis
Nov 17 2010
parent reply Kagamin <spam here.lot> writes:
Jonathan M Davis Wrote:

 This is how it looked on linux:
 

 Thu Jan 1 00:59:58 CET 2009

 Thu Jan 1 00:59:59 CET 2009

 Thu Jan 1 00:59:60 CET 2009

 Thu Jan 1 01:00:00 CET 2009

 Thu Jan 1 01:00:01 CET 2009

That's the standard, but supposedly it varies a bit in how it's handled - at least if you read it up on Wikipedia. I'd have to go digging in std.datetime again to see exactly what would happen on a leap second, but IIRC you end up with either 59 twice or 00 twice.
An exception will be thrown, this is tested: assertExcThrown!(DateTimeException, (){TimeOfDay(0, 0, 0).second = 60;})(LineInfo());
 and in 99.9999999999% of situations, if you 
 have a 60th second, it's a programming error, so TimeOfDay considers 60 to be 
 outside of its range and throws if you try and set its second to 60.
That's probably why Oracle and Solaris rebooted on 2009-01-01.
Nov 17 2010
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday 17 November 2010 12:37:18 Kagamin wrote:
 Jonathan M Davis Wrote:
 This is how it looked on linux:
 

 Thu Jan 1 00:59:58 CET 2009

 Thu Jan 1 00:59:59 CET 2009

 Thu Jan 1 00:59:60 CET 2009

 Thu Jan 1 01:00:00 CET 2009

 Thu Jan 1 01:00:01 CET 2009

That's the standard, but supposedly it varies a bit in how it's handled - at least if you read it up on Wikipedia. I'd have to go digging in std.datetime again to see exactly what would happen on a leap second, but IIRC you end up with either 59 twice or 00 twice.
An exception will be thrown, this is tested: assertExcThrown!(DateTimeException, (){TimeOfDay(0, 0, 0).second = 60;})(LineInfo());
Except that _no_ calculation in std.datetime would _ever_ result in a second being 60. A user program would have to do that by trying to create a TimeOfDay or DateTime (which contains a TimeOfDay) with a second value of 60. The question is what string value or DateTime/TimeOfDay value SysTime gives when converting from a time that is during that leap second application when the TimeZone being used handles leap seconds. It's either going to give 59 or 00, but never 60. I'd have to look at the code in PosixTimeZone to see which.
 and in 99.9999999999% of situations, if you
 have a 60th second, it's a programming error, so TimeOfDay considers 60
 to be outside of its range and throws if you try and set its second to
 60.
That's probably why Oracle and Solaris rebooted on 2009-01-01.
Possibly. But that would mean that their code handled the 60th second (and if it did, they would likely have done it properly). Unless there is some way to get a time out of the OS which gives you a 60th second, and they were using that method of getting the time, they never would have even seen a value of 60 for the seconds anywhere. You have to work at it to get that 60th second. Most stuff just ignores leap seconds completely. If whatever they did caused an exception (like TimeOfDay would throw) and _that_ is what took the system done, then they have other major problems. I have no idea what really caused the problem, but my guess would be that it was code that assumed something which didn't hold when that new leap second was hit, and it resulted in a segfault. Given how robust that kind of software has to be, I would not expect it to go down from a mere exception, unless it were a _major_ one - like what D would typically have as an Error. - Jonathan M Davis
Nov 17 2010
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, November 17, 2010 09:51:30 Jonathan M Davis wrote:
 On Wednesday, November 17, 2010 04:15:52 Kagamin wrote:
 Daniel Gibson Wrote:
 Synchronization can fail if the code asserts that number of seconds
 is not greater than 59 (Jonathan's lib does the same, I think). Is
 it the cause?
How are leap seconds handled on a computer anyway? Does the clock really count to 60 seconds (instead of 59) before the next minute starts, or is the clock just slowed down a bit (like it's - IIRC - done when changing the time with NTP or such)?
This is how it looked on linux: Thu Jan 1 00:59:58 CET 2009 Thu Jan 1 00:59:59 CET 2009 Thu Jan 1 00:59:60 CET 2009 Thu Jan 1 01:00:00 CET 2009 Thu Jan 1 01:00:01 CET 2009
That's the standard, but supposedly it varies a bit in how it's handled - at least if you read it up on Wikipedia. I'd have to go digging in std.datetime again to see exactly what would happen on a leap second, but IIRC you end up with either 59 twice or 00 twice. Unix time specifically ignores leap seconds, and in 99.9999999999% of situations, if you have a 60th second, it's a programming error, so TimeOfDay considers 60 to be outside of its range and throws if you try and set its second to 60. SysTime is really the only type where it would make much sense to worry about leap seconds, but since the only way that you're going to get them is if you go out of your way by using a PosixTimeZone which starts with "right/" for your time zone, it seemed silly to worry about it overly much. The _system time_ ignores leap seconds after all, _even_ if you use one of the time zones that starts with "right/" as your system's time zone. So, the result is that if you use one of the PosixTimeZones with leap seconds, it will correctly adjust for leap seconds except when adding or removing a leap second, at which point, you'd get a duplicate time for two seconds in a row in the case of an addition and probably would skip a second in the case of subtraction (though that's actually probably the correct behavior for a subtraction - not that they've ever subtracted an leap seconds yet). It might be less than ideal if you _really_ care about leap seconds, but allowing for a 60th second could really mess with calculations and allow for bugs to go uncaught in user code. So, allowing for a 60th second when adding a leap second would help an extreme corner case at the cost of harming the normal case, and I decided against it.
Actually, this results in the entertaining situation where you can have two SysTimes which convert to identical strings but where one is less than the other when compared (because their internal times are in unadjusted UTC and would differ). Of course, you'd have to get two times which were exactly 1 second apart, and their precision is 100 ns (though it only manages microsecond precision on Linux since that's as precise as the system clock is; I believe that Windows is slightly higher precision but not the full 100 ns), so the odds of it happening aren't terribly high, but it is technically possible. I suppose that if you got a bug because of it, it would be because you were converting all of your times to strings, and your program couldn't deal with the fact that your strings were suddenly 1 second back in time. Other than that, I don't expect that it would result in a problem. And since the clock can do that _anyway_ when it's adjusted for skew by NTP, I don't see that as being all that big a deal (though in the case of adjusting for NTP, the internal stdTimes for the SysTimes would be off as well, while in the leap second case, they aren't). - Jonathan M Davis
Nov 17 2010
prev sibling next sibling parent reply Steve Teale <steve.teale britseyeview.com> writes:
Jonathan M Davis Wrote:

... (though in the case of adjusting for NTP, the internal stdTimes for the
SysTimes 
 would be off as well, while in the leap second case, they aren't).
 
 - Jonathan M Davis
OK, all, thanks for answering that question, but my primary gripe was that the current std.date does not have a constructor like this(). My assumption being that such a constructor would go to the OS and give you an object corresponding to now. I've looked at Jonathan's documentation, and I don't see a constructor like that there either. So if I want to write a timed log entry, what's the recommendation? Steve
Nov 17 2010
next sibling parent Kagamin <spam here.lot> writes:
Steve Teale Wrote:

 So if I want to write a timed log entry, what's the recommendation?
I won't dare to use std.date.
Nov 17 2010
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday 17 November 2010 21:35:03 Steve Teale wrote:
 Jonathan M Davis Wrote:
 
 ... (though in the case of adjusting for NTP, the internal stdTimes for the
 SysTimes
 
 would be off as well, while in the leap second case, they aren't).
 
 - Jonathan M Davis
OK, all, thanks for answering that question, but my primary gripe was that the current std.date does not have a constructor like this(). My assumption being that such a constructor would go to the OS and give you an object corresponding to now. I've looked at Jonathan's documentation, and I don't see a constructor like that there either. So if I want to write a timed log entry, what's the recommendation?
Structs can't have default constructors, so it's impossible to do that. In the case of std.datetime, the way to get the current time is Clock.currTime(), and since SysTime has a toString() method, you can just print it. So, you can do writeln(Clock.currTime().toString()); It has other types of methods of converting to and from strings if you want a specific format, but toString() works just fine if you aren't picky about the format (it's also the most readable of the various formats). As for std.date. IIRC, you'd use getUTCTime() to get the current time as a d_time and toUTCString() to print it. As I recall, anything that converts to or from UTC is broken, so I wouldn't advise it. If you really want the current time as local time and don't want to use std.datetime before it's actually in Phobos, then I'd advise just using the standard C functions. They're in core.stdc.time. The list can be found here: http://www.cppreference.com/wiki/chrono/c/start This program would print the current time: import core.stdc.time; import std.conv; import std.stdio; import std.string; void main() { auto t = time(null); writeln(strip(to!string(ctime(&t)))); } to!string() is used because ctime() returns a char*, and strip() is used because ctime() returns a string with a newline at the end. - Jonathan M Davis
Nov 17 2010
parent Steve Teale <steve.teale britseyeview.com> writes:
On Wed, 17 Nov 2010 22:18:09 -0800, Jonathan M Davis wrote:

 Structs can't have default constructors, so it's impossible to do that.
 In the case of std.datetime, the way to get the current time is
 Clock.currTime(), and since SysTime has a toString() method, you can
 just print it. So, you can do writeln(Clock.currTime().toString()); It
 has other types of methods of converting to and from strings if you want
 a specific format, but toString() works just fine if you aren't picky
 about the format (it's also the most readable of the various formats).
 
  
 - Jonathan M Davis
Ah! It was Clock.currTime() that I had not spotted. Thanks Jonathan
Nov 18 2010
prev sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
On 16/11/2010 19:11, Steve Teale wrote:
 I have moaned several times about the fact that this module does not
 have a method for creating a date from the system clock.
Does getUTCtime() not do this? What does it do then? <snip>
 It also strikes me as odd that it does not include a table of leap
 seconds.
<snip> What, exactly, would it do with this table? std.date works internally in Unix time. I don't know what platforms have leap second support in the system clock. But one thing I do know is that Unix time, which is what std.date works in, is defined so that 23:59:60.xxx has the same value as 00:00:00.xxx the following day. FWIW, my utility library http://pr.stewartsplace.org.uk/d/sutil/ makes it possible to store leap second times, but otherwise doesn't do anything with them. It also includes a custom formatting scheme that's better than any other I've seen. Stewart.
Nov 18 2010