Reputation: 1017
I am trying to format some dates using the Java Date class. I have some long values that I have gotten through previous calculations. Before I start formatting any dates I have a list of longs, they are as follows.
-12345
0
12345
I do some basic formatting like this...
DateFormat df = new SimpleDateFormat("dd/MMM/yyyy HH:mm:ss");
String formattedDate = df.format(new Date(dateNumber.longValue()));
Because Java uses the start of 1970 as a base my expected output would be something like
31/Dec/1969 23:59:47
01/Jan/1970 00:00:00
01/Jan/1970 00:00:12
However the output I am actually getting is
31/Dec/1969 18:59:47
31/Dec/1969 19:00:00
31/Dec/1969 19:00:12
I am a bit confused as to why they are all on December the 31 rather than split between December 31 and January 1. Due to the face that the second two numbers in the list are positive I cannot figure out why the date would be anything before 1970. If anyone can help me out with this using basic Java libraries I'd much appreciate it.
Upvotes: 1
Views: 601
Reputation: 340158
Other answers are correct but outdated. As they mention, one of the many bad features of java.util.Date is that its toString
method silently applies your JVM’s current default time zone while generating the String representation of the date-time value.
Java 8 and later comes with the java.time framework. A vast improvement over the old java.util.Date/.Calendar.
For a moment on the timeline in UTC, use the Instant
class. The java.time has a factory method ofEpochMilli
, convenient for our purpose here with your numbers of milliseconds since first moment of 1970 UTC. But note that java.time classes have a much higher underlying resolution of nanoseconds rather than milliseconds.
Instant negative = Instant.ofEpochMilli ( - 12345L );
Instant zero = Instant.ofEpochMilli ( 0L );
Instant positive = Instant.ofEpochMilli ( 12345L );
Dump to console.
System.out.println ( "negative: " + negative + " zero: " + zero + " positive: " + positive );
negative: 1969-12-31T23:59:47.655Z zero: 1970-01-01T00:00:00Z positive: 1970-01-01T00:00:12.345Z
We can take any of those Instant
objects and adjust into a specific time zone. This yields a ZonedDateTime
object.
Your offset-from-UTC seems to be -05:00
. So I'll arbitrarily pick a time zone of America/Jamaica
for that offset.
ZoneId zoneId = ZoneId.of ( "America/Jamaica" );
ZonedDateTime zdtNegative = ZonedDateTime.ofInstant ( negative, zoneId );
ZonedDateTime zdtZero = ZonedDateTime.ofInstant ( zero, zoneId );
ZonedDateTime zdtPositive = ZonedDateTime.ofInstant ( positive, zoneId );
Dump to console.
System.out.println ( "zdtNegative: " + zdtNegative + " zdtZero: " + zdtZero + " zdtPositive: " + zdtPositive );
zdtNegative: 1969-12-31T18:59:47.655-05:00[America/Jamaica] zdtZero: 1969-12-31T19:00-05:00[America/Jamaica] zdtPositive: 1969-12-31T19:00:12.345-05:00[America/Jamaica]
Upvotes: 0
Reputation: 431
You can set the timeZone of data format object to GMT:
df.setTimeZone(TimeZone.getTimeZone("GMT"));
and you should get what you wanted. The timestamp represents "number of milliseconds since January 1, 1970, 00:00:00 GMT" and for your current timezone the results will differ.
Upvotes: 3
Reputation: 3651
You need to be careful with timezones. It looks like you are US Eastern time. Date assumes UTC. When you are printing, you are printing int Eastern time, so you are 5 hours behind.
Upvotes: 1