> Also covers: [8249280](https://bugs.openjdk.org/browse/JDK-8249280) > > I will first give a quick summary of the problem. > Put simply, the `LocalDate` form of the `java.sql.Date` is derived using the > `getYear` method of `java.util.Date`. This in turn returns the year of the > normalised internal calendar. > However, the internal calendar `getYear` has an extra layer of complexity. > The calendar has an additional era field, which captures BC/AD. > `getYear` therefore just returns the year _of that era_. > For example, the year 6BC and the year 6AD both return `getYear` as 6. > > **This means that for BC dates, our `LocalDate` conversion loses the sign of > the year.** > > This leads to additional problems down the line, as the year 1BC is for > calculations sake is considered to be year 0 (and 2BC us considered year -1 > and so on). As a result, the various leap year calculations are WRONG for > these years, causing year format validation failures in situations like > marshalling/unmarshalling the dates with a DB. > > There are two seemingly obvious fixes here, however I will attempt to explain > why I did not proceed with them. > > Firstly, it seems sensible is to derive the `LocalDate` from an `Instant` > created from the millisecond representation of the `Date`. After all, why we > are having to use the deprecated `getYear`, `getMonth` and `getDay` methods > anyway? > The answer lies in [8061577](https://bugs.openjdk.org/browse/JDK-8061577). > The underlying millisecond representation between `java.time.Instant` and > `java.util.Date` is fundamentally different. Read that ticket for a greater > explanation. > Ultimately though, it means that the for older dates, the only real way to > bridge between the two calendar systems is to use these year/month/day > methods. > > This is where the second possible solution appears. > The underlying calendar representation that `java.util.Date` uses actually > does have a year method which gives you the correctly signed year, that being > `getNormalizedYear`. > In fact, `java.util.Date` uses the setter counterpart `setNormalizedYear` is > its `setYear` method. > Given this, it seems natural that `getYear` should similarly call > `getNormalizedYear`. > I think this would be my ideal solution, however I recognise that `get`Year > only returning a positive year is very long standing behaviour. Given how > widely spread `java.util.Date` is, I felt it was perhaps better not to rock > the boat too much. > > I have therefore taken the decision to add an equivalent `getNormalizedYear` > method to `java.util.Da...
Sholto has updated the pull request incrementally with four additional commits since the last revision: - 8272194: improve unit tests for Date/Timestamp LocalDate/LocalDateTime conversion - 8272194: update copyright year for java.sql.Date and java.sql.Timestamp to 2026 - 8272194: only use created calendar for year derivation in LocalDate/LocalDateTime conversion - 8272194: fix bad comments in LocalDate/LocalDateTime conversion ------------- Changes: - all: https://git.openjdk.org/jdk/pull/31808/files - new: https://git.openjdk.org/jdk/pull/31808/files/745c717c..50236676 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=31808&range=03 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=31808&range=02-03 Stats: 42 lines in 4 files changed: 16 ins; 0 del; 26 mod Patch: https://git.openjdk.org/jdk/pull/31808.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/31808/head:pull/31808 PR: https://git.openjdk.org/jdk/pull/31808
