Based on Epoch seconds, I convert it to the start of hour and end of hour.
long epochSeconds = 1589374800L;
Instant instant = Instant.ofEpochSecond(epochSeconds);
Calendar now = Calendar.getInstance(TimeZone.getTimeZone(ZoneId.of("Asia/Kolkata")));
now.setTimeInMillis(instant.toEpochMilli());
System.out.println(now.getTime()); // Correct --> Wed May 13 06:00:00 PDT 2020
Calendar endOfHour = (Calendar)now.clone();
endOfHour.set(Calendar.MINUTE, 59);
endOfHour.set(Calendar.SECOND, 59);
endOfHour.set(Calendar.MILLISECOND, 999);
System.out.println(endOfHour.getTime()); // Wrong ---> Wed May 13 06:29:59 PDT 2020
The start of hour seems correct, but the end of hour is not giving it right, instead of upto 59 minute, 59 second, 999 millisecond it is giving only half hour difference.
You are mixing java.time and java.util.Calendar types. Don't do that. For one thing, you're losing the TimeZone you specified when you clone. Basically, Calendar is a mess. But you don't need it here, something like
long epochSeconds = 1589374800L;
LocalDateTime date = Instant.ofEpochSecond(epochSeconds) //
.atZone(ZoneId.of("Asia/Kolkata")) //
.toLocalDateTime();
System.out.println(date);
LocalDateTime endOfHour = date.withMinute(59) //
.withSecond(59) //
.with(ChronoField.MILLI_OF_SECOND, 999);
System.out.println(endOfHour);
Should meet your needs. Here that outputs
2020-05-13T18:30
2020-05-13T18:59:59.999
Two points (and one more at the end):
Just repeating what has already been said: don’t mix old and modern date-time classes. Use the modern ones exclusively. Forget about the old ones. They were always poorly designed anyway.
Your observed result is correct and as should be expected.
You are using Asia/Kolkata time zone for your (outmoded) Calendar object. Asia/Kolkata time zone is special in that it is not offset a whole number of hours from UTC as most time zones are, but +05:30, five and a half hours. Let’s look at your times in this time zone first. Your epoch second value (AKA Unix timestamp) is equal to 2020-05-13T18:30:00+05:30 in Asia/Kolkata. The end of that hour in Asia/Kolkata is 2020-05-13T18:59:59.999. This is the result that you get.
It seems that you are running your program on a JVM in a different time zone (perhaps America/Vancouver or America/Los_Angeles). This time zone is offset a whole number of hours from UTC, so 18:59:59.999 in India equals 06:29:59 PDT (your time zone).
Half-open:
I promised you a third point. Represent the end of the hour as the whole hour, here 19:00 rather than 18:59:59 and some number of 9s. The philosophical argument: The hour doesn’t end one millisecond before the next hour begins, so this is incorrect. The practical argument: It frees you from deciding how many 9s you need. java.time has nanosecond precision, so is able to represent nearly a million points in time between your end of the hour and the beginning of the next hour. You risk hitting such a point and assigning it to the wrong hour. In comparisons just make sure that you are checking whether a point in time is strictly before the whole hour where the hour ends.
If you do need Calendar objects for a legacy API:
ZoneId zone = ZoneId.of("Asia/Kolkata");
long epochSeconds = 1589374800L;
ZonedDateTime now = Instant.ofEpochSecond(epochSeconds).atZone(zone);
Calendar nowAsOldfashionedCalendar = GregorianCalendar.from(now);
ZonedDateTime endOfHour
= now.plusHours(1).truncatedTo(ChronoUnit.HOURS).minusNanos(1);
Calendar endOfHourAsOldfashionedCalendar = GregorianCalendar.from(endOfHour);
I included .minusNanos(1) to get the last nanosecond of the previous hour, but as I said, you should prefer to omit it if you can. The conversion to GregorianCalendar will truncate to milliseconds and give you the same result as in your code in the question.
Related
The following is an example that attempts to calculate the difference in hours between time zones.
import java.util.*;
import java.text.*;
public class ForPosting
{
public static void main (String[] args)
{
try {
String myDateString = "07-13-2021 11:00:00";
SimpleDateFormat localDateTime = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
SimpleDateFormat utcDateTime = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss");
localDateTime.setTimeZone(TimeZone.getTimeZone("EET"));
System.out.println(localDateTime.parse(myDateString));
utcDateTime.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(utcDateTime.parse(myDateString));
float diff = ((localDateTime.parse(myDateString).getTime() - utcDateTime.parse(myDateString).getTime() ) / 3600000);
System.out.println("EET & UTC Time Difference : " + diff);
localDateTime.setTimeZone(TimeZone.getDefault());
System.out.println(localDateTime.parse(myDateString));
utcDateTime.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(utcDateTime.parse(myDateString));
diff = ((localDateTime.parse(myDateString).getTime() - utcDateTime.parse(myDateString).getTime() ) / 3600000);
System.out.println("Default & UTC Time Difference : " + diff);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The above code generates the following output.
The Default & UTC Time Difference : 4.0 was confirmed by checking the current dates and it confirms there is a 4 hour difference.
Doing the same check for EET & UTC is different.
EET & UTC Time Difference : -3.0
The output shows a 3 hour difference yet the following shows there is only 2.
Why does the EET & UTC actual time show 2 hour difference yet the Java code shows a 3 hour difference?
EET is not a time zone
EET is a common abbreviation of some 20 time zones in Europe and Northern Africa that are at offset +02:00 from UTC during standard time. Many, not all of them are using summer time (daylight saving time) abbreviated EEST for Eastern European Summer Time and hence are at offset +03:00 during the 7 “summer” months. So what you get when asking for EET, I can’t tell. So don’t do that. Use a proper time zone ID like Europe/Uzhgorod, always in region/city format. So that you know what you get.
So to answer your question:
Why does the EET & UTC actual time show 2 hour difference yet the Java
code shows a 3 hour difference?
Because they interpret EET differently. Both interpretations are fully valid and none is authoritative.
This is nothing special for EET. Many two, three, four and five letter time zone abbreviations are in common use. Very many of them are ambiguous, like EET. And very many of them are not time zones. It may be that there are situations where you can use one for informal communication to the user, for example just to distinguish between EET and EEST in a situation where the user knows well enough what each of those means in the context. You certainly cannot rely on them for defining a time zone in your program.
java.time
I recommend that you use java.time, the modern Java date and time API, for your date and time work. To find the difference between some time zone and UTC at a moment in time:
ZoneId zone = ZoneId.of("Europe/Uzhgorod");
Instant when = Instant.now();
ZoneOffset differenceFromUtc = when.atZone(zone).getOffset();
System.out.format("%s & UTC Time Difference : %s%n", zone, differenceFromUtc);
Output when running just now:
Europe/Uzhgorod & UTC Time Difference : +03:00
It’s summer now in Europe/Uzhgorod, and the difference of 3 hours comes from that time zone using summer time. Try with an instant in winter:
Instant when = Instant.parse("2022-01-01T00:00:00Z");
Europe/Uzhgorod & UTC Time Difference : +02:00
As I said, some Eastern European time zones do not use summer time. Try with one of those:
ZoneId zone = ZoneId.of("Europe/Kaliningrad");
Instant when = Instant.now();
Europe/Kaliningrad & UTC Time Difference : +02:00
Minor comments to your code
While UTC works for defining a time zone, the canonical ID is Etc/UTC. Etc is a pseudo-region for time zones that don’t belong in a well-defined geographical region including Etc/UTC, Etc/GMT and also the IDs for mere whole-hour offsets like Etc/GMT-2 (for offset +02:00, the sign is inverted).
Assigning the result of your division to a float does not help you. You are dividing a long values by an int value, and the result is always truncated to an long number. When assigning to a float you will still always have a whole number. If you wanted a fraction as result, you would need to convert at least one of the operands to float (or double) before dividing.
And a funny detail, your code measures the difference in hours between when it’s 11 o’clock in EET and 11 o’clock in UTC. You get a result exactly because there are 3 hours between those two moments. What I am not so pleased about is that you are not measuring the difference at a well-defined point in time. Instead in my code I am choosing one point in time and finding the difference at that point.
Link
Oracle tutorial: Date Time explaining how to use java.time.
From the front end I am receiving a separate LocalDate (variable name is date), along with separate Integers for hours, minutes, seconds, and an "AM" or "PM" String, and I need to combine these into a java.time.Instant object to store in the database. I tried to construct a LocalTime as follows, adding 12 hours if this is a PM time and then constructing an Instant:
LocalTime time = LocalTime.of("pm".equals(amPm) ? hours + 12: hours, minutes, seconds);
Instant instant = date.atTime(time).toInstant(ZoneOffset.UTC);
But when I store and reload the page, though the date is always intact, the time is always being changed. If I set the date to 1/29/1900 and the time to 07:01:01 AM, the Instant I am creating and storing has the value: 1900-01-29T07:01:01Z when I debug, which appears correct, but when the page reloads, the time says 02:01:01 AM, and that is the time that is stored in the database.
Am I constructing the time or the instant incorrectly?
There’s hardly any doubt that your unexpected observations are due to one or more time zone issues.
So the first thing you need to do is make sure you know which time zones are involved.
Which time zone is your front end using for sending date and time to you?
Which time zone is your database using for storing the date and time and displaying them to you when you check them? (UTC would be recommended for storing the times.)
Once you know this you can check:
Is the conversion from 1/29/1900 07:01:01 AM from the front end in some time zone to an Instant of 1900-01-29T07:01:01Z correct? The Instant displays its time in UTC (denoted by the trailing Z).
Is the conversion from the Instant to 02:01:01 AM in the database time zone correct?
Is the time being fetched correctly from the database? I am assuming you are fetching it back into Java?
Is the time you’ve got in Java being converted correctly to 02:01:01 AM on the front end? Again I am assuming that on page reload your are displaying the time fetched from the database, but I don’t think you have told us, so I could be wrong.
To answer your question:
Am I constructing the time or the instant incorrectly?
It depends; it’s certainly possible.
Your construction of the time is assuming that pm is always in lower case and that 12 o’clock (midnight or noon) is given as 0. On one hand I find both assumptions more or less unlikely, on the other hand they cannot account for the discrepancy of 5 hours that you observed. 12 would conventionally be given as 12 (not 0) on a 12 hour clock. And your question gives PM in upper case.
Your construction of the Instant assumes that the front end sent the time in UTC. To me this sounds unlikely too, and it may be the reason or one of the reasons why you observed an incorrect time being displayed back after page reoload.
Code example
In the following snippet I am making the opposite assumptions: 12 is given as 12, AM/PM may be in any case, and the front end time zone is America/New_York. It’s probably way off, but there may be a detail that you can pick and use for your purpose.
DateTimeFormatter timeFormatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive() // Accept all of am, AM, aM and Am
.appendPattern("h:m:sa")
.toFormatter(Locale.US);
ZoneId zone = ZoneId.of("America/New_York");
LocalDate date = LocalDate.of(1900, Month.JANUARY, 29);
int hours = 7;
int minutes = 1;
int seconds = 1;
String amPm = "AM";
String constructedTimeString
= "" + hours + ':' + minutes + ':' + seconds + amPm;
LocalTime time = LocalTime.parse(constructedTimeString, timeFormatter);
Instant instant = date.atTime(time).atZone(zone).toInstant();
System.out.println(instant);
Output is:
1900-01-29T12:01:01Z
Geeky section: avoiding formatting time into a string and parsing it back
I couldn’t help thinking about whether it would be possible to have java.time parse the AM/PM string without having to construct a string for the time of day and parse it. It is possible, but we need to use the low-level TemporalAccessor interface, which is otherwise usually unnecessary.
DateTimeFormatter amPmFormatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive() // Accept all of am, AM, aM and Am
.appendPattern("a")
.toFormatter(Locale.US);
int hours = 7;
int minutes = 1;
int seconds = 1;
String amPm = "AM";
TemporalAccessor parsedAmPm = amPmFormatter.parse(amPm);
LocalTime time = LocalTime.of(0, minutes, seconds)
.with(ChronoField.AMPM_OF_DAY, parsedAmPm.get(ChronoField.AMPM_OF_DAY))
.with(ChronoField.CLOCK_HOUR_OF_AMPM, hours);
System.out.println(time);
07:01:01
Construction of the Instant proceeds as before.
I have a problem to convert a java.sql.Time (UTC) which is fetched from a database to a java.time.LocalTime (GMT+1 DST). It is always missing the DST hour. So like a Time of 03:00 is only converted to a LocalTime of 04:00 instead of 05:00.
//Saved UTC time in DB: 03:00
LocalTime.ofInstant(Instant.ofEpochMilli(sqlTime.getTime()), ZoneId.of("Europe/Berlin"));
=> 04:00 //expected 05:00
I guess the problem is that java.sql.Time saves the time with a default date of 1970-01-01 and in 1970 there was no DST in Germany. But of course the time should be shown for today and not for 1970.
So how can I get the correct time for this example?
Assuming that you are using at least JDBC 4.2, you should be able to retrieve a LocalTime from your result set:
LocalTime timeInUtc = yourResultSet.getObject(yourTimeColumn, LocalTime.class);
Then there’s no need bother with the outdated and poorly designed java.sql.Time class. The time you get will still be in UTC, of course. Here’s how to convert:
LocalTime timeInUtc = LocalTime.of(3, 0);
ZoneId zone = ZoneId.of("Europe/Berlin");
LocalTime timeInGermany = OffsetDateTime.now(ZoneOffset.UTC)
.with(timeInUtc)
.atZoneSameInstant(zone)
.toLocalTime();
System.out.println("Zeit heute in Deutschland: " + timeInGermany);
When I ran the code today I got the output you expected:
Zeit heute in Deutschland: 05:00
Edit: If there’s no way you can avoid getting a java.sql.Time, convert it to LocalTime first. Assuming that the Time is in UTC and we don’t want to rely on a fragile JVM time zone setting for conversion, you are correct that we need the getTime method:
Time sqlTimeInUtc = // Get from database
LocalTime timeInUtc
= LocalTime.MIDNIGHT.plus(sqlTimeInUtc.getTime(), ChronoUnit.MILLIS);
If you could rely on the JVM time zone setting also being UTC, the following would be nicer:
LocalTime timeInUtc = sqlTimeInUtc.toLocalTime();
In both cases the rest is as above.
In all cases there are some corner cases around the question whether you want “today in UTC” or “today in Europe/Berlin time zone” when you say “the time should be shown for today”. There’s also a corner case if the time is between 2 and 3 AM and today is the last Sunday in March, where the clocks are turned forward from 2 to 3 to initiate summer time (DST) in Germany. Please think these corner cases through and decide what you want.
By the way your diagnosis is completely correct: Time.getTime returns the time of day on Jan 1, 1970, so when you feed this into an Instant, you are converting the time of day on this date, that is, without summer time.
As far as I understand it your question is: Given a time in UTC convert it to local time according to the current time offset. This time offset is different depending of whether DST is in effect or not.
A possible approach is to determine the current offset using TimeZone:
TimeZone tz = TimeZone.getTimeZone("Europe/Berlin");
int timeZoneOffsetMillis = tz.getOffset(new Date().getTime());
Now timeZoneOffsetMillis contains the number of milliseconds you have to add to your UTC time to get local time.
You can get a LocalTime like this:
LocalTime localTime = LocalTime.ofNanoOfDay((sqlTime.getTime() + timeZoneOffsetMillis) * 1000000L);
If your time is only accurate to seconds instead of nanoseconds anyway you might want to use LocalTime.ofSecondOfDay.
In the following code, range equals durationInDays only when range is less than 30. If it is equal to 30 or greater, durationInDays is always range - 1
Calendar c = Calendar.getInstance();
Date now = new Date();
c.setTime(now);
int range = 35;
c.add(Calendar.DATE, range);
Date then = c.getTime();
Duration duration = Duration.between(now.toInstant(), then.toInstant());
int durationInDays = (int)duration.toDays();
When debugging this example, the variables are set as follows:
this = {CalTest#871}
c = {GregorianCalendar#876} "java.util.GregorianCalendar[time=1522449516301,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Dublin",offset=0,dstSavings=3600000,useDaylight=true,transitions=228,lastRule=java.util.SimpleTimeZone[id=Europe/Dublin,offset=0,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2018,MONTH=2,WEEK_OF_YEAR=13,WEEK_OF_MONTH=5,DAY_OF_MONTH=30,DAY_OF_YEAR=89,DAY_OF_WEEK=6,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,HOUR=11,HOUR_OF_DAY=23,MINUTE=38,SECOND=36,MILLISECOND=301,ZONE_OFFSET=0,DST_OFFSET=3600000]"
now = {Date#877} "Fri Feb 23 23:38:36 GMT 2018"
range = 35
then = {Date#878} "Fri Mar 30 23:38:36 IST 2018"
duration = {Duration#879} "PT839H"
durationInDays = 34
Why does then have an IST timezone? This difference is the causing duration to be a little less than 35 days, rounding to 34.
First, then hasn’t got IST timezone. A Date hasn’t got any time zone. Date.toString chooses a time zone, usually the JVM’s time zone setting, for generating the string only.
Looking at how your two Date objects are rendered in the debugger, one might wonder that it would appear they are rendered in two different time zones. They are not. Both are in Europe/Dublin time zone. As you are probably aware, Ireland with most of the EU switches to summer time (DST) on the last Sunday in March. Therefore, your date in February is in standard time, which in Ireland coincides with GMT, and therefore your string is rendered with GMT as “time zone”. On March 30, summer time is in effect, so the time zone is rendered as IST for Irish Summer Time this time. Edit: the transistion to summer time also accounts for the missing hour compared to your expected duration of 35 days (840 hours).
Edit: Since you can use java.time, the modern Java date and time API, I suggest you go all in and forget about the old-fashioned Date and Calendar. The modern API is so much nicer to work with, and you won’t need all the conversions any longer:
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Europe/Dublin"));
int range = 35;
ZonedDateTime then = now.plusDays(range);
Duration duration = Duration.between(now, then);
int durationInDays = (int) duration.toDays();
The result is still PT839H and hence 34 days.
To obtain a duration in days that agrees with the number of days we added:
int durationInDays = (int) ChronoUnit.DAYS.between(now, then);
System.out.println(durationInDays);
This prints
35
Duration is mostly for durations in hours, minutes and seconds. It does support days, but only days at 24 hours each, so gives the surprising result you saw when used across the summer time transition. ChronoUnit.DAYS on the other hand is exactly made for days. It sees that the two ZonedDateTime instances have the same time-of-day and therefore acknowledges a full 35 days between the two.
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?
The 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 long.
Date d = new Date(1220227200L * 1000);
This shows here
Sun Aug 31 20:00:00 GMT-04:00 2008
tl;dr
java.time.Instant // Represent a moment as seen in UTC. Internally, a count of nanoseconds since 1970-01-01T00:00Z.
.ofEpochSecond( 1_220_227_200L ) // Pass a count of whole seconds since the same epoch reference of 1970-01-01T00:00Z.
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.
Lessons learned:
Determine, don't assume, the meaning of received data.
Read the doc.
Your Data
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.
Joda-Time
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 int.
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 );
When run.
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
java.time
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.
An Instant is a moment on the timeline in UTC with a resolution of nanoseconds. Its epoch is the first moment of 1970 in UTC.
Instant instant = Instant.ofEpochSecond( 1_220_227_200L );
Apply an offset-from-UTC ZoneOffset to get an OffsetDateTime.
Better yet, if known, apply a time zone ZoneId to get a ZonedDateTime.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
It looks like your longs are seconds, and not milliseconds. Date constructor takes time as millis, so
Date d = new Date(timeInSeconds * 1000);
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());
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.
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
Try this:
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1220227200 * 1000);
System.out.println(cal.getTime());
Try this with adjusting the date format.
long longtime = 1212580300;
SimpleDateFormat dateFormat = new SimpleDateFormat("MMddyyHHmm");
Date date = (Date) dateFormat.parseObject(longtime + "");
System.out.println(date);
Note: Check for 24 hours or 12 hours cycle.
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).
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
Because 1220227200 ms = 338,952 hours.
java.util.Date has constructor new Date(Long milliseconds) - Allocates a Date object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
So, in your case just remember 1 sec = 1000 millisec