Does a 'z' in a datetime String have different outputs in different locales?

deHaar :

Not long ago, I provided an answer to a question about how to extract the time zone from a ZonedDateTime parsed from a String.
It worked in general, but there were different outputs of the same code on OP's system an my one, which somehow doesn't let me go anymore.

The related question asked how to get a ZoneId from a ZonedDateTime and I provided a way. Admittedly, it is not the accepted answer, but still seemed worth an upvote from someone.

The special thing about my answer is concerning the 'z' in the pattern used to parse the time String. There is a time zone name in that String representing the zone "Australia/Adelaide" by "... ACST" (Australian Central Standard Time).

When I parse it on my system and print/format the ZonedDateTime using the DateTimeFormatter.ISO_ZONED_DATE_TIME, it prints the time in "America/Manaus" and having extracted the ZoneId, it is still that one from South America. OP stated in a comment below my answer, that on his system, at least one of the output lines shows the desired/correct ZoneId.

How is that possible? Does the system default locale have any influence on parsing the 'z' in datetime Strings?

This is the code from my answer in the question plus an output of my ZoneId.systemDefault():

public static void main(String args[]) throws Exception {
    String time = "2 Jun 2019 03:51:17 PM ACST";
    String pattern = "d MMM yyyy hh:mm:ss a z"; // z detects the time zone (ACST here)
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);

    // parse a time object using the formatter and the time String
    ZonedDateTime zdt = ZonedDateTime.parse(time, formatter);
    // print it using a standard formatter
    System.out.println(zdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
    // extract the zone id
    ZoneId zoneId = zdt.getZone();
    ZoneId sysDefault = ZoneId.systemDefault();
    // print the zone id
    System.out.println("Time zone of parsed String is " + zoneId);
    System.out.println("System default time zone is " + sysDefault);

    // retrieve the instant seconds
    Instant instant = zdt.toInstant();
    // print the epoch seconds of another time zone
    System.out.println("Epoch seconds in Australia/Adelaide are " 
            + instant.atZone(ZoneId.of("Australia/Adelaide")).toEpochSecond());
}

and its output is this:

2019-06-02T15:51:17-04:00[America/Manaus]
Time zone of parsed String is America/Manaus
System default time zone is Europe/Berlin
Epoch seconds in Australia/Adelaide are 1559505077

Can anyone point me to a mistake I have made or confirm and explain the influence of different system default ZoneIds on parsing a String to a ZonedDateTime?

Ole V.V. :

I too have experienced ambiguous time zone abbreviations being parsed differently on different JVMs (also when providing a locale, so that is not the only issue). I don't think the exact behaviour is documented. In some cases the JVMs default time zone was chosen, I don't know if it will always be when it matches, though.

You can control the choice of time zone in ambiguous cases through the overloaded DateTimeFormatterBuilder.appendZoneText(TextStyle, Set<ZoneId>) method.

An example where locale makes a difference: Europe/Berlin and many other European time zones will be formatted into Central European Time or CET in many locales. In a German locale they instead become Mitteleuropäische Zeit or MET.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=125293&siteId=1