Java convert millisecond timestamp to date with respect to given timezone

后端 未结 4 1649
北海茫月
北海茫月 2021-01-15 12:58

I have seen many resources on this but one thing I cant get is when converting the millisecond timestamp, how I add a corresponding time zone, during the conversion process.

相关标签:
4条回答
  • 2021-01-15 13:25

    tl;dr

    Instant.ofEpochMilli( myCountOfMilliseconds ) 
           .atZone( ZoneId.of( "Africa/Tunis" ) )
           .toString()
    

    java.time

    The modern approach uses the java.time classes rather than the troublesome old Calendar/Date classes that are now legacy.

    Assuming your count of milliseconds is a count since the epoch reference of first moment of 1970 in UTC (1970-01-01T00:00), then parse as a 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.ofEpochMilli( myCountOfMilliseconds ) ;
    

    To move from UTC to another time zone, apply a ZoneId to get a ZonedDateTime.

    Specify a proper time zone name in the format of continent/region, such as America/Montreal, 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( "Africa/Tunis" ) ;
    ZonedDateTime zdt = instant.atZone( z ) ;
    

    Objects vs text

    After assigning the time zone, then generate a string in your desired format (not before). You may be conflating date-time values (objects) with strings representing their value textually. Learn to think of smart objects, not dumb strings.

    DateTimeFormatter

    To generate a String in a particular format, use a DateTimeFormatter. Search Stack Overflow as this been covered many many times, as have the other concepts shown here. Of special note are the DateTimeFormatter.ofLocalized… methods.


    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 讨论(0)
  • 2021-01-15 13:30

    I was doing a similar thing in my previous project.You can use setTimeZone method of SimpleDateFormat class. Something like this :

    mydate.setTimeZone(TimeZone.getTimeZone("GMT -0400"));
    
    0 讨论(0)
  • 2021-01-15 13:35
        DateTimeFormatter myDateFormatter
                = DateTimeFormatter.ofPattern("EEE, MMM d, ''yy", Locale.ENGLISH);
        long dateInSec = 1_554_321_098L;
        String utcOffsetString = "-04:00";
        ZoneOffset offset = ZoneOffset.of(utcOffsetString);
        String date = Instant.ofEpochSecond(dateInSec)
                .atOffset(offset)
                .format(myDateFormatter);
        System.out.println(date);
    

    This prints

    Wed, Apr 3, '19
    

    The other example offset you gave, +2:00, is slightly more difficult since ZoneOffset.of requires either only hours (+2) or two-digit hours before the colon (+02:00). One solution is to fix the string before handing it to ZoneOffset:

        String utcOffsetString = "+2:00";
        utcOffsetString = utcOffsetString.replaceFirst("([-+])(\\d:\\d{2})", "$10$2");
        ZoneOffset offset = ZoneOffset.of(utcOffsetString);
    

    The result is still Wed, Apr 3, '19. If there were already 2-digit hours in the string, replaceFirst won’t replace anything, so you just get the same string back.

    If I change the offset to +08:00, I get Thu, Apr 4, '19 instead.

    Edit: I frankly find the regular expression I use for fixing the offset string quite unreadable. Here’s a simpler way of fixing it:

        DateTimeFormatter offsetFormatter = DateTimeFormatter.ofPattern("O", Locale.ENGLISH);
        ZoneOffset offset = ZoneOffset.from(offsetFormatter.parse("GMT" + utcOffsetString));
    

    Like Basil Bourque I am using java.time. See all the details in his answer.

    0 讨论(0)
  • 2021-01-15 13:47

    Not exactly what your looking for but close

    String timeZone = "America/Los_Angeles"
    TimeZone tz = TimeZone.getTimeZone(timeZone);
    SimpleDateFormat sdf = new SimpleDateFormat("EEEEE MMMMM d hh:mm a");
    sdf.setTimeZone(tz);
    
    Date localizedTime = sdf.format(new Date());
    

    If you keep the localization strings instead of the offsets this will work. Or you can make a map.

    0 讨论(0)
提交回复
热议问题