1

I have a string "02:00:00 Feb 05, 2023 PST" which I parse:

ZonedDateTime d = ZonedDateTime.parse(nextPaymentDate, DateTimeFormatter.ofPattern("H:m:s MMM d, uuuu z"));

Comparing it a constructed date:

ZonedDateTime expectedDate = ZonedDateTime.of(2023, 2, 5, 2, 0, 0, 0, ZoneId.of(ZoneId.SHORT_IDS.get("PST")));

fails, because:

Expected :2023-02-05T02:00-08:00[America/Los_Angeles]
Actual   :2023-02-05T02:00-08:00[America/Tijuana]

Setting exact timezone id (e.g. fixing America/Tijuana) does not work, as the timezone is parsed differently on another machine (as America/Los_Angeles instead of America/Tijuana like on my machine).

How can I assert the dates are equal in this case?

KarloSpacapan
  • 173
  • 2
  • 16
  • 3
    So you want to compare the actual time they identify? Then convert them to `Instant` and compare those. – Joachim Sauer Feb 02 '23 at 10:48
  • Related: [IST mapped to wrong ZoneId in java.time library](https://stackoverflow.com/questions/57733849/ist-mapped-to-wrong-zoneid-in-java-time-library) – Ole V.V. Feb 02 '23 at 17:12

2 Answers2

2

The time zone abbreviations used by Java when parsing depend on the locale, so you cannot compare the result to a fixed value. See this answer.

I would convert the ZonedDateTime objects to OffsetDateTime before comparing them, or even to Instant, as Joachim suggested.

rolve
  • 10,083
  • 4
  • 55
  • 75
2

First of all, I suggest you ask the publisher of your data to avoid using abbreviated timezone IDs. In most cases, these abbreviations are 3 characters long but they may be 2 or 4 characters long (e.g. CT and AEST) as commented by Basil Bourque.

Given below is a note from the Java 7 Timezone documentation:

Three-letter time zone IDs

For compatibility with JDK 1.1.x, some other three-letter time zone IDs (such as "PST", "CTT", "AST") are also supported. However, their use is deprecated because the same abbreviation is often used for multiple time zones (for example, "CST" could be U.S. "Central Standard Time" and "China Standard Time"), and the Java platform can then only recognize one of them.

There is already a good suggestion by Joachim Sauer. Alternatively, you can retrieve the ZoneId from the parsed date-time and use it while constructing your ZonedDateTime.

Demo:

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

class Main {
    public static void main(String[] args) {
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("H:m:s MMM d, uuuu z", Locale.ENGLISH);
        String strNextPaymentDate = "02:00:00 Feb 05, 2023 PST";
        ZonedDateTime zdtNextPaymentDate = ZonedDateTime.parse(strNextPaymentDate, parser);
        ZonedDateTime zdtExpectedDate = ZonedDateTime.of(2023, 2, 5, 2, 0, 0, 0, zdtNextPaymentDate.getZone());
        System.out.println(zdtNextPaymentDate);
        System.out.println(zdtExpectedDate);
    }
}

Output:

2023-02-05T02:00-08:00[America/Los_Angeles]
2023-02-05T02:00-08:00[America/Los_Angeles]

ONLINE DEMO

Learn more about the modern Date-Time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • 1
    Actually, those pseudo zones can be 2-4 characters long, not just 3. Examples: [CT](https://www.timeanddate.com/time/zones/ct) and [AEST](https://www.timeanddate.com/time/zones/aest). – Basil Bourque Feb 02 '23 at 17:17