Loss of an hour when returning the January 1970 date from milliseconds

I have the following code that takes a string of milliseconds (it will be from an RSS feed, so there will be a String, the example below is a quick testing program) and converts these millions into a Date object.

public static void main(String[] args) { String ms = "1302805253"; SimpleDateFormat dateFormatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz"); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(Long.parseLong(ms)); try { String dateFormat = dateFormatter.format(calendar.getTime()); System.out.println("Date Format = " + dateFormat); Date dateParse = dateFormatter.parse(dateFormatter.format(calendar.getTime())); System.out.println("Date Parse = " + dateParse); } catch (ParseException e) { // TODO: handle exception } } Output: Date Format = Fri, 16 Jan 1970 02:53:25 GMT Date Parse = Fri Jan 16 03:53:25 GMT 1970 

As you can see, between formatting the calendar object and parsing the resulting string, the hour is lost. In addition, the formatting of the output has changed. Can someone help me why this is happening and how to get around this? I want the Date object to be in the same format as the Date Format output.

+4
source share
2 answers

I believe this is because in the UK in 1970 GMT was not actually used, and Java has a mistake in that ... it will format the date in 1970, as if the UK had used GMT, but without actually changing offsets, a simple example:

 Date date = new Date(0); SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss zzz"); sdf.setTimeZone(TimeZone.getTimeZone("Europe/London")); System.out.println(sdf.format(date)); 

Result:

 01 Jan 1970 01:00:00 GMT 

Please note that he claims 1:00 GMT ... which is not true. It was at 1 am in Europe / London, but Europe / London did not observe GMT.

Joda Time gets it right because it prints BST - but Joda Time doesn't like to analyze values ​​with time zone abbreviations. However, you can force it to use time zones instead:

 import org.joda.time.*; import org.joda.time.format.*; public class Test { public static void main(String[] args) throws Exception { DateTime date = new DateTime(0, DateTimeZone.forID("Europe/London")); DateTimeFormatter formatter = DateTimeFormat.forPattern( "dd MMM yyyy HH:mm:ss Z"); String text = formatter.print(date); // 01 Jan 1970 01:00:00 +0100 System.out.println(text); DateTime parsed = formatter.parseDateTime(text); System.out.println(parsed.equals(date)); // true } } 
+8
source

Jon Skeet's answer is correct.

java.time

Allows you to run the same input through java.time to see the results.

Please enter a valid time zone name . Never use the abbreviation 3-4 letters, for example BST , EST or IST , as they are not real time zones, and are not standardized and not even unique (!). Therefore, we use Europe/London .

Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds .

 String input = "1302805253"; long millis = Long.parseLong ( input ); Instant instant = Instant.ofEpochMilli ( millis ); 

Apply time zone to create a ZonedDateTime object.

 ZoneId zoneId = ZoneId.of ( "Europe/London" ); ZonedDateTime zdt = instant.atZone ( zoneId ); 

Dump for the console. We really see that Europe/London an hour ahead of UTC at this point. Thus, the time of day is 02 hours, not 01 hours. Both represent the same simultaneous moment on the timeline, they are simply viewed through the lenses of two different wall clocks .

 System.out.println ( "input: " + input + " | instant: " + instant + " | zdt: " + zdt ); 

entrance: 1302805253 | instant: 1970-01-16T01: 53: 25.253Z | zdt: 1970-01-16T02: 53: 25.253 + 01: 00 [Europe / London]

Whole seconds

By the way, I suspect your input line represents whole seconds since the 1970 UTC era, not milliseconds. Interpreted that in a matter of seconds we get the date in 2011, in the month that this issue was published.

 String output = Instant.ofEpochSecond ( Long.parseLong ( "1302805253" ) ).atZone ( ZoneId.of ( "Europe/London" ) ).toString (); 

2011-04-14T19: 20: 53 + 01: 00 [Europe / London]

About java.time

The java.time framework is built into Java 8 and later. These classes supersede old inconvenient time classes such as java.util.Date , .Calendar and java.text.SimpleDateFormat .

The Joda-Time project, now in maintenance mode , advises switching to java.time.

To learn more, see the Oracle Tutorial . And search for qaru for many examples and explanations.

Most of the functionality of java.time is ported back to Java 6 and 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP .

The ThreeTen-Extra project extends java.time with additional classes. This project is proof of possible future additions to java.time.

0
source

All Articles