Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

After migrating to Java 17, the date is displayed inaccurately

We've recently transitioned our application from Java 11 to Java 17. Subsequent to the deployment, we've noticed that certain records exhibit a discrepancy where dates are displaying with a one-day difference (+1). This occurs specifically in records with years before 1940. Our application operates in the CEST timezone, and dates are stored in MongoDB as UTC. The following examples highlight instances where we've identified the issue.

DB Java 11 Java 17
1934-07-21T22:40:28.000+00:00 1934-07-22 1934-07-21
1897-08-06T23:40:28.000+00:00 1897-08-07 1897-08-06

The provided code snippet, written in Kotlin, produces satisfactory results in Java 11. However, when executed with Java 17, the same code fails to function as expected.

fun main() {  // Kotlin code
    val date = Date(-1118625572000) //1934-07-21T22:40:28.000+00:00
    println("Date: ${date.toInstant()?.atZone(ZoneId.of("Europe/Amsterdam"))!!.toLocalDate()}")
}

Java11 Output:
Code output showing "Date: 1934-07-22"

Java17 Output:
Code output showing "Date: 1934-07-21"

Is there a solution available in Java 17 to address issues related to these types of dates?

We attempted to rectify those records directly in the database to ensure the population of valid dates.

For example,

1934-07-21T22:40:28.000+00:00 --> 1934-07-22T00:00:00.000+00:00
1897-08-06T23:40:28.000+00:00 --> 1897-08-07T00:00:00.000+00:00

However, we need to explore whether there is a way to handle these types of dates specifically in Java 17.

like image 941
Vivek Buddhadev Avatar asked Oct 23 '25 21:10

Vivek Buddhadev


1 Answers

The issue you're seeing is due to the difference in time zone database being used in the two versions of Java. Time zone rules are updated over time, and you've encountered an old date that is treated differently under newer rules.

For the versions of Java on my machine, I'm getting 1934-07-22 for Java 11 & 17 (time zone database versions 2020d & 2021e, respectively), but 1934-07-21 for Java 21 (time zone database version 2023c).

The specific reason for this is that 2020d & 2021e have a zone offset of +01:19:32 for this instant in Europe/Amsterdam. On the other hand, 2023c has a zone offset of +01:00 in Europe/Amsterdam. Adding 1:19:32 to 1934-07-21T22:40:28Z results in midnight the next day (1934-07-22), but adding 1:00:00 results in 23:40:28 the same day (1934-07-21).

Time zone database change

I did some Internet sleuthing, and per the time zone database mailing list, it looks like this change was made in time zone database version 2022b. So 2022a and earlier use the +01:19:32 offset, and 2022b and later use the +01:00 offset.

2022b merged the Amsterdam & Brussels time zones, which are identical after 1970, but differ in sufficiently early historical dates. It looks like Amsterdam at one point used local mean time, hence the strange-looking offset. However, it seems that Brussels did not.

Between 2022a an b the timezone info for Europe/Amstedam is removed:
      Z Europe/Amsterdam 0:19:32 - LMT 1835
The timezone info for Brussels around that date differs from Amsterdams timezone info.

Determining the timezone information for dates around that period on my Linux system in python returns since the latest update an offset of 0 minutes as opposed to the 19 minutes previously.

Is the removal for this timezone information intentional or a bug?

The maintainer has merged the Amsterdam and Brussels timezone information by using the Brussels rules for Amsterdam, as the rules don't differ since 1970, in the default data package. This wipes out Amsterdam rules from before 1970, including local mean time.

Demonstration

String javaVersion = System.getProperty("java.vendor") + Runtime.version();
String timeZoneDatabase = ZoneRulesProvider.getVersions("UTC")
        .keySet().stream().findFirst().orElseThrow();
Date date = new Date(-1118625572000L);
ZoneId timeZone = ZoneId.of("Europe/Amsterdam");
ZonedDateTime zonedDateTime = date.toInstant().atZone(timeZone);
LocalDate localDate = zonedDateTime.toLocalDate();

System.out.printf("Java: %s%n", javaVersion);
System.out.printf("Time Zone Database: %s%n", timeZoneDatabase);
System.out.printf("Instant (UTC): %s%n", date.toInstant());
System.out.printf("LocalDate (Europe/Amsterdam): %s%n", localDate);
System.out.printf("Time zone offset: %s%n", zonedDateTime.getOffset());

Output

Java: AdoptOpenJDK11.0.10+9
Time Zone Database: 2020d
Instant (UTC): 1934-07-21T22:40:28Z
LocalDate (Europe/Amsterdam): 1934-07-22
Time zone offset: +01:19:32
Java: Eclipse Adoptium17.0.2+8
Time Zone Database: 2021e
Instant (UTC): 1934-07-21T22:40:28Z
LocalDate (Europe/Amsterdam): 1934-07-22
Time zone offset: +01:19:32
Java: Eclipse Adoptium21.0.1+12-LTS
Time Zone Database: 2023c
Instant (UTC): 1934-07-21T22:40:28Z
LocalDate (Europe/Amsterdam): 1934-07-21
Time zone offset: +01:00
like image 80
M. Justin Avatar answered Oct 25 '25 10:10

M. Justin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!