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()}")
}
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.
2
Answers
tl;dr
Your issue of differing dates likely has nothing to do with MongoDB, and nothing to do with versions of Java. Your issue is probably due to using different time zones.
The same moment has different dates when seen through different time zones.
Your code:
… uses default time zone. I suspect that default varied at runtime.
Do not do that, do not rely upon such defaults. 👉🏽 Specify your expected/desired time zone explicitly. For example:
Details
Time zone rules change quite often. Most every version and update of Java includes a fresh tzdata.
Sounds like a time zone issue.
By the way… The time zone rules were retroactively documented mainly for 1970 and later. And even then the rules have some holes and inaccuracies. Going further back in decades is even more likely to be less accurate. Fixes are always possible in later versions of tzdata.
No such thing as
CEST
time zone.Text such as
CEST
is a pseudo-zone that gives a hint about what might be the intended time zone, and whether Daylight Saving Time (DST) is in effect. Pseudo-zones are not standardized, and are not even unique(!). Never use these pseudo-zones for storing, exchanging, or processing date-time values. Use pseudo-zones only for presentation to the user.Real time zones have a name in format of
Continent/Region
such asEurope/Paris
,America/Edmonton
, andPacific/Auckland
.Exactly what data type did you use? Not covered in your Question.
The most likely explanation is that your issue (differing dates) has nothing to do with versions of Java… the issue involves a change in your JVMs’ current default time zone.
For any given moment, 👉🏽 the date varies around the globe by time zone. The same moment can be “tomorrow” in Tokyo Japan while simultaneously “yesterday” in Los Angeles US.
Run this to verify the current default time zone (in Java syntax):
Depending on such defaults is a great way to mess up your tests. Instead, specify your expected/desired time zone.
See this code run at Ideone.com. Notice the differing dates in effect for the same simultaneous point on the timeline. Alice in LA looks up to her wall calendar to see the 21st, while at the very same moment Bob in Tokyo looks up to his wall clock/calendar to see the 22nd.
Verify inputs
Let’s run your examples through Java 12 at Ideone.com.
The issue you’re seeing is almost certainly due to the difference in time zone database being used in the two versions of Java. Time zone rules are updated over time, and it looks like you’ve found 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, but 1934-07-21 for Java 21.
Demonstration
Output