decal
decal

Reputation: 1017

Java Date formatting issue

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

Answers (3)

Basil Bourque
Basil Bourque

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.time

Java 8 and later comes with the java.time framework. A vast improvement over the old java.util.Date/.Calendar.

UTC

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

In A Time Zone

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

Kamil
Kamil

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

pgreen2
pgreen2

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

Related Questions