Win a copy of Penetration Testing Basics this week in the Security forum!

# Date API

Ra Carter
Ranch Hand
Posts: 96
I am trying to learn how to work with Dates in Java 1.5/1.6 but I found some interesting anomalies when trying to subtract the current time from 0/0/00.

This code produced the following results:
start date is 0002-11-30 00:00:00.000 GMT
today is 2007-03-10 14:21:07.938 GMT
time elapsed is 2007 years, 3 months, 13 days

But today is the 10th! why does it say 13 days? And why does it say the start date is on year 0002-11-30?

Alright I know that 0/0/00 is probably not a valid date but trying things like "0000-01-01 00:00:00.000 GMT" also produces strange results.

Am I using the API incorrectly? Do I have to account for leap years?
[ March 10, 2007: Message edited by: Ra Carter ]

Ra Carter
Ranch Hand
Posts: 96
so this has been bothering me all day and i removed all uses of Date and made everything Calendar and I learned some stuff about formating Strings in 1.6. And I am trying to use UTC format to avoid any comparison problems between locales or timezones.

I am expecting this to give me 2007 years, 2 months, and 11 days but it is giving me something else.
start date is 0001-01-01 12:00:00 am UTC
today is 2007-03-11 03:13:15 am UTC
time elapsed is 2007 years, 2 months, 13 days

What am I doing wrong? Maybe my math is bad.. is that the right answer?
[ March 10, 2007: Message edited by: Ra Carter ]

Henry Wong
author
Marshal
Posts: 21705
85

Think about it... if it is January, and you add three months, do you get March or April?

Henry

Paul Clapham
Sheriff
Posts: 21443
33
I don't have any idea whether your arithmetic is wrong or what the right answer to your calculation would be. But you can't put a time interval into a Calendar object and convert that into years, months, and days. Even if you subtract 1970, 1, and 1 (which you only partially did). The months all have different lengths, and you arbitrarily map the months between your two dates to months with length 31, 28, 31, 30, and so on. The wrongness of doing that is not apparent when you test only with the starting date in January, though.

Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
Computing elapsed months this way is pretty meaningless. For example, what is January 31 plus 1 month?

Let's see why. Try your program from 2007-02-15 to 2007-03-15 - it says 0 months, 29 days where you probably wanted 1 month 0 days. It computes the date some number of milliseconds from some year January first. 29 days doesn't get you into February so it registers 0 months have passed.

You can compute the number of days easily by dividing the milliseconds by the number of milliseconds in a day. That never changes unless you deal with DST, leap seconds and adjustments for variations in the Earth's orbit & rotation. To compute the number of years, you need to take leap years into account.

Not it's common conversation to say 2004-04-11 to 2007-06-15 is "3 years, two months, four days" when they mean 2007-2004 = 3 years, 06-04 = two months and 15-11 = 4 days. That's a whole different bunch of math to get a very imprecise answer. The number of days in those years and months could vary quite a bit.

Long answer with no answers. But did it help explain why you're not getting what you expect?

Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
Ha! A plethora, a cornucopia, a veritable smorgasboard of answers in only minutes! What an amazing place.
[ March 10, 2007: Message edited by: Stan James ]

Ra Carter
Ranch Hand
Posts: 96
it's just weird and i think what i am finding is that this problem only exists for the year 0000 which must be invalid? running the same code for 1980-01-01 gives me this:
start date is 1980-01-01 12:00:00 am UTC
today is 2007-03-11 01:20:46 pm UTC
time elapsed is 27 years, 2 months, 11 days
Which seems to make sense to me... 2007 - 1980 = 27, 2 whole months have passed, 11 days have passed in the third month (march) and if this was calculating hours I guess it would be 13 hours of the 11th day have passed. the numbers seem to work when i used 1900, 1800, 1700, 1000 as years but just give me something different on 0000.

Not that I am a fan of .NET or Microsoft's api, but just as a frame of reference, here's basically the same thing in C#:which gives me:
start is 1980-01-01 00:00:00 AM
today is 2007-03-11 13:25:06 PM
duration is 28 years, 3 months, 11 days
Press any key to continue
Why does it say 28 years, 3 months? I have no idea but when I give it the year 0000 it crashes with this exception:
Unhandled Exception: System.ArgumentOutOfRangeException: Valid values are between 1 and 9999, inclusive.
Parameter name: year
at System.Globalization.GregorianCalendar.GetMonthsInYear(Int32 year, Int32 era)
at ...
i guess i don't really have a question anymore, just getting confused out loud. apparently i can enter negative years in java with interesting results. the years seem to be correct when i do that but the days look weird too. i don't care enough now to wonder about that. someone told me in an irc room about a "joda" library. is it true that it is coming to java 1.7 or was that guy messing with me?

Jim Yingst
Wanderer
Sheriff
Posts: 18671
[Ra]: someone told me in an irc room about a "joda" library. is it true that it is coming to java 1.7 or was that guy messing with me?

