Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Convert UTC to PDT/PST with Java 8 time library

I would like to use built-in Java 8 time library to convert from UTC to PST/PDT.

I am writing a program that talks to an API that returns a list of objects according to a time frame. E.g. objects created/modified from a certain date time.

My program uses LocalDateTime and the value is always in UTC.
The API accepts PST/PDT.
"The time zone represented in all API responses is PST/PDT. Similarly, CompanyName asks that you make all time zone convertions and submit any dateTime requests in PST/PDT." -- quote from API documentation

I think what they mean by PST/PDT is that the time value should reflect whether it is in day-light-saving or not.
E.g. the time value changes twice a year.

If that is the case, is there a practical/conventional way to convert from UTC to PST/PDT without manually figuring out if it is in day-light-saving time by looking at the exact date?

UPDATE

The API returns the objects in JSON format.
My app send a request to their API with a query parameter api.com/objects?modified-date=${yyyy-MM-dd hh:mm:ss}

I am currently using the following method to do the conversion:

public static String toSsTimeStr(LocalDateTime utcTime){
    String pattern  = "yyyy-MM-dd HH:mm:ss";

    ZonedDateTime zdt = ZonedDateTime.ofInstant(utcTime, ZoneOffset.UTC, ZoneId.of("America/Los_Angeles"));

    String timeStr = zdt.format(DateTimeFormatter.ofPattern(pattern));
    return timeStr;
}  

Will this help adjust the day-light-saving time, in other words, return the correct value according to the current day-light-saving-time status for me?

Thank you.

like image 940
Minjun Yu Avatar asked Jul 18 '16 23:07

Minjun Yu


2 Answers

My program uses LocalDateTime and the value is always in UTC.

A LocalDateTime has no time zone at all, so it is not in UTC.

For a moment in UTC, use the Instant class. This represents a moment on the timeline in up to nanosecond resolution.

Instant now = Instant.now();

To adjust into a time zone, apply a ZoneId to get a ZonedDateTime.

Never use the 3-4 letter abbreviations like PST & PDT so commonly seen in the mainstream media. They are not real time zones, not standardized, and are not even unique(!). Use proper time zone names in continent/region format.

ZoneId zoneId = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = instant.atZone( zoneId );

It sounds like your data sink has the poor design of taking an input of a string that represents a date-time value assumed to be in America/Los_Angeles time zone but lacking any indicator (no offset-from-UTC, no time zone).

To get such a string, lacking any offset or zone, use the predefined DateTimeFormatter named ISO_LOCAL_DATE_TIME. You will get a string in standard ISO 8601 format like this: 2011-12-03T10:15:30.

String output = zdt.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME );

Your data sink omits the T from the middle, so replace with SPACE.

output = output.replace( `T` , " " );

If your data sink expects only whole seconds, you can truncate any fractional second from your date-time value.

zdt = zdt.truncatedTo( ChronoUnit.SECONDS );

Going the other direction, from string to object, define a formatter, parse as a LocalDateTime and apply the assumed time zone.

String input = "2011-12-03 10:15:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss" );
LocalDateTime ldt = LocalDateTime.parse( input , formatter );
ZoneId zoneId = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = ldt.atZone( zoneId );
like image 145
Basil Bourque Avatar answered Sep 24 '22 14:09

Basil Bourque


How about this?

ZoneId zid = ZoneId.of(ZoneId.SHORT_IDS.get("PST"));
return LocalDate.now(zid)

The SHORT_IDS is a documented way of getting the zoneId based on recognized TZ abbreviations. Documentation, FYR

like image 31
Soumitra Avatar answered Sep 22 '22 14:09

Soumitra