简体   繁体   中英

Timezone issue while constructing java.util.Date object from timestamp

I am facing an issue of Timezone. let me try to describe:

My Web application & DB is running on a server of having different timezone(Europe/Madrid ie UTC+1) than my local timezone(India/Kolkata ie UTC+5:30).

Lets say my local current time is: Wed Jan 15 14:35:00 IST 2014 and that server current time is: Wed Jan 15 10:05:00 CET 2014 ie lag by 4:30 hrs.

Now when I am trying to save a date time on the DB using calendar selection from my web page (GUI) lets say, the date time I am selecting is: Wed Jan 15 18:30:00 , the final date that is getting saved in DB is becoming Wed Jan 15 14:00:00 (see the difference exactly 4:30 hrs lag time).

let me tell you the coding part of the above flow.

After selection from calendar of my web page -> passing the timestamp(in long) of the selected date time to my server side controller -> at server side, I am constructing java.util.Date object and saving to DB like below:

java.util.Date newDt = new java.util.Date(timeStampInMillis);

Here, timeStampInMillis is in long which I converted from the datetime selected in GUI.

Here it is saving the given timestamp in the current Timezone(UTC + 01:00) of that server and that is how the saved datetime is getting lagged by 4:30 Hrs.

But I want to save as it is ie the date time selected from calendar GUI.

I have some couple of solution like, instead of passing timestamp for constructing Date object in my server side controller, I can pass the String representation of the selected date time from my calendar GUI and then parse the format and save into DB.

But I am wondering if there is anything I can do with Timezone APIs.

Hope my problem is clear to you. If not, please clarify your doubt.

Need your help...

Thanks.

Unclear Question

Your question could be better written. You should try to narrow it down to a very specify example. You don't even specify the milliseconds value under discussion.

Server Time

Servers should almost always be set to a UTC/GMT time zone without Daylight Saving Time. On some systems such as Mac OS X, that is difficult. In that case, set time zone of machine to "Atlantic/Reykjavik" because Iceland stays on UTC/GMT year-round without any Daylight Saving Time nonsense.

Avoid java.util.Date

The java.util.Date & .Calendar classes bundled with Java are notoriously troublesome.

One of the pain points is that while a Date has no time zone assigned, its toString method uses the default time zone in rendering the string. So to the naïve programmer it seems like Date has a time zone when it does not.

Use either the Joda-Time library or the new java.time.* classes bundled with Java 8. Search StackOverflow for many examples of both.

Think Globally, Present Locally

Most of your business logic and your database storage should all be done in UTC/GMT (no time zone offset). A competent database such as Postgres will do so by default.

Only switch to a time zone for presentation to a user, as a general rule.

Time Zone

Always specify a time zone. Do not rely on default time zones as that causes surprises in production or any time machines change their time zone.

Avoid the three letter codes, as they are neither standardized nor unique. Use proper time zone names.

Look up your time zone names in a list like this one (slightly outdated, read details). Your mention of "India/Kolkata" in your question is, I believe, incorrect. Should be "Asia/Kolkata".

ISO 8601

If you must serialize , use only the ISO 8601 format. This format is human-readable, unambiguous, and clearly defined.

Example for India time zone: 2014-01-19T12:38:31+05:30

Example for UTC/GMT "Zulu": 2013-11-22T18:28.023Z

java.sql.* Classes

Use the java.sql.* classes for communicating to your database via JDBC.

You construct a java.sql.Timestamp object by passing the milliseconds since 1970 began. In Joda-Time, call getMillis to obtain a value to pass.

Avoid Milliseconds

Generally, I prefer to avoid dealing with milliseconds for tracking time. People tend to get into trouble since some systems track time from an epoch in seconds, milliseconds, or nanoseconds. Furthermore, there are many epochs in use, not always the Unix-style of first day of 1970.

I try to pass around either:

Example Code

But if you are sure your milliseconds value represents the true number of milliseconds since the first day of 1970 in UTC/GMT, then use this kind of code with Joda-Time. Note the 'L' flagging the number as a long integer.

DateTime dateTime = new DateTime( 1390276603054L );

DateTime dateTimeSpain = dateTime.toDateTime( DateTimeZone.forID( "Europe/Madrid" ) );
DateTime dateTimeIndia = dateTime.toDateTime( DateTimeZone.forID( "Asia/Kolkata" ) );
DateTime dateTimeUtcGmt = dateTime.toDateTime( DateTimeZone.UTC );

// For database.
java.sql.Timestamp timestamp = new java.sql.Timestamp( dateTimeSpain.getMillis() );

Dump to console…

System.out.println( "dateTime (default time zone): " + dateTime );
System.out.println( "dateTimeSpain: " + dateTimeSpain );
System.out.println( "dateTimeIndia: " + dateTimeIndia );
System.out.println( "dateTimeUtcGmt: " + dateTimeUtcGmt );
System.out.println( "timestamp: " + timestamp ); // "toString" uses default time zone.

When run…

dateTime (default time zone): 2014-01-20T19:56:43.054-08:00
dateTimeSpain: 2014-01-21T04:56:43.054+01:00
dateTimeIndia: 2014-01-21T09:26:43.054+05:30
dateTimeUtcGmt: 2014-01-21T03:56:43.054Z
timestamp: 2014-01-20 19:56:43.054

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat .

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes.

To learn more, see the Oracle Tutorial . And search Stack Overflow for many examples and explanations. Specification is JSR 310 .

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more .

timestamp in millis has no timezone. If you create new Date() at the same time in Kolkata and Madrid the Dates will have the same timestamp in millis. The problem can rise only when you interprete textual representation. Again, if textual represenation includes timezone like this Wed Jan 15 14:35:00 IST 2014 SimpleDateFormat.parse in Madrid and Kolkata will produce Date object with the same timestamp in millis.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM