views:

831

answers:

3

I'm writing a file that requires dates to be in decimal format:

2007-04-24T13:18:09 becomes 39196.554270833331000

Does anyone have a time formatter that will do this (Decimal time is what VB/Office, etc. use)?

Basic code goes like follows:

final DateTime date = new DateTime(2007, 04, 24, 13, 18, 9, 0, DateTimeZone.UTC);
double decimalTime = (double) date.plusYears(70).plusDays(1).getMillis() / (Days.ONE.toStandardDuration().getMillis())); //=39196.554270833331000.

For the example above.

(I started on a DateTimePrinter that would do this, but it's too hard for now (I don't have the joda source linked, so I can't get ideas easily)).

Note: Decimal time is the number of days since 1900 - the . represents partial days. 2.6666666 would be 4pm on January 2, 1900

A: 

What's wrong with http://java.sun.com/j2se/1.4.2/docs/api/java/util/Date.html#getTime()?

Itay
The problem is that I need to divide that by 84600, after adding 70 years and 1 day.Enough stuff there to cause a few edge cases with getMillis()
Stephen
Simpler answer: Because it's not what the application on the other end of the xml format is expecting
Stephen
A: 

Unfortunately your question is not very clear, but I have a hunch that with decimal time you mean a Julian date. There is a post about converting date to julian date in Java.

lothar
Not julian date - decimal date: what's used in MS programs. It's the number of days since 1970
Stephen
+1  A: 

You can do this using the calendar class:

final long MILLIS_IN_DAY = 1000L * 60L * 60L * 24L;

final Calendar startOfTime = Calendar.getInstance();
startOfTime.setTimeZone(TimeZone.getTimeZone("UTC"));
startOfTime.clear();
startOfTime.set(1900, 0, 1, 0, 0, 0);

final Calendar myDate = Calendar.getInstance();
myDate.setTimeZone(TimeZone.getTimeZone("UTC"));
myDate.clear();
myDate.set(2007, 3, 24, 13, 18, 9); // 2007-04-24T13:18:09

final long diff = myDate.getTimeInMillis() - startOfTime.getTimeInMillis() + (2 * MILLIS_IN_DAY);
final double decimalTime = (double) diff / (double) MILLS_IN_DAY;
System.out.println(decimalTime); // 39196.55427083333

Something to note: This code will only work after 28th February 1900. Excel incorrectly counts 1900 as a leap year, which it of course is not. To circumvent the bug the calculation inserts an extra day (2 * MILLIS_IN_DAY), but this of course corrupts any date calculations before the imaginary leap year took place.