Trying to parse date and time in PDT into ZonedDateTime representation

How should I parse this datetime value which is in the PDT timezone?

06/24/2017 07:00 AM (PDT)

      

I want to store the timezone so that I can then represent times in other timezones depending on the preference of the site visitors.

I tried to use ZonedDateTime

, but I got a parsing error:

   java.time.ZonedDateTime.parse("06/24/2017 07:00 AM (PDT)")

      

Mistake:

java.time.format.DateTimeParseException: Text '06/24/2017 07:00 AM (PDT)' could not be parsed at index 0
   at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
   at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
   at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)
   at java.time.ZonedDateTime.parse(ZonedDateTime.java:582)   ... 29 elided

      

Also, do you agree with what I should be using ZonedDateTime

?

+3


source to share


3 answers


Since your format is non-standard, you need to specify it in the parser:



ZonedDateTime.parse(
    "06/24/2017 07:00 AM (PDT)", 
    DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm a (zzz)")
);

      

+5


source


The method expects in a specific format , eg . Since your input is in a different format, you will need . parse

String

2007-12-03T10:15:30+01:00[Europe/Paris]

DateTimeFormatter

It should be noted that the API uses IANA time zone names (always in the format Continent/City

such as America/Sao_Paulo

or Europe/Berlin

). Avoid using 3-letter abbreviations (for example, CST

or PST

) because they are ambiguous and not standard .

The API makes some exceptions with specific identifiers and provides some default values ​​for them. For, PDT

it defaults to America/Los_Angeles

.

Another detail is that in the example below, I used a lowercase hh

in the template: the format has an AM / PM indication, so I believe this hh

is the correct template since its value is from 1 to 12 (common values ​​when there is an AM / PM).

If you use an uppercase letter hh

, it allows values ​​from 0 to 23 (and this is not often used for use with AM / PM), but throws an exception if the input contains an hour, like07:00 PM

.

So, the code will look like this:

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a (zzz)");
ZonedDateTime z = ZonedDateTime.parse("06/24/2017 07:00 AM (PDT)", fmt);
System.out.println(z);

      

Output:

2017-06-24T07: 00-07: 00 [America / Los_Angeles]

But not all three-letter time zone names will be recognized by the API and will throw an exception.



Anyway, there are other timeslots that are also in the PDT (for example America/Vancouver

) - you can get a list of all by calling ZoneId.getAvailableZoneIds()

. If you want to use a different default timezone, you can create a set of preferred zones and build a formatter with that set:

Set<ZoneId> preferredZones = new HashSet<>();
// set America/Vancouver as preferred zone
preferredZones.add(ZoneId.of("America/Vancouver"));
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
    // pattern
    .appendPattern("MM/dd/yyyy hh:mm a (")
    // append timezone with set of prefered zones
    .appendZoneText(TextStyle.SHORT, preferredZones)
    // finish the pattern
    .appendPattern(")")
    // create formatter
    .toFormatter();
System.out.println(ZonedDateTime.parse("06/24/2017 07:00 AM (PDT)", fmt));

      

The API will use the preferred zones (in this case America/Vancouver

) instead of the default ( America/Los_Angeles

). The output will be:

2017-06-24T07: 00-07: 00 [America / Vancouver]


It is not clear where the entrance came from String

. If you cannot control your format, then you have no choice: they have to be parsed that way. Then you can convert it to a different timezone using the method withZoneSameInstant

:

// parse the input string
ZonedDateTime z = ZonedDateTime.parse("06/24/2017 07:00 AM (PDT)", fmt);
// convert to another timezone
ZonedDateTime other = z.withZoneSameInstant(ZoneId.of("America/Sao_Paulo")); // 2017-06-24T11:00-03:00[America/Sao_Paulo]

      

The value other

will be 2017-06-24T11:00-03:00[America/Sao_Paulo]

.

But if you can control the output, it is always better (IMO) to work with UTC ( java.time.Instant

) and convert to some timezone only when displayed to users:

// convert ZonedDateTime to instant
ZonedDateTime z = // parse input
// convert to UTC (Instant is always in UTC)
Instant instant = z.toInstant();
// internally work with instant (as it always in UTC)

// convert instant to some timezone only when necessary (like displaying to users)
ZonedDateTime converted = instant.atZone(ZoneId.of("Europe/London"));

      

+4


source


The error you are getting is well covered in other answers.

Also, do you agree with what I should be using ZonedDateTime

?

Yes and no. Your string must be parsed into ZonedDateTime

. I recommend that you convert it to Instant

and save it. Then, when you need to present it to the user according to their timezone preference, you can convert or convert Instant

to again ZonedDateTime

or just format it with the DateTimeFormatter

desired default timezone .

Why is that? First, it is common practice to preserve Instant

s. Some people prefer to store only milliseconds from epoch, I think these are some (often misunderstood) performance metrics. Of course, such milliseconds, which I am unreadable, but Instant

can be deciphered by eye, at least roughly. The only alternative that I respect is that you surely know that your application will never worry about the timezone (does this ever happen?) And is sometimes LocalDateTime

used for storage.

If I understand your situation correctly, you need to store a point in time to display in multiple time zones. You do not need to store the timezone in which the time was entered (e.g. PDT, except that PDT is not a complete timezone). Instant

is timezone neutral which is one of the reasons I prefer it to store the time in some timezone like ZonedDateTime

. Also Instant

more understandable conceptually and I guess it is also easier to implement.

There are some much better answers here: Best practices for storing time and time data in a database when the data is date and time dependent .

+4


source







All Articles