It's coming - hopefully to JDK 1.7, maybe later. Joda-time exists now as an independent open-source project. JSR 310 is an attempt to bring something much like Joda-time into the standard JDK. I think there's a decent chance it will arrive in 1.7 - if not, then 1.8. But we won't really know until later. Regardless, you can use Joda-time now if you simply include the extra jar file.

Paul Clapham
Sheriff
Posts: 21443
33
Well, there was no year zero. There was 1 BC and it was followed immediately by 1 AD. And as I said before, your habit of using January for test data is obscuring the fault in your method that Stan and I both pointed out.

And don't get me started on C# and .Net. We just had some custom software written in C# and it has to deal with times in different timezones. Apparently the C# classes can't deal with that, so they "converted everything to GMT". That strategy resulted in all the times being 8 hours later in the database, so I had to write extra code in Java to put it back into the right timezone when I process it. My job this week is to see if my patch still works in daylight saving time.

Jim Yingst
Wanderer
Sheriff
Posts: 18671
[PC]: Well, there was no year zero.

That depends on whom you ask. Astronomers are happy to use zero and negative numbers superimposed as a logical extension of the AD/CE system. (Ignoring BC/BCE which requires the removal of year 0 in order to cater to historical and cultural stupidity.)

Ra: In Java, the SimpleDateFormat class handles zero and negative dates very poorly (apparently by simply ignoring the sign), and should be ignored. Why do you care about dates that old anyway? If you've got a legitimate business need for this, use Joda-time. Otherwise, you'll be much happier not worrying about what the current extremely-crappy date-time implementations try to tell you about very old dates. Many headaches lie on this road.

Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
You'll get expected results when your starting date is 01/01 for any year that has the same leap year status as year zero. I think.

Ra Carter
Ranch Hand
Posts: 96
thanks! i wasn't understanding what the problem with using 01/01 was but i will try it again with a leap year later but i am starting to get bored with dates now anyway. i dont actually have any reason for doing this by the way other than to play with the date api and brought it up so i can understand it and maybe start some controversy .

also as i re-read some of these responses i realize that some of them might be responding to a comment i made before i edited it so sorry if i caused confusion with that.

and a dba once scolded me for trying to use anything but utc to store dates in a database and i think it is considered poor practice to use anything but utc.

anyway... it is sounding like there may be a problem for for scientists, astronomers, engineers, and historians who need to do date calculations regardless of their programming language. i am now wondering if there is a "scientific calendar" or some sort of "metric system for dates" that ignores "historical and cultural stupidity?" i think we need something that starts time at the big bang or something. but i guess it would have to still allow negative numbers in case something happened before that. and what happens if there is a date older (or newer) than what can fit in a long? it looks like joda still has that problem too.

Paul Clapham
Sheriff
Posts: 21443
33
You can learn a lot by fiddling with dates. Sometimes it's more than you wanted to learn, but it does give you practice in dealing with ugly details that you have no control over.

As for storing times in the database in UTC, that must be a Microsoft thing. The Unix/Java convention of storing an offset from an epoch instance works very well and most databases can use that. But Microsoft software generally doesn't handle timezones very well. (That's partly because it's hard to handle timezones well, but as I understand it MS software doesn't help the programmer out.)

The scientific calendar that starts way back when and ignores all that history business is the Julian day system that's used by astronomers in particular.

Stefan Wagner
Ranch Hand
Posts: 1923
start is 1980-01-01 00:00:00 AM
today is 2007-03-11 13:25:06 PM
duration is 28 years, 3 months, 11 days

Why is the difference 11 and not 10 days?
Am I missing something?

Ra Carter
Ranch Hand
Posts: 96
Why is the difference 11 and not 10 days?
Am I missing something?
I don't think so. At first I tried to disregard it as meaning 11 days have passed and we are in the x hour of the next day but it sounds wrong and i have now gotten around to testing joda which seems to be in agreement.
which yeilds
start is 1980-01-01T00:00:00.000Z
today is 2007-03-12T02:27:25.063Z
period is 27 years, 2 months, 11 days, 2 hours, 27 minutes, 25 seconds
to my untrained eye it seems to work on leap years as well. i tried 1984-02-29 and 1983-02-29 (exception since 83 is not a leap year). the bad thing about joda-time is that the examples and tutorials to be found are not nearly as extensive as the sdk libraries. right now i dont know how to parse custom date formats and there are lot of classes that i dont understand yet.

anyway... it doesn't seem like there's much more to be said on this topic except to say that a few missing minutes/hours/days/months/years is not trivial. i know of companies that use standard tools to calculate legalized audit trails, medical records of age, etc. so far what i have gotten out of this is that the safest thing to do is stored dates as epoch seconds as suggested earlier in this thread since it seems like all api's can deal with that.