From 6ddf6dad3140139906d7bef9063f7fb2657c1836 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 27 Dec 2023 14:27:52 +0000 Subject: [PATCH 1/9] Update time zone data to 2023dgtz (#187) Co-authored-by: Stephen Colebourne (CI) --- pom.xml | 2 +- src/main/resources/org/threeten/bp/TZDB.dat | Bin 110189 -> 110501 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6cdd9389c..308ecefe6 100644 --- a/pom.xml +++ b/pom.xml @@ -862,6 +862,6 @@ UTF-8 UTF-8 false - 2023cgtz + 2023dgtz diff --git a/src/main/resources/org/threeten/bp/TZDB.dat b/src/main/resources/org/threeten/bp/TZDB.dat index 10f47707a2a22db378afb29494ae111cb5bf845b..e530c1bcc6de5d3785713bb1ef6140de79b9ded5 100644 GIT binary patch delta 3830 zcmb7GX>^oTw%z*zAxIc2fdm3%AR#F-R#KVBOh_1&NevN0fFL1&3<}~{5g~}80+&JN zK?V^-AVSo}cA`}rkVZsWqk__!RE-Mo%bXCuB*!SpE=`ZK`+9loshn}9i1u(wqKud$(M0p$K)r{%?zdwj?FU+7wrprbt|HylH5fWjM188=RGDYXo<5VzC2>Ss}Jr zR_FFjI_(`D4RW<1KFDs0ciGpY-G0wGI6ByulikTx7e-!ol*X3M&7M?q{Lkm{8I{@9 z{`m-t`ybz{R(bzVt0pi3&N&(c#+M#s?@xC*@!cL1X?Mi*3Ji00H8klScV@@!Z}E9{ zbzFe8aYOA}xqyC6BmE=*3gCu5>*xz}yyCJeKOJ#n_c8)F}czRI~Xj=>q56+iS!=+8O}8k+ny zI9|nmI1PbL+E{pM zBOJ;!J=n8ZQ*8fi_Z7mO(gsf1ZF$LddPbO?mJ!~u$!b_hKF&K2_>^*H)%og>}-|KWT%Lv+eZMLPuw^C*4lSH7A^ReOfQoh^n>*KX4y%X)(lq@?`*(%rRKO}f;X?{OjofTlmXNCARIHnDC%L;rU zb^FIW8dXwxEWWCSDl$P~_Ls=SIUtP=-y~DRS@o#q7`K+lK z96VxWRrRVfzRQ=tsk(4codBa(zS57gRu*;TYF9c%aTBPu7)=y_FRC1*0no|+XB zAa#>Fr)2K#IVBI)=gnkb7Z)G@Gr5j$Ij=%>+e7t-x^MyOM=av$V4ujsdtub0n{gSM zqa9jE{M1icDy;q(gjN`gYfz2Wn5@En0ByJ&ZTWz-K9JTDbbuEf#atJOBzf%w;)o477UL1%R z+>Tf*f?KY7V*%ng7V)?b3Fv}E!AgP;$+!U?K}o?5q;f92EI}G}BAt8WH3yk^3|ZVI zXlIbkIOIrjN#x-Z`0}v|1?+`F97bPG6_2(H(smT{36wAx{m~W!@CpVpU9s4S!Q3hA zU*K9iiR-XM_dAbaoQ&a|ff204Nc@89b^ zjA3&hD&%;q(2Qd}#$z@r@hc{v7j9u9CUP;VcpWBj1FGp&0=UKitQSikxmPjDr+ zFbiApHMa2%C88yso7JUg9XctgTn1^s3VEnnHSre)t>b;B|Jv z8;ru6d=!V3g12}#-j>66@Fm_=Jsd$9-c!bK@!Dj5k=K5`c`HDl9j{J=NoW@qn<2BN2jkguV&TPYM zwpEvIf32qIlKFq!yf3( zFnSm+iC{O;Xs+(FO@a4kG?%g$w=sqVj1>diEEFx0jkL#I$#Z2T-CNYJ{sG&y% zoFZ_k>_{)?sR%cyzSc5B5HlIbEUwe_HVb+NbMPX4xk8(V7R;9vDC32Ak9`H8h+ElD zQY`c(Vnu&+=Kwy*f$X8et5J{pgF~=cJ?=wZ$HzDn%f<6=Ih^Y`LNbyqdA%rh10PYw z?`Elrb`+YUPrTN@G*p_RSggo2Xd+Urq#c&W$FgYWwQcCMV+alZO&Etd$U>{WeuWKz&*ImhXk&N zTg4Tiel(Ap)DJf!Sgv0PoFj=OP8g|(V{bd|lh z%zgM#blk01&JWzrTpm!&>eY&#(?y==KE9xC@E67BAXn4(qE!E?t(O$Ym$`_qC}6MZ z_cg5HA@#1m$@%N}jc+KJZ?ZEF%kV9=p0`zm?}#Puil9f7>-TVyM+M^V0&q;P*Y~-Q z$JGfw(C-P+^Ft=^B=6xrn9q;+5I@FOY{2h6e!}bdsStif@RSZdjjjA#Mql7(o>7JW zQwjKz6Zw@`(y0A^=|*1*)Hjl|ipIA}$9LlMzeTij9K!F>i9e{r|EM>^d4%yNyCz4pjA9q_d2h>wg51tt(9Oc35Roe*a_bB75= zGZTVv(}g2VS0y(;K&$I7vK)n*^>hiTKzgX+IewjRze~3WH3l0C_RWq`_s<^_;Y{SVo}xL*JO delta 3736 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 Date: Mon, 5 Feb 2024 08:09:34 +0000 Subject: [PATCH 2/9] Update time zone data to 2024agtz (#188) Co-authored-by: Stephen Colebourne (CI) --- pom.xml | 2 +- src/main/resources/org/threeten/bp/TZDB.dat | Bin 110501 -> 110501 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 308ecefe6..8b8118da5 100644 --- a/pom.xml +++ b/pom.xml @@ -862,6 +862,6 @@ UTF-8 UTF-8 false - 2023dgtz + 2024agtz diff --git a/src/main/resources/org/threeten/bp/TZDB.dat b/src/main/resources/org/threeten/bp/TZDB.dat index e530c1bcc6de5d3785713bb1ef6140de79b9ded5..30d3a33c8627256d9f5d567cfeefa0bf1b90a49f 100644 GIT binary patch delta 4323 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 delta 4332 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 Cp1VT; From 63775a7614941089fa41755f267f69ae966df348 Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Mon, 25 Mar 2024 17:50:57 +0000 Subject: [PATCH 3/9] Prepare for release v1.6.9 --- src/changes/changes.xml | 5 +++++ src/site/markdown/index.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 8c67258c5..e0cec804e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -8,6 +8,11 @@ + + + Update to time-zone data 2024agtz. + + Update to time-zone data 2023cgtz. diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md index ecbfa8732..1ffc8b495 100644 --- a/src/site/markdown/index.md +++ b/src/site/markdown/index.md @@ -42,7 +42,7 @@ Various documentation is available: ## Releases -Release 1.6.8 is the latest release. +Release 1.6.9 is the latest release. It is considered to be stable and usable in production. The project runs on Java SE 6 (or later) and has no [dependencies](dependencies.html). From f4a423a346677bf7c3e6baca2a48d1af4b623baa Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Mon, 25 Mar 2024 17:56:55 +0000 Subject: [PATCH 4/9] Update maven --- pom.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index 8b8118da5..f283622f3 100644 --- a/pom.xml +++ b/pom.xml @@ -826,26 +826,26 @@ 3.2.0 3.10.1 3.0.0 - 3.3.0 + 3.4.0 3.1.0 3.0.1 - 3.0.1 - 3.2.2 - 3.4.0 - 3.2.0 - 3.6.4 - 3.17.0 - 3.4.0 + 3.1.0 + 3.3.0 + 3.4.1 + 3.3.0 + 3.7.0 + 3.19.0 + 3.4.1 2.5.3 2.4 3.3.0 - 3.12.0 + 3.12.1 3.2.1 3.0.0-M7 3.0.0-M7 3.1.0 - 1.307 + 1.314 1.4.0 1.6.13 1.2 From 7b1a168cae4b4cc5d8db648e1ab00b29c9fa9cba Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Mon, 25 Mar 2024 18:00:41 +0000 Subject: [PATCH 5/9] [maven-release-plugin] prepare release v1.6.9 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f283622f3..cdfeb54d2 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ threetenbp jar ThreeTen backport - 1.6.9-SNAPSHOT + 1.6.9 Backport of JSR-310 from JDK 8 to JDK 7 and JDK 6. NOT an implementation of the JSR. https://www.threeten.org/threetenbp @@ -123,7 +123,7 @@ scm:git:https://github.com/ThreeTen/threetenbp.git scm:git:https://github.com/ThreeTen/threetenbp.git https://github.com/ThreeTen/threetenbp - HEAD + v1.6.9 ThreeTen.org From 0cc27b92e1bffa5f0fca663ed0bbb89e06a9838d Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Mon, 25 Mar 2024 18:00:46 +0000 Subject: [PATCH 6/9] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index cdfeb54d2..a575303ce 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ threetenbp jar ThreeTen backport - 1.6.9 + 1.6.10-SNAPSHOT Backport of JSR-310 from JDK 8 to JDK 7 and JDK 6. NOT an implementation of the JSR. https://www.threeten.org/threetenbp @@ -123,7 +123,7 @@ scm:git:https://github.com/ThreeTen/threetenbp.git scm:git:https://github.com/ThreeTen/threetenbp.git https://github.com/ThreeTen/threetenbp - v1.6.9 + HEAD ThreeTen.org From adcdbc462b4e93e68e6f9c9a82217d0478b7d635 Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Tue, 16 Apr 2024 21:57:00 +0100 Subject: [PATCH 7/9] Add security/CVE page (#192) --- src/site/markdown/index.md | 1 + src/site/markdown/security.md | 37 +++++++++++++++++++++++++++++++++++ src/site/site.xml | 1 + 3 files changed, 39 insertions(+) create mode 100644 src/site/markdown/security.md diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md index 1ffc8b495..c250cedc8 100644 --- a/src/site/markdown/index.md +++ b/src/site/markdown/index.md @@ -35,6 +35,7 @@ Various documentation is available: * The [Javadoc](apidocs/index.html) * The [change notes](changes-report.html) for each release +* The [security](security.html) issues page * The [GitHub](https://github.com/ThreeTen/threetenbp) source repository * The mechanism to [update](update-tzdb.html) the time-zone information diff --git a/src/site/markdown/security.md b/src/site/markdown/security.md new file mode 100644 index 000000000..e9025d581 --- /dev/null +++ b/src/site/markdown/security.md @@ -0,0 +1,37 @@ +## Threeten-Backport Security + +### Security Policy + +**Supported Versions** + +If a security issue occurs, only the latest version is guaranteed to be patched. + +**Reporting a Vulnerability** + +To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). +Tidelift will coordinate the fix and disclosure. + + +### CVEs + +**[CVE-2024-23081](https://www.cve.org/CVERecord?id=CVE-2024-23081)** + +This was raised publicly on 2024-04-10. +There was no prior warning or private disclosure. + +The CVE is nonsense. It was raised by an AI-driven bot. +The CVE describes that a `NullPointerException` is thrown when `null` is passed into a method. +As any Java developer knows, this is perfectly normal and not a security issue or CVE. + +Users of ThreeTen-Backport do not need to take any action as the CVE is invalid. + +**[CVE-2024-23082](https://www.cve.org/CVERecord?id=CVE-2024-23082)** + +This was raised publicly on 2024-04-10. +There was no prior warning or private disclosure. + +The CVE is nonsense. It was raised by an AI-driven bot. +The CVE describes that a `StringIndexOutOfBoundsException` is thrown when a certain input is passed into a method. +As any Java developer knows, this is a perfectly normal exception and not a security issue or CVE. + +Users of ThreeTen-Backport do not need to take any action as the CVE is invalid. diff --git a/src/site/site.xml b/src/site/site.xml index 45c2dcadd..c1afbe7ef 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -75,6 +75,7 @@ + From 08dadbd27fca242e17942d921a0fbb3161c78da2 Mon Sep 17 00:00:00 2001 From: Stanislav Spiridonov Date: Sat, 18 May 2024 10:28:27 +0200 Subject: [PATCH 8/9] Java9 synch (#15) * Add Java 9 methods * Update Github actions --------- Co-authored-by: Stanislav Spiridonov --- .github/workflows/BuildSnapshot.yml | 16 +- .github/workflows/Release.yml | 6 +- .github/workflows/UpdateDependencies.yml | 16 +- .gitignore | 3 + .../threetenbp/gwt/emu/java/time/Clock.java | 42 +- .../gwt/emu/java/time/DayOfWeek.java | 11 +- .../gwt/emu/java/time/Duration.java | 72 +- .../threetenbp/gwt/emu/java/time/Instant.java | 8 +- .../gwt/emu/java/time/LocalDate.java | 100 +- .../gwt/emu/java/time/LocalDateTime.java | 2 + .../gwt/emu/java/time/LocalTime.java | 93 +- .../gwt/emu/java/time/MonthDay.java | 1 + .../gwt/emu/java/time/OffsetDateTime.java | 26 +- .../gwt/emu/java/time/OffsetTime.java | 7 + .../threetenbp/gwt/emu/java/time/Year.java | 1 + .../gwt/emu/java/time/YearMonth.java | 2 +- .../gwt/emu/java/time/ZoneOffset.java | 2 +- .../gwt/emu/java/time/ZonedDateTime.java | 5 +- .../emu/java/time/chrono/ChronoDateImpl.java | 8 +- .../gwt/emu/java/time/chrono/Chronology.java | 28 + .../gwt/emu/java/time/chrono/Era.java | 2 +- .../emu/java/time/chrono/IsoChronology.java | 995 +++++++++--------- .../emu/java/time/format/DecimalStyle.java | 2 +- 23 files changed, 850 insertions(+), 598 deletions(-) diff --git a/.github/workflows/BuildSnapshot.yml b/.github/workflows/BuildSnapshot.yml index 55c08d19e..c63ce1d8b 100644 --- a/.github/workflows/BuildSnapshot.yml +++ b/.github/workflows/BuildSnapshot.yml @@ -12,14 +12,14 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'zulu' cache: maven - - uses: s4u/maven-settings-action@v2.7.0 + - uses: s4u/maven-settings-action@v3.0.0 with: sonatypeSnapshots: true apacheSnapshots: true @@ -45,23 +45,23 @@ jobs: name: Run Sonar analysis runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: # Shallow clones should be disabled for a better relevancy of analysis fetch-depth: 0 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: - java-version: '11' + java-version: '17' distribution: 'zulu' cache: maven - name: Cache SonarCloud packages - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - - uses: s4u/maven-settings-action@v2.7.0 + - uses: s4u/maven-settings-action@v3.0.0 with: sonatypeSnapshots: true apacheSnapshots: true diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index 3aeceb448..f0f530df7 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -9,16 +9,16 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'zulu' cache: maven gpg-private-key: ${{ secrets.GPG_KEY }} - name: maven-settings-xml-action - uses: whelk-io/maven-settings-xml-action@v21 + uses: whelk-io/maven-settings-xml-action@v22 with: repositories: | [ diff --git a/.github/workflows/UpdateDependencies.yml b/.github/workflows/UpdateDependencies.yml index 68a1ade2a..5d4a38a82 100644 --- a/.github/workflows/UpdateDependencies.yml +++ b/.github/workflows/UpdateDependencies.yml @@ -9,16 +9,16 @@ jobs: updateGWT28: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: 'master' - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'zulu' cache: maven - - uses: s4u/maven-settings-action@v2.7.0 + - uses: s4u/maven-settings-action@v3.0.0 with: sonatypeSnapshots: true apacheSnapshots: true @@ -32,7 +32,7 @@ jobs: run: mvn -B versions:resolve-ranges versions:update-properties -Dincludes=com.jresearchsoft*:*,org.jresearch*:* -DallowSnapshots --builder singlethreaded working-directory: pom - name: Create Pull Request - uses: peter-evans/create-pull-request@v4 + uses: peter-evans/create-pull-request@v6 with: branch: gwt28/dep-update commit-message: Update shapshot dependencies @@ -41,16 +41,16 @@ jobs: updateGWT29: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: 'GWT29' - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: '11' distribution: 'zulu' cache: maven - - uses: s4u/maven-settings-action@v2.7.0 + - uses: s4u/maven-settings-action@v3.0.0 with: sonatypeSnapshots: true apacheSnapshots: true @@ -64,7 +64,7 @@ jobs: run: mvn -B versions:resolve-ranges versions:update-properties -Dincludes=com.jresearchsoft*:*,org.jresearch*:* -DallowSnapshots --builder singlethreaded working-directory: pom - name: Create Pull Request - uses: peter-evans/create-pull-request@v4 + uses: peter-evans/create-pull-request@v6 with: branch: gwt29/dep-update commit-message: Update shapshot dependencies diff --git a/.gitignore b/.gitignore index e54913742..18043e6b1 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,6 @@ **/TempTest.java /.idea/ /threetenbp.iml +time/gwt-unitCache/* +time/war/* +time/www-test/* diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Clock.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Clock.java index 7951e23ca..e168e99ab 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Clock.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Clock.java @@ -31,16 +31,9 @@ */ package org.jresearch.threetenbp.gwt.emu.java.time; -import static org.jresearch.threetenbp.gwt.emu.java.time.LocalTime.NANOS_PER_MINUTE; -import static org.jresearch.threetenbp.gwt.emu.java.time.LocalTime.NANOS_PER_SECOND; +import static org.jresearch.threetenbp.gwt.emu.java.time.LocalTime.*; import java.io.Serializable; -import org.jresearch.threetenbp.gwt.emu.java.time.Clock; -import org.jresearch.threetenbp.gwt.emu.java.time.DateTimeException; -import org.jresearch.threetenbp.gwt.emu.java.time.Duration; -import org.jresearch.threetenbp.gwt.emu.java.time.Instant; -import org.jresearch.threetenbp.gwt.emu.java.time.ZoneId; -import org.jresearch.threetenbp.gwt.emu.java.time.ZoneOffset; import java.util.Objects; import java.util.TimeZone; @@ -116,7 +109,7 @@ public abstract class Clock { * @return a clock that uses the best available system clock in the UTC zone, not null */ public static Clock systemUTC() { - return new SystemClock(ZoneOffset.UTC); + return SystemClock.CLOCK_UTC; } /** @@ -159,9 +152,19 @@ public static Clock systemDefaultZone() { */ public static Clock system(ZoneId zone) { Objects.requireNonNull(zone, "zone"); + if (zone == ZoneOffset.UTC) { + return SystemClock.CLOCK_UTC; + } return new SystemClock(zone); } + //------------------------------------------------------------------------- + /** + * @since 9 + */ + public static Clock tickMillis(ZoneId zone) { + return new TickClock(system(zone), NANOS_PER_MILLI); + } //------------------------------------------------------------------------- /** * Obtains a clock that returns the current instant ticking in whole seconds @@ -403,6 +406,7 @@ public int hashCode() { */ static final class SystemClock extends Clock implements Serializable { private static final long serialVersionUID = 6740630888130243051L; + static final SystemClock CLOCK_UTC = new SystemClock(ZoneOffset.UTC); private final ZoneId zone; SystemClock(ZoneId zone) { @@ -414,8 +418,8 @@ public ZoneId getZone() { } @Override public Clock withZone(ZoneId zone) { - //GWT specific - Objects.requireNonNull(zone); + //GWT specific + Objects.requireNonNull(zone); if (zone.equals(this.zone)) { // intentional NPE return this; } @@ -452,7 +456,7 @@ public String toString() { * This is typically used for testing. */ static final class FixedClock extends Clock implements Serializable { - private static final long serialVersionUID = 7430389292664866958L; + private static final long serialVersionUID = 7430389292664866958L; private final Instant instant; private final ZoneId zone; @@ -466,8 +470,8 @@ public ZoneId getZone() { } @Override public Clock withZone(ZoneId zone) { - //GWT specific - Objects.requireNonNull(zone); + //GWT specific + Objects.requireNonNull(zone); if (zone.equals(this.zone)) { // intentional NPE return this; } @@ -504,7 +508,7 @@ public String toString() { * Implementation of a clock that adds an offset to an underlying clock. */ static final class OffsetClock extends Clock implements Serializable { - private static final long serialVersionUID = 2007484719125426256L; + private static final long serialVersionUID = 2007484719125426256L; private final Clock baseClock; private final Duration offset; @@ -518,8 +522,8 @@ public ZoneId getZone() { } @Override public Clock withZone(ZoneId zone) { - //GWT specific - Objects.requireNonNull(zone); + //GWT specific + Objects.requireNonNull(zone); if (zone.equals(baseClock.getZone())) { // intentional NPE return this; } @@ -570,8 +574,8 @@ public ZoneId getZone() { } @Override public Clock withZone(ZoneId zone) { - //GWT specific - Objects.requireNonNull(zone); + //GWT specific + Objects.requireNonNull(zone); if (zone.equals(baseClock.getZone())) { // intentional NPE return this; } diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/DayOfWeek.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/DayOfWeek.java index cf3439ddb..70234011d 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/DayOfWeek.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/DayOfWeek.java @@ -237,7 +237,7 @@ public boolean isSupported(TemporalField field) { *

* If the field is {@link ChronoField#DAY_OF_WEEK DAY_OF_WEEK} then the * range of the day-of-week, from 1 to 7, will be returned. - * All other {@code ChronoField} instances will throw a {@code DateTimeException}. + * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}. *

* If the field is not a {@code ChronoField}, then the result of this method * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)} @@ -247,6 +247,7 @@ public boolean isSupported(TemporalField field) { * @param field the field to query the range for, not null * @return the range of valid values for the field, not null * @throws DateTimeException if the range for the field cannot be obtained + * @throws UnsupportedTemporalTypeException if the type of field is not supported (since 9) */ @Override public ValueRange range(TemporalField field) { @@ -266,7 +267,7 @@ public ValueRange range(TemporalField field) { *

* If the field is {@link ChronoField#DAY_OF_WEEK DAY_OF_WEEK} then the * value of the day-of-week, from 1 to 7, will be returned. - * All other {@code ChronoField} instances will throw a {@code DateTimeException}. + * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}. *

* If the field is not a {@code ChronoField}, then the result of this method * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} @@ -276,8 +277,9 @@ public ValueRange range(TemporalField field) { * @param field the field to get, not null * @return the value for the field, within the valid range of values * @throws DateTimeException if a value for the field cannot be obtained - * @throws DateTimeException if the range of valid values for the field exceeds an {@code int} * @throws DateTimeException if the value is outside the range of valid values for the field + * @throws UnsupportedTemporalTypeException if the type of field is not supported or + * the range of values exceeds an {@code int} (since 9) * @throws ArithmeticException if numeric overflow occurs */ @Override @@ -297,7 +299,7 @@ public int get(TemporalField field) { *

* If the field is {@link ChronoField#DAY_OF_WEEK DAY_OF_WEEK} then the * value of the day-of-week, from 1 to 7, will be returned. - * All other {@code ChronoField} instances will throw a {@code DateTimeException}. + * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}. *

* If the field is not a {@code ChronoField}, then the result of this method * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} @@ -307,6 +309,7 @@ public int get(TemporalField field) { * @param field the field to get, not null * @return the value for the field * @throws DateTimeException if a value for the field cannot be obtained + * @throws UnsupportedTemporalTypeException if the type of field is not supported (since 9) * @throws ArithmeticException if numeric overflow occurs */ @Override diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Duration.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Duration.java index 237c9966c..7bcca85bb 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Duration.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Duration.java @@ -31,18 +31,19 @@ */ package org.jresearch.threetenbp.gwt.emu.java.time; -import static org.jresearch.threetenbp.gwt.emu.java.time.LocalTime.SECONDS_PER_DAY; -import static org.jresearch.threetenbp.gwt.emu.java.time.LocalTime.SECONDS_PER_HOUR; -import static org.jresearch.threetenbp.gwt.emu.java.time.LocalTime.SECONDS_PER_MINUTE; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.NANO_OF_SECOND; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoUnit.DAYS; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoUnit.NANOS; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoUnit.SECONDS; +import static org.jresearch.threetenbp.gwt.emu.java.time.LocalTime.*; +import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.*; +import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoUnit.*; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + import org.jresearch.threetenbp.gwt.emu.java.time.format.DateTimeParseException; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoUnit; @@ -50,10 +51,6 @@ import org.jresearch.threetenbp.gwt.emu.java.time.temporal.TemporalAmount; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.TemporalUnit; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.UnsupportedTemporalTypeException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Objects; import com.google.gwt.regexp.shared.MatchResult; import com.google.gwt.regexp.shared.RegExp; @@ -139,7 +136,7 @@ public final class Duration * @throws ArithmeticException if the input days exceeds the capacity of {@code Duration} */ public static Duration ofDays(long days) { - return create(Math.multiplyExact(days, 86400), 0); + return create(Math.multiplyExact(days, SECONDS_PER_DAY), 0); } /** @@ -154,7 +151,7 @@ public static Duration ofDays(long days) { * @throws ArithmeticException if the input hours exceeds the capacity of {@code Duration} */ public static Duration ofHours(long hours) { - return create(Math.multiplyExact(hours, 3600), 0); + return create(Math.multiplyExact(hours, SECONDS_PER_HOUR), 0); } /** @@ -169,7 +166,7 @@ public static Duration ofHours(long hours) { * @throws ArithmeticException if the input minutes exceeds the capacity of {@code Duration} */ public static Duration ofMinutes(long minutes) { - return create(Math.multiplyExact(minutes, 60), 0); + return create(Math.multiplyExact(minutes, SECONDS_PER_MINUTE), 0); } //----------------------------------------------------------------------- @@ -626,6 +623,7 @@ public Duration plus(Duration duration) { * @param amountToAdd the amount of the period, measured in terms of the unit, positive or negative * @param unit the unit that the period is measured in, must have an exact duration, not null * @return a {@code Duration} based on this duration with the specified duration added, not null + * @throws UnsupportedTemporalTypeException if the type of unit is not supported * @throws ArithmeticException if numeric overflow occurs */ public Duration plus(long amountToAdd, TemporalUnit unit) { @@ -634,7 +632,7 @@ public Duration plus(long amountToAdd, TemporalUnit unit) { return plus(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY), 0); } if (unit.isDurationEstimated()) { - throw new DateTimeException("Unit must not have an estimated duration"); + throw new UnsupportedTemporalTypeException("Unit must not have an estimated duration"); } if (amountToAdd == 0) { return this; @@ -886,7 +884,7 @@ public Duration multipliedBy(long multiplicand) { if (multiplicand == 1) { return this; } - return create(toSeconds().multiply(BigDecimal.valueOf(multiplicand))); + return create(toIntSeconds().multiply(BigDecimal.valueOf(multiplicand))); } /** @@ -906,16 +904,23 @@ public Duration dividedBy(long divisor) { if (divisor == 1) { return this; } - return create(toSeconds().divide(BigDecimal.valueOf(divisor), RoundingMode.DOWN)); + return create(toIntSeconds().divide(BigDecimal.valueOf(divisor), RoundingMode.DOWN)); } + /** + * @since 9 + */ + public long dividedBy(Duration divisor) { + Objects.requireNonNull(divisor, "divisor"); + return toIntSeconds().divideToIntegralValue(divisor.toIntSeconds()).longValueExact(); + } /** * Converts this duration to the total length in seconds and * fractional nanoseconds expressed as a {@code BigDecimal}. * * @return the total length of the duration in seconds, with a scale of 9, not null */ - private BigDecimal toSeconds() { + private BigDecimal toIntSeconds() { return BigDecimal.valueOf(seconds).add(BigDecimal.valueOf(nanos, 9)); } @@ -1079,12 +1084,18 @@ public long toHours() { *

* This instance is immutable and unaffected by this method call. * - * @return the number of minutes in the duration, may be negative + * */ public long toMinutes() { return seconds / SECONDS_PER_MINUTE; } + /** + * @since 9 + */ + public long toSeconds() { + return seconds; + } /** * Converts this duration to the total length in milliseconds. *

@@ -1213,6 +1224,29 @@ public int toNanosPart() { return nanos; } + //----------------------------------------------------------------------- + /** + * @since 9 + */ + public Duration truncatedTo(TemporalUnit unit) { + Objects.requireNonNull(unit, "unit"); + if (unit == ChronoUnit.NANOS) { + return this; + } else if (unit == ChronoUnit.SECONDS && (seconds >= 0 || nanos == 0)) { + return new Duration(seconds, 0); + } + Duration unitDuration = unit.getDuration(); + if (unitDuration.getSeconds() > LocalTime.SECONDS_PER_DAY) { + throw new UnsupportedTemporalTypeException("Unit is too large"); + } + long unitNanos = unitDuration.toNanos(); + if ((LocalTime.NANOS_PER_DAY % unitNanos) != 0) { + throw new UnsupportedTemporalTypeException("Can't divide unit into a standard day without remainder"); + } + long dayNanos = (seconds % LocalTime.SECONDS_PER_DAY) * LocalTime.NANOS_PER_SECOND + nanos; + long result = (dayNanos / unitNanos) * unitNanos ; + return plusNanos(result - dayNanos); + } //----------------------------------------------------------------------- /** * Compares this duration to the specified {@code Duration}. diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Instant.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Instant.java index 74d7f2f0d..e2bb7e4cb 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Instant.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Instant.java @@ -328,6 +328,10 @@ public static Instant ofEpochMilli(long epochMilli) { * @throws DateTimeException if unable to convert to an {@code Instant} */ public static Instant from(TemporalAccessor temporal) { + if (temporal instanceof Instant) { + return (Instant) temporal; + } + Objects.requireNonNull(temporal, "temporal"); try { long instantSecs = temporal.getLong(INSTANT_SECONDS); int nanoOfSecond = temporal.get(NANO_OF_SECOND); @@ -675,11 +679,11 @@ public Instant truncatedTo(TemporalUnit unit) { } Duration unitDur = unit.getDuration(); if (unitDur.getSeconds() > LocalTime.SECONDS_PER_DAY) { - throw new DateTimeException("Unit is too large to be used for truncation"); + throw new UnsupportedTemporalTypeException("Unit is too large to be used for truncation"); } long dur = unitDur.toNanos(); if ((LocalTime.NANOS_PER_DAY % dur) != 0) { - throw new DateTimeException("Unit must divide into a standard day without remainder"); + throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder"); } long nod = (seconds % LocalTime.SECONDS_PER_DAY) * LocalTime.NANOS_PER_SECOND + nanos; long result = Math.floorDiv(nod, dur) * dur; diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/LocalDate.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/LocalDate.java index 6ff22a74a..773acf671 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/LocalDate.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/LocalDate.java @@ -66,6 +66,8 @@ import org.jresearch.threetenbp.gwt.emu.java.time.zone.ZoneOffsetTransition; import org.jresearch.threetenbp.gwt.emu.java.time.zone.ZoneRules; import java.util.Objects; +import java.util.stream.LongStream; +import java.util.stream.Stream; /** * A date without a time-zone in the ISO-8601 calendar system, @@ -117,7 +119,7 @@ public final class LocalDate * There are five 400 year cycles from year zero to 2000. * There are 7 leap years from 1970 to 2000. */ - static final long DAYS_0000_TO_1970 = (DAYS_PER_CYCLE * 5L) - (30L * 365L + 7L); + public static final long DAYS_0000_TO_1970 = (DAYS_PER_CYCLE * 5L) - (30L * 365L + 7L); /** * The year. @@ -177,10 +179,7 @@ public static LocalDate now(ZoneId zone) { public static LocalDate now(Clock clock) { Objects.requireNonNull(clock, "clock"); final Instant now = clock.instant(); // called once - ZoneOffset offset = clock.getZone().getRules().getOffset(now); - long epochSec = now.getEpochSecond() + offset.getTotalSeconds(); // overflow caught later - long epochDay = Math.floorDiv(epochSec, SECONDS_PER_DAY); - return LocalDate.ofEpochDay(epochDay); + return ofInstant(now, clock.getZone()); } //----------------------------------------------------------------------- @@ -250,6 +249,18 @@ public static LocalDate ofYearDay(int year, int dayOfYear) { return create(year, moy, dom); } + //----------------------------------------------------------------------- + /** + * @since 9 + */ + public static LocalDate ofInstant(Instant instant, ZoneId zone) { + Objects.requireNonNull(instant, "instant"); + Objects.requireNonNull(zone, "zone"); + ZoneOffset offset = zone.getRules().getOffset(instant); + long epochSec = instant.getEpochSecond() + offset.getTotalSeconds(); // overflow caught later + long epochDay = Math.floorDiv(epochSec, SECONDS_PER_DAY); + return LocalDate.ofEpochDay(epochDay); + } //----------------------------------------------------------------------- /** * Obtains an instance of {@code LocalDate} from the epoch day count. @@ -573,11 +584,11 @@ private int get0(TemporalField field) { case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1; case DAY_OF_MONTH: return day; case DAY_OF_YEAR: return getDayOfYear(); - case EPOCH_DAY: throw new DateTimeException("Field too large for an int: " + field); + case EPOCH_DAY: throw new UnsupportedTemporalTypeException("Field too large for an int: " + field); case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1; case ALIGNED_WEEK_OF_YEAR: return ((getDayOfYear() - 1) / 7) + 1; case MONTH_OF_YEAR: return month; - case PROLEPTIC_MONTH: throw new DateTimeException("Field too large for an int: " + field); + case PROLEPTIC_MONTH: throw new UnsupportedTemporalTypeException("Field too large for an int: " + field); case YEAR_OF_ERA: return (year >= 1 ? year : 1 - year); case YEAR: return year; case ERA: return (year >= 1 ? 1 : 0); @@ -1500,6 +1511,71 @@ public Period until(ChronoLocalDate endDate) { return Period.of(Math.toIntExact(years), months, days); } + /** + * @since 9 + */ + public Stream datesUntil(LocalDate endExclusive) { + long end = endExclusive.toEpochDay(); + long start = toEpochDay(); + if (end < start) { + throw new IllegalArgumentException("Given date " + endExclusive + "is before current"); + } + return LongStream.range(start, end).mapToObj(LocalDate::ofEpochDay); + } + /** + * @since 9 + */ + public Stream datesUntil(LocalDate endExclusive, Period step) { + if (step.isZero()) { + throw new IllegalArgumentException("step is zero"); + } + long end = endExclusive.toEpochDay(); + long start = toEpochDay(); + long until = end - start; + if (until == 0) { + return Stream.empty(); + } + long months = step.toTotalMonths(); + long days = step.getDays(); + if ((months < 0 && days > 0) || (months > 0 && days < 0)) { + throw new IllegalArgumentException("period months and days are of opposite sign"); + } + int sign = months > 0 || days > 0 ? 1 : -1; + if (sign < 0 ^ until < 0) { + throw new IllegalArgumentException(endExclusive + (sign < 0 ? " > " : " < ") + this); + } + if (months == 0) { + //Calculate from days only + long steps = (until - sign) / days; + return LongStream.rangeClosed(0, steps) + .mapToObj(n -> LocalDate.ofEpochDay(start + n * days)); + } + long steps = countSteps(end, until, months, days, sign); + return LongStream.rangeClosed(0, steps) + .mapToObj(n -> this.plusMonths(months * n).plusDays(days * n)); + } + + private long countSteps(long end, long daysUntilEnd, long monthsPart, long daysPart, int sign) { + // 1600 and 48699 is used to calculate days per month 365.2425/12 is the same as 48699/1600 + long steps = daysUntilEnd * 1600 / (monthsPart * 48699 + daysPart * 1600) + 1; + long addMonths = monthsPart * steps; + long addDays = daysPart * steps; + long maxAddMonths = sign > 0 + ? MAX.getProlepticMonth() - getProlepticMonth() + : getProlepticMonth() - MIN.getProlepticMonth(); + // adjust steps estimation + if (addMonths * sign > maxAddMonths + || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) { + steps--; + addMonths -= monthsPart; + addDays -= daysPart; + if (addMonths * sign > maxAddMonths + || (plusMonths(addMonths).toEpochDay() + addDays) * sign >= end * sign) { + steps--; + } + } + return steps; + } //----------------------------------------------------------------------- /** * Combines this date with a time to create a {@code LocalDateTime}. @@ -1659,6 +1735,16 @@ public long toEpochDay() { return total - DAYS_0000_TO_1970; } + /** + * @since 9 + */ + public long toEpochSecond(LocalTime time, ZoneOffset offset) { + Objects.requireNonNull(time, "time"); + Objects.requireNonNull(offset, "offset"); + long secs = toEpochDay() * SECONDS_PER_DAY + time.toSecondOfDay(); + secs -= offset.getTotalSeconds(); + return secs; + } //----------------------------------------------------------------------- /** * Compares this date to another date. diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/LocalDateTime.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/LocalDateTime.java index 3237ea975..2e44960ce 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/LocalDateTime.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/LocalDateTime.java @@ -387,6 +387,8 @@ public static LocalDateTime from(TemporalAccessor temporal) { return (LocalDateTime) temporal; } else if (temporal instanceof ZonedDateTime) { return ((ZonedDateTime) temporal).toLocalDateTime(); + } else if (temporal instanceof OffsetDateTime) { + return ((OffsetDateTime) temporal).toLocalDateTime(); } try { LocalDate date = LocalDate.from(temporal); diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/LocalTime.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/LocalTime.java index 8544d8986..c0ee7d0c0 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/LocalTime.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/LocalTime.java @@ -145,6 +145,10 @@ public final class LocalTime * Microseconds per day. */ static final long MICROS_PER_DAY = SECONDS_PER_DAY * 1000_000L; + /** + * Nanos per millisecond. + */ + static final long NANOS_PER_MILLI = 1000_000L; /** * Nanos per second. */ @@ -229,13 +233,7 @@ public static LocalTime now(ZoneId zone) { public static LocalTime now(Clock clock) { Objects.requireNonNull(clock, "clock"); final Instant now = clock.instant(); // called once - ZoneOffset offset = clock.getZone().getRules().getOffset(now); - long secsOfDay = now.getEpochSecond() % SECONDS_PER_DAY; - secsOfDay = (secsOfDay + offset.getTotalSeconds()) % SECONDS_PER_DAY; - if (secsOfDay < 0) { - secsOfDay += SECONDS_PER_DAY; - } - return LocalTime.ofSecondOfDay(secsOfDay, now.getNano()); + return ofInstant(now, clock.getZone()); } //------------------------get----------------------------------------------- @@ -303,6 +301,21 @@ public static LocalTime of(int hour, int minute, int second, int nanoOfSecond) { return create(hour, minute, second, nanoOfSecond); } + /** + * @since 9 + */ + public static LocalTime ofInstant(Instant instant, ZoneId zone) { + Objects.requireNonNull(instant, "instant"); + Objects.requireNonNull(zone, "zone"); + + ZoneOffset offset = zone.getRules().getOffset(instant); + long secsOfDay = instant.getEpochSecond() % SECONDS_PER_DAY; + secsOfDay = (secsOfDay + offset.getTotalSeconds()) % SECONDS_PER_DAY; + if (secsOfDay < 0) { + secsOfDay += SECONDS_PER_DAY; + } + return LocalTime.ofSecondOfDay(secsOfDay, instant.getNano()); + } //----------------------------------------------------------------------- /** * Obtains an instance of {@code LocalTime} from a second-of-day value. @@ -381,8 +394,8 @@ public static LocalTime ofNanoOfDay(long nanoOfDay) { * @throws DateTimeException if unable to convert to a {@code LocalTime} */ public static LocalTime from(TemporalAccessor temporal) { - //GWT specific - Objects.requireNonNull(temporal); + //GWT specific + Objects.requireNonNull(temporal); LocalTime time = temporal.query(TemporalQueries.localTime()); if (time == null) { throw new DateTimeException("Unable to obtain LocalTime from TemporalAccessor: " + @@ -561,8 +574,8 @@ public ValueRange range(TemporalField field) { */ @Override // override for Javadoc and performance public int get(TemporalField field) { - //GWT specific - Objects.requireNonNull(field); + //GWT specific + Objects.requireNonNull(field); if (field instanceof ChronoField) { return get0(field); } @@ -593,8 +606,8 @@ public int get(TemporalField field) { */ @Override public long getLong(TemporalField field) { - //GWT Specific - Objects.requireNonNull(field, "field"); + //GWT Specific + Objects.requireNonNull(field, "field"); if (field instanceof ChronoField) { if (field == NANO_OF_DAY) { return toNanoOfDay(); @@ -608,13 +621,13 @@ public long getLong(TemporalField field) { } private int get0(TemporalField field) { - //GWT specific - Objects.requireNonNull(field); + //GWT specific + Objects.requireNonNull(field); switch ((ChronoField) field) { case NANO_OF_SECOND: return nano; - case NANO_OF_DAY: throw new DateTimeException("Field too large for an int: " + field); + case NANO_OF_DAY: throw new UnsupportedTemporalTypeException("Field too large for an int: " + field); case MICRO_OF_SECOND: return nano / 1000; - case MICRO_OF_DAY: throw new DateTimeException("Field too large for an int: " + field); + case MICRO_OF_DAY: throw new UnsupportedTemporalTypeException("Field too large for an int: " + field); case MILLI_OF_SECOND: return nano / 1000_000; case MILLI_OF_DAY: return (int) (toNanoOfDay() / 1000_000); case SECOND_OF_MINUTE: return second; @@ -691,8 +704,8 @@ public int getNano() { */ @Override public LocalTime with(TemporalAdjuster adjuster) { - //GWT specific - Objects.requireNonNull(adjuster); + //GWT specific + Objects.requireNonNull(adjuster); // optimizations if (adjuster instanceof LocalTime) { return (LocalTime) adjuster; @@ -898,18 +911,18 @@ public LocalTime withNano(int nanoOfSecond) { * @throws DateTimeException if unable to truncate */ public LocalTime truncatedTo(TemporalUnit unit) { - //GWT specific - Objects.requireNonNull(unit); + //GWT specific + Objects.requireNonNull(unit); if (unit == ChronoUnit.NANOS) { return this; } Duration unitDur = unit.getDuration(); if (unitDur.getSeconds() > SECONDS_PER_DAY) { - throw new DateTimeException("Unit is too large to be used for truncation"); + throw new UnsupportedTemporalTypeException("Unit is too large to be used for truncation"); } long dur = unitDur.toNanos(); if ((NANOS_PER_DAY % dur) != 0) { - throw new DateTimeException("Unit must divide into a standard day without remainder"); + throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder"); } long nod = toNanoOfDay(); return ofNanoOfDay((nod / dur) * dur); @@ -934,8 +947,8 @@ public LocalTime truncatedTo(TemporalUnit unit) { */ @Override public LocalTime plus(TemporalAmount amount) { - //GWT specific - Objects.requireNonNull(amount); + //GWT specific + Objects.requireNonNull(amount); return (LocalTime) amount.addTo(this); } @@ -956,8 +969,8 @@ public LocalTime plus(TemporalAmount amount) { */ @Override public LocalTime plus(long amountToAdd, TemporalUnit unit) { - //GWT specific - Objects.requireNonNull(unit); + //GWT specific + Objects.requireNonNull(unit); if (unit instanceof ChronoUnit) { ChronoUnit f = (ChronoUnit) unit; switch (f) { @@ -1092,8 +1105,8 @@ public LocalTime plusNanos(long nanosToAdd) { */ @Override public LocalTime minus(TemporalAmount amount) { - //GWT specific - Objects.requireNonNull(amount); + //GWT specific + Objects.requireNonNull(amount); return (LocalTime) amount.subtractFrom(this); } @@ -1114,8 +1127,8 @@ public LocalTime minus(TemporalAmount amount) { */ @Override public LocalTime minus(long amountToSubtract, TemporalUnit unit) { - //GWT specific - Objects.requireNonNull(unit); + //GWT specific + Objects.requireNonNull(unit); return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit)); } @@ -1202,8 +1215,8 @@ public LocalTime minusNanos(long nanosToSubtract) { @SuppressWarnings("unchecked") @Override public R query(TemporalQuery query) { - //GWT specific - Objects.requireNonNull(query); + //GWT specific + Objects.requireNonNull(query); if (query == TemporalQueries.precision()) { return (R) NANOS; } else if (query == TemporalQueries.localTime()) { @@ -1364,6 +1377,14 @@ public long toNanoOfDay() { return total; } + /** + * @since 9 + */ + public long toEpochSecond(LocalDate date, ZoneOffset offset) { + Objects.requireNonNull(date); + Objects.requireNonNull(offset); + return date.toEpochDay() * 86400 + toSecondOfDay() - offset.getTotalSeconds(); + } //----------------------------------------------------------------------- /** * Compares this {@code LocalTime} to another time. @@ -1377,8 +1398,8 @@ public long toNanoOfDay() { */ @Override public int compareTo(LocalTime other) { - //GWT specific - Objects.requireNonNull(other); + //GWT specific + Objects.requireNonNull(other); int cmp = Integer.compare(hour, other.hour); if (cmp == 0) { cmp = Integer.compare(minute, other.minute); @@ -1512,4 +1533,4 @@ public String format(DateTimeFormatter formatter) { return formatter.format(this); } -} \ No newline at end of file +} diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/MonthDay.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/MonthDay.java index b4e4d4cba..882a827b1 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/MonthDay.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/MonthDay.java @@ -616,6 +616,7 @@ public LocalDate atYear(int year) { * @param other the other month-day to compare to, not null * @return the comparator value, negative if less, positive if greater */ + @Override public int compareTo(MonthDay other) { //GWT specific Objects.requireNonNull(other); diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/OffsetDateTime.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/OffsetDateTime.java index d556eeb80..279ae0c75 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/OffsetDateTime.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/OffsetDateTime.java @@ -52,6 +52,7 @@ import org.jresearch.threetenbp.gwt.emu.java.time.temporal.TemporalQueries; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.TemporalQuery; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.TemporalUnit; +import org.jresearch.threetenbp.gwt.emu.java.time.temporal.UnsupportedTemporalTypeException; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.ValueRange; import org.jresearch.threetenbp.gwt.emu.java.time.zone.ZoneRules; import java.util.Comparator; @@ -125,7 +126,9 @@ private static int compareInstant(OffsetDateTime datetime1, OffsetDateTime datet } int cmp = Long.compare(datetime1.toEpochSecond(), datetime2.toEpochSecond()); if (cmp == 0) { - cmp = Long.compare(datetime1.getNano(), datetime2.getNano()); + //GWT specific + //Avoid long comparation due to JS. Here is enought nano from time + cmp = datetime1.toLocalTime().getNano() - datetime2.toLocalTime().getNano(); } return cmp; } @@ -302,14 +305,17 @@ public static OffsetDateTime from(TemporalAccessor temporal) { return (OffsetDateTime) temporal; } try { - ZoneOffset offset = ZoneOffset.from(temporal); - try { - LocalDateTime ldt = LocalDateTime.from(temporal); - return OffsetDateTime.of(ldt, offset); - } catch (DateTimeException ignore) { - Instant instant = Instant.from(temporal); - return OffsetDateTime.ofInstant(instant, offset); - } + ZoneOffset offset = ZoneOffset.from(temporal); + // GWT specific - avoid exception driven logic + LocalDate localDate = temporal.query(TemporalQueries.localDate()); + if (localDate != null) { + LocalTime localTime = temporal.query(TemporalQueries.localTime()); + if (localTime != null) { + return OffsetDateTime.of(localDate, localTime, offset); + } + } + Instant instant = Instant.from(temporal); + return OffsetDateTime.ofInstant(instant, offset); } catch (DateTimeException ex) { throw new DateTimeException("Unable to obtain OffsetDateTime from TemporalAccessor: " + temporal + ", type " + temporal.getClass().getName()); @@ -503,7 +509,7 @@ public int get(TemporalField field) { Objects.requireNonNull(field); if (field instanceof ChronoField) { switch ((ChronoField) field) { - case INSTANT_SECONDS: throw new DateTimeException("Field too large for an int: " + field); + case INSTANT_SECONDS: throw new UnsupportedTemporalTypeException("Field too large for an int: " + field); case OFFSET_SECONDS: return getOffset().getTotalSeconds(); } return dateTime.get(field); diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/OffsetTime.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/OffsetTime.java index 4264e367b..4643533c7 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/OffsetTime.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/OffsetTime.java @@ -1128,6 +1128,13 @@ private long toEpochNano() { return nod - offsetNanos; } + /** + * @since 9 + */ + public long toEpochSecond(LocalDate date) { + Objects.requireNonNull(date); + return date.toEpochDay() * 86400 + time.toSecondOfDay() - offset.getTotalSeconds(); + } //----------------------------------------------------------------------- /** * Compares this {@code OffsetTime} to another time. diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Year.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Year.java index b536207c2..ea8e7f114 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Year.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/Year.java @@ -862,6 +862,7 @@ public LocalDate atMonthDay(MonthDay monthDay) { * @param other the other year to compare to, not null * @return the comparator value, negative if less, positive if greater */ + @Override public int compareTo(Year other) { //GWT specific Objects.requireNonNull(other); diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/YearMonth.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/YearMonth.java index ab3b15f30..4a5bafc3b 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/YearMonth.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/YearMonth.java @@ -616,7 +616,7 @@ public YearMonth with(TemporalField field, long newValue) { f.checkValidValue(newValue); switch (f) { case MONTH_OF_YEAR: return withMonth((int) newValue); - case PROLEPTIC_MONTH: return plusMonths(newValue - getLong(PROLEPTIC_MONTH)); + case PROLEPTIC_MONTH: return plusMonths(newValue - getProlepticMonth()); case YEAR_OF_ERA: return withYear((int) (year < 1 ? 1 - newValue : newValue)); case YEAR: return withYear((int) newValue); case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year)); diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/ZoneOffset.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/ZoneOffset.java index 7c1a0df65..50fb11bac 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/ZoneOffset.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/ZoneOffset.java @@ -581,7 +581,7 @@ public long getLong(TemporalField field) { if (field == OFFSET_SECONDS) { return totalSeconds; } else if (field instanceof ChronoField) { - throw new DateTimeException("Unsupported field: " + field); + throw new UnsupportedTemporalTypeException("Unsupported field: " + field); } return field.getFrom(this); } diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/ZonedDateTime.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/ZonedDateTime.java index 55eb204f7..574401bc0 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/ZonedDateTime.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/ZonedDateTime.java @@ -727,7 +727,7 @@ public int get(TemporalField field) { Objects.requireNonNull(field); if (field instanceof ChronoField) { switch ((ChronoField) field) { - case INSTANT_SECONDS: throw new DateTimeException("Field too large for an int: " + field); + case INSTANT_SECONDS: throw new UnsupportedTemporalTypeException("Field too large for an int: " + field); case OFFSET_SECONDS: return getOffset().getTotalSeconds(); } return dateTime.get(field); @@ -1111,6 +1111,9 @@ public ZonedDateTime with(TemporalAdjuster adjuster) { return resolveLocal(LocalDateTime.of(dateTime.toLocalDate(), (LocalTime) adjuster)); } else if (adjuster instanceof LocalDateTime) { return resolveLocal((LocalDateTime) adjuster); + } else if (adjuster instanceof OffsetDateTime) { + OffsetDateTime odt = (OffsetDateTime) adjuster; + return ofLocal(odt.toLocalDateTime(), zone, odt.getOffset()); } else if (adjuster instanceof Instant) { Instant instant = (Instant) adjuster; return create(instant.getEpochSecond(), instant.getNano(), zone); diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/ChronoDateImpl.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/ChronoDateImpl.java index a172f7ec1..a19f351fb 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/ChronoDateImpl.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/ChronoDateImpl.java @@ -31,11 +31,10 @@ */ package org.jresearch.threetenbp.gwt.emu.java.time.chrono; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.DAY_OF_MONTH; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.MONTH_OF_YEAR; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.YEAR_OF_ERA; +import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.*; import java.io.Serializable; + import org.jresearch.threetenbp.gwt.emu.java.time.DateTimeException; import org.jresearch.threetenbp.gwt.emu.java.time.LocalDate; import org.jresearch.threetenbp.gwt.emu.java.time.LocalTime; @@ -43,6 +42,7 @@ import org.jresearch.threetenbp.gwt.emu.java.time.temporal.Temporal; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.TemporalAdjuster; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.TemporalUnit; +import org.jresearch.threetenbp.gwt.emu.java.time.temporal.UnsupportedTemporalTypeException; /** * A date expressed in terms of a standard year-month-day calendar system. @@ -141,7 +141,7 @@ public D plus(long amountToAdd, TemporalUnit unit) { // case ERAS: throw new DateTimeException("Unable to add era, standard calendar system only has one era"); // case FOREVER: return (period == 0 ? this : (period > 0 ? LocalDate.MAX_DATE : LocalDate.MIN_DATE)); } - throw new DateTimeException(unit + " not valid for chronology " + getChronology().getId()); + throw new UnsupportedTemporalTypeException(unit + " not valid for chronology " + getChronology().getId()); } return (D) ChronoLocalDate.super.plus(amountToAdd, unit); } diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/Chronology.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/Chronology.java index 8c3da2663..52f34c041 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/Chronology.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/Chronology.java @@ -37,6 +37,7 @@ import org.jresearch.threetenbp.gwt.emu.java.time.LocalDate; import org.jresearch.threetenbp.gwt.emu.java.time.LocalTime; import org.jresearch.threetenbp.gwt.emu.java.time.ZoneId; +import org.jresearch.threetenbp.gwt.emu.java.time.ZoneOffset; import org.jresearch.threetenbp.gwt.emu.java.time.format.DateTimeFormatterBuilder; import org.jresearch.threetenbp.gwt.emu.java.time.format.ResolverStyle; import org.jresearch.threetenbp.gwt.emu.java.time.format.TextStyle; @@ -48,6 +49,9 @@ import org.jresearch.threetenbp.gwt.emu.java.time.temporal.TemporalQuery; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.UnsupportedTemporalTypeException; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.ValueRange; + +import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.*; + import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -766,6 +770,30 @@ void updateResolveMap(Map fieldValues, ChronoField field, l fieldValues.put(field, value); } + //--------------------------------------------------------------------- + + /** + * @since 9 + */ + public long epochSecond(int year, int month, int dayOfMonth, int hour, int minute, int second, ZoneOffset zoneOffset) { + Objects.requireNonNull(zoneOffset); + HOUR_OF_DAY.checkValidValue(hour); + MINUTE_OF_HOUR.checkValidValue(minute); + SECOND_OF_MINUTE.checkValidValue(second); + long days = date(year, month, dayOfMonth).toEpochDay(); + long daySeconds = Math.multiplyExact(days, 86400) - zoneOffset.getTotalSeconds(); + long timeinSeconds = (hour * 60 + minute) * 60l + second; + return Math.addExact(daySeconds, timeinSeconds); + } + + /** + * @since 9 + */ + public long epochSecond(Era era, int yearOfEra, int month, int dayOfMonth, int hour, int minute, int second, ZoneOffset zoneOffset) { + Objects.requireNonNull(era); + return epochSecond(prolepticYear(era, yearOfEra), month, dayOfMonth, hour, minute, second, zoneOffset); + } + //----------------------------------------------------------------------- /** * Compares this chronology to another chronology. diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/Era.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/Era.java index ca107e1f2..213bb4462 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/Era.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/Era.java @@ -210,7 +210,7 @@ default long getLong(TemporalField field) { if (field == ERA) { return getValue(); } else if (field instanceof ChronoField) { - throw new DateTimeException("Unsupported field: " + field); + throw new UnsupportedTemporalTypeException("Unsupported field: " + field); } return field.getFrom(this); } diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/IsoChronology.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/IsoChronology.java index 187fcb27c..77134bf30 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/IsoChronology.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/chrono/IsoChronology.java @@ -31,22 +31,16 @@ */ package org.jresearch.threetenbp.gwt.emu.java.time.chrono; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.DAY_OF_MONTH; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.DAY_OF_WEEK; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.DAY_OF_YEAR; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.EPOCH_DAY; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.ERA; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.MONTH_OF_YEAR; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.PROLEPTIC_MONTH; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.YEAR; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.YEAR_OF_ERA; -import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.TemporalAdjusters.nextOrSame; +import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField.*; +import static org.jresearch.threetenbp.gwt.emu.java.time.temporal.TemporalAdjusters.*; import java.io.Serializable; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; + import org.jresearch.threetenbp.gwt.emu.java.time.Clock; import org.jresearch.threetenbp.gwt.emu.java.time.DateTimeException; import org.jresearch.threetenbp.gwt.emu.java.time.DayOfWeek; @@ -56,481 +50,536 @@ import org.jresearch.threetenbp.gwt.emu.java.time.Month; import org.jresearch.threetenbp.gwt.emu.java.time.Year; import org.jresearch.threetenbp.gwt.emu.java.time.ZoneId; +import org.jresearch.threetenbp.gwt.emu.java.time.ZoneOffset; import org.jresearch.threetenbp.gwt.emu.java.time.ZonedDateTime; import org.jresearch.threetenbp.gwt.emu.java.time.format.ResolverStyle; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.ChronoField; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.TemporalAccessor; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.TemporalField; import org.jresearch.threetenbp.gwt.emu.java.time.temporal.ValueRange; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Objects; /** * The ISO calendar system. *

- * This chronology defines the rules of the ISO calendar system. - * This calendar system is based on the ISO-8601 standard, which is the - * de facto world calendar. + * This chronology defines the rules of the ISO calendar system. This calendar + * system is based on the ISO-8601 standard, which is the de facto world + * calendar. *

* The fields are defined as follows: - *

    - *
  • era - There are two eras, 'Current Era' (CE) and 'Before Current Era' (BCE). - *
  • year-of-era - The year-of-era is the same as the proleptic-year for the current CE era. - * For the BCE era before the ISO epoch the year increases from 1 upwards as time goes backwards. - *
  • proleptic-year - The proleptic year is the same as the year-of-era for the - * current era. For the previous era, years have zero, then negative values. - *
  • month-of-year - There are 12 months in an ISO year, numbered from 1 to 12. - *
  • day-of-month - There are between 28 and 31 days in each of the ISO month, numbered from 1 to 31. - * Months 4, 6, 9 and 11 have 30 days, Months 1, 3, 5, 7, 8, 10 and 12 have 31 days. - * Month 2 has 28 days, or 29 in a leap year. - *
  • day-of-year - There are 365 days in a standard ISO year and 366 in a leap year. - * The days are numbered from 1 to 365 or 1 to 366. - *
  • leap-year - Leap years occur every 4 years, except where the year is divisble by 100 and not divisble by 400. - *

+ *

+ *

    + *
  • era - There are two eras, 'Current Era' (CE) and 'Before Current Era' + * (BCE). + *
  • year-of-era - The year-of-era is the same as the proleptic-year for the + * current CE era. For the BCE era before the ISO epoch the year increases from + * 1 upwards as time goes backwards. + *
  • proleptic-year - The proleptic year is the same as the year-of-era for + * the current era. For the previous era, years have zero, then negative values. + *
  • month-of-year - There are 12 months in an ISO year, numbered from 1 to + * 12. + *
  • day-of-month - There are between 28 and 31 days in each of the ISO month, + * numbered from 1 to 31. Months 4, 6, 9 and 11 have 30 days, Months 1, 3, 5, 7, + * 8, 10 and 12 have 31 days. Month 2 has 28 days, or 29 in a leap year. + *
  • day-of-year - There are 365 days in a standard ISO year and 366 in a leap + * year. The days are numbered from 1 to 365 or 1 to 366. + *
  • leap-year - Leap years occur every 4 years, except where the year is + * divisble by 100 and not divisble by 400. + *
+ *

* - *

Specification for implementors

- * This class is immutable and thread-safe. + *

Specification for implementors

This class is immutable and + * thread-safe. */ public final class IsoChronology extends Chronology implements Serializable { - /** - * Singleton instance of the ISO chronology. - */ - public static final IsoChronology INSTANCE = new IsoChronology(); - - /** - * Serialization version. - */ - private static final long serialVersionUID = -1440403870442975015L; - - /** - * Restricted constructor. - */ - private IsoChronology() { - } - - /** - * Resolve singleton. - * - * @return the singleton instance, not null - */ - private Object readResolve() { - return INSTANCE; - } - - //----------------------------------------------------------------------- - /** - * Gets the ID of the chronology - 'ISO'. - *

- * The ID uniquely identifies the {@code Chronology}. - * It can be used to lookup the {@code Chronology} using {@link #of(String)}. - * - * @return the chronology ID - 'ISO' - * @see #getCalendarType() - */ - @Override - public String getId() { - return "ISO"; - } - - /** - * Gets the calendar type of the underlying calendar system - 'iso8601'. - *

- * The calendar type is an identifier defined by the - * Unicode Locale Data Markup Language (LDML) specification. - * It can be used to lookup the {@code Chronology} using {@link #of(String)}. - * It can also be used as part of a locale, accessible via - * {@link Locale#getUnicodeLocaleType(String)} with the key 'ca'. - * - * @return the calendar system type - 'iso8601' - * @see #getId() - */ - @Override - public String getCalendarType() { - return "iso8601"; - } - - //----------------------------------------------------------------------- - /** - * Obtains an ISO local date from the era, year-of-era, month-of-year - * and day-of-month fields. - * - * @param era the ISO era, not null - * @param yearOfEra the ISO year-of-era - * @param month the ISO month-of-year - * @param dayOfMonth the ISO day-of-month - * @return the ISO local date, not null - * @throws DateTimeException if unable to create the date - */ - @Override // override with covariant return type - public LocalDate date(Era era, int yearOfEra, int month, int dayOfMonth) { - return date(prolepticYear(era, yearOfEra), month, dayOfMonth); - } - - /** - * Obtains an ISO local date from the proleptic-year, month-of-year - * and day-of-month fields. - *

- * This is equivalent to {@link LocalDate#of(int, int, int)}. - * - * @param prolepticYear the ISO proleptic-year - * @param month the ISO month-of-year - * @param dayOfMonth the ISO day-of-month - * @return the ISO local date, not null - * @throws DateTimeException if unable to create the date - */ - @Override // override with covariant return type - public LocalDate date(int prolepticYear, int month, int dayOfMonth) { - return LocalDate.of(prolepticYear, month, dayOfMonth); - } - - /** - * Obtains an ISO local date from the era, year-of-era and day-of-year fields. - * - * @param era the ISO era, not null - * @param yearOfEra the ISO year-of-era - * @param dayOfYear the ISO day-of-year - * @return the ISO local date, not null - * @throws DateTimeException if unable to create the date - */ - @Override // override with covariant return type - public LocalDate dateYearDay(Era era, int yearOfEra, int dayOfYear) { - return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear); - } - - /** - * Obtains an ISO local date from the proleptic-year and day-of-year fields. - *

- * This is equivalent to {@link LocalDate#ofYearDay(int, int)}. - * - * @param prolepticYear the ISO proleptic-year - * @param dayOfYear the ISO day-of-year - * @return the ISO local date, not null - * @throws DateTimeException if unable to create the date - */ - @Override // override with covariant return type - public LocalDate dateYearDay(int prolepticYear, int dayOfYear) { - return LocalDate.ofYearDay(prolepticYear, dayOfYear); - } - - @Override - public LocalDate dateEpochDay(long epochDay) { - return LocalDate.ofEpochDay(epochDay); - } - - //----------------------------------------------------------------------- - /** - * Obtains an ISO local date from another date-time object. - *

- * This is equivalent to {@link LocalDate#from(TemporalAccessor)}. - * - * @param temporal the date-time object to convert, not null - * @return the ISO local date, not null - * @throws DateTimeException if unable to create the date - */ - @Override // override with covariant return type - public LocalDate date(TemporalAccessor temporal) { - return LocalDate.from(temporal); - } - - /** - * Obtains an ISO local date-time from another date-time object. - *

- * This is equivalent to {@link LocalDateTime#from(TemporalAccessor)}. - * - * @param temporal the date-time object to convert, not null - * @return the ISO local date-time, not null - * @throws DateTimeException if unable to create the date-time - */ - @Override // override with covariant return type - public LocalDateTime localDateTime(TemporalAccessor temporal) { - return LocalDateTime.from(temporal); - } - - /** - * Obtains an ISO zoned date-time from another date-time object. - *

- * This is equivalent to {@link ZonedDateTime#from(TemporalAccessor)}. - * - * @param temporal the date-time object to convert, not null - * @return the ISO zoned date-time, not null - * @throws DateTimeException if unable to create the date-time - */ - @Override // override with covariant return type - public ZonedDateTime zonedDateTime(TemporalAccessor temporal) { - return ZonedDateTime.from(temporal); - } - - /** - * Obtains an ISO zoned date-time from an instant. - *

- * This is equivalent to {@link ZonedDateTime#ofInstant(Instant, ZoneId)}. - * - * @param instant the instant to convert, not null - * @param zone the zone to use, not null - * @return the ISO zoned date-time, not null - * @throws DateTimeException if unable to create the date-time - */ - @Override // override with covariant return type - public ZonedDateTime zonedDateTime(Instant instant, ZoneId zone) { - return ZonedDateTime.ofInstant(instant, zone); - } - - //----------------------------------------------------------------------- - /** - * Obtains the current ISO local date from the system clock in the default time-zone. - *

- * This will query the {@link Clock#systemDefaultZone() system clock} in the default - * time-zone to obtain the current date. - *

- * Using this method will prevent the ability to use an alternate clock for testing - * because the clock is hard-coded. - * - * @return the current ISO local date using the system clock and default time-zone, not null - * @throws DateTimeException if unable to create the date - */ - @Override // override with covariant return type - public LocalDate dateNow() { - return dateNow(Clock.systemDefaultZone()); - } - - /** - * Obtains the current ISO local date from the system clock in the specified time-zone. - *

- * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date. - * Specifying the time-zone avoids dependence on the default time-zone. - *

- * Using this method will prevent the ability to use an alternate clock for testing - * because the clock is hard-coded. - * - * @return the current ISO local date using the system clock, not null - * @throws DateTimeException if unable to create the date - */ - @Override // override with covariant return type - public LocalDate dateNow(ZoneId zone) { - return dateNow(Clock.system(zone)); - } - - /** - * Obtains the current ISO local date from the specified clock. - *

- * This will query the specified clock to obtain the current date - today. - * Using this method allows the use of an alternate clock for testing. - * The alternate clock may be introduced using {@link Clock dependency injection}. - * - * @param clock the clock to use, not null - * @return the current ISO local date, not null - * @throws DateTimeException if unable to create the date - */ - @Override // override with covariant return type - public LocalDate dateNow(Clock clock) { - Objects.requireNonNull(clock, "clock"); - return date(LocalDate.now(clock)); - } - - //----------------------------------------------------------------------- - /** - * Checks if the year is a leap year, according to the ISO proleptic - * calendar system rules. - *

- * This method applies the current rules for leap years across the whole time-line. - * In general, a year is a leap year if it is divisible by four without - * remainder. However, years divisible by 100, are not leap years, with - * the exception of years divisible by 400 which are. - *

- * For example, 1904 is a leap year it is divisible by 4. - * 1900 was not a leap year as it is divisible by 100, however 2000 was a - * leap year as it is divisible by 400. - *

- * The calculation is proleptic - applying the same rules into the far future and far past. - * This is historically inaccurate, but is correct for the ISO-8601 standard. - * - * @param prolepticYear the ISO proleptic year to check - * @return true if the year is leap, false otherwise - */ - @Override - public boolean isLeapYear(long prolepticYear) { - return ((prolepticYear & 3) == 0) && ((prolepticYear % 100) != 0 || (prolepticYear % 400) == 0); - } - - @Override - public int prolepticYear(Era era, int yearOfEra) { - if (era instanceof IsoEra == false) { - throw new ClassCastException("Era must be IsoEra"); - } - return (era == IsoEra.CE ? yearOfEra : 1 - yearOfEra); - } - - @Override - public IsoEra eraOf(int eraValue) { - return IsoEra.of(eraValue); - } - - @Override - public List eras() { - return Arrays.asList(IsoEra.values()); - } - - //----------------------------------------------------------------------- - @Override - public ValueRange range(ChronoField field) { - return field.range(); - } - - @Override - public LocalDate resolveDate(Map fieldValues, ResolverStyle resolverStyle) { - if (fieldValues.containsKey(EPOCH_DAY)) { - return LocalDate.ofEpochDay(fieldValues.remove(EPOCH_DAY)); - } - - // normalize fields - Long prolepticMonth = fieldValues.remove(PROLEPTIC_MONTH); - if (prolepticMonth != null) { - if (resolverStyle != ResolverStyle.LENIENT) { - PROLEPTIC_MONTH.checkValidValue(prolepticMonth); - } - updateResolveMap(fieldValues, MONTH_OF_YEAR, Math.floorMod(prolepticMonth, 12) + 1); + /** + * Singleton instance of the ISO chronology. + */ + public static final IsoChronology INSTANCE = new IsoChronology(); + + /** + * Serialization version. + */ + private static final long serialVersionUID = -1440403870442975015L; + + /** + * Restricted constructor. + */ + private IsoChronology() { + } + + /** + * Resolve singleton. + * + * @return the singleton instance, not null + */ + private Object readResolve() { + return INSTANCE; + } + + // ----------------------------------------------------------------------- + /** + * Gets the ID of the chronology - 'ISO'. + *

+ * The ID uniquely identifies the {@code Chronology}. It can be used to lookup + * the {@code Chronology} using {@link #of(String)}. + * + * @return the chronology ID - 'ISO' + * @see #getCalendarType() + */ + @Override + public String getId() { + return "ISO"; + } + + /** + * Gets the calendar type of the underlying calendar system - 'iso8601'. + *

+ * The calendar type is an identifier defined by the Unicode Locale Data + * Markup Language (LDML) specification. It can be used to lookup the + * {@code Chronology} using {@link #of(String)}. It can also be used as part of + * a locale, accessible via {@link Locale#getUnicodeLocaleType(String)} with the + * key 'ca'. + * + * @return the calendar system type - 'iso8601' + * @see #getId() + */ + @Override + public String getCalendarType() { + return "iso8601"; + } + + // ----------------------------------------------------------------------- + /** + * Obtains an ISO local date from the era, year-of-era, month-of-year and + * day-of-month fields. + * + * @param era the ISO era, not null + * @param yearOfEra the ISO year-of-era + * @param month the ISO month-of-year + * @param dayOfMonth the ISO day-of-month + * @return the ISO local date, not null + * @throws DateTimeException if unable to create the date + */ + @Override // override with covariant return type + public LocalDate date(Era era, int yearOfEra, int month, int dayOfMonth) { + return date(prolepticYear(era, yearOfEra), month, dayOfMonth); + } + + /** + * Obtains an ISO local date from the proleptic-year, month-of-year and + * day-of-month fields. + *

+ * This is equivalent to {@link LocalDate#of(int, int, int)}. + * + * @param prolepticYear the ISO proleptic-year + * @param month the ISO month-of-year + * @param dayOfMonth the ISO day-of-month + * @return the ISO local date, not null + * @throws DateTimeException if unable to create the date + */ + @Override // override with covariant return type + public LocalDate date(int prolepticYear, int month, int dayOfMonth) { + return LocalDate.of(prolepticYear, month, dayOfMonth); + } + + /** + * Obtains an ISO local date from the era, year-of-era and day-of-year fields. + * + * @param era the ISO era, not null + * @param yearOfEra the ISO year-of-era + * @param dayOfYear the ISO day-of-year + * @return the ISO local date, not null + * @throws DateTimeException if unable to create the date + */ + @Override // override with covariant return type + public LocalDate dateYearDay(Era era, int yearOfEra, int dayOfYear) { + return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear); + } + + /** + * Obtains an ISO local date from the proleptic-year and day-of-year fields. + *

+ * This is equivalent to {@link LocalDate#ofYearDay(int, int)}. + * + * @param prolepticYear the ISO proleptic-year + * @param dayOfYear the ISO day-of-year + * @return the ISO local date, not null + * @throws DateTimeException if unable to create the date + */ + @Override // override with covariant return type + public LocalDate dateYearDay(int prolepticYear, int dayOfYear) { + return LocalDate.ofYearDay(prolepticYear, dayOfYear); + } + + @Override + public LocalDate dateEpochDay(long epochDay) { + return LocalDate.ofEpochDay(epochDay); + } + + // ----------------------------------------------------------------------- + /** + * Obtains an ISO local date from another date-time object. + *

+ * This is equivalent to {@link LocalDate#from(TemporalAccessor)}. + * + * @param temporal the date-time object to convert, not null + * @return the ISO local date, not null + * @throws DateTimeException if unable to create the date + */ + @Override // override with covariant return type + public LocalDate date(TemporalAccessor temporal) { + return LocalDate.from(temporal); + } + + /** + * @since 9 + */ + @Override + public long epochSecond(int year, int month, int dayOfMonth, int hour, int minute, int second, ZoneOffset zoneOffset) { + YEAR.checkValidValue(year); + MONTH_OF_YEAR.checkValidValue(month); + DAY_OF_MONTH.checkValidValue(dayOfMonth); + HOUR_OF_DAY.checkValidValue(hour); + MINUTE_OF_HOUR.checkValidValue(minute); + SECOND_OF_MINUTE.checkValidValue(second); + Objects.requireNonNull(zoneOffset, "zoneOffset"); + if (dayOfMonth > 28 && dayOfMonth > maxDays(year, month)) { + throw new DateTimeException("Invalid date '" + Month.of(month).name() + " " + dayOfMonth + "'"); + } + long totalDays = 365L * year; + // Remove/add leap days + if (year >= 0) { + totalDays += (year + 3L) / 4 - (year + 99L) / 100 + (year + 399L) / 400; + } else { + totalDays -= year / -4 - year / -100 + year / -400; + } + totalDays += (367 * month - 362) / 12; + totalDays += dayOfMonth - 1; + if (month >= 3) { + // Minus one day for Feb. + totalDays--; + if (!IsoChronology.INSTANCE.isLeapYear(year)) { + // Minus one day for non-leap year + totalDays--; + } + } + // Start from 1970 + totalDays -= LocalDate.DAYS_0000_TO_1970; + int timeSeconds = (hour * 60 + minute) * 60 + second - zoneOffset.getTotalSeconds(); + return Math.addExact(Math.multiplyExact(totalDays, 86400L), timeSeconds); + } + + private static int maxDays(int year, int month) { + if (month == 2) { + return IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28; + } + if (month == 4 || month == 6 || month == 9 || month == 11) { + return 30; + } + return 31; + } + + /** + * Obtains an ISO local date-time from another date-time object. + *

+ * This is equivalent to {@link LocalDateTime#from(TemporalAccessor)}. + * + * @param temporal the date-time object to convert, not null + * @return the ISO local date-time, not null + * @throws DateTimeException if unable to create the date-time + */ + @Override // override with covariant return type + public LocalDateTime localDateTime(TemporalAccessor temporal) { + return LocalDateTime.from(temporal); + } + + /** + * Obtains an ISO zoned date-time from another date-time object. + *

+ * This is equivalent to {@link ZonedDateTime#from(TemporalAccessor)}. + * + * @param temporal the date-time object to convert, not null + * @return the ISO zoned date-time, not null + * @throws DateTimeException if unable to create the date-time + */ + @Override // override with covariant return type + public ZonedDateTime zonedDateTime(TemporalAccessor temporal) { + return ZonedDateTime.from(temporal); + } + + /** + * Obtains an ISO zoned date-time from an instant. + *

+ * This is equivalent to {@link ZonedDateTime#ofInstant(Instant, ZoneId)}. + * + * @param instant the instant to convert, not null + * @param zone the zone to use, not null + * @return the ISO zoned date-time, not null + * @throws DateTimeException if unable to create the date-time + */ + @Override // override with covariant return type + public ZonedDateTime zonedDateTime(Instant instant, ZoneId zone) { + return ZonedDateTime.ofInstant(instant, zone); + } + + // ----------------------------------------------------------------------- + /** + * Obtains the current ISO local date from the system clock in the default + * time-zone. + *

+ * This will query the {@link Clock#systemDefaultZone() system clock} in the + * default time-zone to obtain the current date. + *

+ * Using this method will prevent the ability to use an alternate clock for + * testing because the clock is hard-coded. + * + * @return the current ISO local date using the system clock and default + * time-zone, not null + * @throws DateTimeException if unable to create the date + */ + @Override // override with covariant return type + public LocalDate dateNow() { + return dateNow(Clock.systemDefaultZone()); + } + + /** + * Obtains the current ISO local date from the system clock in the specified + * time-zone. + *

+ * This will query the {@link Clock#system(ZoneId) system clock} to obtain the + * current date. Specifying the time-zone avoids dependence on the default + * time-zone. + *

+ * Using this method will prevent the ability to use an alternate clock for + * testing because the clock is hard-coded. + * + * @return the current ISO local date using the system clock, not null + * @throws DateTimeException if unable to create the date + */ + @Override // override with covariant return type + public LocalDate dateNow(ZoneId zone) { + return dateNow(Clock.system(zone)); + } + + /** + * Obtains the current ISO local date from the specified clock. + *

+ * This will query the specified clock to obtain the current date - today. Using + * this method allows the use of an alternate clock for testing. The alternate + * clock may be introduced using {@link Clock dependency injection}. + * + * @param clock the clock to use, not null + * @return the current ISO local date, not null + * @throws DateTimeException if unable to create the date + */ + @Override // override with covariant return type + public LocalDate dateNow(Clock clock) { + Objects.requireNonNull(clock, "clock"); + return date(LocalDate.now(clock)); + } + + // ----------------------------------------------------------------------- + /** + * Checks if the year is a leap year, according to the ISO proleptic calendar + * system rules. + *

+ * This method applies the current rules for leap years across the whole + * time-line. In general, a year is a leap year if it is divisible by four + * without remainder. However, years divisible by 100, are not leap years, with + * the exception of years divisible by 400 which are. + *

+ * For example, 1904 is a leap year it is divisible by 4. 1900 was not a leap + * year as it is divisible by 100, however 2000 was a leap year as it is + * divisible by 400. + *

+ * The calculation is proleptic - applying the same rules into the far future + * and far past. This is historically inaccurate, but is correct for the + * ISO-8601 standard. + * + * @param prolepticYear the ISO proleptic year to check + * @return true if the year is leap, false otherwise + */ + @Override + public boolean isLeapYear(long prolepticYear) { + return ((prolepticYear & 3) == 0) && ((prolepticYear % 100) != 0 || (prolepticYear % 400) == 0); + } + + @Override + public int prolepticYear(Era era, int yearOfEra) { + if (era instanceof IsoEra == false) { + throw new ClassCastException("Era must be IsoEra"); + } + return (era == IsoEra.CE ? yearOfEra : 1 - yearOfEra); + } + + @Override + public IsoEra eraOf(int eraValue) { + return IsoEra.of(eraValue); + } + + @Override + public List eras() { + return Arrays.asList(IsoEra.values()); + } + + // ----------------------------------------------------------------------- + @Override + public ValueRange range(ChronoField field) { + return field.range(); + } + + @Override + public LocalDate resolveDate(Map fieldValues, ResolverStyle resolverStyle) { + if (fieldValues.containsKey(EPOCH_DAY)) { + return LocalDate.ofEpochDay(fieldValues.remove(EPOCH_DAY)); + } + + // normalize fields + Long prolepticMonth = fieldValues.remove(PROLEPTIC_MONTH); + if (prolepticMonth != null) { + if (resolverStyle != ResolverStyle.LENIENT) { + PROLEPTIC_MONTH.checkValidValue(prolepticMonth); + } + updateResolveMap(fieldValues, MONTH_OF_YEAR, Math.floorMod(prolepticMonth, 12) + 1); updateResolveMap(fieldValues, YEAR, Math.floorDiv(prolepticMonth, 12)); - } - - // eras - Long yoeLong = fieldValues.remove(YEAR_OF_ERA); - if (yoeLong != null) { - if (resolverStyle != ResolverStyle.LENIENT) { - YEAR_OF_ERA.checkValidValue(yoeLong); - } - Long era = fieldValues.remove(ERA); - if (era == null) { - Long year = fieldValues.get(YEAR); - if (resolverStyle == ResolverStyle.STRICT) { - // do not invent era if strict, but do cross-check with year - if (year != null) { - updateResolveMap(fieldValues, YEAR, (year > 0 ? yoeLong: Math.subtractExact(1, yoeLong))); - } else { - // reinstate the field removed earlier, no cross-check issues - fieldValues.put(YEAR_OF_ERA, yoeLong); - } - } else { - // invent era - updateResolveMap(fieldValues, YEAR, (year == null || year > 0 ? yoeLong: Math.subtractExact(1, yoeLong))); - } - } else if (era.longValue() == 1L) { - updateResolveMap(fieldValues, YEAR, yoeLong); - } else if (era.longValue() == 0L) { - updateResolveMap(fieldValues, YEAR, Math.subtractExact(1, yoeLong)); - } else { - throw new DateTimeException("Invalid value for era: " + era); - } - } else if (fieldValues.containsKey(ERA)) { - ERA.checkValidValue(fieldValues.get(ERA)); // always validated - } - - // build date - if (fieldValues.containsKey(YEAR)) { - if (fieldValues.containsKey(MONTH_OF_YEAR)) { - if (fieldValues.containsKey(DAY_OF_MONTH)) { - int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR)); - int moy = Math.toIntExact(fieldValues.remove(MONTH_OF_YEAR)); - int dom = Math.toIntExact(fieldValues.remove(DAY_OF_MONTH)); - if (resolverStyle == ResolverStyle.LENIENT) { - long months = Math.subtractExact(moy, 1); - long days = Math.subtractExact(dom, 1); - return LocalDate.of(y, 1, 1).plusMonths(months).plusDays(days); - } else if (resolverStyle == ResolverStyle.SMART){ - DAY_OF_MONTH.checkValidValue(dom); - if (moy == 4 || moy == 6 || moy == 9 || moy == 11) { - dom = Math.min(dom, 30); - } else if (moy == 2) { - dom = Math.min(dom, Month.FEBRUARY.length(Year.isLeap(y))); - } - return LocalDate.of(y, moy, dom); - } else { - return LocalDate.of(y, moy, dom); - } - } - if (fieldValues.containsKey(ALIGNED_WEEK_OF_MONTH)) { - if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_MONTH)) { - int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR)); - if (resolverStyle == ResolverStyle.LENIENT) { - long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1); - long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1); - long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), 1); - return LocalDate.of(y, 1, 1).plusMonths(months).plusWeeks(weeks).plusDays(days); - } - int moy = MONTH_OF_YEAR.checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR)); - int aw = ALIGNED_WEEK_OF_MONTH.checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH)); - int ad = ALIGNED_DAY_OF_WEEK_IN_MONTH.checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH)); - LocalDate date = LocalDate.of(y, moy, 1).plusDays((aw - 1) * 7 + (ad - 1)); - if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) { - throw new DateTimeException("Strict mode rejected date parsed to a different month"); - } - return date; - } - if (fieldValues.containsKey(DAY_OF_WEEK)) { - int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR)); - if (resolverStyle == ResolverStyle.LENIENT) { - long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1); - long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1); - long days = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1); - return LocalDate.of(y, 1, 1).plusMonths(months).plusWeeks(weeks).plusDays(days); - } - int moy = MONTH_OF_YEAR.checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR)); - int aw = ALIGNED_WEEK_OF_MONTH.checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH)); - int dow = DAY_OF_WEEK.checkValidIntValue(fieldValues.remove(DAY_OF_WEEK)); - LocalDate date = LocalDate.of(y, moy, 1).plusWeeks(aw - 1).with(nextOrSame(DayOfWeek.of(dow))); - if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) { - throw new DateTimeException("Strict mode rejected date parsed to a different month"); - } - return date; - } - } - } - if (fieldValues.containsKey(DAY_OF_YEAR)) { - int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR)); - if (resolverStyle == ResolverStyle.LENIENT) { - long days = Math.subtractExact(fieldValues.remove(DAY_OF_YEAR), 1); - return LocalDate.ofYearDay(y, 1).plusDays(days); - } - int doy = DAY_OF_YEAR.checkValidIntValue(fieldValues.remove(DAY_OF_YEAR)); - return LocalDate.ofYearDay(y, doy); - } - if (fieldValues.containsKey(ALIGNED_WEEK_OF_YEAR)) { - if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_YEAR)) { - int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR)); - if (resolverStyle == ResolverStyle.LENIENT) { - long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1); - long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), 1); - return LocalDate.of(y, 1, 1).plusWeeks(weeks).plusDays(days); - } - int aw = ALIGNED_WEEK_OF_YEAR.checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR)); - int ad = ALIGNED_DAY_OF_WEEK_IN_YEAR.checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR)); - LocalDate date = LocalDate.of(y, 1, 1).plusDays((aw - 1) * 7 + (ad - 1)); - if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) { - throw new DateTimeException("Strict mode rejected date parsed to a different year"); - } - return date; - } - if (fieldValues.containsKey(DAY_OF_WEEK)) { - int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR)); - if (resolverStyle == ResolverStyle.LENIENT) { - long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1); - long days = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1); - return LocalDate.of(y, 1, 1).plusWeeks(weeks).plusDays(days); - } - int aw = ALIGNED_WEEK_OF_YEAR.checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR)); - int dow = DAY_OF_WEEK.checkValidIntValue(fieldValues.remove(DAY_OF_WEEK)); - LocalDate date = LocalDate.of(y, 1, 1).plusWeeks(aw - 1).with(nextOrSame(DayOfWeek.of(dow))); - if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) { - throw new DateTimeException("Strict mode rejected date parsed to a different month"); - } - return date; - } - } - } - return null; - } + } + + // eras + Long yoeLong = fieldValues.remove(YEAR_OF_ERA); + if (yoeLong != null) { + if (resolverStyle != ResolverStyle.LENIENT) { + YEAR_OF_ERA.checkValidValue(yoeLong); + } + Long era = fieldValues.remove(ERA); + if (era == null) { + Long year = fieldValues.get(YEAR); + if (resolverStyle == ResolverStyle.STRICT) { + // do not invent era if strict, but do cross-check with year + if (year != null) { + updateResolveMap(fieldValues, YEAR, (year > 0 ? yoeLong : Math.subtractExact(1, yoeLong))); + } else { + // reinstate the field removed earlier, no cross-check issues + fieldValues.put(YEAR_OF_ERA, yoeLong); + } + } else { + // invent era + updateResolveMap(fieldValues, YEAR, (year == null || year > 0 ? yoeLong : Math.subtractExact(1, yoeLong))); + } + } else if (era.longValue() == 1L) { + updateResolveMap(fieldValues, YEAR, yoeLong); + } else if (era.longValue() == 0L) { + updateResolveMap(fieldValues, YEAR, Math.subtractExact(1, yoeLong)); + } else { + throw new DateTimeException("Invalid value for era: " + era); + } + } else if (fieldValues.containsKey(ERA)) { + ERA.checkValidValue(fieldValues.get(ERA)); // always validated + } + + // build date + if (fieldValues.containsKey(YEAR)) { + if (fieldValues.containsKey(MONTH_OF_YEAR)) { + if (fieldValues.containsKey(DAY_OF_MONTH)) { + int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR)); + int moy = Math.toIntExact(fieldValues.remove(MONTH_OF_YEAR)); + int dom = Math.toIntExact(fieldValues.remove(DAY_OF_MONTH)); + if (resolverStyle == ResolverStyle.LENIENT) { + long months = Math.subtractExact(moy, 1); + long days = Math.subtractExact(dom, 1); + return LocalDate.of(y, 1, 1).plusMonths(months).plusDays(days); + } else if (resolverStyle == ResolverStyle.SMART) { + DAY_OF_MONTH.checkValidValue(dom); + if (moy == 4 || moy == 6 || moy == 9 || moy == 11) { + dom = Math.min(dom, 30); + } else if (moy == 2) { + dom = Math.min(dom, Month.FEBRUARY.length(Year.isLeap(y))); + } + return LocalDate.of(y, moy, dom); + } else { + return LocalDate.of(y, moy, dom); + } + } + if (fieldValues.containsKey(ALIGNED_WEEK_OF_MONTH)) { + if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_MONTH)) { + int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR)); + if (resolverStyle == ResolverStyle.LENIENT) { + long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1); + long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1); + long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), 1); + return LocalDate.of(y, 1, 1).plusMonths(months).plusWeeks(weeks).plusDays(days); + } + int moy = MONTH_OF_YEAR.checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR)); + int aw = ALIGNED_WEEK_OF_MONTH.checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH)); + int ad = ALIGNED_DAY_OF_WEEK_IN_MONTH.checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH)); + LocalDate date = LocalDate.of(y, moy, 1).plusDays((aw - 1) * 7 + (ad - 1)); + if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) { + throw new DateTimeException("Strict mode rejected date parsed to a different month"); + } + return date; + } + if (fieldValues.containsKey(DAY_OF_WEEK)) { + int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR)); + if (resolverStyle == ResolverStyle.LENIENT) { + long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1); + long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1); + long days = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1); + return LocalDate.of(y, 1, 1).plusMonths(months).plusWeeks(weeks).plusDays(days); + } + int moy = MONTH_OF_YEAR.checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR)); + int aw = ALIGNED_WEEK_OF_MONTH.checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH)); + int dow = DAY_OF_WEEK.checkValidIntValue(fieldValues.remove(DAY_OF_WEEK)); + LocalDate date = LocalDate.of(y, moy, 1).plusWeeks(aw - 1).with(nextOrSame(DayOfWeek.of(dow))); + if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) { + throw new DateTimeException("Strict mode rejected date parsed to a different month"); + } + return date; + } + } + } + if (fieldValues.containsKey(DAY_OF_YEAR)) { + int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR)); + if (resolverStyle == ResolverStyle.LENIENT) { + long days = Math.subtractExact(fieldValues.remove(DAY_OF_YEAR), 1); + return LocalDate.ofYearDay(y, 1).plusDays(days); + } + int doy = DAY_OF_YEAR.checkValidIntValue(fieldValues.remove(DAY_OF_YEAR)); + return LocalDate.ofYearDay(y, doy); + } + if (fieldValues.containsKey(ALIGNED_WEEK_OF_YEAR)) { + if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_YEAR)) { + int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR)); + if (resolverStyle == ResolverStyle.LENIENT) { + long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1); + long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), 1); + return LocalDate.of(y, 1, 1).plusWeeks(weeks).plusDays(days); + } + int aw = ALIGNED_WEEK_OF_YEAR.checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR)); + int ad = ALIGNED_DAY_OF_WEEK_IN_YEAR.checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR)); + LocalDate date = LocalDate.of(y, 1, 1).plusDays((aw - 1) * 7 + (ad - 1)); + if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) { + throw new DateTimeException("Strict mode rejected date parsed to a different year"); + } + return date; + } + if (fieldValues.containsKey(DAY_OF_WEEK)) { + int y = YEAR.checkValidIntValue(fieldValues.remove(YEAR)); + if (resolverStyle == ResolverStyle.LENIENT) { + long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1); + long days = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1); + return LocalDate.of(y, 1, 1).plusWeeks(weeks).plusDays(days); + } + int aw = ALIGNED_WEEK_OF_YEAR.checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR)); + int dow = DAY_OF_WEEK.checkValidIntValue(fieldValues.remove(DAY_OF_WEEK)); + LocalDate date = LocalDate.of(y, 1, 1).plusWeeks(aw - 1).with(nextOrSame(DayOfWeek.of(dow))); + if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) { + throw new DateTimeException("Strict mode rejected date parsed to a different month"); + } + return date; + } + } + } + return null; + } } diff --git a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/format/DecimalStyle.java b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/format/DecimalStyle.java index c572830c1..9cf2aa035 100644 --- a/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/format/DecimalStyle.java +++ b/time/src/main/java/org/jresearch/threetenbp/gwt/emu/java/time/format/DecimalStyle.java @@ -94,7 +94,7 @@ public final class DecimalStyle { // GWT Specific public static Set getAvailableLocales() { Locale[] locales = Support.supportedLocalesOfNumberFormat(Locale.getAvailableLocales()); - HashSet result = new HashSet<>(); + HashSet result = new HashSet<>(locales.length); Collections.addAll(result, locales); return result; } From 567c48b37f63303644d7254dd32a57bee7553590 Mon Sep 17 00:00:00 2001 From: Stanislav Spiridonov Date: Sat, 18 May 2024 16:07:30 +0200 Subject: [PATCH 9/9] Update CLDR to 45 --- pom/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom/pom.xml b/pom/pom.xml index 7eb1de5f6..b57fc6ee4 100644 --- a/pom/pom.xml +++ b/pom/pom.xml @@ -383,9 +383,9 @@ 1.2 1.1 1.0.2-gwt2.8.2 - 2.0.14 + 2.0.15 1.0.5 - 1.0.6 + 1.0.7 1.0.3 11