This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
I know most people don't care about leap seconds, but alas I just happen to be in an industry that does (it's even written up in our requirements document). So, according to the Date API seconds are integers from 0-61. However, if trying to set a Calendar object like Calendar.set( 1995 , 05 , 30 , 23 , 59 , 61 ), and then printing the date from Calendar.getTime(), I end up with July 01, 2003 00:00:01. This is run on a Windows system The question is, is there a Windows Java implementation out there that won't roll over a date such as this, or that actually handles leap seconds correctly? Not sure if I am asking the right question, but I'm guessing that the JRE we are using is causing this behavior, or is it the actual OS? Any help would be much appreciated.
First off, I don't believe there was any leap second added in June/July 1995. The Date API says there was one at the very end of the year. And the US Navy says that there was one at the very beginning of 1996. I guess the last two statements are fairly easy to reconcile; it's a to-MAY-to to-MAH-to sort of thing. But forget about testing for June, unless you've got other info here. Anyway - it appears that Sun's JDK doesn't allow for leap seconds in the implementation of GregorianCalendar, which also contains no native code. So my guess is that this won't really depend on the OS you use; and JDK using GregorianCalenar will probably give you the same results. I say probably; this isn't guaranteed. If you want to guarantee behavior, you may well have to implement date parsing and interpretation from the ground up. If you don't require quite so much certainty, you may be able to get by using GregorianCalendar's results as a baseline, and then write a relatively simple program to convert to corrected dates by figuring out how the current date fits into the US Navy table I linked to, and adding the appropriate number of seconds. This assumes that GregorianCalendar is will always be uncorrected for leap seconds; this may not be true on all platforms, for all JDKs. Good luck. Note - I did spend some time googling java "leap seconds" until I got tired of looking. There may be an easy-to -use implementation already out there in Java, but I didn't find it. Lots of articles without implementation though. Note that whatever you do, you'll probably also have to make provisions for getting updated info on leap seconds from the US Navy or IERS. (Yes, there's an international agency monitoring the earth's rotation. It's probably a good sign that most of us have never heard of it - I don't want to be there the day they find it necessaryto issue some sort of emergency bulletin.) Also note that any calculations regarding dates in the future will really be predictions at best; since UTC is tied to actual earth rotation, you won't be able to make absolute statements about dates & times until they actually come to pass and you know how many leap seconds really occured prior to the given date. Which doesn't bother most of us, but you might want to look carefully at how your software specs are worded - you may find they're asking you to do something which is impossible. Not that you should let that stop you, but it's good to know what you're in for... [ September 22, 2003: Message edited by: Jim Yingst ]
"I'm not back." - Bill Harding, Twister
Chicken Farmer ()
Joined: May 08, 2001
Originally posted by Jim Yingst: It's probably a good sign that most of us have never heard of it - I don't want to be there the day they find it necessary to issue some sort of emergency bulletin.) [ September 22, 2003: Message edited by: Jim Yingst ]
ROFL! The problem is there is the possibility that an event may occur at the exact time a leap second occurs. For instance, and I don't know the probability but the fact that the possibility exists is enough for all the engineers, a nodal crossing may occur at Jun 30 23:59:61, and that time needs to be represented in our system. Since them things up there in that thar space thingy travel so friggin fast, being off by one second means we're placing the satellite around 6.2 km off of its true location. As far as getting the time from UTC, all the systems will be synced with "real" time, so that isn't an issue. The issue is being able to represent when that leap second is actually added, which is probably a bigger issue than just how to deal with it in Java. If the underlying system, our Oracle databases, and anything else can't represent that number, then having the application layer doing so will probably make things all floopy. I just keep hoping that one day all these egg-heads will realize that there really is no such thing as linear time and we just do away with the whole concept all together. (Paul's signature about Time and the Universe hits the proverbial nail on the cosmic head). Myself and one of the senior members of the group started discussing writing our own Calendar implementation, pretty much figured after looking through the source code for Gregorian, Date, DateFormat, etc. that that may very well be the way we have to go. Thanks for the info Jim! [ September 23, 2003: Message edited by: jason adam ]
Joined: Jan 30, 2000
I just keep hoping that one day all these egg-heads will realize that there really is no such thing as linear time and we just do away with the whole concept all together. Or at least clean up the current system. I mean, here in the US we have four dicsontinuities a day. Whose idea was it that 11:59 AM should be followed by 12:00 PM, while 12:59 PM is followed by 1:00 PM? Ugh. We need 24-hour clocks at least; those make some sense. As for those pesky leap years and leap seconds - I think the next step is to alter the Earth's orbit so that one year is a nice even 360 days. This fits in nicely with the multiples of 60 used elsewhere in our timekeeping. (Hey, be glad I'm not yet trying to switch us over to metric timekeeping.) So yeah, I suppose we'd probably lose a few holidays in the process, but you've got to break a few eggs to make an omelette after all. Might have some increased global warming too, what with moving the Earth a little closer to the Sun - but again, that's even better for making omelettes. Well anyway, back to the original question. Interesting problem. I think you're going to have to be very paranoid about any date/time info you receive, asking yourself where it came from, was it a source that definitely understands leap seconds, etc. I'd probably store all data/times as long, using the definition Data supposedly uses - milliseconds elapsed since 1970/01/01 00:00:00 UTC. Don't store them in Oracle as a DATETIME or whatever, as that will just tempt people to use existing functions to interpret the data, and they'll probably ber wrong. Within Java I'd prb=obably make a new wrapper class named something like TrueDateTime so that no one tres to convert it to some other format without using the custom conversion methods you provide. As for how to handle representing the time of the leap second itself - how does the source you're getting data from represent it? If the leap second is represented with a seconds value of 60, or very rarely, 61, then you can just detect that case early on in the interpretation process, and handle it appropriately. E.g. for ( 1995 , 11 , 31 , 23 , 59 , 60 ) the moment you see seconds > 59, you subtract, say, 2 sec from the value, to get ( 1995 , 11 , 31 , 23 , 59 , 58 ). Convert that to a Java Date using GregorianCalendar or something equivalent (preferably something you can better guarantee the behavior of), then get the equivalent milliseconds since 1970-01-01, then add in the missing leap seconds as discussed earlier, then add back the 2 seconds you subtracted out earlier. (I chose 2 sec because 1 sec isn't always enough if sec = 61; you can use any number >= 2.) Then test your method for a series of times beofre & after the leap second, e.g. ( 1995 , 11 , 31 , 23 , 59 , 58 ) ( 1995 , 11 , 31 , 23 , 59 , 59 ) ( 1995 , 11 , 31 , 23 , 59 , 60 ) ( 1996 , 0 , 1 , 0 , 0 , 0 ) ( 1996 , 0 , 1 , 0 , 0 , 1 ) to make sure they all come out 1 sec apart as they should. Good luck, hope that helps...