Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
The moose likes Java in General and the fly likes Adding days to January 1, 1900 Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Adding days to January 1, 1900" Watch "Adding days to January 1, 1900" New topic
Author

Adding days to January 1, 1900

Ron Rea
Greenhorn

Joined: Jul 03, 2001
Posts: 23
I am trying to convert a 5 digit numeric number to a date with a format of MM/DD/YYYY. The 5 digit number represents the number of days since January 1, 1900 - where January 1, 1900 = 1.
Any ideas on how to, for example, turn 37106 into 08/03/2001?
Thanks.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Well, java.util.Date has methods to convert to and from the number of milliseconds since Jan 1, 1970. (This value can be negative.) So you can get a Date for Jan 1, 1900, nad convert it into milliseconds. Then add (number_of_days * milliseconds_per_day), and convert the resulting milliseconds into a Date. Then use a DateFormat to print the Date as a String in the desired format.


"I'm not back." - Bill Harding, Twister
Joshua Bloch
Author and "Sun God"
Ranch Hand

Joined: May 30, 2001
Posts: 124
Ron,
Hi. This sort of thing should be easy with Calendar, but unfortunately it isn't. Often the easiest way to deal with dates is as longs representing milliseconds since the beginning of the "epoch" (January 1, 1970, 00:00:00 GMT). Besides being predictable and fast, dates represented in this fashion are immutable, which has many advantages (discussed in Item 13: Favor immutability).
Here's a little program that solves your problem using this technique:
<pre>
import java.util.*;
public class ConvertDate {
// The number of ms in a day
static final long MILLIS_PER_DAY = 24L * 60 * 60 * 1000;
// The number of ms since 1/1/1970 representing 1/1/1900
static final long START = -2208988800000L;
public static void main(String[] args) {
int daysSinceStart = Integer.parseInt(args[0]) - 1;
long millisSinceStart = daysSinceStart * MILLIS_PER_DAY;
System.out.println(new Date(START + millisSinceStart).toGMTString());
}
}
</pre>
This program isn't quite politically correct as it uses the toGMTString method, which was deprecated in 1.1. Arguably it should not have been deprecated, but that's water over the dam. Feel free to replace this call with the appropriate DateFormat call if you wish.
Regards,
------------------
Joshua Bloch
Author of Effective Java


Joshua Bloch <br />Author of <a href="http://www.amazon.com/exec/obidos/ASIN/0201310058/ref=ase_electricporkchop" target="_blank" rel="nofollow">Effective Java</a> and coauthor of <a href="http://www.amazon.com/exec/obidos/ASIN/032133678X/ref=ase_electricporkchop" target="_blank" rel="nofollow">Java Puzzlers</a>
Joshua Bloch
Author and "Sun God"
Ranch Hand

Joined: May 30, 2001
Posts: 124
Wow! Jim and I -- independently, I swear -- suggested exactly the same thing at nearly the same time.
I should point out that there's a tiny error in the original post - if 1 represents 1/1/1900, then 37106 represents 08/04/2001. Perhaps you meant to say that 0 represents 1/1/1900, in which case remove the "- 1" from the daysSinceStart computation in my program.
Regards,

------------------
Joshua Bloch
Author of Effective Java
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Wow! Jim and I -- independently, I swear -- suggested exactly the same thing at nearly the same time.

What are you talking about? I beat you by over two hours.
For amusement, here's the version I had written. Note that we share one variable name as well - though I suppose it was reasonably obvious.
<code><pre>
public class DateConverter {

private static DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
private static long JAN_1_1900_MILLIS;
static {
try {
JAN_1_1900_MILLIS = formatter.parse("01/01/1900").getTime();
}
catch (ParseException e) {
e.printStackTrace();
}
}

private static final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;

public static Date getDate(int days) {
long millis = JAN_1_1900_MILLIS + days * MILLIS_PER_DAY;
return new Date(millis);
}

public static String getDateString(int days) {
return formatter.format(getDate(days));
}

public static void showConversion(int days) {
System.out.println(days + " days after 01/01/1900 = " + getDateString(days));
}

public static void main(String[] s) {
showConversion(0);
showConversion(1);
showConversion(365);
showConversion(37106);
}
}
</pre></code>
I should point out that there's a tiny error in the original post...

