please see if you can tell me how to handle the DST issue in my case.
first, my application is a logistic system and it is for global user,so it involves timezone problem,i will handle it as following when set user local date of booking:
1.when user login application,we could get user's timezone according to login IP,but is is just an offset (i don't remember the term of this stuff) e.g "GMT+08"(BeiJing) or "GMT-06"(Chicago) .
2.before user save booking ,we need to set booking local date,as i can't get user local date direct .so i will get the server date first(in my case,it is BeiJing time),then calculate local date according to server date and user timezone,e.g if user timezone is "GMT-08",server date is 2013-08-29 17:45:00. server timezone is "GMT+08",then i will use server date-8-8 and the result will be 2013-08-29 01:45:00.but as i don't consider the DST,the calculated local date will be difference from the actual date.e.g now in San Francisco,the actual local date will be earlier one hour than the result that i calculated using this way,
i find the java TimeZone have already considered the DST problem,but i need to provide "location" name(e.g US/Alaska,Pacific/Apia) when construct TimeZone . while in my case, what i can get is just the offset.so can you tell me how to fix the DST issue in my case?
The right way to handle DST in Java is to instantiate a Timezone with a specific TZDB Timezone ID, eg. “Europe/Rome”. Then, we'll use this in conjunction with time-specific classes like java. util.
The observesDaylightTime() method of TimeZone class in Java is used to check and verify whether the given date is in daylight saving time or if any transition from Standard Time to Daylight Saving Time will occur at any future time.
If you cannot change the OS or the JVM timezone, you can still convert a Java Date/Time or Timestamp to a specific time zone using the following two JDBC methods: PreparedStatement#setTimestamp(int parameterIndex, Timestamp x, Calendar cal) – to convert the timestamp that goes to the database.
The switch to daylight saving time does not affect UTC. It refers to time on the zero or Greenwich meridian, which is not adjusted to reflect changes either to or from Daylight Saving Time.
Yes, you should use either Joda-Time or the new java.time package in Java 8 (inspired by Joda-Time).
An offset is the number hours-minutes-seconds from UTC (GMT) that is represented by a certain date-time value. West coast is -08:00 (ignoring Daylight Saving Time nonsense), meaning 8 hours behind UTC.
Beware that java.time in its initial release has a small bug where it fails to handle an offset of just hours (such as +08
) without minutes (such as +08:00
).
A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region.
Use proper time zone names (mostly continent slash city). Avoid the 3 or 4 letter codes, such as EST, which are neither standardized nor unique.
A java.util.Date
has no time zone, while a Joda-Time DateTime
does.
To get a web browser's time zone, see this question. But often, this does not work well. As you've probably seen, many web sites ask the user to choose a time zone.
Your exact use-case is confusing. Generally the best approach is to use date-time values for UTC, then adjust to user's local time as needed. Usually best for your software to work and store date-times as UTC. Then present a local date-time adjusted to suit the user. In other words, think globally (UTC), present locally (local time zone adjusted).
Usually sysadmins keep their server computers set to UTC (no time zone offset). If your OS (like Mac OS X) does not offer UTC, then use Reykjavik
as Iceland uses UTC year-round without any Daylight Saving Time. Likewise, database engines almost always convert date-time values to UTC for storage.
Joda-Time does offer a LocalDate class for when you truly do not care about time zone or time. But often it is better to use a date-time (a DateTime instance), and format for a date-only string as needed.
Example code in Joda-Time 2.3.
DateTimeZone timeZoneChina = DateTimeZone.forID( "Asia/Shanghai" );
DateTime dateTimeChina = new DateTime( 2013, 8, 29, 17, 45, 00, timeZoneChina );
DateTime dateTimeUtc = dateTimeChina.withZone( DateTimeZone.UTC );
DateTime dateTimeParis = dateTimeChina.withZone( DateTimeZone.forID( "Europe/Paris" ) );
DateTimeZone timeZoneUsWestCoast = DateTimeZone.forID( "America/Los_Angeles" );
DateTime dateTimeUnitedStatesWestCoast = dateTimeChina.withZone( timeZoneUsWestCoast );
DateTimeFormatter formatter = ISODateTimeFormat.date();
String outputDateOnlyForUnitedStatesWestCoast = formatter.withZone( timeZoneUsWestCoast ).print( dateTimeUtc );
Dump to console…
System.out.println( "dateTimeChina: " + dateTimeChina );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "dateTimeParis: " + dateTimeParis );
System.out.println( "dateTimeUnitedStatesWestCoast: " + dateTimeUnitedStatesWestCoast );
System.out.println( "outputDateOnlyForUnitedStatesWestCoast: " + outputDateOnlyForUnitedStatesWestCoast );
When run…
dateTimeChina: 2013-08-29T17:45:00.000+08:00
dateTimeUtc: 2013-08-29T09:45:00.000Z
dateTimeParis: 2013-08-29T11:45:00.000+02:00
dateTimeUnitedStatesWestCoast: 2013-08-29T02:45:00.000-07:00
outputDateOnlyForUnitedStatesWestCoast: 2013-08-29
Similar code in java.time.
Current moment in UTC.
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC.
Adjust into a time zone for Chicago area, yielding a ZonedDateTime
object.
ZoneId zChicago = ZoneId.of( "America/Chicago" ) ;
ZonedDateTime zdtChicago = instant.atZone( z ) ;
Adjust into China time zone.
ZoneId zShanghai = ZoneId.of( "Asia/Shanghai" ) ;
ZonedDateTime zdtShanghai = zdtChicago.withZoneSameInstant( zChicago ) ;
All three objects (instant
, zdtChicago
, and zdtShanghai
) represent the same moment, the same point on the timeline. Simultaneous, but seen through various wall-clock times.
Apparently you want just the date portion for some purpose, without the time-of-day and without time zone. For that extract a LocalDate
object.
LocalDate ld = zdtChicago.toLocalDate() ;
Of course that may be a different date than returned by zdtShanghai.toLocalDate()
.
You may need to construct a specific moment.
ZonedDateTime zdtShanghai = ZonedDateTime.of( 2013, 8, 29, 17, 45, 0, 0 , zShanghai ) ;
You said:
i need to provide "location" name
Location has nothing to do with time zone. A businessperson from Québec might want to see a particular schedule in America/Montreal
zone while physically traveling in Tokyo Japan.
You can ask the user’s web browser or local JVM for its current default time zone. But ultimately, if critical, you must confirm the desired/expected time zone with the user.
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
.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
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. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
It's a common source of headache
I solved a similar problem with the following approach : You associate a precise timezone to each user in your server-side database. When user fills a booking form you display a TZ selector, pre-filled with his default TZ. So he can double check it (IMHO much safer than guessing by IP) and on server side, Dates can be safely converted from local to server time and back.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With