Convert Date/Time for given Timezone - java

前端 未结 16 2491
孤城傲影
孤城傲影 2020-11-22 12:36

I want to convert this GMT time stamp to GMT+13:

2011-10-06 03:35:05

I have tried about 100 different combinations of DateFormat, TimeZone,

16条回答
  •  北恋
    北恋 (楼主)
    2020-11-22 12:56

    tl;dr

    Instant.ofEpochMilli( 1_317_816_735_000L )
        .atZone( ZoneId.of( "Pacific/Auckland" ) )
        .format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( new Locale( "en" , "NZ" ) ) )
    

    …also…

    LocalDateTime.parse( "2011-10-06 03:35:05".replace( " " , "T" ) )
        .atZone( ZoneId.of( "Pacific/Auckland" ) )
    

    java.time

    The Question and most Answers use outdated legacy date-time classes from the earliest versions of Java. These old classes have proven to be troublesome and confusing. Avoid them. Instead use the java.time classes.

    ISO 8601

    Your input string is nearly in standard ISO 8601 format. Just replace the SPACE in the middle with a T.

    String input = "2011-10-06 03:35:05".replace( " " , "T" );
    

    LocalDateTime

    Now parse as a LocalDateTime because the input lacks any information about offset-from-UTC or time zone. A LocalDateTime has no concept of offset nor time zone, so it does not represent an actual moment on the timeline.

    LocalDateTime ldt = LocalDateTime.parse( input );
    

    ZoneOffset

    You seem to be saying that from the business context you know the intention of this string is to represent a moment that is 13 hours ahead of UTC. So we instantiate a ZoneOffset.

    ZoneOffset offset = ZoneOffset.ofHours( 13 ); // 13 hours ahead of UTC, in the far east of the globe.
    

    OffsetDateTime

    Apply it to get an OffsetDateTime object. This becomes an actual moment on the timeline.

    OffsetDateTime odt = ldt.atOffset( offset);
    

    ZoneId

    But then you mention New Zealand. So you had a specific time zone in mind. A time zone is an offset-from-UTC plus a set of rules for handling anomalies such as Daylight Saving Time (DST). So we can specify a ZoneId to a ZonedDateTime rather than a mere offset.

    Specify a proper time zone name. 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(!). For example, Pacific/Auckland.

    ZoneId z = ZoneId.of( "Pacific/Auckland" );
    

    ZonedDateTime

    Apply the ZoneId.

    ZonedDateTime zdt = ldt.atZone( z );
    

    You can easily adjust into another zone for the very same moment on the timeline.

    ZoneId zParis = ZoneId.of( "Europe/Paris" );
    ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis );  // Same moment in time, but seen through lens of Paris wall-clock time.
    

    Count from epoch

    I strongly recommend against handling date-time values as a count from epoch, such as milliseconds from the start of 1970 UTC. But if you must, create a Instant from such a number.

    Instant instant = Instant.ofEpochMilli( 1_317_816_735_000L );
    

    Then assign a time zone as seen above, if desired, to move away from UTC.

    ZoneId z = ZoneId.of( "Pacific/Auckland" );
    ZonedDateTime zdt = instant.atZone( z );
    

    Your value of 1_317_816_735_000L is:

    • 2011-10-05T12:12:15Z (Wed, 05 Oct 2011 12:12:15 GMT)
    • 2011-10-06T01:12:15+13:00[Pacific/Auckland] (Thursday October 06, 2011 01:12:15 in Auckland New Zealand).

    Generate strings

    To generate a string in standard ISO 8601 format, simply call toString. Note that ZonedDateTime wisely extends the standard format by appending the name of the time zone in square brackets.

    String output = zdt.toString();
    

    For other formats, search Stack Overflow for DateTimeFormatter class. Already covered many times.

    Specify a FormatStyle and a Locale.

    Locale l = new Locale( "en" , "NZ" );
    DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l );
    String output = zdt.format( f );
    

    Note that time zone has nothing to do with locale. You can have a Europe/Paris date-time displayed in Japanese language & cultural norms, or a Asia/Kolkata date-time displayed in Portuguese language and Brazil cultural norms.

    About java.time

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

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

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

    Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).

    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.

提交回复
热议问题