Home > OS >  Convert timestamp to Date time for a particular timezone
Convert timestamp to Date time for a particular timezone

Time:12-30

I want to convert a timestamp (which is in GMT) to a local date and time.

This is what I have implemented so far, but it is giving me wrong month

Timestamp stp = new Timestamp(1640812878000L);
Calendar convertTimestamp = convertTimeStamp(stp,"America/Phoenix");
System.out.println(convertTimestamp.getTime());
    

public static Calendar convertTimeStamp( Timestamp p_gmtTime, String p_timeZone) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy HH:MM:SS a", Locale.ENGLISH);
        DateFormat formatter = DateFormat.getDateTimeInstance();
        if (p_timeZone != null) {
            formatter.setTimeZone(TimeZone.getTimeZone(p_timeZone));
        } else {
            formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
        }

        String gmt_time = formatter.format(p_gmtTime);
        Calendar cal = Calendar.getInstance();
        cal.setTime(sdf.parse(gmt_time));
        return cal;
    }

Any help would be appreciated.

CodePudding user response:

You cannot convert a timestamp to another timezone, cause timestamps are always GMT, they are a given moment in the line of time in the universe.

We humans are used to local time on our planet, so a timestamp can be formatted to be more human readable, and in that context it is converted to a local timezone.

Using legacy java.util.* packages, this is done as follows:

DateFormat tzFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
tzFormat.setTimeZone(TimeZone.getTimeZone("CET")); // Use whatever timezone
System.out.println(tzFormat.format(date));

If you need to make "math" over the timestamp on local timezone (like, tomorrow at 8:00 local timezone), then the situation is more complex.

To do this you can resort to a number of hacks (like parsing or modifying the string obtained with the method above), or use the new Java date & time classes that have a specific class to deal with date and time in local time zones:

Instant timestamp = Instant.ofEpochMilli(inputValue);
ZonedDateTime romeTime = timestamp.atZone(ZoneId.of("Europe/Rome"));

Note how this second example uses "Europe/Rome" and not generically "CET". This is very important if you're planning to deal with timezones where DST is used, cause the DST change day (or if they use DST or not) may change from country to country even if they are in the same timezone.

CodePudding user response:

tl;dr

Instant
.ofEpochMilli(                       // Parse a count of milliseconds since 1970-01-01T00:00Z.
    1_640_812_878_000L
)                                    // Returns a `Instant` object.
.atZone(                             // Adjust from UTC to a time zone. Same moment, same point on the timeline, different wall-clock time.
    ZoneId.of( "America/Phoenix" ) 
)                                    // Returns a `ZonedDateTime` object.
.format(                             // Generat text representing the date-time value kept within that `ZonedDateTime` object.
    DateTimeFormatter
    .ofLocalizedDateTime( FormatStyle.MEDIUM )
    .withLocale( Locale.US ) 
)                                    // Returns a `String` object.

See this code run live at IdeOne.com.

Dec 29, 2021, 2:21:18 PM

Details

You are using terrible old date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310. Never use Timestamp, Calendar, Date, SimpleDateFormat, etc.

Use the Instant class to represent a moment as seen in UTC, with an offset of zero hours-minutes-seconds.

long millisecondsSinceBeginningOf1970InUtc = 1_640_812_878_000L ;
Instant instant = Instant.ofEpochMilli( millisecondsSinceBeginningOf1970InUtc ) ;

Specify the time zone in which you are interested.

ZoneID z = ZoneId.of( "Africa/Tunis" ) ;

Adjust from offset of zero to that time zone to produce a ZonedDateTime object.

ZonedDateTime zdt = instant.atZone( z ) ;

Generate text representing that moment by automatically localizing. Use a Locale to specify the human language to use in translation as well as a culture to use in deciding abbreviation, capitalization, order of elements, and so on.

Locale locale = Locale.JAPAN ; // Or Locale.US, Locale.ITALY, etc.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.LONG ).withLocale( locale ) ;
String output = zdt.format( f ) ;

All of this has been addressed many times on Stack Overflow. Search to learn more.

  • Related