I have list with long values (for example: 1220227200, 1220832000, 1221436800…) which I downloaded from web service. I must convert it to Dates. Unfortunately this way, for example:
Date d = new Date(1220227200);
returns 1 Jan 1970. Anyone know another way to convert it correctly?
Date constructor (click the link!) accepts the time as
long in milliseconds, not seconds. You need to multiply it by 1000 and make sure that you supply it as
Date d = new Date(1220227200L * 1000);
This shows here
Sun Aug 31 20:00:00 GMT-04:00 2008
It looks like your longs are seconds, and not milliseconds. Date constructor takes time as millis, so
Date d = new Date(timeInSeconds * 1000);
Instant.ofEpochSecond( 1_220_227_200L )
Know Your Data
People use various precisions in tracking time as a number since an epoch. So when you obtain some numbers to be interpreted as a count since an epoch, you must determine:
- What epoch?
Many epochs dates have been used in various systems. Commonly used is POSIX/Unix time, where the epoch is the first moment of 1970 in UTC. But you should not assume this epoch.
- What precision?
Are we talking seconds, milliseconds, microseconds, or nanoseconds since the epoch?
- What time zone?
Usually a count since epoch is in UTC/GMT time zone, that is, has no time zone offset at all. But sometimes, when involving inexperienced or date-time ignorant programmers, there may be an implied time zone.
In your case, as others noted, you seem to have been given seconds since the Unix epoch. But you are passing those seconds to a constructor that expects milliseconds. So the solution is to multiply by 1,000.
- Determine, don’t assume, the meaning of received data.
- Read the doc.
Your data seems to be in whole seconds. If we assume an epoch of the beginning of 1970, and if we assume UTC time zone, then
1,220,227,200 is the first moment of the first day of September 2008.
The java.util.Date and .Calendar classes bundled with Java are notoriously troublesome. Avoid them. Use instead either the Joda-Time library or the new java.time package bundled in Java 8 (and inspired by Joda-Time).
Note that unlike j.u.Date, a
DateTime in Joda-Time truly knows its own assigned time zone. So in the example Joda-Time 2.4 code seen below, note that we first parse the milliseconds using the default assumption of UTC. Then, secondly, we assign a time zone of Paris to adjust. Same moment in the timeline of the Universe, but different wall-clock time. For demonstration, we adjust again, to UTC. Almost always better to explicitly specify your desired/expected time zone rather than rely on an implicit default (often the cause of trouble in date-time work).
We need milliseconds to construct a DateTime. So take your input of seconds, and multiply by a thousand. Note that the result must be a 64-bit
long as we would overflow a 32-bit
long input = 1_220_227_200L; // Note the "L" appended to long integer literals. long milliseconds = ( input * 1_000L ); // Use a "long", not the usual "int". Note the appended "L".
Feed that count of milliseconds to constructor. That particular constructor assumes the count is from the Unix epoch of 1970. So adjust time zone as desired, after construction.
Use proper time zone names, a combination of continent and city/region. Never use 3 or 4 letter codes such as
EST as they are neither standardized not unique.
DateTime dateTimeParis = new DateTime( milliseconds ).withZone( DateTimeZone.forID( "Europe/Paris" ) );
For demonstration, adjust the time zone again.
DateTime dateTimeUtc = dateTimeParis.withZone( DateTimeZone.UTC ); DateTime dateTimeMontréal = dateTimeParis.withZone( DateTimeZone.forID( "America/Montreal" ) );
Dump to console. Note how the date is different in Montréal, as the new day has begun in Europe but not yet in America.
System.out.println( "dateTimeParis: " + dateTimeParis ); System.out.println( "dateTimeUTC: " + dateTimeUtc ); System.out.println( "dateTimeMontréal: " + dateTimeMontréal );
dateTimeParis: 2008-09-01T02:00:00.000+02:00 dateTimeUTC: 2008-09-01T00:00:00.000Z dateTimeMontréal: 2008-08-31T20:00:00.000-04:00
The makers of Joda-Time have asked us to migrate to its replacement, the java.time framework as soon as is convenient. While Joda-Time continues to be actively supported, all future development will be done on the java.time classes and their extensions in the ThreeTen-Extra project.
The java-time framework is defined by JSR 310 and built into Java 8 and later. The java.time classes have been back-ported to Java 6 & 7 on the ThreeTen-Backport project and to Android in the ThreeTenABP project.
Instant instant = Instant.ofEpochSecond( 1_220_227_200L );
ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Those are probably timestamps in seconds and not in milliseconds which is required for the java new Date(long) constructor. Just multiply them by 1000 and you should be allright.
Only set the time in mills on Calendar object
Calendar c = Calendar.getInstance(); c.setTimeInMillis(1385355600000l); System.out.println(c.get(Calendar.YEAR)); System.out.println(c.get(Calendar.MONTH)); System.out.println(c.get(Calendar.DAY_OF_MONTH)); // get Date System.out.println(c.getTime());
Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(1220227200 * 1000); System.out.println(cal.getTime());
The long values, most likely, correspond to Epoch timestamps, and the values are:
1220227200 = Mon, 01 Sep 2008 00:00:00 GMT
1220832000 = Mon, 08 Sep 2008 00:00:00 GMT
1221436800 = Mon, 15 Sep 2008 00:00:00 GMT
One can convert these long values to java.util.Date, taking into account the fact java.util.Date uses millisecs – as previously hinted, but with some flaw – like this:
// note: enforcing long literals (L), without it the values would just be wrong. Date date = new Date(1220227200L * 1000L);
Now, to display the date correctly, one can use java.text.DateFormat as illustrated hereafter:
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL); df.setTimeZone(TimeZone.getTimeZone("UTC")); System.out.println("Wrong date time value: " + date); System.out.println("Correct date time value: " + df.format(date));
Below are the results of displaying the converted long value to java.util.Date without
using and using the DateFormat:
Date wrong (off by 2 hours): Mon Sep 01 02:00:00 CEST 2008 Correct date : Monday, 1 September 2008 00:00:00 o'clock UTC
New Date(number) returns a date that’s
number milliseconds after 1 Jan 1970. Odds are you date format isn’t showing hours, minutes, and seconds for you to see that it’s just a little bit after 1 Jan 1970.
You need to parse the date according to the correct parsing routing. I don’t know what a 1220227200 is, but if it’s seconds after 1 JAN 1970, then multiply it to yield milliseconds. If it is not, then convert it in some manner to milliseconds after 1970 (if you want to continue to use java.util.Date).
Works for me. You probably want to multiplz it with 1000, since what you get are the seconds from 1970 and you have to pass the milliseconds from jan 1 1970
1220227200 corresponds to Jan 15 1980 (and indeed new Date(1220227200).toString() returns “Thu Jan 15 03:57:07 CET 1970”). If you pass a long value to a date, that is before 01/01/1970 it will in fact return a date of 01/01/1970. Make sure that your values are not in this situation (lower than 82800000).