Actually there are two. "The 5 digit number represents the number of days since January 1, 1900" - this is a nice unambiguous definition or the meaning of the number which is subsequently contradicted by "January 1, 1900 = 1". I implemented the former statement and ignored (overlooked, really ) the latter. Depending on which of these two interpretations is chosen, the date for 37106 is either 08/04/2001 (Josh's version), or 08/05/2001 (my version). I don't see a way to get 08/03/2001.
[This message has been edited by Jim Yingst (edited July 11, 2001).]
Joshua Bloch
Author and "Sun God"
Ranch Hand

Joined: May 30, 2001
Posts: 124
Originally posted by Jim Yingst:
Wow! Jim and I -- independently, I swear -- suggested exactly the same thing at nearly the same time.

What are you talking about? I beat you by over two hours.

Actually I think there may be timezone issues at work. Your messages consistently come out with times later than those on my machine's clock. Who knows? Anyway you slice it, it's past my bedtime
By the way, you are, of course, correct that the original post listed two inconsitent descriptions of the integer date. That's why I suggested that Ron probably intended 0 to represent 1/1/1900. Well, it looks like we've beaten this one to death.
G'night,

------------------
Joshua Bloch
Author of Effective Java
Rajesh Pohuja
Greenhorn

Joined: May 29, 2001
Posts: 6
Originally posted by Joshua Bloch:
This sort of thing should be easy with Calendar, but unfortunately it isn't.

I am not sure of the proper way to do such conversion but
you can use Calendar to do it. Here is a modified version
of Jim's DateConverter class without all those calculations.
It produces same results.
Rajesh Pohuja
Greenhorn

Joined: May 29, 2001
Posts: 6
Another advantage of using java.util.Calendar is that it handles pre-1600 dates correctly, just in case you need to convert from those dates
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Actually I think there may be timezone issues at work.

Eh? I'm in Santa Clara. How many time zones is that from Cupertino, anyway?
Seriously - the JavaRanch server is in Colorado, so all our messages are timestamped Mountain Standard Time. Which of course should affect us both equally.
Sorry, I was feeling a bit obnoxiously competetive yesterday. Someone recently accused me of being "too nice", so I thought I should work to change that.
Hagar Nishaachar
Greenhorn

Joined: Sep 03, 2003
Posts: 4
While on the topic of Date calculations, can someone suggest how I can add x months to a date.
ie. newDate = oldDate + x
Where 'x' is term in months.
Thanks,
Hagar
Joel McNary
Bartender

Joined: Aug 20, 2001
Posts: 1821

Hagar da orrible:
Welcome to JavaRanch!
We don't have many rules here at JavaRanch, but we do have one. Please change your display name to comply with The JavaRanch Naming Policy. (We are looking for names that are not obviously fictitious.)
To answer your question, you should use the functions in the java.util.Calendar class.

(Edited to show correct semantics...field, then increment -- JAM)
[ September 04, 2003: Message edited by: Joel McNary ]

Piscis Babelis est parvus, flavus, et hiridicus, et est probabiliter insolitissima raritas in toto mundo.
Hagar Nishaachar
Greenhorn

Joined: Sep 03, 2003
Posts: 4
Thanks !
Name change is done.
Wayne L Johnson
Ranch Hand

Joined: Sep 03, 2003
Posts: 399
Not to nitpick, but I think it's:
...
aCalendar.add(Calendar.MONTH, x); // FIELD, then amount
...
The amount can be positive or negative.
Hagar Nishaachar
Greenhorn

Joined: Sep 03, 2003
Posts: 4
Yes Mate that correct.
Thanks for the pointer.
cheers
Hagar
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Adding days to January 1, 1900