开发者

converting a UTC time to a local time zone in Java

I know this subject has been beaten to death but after searching for a few hours to this problem I had to ask.

My Problem: do calculations on dates on a server based on the current time zone of a client app (iphone). The client app tells the server, in seconds, how far away its time zone is away from GMT. I would like to then use this information to do computation on dates in the server. The dates on the server are all stored as UTC time. So I would like to get the HOUR of a UTC Date object after it has been converted 开发者_开发百科to this local time zone.

My current attempt:

int hours = (int) Math.floor(secondsFromGMT / (60.0 * 60.0));
int mins = (int) Math.floor((secondsFromGMT - (hours * 60.0 * 60.0)) / 60.0);
String sign = hours > 0 ? "+" : "-";

Calendar now = Calendar.getInstance();
TimeZone t = TimeZone.getTimeZone("GMT" + sign + hours + ":" + mins);
now.setTimeZone(t);

now.setTime(someDateTimeObject);

int hourOfDay = now.get(Calendar.HOUR_OF_DAY);

The variables hour and mins represent the hour and mins the local time zone is away from GMT. After debugging this code - the variables hour, mins and sign are correct.

The problem is hourOfDay does not return the correct hour - it is returning the hour as of UTC time and not local time. Ideas?


You timezone string is formulated incorrectly. Try this,

String sign = secondsFromGMT > 0 ? "+" : "-";
secondsFromGMT = Math.abs(secondsFromGMT);      
int hours = secondsFromGMT/3600;
int mins = (secondsFromGMT%3600)/60;
String zone = String.format("GMT%s%02d:%02d", sign, hours, mins);          
TimeZone t = TimeZone.getTimeZone(zone);


tl;dr

get the HOUR of a UTC Date object after it has been converted to this local time zone

Zone (preferred)

ZonedDateTime.now(
    ZoneId.of( "Africa/Tunis" )  // Use a zone rather than a mere offset-from-UTC whenever possible.
).getHour()

23

Offset

OffsetDateTime.now(
    ZoneOffset.ofTotalSeconds( secondsFromGMT )  // Use a mere offset-from-UTC only when the appropriate zone is unavailable AND you have been assured this particular offset is correct for your input data.
).getHour()

23

Avoid legacy date-time classes

You are using troublesome old date-time classes that are now legacy, supplanted by the modern industry-leading java.time classes.

java.time

Get the current moment in UTC as an Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant instant = Instant.now() ;

Adjust into a particular time zone.

Specify a [proper time zone name](https://en.wikipedia.org/wiki/List_of_tz_zones_by_name) in the format of `continent/region`, such as [`America/Montreal`](https://en.wikipedia.org/wiki/America/Montreal), [`Africa/Casablanca`](https://en.wikipedia.org/wiki/Africa/Casablanca), or `Pacific/Auckland`. Never use the 3-4 letter abbreviation such as `EST` or `IST` as they are *not* true time zones, not standardized, and not even unique(!). 

ZoneId z = ZoneId.of( "America/Montreal" );

If at runtime you want the JVM’s current default time zone, ask for it. Keep in mind this can change at any moment. So if critical, you should ask or confirm with the user.

ZoneId z = ZoneId.systemDefault() ;

Apply the time zone to produce a ZonedDateTime object.

ZonedDateTime zdt = instant.atZone( z ) ;

You said you want only the hour-of-day from this zoned date-time. Interrogate with a specific method.

int hourOfDay = zdt.getHour() ;

By the way, you may find the LocalTime class useful.

LocalTime lt = zdt.toLocalTime() ;

Offset vs Zone

The variables hour and mins represent the hour and mins the local time zone is away from GMT

No, not a time zone. You have conflated zone with offset. Very important to understand the distinction.

  • Offset
    An offset-from-UTC is a number of hours and minutes and seconds before/after UTC (GMT). Nothing more, nothing less.
  • Zone
    A time zone is a history of the various offsets in use by the peoples of a particular regian. A zone represents all the changes in the offset over time, past, present, and near-future. Politicians around the world have shown a penchant for frequently changing the offset of their time zone(s).

A particular offset may be in use in multiple places by coincidence. For example, sometimes Dublin, London, Casablanca, Lagos, and Brazzaville all share the same offset of +01:00, one hour ahead of UTC. But at other times they may not, such as in the winter this year when Lagos remains one hour ahead of UTC while the other three switch to zero hours ahead of UTC (that is, UTC itself).

With a zone and a moment, you can determine an offset. But not so going the other direction; with only an offset, you cannot reliably determine a zone.

So your number of hours and minutes is merely an offset. That offset may not be correct for your zone for the input’s particular date. So always prefer a time zone over a mere offset.

OffsetDateTime

If you are stuck for some reason with an offset that you are certain is correct for your given inputs but you do not know the time zone, then use ZoneOffset & OffsetDateTime rather than ZoneId & ZonedDateTime. But if at all possible, use zone instead of offset as explained above.

ZoneOffset offset = ZoneOffset.ofTotalSeconds( secondsFromGMT ) ;
OffsetDateTime odt = OffsetDateTime.now( offset ) ;

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.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, and later
    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