Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i convert time zone string to the TimeZone Object in java?

I have several time zone strings in UTC format, such as "UTC+08:00", "UTC-05:00", the question is how can i convert these utc format strings to the java.util.TimeZone in Java?

I have tried to convert by ZoneId as follows, but it did not work:

ZoneId zoneId = ZoneId.of("UTC+08:00");
TimeZone timeZone = TimeZone.getTimeZone(zoneId);

I know TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai"); would work, but I do not know the mapping between "UTC+08:00" and "Asia/Shanghai"

like image 308
Jianeng Xu Avatar asked Jan 04 '23 01:01

Jianeng Xu


1 Answers

tl;dr

  • Do not use TimeZone class (now legacy).
  • Use ZoneOffset and ZoneId instead.

Example:

ZoneOffset.of( "+08:00" )

Use java.time.ZoneId, not TimeZone

The troublesome old date-time classes bundled with the earliest versions of Java are now legacy, supplanted by the java.time classes. Among these old legacy classes is TimeZone, now supplanted by ZoneId and ZoneOffset.

An offset-from-UTC is a number of hours and minutes adjustment ahead of, or behind, UTC. This is represented by the ZoneOffset class.

A time zone is a collection of offsets, the history of changes in the offset used by a particular region in determining their wall-clock time. This is represented by the ZoneId class.

Using a time zone is always preferable to an offset as a zone has the offset plus so much more information. But your examples are only mere offsets. So use the ZoneOffset to parse the strings after deleting the characters UTC.

String input = "UTC+08:00".replace( "UTC" , "" ) ;
ZoneOffset offset = ZoneOffset.of( input ) ;

Do not guess the time zone

You cannot assume that a particular offset implies a particular time zone. Many zones may have used a particular offset in the past, present, or future. So you should not guess the zone.

Take, for example, the offset of +08:00. That offset is currently used by several different time zones including Asia/Shangai, Asia/Macao, and Australia/Perth.

If you are certain a particular zone was intended for a date-time value, apply it to get a ZonedDateTime. But do not guess.

The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.

Instant instant = Instant.now() ;
ZoneId z = ZoneId.of( "Asia/Shanghai" ) ; 
ZonedDateTime zdt = instant.atZone( z ) ;

If you do not know for certain the intended time zone and have only an offset, use the offset to get an OffsetDateTime.

Instant instant = Instant.now() ;
ZoneOffset offset = ZoneOffset.of( "+08:00" ) ; 
OffsetDateTime odt = instant.atOffset( offset ) ;

Convert

Best to avoid the old legacy class TimeZone. But if you must use that class to work with old code not yet updated for the java.time classes, you can convert to/from a ZoneId. Use the new conversion methods added to the old classes.

TimeZone myLegacyTimeZone = TimeZone.getTimeZone( myModernZoneId ); 

…and…

ZoneId z = myLegacyTimeZone.toZoneId() ;

Note that ZoneOffset is a subclass of ZoneId. Normally, we ignore that inheritance relationship. If you have only a mere offset such as +08:00, use ZoneOffset. If you have a full time zone such as Asia/Shanghai, use ZoneId. One exception to this rule is for this conversion to/from TimeZone where only the superclass ZoneId is recognized.

like image 183
Basil Bourque Avatar answered Jan 13 '23 14:01

Basil Bourque