mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-25 17:50:45 +00:00
Merge
This commit is contained in:
commit
2a904298d2
@ -198,3 +198,4 @@ a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70
|
||||
57d5d954462831ac353a1f40d3bb05ddb4620952 jdk8-b74
|
||||
4a67fdb752b7d6329d9be9c28d3f9d6cf7eb9a3c jdk8-b75
|
||||
3a263052866137b645ab86498a43693ff5c19e69 jdk8-b76
|
||||
b2fc8e31cecc35b76188e821d4c5dc0e0b74ac24 jdk8-b77
|
||||
|
||||
@ -128,9 +128,9 @@ CORE_PKGS = \
|
||||
java.text \
|
||||
java.text.spi \
|
||||
java.time \
|
||||
java.time.temporal \
|
||||
java.time.calendar \
|
||||
java.time.chrono \
|
||||
java.time.format \
|
||||
java.time.temporal \
|
||||
java.time.zone \
|
||||
java.util \
|
||||
java.util.concurrent \
|
||||
|
||||
@ -255,7 +255,6 @@ JAVA_JAVA_java = \
|
||||
java/util/SimpleTimeZone.java \
|
||||
sun/util/calendar/ZoneInfo.java \
|
||||
sun/util/calendar/ZoneInfoFile.java \
|
||||
sun/util/calendar/TzIDOldMapping.java \
|
||||
java/util/TooManyListenersException.java \
|
||||
java/util/Comparator.java \
|
||||
java/util/Collections.java \
|
||||
@ -389,6 +388,7 @@ JAVA_JAVA_java = \
|
||||
java/util/concurrent/locks/ReadWriteLock.java \
|
||||
java/util/concurrent/locks/ReentrantLock.java \
|
||||
java/util/concurrent/locks/ReentrantReadWriteLock.java \
|
||||
java/util/concurrent/locks/StampedLock.java \
|
||||
java/util/regex/Pattern.java \
|
||||
java/util/regex/Matcher.java \
|
||||
java/util/regex/MatchResult.java \
|
||||
|
||||
@ -63,6 +63,7 @@ jprt.vm.default.test.targets= \
|
||||
${jprt.my.test.target.set:TESTNAME=jvm98}
|
||||
|
||||
# Default jdk test targets (testset=default)
|
||||
# NOTE: This does not match test/Makefile :: jdk_default
|
||||
jprt.make.rule.default.test.targets= \
|
||||
${jprt.my.test.target.set:TESTNAME=jdk_lang}, \
|
||||
${jprt.my.test.target.set:TESTNAME=jdk_math}
|
||||
@ -72,6 +73,7 @@ jprt.vm.core.test.targets= \
|
||||
${jprt.vm.default.test.targets}
|
||||
|
||||
# Core jdk test targets (testset=core)
|
||||
# NOTE: please keep this in sync with test/Makefile :: jdk_core
|
||||
jprt.make.rule.core.test.targets= \
|
||||
${jprt.make.rule.default.test.targets}, \
|
||||
${jprt.my.test.target.set:TESTNAME=jdk_util}, \
|
||||
@ -97,6 +99,7 @@ jprt.vm.all.test.targets= \
|
||||
${jprt.my.test.target.set:TESTNAME=jbb_default}
|
||||
|
||||
# All jdk test targets (testset=all)
|
||||
# NOTE: This does not match test/Makefile :: jdk_all
|
||||
jprt.make.rule.all.test.targets= \
|
||||
${jprt.make.rule.core.test.targets}, \
|
||||
${jprt.my.test.target.set:TESTNAME=jdk_awt}, \
|
||||
|
||||
@ -70,7 +70,7 @@ else
|
||||
endif
|
||||
|
||||
# nio need to be compiled before awt to have all charsets ready
|
||||
SUBDIRS = jar security javazic misc net nio text util launcher cldr tzdb
|
||||
SUBDIRS = jar security misc net nio text util launcher cldr tzdb
|
||||
|
||||
ifdef BUILD_HEADLESS_ONLY
|
||||
DISPLAY_LIBS = awt $(HEADLESS_SUBDIR)
|
||||
|
||||
@ -33,11 +33,11 @@ include $(BUILDDIR)/common/Defs.gmk
|
||||
|
||||
# Time zone data file creation
|
||||
TZDATA = ./tzdata/
|
||||
TZDATA_VER = `$(GREP) '^tzdata' $(TZDATA)VERSION`
|
||||
TZDATA_VER := $(shell $(GREP) '^tzdata' $(TZDATA)VERSION)
|
||||
TZFILE = \
|
||||
africa antarctica asia australasia europe northamerica \
|
||||
pacificnew southamerica backward \
|
||||
etcetera solar87 solar88 solar89 systemv
|
||||
etcetera systemv
|
||||
JDKTZDATA = ./tzdata_jdk/
|
||||
JDKTZFILES = gmt jdk11_backward
|
||||
TZFILES = \
|
||||
|
||||
27
jdk/make/sun/javazic/tzdata/gmt
Normal file
27
jdk/make/sun/javazic/tzdata/gmt
Normal file
@ -0,0 +1,27 @@
|
||||
#
|
||||
# Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone GMT 0:00 - GMT
|
||||
51
jdk/make/sun/javazic/tzdata/jdk11_backward
Normal file
51
jdk/make/sun/javazic/tzdata/jdk11_backward
Normal file
@ -0,0 +1,51 @@
|
||||
#
|
||||
# Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. Oracle designates this
|
||||
# particular file as subject to the "Classpath" exception as provided
|
||||
# by Oracle in the LICENSE file that accompanied this code.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
# JDK 1.1.x compatible time zone IDs
|
||||
#
|
||||
|
||||
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
|
||||
Rule SystemV min 1973 - Apr lastSun 2:00 1:00 D
|
||||
Rule SystemV min 1973 - Oct lastSun 2:00 0 S
|
||||
Rule SystemV 1974 only - Jan 6 2:00 1:00 D
|
||||
Rule SystemV 1974 only - Nov lastSun 2:00 0 S
|
||||
Rule SystemV 1975 only - Feb 23 2:00 1:00 D
|
||||
Rule SystemV 1975 only - Oct lastSun 2:00 0 S
|
||||
Rule SystemV 1976 max - Apr lastSun 2:00 1:00 D
|
||||
Rule SystemV 1976 max - Oct lastSun 2:00 0 S
|
||||
|
||||
# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
|
||||
Zone SystemV/AST4ADT -4:00 SystemV A%sT
|
||||
Zone SystemV/EST5EDT -5:00 SystemV E%sT
|
||||
Zone SystemV/CST6CDT -6:00 SystemV C%sT
|
||||
Zone SystemV/MST7MDT -7:00 SystemV M%sT
|
||||
Zone SystemV/PST8PDT -8:00 SystemV P%sT
|
||||
Zone SystemV/YST9YDT -9:00 SystemV Y%sT
|
||||
Zone SystemV/AST4 -4:00 - AST
|
||||
Zone SystemV/EST5 -5:00 - EST
|
||||
Zone SystemV/CST6 -6:00 - CST
|
||||
Zone SystemV/MST7 -7:00 - MST
|
||||
Zone SystemV/PST8 -8:00 - PST
|
||||
Zone SystemV/YST9 -9:00 - YST
|
||||
Zone SystemV/HST10 -10:00 - HST
|
||||
@ -43,9 +43,15 @@ BUILD_MANIFEST=true
|
||||
#
|
||||
TZDATA_DIR := ../javazic/tzdata
|
||||
TZDATA_VER := $(subst tzdata,,$(shell $(GREP) '^tzdata' $(TZDATA_DIR)/VERSION))
|
||||
TZFILE := africa antarctica asia australasia europe northamerica southamerica backward etcetera
|
||||
TZFILE := \
|
||||
africa antarctica asia australasia europe northamerica \
|
||||
pacificnew southamerica backward etcetera \
|
||||
gmt jdk11_backward
|
||||
|
||||
TZFILES := $(addprefix $(TZDATA_DIR)/,$(TZFILE))
|
||||
|
||||
|
||||
|
||||
TZDB_JAR = tzdb.jar
|
||||
|
||||
#
|
||||
@ -61,7 +67,7 @@ build: $(LIBDIR)/$(TZDB_JAR)
|
||||
$(LIBDIR)/$(TZDB_JAR): $(TZFILES)
|
||||
$(prep-target)
|
||||
echo build tzdb from version $(TZDATA_VER)
|
||||
$(BOOT_JAVA_CMD) -jar $(BUILDTOOLJARDIR)/tzdb.jar -verbose \
|
||||
$(BOOT_JAVA_CMD) -jar $(BUILDTOOLJARDIR)/tzdb.jar \
|
||||
-version $(TZDATA_VER) -srcdir $(TZDATA_DIR) -dstdir $(LIBDIR) $(TZFILE)
|
||||
|
||||
clean clobber::
|
||||
|
||||
@ -48,7 +48,6 @@ SUBDIRS = \
|
||||
hasher_classes \
|
||||
jarreorder \
|
||||
jarsplit \
|
||||
javazic \
|
||||
jdwpgen \
|
||||
makeclasslist \
|
||||
strip_properties \
|
||||
|
||||
@ -490,11 +490,16 @@ class Zoneinfo {
|
||||
tz.addUsedRec(rrec);
|
||||
usedZone = true;
|
||||
}
|
||||
} else {
|
||||
} else { // fromTime == minTime
|
||||
int save = rrec.getSave();
|
||||
tz.addTransition(fromTime,
|
||||
tz.addTransition(minTime,
|
||||
tz.getOffsetIndex(gmtOffset),
|
||||
tz.getDstOffsetIndex(0));
|
||||
|
||||
tz.addTransition(transition,
|
||||
tz.getOffsetIndex(gmtOffset+save),
|
||||
tz.getDstOffsetIndex(save));
|
||||
|
||||
tz.addUsedRec(rrec);
|
||||
usedZone = true;
|
||||
}
|
||||
|
||||
@ -227,6 +227,7 @@ public final class TzdbZoneRulesCompiler {
|
||||
Map<String, SortedMap<String, ZoneRules>> allBuiltZones = new TreeMap<>();
|
||||
Set<String> allRegionIds = new TreeSet<String>();
|
||||
Set<ZoneRules> allRules = new HashSet<ZoneRules>();
|
||||
Map<String, Map<String, String>> allLinks = new TreeMap<>();
|
||||
|
||||
for (File srcDir : srcDirs) {
|
||||
// source files in this directory
|
||||
@ -242,7 +243,8 @@ public final class TzdbZoneRulesCompiler {
|
||||
}
|
||||
|
||||
// compile
|
||||
String loopVersion = srcDir.getName();
|
||||
String loopVersion = (srcDirs.size() == 1 && version != null)
|
||||
? version : srcDir.getName();
|
||||
TzdbZoneRulesCompiler compiler = new TzdbZoneRulesCompiler(loopVersion, srcFiles, verbose);
|
||||
try {
|
||||
// compile
|
||||
@ -255,12 +257,13 @@ public final class TzdbZoneRulesCompiler {
|
||||
if (verbose) {
|
||||
System.out.println("Outputting file: " + dstFile);
|
||||
}
|
||||
outputFile(dstFile, loopVersion, builtZones);
|
||||
outputFile(dstFile, loopVersion, builtZones, compiler.links);
|
||||
|
||||
// create totals
|
||||
allBuiltZones.put(loopVersion, builtZones);
|
||||
allRegionIds.addAll(builtZones.keySet());
|
||||
allRules.addAll(builtZones.values());
|
||||
allLinks.put(loopVersion, compiler.links);
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Failed: " + ex.toString());
|
||||
ex.printStackTrace();
|
||||
@ -274,7 +277,7 @@ public final class TzdbZoneRulesCompiler {
|
||||
if (verbose) {
|
||||
System.out.println("Outputting combined file: " + dstFile);
|
||||
}
|
||||
outputFile(dstFile, allBuiltZones, allRegionIds, allRules);
|
||||
outputFile(dstFile, allBuiltZones, allRegionIds, allRules, allLinks);
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,12 +286,15 @@ public final class TzdbZoneRulesCompiler {
|
||||
*/
|
||||
private static void outputFile(File dstFile,
|
||||
String version,
|
||||
SortedMap<String, ZoneRules> builtZones) {
|
||||
SortedMap<String, ZoneRules> builtZones,
|
||||
Map<String, String> links) {
|
||||
Map<String, SortedMap<String, ZoneRules>> loopAllBuiltZones = new TreeMap<>();
|
||||
loopAllBuiltZones.put(version, builtZones);
|
||||
Set<String> loopAllRegionIds = new TreeSet<String>(builtZones.keySet());
|
||||
Set<ZoneRules> loopAllRules = new HashSet<ZoneRules>(builtZones.values());
|
||||
outputFile(dstFile, loopAllBuiltZones, loopAllRegionIds, loopAllRules);
|
||||
Map<String, Map<String, String>> loopAllLinks = new TreeMap<>();
|
||||
loopAllLinks.put(version, links);
|
||||
outputFile(dstFile, loopAllBuiltZones, loopAllRegionIds, loopAllRules, loopAllLinks);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,10 +303,10 @@ public final class TzdbZoneRulesCompiler {
|
||||
private static void outputFile(File dstFile,
|
||||
Map<String, SortedMap<String, ZoneRules>> allBuiltZones,
|
||||
Set<String> allRegionIds,
|
||||
Set<ZoneRules> allRules)
|
||||
{
|
||||
Set<ZoneRules> allRules,
|
||||
Map<String, Map<String, String>> allLinks) {
|
||||
try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(dstFile))) {
|
||||
outputTZEntry(jos, allBuiltZones, allRegionIds, allRules);
|
||||
outputTZEntry(jos, allBuiltZones, allRegionIds, allRules, allLinks);
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Failed: " + ex.toString());
|
||||
ex.printStackTrace();
|
||||
@ -314,7 +320,8 @@ public final class TzdbZoneRulesCompiler {
|
||||
private static void outputTZEntry(JarOutputStream jos,
|
||||
Map<String, SortedMap<String, ZoneRules>> allBuiltZones,
|
||||
Set<String> allRegionIds,
|
||||
Set<ZoneRules> allRules) {
|
||||
Set<ZoneRules> allRules,
|
||||
Map<String, Map<String, String>> allLinks) {
|
||||
// this format is not publicly specified
|
||||
try {
|
||||
jos.putNextEntry(new ZipEntry("TZDB.dat"));
|
||||
@ -359,6 +366,16 @@ public final class TzdbZoneRulesCompiler {
|
||||
out.writeShort(rulesIndex);
|
||||
}
|
||||
}
|
||||
// alias-region
|
||||
for (String version : allLinks.keySet()) {
|
||||
out.writeShort(allLinks.get(version).size());
|
||||
for (Map.Entry<String, String> entry : allLinks.get(version).entrySet()) {
|
||||
int aliasIndex = Arrays.binarySearch(regionArray, entry.getKey());
|
||||
int regionIndex = Arrays.binarySearch(regionArray, entry.getValue());
|
||||
out.writeShort(aliasIndex);
|
||||
out.writeShort(regionIndex);
|
||||
}
|
||||
}
|
||||
out.flush();
|
||||
jos.closeEntry();
|
||||
} catch (Exception ex) {
|
||||
@ -621,7 +638,8 @@ public final class TzdbZoneRulesCompiler {
|
||||
private int parseYear(String str, int defaultYear) {
|
||||
if (YEAR.reset(str).matches()) {
|
||||
if (YEAR.group("min") != null) {
|
||||
return YEAR_MIN_VALUE;
|
||||
//return YEAR_MIN_VALUE;
|
||||
return 1900; // systemv has min
|
||||
} else if (YEAR.group("max") != null) {
|
||||
return YEAR_MAX_VALUE;
|
||||
} else if (YEAR.group("only") != null) {
|
||||
@ -742,16 +760,20 @@ public final class TzdbZoneRulesCompiler {
|
||||
if (realRules == null) {
|
||||
throw new IllegalArgumentException("Alias '" + aliasId + "' links to invalid zone '" + realId + "' for '" + version + "'");
|
||||
}
|
||||
links.put(aliasId, realId);
|
||||
|
||||
}
|
||||
builtZones.put(aliasId, realRules);
|
||||
}
|
||||
|
||||
// remove UTC and GMT
|
||||
builtZones.remove("UTC");
|
||||
builtZones.remove("GMT");
|
||||
builtZones.remove("GMT0");
|
||||
//builtZones.remove("UTC");
|
||||
//builtZones.remove("GMT");
|
||||
//builtZones.remove("GMT0");
|
||||
builtZones.remove("GMT+0");
|
||||
builtZones.remove("GMT-0");
|
||||
links.remove("GMT+0");
|
||||
links.remove("GMT-0");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -785,7 +807,6 @@ public final class TzdbZoneRulesCompiler {
|
||||
boolean endOfDay;
|
||||
/** The time of the cutover. */
|
||||
TimeDefinition timeDefinition = TimeDefinition.WALL;
|
||||
|
||||
void adjustToFowards(int year) {
|
||||
if (adjustForwards == false && dayOfMonth > 0) {
|
||||
LocalDate adjustedDate = LocalDate.of(year, month, dayOfMonth).minusDays(6);
|
||||
|
||||
@ -30,7 +30,7 @@ GENDATA_TZDB :=
|
||||
#
|
||||
TZDATA_DIR := $(JDK_TOPDIR)/make/sun/javazic/tzdata
|
||||
TZDATA_VER := $(subst tzdata,,$(shell $(GREP) '^tzdata' $(TZDATA_DIR)/VERSION))
|
||||
TZDATA_TZFILE := africa antarctica asia australasia europe northamerica southamerica backward etcetera
|
||||
TZDATA_TZFILE := africa antarctica asia australasia europe northamerica pacificnew southamerica backward etcetera gmt jdk11_backward
|
||||
TZDATA_TZFILES := $(addprefix $(TZDATA_DIR)/,$(TZDATA_TZFILE))
|
||||
|
||||
GENDATA_TZDB_DST := $(JDK_OUTPUTDIR)/lib
|
||||
@ -39,6 +39,6 @@ GENDATA_TZDB_JAR := tzdb.jar
|
||||
$(GENDATA_TZDB_DST)/$(GENDATA_TZDB_JAR) : $(TZDATA_TZFILES)
|
||||
$(RM) $(GENDATA_TZDB_DST)/$(GENDATA_TZDB_JAR)
|
||||
echo building tzdb from version $(TZDATA_VER)
|
||||
$(TOOL_TZDB) -verbose -version $(TZDATA_VER) -srcdir $(TZDATA_DIR) -dstdir $(GENDATA_TZDB_DST) $(TZDATA_TZFILE)
|
||||
$(TOOL_TZDB) -version $(TZDATA_VER) -srcdir $(TZDATA_DIR) -dstdir $(GENDATA_TZDB_DST) $(TZDATA_TZFILE)
|
||||
|
||||
GENDATA_TZDB += $(GENDATA_TZDB_DST)/$(GENDATA_TZDB_JAR)
|
||||
|
||||
@ -34,7 +34,7 @@ GENDATA_TIMEZONE_TMP := $(JDK_OUTPUTDIR)/gendata_timezone
|
||||
TZFILE0 := \
|
||||
africa antarctica asia australasia europe northamerica \
|
||||
pacificnew southamerica backward \
|
||||
etcetera solar87 solar88 solar89 systemv
|
||||
etcetera systemv
|
||||
|
||||
TZFILE1 := \
|
||||
gmt jdk11_backward
|
||||
|
||||
@ -44,9 +44,6 @@ GENDATA += $(BREAK_ITERATOR)
|
||||
include GendataFontConfig.gmk
|
||||
GENDATA += $(GENDATA_FONT_CONFIG)
|
||||
|
||||
include GendataTimeZone.gmk
|
||||
GENDATA += $(GENDATA_TIMEZONE)
|
||||
|
||||
include GendataTZDB.gmk
|
||||
GENDATA += $(GENDATA_TZDB)
|
||||
|
||||
|
||||
@ -103,9 +103,6 @@ TOOL_HASHER=$(JAVA) -cp $(JDK_OUTPUTDIR)/btclasses \
|
||||
TOOL_JARSPLIT=$(JAVA) -cp $(JDK_OUTPUTDIR)/btclasses \
|
||||
build.tools.jarsplit.JarSplit
|
||||
|
||||
TOOL_JAVAZIC=$(JAVA) -cp $(JDK_OUTPUTDIR)/btclasses \
|
||||
build.tools.javazic.Main
|
||||
|
||||
TOOL_TZDB=$(JAVA) -cp $(JDK_OUTPUTDIR)/btclasses \
|
||||
build.tools.tzdb.TzdbZoneRulesCompiler
|
||||
|
||||
|
||||
@ -30,6 +30,8 @@ import java.awt.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.print.*;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import javax.print.*;
|
||||
import javax.print.attribute.PrintRequestAttributeSet;
|
||||
@ -47,6 +49,8 @@ public class CPrinterJob extends RasterPrinterJob {
|
||||
|
||||
private static String sShouldNotReachHere = "Should not reach here.";
|
||||
|
||||
private volatile SecondaryLoop printingLoop;
|
||||
|
||||
private boolean noDefaultPrinter = false;
|
||||
|
||||
private static Font defaultFont;
|
||||
@ -160,11 +164,22 @@ public class CPrinterJob extends RasterPrinterJob {
|
||||
|
||||
volatile boolean onEventThread;
|
||||
|
||||
@Override
|
||||
protected void cancelDoc() throws PrinterAbortException {
|
||||
super.cancelDoc();
|
||||
if (printingLoop != null) {
|
||||
printingLoop.exit();
|
||||
}
|
||||
}
|
||||
|
||||
private void completePrintLoop() {
|
||||
Runnable r = new Runnable() { public void run() {
|
||||
synchronized(this) {
|
||||
performingPrinting = false;
|
||||
}
|
||||
if (printingLoop != null) {
|
||||
printingLoop.exit();
|
||||
}
|
||||
}};
|
||||
|
||||
if (onEventThread) {
|
||||
@ -219,17 +234,21 @@ public class CPrinterJob extends RasterPrinterJob {
|
||||
|
||||
onEventThread = true;
|
||||
|
||||
printingLoop = AccessController.doPrivileged(new PrivilegedAction<SecondaryLoop>() {
|
||||
@Override
|
||||
public SecondaryLoop run() {
|
||||
return Toolkit.getDefaultToolkit()
|
||||
.getSystemEventQueue()
|
||||
.createSecondaryLoop();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
// Fire off the print rendering loop on the AppKit thread, and don't have
|
||||
// it wait and block this thread.
|
||||
if (printLoop(false, firstPage, lastPage)) {
|
||||
// Fire off the EventConditional that will what until the condition is met,
|
||||
// but will still process AWTEvent's as they occur.
|
||||
new EventDispatchAccess() {
|
||||
public boolean evaluate() {
|
||||
return performingPrinting;
|
||||
}
|
||||
}.pumpEventsAndWait();
|
||||
// Start a secondary loop on EDT until printing operation is finished or cancelled
|
||||
printingLoop.enter();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@ -253,6 +272,9 @@ public class CPrinterJob extends RasterPrinterJob {
|
||||
performingPrinting = false;
|
||||
notify();
|
||||
}
|
||||
if (printingLoop != null) {
|
||||
printingLoop.exit();
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize the collated, # copies, numPages, first/last pages. Need to
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
#
|
||||
# This properties file is used to initialize the default
|
||||
# java.awt.datatransfer.SystemFlavorMap. It contains the X11 platform-specific,
|
||||
# default mappings between common X11 selection atoms and platform-independent
|
||||
# java.awt.datatransfer.SystemFlavorMap. It contains the Mac OS X platform-specific,
|
||||
# default mappings between common Mac OS X selection atoms and platform-independent
|
||||
# MIME type strings, which will be converted into
|
||||
# java.awt.datatransfer.DataFlavors.
|
||||
#
|
||||
@ -76,3 +76,5 @@ FILE_NAME=application/x-java-file-list;class=java.util.List
|
||||
text/uri-list=application/x-java-file-list;class=java.util.List
|
||||
PNG=image/x-java-image;class=java.awt.Image
|
||||
JFIF=image/x-java-image;class=java.awt.Image
|
||||
RICH_TEXT=text/rtf
|
||||
HTML=text/html;charset=utf-8;eoln="\r\n";terminators=1
|
||||
|
||||
@ -34,7 +34,7 @@ JNIEXPORT jlong JNICALL Java_com_apple_jobjc_SEL_getSelectorPtr
|
||||
const char *selNameAsChars = (*env)->GetStringUTFChars(env, selName, JNI_FALSE);
|
||||
const SEL sel = sel_registerName(selNameAsChars);
|
||||
(*env)->ReleaseStringUTFChars(env, selName, selNameAsChars);
|
||||
return ptr_to_jlong(sel);
|
||||
return ptr_to_jlong((void*)sel);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_com_apple_jobjc_SEL_getSelectorName
|
||||
|
||||
@ -383,31 +383,6 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_EventDispatchAccess
|
||||
* Method: pumpEventsAndWait
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_EventDispatchAccess_pumpEventsAndWait
|
||||
(JNIEnv *env, jobject eda)
|
||||
{
|
||||
static JNF_CLASS_CACHE(jc_Thread, "java/lang/Thread");
|
||||
static JNF_STATIC_MEMBER_CACHE(jm_currentThread, jc_Thread, "currentThread", "()Ljava/lang/Thread;");
|
||||
static JNF_CLASS_CACHE(jc_EventDispatchThread, "java/awt/EventDispatchThread");
|
||||
static JNF_MEMBER_CACHE(jm_macosxGetConditional, jc_EventDispatchThread, "_macosxGetConditional", "(Ljava/lang/Object;)Ljava/awt/Conditional;");
|
||||
static JNF_MEMBER_CACHE(jm_pumpEvents, jc_EventDispatchThread, "pumpEvents", "(Ljava/awt/Conditional;)V");
|
||||
|
||||
JNF_COCOA_DURING(env);
|
||||
|
||||
jobject thread = JNFCallStaticObjectMethod(env, jm_currentThread);
|
||||
jobject conditional = JNFCallObjectMethod(env, thread, jm_macosxGetConditional, eda);
|
||||
if (conditional != NULL) {
|
||||
JNFCallVoidMethod(env, thread, jm_pumpEvents, conditional);
|
||||
}
|
||||
|
||||
JNF_COCOA_HANDLE(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CPrinterJob
|
||||
* Method: abortDoc
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -106,8 +106,9 @@ inflate_file(int fd, zentry *entry, int *size_out)
|
||||
*size_out = (int)entry->isize;
|
||||
}
|
||||
return (out);
|
||||
} else
|
||||
return (NULL);
|
||||
}
|
||||
free(in);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static jboolean zip64_present = JNI_FALSE;
|
||||
@ -563,7 +564,7 @@ JLI_ParseManifest(char *jarfile, manifest_info *info)
|
||||
|
||||
if ((fd = open(jarfile, O_RDONLY
|
||||
#ifdef O_LARGEFILE
|
||||
| O_LARGEFILE /* large file mode on solaris */
|
||||
| O_LARGEFILE /* large file mode */
|
||||
#endif
|
||||
#ifdef O_BINARY
|
||||
| O_BINARY /* use binary mode on windows */
|
||||
@ -618,6 +619,9 @@ JLI_JarUnpackFile(const char *jarfile, const char *filename, int *size) {
|
||||
void *data = NULL;
|
||||
|
||||
fd = open(jarfile, O_RDONLY
|
||||
#ifdef O_LARGEFILE
|
||||
| O_LARGEFILE /* large file mode */
|
||||
#endif
|
||||
#ifdef O_BINARY
|
||||
| O_BINARY /* use binary mode on windows */
|
||||
#endif
|
||||
@ -661,6 +665,9 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data)
|
||||
int rc;
|
||||
|
||||
if ((fd = open(jarfile, O_RDONLY
|
||||
#ifdef O_LARGEFILE
|
||||
| O_LARGEFILE /* large file mode */
|
||||
#endif
|
||||
#ifdef O_BINARY
|
||||
| O_BINARY /* use binary mode on windows */
|
||||
#endif
|
||||
|
||||
@ -52,16 +52,19 @@ import sun.misc.HexDumpEncoder;
|
||||
* principal set and private credentials set are updated only when
|
||||
* <code>commit</code> is called.
|
||||
* When <code>commit</code> is called, the <code>KerberosPrincipal</code>
|
||||
* is added to the <code>Subject</code>'s
|
||||
* principal set and <code>KerberosTicket</code> is
|
||||
* is added to the <code>Subject</code>'s principal set (unless the
|
||||
* <code>principal</code> is specified as "*"). If <code>isInitiator</code>
|
||||
* is true, the <code>KerberosTicket</code> is
|
||||
* added to the <code>Subject</code>'s private credentials.
|
||||
*
|
||||
* <p> If the configuration entry for <code>KerberosLoginModule</code>
|
||||
* has the option <code>storeKey</code> set to true, then
|
||||
* <code>KerberosKey</code> will also be added to the
|
||||
* <code>KerberosKey</code> or <code>KeyTab</code> will also be added to the
|
||||
* subject's private credentials. <code>KerberosKey</code>, the principal's
|
||||
* key will be either obtained from the keytab or
|
||||
* derived from user's password.
|
||||
* key(s) will be derived from user's password, and <code>KeyTab</code> is
|
||||
* the keytab used when <code>useKeyTab</code> is set to true. The
|
||||
* <code>KeyTab</code> object is restricted to be used by the specified
|
||||
* principal unless the principal value is "*".
|
||||
*
|
||||
* <p> This <code>LoginModule</code> recognizes the <code>doNotPrompt</code>
|
||||
* option. If set to true the user will not be prompted for the password.
|
||||
@ -75,8 +78,8 @@ import sun.misc.HexDumpEncoder;
|
||||
*
|
||||
* <p> The principal name can be specified in the configuration entry
|
||||
* by using the option <code>principal</code>. The principal name
|
||||
* can either be a simple user name or a service name such as
|
||||
* <code>host/mission.eng.sun.com</code>. The principal can also
|
||||
* can either be a simple user name, a service name such as
|
||||
* <code>host/mission.eng.sun.com</code>, or "*". The principal can also
|
||||
* be set using the system property <code>sun.security.krb5.principal</code>.
|
||||
* This property is checked during login. If this property is not set, then
|
||||
* the principal name from the configuration is used. In the
|
||||
@ -87,11 +90,10 @@ import sun.misc.HexDumpEncoder;
|
||||
*
|
||||
* <p> The following is a list of configuration options supported
|
||||
* for <code>Krb5LoginModule</code>:
|
||||
* <dl>
|
||||
* <blockquote><dt><b><code>refreshKrb5Config</code></b>:</dt>
|
||||
* <blockquote><dl>
|
||||
* <dt><b><code>refreshKrb5Config</code></b>:</dt>
|
||||
* <dd> Set this to true, if you want the configuration
|
||||
* to be refreshed before the <code>login</code> method is called.</dd>
|
||||
* <P>
|
||||
* <dt><b><code>useTicketCache</code></b>:</dt>
|
||||
* <dd>Set this to true, if you want the
|
||||
* TGT to be obtained
|
||||
@ -112,19 +114,16 @@ import sun.misc.HexDumpEncoder;
|
||||
* <code>ticketCache</code>.
|
||||
* For Windows, if a ticket cannot be retrieved from the file ticket cache,
|
||||
* it will use Local Security Authority (LSA) API to get the TGT.
|
||||
* <P>
|
||||
* <dt><b><code>ticketCache</code></b>:</dt>
|
||||
* <dd>Set this to the name of the ticket
|
||||
* cache that contains user's TGT.
|
||||
* If this is set, <code>useTicketCache</code>
|
||||
* must also be set to true; Otherwise a configuration error will
|
||||
* be returned.</dd>
|
||||
* <P>
|
||||
* <dt><b><code>renewTGT</code></b>:</dt>
|
||||
* <dd>Set this to true, if you want to renew
|
||||
* the TGT. If this is set, <code>useTicketCache</code> must also be
|
||||
* set to true; otherwise a configuration error will be returned.</dd>
|
||||
* <p>
|
||||
* <dt><b><code>doNotPrompt</code></b>:</dt>
|
||||
* <dd>Set this to true if you do not want to be
|
||||
* prompted for the password
|
||||
@ -132,7 +131,6 @@ import sun.misc.HexDumpEncoder;
|
||||
* or through shared state.(Default is false)
|
||||
* If set to true, credential must be obtained through cache, keytab,
|
||||
* or shared state. Otherwise, authentication will fail.</dd>
|
||||
* <P>
|
||||
* <dt><b><code>useKeyTab</code></b>:</dt>
|
||||
* <dd>Set this to true if you
|
||||
* want the module to get the principal's key from the
|
||||
@ -144,15 +142,15 @@ import sun.misc.HexDumpEncoder;
|
||||
* If it is not specified in the Kerberos configuration file
|
||||
* then it will look for the file
|
||||
* <code>{user.home}{file.separator}</code>krb5.keytab.</dd>
|
||||
* <P>
|
||||
* <dt><b><code>keyTab</code></b>:</dt>
|
||||
* <dd>Set this to the file name of the
|
||||
* keytab to get principal's secret key.</dd>
|
||||
* <P>
|
||||
* <dt><b><code>storeKey</code></b>:</dt>
|
||||
* <dd>Set this to true to if you want the
|
||||
* principal's key to be stored in the Subject's private credentials. </dd>
|
||||
* <p>
|
||||
* <dd>Set this to true to if you want the keytab or the
|
||||
* principal's key to be stored in the Subject's private credentials.
|
||||
* For <code>isInitiator</code> being false, if <code>principal</code>
|
||||
* is "*", the {@link KeyTab} stored can be used by anyone, otherwise,
|
||||
* it's restricted to be used by the specified principal only.</dd>
|
||||
* <dt><b><code>principal</code></b>:</dt>
|
||||
* <dd>The name of the principal that should
|
||||
* be used. The principal can be a simple username such as
|
||||
@ -165,8 +163,13 @@ import sun.misc.HexDumpEncoder;
|
||||
* <code>sun.security.krb5.principal</code>. In addition, if this
|
||||
* system property is defined, then it will be used. If this property
|
||||
* is not set, then the principal name from the configuration will be
|
||||
* used.</dd>
|
||||
* <P>
|
||||
* used.
|
||||
* The principal name can be set to "*" when <code>isInitiator</code> is false.
|
||||
* In this case, the acceptor is not bound to a single principal. It can
|
||||
* act as any principal an initiator requests if keys for that principal
|
||||
* can be found. When <code>isInitiator</code> is true, the principal name
|
||||
* cannot be set to "*".
|
||||
* </dd>
|
||||
* <dt><b><code>isInitiator</code></b>:</dt>
|
||||
* <dd>Set this to true, if initiator. Set this to false, if acceptor only.
|
||||
* (Default is true).
|
||||
@ -177,18 +180,20 @@ import sun.misc.HexDumpEncoder;
|
||||
* <code>Configuration</code>
|
||||
* options that enable you to share username and passwords across different
|
||||
* authentication modules:
|
||||
* <pre>
|
||||
* <blockquote><dl>
|
||||
*
|
||||
* useFirstPass if, true, this LoginModule retrieves the
|
||||
* <dt><b><code>useFirstPass</code></b>:</dt>
|
||||
* <dd>if, true, this LoginModule retrieves the
|
||||
* username and password from the module's shared state,
|
||||
* using "javax.security.auth.login.name" and
|
||||
* "javax.security.auth.login.password" as the respective
|
||||
* keys. The retrieved values are used for authentication.
|
||||
* If authentication fails, no attempt for a retry
|
||||
* is made, and the failure is reported back to the
|
||||
* calling application.
|
||||
* calling application.</dd>
|
||||
*
|
||||
* tryFirstPass if, true, this LoginModule retrieves the
|
||||
* <dt><b><code>tryFirstPass</code></b>:</dt>
|
||||
* <dd>if, true, this LoginModule retrieves the
|
||||
* the username and password from the module's shared
|
||||
* state using "javax.security.auth.login.name" and
|
||||
* "javax.security.auth.login.password" as the respective
|
||||
@ -198,26 +203,28 @@ import sun.misc.HexDumpEncoder;
|
||||
* CallbackHandler to retrieve a new username
|
||||
* and password, and another attempt to authenticate
|
||||
* is made. If the authentication fails,
|
||||
* the failure is reported back to the calling application
|
||||
* the failure is reported back to the calling application</dd>
|
||||
*
|
||||
* storePass if, true, this LoginModule stores the username and
|
||||
* <dt><b><code>storePass</code></b>:</dt>
|
||||
* <dd>if, true, this LoginModule stores the username and
|
||||
* password obtained from the CallbackHandler in the
|
||||
* modules shared state, using
|
||||
* "javax.security.auth.login.name" and
|
||||
* "javax.security.auth.login.password" as the respective
|
||||
* keys. This is not performed if existing values already
|
||||
* exist for the username and password in the shared
|
||||
* state, or if authentication fails.
|
||||
* state, or if authentication fails.</dd>
|
||||
*
|
||||
* clearPass if, true, this LoginModule clears the
|
||||
* <dt><b><code>clearPass</code></b>:</dt>
|
||||
* <dd>if, true, this LoginModule clears the
|
||||
* username and password stored in the module's shared
|
||||
* state after both phases of authentication
|
||||
* (login and commit) have completed.
|
||||
* </pre>
|
||||
* (login and commit) have completed.</dd>
|
||||
* </dl></blockquote>
|
||||
* <p>If the principal system property or key is already provided, the value of
|
||||
* "javax.security.auth.login.name" in the shared state is ignored.
|
||||
* <p>When multiple mechanisms to retrieve a ticket or key is provided, the
|
||||
* preference order looks like this:
|
||||
* preference order is:
|
||||
* <ol>
|
||||
* <li>ticket cache
|
||||
* <li>keytab
|
||||
@ -225,7 +232,7 @@ import sun.misc.HexDumpEncoder;
|
||||
* <li>user prompt
|
||||
* </ol>
|
||||
* <p>Note that if any step fails, it will fallback to the next step.
|
||||
* There's only one exception, it the shared state step fails and
|
||||
* There's only one exception, if the shared state step fails and
|
||||
* <code>useFirstPass</code>=true, no user prompt is made.
|
||||
* <p>Examples of some configuration values for Krb5LoginModule in
|
||||
* JAAS config file and the results are:
|
||||
@ -318,7 +325,7 @@ import sun.misc.HexDumpEncoder;
|
||||
* <p> <code>useKeyTab</code> = true
|
||||
* <code>keyTab</code>=<keytabname>
|
||||
* <code>storeKey</code>=true
|
||||
* <code>doNotPrompt</code>=true;
|
||||
* <code>doNotPrompt</code>=false;
|
||||
*</ul>
|
||||
* <p>The user will be prompted for the service principal name.
|
||||
* If the principal's
|
||||
@ -328,6 +335,14 @@ import sun.misc.HexDumpEncoder;
|
||||
* If successful the TGT will be added to the
|
||||
* Subject's private credentials set. Otherwise the authentication will
|
||||
* fail.
|
||||
* <ul>
|
||||
* <p> <code>isInitiator</code> = false <code>useKeyTab</code> = true
|
||||
* <code>keyTab</code>=<keytabname>
|
||||
* <code>storeKey</code>=true
|
||||
* <code>principal</code>=*;
|
||||
*</ul>
|
||||
* <p>The acceptor will be an unbound acceptor and it can act as any principal
|
||||
* as long that principal has keys in the keytab.
|
||||
*<ul>
|
||||
* <p>
|
||||
* <code>useTicketCache</code>=true
|
||||
@ -409,6 +424,7 @@ public class Krb5LoginModule implements LoginModule {
|
||||
private KerberosTicket kerbTicket = null;
|
||||
private KerberosKey[] kerbKeys = null;
|
||||
private StringBuffer krb5PrincName = null;
|
||||
private boolean unboundServer = false;
|
||||
private char[] password = null;
|
||||
|
||||
private static final String NAME = "javax.security.auth.login.name";
|
||||
@ -520,8 +536,6 @@ public class Krb5LoginModule implements LoginModule {
|
||||
*/
|
||||
public boolean login() throws LoginException {
|
||||
|
||||
int len;
|
||||
validateConfiguration();
|
||||
if (refreshKrb5Config) {
|
||||
try {
|
||||
if (debug) {
|
||||
@ -544,6 +558,12 @@ public class Krb5LoginModule implements LoginModule {
|
||||
}
|
||||
}
|
||||
|
||||
validateConfiguration();
|
||||
|
||||
if (krb5PrincName != null && krb5PrincName.toString().equals("*")) {
|
||||
unboundServer = true;
|
||||
}
|
||||
|
||||
if (tryFirstPass) {
|
||||
try {
|
||||
attemptAuthentication(true);
|
||||
@ -698,9 +718,17 @@ public class Krb5LoginModule implements LoginModule {
|
||||
* (encKeys == null) to check.
|
||||
*/
|
||||
if (useKeyTab) {
|
||||
ktab = (keyTabName == null)
|
||||
? KeyTab.getInstance()
|
||||
: KeyTab.getInstance(new File(keyTabName));
|
||||
if (!unboundServer) {
|
||||
KerberosPrincipal kp =
|
||||
new KerberosPrincipal(principal.getName());
|
||||
ktab = (keyTabName == null)
|
||||
? KeyTab.getInstance(kp)
|
||||
: KeyTab.getInstance(kp, new File(keyTabName));
|
||||
} else {
|
||||
ktab = (keyTabName == null)
|
||||
? KeyTab.getUnboundInstance()
|
||||
: KeyTab.getUnboundInstance(new File(keyTabName));
|
||||
}
|
||||
if (isInitiator) {
|
||||
if (Krb5Util.keysFromJavaxKeyTab(ktab, principal).length
|
||||
== 0) {
|
||||
@ -939,6 +967,13 @@ public class Krb5LoginModule implements LoginModule {
|
||||
("Configuration Error"
|
||||
+ " - either useTicketCache should be "
|
||||
+ " true or renewTGT should be false");
|
||||
if (krb5PrincName != null && krb5PrincName.toString().equals("*")) {
|
||||
if (isInitiator) {
|
||||
throw new LoginException
|
||||
("Configuration Error"
|
||||
+ " - principal cannot be * when isInitiator is true");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCurrent(Credentials creds)
|
||||
@ -1052,7 +1087,10 @@ public class Krb5LoginModule implements LoginModule {
|
||||
}
|
||||
// Let us add the kerbClientPrinc,kerbTicket and KeyTab/KerbKey (if
|
||||
// storeKey is true)
|
||||
if (!princSet.contains(kerbClientPrinc)) {
|
||||
|
||||
// We won't add "*" as a KerberosPrincipal
|
||||
if (!unboundServer &&
|
||||
!princSet.contains(kerbClientPrinc)) {
|
||||
princSet.add(kerbClientPrinc);
|
||||
}
|
||||
|
||||
|
||||
@ -138,8 +138,7 @@ public final class Client extends NTLM {
|
||||
domain = domainFromServer;
|
||||
}
|
||||
if (domain == null) {
|
||||
throw new NTLMException(NTLMException.NO_DOMAIN_INFO,
|
||||
"No domain info");
|
||||
domain = "";
|
||||
}
|
||||
|
||||
int flags = 0x88200 | (inputFlags & 3);
|
||||
|
||||
@ -136,10 +136,10 @@ class NTLM {
|
||||
|
||||
int readInt(int offset) throws NTLMException {
|
||||
try {
|
||||
return internal[offset] & 0xff +
|
||||
(internal[offset+1] & 0xff << 8) +
|
||||
(internal[offset+2] & 0xff << 16) +
|
||||
(internal[offset+3] & 0xff << 24);
|
||||
return (internal[offset] & 0xff) +
|
||||
((internal[offset+1] & 0xff) << 8) +
|
||||
((internal[offset+2] & 0xff) << 16) +
|
||||
((internal[offset+3] & 0xff) << 24);
|
||||
} catch (ArrayIndexOutOfBoundsException ex) {
|
||||
throw new NTLMException(NTLMException.PACKET_READ_ERROR,
|
||||
"Input message incorrect size");
|
||||
@ -148,8 +148,8 @@ class NTLM {
|
||||
|
||||
int readShort(int offset) throws NTLMException {
|
||||
try {
|
||||
return internal[offset] & 0xff +
|
||||
(internal[offset+1] & 0xff << 8);
|
||||
return (internal[offset] & 0xff) +
|
||||
((internal[offset+1] & 0xff << 8));
|
||||
} catch (ArrayIndexOutOfBoundsException ex) {
|
||||
throw new NTLMException(NTLMException.PACKET_READ_ERROR,
|
||||
"Input message incorrect size");
|
||||
|
||||
@ -107,34 +107,6 @@ class EventDispatchThread extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
// MacOSX change:
|
||||
// This was added because this class (and java.awt.Conditional) are package private.
|
||||
// There are certain instances where classes in other packages need to block the
|
||||
// AWTEventQueue while still allowing it to process events. This uses reflection
|
||||
// to call back into the caller in order to remove dependencies.
|
||||
//
|
||||
// NOTE: This uses reflection in its implementation, so it is not for performance critical code.
|
||||
//
|
||||
// cond is an instance of sun.lwawt.macosx.EventDispatchAccess
|
||||
//
|
||||
private Conditional _macosxGetConditional(final Object cond) {
|
||||
try {
|
||||
return new Conditional() {
|
||||
final Method evaluateMethod = Class.forName("sun.lwawt.macosx.EventDispatchAccess").getMethod("evaluate", null);
|
||||
public boolean evaluate() {
|
||||
try {
|
||||
return ((Boolean)evaluateMethod.invoke(cond, null)).booleanValue();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
} catch (Exception e) {
|
||||
return new Conditional() { public boolean evaluate() { return false; } };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void pumpEvents(Conditional cond) {
|
||||
pumpEvents(ANY_EVENT, cond);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,7 +34,7 @@ import java.io.IOException;
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Closeable extends AutoCloseable {
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,6 +35,7 @@ package java.io;
|
||||
*
|
||||
* @since 1.2
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface FileFilter {
|
||||
|
||||
/**
|
||||
@ -46,5 +47,4 @@ public interface FileFilter {
|
||||
* should be included
|
||||
*/
|
||||
boolean accept(File pathname);
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,8 +39,8 @@ package java.io;
|
||||
* @see java.io.File#list(java.io.FilenameFilter)
|
||||
* @since JDK1.0
|
||||
*/
|
||||
public
|
||||
interface FilenameFilter {
|
||||
@FunctionalInterface
|
||||
public interface FilenameFilter {
|
||||
/**
|
||||
* Tests if a specified file should be included in a file list.
|
||||
*
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,7 +34,7 @@ import java.io.IOException;
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Flushable {
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -31,6 +31,7 @@ package java.lang;
|
||||
* @author Josh Bloch
|
||||
* @since 1.7
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface AutoCloseable {
|
||||
/**
|
||||
* Closes this resource, relinquishing any underlying resources.
|
||||
|
||||
@ -3087,7 +3087,8 @@ public final
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
public <A extends Annotation> A[] getAnnotations(Class<A> annotationClass) {
|
||||
@Override
|
||||
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
|
||||
initAnnotationsIfNecessary();
|
||||
@ -3106,6 +3107,7 @@ public final
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
@ -3118,7 +3120,8 @@ public final
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
public <A extends Annotation> A[] getDeclaredAnnotations(Class<A> annotationClass) {
|
||||
@Override
|
||||
public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
|
||||
initAnnotationsIfNecessary();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -93,7 +93,7 @@ import java.util.*;
|
||||
* @see java.util.Comparator
|
||||
* @since 1.2
|
||||
*/
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Comparable<T> {
|
||||
/**
|
||||
* Compares this object with the specified object for order. Returns a
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,6 +35,7 @@ import java.util.Iterator;
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Iterable<T> {
|
||||
|
||||
/**
|
||||
|
||||
@ -389,8 +389,9 @@ public class Package implements java.lang.reflect.AnnotatedElement {
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
public <A extends Annotation> A[] getAnnotations(Class<A> annotationClass) {
|
||||
return getPackageInfo().getAnnotations(annotationClass);
|
||||
@Override
|
||||
public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationClass) {
|
||||
return getPackageInfo().getAnnotationsByType(annotationClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -404,6 +405,7 @@ public class Package implements java.lang.reflect.AnnotatedElement {
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
@Override
|
||||
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
|
||||
return getPackageInfo().getDeclaredAnnotation(annotationClass);
|
||||
}
|
||||
@ -412,8 +414,9 @@ public class Package implements java.lang.reflect.AnnotatedElement {
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
public <A extends Annotation> A[] getDeclaredAnnotations(Class<A> annotationClass) {
|
||||
return getPackageInfo().getDeclaredAnnotations(annotationClass);
|
||||
@Override
|
||||
public <A extends Annotation> A[] getDeclaredAnnotationsByType(Class<A> annotationClass) {
|
||||
return getPackageInfo().getDeclaredAnnotationsByType(annotationClass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,7 +34,7 @@ import java.io.IOException;
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Readable {
|
||||
|
||||
/**
|
||||
@ -51,5 +51,4 @@ public interface Readable {
|
||||
* @throws java.nio.ReadOnlyBufferException if cb is a read only buffer
|
||||
*/
|
||||
public int read(java.nio.CharBuffer cb) throws IOException;
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -52,8 +52,8 @@ package java.lang;
|
||||
* @see java.util.concurrent.Callable
|
||||
* @since JDK1.0
|
||||
*/
|
||||
public
|
||||
interface Runnable {
|
||||
@FunctionalInterface
|
||||
public interface Runnable {
|
||||
/**
|
||||
* When an object implementing interface <code>Runnable</code> is used
|
||||
* to create a thread, starting the thread causes the object's
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1851,6 +1851,7 @@ class Thread implements Runnable {
|
||||
* @see ThreadGroup#uncaughtException
|
||||
* @since 1.5
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface UncaughtExceptionHandler {
|
||||
/**
|
||||
* Method invoked when the given thread terminates due to the
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -184,7 +184,8 @@ public class AccessibleObject implements AnnotatedElement {
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
|
||||
@Override
|
||||
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
|
||||
throw new AssertionError("All subclasses should override this method");
|
||||
}
|
||||
|
||||
@ -199,6 +200,7 @@ public class AccessibleObject implements AnnotatedElement {
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
@Override
|
||||
public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
|
||||
// Only annotations on classes are inherited, for all other
|
||||
// objects getDeclaredAnnotation is the same as
|
||||
@ -210,11 +212,12 @@ public class AccessibleObject implements AnnotatedElement {
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
|
||||
@Override
|
||||
public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
|
||||
// Only annotations on classes are inherited, for all other
|
||||
// objects getDeclaredAnnotations is the same as
|
||||
// getAnnotations.
|
||||
return getAnnotations(annotationClass);
|
||||
// objects getDeclaredAnnotationsByType is the same as
|
||||
// getAnnotationsByType.
|
||||
return getAnnotationsByType(annotationClass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -35,22 +35,43 @@ import java.lang.annotation.Annotation;
|
||||
* arrays returned by accessors for array-valued enum members; it will
|
||||
* have no affect on the arrays returned to other callers.
|
||||
*
|
||||
* <p>An annotation A is <em>directly present</em> on an element E if the
|
||||
* RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations attribute
|
||||
* associated with E either:
|
||||
* <p>The {@link #getAnnotationsByType(Class)} and {@link
|
||||
* #getDeclaredAnnotationsByType(Class)} methods support multiple
|
||||
* annotations of the same type on an element. If the argument to either method
|
||||
* is a repeatable annotation type (JLS 9.6), then the method will "look
|
||||
* through" a container annotation (JLS 9.7) which was generated at
|
||||
* compile-time to wrap multiple annotations of the argument type.
|
||||
*
|
||||
* <p>The terms <em>directly present</em> and <em>present</em> are used
|
||||
* throughout this interface to describe precisely which annotations are
|
||||
* returned by methods:
|
||||
*
|
||||
* <ul>
|
||||
* <li>contains A; or
|
||||
* <li>for invocations of get[Declared]Annotations(Class<T>),
|
||||
* contains A or exactly one annotation C whose type is the containing
|
||||
* annotation type of A's type (JLS 9.6) and whose value element contains A
|
||||
* <li>An annotation A is <em>directly present</em> on an element E if E is
|
||||
* associated with a RuntimeVisibleAnnotations or
|
||||
* RuntimeVisibleParameterAnnotations attribute, and:
|
||||
*
|
||||
* <ul>
|
||||
* <li>for an invocation of {@code get[Declared]Annotation(Class<T>)} or
|
||||
* {@code get[Declared]Annotations()}, the attribute contains A.
|
||||
*
|
||||
* <li>for an invocation of {@code get[Declared]AnnotationsByType(Class<T>)}, the
|
||||
* attribute either contains A or, if the type of A is repeatable, contains
|
||||
* exactly one annotation whose value element contains A and whose type is the
|
||||
* containing annotation type of A's type (JLS 9.6).
|
||||
* </ul>
|
||||
*
|
||||
* <p>An annotation A is <em>present</em> on an element E if either:
|
||||
* <p>
|
||||
* <li>An annotation A is <em>present</em> on an element E if either:
|
||||
*
|
||||
* <ul>
|
||||
* <li>A is <em>directly present</em> on E; or
|
||||
* <li>There are no annotations of A's type which are <em>directly present</em>
|
||||
* on E, and E is a class, and A's type is inheritable (JLS 9.6.3.3), and A is
|
||||
* present on the superclass of E
|
||||
*
|
||||
* <li>A is not <em>directly present</em> on E, and E is a class, and A's type
|
||||
* is inheritable (JLS 9.6.3.3), and A is <em>present</em> on the superclass of
|
||||
* E.
|
||||
* </ul>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <p>If an annotation returned by a method in this interface contains
|
||||
@ -119,12 +140,19 @@ public interface AnnotatedElement {
|
||||
<T extends Annotation> T getAnnotation(Class<T> annotationClass);
|
||||
|
||||
/**
|
||||
* Returns an array of all this element's annotations for the
|
||||
* specified type if one or more of such annotation is present,
|
||||
* else an array of length zero.
|
||||
* Returns annotations that are <em>present</em> on this element.
|
||||
*
|
||||
* The caller of this method is free to modify the returned array;
|
||||
* it will have no effect on the arrays returned to other callers.
|
||||
* If there are no annotations <em>present</em> on this element, the return
|
||||
* value is an array of length 0.
|
||||
*
|
||||
* The difference between this method and {@link #getAnnotation(Class)}
|
||||
* is that this method detects if its argument is a <em>repeatable
|
||||
* annotation type</em> (JLS 9.6), and if so, attempts to find one or
|
||||
* more annotations of that type by "looking through" a container
|
||||
* annotation.
|
||||
*
|
||||
* The caller of this method is free to modify the returned array; it will
|
||||
* have no effect on the arrays returned to other callers.
|
||||
*
|
||||
* @param annotationClass the Class object corresponding to the
|
||||
* annotation type
|
||||
@ -133,7 +161,7 @@ public interface AnnotatedElement {
|
||||
* @throws NullPointerException if the given annotation class is null
|
||||
* @since 1.8
|
||||
*/
|
||||
<T extends Annotation> T[] getAnnotations(Class<T> annotationClass);
|
||||
<T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass);
|
||||
|
||||
/**
|
||||
* Returns annotations that are <em>present</em> on this element.
|
||||
@ -165,16 +193,21 @@ public interface AnnotatedElement {
|
||||
*/
|
||||
<T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass);
|
||||
|
||||
/**
|
||||
* Returns an array of all this element's annotations for the
|
||||
* specified type if one or more of such annotation is directly
|
||||
* present, else an array of length zero.
|
||||
/**
|
||||
* Returns annotations that are <em>directly present</em> on this element.
|
||||
* This method ignores inherited annotations.
|
||||
*
|
||||
* This method ignores inherited annotations. (Returns
|
||||
* an array of length zero if no annotations are directly present
|
||||
* on this element.) The caller of this method is free to modify
|
||||
* the returned array; it will have no effect on the arrays
|
||||
* returned to other callers.
|
||||
* If there are no annotations <em>directly present</em> on this element,
|
||||
* the return value is an array of length 0.
|
||||
*
|
||||
* The difference between this method and {@link
|
||||
* #getDeclaredAnnotation(Class)} is that this method detects if its
|
||||
* argument is a <em>repeatable annotation type</em> (JLS 9.6), and if so,
|
||||
* attempts to find one or more annotations of that type by "looking
|
||||
* through" a container annotation.
|
||||
*
|
||||
* The caller of this method is free to modify the returned array; it will
|
||||
* have no effect on the arrays returned to other callers.
|
||||
*
|
||||
* @param annotationClass the Class object corresponding to the
|
||||
* annotation type
|
||||
@ -183,7 +216,7 @@ public interface AnnotatedElement {
|
||||
* @throws NullPointerException if the given annotation class is null
|
||||
* @since 1.8
|
||||
*/
|
||||
<T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass);
|
||||
<T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass);
|
||||
|
||||
/**
|
||||
* Returns annotations that are <em>directly present</em> on this element.
|
||||
|
||||
@ -278,6 +278,10 @@ public abstract class Executable extends AccessibleObject
|
||||
* this object. Returns an array of length 0 if the executable
|
||||
* has no parameters.
|
||||
*
|
||||
* The parameters of the underlying executable do not necessarily
|
||||
* have unique names, or names that are legal identifiers in the
|
||||
* Java programming language (JLS 3.8).
|
||||
*
|
||||
* @return an array of {@code Parameter} objects representing all
|
||||
* the parameters to the executable this object represents
|
||||
*/
|
||||
@ -445,7 +449,8 @@ public abstract class Executable extends AccessibleObject
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
|
||||
@Override
|
||||
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
|
||||
return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
|
||||
|
||||
@ -1029,7 +1029,8 @@ class Field extends AccessibleObject implements Member {
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
* @since 1.8
|
||||
*/
|
||||
public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
|
||||
@Override
|
||||
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
|
||||
return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
|
||||
|
||||
@ -342,13 +342,13 @@ class Modifier {
|
||||
static final int SYNTHETIC = 0x00001000;
|
||||
static final int ANNOTATION = 0x00002000;
|
||||
static final int ENUM = 0x00004000;
|
||||
static final int SYNTHESIZED = 0x00010000;
|
||||
static final int MANDATED = 0x00008000;
|
||||
static boolean isSynthetic(int mod) {
|
||||
return (mod & SYNTHETIC) != 0;
|
||||
}
|
||||
|
||||
static boolean isSynthesized(int mod) {
|
||||
return (mod & SYNTHESIZED) != 0;
|
||||
static boolean isMandated(int mod) {
|
||||
return (mod & MANDATED) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -44,7 +44,7 @@ public final class Parameter implements AnnotatedElement {
|
||||
private final String name;
|
||||
private final int modifiers;
|
||||
private final Executable executable;
|
||||
private int index;
|
||||
private final int index;
|
||||
|
||||
/**
|
||||
* Package-private constructor for {@code Parameter}.
|
||||
@ -95,9 +95,14 @@ public final class Parameter implements AnnotatedElement {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the parameter's modifiers,
|
||||
* its attributes, its type, its name, and a trailing ... if it is
|
||||
* a variadic parameter.
|
||||
* Returns a string describing this parameter. The format is the
|
||||
* modifiers for the parameter, if any, in canonical order as
|
||||
* recommended by <cite>The Java™ Language
|
||||
* Specification</cite>, followed by the fully- qualified type of
|
||||
* the parameter (excluding the last [] if the parameter is
|
||||
* variable arity), followed by "..." if the parameter is variable
|
||||
* arity, followed by a space, followed by the name of the
|
||||
* parameter.
|
||||
*
|
||||
* @return A string representation of the parameter and associated
|
||||
* information.
|
||||
@ -118,7 +123,7 @@ public final class Parameter implements AnnotatedElement {
|
||||
sb.append(typename);
|
||||
|
||||
sb.append(" ");
|
||||
sb.append(name);
|
||||
sb.append(getName());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
@ -143,11 +148,23 @@ public final class Parameter implements AnnotatedElement {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the parameter represented by this
|
||||
* {@code Parameter} object.
|
||||
* Returns the name of the parameter. The names of the parameters
|
||||
* of a single executable must all the be distinct. When names
|
||||
* from the originating source are available, they are returned.
|
||||
* Otherwise, an implementation of this method is free to create a
|
||||
* name of this parameter, subject to the unquiness requirments.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
// As per the spec, if a parameter has no name, return argX,
|
||||
// where x is the index.
|
||||
//
|
||||
// Note: spec updates now outlaw empty strings as parameter
|
||||
// names. The .equals("") is for compatibility with current
|
||||
// JVM behavior. It may be removed at some point.
|
||||
if(name == null || name.equals(""))
|
||||
return "arg" + index;
|
||||
else
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -190,20 +207,21 @@ public final class Parameter implements AnnotatedElement {
|
||||
private transient volatile Class<?> parameterClassCache = null;
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this parameter is a synthesized
|
||||
* construct; returns {@code false} otherwise.
|
||||
* Returns {@code true} if this parameter is implicitly declared
|
||||
* in source code; returns {@code false} otherwise.
|
||||
*
|
||||
* @return true if and only if this parameter is a synthesized
|
||||
* construct as defined by
|
||||
* <cite>The Java™ Language Specification</cite>.
|
||||
* @return true if and only if this parameter is implicitly
|
||||
* declared as defined by <cite>The Java™ Language
|
||||
* Specification</cite>.
|
||||
*/
|
||||
public boolean isSynthesized() {
|
||||
return Modifier.isSynthesized(getModifiers());
|
||||
public boolean isImplicit() {
|
||||
return Modifier.isMandated(getModifiers());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this parameter is a synthetic
|
||||
* construct; returns {@code false} otherwise.
|
||||
* Returns {@code true} if this parameter is neither implicitly
|
||||
* nor explicitly declared in source code; returns {@code false}
|
||||
* otherwise.
|
||||
*
|
||||
* @jls 13.1 The Form of a Binary
|
||||
* @return true if and only if this parameter is a synthetic
|
||||
@ -240,7 +258,8 @@ public final class Parameter implements AnnotatedElement {
|
||||
* {@inheritDoc}
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
*/
|
||||
public <T extends Annotation> T[] getAnnotations(Class<T> annotationClass) {
|
||||
@Override
|
||||
public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
|
||||
Objects.requireNonNull(annotationClass);
|
||||
|
||||
return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass);
|
||||
@ -266,11 +285,12 @@ public final class Parameter implements AnnotatedElement {
|
||||
/**
|
||||
* @throws NullPointerException {@inheritDoc}
|
||||
*/
|
||||
public <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass) {
|
||||
@Override
|
||||
public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
|
||||
// Only annotations on classes are inherited, for all other
|
||||
// objects getDeclaredAnnotations is the same as
|
||||
// getAnnotations.
|
||||
return getAnnotations(annotationClass);
|
||||
return getAnnotationsByType(annotationClass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -117,8 +117,7 @@ import java.io.IOException;
|
||||
*/
|
||||
|
||||
public interface DirectoryStream<T>
|
||||
extends Closeable, Iterable<T>
|
||||
{
|
||||
extends Closeable, Iterable<T> {
|
||||
/**
|
||||
* An interface that is implemented by objects that decide if a directory
|
||||
* entry should be accepted or filtered. A {@code Filter} is passed as the
|
||||
@ -130,6 +129,7 @@ public interface DirectoryStream<T>
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public static interface Filter<T> {
|
||||
/**
|
||||
* Decides if the given directory entry should be accepted or filtered.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,7 +34,7 @@ package java.nio.file;
|
||||
* @see FileSystem#getPathMatcher
|
||||
* @see Files#newDirectoryStream(Path,String)
|
||||
*/
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PathMatcher {
|
||||
/**
|
||||
* Tells if given path matches this matcher's pattern.
|
||||
|
||||
@ -218,6 +218,150 @@ public class KeyStore {
|
||||
public ProtectionParameter getProtectionParameter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration data that specifies the keystores in a keystore domain.
|
||||
* A keystore domain is a collection of keystores that are presented as a
|
||||
* single logical keystore. The configuration data is used during
|
||||
* {@code KeyStore}
|
||||
* {@link #load(KeyStore.LoadStoreParameter) load} and
|
||||
* {@link #store(KeyStore.LoadStoreParameter) store} operations.
|
||||
* <p>
|
||||
* The following syntax is supported for configuration data:
|
||||
* <pre>
|
||||
*
|
||||
* domain <domainName> [<property> ...] {
|
||||
* keystore <keystoreName> [<property> ...] ;
|
||||
* ...
|
||||
* };
|
||||
* ...
|
||||
*
|
||||
* </pre>
|
||||
* where {@code domainName} and {@code keystoreName} are identifiers
|
||||
* and {@code property} is a key/value pairing. The key and value are
|
||||
* separated by an 'equals' symbol and the value is enclosed in double
|
||||
* quotes. A property value may be either a printable string or a binary
|
||||
* string of colon-separated pairs of hexadecimal digits. Multi-valued
|
||||
* properties are represented as a comma-separated list of values,
|
||||
* enclosed in square brackets.
|
||||
* See {@link Arrays#toString(java.lang.Object[])}.
|
||||
* <p>
|
||||
* To ensure that keystore entries are uniquely identified, each
|
||||
* entry's alias is prefixed by its {@code keystoreName} followed
|
||||
* by the entry name separator and each {@code keystoreName} must be
|
||||
* unique within its domain. Entry name prefixes are omitted when
|
||||
* storing a keystore.
|
||||
* <p>
|
||||
* Properties are context-sensitive: properties that apply to
|
||||
* all the keystores in a domain are located in the domain clause,
|
||||
* and properties that apply only to a specific keystore are located
|
||||
* in that keystore's clause.
|
||||
* Unless otherwise specified, a property in a keystore clause overrides
|
||||
* a property of the same name in the domain clause. All property names
|
||||
* are case-insensitive. The following properties are supported:
|
||||
* <dl>
|
||||
* <dt> {@code keystoreType="<type>"} </dt>
|
||||
* <dd> The keystore type. </dd>
|
||||
* <dt> {@code keystoreURI="<url>"} </dt>
|
||||
* <dd> The keystore location. </dd>
|
||||
* <dt> {@code keystoreProviderName="<name>"} </dt>
|
||||
* <dd> The name of the keystore's JCE provider. </dd>
|
||||
* <dt> {@code keystorePasswordEnv="<environment-variable>"} </dt>
|
||||
* <dd> The environment variable that stores a keystore password.
|
||||
* Alternatively, passwords may be supplied to the constructor
|
||||
* method in a {@code Map<String, ProtectionParameter>}. </dd>
|
||||
* <dt> {@code entryNameSeparator="<separator>"} </dt>
|
||||
* <dd> The separator between a keystore name prefix and an entry name.
|
||||
* When specified, it applies to all the entries in a domain.
|
||||
* Its default value is a space. </dd>
|
||||
* </dl>
|
||||
* <p>
|
||||
* For example, configuration data for a simple keystore domain
|
||||
* comprising three keystores is shown below:
|
||||
* <pre>
|
||||
*
|
||||
* domain app1 {
|
||||
* keystore app1-truststore
|
||||
* keystoreURI="file:///app1/etc/truststore.jks"
|
||||
*
|
||||
* keystore system-truststore
|
||||
* keystoreURI="${java.home}/lib/security/cacerts"
|
||||
*
|
||||
* keystore app1-keystore
|
||||
* keystoreType="PKCS12"
|
||||
* keystoreURI="file:///app1/etc/keystore.p12"
|
||||
* };
|
||||
*
|
||||
* </pre>
|
||||
* @since 1.8
|
||||
*/
|
||||
public static final class DomainLoadStoreParameter
|
||||
implements LoadStoreParameter {
|
||||
|
||||
private final URI configuration;
|
||||
private final Map<String,ProtectionParameter> protectionParams;
|
||||
|
||||
/**
|
||||
* Constructs a DomainLoadStoreParameter for a keystore domain with
|
||||
* the parameters used to protect keystore data.
|
||||
*
|
||||
* @param configuration identifier for the domain configuration data.
|
||||
* The name of the target domain should be specified in the
|
||||
* {@code java.net.URI} fragment component when it is necessary
|
||||
* to distinguish between several domain configurations at the
|
||||
* same location.
|
||||
*
|
||||
* @param protectionParams the map from keystore name to the parameter
|
||||
* used to protect keystore data.
|
||||
* A {@code java.util.Collections.EMPTY_MAP} should be used
|
||||
* when protection parameters are not required or when they have
|
||||
* been specified by properties in the domain configuration data.
|
||||
* It is cloned to prevent subsequent modification.
|
||||
*
|
||||
* @exception NullPointerExcetion if {@code configuration} or
|
||||
* {@code protectionParams} is {@code null}
|
||||
*/
|
||||
public DomainLoadStoreParameter(URI configuration,
|
||||
Map<String,ProtectionParameter> protectionParams) {
|
||||
if (configuration == null || protectionParams == null) {
|
||||
throw new NullPointerException("invalid null input");
|
||||
}
|
||||
this.configuration = configuration;
|
||||
this.protectionParams =
|
||||
Collections.unmodifiableMap(new HashMap<>(protectionParams));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the identifier for the domain configuration data.
|
||||
*
|
||||
* @return the identifier for the configuration data
|
||||
*/
|
||||
public URI getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the keystore protection parameters for keystores in this
|
||||
* domain.
|
||||
*
|
||||
* @return an unmodifiable map of keystore names to protection
|
||||
* parameters
|
||||
*/
|
||||
public Map<String,ProtectionParameter> getProtectionParams() {
|
||||
return protectionParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the keystore protection parameters for this domain.
|
||||
* Keystore domains do not support a protection parameter.
|
||||
*
|
||||
* @return always returns {@code null}
|
||||
*/
|
||||
@Override
|
||||
public KeyStore.ProtectionParameter getProtectionParameter() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A marker interface for keystore protection parameters.
|
||||
*
|
||||
|
||||
@ -25,6 +25,9 @@
|
||||
|
||||
package java.sql;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* <P>A thin wrapper around a millisecond value that allows
|
||||
* JDBC to identify this as an SQL <code>DATE</code> value. A
|
||||
@ -113,7 +116,6 @@ public class Date extends java.util.Date {
|
||||
int firstDash;
|
||||
int secondDash;
|
||||
Date d = null;
|
||||
|
||||
if (s == null) {
|
||||
throw new java.lang.IllegalArgumentException();
|
||||
}
|
||||
@ -255,4 +257,50 @@ public class Date extends java.util.Date {
|
||||
* compatibility.
|
||||
*/
|
||||
static final long serialVersionUID = 1511598038487230103L;
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code Date} from a {@link LocalDate} object
|
||||
* with the same year, month and day of month value as the given
|
||||
* {@code LocalDate}.
|
||||
* <p>
|
||||
* The provided {@code LocalDate} is interpreted as the local date
|
||||
* in the local time zone.
|
||||
*
|
||||
* @param date a {@code LocalDate} to convert
|
||||
* @return a {@code Date} object
|
||||
* @exception NullPointerException if {@code date} is null
|
||||
* @since 1.8
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Date valueOf(LocalDate date) {
|
||||
return new Date(date.getYear() - 1900, date.getMonthValue() -1,
|
||||
date.getDayOfMonth());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this {@code Date} object to a {@code LocalDate}
|
||||
* <p>
|
||||
* The conversion creates a {@code LocalDate} that represents the same
|
||||
* date value as this {@code Date} in local time zone
|
||||
*
|
||||
* @return a {@code LocalDate} object representing the same date value
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public LocalDate toLocalDate() {
|
||||
return LocalDate.of(getYear() + 1900, getMonth() + 1, getDate());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method always throws an UnsupportedOperationException and should
|
||||
* not be used because SQL {@code Date} values do not have a time
|
||||
* component.
|
||||
*
|
||||
* @exception java.lang.UnsupportedOperationException if this method is invoked
|
||||
*/
|
||||
@Override
|
||||
public Instant toInstant() {
|
||||
throw new java.lang.UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,7 +190,17 @@ public enum JDBCType implements SQLType {
|
||||
/**
|
||||
* Identifies the generic SQL type {@code REF_CURSOR}.
|
||||
*/
|
||||
REF_CURSOR(Types.REF_CURSOR);
|
||||
REF_CURSOR(Types.REF_CURSOR),
|
||||
|
||||
/**
|
||||
* Identifies the generic SQL type {@code TIME_WITH_TIMEZONE}.
|
||||
*/
|
||||
TIME_WITH_TIMEZONE(Types.TIME_WITH_TIMEZONE),
|
||||
|
||||
/**
|
||||
* Identifies the generic SQL type {@code TIMESTAMP_WITH_TIMEZONE}.
|
||||
*/
|
||||
TIMESTAMP_WITH_TIMEZONE(Types.TIMESTAMP_WITH_TIMEZONE);
|
||||
|
||||
/**
|
||||
* The Integer value for the JDBCType. It maps to a value in
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -421,4 +421,38 @@ public interface SQLInput {
|
||||
*/
|
||||
RowId readRowId() throws SQLException;
|
||||
|
||||
//--------------------------JDBC 4.2 -----------------------------
|
||||
|
||||
/**
|
||||
* Reads the next attribute in the stream and returns it as an
|
||||
* {@code Object} in the Java programming language. The
|
||||
* actual type of the object returned is determined by the specified
|
||||
* Java data type, and any customizations present in this
|
||||
* stream's type map.
|
||||
*
|
||||
* <P>A type map is registered with the stream by the JDBC driver before the
|
||||
* stream is passed to the application.
|
||||
*
|
||||
* <P>When the attribute at the head of the stream is an SQL {@code NULL}
|
||||
* the method returns {@code null}. If the attribute is an SQL
|
||||
* structured or distinct
|
||||
* type, it determines the SQL type of the attribute at the head of the stream.
|
||||
* If the stream's type map has an entry for that SQL type, the driver
|
||||
* constructs an object of the appropriate class and calls the method
|
||||
* {@code SQLData.readSQL} on that object, which reads additional data from the
|
||||
* stream, using the protocol described for that method.
|
||||
*<p>
|
||||
* The default implementation will throw {@code SQLFeatureNotSupportedException}
|
||||
*
|
||||
* @param type Class representing the Java data type to convert the attribute to.
|
||||
* @return the attribute at the head of the stream as an {@code Object} in the
|
||||
* Java programming language;{@code null} if the attribute is SQL {@code NULL}
|
||||
* @exception SQLException if a database access error occurs
|
||||
* @exception SQLFeatureNotSupportedException if the JDBC driver does not support
|
||||
* this method
|
||||
* @since 1.8
|
||||
*/
|
||||
default <T> T readObject(Class<T> type) throws SQLException {
|
||||
throw new SQLFeatureNotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -272,7 +272,7 @@ package java.sql;
|
||||
* Otherwise, it calls the <code>SQLData.writeSQL</code>
|
||||
* method of the given object, which
|
||||
* writes the object's attributes to the stream.
|
||||
* The implementation of the method <code>SQLData.writeSQ</code>
|
||||
* The implementation of the method <code>SQLData.writeSQL</code>
|
||||
* calls the appropriate <code>SQLOutput</code> writer method(s)
|
||||
* for writing each of the object's attributes in order.
|
||||
* The attributes must be read from an <code>SQLInput</code>
|
||||
@ -433,5 +433,43 @@ package java.sql;
|
||||
*/
|
||||
void writeSQLXML(SQLXML x) throws SQLException;
|
||||
|
||||
//--------------------------JDBC 4.2 -----------------------------
|
||||
|
||||
/**
|
||||
* Writes to the stream the data contained in the given object. The
|
||||
* object will be converted to the specified targetSqlType
|
||||
* before being sent to the stream.
|
||||
*<p>
|
||||
* When the {@code object} is {@code null}, this
|
||||
* method writes an SQL {@code NULL} to the stream.
|
||||
* <p>
|
||||
* If the object has a custom mapping (is of a class implementing the
|
||||
* interface {@code SQLData}),
|
||||
* the JDBC driver should call the method {@code SQLData.writeSQL} to
|
||||
* write it to the SQL data stream.
|
||||
* If, on the other hand, the object is of a class implementing
|
||||
* {@code Ref}, {@code Blob}, {@code Clob}, {@code NClob},
|
||||
* {@code Struct}, {@code java.net.URL},
|
||||
* or {@code Array}, the driver should pass it to the database as a
|
||||
* value of the corresponding SQL type.
|
||||
*<P>
|
||||
* The default implementation will throw {@code SQLFeatureNotSupportedException}
|
||||
*
|
||||
* @param x the object containing the input parameter value
|
||||
* @param targetSqlType the SQL type to be sent to the database.
|
||||
* @exception SQLException if a database access error occurs or
|
||||
* if the Java Object specified by x is an InputStream
|
||||
* or Reader object and the value of the scale parameter is less
|
||||
* than zero
|
||||
* @exception SQLFeatureNotSupportedException if
|
||||
* the JDBC driver does not support this data type
|
||||
* @see JDBCType
|
||||
* @see SQLType
|
||||
* @since 1.8
|
||||
*/
|
||||
default void writeObject(Object x, SQLType targetSqlType) throws SQLException {
|
||||
throw new SQLFeatureNotSupportedException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,9 @@
|
||||
|
||||
package java.sql;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalTime;
|
||||
|
||||
/**
|
||||
* <P>A thin wrapper around the <code>java.util.Date</code> class that allows the JDBC
|
||||
* API to identify this as an SQL <code>TIME</code> value. The <code>Time</code>
|
||||
@ -246,4 +249,45 @@ public class Time extends java.util.Date {
|
||||
* compatibility.
|
||||
*/
|
||||
static final long serialVersionUID = 8397324403548013681L;
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code Time} from a {@link LocalTime} object
|
||||
* with the same hour, minute and second time value as the given
|
||||
* {@code LocalTime}.
|
||||
*
|
||||
* @param time a {@code LocalTime} to convert
|
||||
* @return a {@code Time} object
|
||||
* @exception NullPointerException if {@code time} is null
|
||||
* @since 1.8
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Time valueOf(LocalTime time) {
|
||||
return new Time(time.getHour(), time.getMinute(), time.getSecond());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this {@code Time} object to a {@code LocalTime}.
|
||||
* <p>
|
||||
* The conversion creates a {@code LocalTime} that represents the same
|
||||
* hour, minute, and second time value as this {@code Time}.
|
||||
*
|
||||
* @return a {@code LocalTime} object representing the same time value
|
||||
* @since 1.8
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public LocalTime toLocalTime() {
|
||||
return LocalTime.of(getHours(), getMinutes(), getSeconds());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method always throws an UnsupportedOperationException and should
|
||||
* not be used because SQL {@code Time} values do not have a date
|
||||
* component.
|
||||
*
|
||||
* @exception java.lang.UnsupportedOperationException if this method is invoked
|
||||
*/
|
||||
@Override
|
||||
public Instant toInstant() {
|
||||
throw new java.lang.UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,6 +25,8 @@
|
||||
|
||||
package java.sql;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
@ -485,7 +487,6 @@ public class Timestamp extends java.util.Date {
|
||||
}
|
||||
}
|
||||
return i;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -530,4 +531,89 @@ public class Timestamp extends java.util.Date {
|
||||
|
||||
static final long serialVersionUID = 2745179027874758501L;
|
||||
|
||||
private static final int MILLIS_PER_SECOND = 1000;
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code Timestamp} from a {@code LocalDateTime}
|
||||
* object, with the same year, month, day of month, hours, minutes,
|
||||
* seconds and nanos date-time value as the provided {@code LocalDateTime}.
|
||||
* <p>
|
||||
* The provided {@code LocalDateTime} is interpreted as the local
|
||||
* date-time in the local time zone.
|
||||
*
|
||||
* @param dateTime a {@code LocalDateTime} to convert
|
||||
* @return a {@code Timestamp} object
|
||||
* @exception NullPointerException if {@code dateTime} is null.
|
||||
* @since 1.8
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Timestamp valueOf(LocalDateTime dateTime) {
|
||||
return new Timestamp(dateTime.getYear() - 1900,
|
||||
dateTime.getMonthValue() - 1,
|
||||
dateTime.getDayOfMonth(),
|
||||
dateTime.getHour(),
|
||||
dateTime.getMinute(),
|
||||
dateTime.getSecond(),
|
||||
dateTime.getNano());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this {@code Timestamp} object to a {@code LocalDateTime}.
|
||||
* <p>
|
||||
* The conversion creates a {@code LocalDateTime} that represents the
|
||||
* same year, month, day of month, hours, minutes, seconds and nanos
|
||||
* date-time value as this {@code Timestamp} in the local time zone.
|
||||
*
|
||||
* @return a {@code LocalDateTime} object representing the same date-time value
|
||||
* @since 1.8
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public LocalDateTime toLocalDateTime() {
|
||||
return LocalDateTime.of(getYear() + 1900,
|
||||
getMonth() + 1,
|
||||
getDate(),
|
||||
getHours(),
|
||||
getMinutes(),
|
||||
getSeconds(),
|
||||
getNanos());
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code Timestamp} from an {@link Instant} object.
|
||||
* <p>
|
||||
* {@code Instant} can store points on the time-line further in the future
|
||||
* and further in the past than {@code Date}. In this scenario, this method
|
||||
* will throw an exception.
|
||||
*
|
||||
* @param instant the instant to convert
|
||||
* @return an {@code Timestamp} representing the same point on the time-line as
|
||||
* the provided instant
|
||||
* @exception NullPointerException if {@code instant} is null.
|
||||
* @exception IllegalArgumentException if the instant is too large to
|
||||
* represent as a {@code Timesamp}
|
||||
* @since 1.8
|
||||
*/
|
||||
public static Timestamp from(Instant instant) {
|
||||
try {
|
||||
Timestamp stamp = new Timestamp(instant.getEpochSecond() * MILLIS_PER_SECOND);
|
||||
stamp.nanos = instant.getNano();
|
||||
return stamp;
|
||||
} catch (ArithmeticException ex) {
|
||||
throw new IllegalArgumentException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this {@code Timestamp} object to an {@code Instant}.
|
||||
* <p>
|
||||
* The conversion creates an {@code Instant} that represents the same
|
||||
* point on the time-line as this {@code Timestamp}.
|
||||
*
|
||||
* @return an instant representing the same point on the time-line
|
||||
* @since 1.8
|
||||
*/
|
||||
@Override
|
||||
public Instant toInstant() {
|
||||
return Instant.ofEpochSecond(super.getTime() / MILLIS_PER_SECOND, nanos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,6 +319,24 @@ public class Types {
|
||||
*/
|
||||
public static final int REF_CURSOR = 2012;
|
||||
|
||||
/**
|
||||
* The constant in the Java programming language, sometimes referred to
|
||||
* as a type code, that identifies the generic SQL type
|
||||
* {@code TIME WITH TIMEZONE}.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public static final int TIME_WITH_TIMEZONE = 2013;
|
||||
|
||||
/**
|
||||
* The constant in the Java programming language, sometimes referred to
|
||||
* as a type code, that identifies the generic SQL type
|
||||
* {@code TIMESTAMP WITH TIMEZONE}.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public static final int TIMESTAMP_WITH_TIMEZONE = 2014;
|
||||
|
||||
// Prevent instantiation
|
||||
private Types() {}
|
||||
}
|
||||
|
||||
@ -377,60 +377,57 @@ public abstract class Clock {
|
||||
* an instant on the time-line rather than a raw millisecond value.
|
||||
* This method is provided to allow the use of the clock in high performance use cases
|
||||
* where the creation of an object would be unacceptable.
|
||||
* <p>
|
||||
* The default implementation currently calls {@link #instant}.
|
||||
*
|
||||
* @return the current millisecond instant from this clock, measured from
|
||||
* the Java epoch of 1970-01-01T00:00 UTC, not null
|
||||
* @throws DateTimeException if the instant cannot be obtained, not thrown by most implementations
|
||||
*/
|
||||
public abstract long millis();
|
||||
public long millis() {
|
||||
return instant().toEpochMilli();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the current instant of the clock.
|
||||
* <p>
|
||||
* This returns an instant representing the current instant as defined by the clock.
|
||||
* <p>
|
||||
* The default implementation currently calls {@link #millis}.
|
||||
*
|
||||
* @return the current instant from this clock, not null
|
||||
* @throws DateTimeException if the instant cannot be obtained, not thrown by most implementations
|
||||
*/
|
||||
public Instant instant() {
|
||||
return Instant.ofEpochMilli(millis());
|
||||
}
|
||||
public abstract Instant instant();
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Checks if this clock is equal to another clock.
|
||||
* <p>
|
||||
* Clocks must compare equal based on their state and behavior.
|
||||
* Clocks should override this method to compare equals based on
|
||||
* their state and to meet the contract of {@link Object#equals}.
|
||||
* If not overridden, the behavior is defined by {@link Object#equals}
|
||||
*
|
||||
* @param obj the object to check, null returns false
|
||||
* @return true if this is equal to the other clock
|
||||
*/
|
||||
@Override
|
||||
public abstract boolean equals(Object obj);
|
||||
public boolean equals(Object obj) {
|
||||
return super.equals(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* A hash code for this clock.
|
||||
* <p>
|
||||
* Clocks should override this method based on
|
||||
* their state and to meet the contract of {@link Object#hashCode}.
|
||||
* If not overridden, the behavior is defined by {@link Object#hashCode}
|
||||
*
|
||||
* @return a suitable hash code
|
||||
*/
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a string describing this clock.
|
||||
* <p>
|
||||
* Clocks must have a string representation based on their state and behavior.
|
||||
* For example, 'System[Europe/Paris]' could be used to represent the System
|
||||
* clock in the 'Europe/Paris' time-zone.
|
||||
*
|
||||
* @return a string representation of this clock, not null
|
||||
*/
|
||||
@Override
|
||||
public abstract String toString();
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@ -460,6 +457,10 @@ public abstract class Clock {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
@Override
|
||||
public Instant instant() {
|
||||
return Instant.ofEpochMilli(millis());
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof SystemClock) {
|
||||
return zone.equals(((SystemClock) obj).zone);
|
||||
|
||||
@ -170,8 +170,9 @@ public enum DayOfWeek implements TemporalAccessor, TemporalAdjuster {
|
||||
/**
|
||||
* Obtains an instance of {@code DayOfWeek} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code DayOfWeek}.
|
||||
* This obtains a day-of-week based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code DayOfWeek}.
|
||||
* <p>
|
||||
* The conversion extracts the {@link ChronoField#DAY_OF_WEEK DAY_OF_WEEK} field.
|
||||
* <p>
|
||||
@ -206,8 +207,9 @@ public enum DayOfWeek implements TemporalAccessor, TemporalAdjuster {
|
||||
/**
|
||||
* Gets the textual representation, such as 'Mon' or 'Friday'.
|
||||
* <p>
|
||||
* This returns the textual name used to identify the day-of-week.
|
||||
* The parameters control the length of the returned text and the locale.
|
||||
* This returns the textual name used to identify the day-of-week,
|
||||
* suitable for presentation to the user.
|
||||
* The parameters control the style of the returned text and the locale.
|
||||
* <p>
|
||||
* If no textual mapping is found then the {@link #getValue() numeric value} is returned.
|
||||
*
|
||||
@ -215,8 +217,8 @@ public enum DayOfWeek implements TemporalAccessor, TemporalAdjuster {
|
||||
* @param locale the locale to use, not null
|
||||
* @return the text value of the day-of-week, not null
|
||||
*/
|
||||
public String getText(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendText(DAY_OF_WEEK, style).toFormatter(locale).print(this);
|
||||
public String getDisplayName(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendText(DAY_OF_WEEK, style).toFormatter(locale).format(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -232,7 +234,7 @@ public enum DayOfWeek implements TemporalAccessor, TemporalAdjuster {
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -244,7 +246,7 @@ public enum DayOfWeek implements TemporalAccessor, TemporalAdjuster {
|
||||
if (field instanceof ChronoField) {
|
||||
return field == DAY_OF_WEEK;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -260,7 +262,7 @@ public enum DayOfWeek implements TemporalAccessor, TemporalAdjuster {
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -289,15 +291,13 @@ public enum DayOfWeek implements TemporalAccessor, TemporalAdjuster {
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the 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 ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
@ -320,7 +320,7 @@ public enum DayOfWeek implements TemporalAccessor, TemporalAdjuster {
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -336,7 +336,7 @@ public enum DayOfWeek implements TemporalAccessor, TemporalAdjuster {
|
||||
} else if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
@ -61,10 +61,14 @@
|
||||
*/
|
||||
package java.time;
|
||||
|
||||
import static java.time.LocalTime.NANOS_PER_SECOND;
|
||||
import static java.time.LocalTime.SECONDS_PER_DAY;
|
||||
import static java.time.temporal.ChronoField.INSTANT_SECONDS;
|
||||
import static java.time.LocalTime.SECONDS_PER_HOUR;
|
||||
import static java.time.LocalTime.SECONDS_PER_MINUTE;
|
||||
import static java.time.temporal.ChronoField.NANO_OF_SECOND;
|
||||
import static java.time.temporal.ChronoUnit.DAYS;
|
||||
import static java.time.temporal.ChronoUnit.NANOS;
|
||||
import static java.time.temporal.ChronoUnit.SECONDS;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@ -79,17 +83,23 @@ import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdder;
|
||||
import java.time.temporal.TemporalSubtractor;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A duration between two instants on the time-line.
|
||||
* A time-based amount of time, such as '34.5 seconds'.
|
||||
* <p>
|
||||
* This class models a duration of time and is not tied to any instant.
|
||||
* The model is of a directed duration, meaning that the duration may be negative.
|
||||
* This class models a quantity or amount of time in terms of seconds and nanoseconds.
|
||||
* It can be accessed using other duration-based units, such as minutes and hours.
|
||||
* In addition, the {@link ChronoUnit#DAYS DAYS} unit can be used and is treated as
|
||||
* exactly equal to 24 hours, thus ignoring daylight savings effects.
|
||||
* See {@link Period} for the date-based equivalent to this class.
|
||||
* <p>
|
||||
* A physical duration could be of infinite length.
|
||||
* For practicality, the duration is stored with constraints similar to {@link Instant}.
|
||||
@ -99,6 +109,7 @@ import java.util.Objects;
|
||||
* The range of a duration requires the storage of a number larger than a {@code long}.
|
||||
* To achieve this, the class stores a {@code long} representing seconds and an {@code int}
|
||||
* representing nanosecond-of-second, which will always be between 0 and 999,999,999.
|
||||
* The model is of a directed duration, meaning that the duration may be negative.
|
||||
* <p>
|
||||
* The duration is measured in "seconds", but these are not necessarily identical to
|
||||
* the scientific "SI second" definition based on atomic clocks.
|
||||
@ -112,7 +123,7 @@ import java.util.Objects;
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class Duration
|
||||
implements TemporalAdder, TemporalSubtractor, Comparable<Duration>, Serializable {
|
||||
implements TemporalAmount, Comparable<Duration>, Serializable {
|
||||
|
||||
/**
|
||||
* Constant for a duration of zero.
|
||||
@ -122,14 +133,17 @@ public final class Duration
|
||||
* Serialization version.
|
||||
*/
|
||||
private static final long serialVersionUID = 3078945930695997490L;
|
||||
/**
|
||||
* Constant for nanos per second.
|
||||
*/
|
||||
private static final int NANOS_PER_SECOND = 1000_000_000;
|
||||
/**
|
||||
* Constant for nanos per second.
|
||||
*/
|
||||
private static final BigInteger BI_NANOS_PER_SECOND = BigInteger.valueOf(NANOS_PER_SECOND);
|
||||
/**
|
||||
* The pattern for parsing.
|
||||
*/
|
||||
private final static Pattern PATTERN =
|
||||
Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)D)?" +
|
||||
"(T(?:([-+]?[0-9]+)H)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)(?:[.,]([0-9]{0,9}))?S)?)?",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* The number of seconds in the duration.
|
||||
@ -143,7 +157,53 @@ public final class Duration
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code Duration} from a number of seconds.
|
||||
* Obtains a {@code Duration} representing a number of standard 24 hour days.
|
||||
* <p>
|
||||
* The seconds are calculated based on the standard definition of a day,
|
||||
* where each day is 86400 seconds which implies a 24 hour day.
|
||||
* The nanosecond in second field is set to zero.
|
||||
*
|
||||
* @param days the number of days, positive or negative
|
||||
* @return a {@code Duration}, not null
|
||||
* @throws ArithmeticException if the input days exceeds the capacity of {@code Duration}
|
||||
*/
|
||||
public static Duration ofDays(long days) {
|
||||
return create(Math.multiplyExact(days, SECONDS_PER_DAY), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code Duration} representing a number of standard hours.
|
||||
* <p>
|
||||
* The seconds are calculated based on the standard definition of an hour,
|
||||
* where each hour is 3600 seconds.
|
||||
* The nanosecond in second field is set to zero.
|
||||
*
|
||||
* @param hours the number of hours, positive or negative
|
||||
* @return a {@code Duration}, not null
|
||||
* @throws ArithmeticException if the input hours exceeds the capacity of {@code Duration}
|
||||
*/
|
||||
public static Duration ofHours(long hours) {
|
||||
return create(Math.multiplyExact(hours, SECONDS_PER_HOUR), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code Duration} representing a number of standard minutes.
|
||||
* <p>
|
||||
* The seconds are calculated based on the standard definition of a minute,
|
||||
* where each minute is 60 seconds.
|
||||
* The nanosecond in second field is set to zero.
|
||||
*
|
||||
* @param minutes the number of minutes, positive or negative
|
||||
* @return a {@code Duration}, not null
|
||||
* @throws ArithmeticException if the input minutes exceeds the capacity of {@code Duration}
|
||||
*/
|
||||
public static Duration ofMinutes(long minutes) {
|
||||
return create(Math.multiplyExact(minutes, SECONDS_PER_MINUTE), 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains a {@code Duration} representing a number of seconds.
|
||||
* <p>
|
||||
* The nanosecond in second field is set to zero.
|
||||
*
|
||||
@ -155,8 +215,8 @@ public final class Duration
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code Duration} from a number of seconds
|
||||
* and an adjustment in nanoseconds.
|
||||
* Obtains a {@code Duration} representing a number of seconds and an
|
||||
* adjustment in nanoseconds.
|
||||
* <p>
|
||||
* This method allows an arbitrary number of nanoseconds to be passed in.
|
||||
* The factory will alter the values of the second and nanosecond in order
|
||||
@ -175,13 +235,13 @@ public final class Duration
|
||||
*/
|
||||
public static Duration ofSeconds(long seconds, long nanoAdjustment) {
|
||||
long secs = Math.addExact(seconds, Math.floorDiv(nanoAdjustment, NANOS_PER_SECOND));
|
||||
int nos = (int)Math.floorMod(nanoAdjustment, NANOS_PER_SECOND);
|
||||
int nos = (int) Math.floorMod(nanoAdjustment, NANOS_PER_SECOND);
|
||||
return create(secs, nos);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code Duration} from a number of milliseconds.
|
||||
* Obtains a {@code Duration} representing a number of milliseconds.
|
||||
* <p>
|
||||
* The seconds and nanoseconds are extracted from the specified milliseconds.
|
||||
*
|
||||
@ -200,7 +260,7 @@ public final class Duration
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code Duration} from a number of nanoseconds.
|
||||
* Obtains a {@code Duration} representing a number of nanoseconds.
|
||||
* <p>
|
||||
* The seconds and nanoseconds are extracted from the specified nanoseconds.
|
||||
*
|
||||
@ -219,53 +279,7 @@ public final class Duration
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code Duration} from a number of standard length minutes.
|
||||
* <p>
|
||||
* The seconds are calculated based on the standard definition of a minute,
|
||||
* where each minute is 60 seconds.
|
||||
* The nanosecond in second field is set to zero.
|
||||
*
|
||||
* @param minutes the number of minutes, positive or negative
|
||||
* @return a {@code Duration}, not null
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code Duration} from a number of standard length hours.
|
||||
* <p>
|
||||
* The seconds are calculated based on the standard definition of an hour,
|
||||
* where each hour is 3600 seconds.
|
||||
* The nanosecond in second field is set to zero.
|
||||
*
|
||||
* @param hours the number of hours, positive or negative
|
||||
* @return a {@code Duration}, not null
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code Duration} from a number of standard 24 hour days.
|
||||
* <p>
|
||||
* The seconds are calculated based on the standard definition of a day,
|
||||
* where each day is 86400 seconds which implies a 24 hour day.
|
||||
* The nanosecond in second field is set to zero.
|
||||
*
|
||||
* @param days the number of days, positive or negative
|
||||
* @return a {@code Duration}, not null
|
||||
* @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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code Duration} from a duration in the specified unit.
|
||||
* Obtains a {@code Duration} representing an amount in the specified unit.
|
||||
* <p>
|
||||
* The parameters represent the two parts of a phrase like '6 Hours'. For example:
|
||||
* <pre>
|
||||
@ -288,110 +302,139 @@ public final class Duration
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code Duration} representing the duration between two instants.
|
||||
* Obtains a {@code Duration} representing the duration between two instants.
|
||||
* <p>
|
||||
* A {@code Duration} represents a directed distance between two points on the time-line.
|
||||
* As such, this method will return a negative duration if the end is before the start.
|
||||
* To guarantee to obtain a positive duration call {@link #abs()} on the result of this factory.
|
||||
* This calculates the duration between two temporal objects of the same type.
|
||||
* The difference in seconds is calculated using
|
||||
* {@link Temporal#periodUntil(Temporal, TemporalUnit)}.
|
||||
* The difference in nanoseconds is calculated using by querying the
|
||||
* {@link ChronoField#NANO_OF_SECOND NANO_OF_SECOND} field.
|
||||
* <p>
|
||||
* The result of this method can be a negative period if the end is before the start.
|
||||
* To guarantee to obtain a positive duration call {@link #abs()} on the result.
|
||||
*
|
||||
* @param startInclusive the start instant, inclusive, not null
|
||||
* @param endExclusive the end instant, exclusive, not null
|
||||
* @return a {@code Duration}, not null
|
||||
* @throws ArithmeticException if the calculation exceeds the capacity of {@code Duration}
|
||||
*/
|
||||
public static Duration between(TemporalAccessor startInclusive, TemporalAccessor endExclusive) {
|
||||
long secs = Math.subtractExact(endExclusive.getLong(INSTANT_SECONDS), startInclusive.getLong(INSTANT_SECONDS));
|
||||
long nanos = endExclusive.getLong(NANO_OF_SECOND) - startInclusive.getLong(NANO_OF_SECOND);
|
||||
secs = Math.addExact(secs, Math.floorDiv(nanos, NANOS_PER_SECOND));
|
||||
nanos = Math.floorMod(nanos, NANOS_PER_SECOND);
|
||||
return create(secs, (int) nanos); // safe from overflow
|
||||
public static Duration between(Temporal startInclusive, Temporal endExclusive) {
|
||||
long secs = startInclusive.periodUntil(endExclusive, SECONDS);
|
||||
long nanos;
|
||||
try {
|
||||
nanos = endExclusive.getLong(NANO_OF_SECOND) - startInclusive.getLong(NANO_OF_SECOND);
|
||||
} catch (DateTimeException ex) {
|
||||
nanos = 0;
|
||||
}
|
||||
return ofSeconds(secs, nanos);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code Duration} by parsing a text string.
|
||||
* Obtains a {@code Duration} from a text string such as {@code PnDTnHnMn.nS}.
|
||||
* <p>
|
||||
* This will parse the string produced by {@link #toString()} which is
|
||||
* the ISO-8601 format {@code PTnS} where {@code n} is
|
||||
* the number of seconds with optional decimal part.
|
||||
* The number must consist of ASCII numerals.
|
||||
* There must only be a negative sign at the start of the number and it can
|
||||
* only be present if the value is less than zero.
|
||||
* There must be at least one digit before any decimal point.
|
||||
* There must be between 1 and 9 inclusive digits after any decimal point.
|
||||
* The letters (P, T and S) will be accepted in upper or lower case.
|
||||
* This will parse a textual representation of a duration, including the
|
||||
* string produced by {@code toString()}. The formats accepted are based
|
||||
* on the ISO-8601 duration format {@code PnDTnHnMn.nS} with days
|
||||
* considered to be exactly 24 hours.
|
||||
* <p>
|
||||
* The string starts with an optional sign, denoted by the ASCII negative
|
||||
* or positive symbol. If negative, the whole period is negated.
|
||||
* The ASCII letter "P" is next in upper or lower case.
|
||||
* There are then four sections, each consisting of a number and a suffix.
|
||||
* The sections have suffixes in ASCII of "D", "H", "M" and "S" for
|
||||
* days, hours, minutes and seconds, accepted in upper or lower case.
|
||||
* The suffixes must occur in order. The ASCII letter "T" must occur before
|
||||
* the first occurrence, if any, of an hour, minute or second section.
|
||||
* At least one of the four sections must be present, and if "T" is present
|
||||
* there must be at least one section after the "T".
|
||||
* The number part of each section must consist of one or more ASCII digits.
|
||||
* The number may be prefixed by the ASCII negative or positive symbol.
|
||||
* The number of days, hours and minutes must parse to an {@code long}.
|
||||
* The number of seconds must parse to an {@code long} with optional fraction.
|
||||
* The decimal point may be either a dot or a comma.
|
||||
* The fractional part may have from zero to 9 digits.
|
||||
* <p>
|
||||
* The leading plus/minus sign, and negative values for other units are
|
||||
* not part of the ISO-8601 standard.
|
||||
* <p>
|
||||
* Examples:
|
||||
* <pre>
|
||||
* "PT20.345S" -> parses as "20.345 seconds"
|
||||
* "PT15M" -> parses as "15 minutes" (where a minute is 60 seconds)
|
||||
* "PT10H" -> parses as "10 hours" (where an hour is 3600 seconds)
|
||||
* "P2D" -> parses as "2 days" (where a day is 24 hours or 86400 seconds)
|
||||
* "P2DT3H4M" -> parses as "2 days, 3 hours and 4 minutes"
|
||||
* "P-6H3M" -> parses as "-6 hours and +3 minutes"
|
||||
* "-P6H3M" -> parses as "-6 hours and -3 minutes"
|
||||
* "-P-6H+3M" -> parses as "+6 hours and -3 minutes"
|
||||
* </pre>
|
||||
*
|
||||
* @param text the text to parse, not null
|
||||
* @return a {@code Duration}, not null
|
||||
* @throws DateTimeParseException if the text cannot be parsed to a {@code Duration}
|
||||
* @return the parsed duration, not null
|
||||
* @throws DateTimeParseException if the text cannot be parsed to a duration
|
||||
*/
|
||||
public static Duration parse(final CharSequence text) {
|
||||
public static Duration parse(CharSequence text) {
|
||||
Objects.requireNonNull(text, "text");
|
||||
int len = text.length();
|
||||
if (len < 4 ||
|
||||
(text.charAt(0) != 'P' && text.charAt(0) != 'p') ||
|
||||
(text.charAt(1) != 'T' && text.charAt(1) != 't') ||
|
||||
(text.charAt(len - 1) != 'S' && text.charAt(len - 1) != 's') ||
|
||||
(len == 5 && text.charAt(2) == '-' && text.charAt(3) == '0')) {
|
||||
throw new DateTimeParseException("Duration could not be parsed: " + text, text, 0);
|
||||
}
|
||||
String numberText = text.subSequence(2, len - 1).toString().replace(',', '.');
|
||||
if (numberText.charAt(0) == '+') {
|
||||
throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2);
|
||||
}
|
||||
int dot = numberText.indexOf('.');
|
||||
try {
|
||||
if (dot == -1) {
|
||||
// no decimal places
|
||||
if (numberText.startsWith("-0")) {
|
||||
throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2);
|
||||
Matcher matcher = PATTERN.matcher(text);
|
||||
if (matcher.matches()) {
|
||||
// check for letter T but no time sections
|
||||
if ("T".equals(matcher.group(3)) == false) {
|
||||
boolean negate = "-".equals(matcher.group(1));
|
||||
String dayMatch = matcher.group(2);
|
||||
String hourMatch = matcher.group(4);
|
||||
String minuteMatch = matcher.group(5);
|
||||
String secondMatch = matcher.group(6);
|
||||
String fractionMatch = matcher.group(7);
|
||||
if (dayMatch != null || hourMatch != null || minuteMatch != null || secondMatch != null) {
|
||||
long daysAsSecs = parseNumber(text, dayMatch, SECONDS_PER_DAY, "days");
|
||||
long hoursAsSecs = parseNumber(text, hourMatch, SECONDS_PER_HOUR, "hours");
|
||||
long minsAsSecs = parseNumber(text, minuteMatch, SECONDS_PER_MINUTE, "minutes");
|
||||
long seconds = parseNumber(text, secondMatch, 1, "seconds");
|
||||
int nanos = parseFraction(text, fractionMatch, seconds < 0 ? -1 : 1);
|
||||
try {
|
||||
return create(negate, daysAsSecs, hoursAsSecs, minsAsSecs, seconds, nanos);
|
||||
} catch (ArithmeticException ex) {
|
||||
throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: overflow", text, 0).initCause(ex);
|
||||
}
|
||||
}
|
||||
return create(Long.parseLong(numberText), 0);
|
||||
}
|
||||
// decimal places
|
||||
boolean negative = false;
|
||||
if (numberText.charAt(0) == '-') {
|
||||
negative = true;
|
||||
}
|
||||
long secs = Long.parseLong(numberText.substring(0, dot));
|
||||
numberText = numberText.substring(dot + 1);
|
||||
len = numberText.length();
|
||||
if (len == 0 || len > 9 || numberText.charAt(0) == '-' || numberText.charAt(0) == '+') {
|
||||
throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2);
|
||||
}
|
||||
int nanos = Integer.parseInt(numberText);
|
||||
switch (len) {
|
||||
case 1:
|
||||
nanos *= 100000000;
|
||||
break;
|
||||
case 2:
|
||||
nanos *= 10000000;
|
||||
break;
|
||||
case 3:
|
||||
nanos *= 1000000;
|
||||
break;
|
||||
case 4:
|
||||
nanos *= 100000;
|
||||
break;
|
||||
case 5:
|
||||
nanos *= 10000;
|
||||
break;
|
||||
case 6:
|
||||
nanos *= 1000;
|
||||
break;
|
||||
case 7:
|
||||
nanos *= 100;
|
||||
break;
|
||||
case 8:
|
||||
nanos *= 10;
|
||||
break;
|
||||
}
|
||||
return negative ? ofSeconds(secs, -nanos) : create(secs, nanos);
|
||||
|
||||
} catch (ArithmeticException | NumberFormatException ex) {
|
||||
throw new DateTimeParseException("Duration could not be parsed: " + text, text, 2, ex);
|
||||
}
|
||||
throw new DateTimeParseException("Text cannot be parsed to a Duration", text, 0);
|
||||
}
|
||||
|
||||
private static long parseNumber(CharSequence text, String parsed, int multiplier, String errorText) {
|
||||
// regex limits to [-+]?[0-9]+
|
||||
if (parsed == null) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
long val = Long.parseLong(parsed);
|
||||
return Math.multiplyExact(val, multiplier);
|
||||
} catch (NumberFormatException | ArithmeticException ex) {
|
||||
throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: " + errorText, text, 0).initCause(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static int parseFraction(CharSequence text, String parsed, int negate) {
|
||||
// regex limits to [0-9]{0,9}
|
||||
if (parsed == null || parsed.length() == 0) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
parsed = (parsed + "000000000").substring(0, 9);
|
||||
return Integer.parseInt(parsed) * negate;
|
||||
} catch (NumberFormatException | ArithmeticException ex) {
|
||||
throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: fraction", text, 0).initCause(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static Duration create(boolean negate, long daysAsSecs, long hoursAsSecs, long minsAsSecs, long secs, int nanos) {
|
||||
long seconds = Math.addExact(daysAsSecs, Math.addExact(hoursAsSecs, Math.addExact(minsAsSecs, secs)));
|
||||
if (negate) {
|
||||
return ofSeconds(seconds, nanos).negated();
|
||||
}
|
||||
return ofSeconds(seconds, nanos);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -420,6 +463,56 @@ public final class Duration
|
||||
this.nanos = nanos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the value of the requested unit.
|
||||
* <p>
|
||||
* This returns a value for each of the two supported units,
|
||||
* {@link ChronoUnit#SECONDS SECONDS} and {@link ChronoUnit#NANOS NANOS}.
|
||||
* All other units throw an exception.
|
||||
*
|
||||
* @param unit the {@code TemporalUnit} for which to return the value
|
||||
* @return the long value of the unit
|
||||
* @throws DateTimeException if the unit is not supported
|
||||
*/
|
||||
@Override
|
||||
public long get(TemporalUnit unit) {
|
||||
if (unit == SECONDS) {
|
||||
return seconds;
|
||||
} else if (unit == NANOS) {
|
||||
return nanos;
|
||||
} else {
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of units supported by this duration.
|
||||
* <p>
|
||||
* The supported units are {@link ChronoUnit#SECONDS SECONDS},
|
||||
* and {@link ChronoUnit#NANOS NANOS}.
|
||||
* They are returned in the order seconds, nanos.
|
||||
* <p>
|
||||
* This set can be used in conjunction with {@link #get(TemporalUnit)}
|
||||
* to access the entire state of the period.
|
||||
*
|
||||
* @return a list containing the seconds and nanos units, not null
|
||||
*/
|
||||
@Override
|
||||
public List<TemporalUnit> getUnits() {
|
||||
return DurationUnits.UNITS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Private class to delay initialization of this list until needed.
|
||||
* The circular dependency between Duration and ChronoUnit prevents
|
||||
* the simple initialization in Duration.
|
||||
*/
|
||||
private static class DurationUnits {
|
||||
final static List<TemporalUnit> UNITS =
|
||||
Collections.unmodifiableList(Arrays.<TemporalUnit>asList(SECONDS, NANOS));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Checks if this duration is zero length.
|
||||
@ -434,19 +527,6 @@ public final class Duration
|
||||
return (seconds | nanos) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this duration is positive, excluding zero.
|
||||
* <p>
|
||||
* A {@code Duration} represents a directed distance between two points on
|
||||
* the time-line and can therefore be positive, zero or negative.
|
||||
* This method checks whether the length is greater than zero.
|
||||
*
|
||||
* @return true if this duration has a total length greater than zero
|
||||
*/
|
||||
public boolean isPositive() {
|
||||
return seconds >= 0 && ((seconds | nanos) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this duration is negative, excluding zero.
|
||||
* <p>
|
||||
@ -497,6 +577,39 @@ public final class Duration
|
||||
return nanos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this duration with the specified amount of seconds.
|
||||
* <p>
|
||||
* This returns a duration with the specified seconds, retaining the
|
||||
* nano-of-second part of this duration.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param seconds the seconds to represent, may be negative
|
||||
* @return a {@code Duration} based on this period with the requested seconds, not null
|
||||
*/
|
||||
public Duration withSeconds(long seconds) {
|
||||
return create(seconds, nanos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this duration with the specified nano-of-second.
|
||||
* <p>
|
||||
* This returns a duration with the specified nano-of-second, retaining the
|
||||
* seconds part of this duration.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param nanoOfSecond the nano-of-second to represent, from 0 to 999,999,999
|
||||
* @return a {@code Duration} based on this period with the requested nano-of-second, not null
|
||||
* @throws DateTimeException if the nano-of-second is invalid
|
||||
*/
|
||||
public Duration withNanos(int nanoOfSecond) {
|
||||
NANO_OF_SECOND.checkValidIntValue(nanoOfSecond);
|
||||
return create(seconds, nanoOfSecond);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this duration with the specified duration added.
|
||||
@ -551,6 +664,48 @@ public final class Duration
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this duration with the specified duration in standard 24 hour days added.
|
||||
* <p>
|
||||
* The number of days is multiplied by 86400 to obtain the number of seconds to add.
|
||||
* This is based on the standard definition of a day as 24 hours.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param daysToAdd the days to add, positive or negative
|
||||
* @return a {@code Duration} based on this duration with the specified days added, not null
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
public Duration plusDays(long daysToAdd) {
|
||||
return plus(Math.multiplyExact(daysToAdd, SECONDS_PER_DAY), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this duration with the specified duration in hours added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param hoursToAdd the hours to add, positive or negative
|
||||
* @return a {@code Duration} based on this duration with the specified hours added, not null
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
public Duration plusHours(long hoursToAdd) {
|
||||
return plus(Math.multiplyExact(hoursToAdd, SECONDS_PER_HOUR), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this duration with the specified duration in minutes added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param minutesToAdd the minutes to add, positive or negative
|
||||
* @return a {@code Duration} based on this duration with the specified minutes added, not null
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
public Duration plusMinutes(long minutesToAdd) {
|
||||
return plus(Math.multiplyExact(minutesToAdd, SECONDS_PER_MINUTE), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this duration with the specified duration in seconds added.
|
||||
* <p>
|
||||
@ -650,6 +805,52 @@ public final class Duration
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this duration with the specified duration in standard 24 hour days subtracted.
|
||||
* <p>
|
||||
* The number of days is multiplied by 86400 to obtain the number of seconds to subtract.
|
||||
* This is based on the standard definition of a day as 24 hours.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param daysToSubtract the days to subtract, positive or negative
|
||||
* @return a {@code Duration} based on this duration with the specified days subtracted, not null
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
public Duration minusDays(long daysToSubtract) {
|
||||
return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this duration with the specified duration in hours subtracted.
|
||||
* <p>
|
||||
* The number of hours is multiplied by 3600 to obtain the number of seconds to subtract.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param hoursToSubtract the hours to subtract, positive or negative
|
||||
* @return a {@code Duration} based on this duration with the specified hours subtracted, not null
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
public Duration minusHours(long hoursToSubtract) {
|
||||
return (hoursToSubtract == Long.MIN_VALUE ? plusHours(Long.MAX_VALUE).plusHours(1) : plusHours(-hoursToSubtract));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this duration with the specified duration in minutes subtracted.
|
||||
* <p>
|
||||
* The number of hours is multiplied by 60 to obtain the number of seconds to subtract.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param minutesToSubtract the minutes to subtract, positive or negative
|
||||
* @return a {@code Duration} based on this duration with the specified minutes subtracted, not null
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
public Duration minusMinutes(long minutesToSubtract) {
|
||||
return (minutesToSubtract == Long.MIN_VALUE ? plusMinutes(Long.MAX_VALUE).plusMinutes(1) : plusMinutes(-minutesToSubtract));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this duration with the specified duration in seconds subtracted.
|
||||
* <p>
|
||||
@ -716,8 +917,7 @@ public final class Duration
|
||||
*
|
||||
* @param divisor the value to divide the duration by, positive or negative, not zero
|
||||
* @return a {@code Duration} based on this duration divided by the specified divisor, not null
|
||||
* @throws ArithmeticException if the divisor is zero
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
* @throws ArithmeticException if the divisor is zero or if numeric overflow occurs
|
||||
*/
|
||||
public Duration dividedBy(long divisor) {
|
||||
if (divisor == 0) {
|
||||
@ -794,15 +994,15 @@ public final class Duration
|
||||
* with this duration added.
|
||||
* <p>
|
||||
* In most cases, it is clearer to reverse the calling pattern by using
|
||||
* {@link Temporal#plus(TemporalAdder)}.
|
||||
* {@link Temporal#plus(TemporalAmount)}.
|
||||
* <pre>
|
||||
* // these two lines are equivalent, but the second approach is recommended
|
||||
* dateTime = thisDuration.addTo(dateTime);
|
||||
* dateTime = dateTime.plus(thisDuration);
|
||||
* </pre>
|
||||
* <p>
|
||||
* A {@code Duration} can only be added to a {@code Temporal} that
|
||||
* represents an instant and can supply {@link ChronoField#INSTANT_SECONDS}.
|
||||
* The calculation will add the seconds, then nanos.
|
||||
* Only non-zero amounts will be added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
@ -813,13 +1013,13 @@ public final class Duration
|
||||
*/
|
||||
@Override
|
||||
public Temporal addTo(Temporal temporal) {
|
||||
long instantSecs = temporal.getLong(INSTANT_SECONDS);
|
||||
long instantNanos = temporal.getLong(NANO_OF_SECOND);
|
||||
instantSecs = Math.addExact(instantSecs, seconds);
|
||||
instantNanos = Math.addExact(instantNanos, nanos);
|
||||
instantSecs = Math.addExact(instantSecs, Math.floorDiv(instantNanos, NANOS_PER_SECOND));
|
||||
instantNanos = Math.floorMod(instantNanos, NANOS_PER_SECOND);
|
||||
return temporal.with(INSTANT_SECONDS, instantSecs).with(NANO_OF_SECOND, instantNanos);
|
||||
if (seconds != 0) {
|
||||
temporal = temporal.plus(seconds, SECONDS);
|
||||
}
|
||||
if (nanos != 0) {
|
||||
temporal = temporal.plus(nanos, NANOS);
|
||||
}
|
||||
return temporal;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -829,15 +1029,15 @@ public final class Duration
|
||||
* with this duration subtracted.
|
||||
* <p>
|
||||
* In most cases, it is clearer to reverse the calling pattern by using
|
||||
* {@link Temporal#minus(TemporalSubtractor)}.
|
||||
* {@link Temporal#minus(TemporalAmount)}.
|
||||
* <pre>
|
||||
* // these two lines are equivalent, but the second approach is recommended
|
||||
* dateTime = thisDuration.subtractFrom(dateTime);
|
||||
* dateTime = dateTime.minus(thisDuration);
|
||||
* </pre>
|
||||
* <p>
|
||||
* A {@code Duration} can only be subtracted from a {@code Temporal} that
|
||||
* represents an instant and can supply {@link ChronoField#INSTANT_SECONDS}.
|
||||
* The calculation will subtract the seconds, then nanos.
|
||||
* Only non-zero amounts will be added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
@ -848,16 +1048,59 @@ public final class Duration
|
||||
*/
|
||||
@Override
|
||||
public Temporal subtractFrom(Temporal temporal) {
|
||||
long instantSecs = temporal.getLong(INSTANT_SECONDS);
|
||||
long instantNanos = temporal.getLong(NANO_OF_SECOND);
|
||||
instantSecs = Math.subtractExact(instantSecs, seconds);
|
||||
instantNanos = Math.subtractExact(instantNanos, nanos);
|
||||
instantSecs = Math.addExact(instantSecs, Math.floorDiv(instantNanos, NANOS_PER_SECOND));
|
||||
instantNanos = Math.floorMod(instantNanos, NANOS_PER_SECOND);
|
||||
return temporal.with(INSTANT_SECONDS, instantSecs).with(NANO_OF_SECOND, instantNanos);
|
||||
if (seconds != 0) {
|
||||
temporal = temporal.minus(seconds, SECONDS);
|
||||
}
|
||||
if (nanos != 0) {
|
||||
temporal = temporal.minus(nanos, NANOS);
|
||||
}
|
||||
return temporal;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the number of minutes in this duration.
|
||||
* <p>
|
||||
* This returns the total number of minutes in the duration by dividing the
|
||||
* number of seconds by 86400.
|
||||
* This is based on the standard definition of a day as 24 hours.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @return the number of minutes in the duration, may be negative
|
||||
*/
|
||||
public long toDays() {
|
||||
return seconds / SECONDS_PER_DAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of minutes in this duration.
|
||||
* <p>
|
||||
* This returns the total number of minutes in the duration by dividing the
|
||||
* number of seconds by 3600.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @return the number of minutes in the duration, may be negative
|
||||
*/
|
||||
public long toHours() {
|
||||
return seconds / SECONDS_PER_HOUR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of minutes in this duration.
|
||||
* <p>
|
||||
* This returns the total number of minutes in the duration by dividing the
|
||||
* number of seconds by 60.
|
||||
* <p>
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this duration to the total length in milliseconds.
|
||||
* <p>
|
||||
@ -887,7 +1130,7 @@ public final class Duration
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
public long toNanos() {
|
||||
long millis = Math.multiplyExact(seconds, 1000_000_000);
|
||||
long millis = Math.multiplyExact(seconds, NANOS_PER_SECOND);
|
||||
millis = Math.addExact(millis, nanos);
|
||||
return millis;
|
||||
}
|
||||
@ -911,30 +1154,6 @@ public final class Duration
|
||||
return nanos - otherDuration.nanos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this duration is greater than the specified {@code Duration}.
|
||||
* <p>
|
||||
* The comparison is based on the total length of the durations.
|
||||
*
|
||||
* @param otherDuration the other duration to compare to, not null
|
||||
* @return true if this duration is greater than the specified duration
|
||||
*/
|
||||
public boolean isGreaterThan(Duration otherDuration) {
|
||||
return compareTo(otherDuration) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this duration is less than the specified {@code Duration}.
|
||||
* <p>
|
||||
* The comparison is based on the total length of the durations.
|
||||
*
|
||||
* @param otherDuration the other duration to compare to, not null
|
||||
* @return true if this duration is less than the specified duration
|
||||
*/
|
||||
public boolean isLessThan(Duration otherDuration) {
|
||||
return compareTo(otherDuration) < 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Checks if this duration is equal to the specified {@code Duration}.
|
||||
@ -970,29 +1189,57 @@ public final class Duration
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* A string representation of this duration using ISO-8601 seconds
|
||||
* based representation, such as {@code PT12.345S}.
|
||||
* based representation, such as {@code PT8H6M12.345S}.
|
||||
* <p>
|
||||
* The format of the returned string will be {@code PTnS} where n is
|
||||
* the seconds and fractional seconds of the duration.
|
||||
* The format of the returned string will be {@code PTnHnMnS}, where n is
|
||||
* the relevant hours, minutes or seconds part of the duration.
|
||||
* Any fractional seconds are placed after a decimal point i the seconds section.
|
||||
* If a section has a zero value, it is omitted.
|
||||
* The hours, minutes and seconds will all have the same sign.
|
||||
* <p>
|
||||
* Examples:
|
||||
* <pre>
|
||||
* "20.345 seconds" -> "PT20.345S
|
||||
* "15 minutes" (15 * 60 seconds) -> "PT15M"
|
||||
* "10 hours" (10 * 3600 seconds) -> "PT10H"
|
||||
* "2 days" (2 * 86400 seconds) -> "PT48H"
|
||||
* </pre>
|
||||
* Note that multiples of 24 hours are not output as days to avoid confusion
|
||||
* with {@code Period}.
|
||||
*
|
||||
* @return an ISO-8601 representation of this duration, not null
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
if (this == ZERO) {
|
||||
return "PT0S";
|
||||
}
|
||||
long hours = seconds / SECONDS_PER_HOUR;
|
||||
int minutes = (int) ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
|
||||
int secs = (int) (seconds % SECONDS_PER_MINUTE);
|
||||
StringBuilder buf = new StringBuilder(24);
|
||||
buf.append("PT");
|
||||
if (seconds < 0 && nanos > 0) {
|
||||
if (seconds == -1) {
|
||||
if (hours != 0) {
|
||||
buf.append(hours).append('H');
|
||||
}
|
||||
if (minutes != 0) {
|
||||
buf.append(minutes).append('M');
|
||||
}
|
||||
if (secs == 0 && nanos == 0 && buf.length() > 2) {
|
||||
return buf.toString();
|
||||
}
|
||||
if (secs < 0 && nanos > 0) {
|
||||
if (secs == -1) {
|
||||
buf.append("-0");
|
||||
} else {
|
||||
buf.append(seconds + 1);
|
||||
buf.append(secs + 1);
|
||||
}
|
||||
} else {
|
||||
buf.append(seconds);
|
||||
buf.append(secs);
|
||||
}
|
||||
if (nanos > 0) {
|
||||
int pos = buf.length();
|
||||
if (seconds < 0) {
|
||||
if (secs < 0) {
|
||||
buf.append(2 * NANOS_PER_SECOND - nanos);
|
||||
} else {
|
||||
buf.append(nanos + NANOS_PER_SECOND);
|
||||
|
||||
@ -61,6 +61,7 @@
|
||||
*/
|
||||
package java.time;
|
||||
|
||||
import static java.time.LocalTime.NANOS_PER_SECOND;
|
||||
import static java.time.LocalTime.SECONDS_PER_DAY;
|
||||
import static java.time.LocalTime.SECONDS_PER_HOUR;
|
||||
import static java.time.LocalTime.SECONDS_PER_MINUTE;
|
||||
@ -76,18 +77,17 @@ import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.time.format.DateTimeFormatters;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdder;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalSubtractor;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Objects;
|
||||
@ -225,10 +225,6 @@ public final class Instant
|
||||
* Serialization version.
|
||||
*/
|
||||
private static final long serialVersionUID = -665713676816604388L;
|
||||
/**
|
||||
* Constant for nanos per second.
|
||||
*/
|
||||
private static final int NANOS_PER_SECOND = 1000_000_000;
|
||||
|
||||
/**
|
||||
* The number of seconds from the epoch of 1970-01-01T00:00:00Z.
|
||||
@ -333,8 +329,9 @@ public final class Instant
|
||||
/**
|
||||
* Obtains an instance of {@code Instant} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code Instant}.
|
||||
* This obtains an instant based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code Instant}.
|
||||
* <p>
|
||||
* The conversion extracts the {@link ChronoField#INSTANT_SECONDS INSTANT_SECONDS}
|
||||
* and {@link ChronoField#NANO_OF_SECOND NANO_OF_SECOND} fields.
|
||||
@ -358,14 +355,14 @@ public final class Instant
|
||||
* {@code 2007-12-03T10:15:30:00}.
|
||||
* <p>
|
||||
* The string must represent a valid instant in UTC and is parsed using
|
||||
* {@link DateTimeFormatters#isoInstant()}.
|
||||
* {@link DateTimeFormatter#ISO_INSTANT}.
|
||||
*
|
||||
* @param text the text to parse, not null
|
||||
* @return the parsed instant, not null
|
||||
* @throws DateTimeParseException if the text cannot be parsed
|
||||
*/
|
||||
public static Instant parse(final CharSequence text) {
|
||||
return DateTimeFormatters.isoInstant().parse(text, Instant::from);
|
||||
return DateTimeFormatter.ISO_INSTANT.parse(text, Instant::from);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -418,7 +415,7 @@ public final class Instant
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -430,7 +427,7 @@ public final class Instant
|
||||
if (field instanceof ChronoField) {
|
||||
return field == INSTANT_SECONDS || field == NANO_OF_SECOND || field == MICRO_OF_SECOND || field == MILLI_OF_SECOND;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -447,7 +444,7 @@ public final class Instant
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -475,7 +472,7 @@ public final class Instant
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -495,7 +492,7 @@ public final class Instant
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return range(field).checkValidIntValue(field.doGet(this), field);
|
||||
return range(field).checkValidIntValue(field.getFrom(this), field);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -511,7 +508,7 @@ public final class Instant
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -531,7 +528,7 @@ public final class Instant
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -565,7 +562,7 @@ public final class Instant
|
||||
/**
|
||||
* Returns an adjusted copy of this instant.
|
||||
* <p>
|
||||
* This returns a new {@code Instant}, based on this one, with the date adjusted.
|
||||
* This returns an {@code Instant}, based on this one, with the instant adjusted.
|
||||
* The adjustment takes place using the specified adjuster strategy object.
|
||||
* Read the documentation of the adjuster to understand what adjustment will be made.
|
||||
* <p>
|
||||
@ -588,7 +585,7 @@ public final class Instant
|
||||
/**
|
||||
* Returns a copy of this instant with the specified field set to a new value.
|
||||
* <p>
|
||||
* This returns a new {@code Instant}, based on this one, with the value
|
||||
* This returns an {@code Instant}, based on this one, with the value
|
||||
* for the specified field changed.
|
||||
* If it is not possible to set the value, because the field is not supported or for
|
||||
* some other reason, an exception is thrown.
|
||||
@ -616,7 +613,7 @@ public final class Instant
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doWith(Temporal, long)}
|
||||
* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the field determines
|
||||
* whether and how to adjust the instant.
|
||||
* <p>
|
||||
@ -647,24 +644,130 @@ public final class Instant
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doWith(this, newValue);
|
||||
return field.adjustInto(this, newValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
* Returns a copy of this {@code Instant} truncated to the specified unit.
|
||||
* <p>
|
||||
* Truncating the instant returns a copy of the original with fields
|
||||
* smaller than the specified unit set to zero.
|
||||
* The fields are calculated on the basis of using a UTC offset as seen
|
||||
* in {@code toString}.
|
||||
* For example, truncating with the {@link ChronoUnit#MINUTES MINUTES} unit will
|
||||
* round down to the nearest minute, setting the seconds and nanoseconds to zero.
|
||||
* <p>
|
||||
* The unit must have a {@linkplain TemporalUnit#getDuration() duration}
|
||||
* that divides into the length of a standard day without remainder.
|
||||
* This includes all supplied time units on {@link ChronoUnit} and
|
||||
* {@link ChronoUnit#DAYS DAYS}. Other units throw an exception.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param unit the unit to truncate to, not null
|
||||
* @return an {@code Instant} based on this instant with the time truncated, not null
|
||||
* @throws DateTimeException if the unit is invalid for truncation
|
||||
*/
|
||||
public Instant truncatedTo(TemporalUnit unit) {
|
||||
if (unit == ChronoUnit.NANOS) {
|
||||
return this;
|
||||
}
|
||||
Duration unitDur = unit.getDuration();
|
||||
if (unitDur.getSeconds() > LocalTime.SECONDS_PER_DAY) {
|
||||
throw new DateTimeException("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");
|
||||
}
|
||||
long nod = (seconds % LocalTime.SECONDS_PER_DAY) * LocalTime.NANOS_PER_SECOND + nanos;
|
||||
long result = (nod / dur) * dur;
|
||||
return plusNanos(result - nod);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this instant with the specified amount added.
|
||||
* <p>
|
||||
* This returns an {@code Instant}, based on this one, with the specified amount added.
|
||||
* The amount is typically {@link Duration} but may be any other type implementing
|
||||
* the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free
|
||||
* to implement the addition in any way it wishes, however it typically
|
||||
* calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToAdd the amount to add, not null
|
||||
* @return an {@code Instant} based on this instant with the addition made, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public Instant plus(TemporalAdder adder) {
|
||||
return (Instant) adder.addTo(this);
|
||||
public Instant plus(TemporalAmount amountToAdd) {
|
||||
return (Instant) amountToAdd.addTo(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
* Returns a copy of this instant with the specified amount added.
|
||||
* <p>
|
||||
* This returns an {@code Instant}, based on this one, with the amount
|
||||
* in terms of the unit added. If it is not possible to add the amount, because the
|
||||
* unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoUnit} then the addition is implemented here.
|
||||
* The supported fields behave as follows:
|
||||
* <ul>
|
||||
* <li>{@code NANOS} -
|
||||
* Returns a {@code Instant} with the specified number of nanoseconds added.
|
||||
* This is equivalent to {@link #plusNanos(long)}.
|
||||
* <li>{@code MICROS} -
|
||||
* Returns a {@code Instant} with the specified number of microseconds added.
|
||||
* This is equivalent to {@link #plusNanos(long)} with the amount
|
||||
* multiplied by 1,000.
|
||||
* <li>{@code MILLIS} -
|
||||
* Returns a {@code Instant} with the specified number of milliseconds added.
|
||||
* This is equivalent to {@link #plusNanos(long)} with the amount
|
||||
* multiplied by 1,000,000.
|
||||
* <li>{@code SECONDS} -
|
||||
* Returns a {@code Instant} with the specified number of seconds added.
|
||||
* This is equivalent to {@link #plusSeconds(long)}.
|
||||
* <li>{@code MINUTES} -
|
||||
* Returns a {@code Instant} with the specified number of minutes added.
|
||||
* This is equivalent to {@link #plusSeconds(long)} with the amount
|
||||
* multiplied by 60.
|
||||
* <li>{@code HOURS} -
|
||||
* Returns a {@code Instant} with the specified number of hours added.
|
||||
* This is equivalent to {@link #plusSeconds(long)} with the amount
|
||||
* multiplied by 3,600.
|
||||
* <li>{@code HALF_DAYS} -
|
||||
* Returns a {@code Instant} with the specified number of half-days added.
|
||||
* This is equivalent to {@link #plusSeconds(long)} with the amount
|
||||
* multiplied by 43,200 (12 hours).
|
||||
* <li>{@code DAYS} -
|
||||
* Returns a {@code Instant} with the specified number of days added.
|
||||
* This is equivalent to {@link #plusSeconds(long)} with the amount
|
||||
* multiplied by 86,400 (24 hours).
|
||||
* </ul>
|
||||
* <p>
|
||||
* All other {@code ChronoUnit} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoUnit}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the unit determines
|
||||
* whether and how to perform the addition.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToAdd the amount of the unit to add to the result, may be negative
|
||||
* @param unit the unit of the amount to add, not null
|
||||
* @return an {@code Instant} based on this instant with the specified amount added, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public Instant plus(long amountToAdd, TemporalUnit unit) {
|
||||
@ -681,7 +784,7 @@ public final class Instant
|
||||
}
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
return unit.doPlus(this, amountToAdd);
|
||||
return unit.addTo(this, amountToAdd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -751,19 +854,47 @@ public final class Instant
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
* Returns a copy of this instant with the specified amount subtracted.
|
||||
* <p>
|
||||
* This returns an {@code Instant}, based on this one, with the specified amount subtracted.
|
||||
* The amount is typically {@link Duration} but may be any other type implementing
|
||||
* the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free
|
||||
* to implement the subtraction in any way it wishes, however it typically
|
||||
* calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully subtracted.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToSubtract the amount to subtract, not null
|
||||
* @return an {@code Instant} based on this instant with the subtraction made, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public Instant minus(TemporalSubtractor subtractor) {
|
||||
return (Instant) subtractor.subtractFrom(this);
|
||||
public Instant minus(TemporalAmount amountToSubtract) {
|
||||
return (Instant) amountToSubtract.subtractFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
* Returns a copy of this instant with the specified amount subtracted.
|
||||
* <p>
|
||||
* This returns a {@code Instant}, based on this one, with the amount
|
||||
* in terms of the unit subtracted. If it is not possible to subtract the amount,
|
||||
* because the unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.
|
||||
* See that method for a full description of how addition, and thus subtraction, works.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToSubtract the amount of the unit to subtract from the result, may be negative
|
||||
* @param unit the unit of the amount to subtract, not null
|
||||
* @return an {@code Instant} based on this instant with the specified amount subtracted, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public Instant minus(long amountToSubtract, TemporalUnit unit) {
|
||||
@ -848,7 +979,7 @@ public final class Instant
|
||||
return (R) NANOS;
|
||||
}
|
||||
// inline TemporalAccessor.super.query(query) as an optimization
|
||||
if (query == Queries.chrono() || query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
|
||||
if (query == Queries.chronology() || query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
|
||||
return null;
|
||||
}
|
||||
return query.queryFrom(this);
|
||||
@ -945,7 +1076,7 @@ public final class Instant
|
||||
}
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
return unit.between(this, endInstant).getAmount();
|
||||
return unit.between(this, endInstant);
|
||||
}
|
||||
|
||||
private long nanosUntil(Instant end) {
|
||||
@ -957,6 +1088,43 @@ public final class Instant
|
||||
return Math.subtractExact(end.seconds, seconds);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Combines this instant with an offset to create an {@code OffsetDateTime}.
|
||||
* <p>
|
||||
* This returns an {@code OffsetDateTime} formed from this instant at the
|
||||
* specified offset from UTC/Greenwich. An exception will be thrown if the
|
||||
* instant is too large to fit into an offset date-time.
|
||||
* <p>
|
||||
* This method is equivalent to
|
||||
* {@link OffsetDateTime#ofInstant(Instant, ZoneId) OffsetDateTime.ofInstant(this, offset)}.
|
||||
*
|
||||
* @param offset the offset to combine with, not null
|
||||
* @return the offset date-time formed from this instant and the specified offset, not null
|
||||
* @throws DateTimeException if the result exceeds the supported range
|
||||
*/
|
||||
public OffsetDateTime atOffset(ZoneOffset offset) {
|
||||
return OffsetDateTime.ofInstant(this, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines this instant with a time-zone to create a {@code ZonedDateTime}.
|
||||
* <p>
|
||||
* This returns an {@code ZonedDateTime} formed from this instant at the
|
||||
* specified time-zone. An exception will be thrown if the instant is too
|
||||
* large to fit into a zoned date-time.
|
||||
* <p>
|
||||
* This method is equivalent to
|
||||
* {@link ZonedDateTime#ofInstant(Instant, ZoneId) ZonedDateTime.ofInstant(this, zone)}.
|
||||
*
|
||||
* @param zone the zone to combine with, not null
|
||||
* @return the zoned date-time formed from this instant and the specified zone, not null
|
||||
* @throws DateTimeException if the result exceeds the supported range
|
||||
*/
|
||||
public ZonedDateTime atZone(ZoneId zone) {
|
||||
return ZonedDateTime.ofInstant(this, zone);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Converts this instant to the number of milliseconds from the epoch
|
||||
@ -1059,13 +1227,13 @@ public final class Instant
|
||||
/**
|
||||
* A string representation of this instant using ISO-8601 representation.
|
||||
* <p>
|
||||
* The format used is the same as {@link DateTimeFormatters#isoInstant()}.
|
||||
* The format used is the same as {@link DateTimeFormatter#ISO_INSTANT}.
|
||||
*
|
||||
* @return an ISO-8601 representation of this instant, not null
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return DateTimeFormatters.isoInstant().print(this);
|
||||
return DateTimeFormatter.ISO_INSTANT.format(this);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
@ -80,26 +80,22 @@ import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.time.format.DateTimeBuilder;
|
||||
import java.time.chrono.ChronoLocalDate;
|
||||
import java.time.chrono.Era;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatters;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.Era;
|
||||
import java.time.temporal.ISOChrono;
|
||||
import java.time.temporal.OffsetDate;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdder;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalSubtractor;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.time.temporal.Year;
|
||||
import java.time.zone.ZoneOffsetTransition;
|
||||
import java.time.zone.ZoneRules;
|
||||
import java.util.Objects;
|
||||
@ -131,7 +127,7 @@ import java.util.Objects;
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class LocalDate
|
||||
implements Temporal, TemporalAdjuster, ChronoLocalDate<ISOChrono>, Serializable {
|
||||
implements Temporal, TemporalAdjuster, ChronoLocalDate<LocalDate>, Serializable {
|
||||
|
||||
/**
|
||||
* The minimum supported {@code LocalDate}, '-999999999-01-01'.
|
||||
@ -216,7 +212,7 @@ public final class LocalDate
|
||||
*/
|
||||
public static LocalDate now(Clock clock) {
|
||||
Objects.requireNonNull(clock, "clock");
|
||||
// inline OffsetDate factory to avoid creating object and InstantProvider checks
|
||||
// inline to avoid creating object and Instant checks
|
||||
final Instant now = clock.instant(); // called once
|
||||
ZoneOffset offset = clock.getZone().getRules().getOffset(now);
|
||||
long epochSec = now.getEpochSecond() + offset.getTotalSeconds(); // overflow caught later
|
||||
@ -228,14 +224,15 @@ public final class LocalDate
|
||||
/**
|
||||
* Obtains an instance of {@code LocalDate} from a year, month and day.
|
||||
* <p>
|
||||
* This returns a {@code LocalDate} with the specified year, month and day-of-month.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param year the year to represent, from MIN_YEAR to MAX_YEAR
|
||||
* @param month the month-of-year to represent, not null
|
||||
* @param dayOfMonth the day-of-month to represent, from 1 to 31
|
||||
* @return the local date, not null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static LocalDate of(int year, Month month, int dayOfMonth) {
|
||||
YEAR.checkValidValue(year);
|
||||
@ -247,14 +244,15 @@ public final class LocalDate
|
||||
/**
|
||||
* Obtains an instance of {@code LocalDate} from a year, month and day.
|
||||
* <p>
|
||||
* This returns a {@code LocalDate} with the specified year, month and day-of-month.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param year the year to represent, from MIN_YEAR to MAX_YEAR
|
||||
* @param month the month-of-year to represent, from 1 (January) to 12 (December)
|
||||
* @param dayOfMonth the day-of-month to represent, from 1 to 31
|
||||
* @return the local date, not null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static LocalDate of(int year, int month, int dayOfMonth) {
|
||||
YEAR.checkValidValue(year);
|
||||
@ -267,18 +265,19 @@ public final class LocalDate
|
||||
/**
|
||||
* Obtains an instance of {@code LocalDate} from a year and day-of-year.
|
||||
* <p>
|
||||
* This returns a {@code LocalDate} with the specified year and day-of-year.
|
||||
* The day-of-year must be valid for the year, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param year the year to represent, from MIN_YEAR to MAX_YEAR
|
||||
* @param dayOfYear the day-of-year to represent, from 1 to 366
|
||||
* @return the local date, not null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
* @throws DateTimeException if the day-of-year is invalid for the month-year
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-year is invalid for the month-year
|
||||
*/
|
||||
public static LocalDate ofYearDay(int year, int dayOfYear) {
|
||||
YEAR.checkValidValue(year);
|
||||
DAY_OF_YEAR.checkValidValue(dayOfYear);
|
||||
boolean leap = ISOChrono.INSTANCE.isLeapYear(year);
|
||||
boolean leap = IsoChronology.INSTANCE.isLeapYear(year);
|
||||
if (dayOfYear == 366 && leap == false) {
|
||||
throw new DateTimeException("Invalid date 'DayOfYear 366' as '" + year + "' is not a leap year");
|
||||
}
|
||||
@ -295,8 +294,9 @@ public final class LocalDate
|
||||
/**
|
||||
* Obtains an instance of {@code LocalDate} from the epoch day count.
|
||||
* <p>
|
||||
* The Epoch Day count is a simple incrementing count of days
|
||||
* where day 0 is 1970-01-01. Negative numbers represent earlier days.
|
||||
* This returns a {@code LocalDate} with the specified epoch-day.
|
||||
* The {@link ChronoField#EPOCH_DAY EPOCH_DAY} is a simple incrementing count
|
||||
* of days where day 0 is 1970-01-01. Negative numbers represent earlier days.
|
||||
*
|
||||
* @param epochDay the Epoch Day to convert, based on the epoch 1970-01-01
|
||||
* @return the local date, not null
|
||||
@ -338,10 +338,12 @@ public final class LocalDate
|
||||
/**
|
||||
* Obtains an instance of {@code LocalDate} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code LocalDate}.
|
||||
* This obtains a local date based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code LocalDate}.
|
||||
* <p>
|
||||
* The conversion extracts the {@link ChronoField#EPOCH_DAY EPOCH_DAY} field.
|
||||
* The conversion uses the {@link Queries#localDate()} query, which relies
|
||||
* on extracting the {@link ChronoField#EPOCH_DAY EPOCH_DAY} field.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used as a query via method reference, {@code LocalDate::from}.
|
||||
@ -351,26 +353,11 @@ public final class LocalDate
|
||||
* @throws DateTimeException if unable to convert to a {@code LocalDate}
|
||||
*/
|
||||
public static LocalDate from(TemporalAccessor temporal) {
|
||||
if (temporal instanceof LocalDate) {
|
||||
return (LocalDate) temporal;
|
||||
} else if (temporal instanceof LocalDateTime) {
|
||||
return ((LocalDateTime) temporal).getDate();
|
||||
} else if (temporal instanceof ZonedDateTime) {
|
||||
return ((ZonedDateTime) temporal).getDate();
|
||||
}
|
||||
// handle builder as a special case
|
||||
if (temporal instanceof DateTimeBuilder) {
|
||||
DateTimeBuilder builder = (DateTimeBuilder) temporal;
|
||||
LocalDate date = builder.extract(LocalDate.class);
|
||||
if (date != null) {
|
||||
return date;
|
||||
}
|
||||
}
|
||||
try {
|
||||
return ofEpochDay(temporal.getLong(EPOCH_DAY));
|
||||
} catch (DateTimeException ex) {
|
||||
throw new DateTimeException("Unable to obtain LocalDate from TemporalAccessor: " + temporal.getClass(), ex);
|
||||
LocalDate date = temporal.query(Queries.localDate());
|
||||
if (date == null) {
|
||||
throw new DateTimeException("Unable to obtain LocalDate from TemporalAccessor: " + temporal.getClass());
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -378,14 +365,14 @@ public final class LocalDate
|
||||
* Obtains an instance of {@code LocalDate} from a text string such as {@code 2007-12-03}.
|
||||
* <p>
|
||||
* The string must represent a valid date and is parsed using
|
||||
* {@link java.time.format.DateTimeFormatters#isoLocalDate()}.
|
||||
* {@link java.time.format.DateTimeFormatter#ISO_LOCAL_DATE}.
|
||||
*
|
||||
* @param text the text to parse such as "2007-12-03", not null
|
||||
* @return the parsed local date, not null
|
||||
* @throws DateTimeParseException if the text cannot be parsed
|
||||
*/
|
||||
public static LocalDate parse(CharSequence text) {
|
||||
return parse(text, DateTimeFormatters.isoLocalDate());
|
||||
return parse(text, DateTimeFormatter.ISO_LOCAL_DATE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -414,7 +401,7 @@ public final class LocalDate
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
private static LocalDate create(int year, Month month, int dayOfMonth) {
|
||||
if (dayOfMonth > 28 && dayOfMonth > month.length(ISOChrono.INSTANCE.isLeapYear(year))) {
|
||||
if (dayOfMonth > 28 && dayOfMonth > month.length(IsoChronology.INSTANCE.isLeapYear(year))) {
|
||||
if (dayOfMonth == 29) {
|
||||
throw new DateTimeException("Invalid date 'February 29' as '" + year + "' is not a leap year");
|
||||
} else {
|
||||
@ -435,7 +422,7 @@ public final class LocalDate
|
||||
private static LocalDate resolvePreviousValid(int year, int month, int day) {
|
||||
switch (month) {
|
||||
case 2:
|
||||
day = Math.min(day, ISOChrono.INSTANCE.isLeapYear(year) ? 29 : 28);
|
||||
day = Math.min(day, IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
@ -469,8 +456,6 @@ public final class LocalDate
|
||||
* {@link #get(TemporalField) get} methods will throw an exception.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoField} then the query is implemented here.
|
||||
* The {@link #isSupported(TemporalField) supported fields} will return valid
|
||||
* values based on this date-time.
|
||||
* The supported fields are:
|
||||
* <ul>
|
||||
* <li>{@code DAY_OF_WEEK}
|
||||
@ -490,7 +475,7 @@ public final class LocalDate
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -516,7 +501,7 @@ public final class LocalDate
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -540,7 +525,7 @@ public final class LocalDate
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doRange(this);
|
||||
return field.rangeRefinedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -558,7 +543,7 @@ public final class LocalDate
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -588,7 +573,7 @@ public final class LocalDate
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -608,7 +593,7 @@ public final class LocalDate
|
||||
}
|
||||
return get0(field);
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
private int get0(TemporalField field) {
|
||||
@ -638,7 +623,7 @@ public final class LocalDate
|
||||
/**
|
||||
* Gets the chronology of this date, which is the ISO calendar system.
|
||||
* <p>
|
||||
* The {@code Chrono} represents the calendar system in use.
|
||||
* The {@code Chronology} represents the calendar system in use.
|
||||
* The ISO-8601 calendar system is the modern civil calendar system used today
|
||||
* in most of the world. It is equivalent to the proleptic Gregorian calendar
|
||||
* system, in which todays's rules for leap years are applied for all time.
|
||||
@ -646,14 +631,14 @@ public final class LocalDate
|
||||
* @return the ISO chronology, not null
|
||||
*/
|
||||
@Override
|
||||
public ISOChrono getChrono() {
|
||||
return ISOChrono.INSTANCE;
|
||||
public IsoChronology getChronology() {
|
||||
return IsoChronology.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the era applicable at this date.
|
||||
* <p>
|
||||
* The official ISO-8601 standard does not define eras, however {@code ISOChrono} does.
|
||||
* The official ISO-8601 standard does not define eras, however {@code IsoChronology} does.
|
||||
* It defines two eras, 'CE' from year one onwards and 'BCE' from year zero backwards.
|
||||
* Since dates before the Julian-Gregorian cutover are not in line with history,
|
||||
* the cutover between 'BCE' and 'CE' is also not aligned with the commonly used
|
||||
@ -664,12 +649,12 @@ public final class LocalDate
|
||||
* the Japanese calendar system.
|
||||
* <p>
|
||||
* The returned era will be a singleton capable of being compared with the constants
|
||||
* in {@link ISOChrono} using the {@code ==} operator.
|
||||
* in {@link IsoChronology} using the {@code ==} operator.
|
||||
*
|
||||
* @return the {@code ISOChrono} era constant applicable at this date, not null
|
||||
* @return the {@code IsoChronology} era constant applicable at this date, not null
|
||||
*/
|
||||
@Override // override for Javadoc
|
||||
public Era<ISOChrono> getEra() {
|
||||
public Era getEra() {
|
||||
return ChronoLocalDate.super.getEra();
|
||||
}
|
||||
|
||||
@ -679,7 +664,7 @@ public final class LocalDate
|
||||
* This method returns the primitive {@code int} value for the year.
|
||||
* <p>
|
||||
* The year returned by this method is proleptic as per {@code get(YEAR)}.
|
||||
* To obtain the year-of-era, use {@code get(YEAR_OF_ERA}.
|
||||
* To obtain the year-of-era, use {@code get(YEAR_OF_ERA)}.
|
||||
*
|
||||
* @return the year, from MIN_YEAR to MAX_YEAR
|
||||
*/
|
||||
@ -777,7 +762,7 @@ public final class LocalDate
|
||||
*/
|
||||
@Override // override for Javadoc and performance
|
||||
public boolean isLeapYear() {
|
||||
return ISOChrono.INSTANCE.isLeapYear(year);
|
||||
return IsoChronology.INSTANCE.isLeapYear(year);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -819,7 +804,7 @@ public final class LocalDate
|
||||
/**
|
||||
* Returns an adjusted copy of this date.
|
||||
* <p>
|
||||
* This returns a new {@code LocalDate}, based on this one, with the date adjusted.
|
||||
* This returns a {@code LocalDate}, based on this one, with the date adjusted.
|
||||
* The adjustment takes place using the specified adjuster strategy object.
|
||||
* Read the documentation of the adjuster to understand what adjustment will be made.
|
||||
* <p>
|
||||
@ -828,7 +813,7 @@ public final class LocalDate
|
||||
* A selection of common adjustments is provided in {@link java.time.temporal.Adjusters}.
|
||||
* These include finding the "last day of the month" and "next Wednesday".
|
||||
* Key date-time classes also implement the {@code TemporalAdjuster} interface,
|
||||
* such as {@link Month} and {@link java.time.temporal.MonthDay MonthDay}.
|
||||
* such as {@link Month} and {@link java.time.MonthDay MonthDay}.
|
||||
* The adjuster is responsible for handling special cases, such as the varying
|
||||
* lengths of month and leap years.
|
||||
* <p>
|
||||
@ -863,7 +848,7 @@ public final class LocalDate
|
||||
/**
|
||||
* Returns a copy of this date with the specified field set to a new value.
|
||||
* <p>
|
||||
* This returns a new {@code LocalDate}, based on this one, with the value
|
||||
* This returns a {@code LocalDate}, based on this one, with the value
|
||||
* for the specified field changed.
|
||||
* This can be used to change any supported field, such as the year, month or day-of-month.
|
||||
* If it is not possible to set the value, because the field is not supported or for
|
||||
@ -951,7 +936,7 @@ public final class LocalDate
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doWith(Temporal, long)}
|
||||
* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the field determines
|
||||
* whether and how to adjust the instant.
|
||||
* <p>
|
||||
@ -985,7 +970,7 @@ public final class LocalDate
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doWith(this, newValue);
|
||||
return field.adjustInto(this, newValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -1033,8 +1018,8 @@ public final class LocalDate
|
||||
*
|
||||
* @param dayOfMonth the day-of-month to set in the result, from 1 to 28-31
|
||||
* @return a {@code LocalDate} based on this date with the requested day, not null
|
||||
* @throws DateTimeException if the day-of-month value is invalid
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
* @throws DateTimeException if the day-of-month value is invalid,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public LocalDate withDayOfMonth(int dayOfMonth) {
|
||||
if (this.day == dayOfMonth) {
|
||||
@ -1051,8 +1036,8 @@ public final class LocalDate
|
||||
*
|
||||
* @param dayOfYear the day-of-year to set in the result, from 1 to 365-366
|
||||
* @return a {@code LocalDate} based on this date with the requested day, not null
|
||||
* @throws DateTimeException if the day-of-year value is invalid
|
||||
* @throws DateTimeException if the day-of-year is invalid for the year
|
||||
* @throws DateTimeException if the day-of-year value is invalid,
|
||||
* or if the day-of-year is invalid for the year
|
||||
*/
|
||||
public LocalDate withDayOfYear(int dayOfYear) {
|
||||
if (this.getDayOfYear() == dayOfYear) {
|
||||
@ -1063,40 +1048,109 @@ public final class LocalDate
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this date with the specified period added.
|
||||
* Returns a copy of this date with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new date based on this date with the specified period added.
|
||||
* The adder is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalAdder} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #plus(long, TemporalUnit)}.
|
||||
* This returns a {@code LocalDate}, based on this one, with the specified amount added.
|
||||
* The amount is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free
|
||||
* to implement the addition in any way it wishes, however it typically
|
||||
* calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param adder the adder to use, not null
|
||||
* @param amountToAdd the amount to add, not null
|
||||
* @return a {@code LocalDate} based on this date with the addition made, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public LocalDate plus(TemporalAdder adder) {
|
||||
return (LocalDate) adder.addTo(this);
|
||||
public LocalDate plus(TemporalAmount amountToAdd) {
|
||||
return (LocalDate) amountToAdd.addTo(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this date with the specified period added.
|
||||
* Returns a copy of this date with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new date based on this date with the specified period added.
|
||||
* This can be used to add any period that is defined by a unit, for example to add years, months or days.
|
||||
* The unit is responsible for the details of the calculation, including the resolution
|
||||
* of any edge cases in the calculation.
|
||||
* This returns a {@code LocalDate}, based on this one, with the amount
|
||||
* in terms of the unit added. If it is not possible to add the amount, because the
|
||||
* unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* In some cases, adding the amount can cause the resulting date to become invalid.
|
||||
* For example, adding one month to 31st January would result in 31st February.
|
||||
* In cases like this, the unit is responsible for resolving the date.
|
||||
* Typically it will choose the previous valid date, which would be the last valid
|
||||
* day of February in this example.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoUnit} then the addition is implemented here.
|
||||
* The supported fields behave as follows:
|
||||
* <ul>
|
||||
* <li>{@code DAYS} -
|
||||
* Returns a {@code LocalDate} with the specified number of days added.
|
||||
* This is equivalent to {@link #plusDays(long)}.
|
||||
* <li>{@code WEEKS} -
|
||||
* Returns a {@code LocalDate} with the specified number of weeks added.
|
||||
* This is equivalent to {@link #plusWeeks(long)} and uses a 7 day week.
|
||||
* <li>{@code MONTHS} -
|
||||
* Returns a {@code LocalDate} with the specified number of months added.
|
||||
* This is equivalent to {@link #plusMonths(long)}.
|
||||
* The day-of-month will be unchanged unless it would be invalid for the new
|
||||
* month and year. In that case, the day-of-month is adjusted to the maximum
|
||||
* valid value for the new month and year.
|
||||
* <li>{@code YEARS} -
|
||||
* Returns a {@code LocalDate} with the specified number of years added.
|
||||
* This is equivalent to {@link #plusYears(long)}.
|
||||
* The day-of-month will be unchanged unless it would be invalid for the new
|
||||
* month and year. In that case, the day-of-month is adjusted to the maximum
|
||||
* valid value for the new month and year.
|
||||
* <li>{@code DECADES} -
|
||||
* Returns a {@code LocalDate} with the specified number of decades added.
|
||||
* This is equivalent to calling {@link #plusYears(long)} with the amount
|
||||
* multiplied by 10.
|
||||
* The day-of-month will be unchanged unless it would be invalid for the new
|
||||
* month and year. In that case, the day-of-month is adjusted to the maximum
|
||||
* valid value for the new month and year.
|
||||
* <li>{@code CENTURIES} -
|
||||
* Returns a {@code LocalDate} with the specified number of centuries added.
|
||||
* This is equivalent to calling {@link #plusYears(long)} with the amount
|
||||
* multiplied by 100.
|
||||
* The day-of-month will be unchanged unless it would be invalid for the new
|
||||
* month and year. In that case, the day-of-month is adjusted to the maximum
|
||||
* valid value for the new month and year.
|
||||
* <li>{@code MILLENNIA} -
|
||||
* Returns a {@code LocalDate} with the specified number of millennia added.
|
||||
* This is equivalent to calling {@link #plusYears(long)} with the amount
|
||||
* multiplied by 1,000.
|
||||
* The day-of-month will be unchanged unless it would be invalid for the new
|
||||
* month and year. In that case, the day-of-month is adjusted to the maximum
|
||||
* valid value for the new month and year.
|
||||
* <li>{@code ERAS} -
|
||||
* Returns a {@code LocalDate} with the specified number of eras added.
|
||||
* Only two eras are supported so the amount must be one, zero or minus one.
|
||||
* If the amount is non-zero then the year is changed such that the year-of-era
|
||||
* is unchanged.
|
||||
* The day-of-month will be unchanged unless it would be invalid for the new
|
||||
* month and year. In that case, the day-of-month is adjusted to the maximum
|
||||
* valid value for the new month and year.
|
||||
* </ul>
|
||||
* <p>
|
||||
* All other {@code ChronoUnit} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoUnit}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the unit determines
|
||||
* whether and how to perform the addition.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToAdd the amount of the unit to add to the result, may be negative
|
||||
* @param unit the unit of the period to add, not null
|
||||
* @return a {@code LocalDate} based on this date with the specified period added, not null
|
||||
* @throws DateTimeException if the unit cannot be added to this type
|
||||
* @param unit the unit of the amount to add, not null
|
||||
* @return a {@code LocalDate} based on this date with the specified amount added, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public LocalDate plus(long amountToAdd, TemporalUnit unit) {
|
||||
@ -1114,7 +1168,7 @@ public final class LocalDate
|
||||
}
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
return unit.doPlus(this, amountToAdd);
|
||||
return unit.addTo(this, amountToAdd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -1221,40 +1275,47 @@ public final class LocalDate
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this date with the specified period subtracted.
|
||||
* Returns a copy of this date with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new date based on this date with the specified period subtracted.
|
||||
* The subtractor is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalSubtractor} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #minus(long, TemporalUnit)}.
|
||||
* This returns a {@code LocalDate}, based on this one, with the specified amount subtracted.
|
||||
* The amount is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free
|
||||
* to implement the subtraction in any way it wishes, however it typically
|
||||
* calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully subtracted.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param subtractor the subtractor to use, not null
|
||||
* @param amountToSubtract the amount to subtract, not null
|
||||
* @return a {@code LocalDate} based on this date with the subtraction made, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public LocalDate minus(TemporalSubtractor subtractor) {
|
||||
return (LocalDate) subtractor.subtractFrom(this);
|
||||
public LocalDate minus(TemporalAmount amountToSubtract) {
|
||||
return (LocalDate) amountToSubtract.subtractFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this date with the specified period subtracted.
|
||||
* Returns a copy of this date with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new date based on this date with the specified period subtracted.
|
||||
* This can be used to subtract any period that is defined by a unit, for example to subtract years, months or days.
|
||||
* The unit is responsible for the details of the calculation, including the resolution
|
||||
* of any edge cases in the calculation.
|
||||
* This returns a {@code LocalDate}, based on this one, with the amount
|
||||
* in terms of the unit subtracted. If it is not possible to subtract the amount,
|
||||
* because the unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.
|
||||
* See that method for a full description of how addition, and thus subtraction, works.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToSubtract the amount of the unit to subtract from the result, may be negative
|
||||
* @param unit the unit of the period to subtract, not null
|
||||
* @return a {@code LocalDate} based on this date with the specified period subtracted, not null
|
||||
* @throws DateTimeException if the unit cannot be added to this type
|
||||
* @param unit the unit of the amount to subtract, not null
|
||||
* @return a {@code LocalDate} based on this date with the specified amount subtracted, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public LocalDate minus(long amountToSubtract, TemporalUnit unit) {
|
||||
@ -1367,8 +1428,12 @@ public final class LocalDate
|
||||
* @throws DateTimeException if unable to query (defined by the query)
|
||||
* @throws ArithmeticException if numeric overflow occurs (defined by the query)
|
||||
*/
|
||||
@Override // override for Javadoc
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.localDate()) {
|
||||
return (R) this;
|
||||
}
|
||||
return ChronoLocalDate.super.query(query);
|
||||
}
|
||||
|
||||
@ -1417,14 +1482,15 @@ public final class LocalDate
|
||||
* For example, the period in months between 2012-06-15 and 2012-08-14
|
||||
* will only be one month as it is one day short of two months.
|
||||
* <p>
|
||||
* This method operates in association with {@link TemporalUnit#between}.
|
||||
* The result of this method is a {@code long} representing the amount of
|
||||
* the specified unit. By contrast, the result of {@code between} is an
|
||||
* object that can be used directly in addition/subtraction:
|
||||
* There are two equivalent ways of using this method.
|
||||
* The first is to invoke this method.
|
||||
* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
|
||||
* <pre>
|
||||
* long period = start.periodUntil(end, MONTHS); // this method
|
||||
* dateTime.plus(MONTHS.between(start, end)); // use in plus/minus
|
||||
* // these two lines are equivalent
|
||||
* amount = start.periodUntil(end, MONTHS);
|
||||
* amount = MONTHS.between(start, end);
|
||||
* </pre>
|
||||
* The choice should be made based on which makes the code more readable.
|
||||
* <p>
|
||||
* The calculation is implemented in this method for {@link ChronoUnit}.
|
||||
* The units {@code DAYS}, {@code WEEKS}, {@code MONTHS}, {@code YEARS},
|
||||
@ -1464,7 +1530,7 @@ public final class LocalDate
|
||||
}
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
return unit.between(this, endDate).getAmount();
|
||||
return unit.between(this, endDate);
|
||||
}
|
||||
|
||||
long daysUntil(LocalDate end) {
|
||||
@ -1477,14 +1543,64 @@ public final class LocalDate
|
||||
return (packed2 - packed1) / 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the period between this date and another date as a {@code Period}.
|
||||
* <p>
|
||||
* This calculates the period between two dates in terms of years, months and days.
|
||||
* The start and end points are {@code this} and the specified date.
|
||||
* The result will be negative if the end is before the start.
|
||||
* <p>
|
||||
* The calculation is performed using the ISO calendar system.
|
||||
* If necessary, the input date will be converted to ISO.
|
||||
* <p>
|
||||
* The start date is included, but the end date is not.
|
||||
* The period is calculated by removing complete months, then calculating
|
||||
* the remaining number of days, adjusting to ensure that both have the same sign.
|
||||
* The number of months is then normalized into years and months based on a 12 month year.
|
||||
* A month is considered to be complete if the end day-of-month is greater
|
||||
* than or equal to the start day-of-month.
|
||||
* For example, from {@code 2010-01-15} to {@code 2011-03-18} is "1 year, 2 months and 3 days".
|
||||
* <p>
|
||||
* The result of this method can be a negative period if the end is before the start.
|
||||
* The negative sign will be the same in each of year, month and day.
|
||||
* <p>
|
||||
* There are two equivalent ways of using this method.
|
||||
* The first is to invoke this method.
|
||||
* The second is to use {@link Period#between(LocalDate, LocalDate)}:
|
||||
* <pre>
|
||||
* // these two lines are equivalent
|
||||
* period = start.periodUntil(end);
|
||||
* period = Period.between(start, end);
|
||||
* </pre>
|
||||
* The choice should be made based on which makes the code more readable.
|
||||
*
|
||||
* @param endDate the end date, exclusive, which may be in any chronology, not null
|
||||
* @return the period between this date and the end date, not null
|
||||
*/
|
||||
@Override
|
||||
public Period periodUntil(ChronoLocalDate<?> endDate) {
|
||||
LocalDate end = LocalDate.from(endDate);
|
||||
long totalMonths = end.getEpochMonth() - this.getEpochMonth(); // safe
|
||||
int days = end.day - this.day;
|
||||
if (totalMonths > 0 && days < 0) {
|
||||
totalMonths--;
|
||||
LocalDate calcDate = this.plusMonths(totalMonths);
|
||||
days = (int) (end.toEpochDay() - calcDate.toEpochDay()); // safe
|
||||
} else if (totalMonths < 0 && days > 0) {
|
||||
totalMonths++;
|
||||
days -= end.lengthOfMonth();
|
||||
}
|
||||
long years = totalMonths / 12; // safe
|
||||
int months = (int) (totalMonths % 12); // safe
|
||||
return Period.of(Math.toIntExact(years), months, days);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a local date-time formed from this date at the specified time.
|
||||
* Combines this date with a time to create a {@code LocalDateTime}.
|
||||
* <p>
|
||||
* This combines this date with the specified time to form a {@code LocalDateTime}.
|
||||
* This returns a {@code LocalDateTime} formed from this date at the specified time.
|
||||
* All possible combinations of date and time are valid.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param time the time to combine with, not null
|
||||
* @return the local date-time formed from this date and the specified time, not null
|
||||
@ -1495,13 +1611,13 @@ public final class LocalDate
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a local date-time formed from this date at the specified time.
|
||||
* Combines this date with a time to create a {@code LocalDateTime}.
|
||||
* <p>
|
||||
* This combines this date with the specified time to form a {@code LocalDateTime}.
|
||||
* This returns a {@code LocalDateTime} formed from this date at the
|
||||
* specified hour and minute.
|
||||
* The seconds and nanosecond fields will be set to zero.
|
||||
* The individual time fields must be within their valid range.
|
||||
* All possible combinations of date and time are valid.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param hour the hour-of-day to use, from 0 to 23
|
||||
* @param minute the minute-of-hour to use, from 0 to 59
|
||||
@ -1513,13 +1629,13 @@ public final class LocalDate
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a local date-time formed from this date at the specified time.
|
||||
* Combines this date with a time to create a {@code LocalDateTime}.
|
||||
* <p>
|
||||
* This combines this date with the specified time to form a {@code LocalDateTime}.
|
||||
* This returns a {@code LocalDateTime} formed from this date at the
|
||||
* specified hour, minute and second.
|
||||
* The nanosecond field will be set to zero.
|
||||
* The individual time fields must be within their valid range.
|
||||
* All possible combinations of date and time are valid.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param hour the hour-of-day to use, from 0 to 23
|
||||
* @param minute the minute-of-hour to use, from 0 to 59
|
||||
@ -1532,13 +1648,12 @@ public final class LocalDate
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a local date-time formed from this date at the specified time.
|
||||
* Combines this date with a time to create a {@code LocalDateTime}.
|
||||
* <p>
|
||||
* This combines this date with the specified time to form a {@code LocalDateTime}.
|
||||
* This returns a {@code LocalDateTime} formed from this date at the
|
||||
* specified hour, minute, second and nanosecond.
|
||||
* The individual time fields must be within their valid range.
|
||||
* All possible combinations of date and time are valid.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param hour the hour-of-day to use, from 0 to 23
|
||||
* @param minute the minute-of-hour to use, from 0 to 59
|
||||
@ -1552,18 +1667,29 @@ public final class LocalDate
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an offset date formed from this date and the specified offset.
|
||||
* Combines this date with an offset time to create an {@code OffsetDateTime}.
|
||||
* <p>
|
||||
* This combines this date with the specified offset to form an {@code OffsetDate}.
|
||||
* All possible combinations of date and offset are valid.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
* This returns an {@code OffsetDateTime} formed from this date at the specified time.
|
||||
* All possible combinations of date and time are valid.
|
||||
*
|
||||
* @param offset the offset to combine with, not null
|
||||
* @return the offset date formed from this date and the specified offset, not null
|
||||
* @param time the time to combine with, not null
|
||||
* @return the offset date-time formed from this date and the specified time, not null
|
||||
*/
|
||||
public OffsetDate atOffset(ZoneOffset offset) {
|
||||
return OffsetDate.of(this, offset);
|
||||
public OffsetDateTime atTime(OffsetTime time) {
|
||||
return OffsetDateTime.of(LocalDateTime.of(this, time.toLocalTime()), time.getOffset());
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines this date with the time of midnight to create a {@code LocalDateTime}
|
||||
* at the start of this date.
|
||||
* <p>
|
||||
* This returns a {@code LocalDateTime} formed from this date at the time of
|
||||
* midnight, 00:00, at the start of this date.
|
||||
*
|
||||
* @return the local date-time of midnight at the start of this date, not null
|
||||
*/
|
||||
public LocalDateTime atStartOfDay() {
|
||||
return LocalDateTime.of(this, LocalTime.MIDNIGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1582,8 +1708,6 @@ public final class LocalDate
|
||||
* <p>
|
||||
* To convert to a specific time in a given time-zone call {@link #atTime(LocalTime)}
|
||||
* followed by {@link LocalDateTime#atZone(ZoneId)}.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param zone the zone ID to use, not null
|
||||
* @return the zoned date-time formed from this date and the earliest valid time for the zone, not null
|
||||
@ -1636,7 +1760,7 @@ public final class LocalDate
|
||||
* If all the dates being compared are instances of {@code LocalDate},
|
||||
* then the comparison will be entirely based on the date.
|
||||
* If some dates being compared are in different chronologies, then the
|
||||
* chronology is also considered, see {@link java.time.temporal.ChronoLocalDate#compareTo}.
|
||||
* chronology is also considered, see {@link java.time.chrono.ChronoLocalDate#compareTo}.
|
||||
*
|
||||
* @param other the other date to compare to, not null
|
||||
* @return the comparator value, negative if less, positive if greater
|
||||
@ -1822,7 +1946,7 @@ public final class LocalDate
|
||||
* Outputs this date as a {@code String} using the formatter.
|
||||
* <p>
|
||||
* This date will be passed to the formatter
|
||||
* {@link DateTimeFormatter#print(TemporalAccessor) print method}.
|
||||
* {@link DateTimeFormatter#format(TemporalAccessor) format method}.
|
||||
*
|
||||
* @param formatter the formatter to use, not null
|
||||
* @return the formatted date string, not null
|
||||
|
||||
@ -70,6 +70,7 @@ import static java.time.LocalTime.NANOS_PER_HOUR;
|
||||
import static java.time.LocalTime.NANOS_PER_MINUTE;
|
||||
import static java.time.LocalTime.NANOS_PER_SECOND;
|
||||
import static java.time.LocalTime.SECONDS_PER_DAY;
|
||||
import static java.time.temporal.ChronoField.NANO_OF_SECOND;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@ -77,21 +78,19 @@ import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.time.chrono.ChronoLocalDateTime;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatters;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.ISOChrono;
|
||||
import java.time.temporal.OffsetDateTime;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdder;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalSubtractor;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.time.zone.ZoneRules;
|
||||
@ -127,7 +126,7 @@ import java.util.Objects;
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class LocalDateTime
|
||||
implements Temporal, TemporalAdjuster, ChronoLocalDateTime<ISOChrono>, Serializable {
|
||||
implements Temporal, TemporalAdjuster, ChronoLocalDateTime<LocalDate>, Serializable {
|
||||
|
||||
/**
|
||||
* The minimum supported {@code LocalDateTime}, '-999999999-01-01T00:00:00'.
|
||||
@ -212,6 +211,8 @@ public final class LocalDateTime
|
||||
* Obtains an instance of {@code LocalDateTime} from year, month,
|
||||
* day, hour and minute, setting the second and nanosecond to zero.
|
||||
* <p>
|
||||
* This returns a {@code LocalDateTime} with the specified year, month,
|
||||
* day-of-month, hour and minute.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
* The second and nanosecond fields will be set to zero.
|
||||
*
|
||||
@ -221,8 +222,8 @@ public final class LocalDateTime
|
||||
* @param hour the hour-of-day to represent, from 0 to 23
|
||||
* @param minute the minute-of-hour to represent, from 0 to 59
|
||||
* @return the local date-time, not null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute) {
|
||||
LocalDate date = LocalDate.of(year, month, dayOfMonth);
|
||||
@ -234,6 +235,8 @@ public final class LocalDateTime
|
||||
* Obtains an instance of {@code LocalDateTime} from year, month,
|
||||
* day, hour, minute and second, setting the nanosecond to zero.
|
||||
* <p>
|
||||
* This returns a {@code LocalDateTime} with the specified year, month,
|
||||
* day-of-month, hour, minute and second.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
* The nanosecond field will be set to zero.
|
||||
*
|
||||
@ -244,8 +247,8 @@ public final class LocalDateTime
|
||||
* @param minute the minute-of-hour to represent, from 0 to 59
|
||||
* @param second the second-of-minute to represent, from 0 to 59
|
||||
* @return the local date-time, not null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute, int second) {
|
||||
LocalDate date = LocalDate.of(year, month, dayOfMonth);
|
||||
@ -257,6 +260,8 @@ public final class LocalDateTime
|
||||
* Obtains an instance of {@code LocalDateTime} from year, month,
|
||||
* day, hour, minute, second and nanosecond.
|
||||
* <p>
|
||||
* This returns a {@code LocalDateTime} with the specified year, month,
|
||||
* day-of-month, hour, minute, second and nanosecond.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param year the year to represent, from MIN_YEAR to MAX_YEAR
|
||||
@ -267,8 +272,8 @@ public final class LocalDateTime
|
||||
* @param second the second-of-minute to represent, from 0 to 59
|
||||
* @param nanoOfSecond the nano-of-second to represent, from 0 to 999,999,999
|
||||
* @return the local date-time, not null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond) {
|
||||
LocalDate date = LocalDate.of(year, month, dayOfMonth);
|
||||
@ -281,6 +286,8 @@ public final class LocalDateTime
|
||||
* Obtains an instance of {@code LocalDateTime} from year, month,
|
||||
* day, hour and minute, setting the second and nanosecond to zero.
|
||||
* <p>
|
||||
* This returns a {@code LocalDateTime} with the specified year, month,
|
||||
* day-of-month, hour and minute.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
* The second and nanosecond fields will be set to zero.
|
||||
*
|
||||
@ -290,8 +297,8 @@ public final class LocalDateTime
|
||||
* @param hour the hour-of-day to represent, from 0 to 23
|
||||
* @param minute the minute-of-hour to represent, from 0 to 59
|
||||
* @return the local date-time, not null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute) {
|
||||
LocalDate date = LocalDate.of(year, month, dayOfMonth);
|
||||
@ -303,6 +310,8 @@ public final class LocalDateTime
|
||||
* Obtains an instance of {@code LocalDateTime} from year, month,
|
||||
* day, hour, minute and second, setting the nanosecond to zero.
|
||||
* <p>
|
||||
* This returns a {@code LocalDateTime} with the specified year, month,
|
||||
* day-of-month, hour, minute and second.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
* The nanosecond field will be set to zero.
|
||||
*
|
||||
@ -313,8 +322,8 @@ public final class LocalDateTime
|
||||
* @param minute the minute-of-hour to represent, from 0 to 59
|
||||
* @param second the second-of-minute to represent, from 0 to 59
|
||||
* @return the local date-time, not null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second) {
|
||||
LocalDate date = LocalDate.of(year, month, dayOfMonth);
|
||||
@ -326,6 +335,8 @@ public final class LocalDateTime
|
||||
* Obtains an instance of {@code LocalDateTime} from year, month,
|
||||
* day, hour, minute, second and nanosecond.
|
||||
* <p>
|
||||
* This returns a {@code LocalDateTime} with the specified year, month,
|
||||
* day-of-month, hour, minute, second and nanosecond.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param year the year to represent, from MIN_YEAR to MAX_YEAR
|
||||
@ -336,8 +347,8 @@ public final class LocalDateTime
|
||||
* @param second the second-of-minute to represent, from 0 to 59
|
||||
* @param nanoOfSecond the nano-of-second to represent, from 0 to 999,999,999
|
||||
* @return the local date-time, not null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond) {
|
||||
LocalDate date = LocalDate.of(year, month, dayOfMonth);
|
||||
@ -392,15 +403,17 @@ public final class LocalDateTime
|
||||
* @param nanoOfSecond the nanosecond within the second, from 0 to 999,999,999
|
||||
* @param offset the zone offset, not null
|
||||
* @return the local date-time, not null
|
||||
* @throws DateTimeException if the result exceeds the supported range
|
||||
* @throws DateTimeException if the result exceeds the supported range,
|
||||
* or if the nano-of-second is invalid
|
||||
*/
|
||||
public static LocalDateTime ofEpochSecond(long epochSecond, int nanoOfSecond, ZoneOffset offset) {
|
||||
Objects.requireNonNull(offset, "offset");
|
||||
NANO_OF_SECOND.checkValidValue(nanoOfSecond);
|
||||
long localSecond = epochSecond + offset.getTotalSeconds(); // overflow caught later
|
||||
long localEpochDay = Math.floorDiv(localSecond, SECONDS_PER_DAY);
|
||||
int secsOfDay = (int)Math.floorMod(localSecond, SECONDS_PER_DAY);
|
||||
LocalDate date = LocalDate.ofEpochDay(localEpochDay);
|
||||
LocalTime time = LocalTime.ofSecondOfDay(secsOfDay, nanoOfSecond);
|
||||
LocalTime time = LocalTime.ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + nanoOfSecond);
|
||||
return new LocalDateTime(date, time);
|
||||
}
|
||||
|
||||
@ -408,10 +421,14 @@ public final class LocalDateTime
|
||||
/**
|
||||
* Obtains an instance of {@code LocalDateTime} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code LocalDateTime}.
|
||||
* This obtains an offset time based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code LocalDateTime}.
|
||||
* <p>
|
||||
* The conversion extracts and combines {@code LocalDate} and {@code LocalTime}.
|
||||
* The conversion extracts and combines the {@code LocalDate} and the
|
||||
* {@code LocalTime} from the temporal object.
|
||||
* Implementations are permitted to perform optimizations such as accessing
|
||||
* those fields that are equivalent to the relevant objects.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used as a query via method reference, {@code LocalDateTime::from}.
|
||||
@ -424,7 +441,9 @@ public final class LocalDateTime
|
||||
if (temporal instanceof LocalDateTime) {
|
||||
return (LocalDateTime) temporal;
|
||||
} else if (temporal instanceof ZonedDateTime) {
|
||||
return ((ZonedDateTime) temporal).getDateTime();
|
||||
return ((ZonedDateTime) temporal).toLocalDateTime();
|
||||
} else if (temporal instanceof OffsetDateTime) {
|
||||
return ((OffsetDateTime) temporal).toLocalDateTime();
|
||||
}
|
||||
try {
|
||||
LocalDate date = LocalDate.from(temporal);
|
||||
@ -440,14 +459,14 @@ public final class LocalDateTime
|
||||
* Obtains an instance of {@code LocalDateTime} from a text string such as {@code 2007-12-03T10:15:30}.
|
||||
* <p>
|
||||
* The string must represent a valid date-time and is parsed using
|
||||
* {@link java.time.format.DateTimeFormatters#isoLocalDateTime()}.
|
||||
* {@link java.time.format.DateTimeFormatter#ISO_LOCAL_DATE_TIME}.
|
||||
*
|
||||
* @param text the text to parse such as "2007-12-03T10:15:30", not null
|
||||
* @return the parsed local date-time, not null
|
||||
* @throws DateTimeParseException if the text cannot be parsed
|
||||
*/
|
||||
public static LocalDateTime parse(CharSequence text) {
|
||||
return parse(text, DateTimeFormatters.isoLocalDateTime());
|
||||
return parse(text, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -535,7 +554,7 @@ public final class LocalDateTime
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -548,7 +567,7 @@ public final class LocalDateTime
|
||||
ChronoField f = (ChronoField) field;
|
||||
return f.isDateField() || f.isTimeField();
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -565,7 +584,7 @@ public final class LocalDateTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -579,7 +598,7 @@ public final class LocalDateTime
|
||||
ChronoField f = (ChronoField) field;
|
||||
return (f.isTimeField() ? time.range(field) : date.range(field));
|
||||
}
|
||||
return field.doRange(this);
|
||||
return field.rangeRefinedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -598,7 +617,7 @@ public final class LocalDateTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -629,7 +648,7 @@ public final class LocalDateTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -644,7 +663,7 @@ public final class LocalDateTime
|
||||
ChronoField f = (ChronoField) field;
|
||||
return (f.isTimeField() ? time.getLong(field) : date.getLong(field));
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -657,7 +676,7 @@ public final class LocalDateTime
|
||||
* @return the date part of this date-time, not null
|
||||
*/
|
||||
@Override
|
||||
public LocalDate getDate() {
|
||||
public LocalDate toLocalDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
@ -667,7 +686,7 @@ public final class LocalDateTime
|
||||
* This method returns the primitive {@code int} value for the year.
|
||||
* <p>
|
||||
* The year returned by this method is proleptic as per {@code get(YEAR)}.
|
||||
* To obtain the year-of-era, use {@code get(YEAR_OF_ERA}.
|
||||
* To obtain the year-of-era, use {@code get(YEAR_OF_ERA)}.
|
||||
*
|
||||
* @return the year, from MIN_YEAR to MAX_YEAR
|
||||
*/
|
||||
@ -753,7 +772,7 @@ public final class LocalDateTime
|
||||
* @return the time part of this date-time, not null
|
||||
*/
|
||||
@Override
|
||||
public LocalTime getTime() {
|
||||
public LocalTime toLocalTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
@ -797,7 +816,7 @@ public final class LocalDateTime
|
||||
/**
|
||||
* Returns an adjusted copy of this date-time.
|
||||
* <p>
|
||||
* This returns a new {@code LocalDateTime}, based on this one, with the date-time adjusted.
|
||||
* This returns a {@code LocalDateTime}, based on this one, with the date-time adjusted.
|
||||
* The adjustment takes place using the specified adjuster strategy object.
|
||||
* Read the documentation of the adjuster to understand what adjustment will be made.
|
||||
* <p>
|
||||
@ -806,7 +825,7 @@ public final class LocalDateTime
|
||||
* A selection of common adjustments is provided in {@link java.time.temporal.Adjusters}.
|
||||
* These include finding the "last day of the month" and "next Wednesday".
|
||||
* Key date-time classes also implement the {@code TemporalAdjuster} interface,
|
||||
* such as {@link Month} and {@link java.time.temporal.MonthDay MonthDay}.
|
||||
* such as {@link Month} and {@link java.time.MonthDay MonthDay}.
|
||||
* The adjuster is responsible for handling special cases, such as the varying
|
||||
* lengths of month and leap years.
|
||||
* <p>
|
||||
@ -852,7 +871,7 @@ public final class LocalDateTime
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified field set to a new value.
|
||||
* <p>
|
||||
* This returns a new {@code LocalDateTime}, based on this one, with the value
|
||||
* This returns a {@code LocalDateTime}, based on this one, with the value
|
||||
* for the specified field changed.
|
||||
* This can be used to change any supported field, such as the year, month or day-of-month.
|
||||
* If it is not possible to set the value, because the field is not supported or for
|
||||
@ -870,7 +889,7 @@ public final class LocalDateTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doWith(Temporal, long)}
|
||||
* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the field determines
|
||||
* whether and how to adjust the instant.
|
||||
* <p>
|
||||
@ -892,7 +911,7 @@ public final class LocalDateTime
|
||||
return with(date.with(field, newValue), time);
|
||||
}
|
||||
}
|
||||
return field.doWith(this, newValue);
|
||||
return field.adjustInto(this, newValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -935,8 +954,8 @@ public final class LocalDateTime
|
||||
*
|
||||
* @param dayOfMonth the day-of-month to set in the result, from 1 to 28-31
|
||||
* @return a {@code LocalDateTime} based on this date-time with the requested day, not null
|
||||
* @throws DateTimeException if the day-of-month value is invalid
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
* @throws DateTimeException if the day-of-month value is invalid,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public LocalDateTime withDayOfMonth(int dayOfMonth) {
|
||||
return with(date.withDayOfMonth(dayOfMonth), time);
|
||||
@ -950,8 +969,8 @@ public final class LocalDateTime
|
||||
*
|
||||
* @param dayOfYear the day-of-year to set in the result, from 1 to 365-366
|
||||
* @return a {@code LocalDateTime} based on this date with the requested day, not null
|
||||
* @throws DateTimeException if the day-of-year value is invalid
|
||||
* @throws DateTimeException if the day-of-year is invalid for the year
|
||||
* @throws DateTimeException if the day-of-year value is invalid,
|
||||
* or if the day-of-year is invalid for the year
|
||||
*/
|
||||
public LocalDateTime withDayOfYear(int dayOfYear) {
|
||||
return with(date.withDayOfYear(dayOfYear), time);
|
||||
@ -1023,8 +1042,10 @@ public final class LocalDateTime
|
||||
* For example, truncating with the {@link ChronoUnit#MINUTES minutes} unit
|
||||
* will set the second-of-minute and nano-of-second field to zero.
|
||||
* <p>
|
||||
* Not all units are accepted. The {@link ChronoUnit#DAYS days} unit and time
|
||||
* units with an exact duration can be used, other units throw an exception.
|
||||
* The unit must have a {@linkplain TemporalUnit#getDuration() duration}
|
||||
* that divides into the length of a standard day without remainder.
|
||||
* This includes all supplied time units on {@link ChronoUnit} and
|
||||
* {@link ChronoUnit#DAYS DAYS}. Other units throw an exception.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
@ -1038,40 +1059,54 @@ public final class LocalDateTime
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified period added.
|
||||
* Returns a copy of this date-time with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new date-time based on this time with the specified period added.
|
||||
* The adder is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalAdder} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #plus(long, TemporalUnit)}.
|
||||
* This returns a {@code LocalDateTime}, based on this one, with the specified amount added.
|
||||
* The amount is typically {@link Period} or {@link Duration} but may be
|
||||
* any other type implementing the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free
|
||||
* to implement the addition in any way it wishes, however it typically
|
||||
* calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param adder the adder to use, not null
|
||||
* @param amountToAdd the amount to add, not null
|
||||
* @return a {@code LocalDateTime} based on this date-time with the addition made, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public LocalDateTime plus(TemporalAdder adder) {
|
||||
return (LocalDateTime) adder.addTo(this);
|
||||
public LocalDateTime plus(TemporalAmount amountToAdd) {
|
||||
return (LocalDateTime) amountToAdd.addTo(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified period added.
|
||||
* Returns a copy of this date-time with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new date-time based on this date-time with the specified period added.
|
||||
* This can be used to add any period that is defined by a unit, for example to add years, months or days.
|
||||
* The unit is responsible for the details of the calculation, including the resolution
|
||||
* of any edge cases in the calculation.
|
||||
* This returns a {@code LocalDateTime}, based on this one, with the amount
|
||||
* in terms of the unit added. If it is not possible to add the amount, because the
|
||||
* unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoUnit} then the addition is implemented here.
|
||||
* Date units are added as per {@link LocalDate#plus(long, TemporalUnit)}.
|
||||
* Time units are added as per {@link LocalTime#plus(long, TemporalUnit)} with
|
||||
* any overflow in days added equivalent to using {@link #plusDays(long)}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoUnit}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the unit determines
|
||||
* whether and how to perform the addition.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToAdd the amount of the unit to add to the result, may be negative
|
||||
* @param unit the unit of the period to add, not null
|
||||
* @return a {@code LocalDateTime} based on this date-time with the specified period added, not null
|
||||
* @throws DateTimeException if the unit cannot be added to this type
|
||||
* @param unit the unit of the amount to add, not null
|
||||
* @return a {@code LocalDateTime} based on this date-time with the specified amount added, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public LocalDateTime plus(long amountToAdd, TemporalUnit unit) {
|
||||
@ -1088,7 +1123,7 @@ public final class LocalDateTime
|
||||
}
|
||||
return with(date.plus(amountToAdd, unit), time);
|
||||
}
|
||||
return unit.doPlus(this, amountToAdd);
|
||||
return unit.addTo(this, amountToAdd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -1237,40 +1272,47 @@ public final class LocalDateTime
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified period subtracted.
|
||||
* Returns a copy of this date-time with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new date-time based on this time with the specified period subtracted.
|
||||
* The subtractor is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalSubtractor} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #minus(long, TemporalUnit)}.
|
||||
* This returns a {@code LocalDateTime}, based on this one, with the specified amount subtracted.
|
||||
* The amount is typically {@link Period} or {@link Duration} but may be
|
||||
* any other type implementing the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free
|
||||
* to implement the subtraction in any way it wishes, however it typically
|
||||
* calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully subtracted.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param subtractor the subtractor to use, not null
|
||||
* @param amountToSubtract the amount to subtract, not null
|
||||
* @return a {@code LocalDateTime} based on this date-time with the subtraction made, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public LocalDateTime minus(TemporalSubtractor subtractor) {
|
||||
return (LocalDateTime) subtractor.subtractFrom(this);
|
||||
public LocalDateTime minus(TemporalAmount amountToSubtract) {
|
||||
return (LocalDateTime) amountToSubtract.subtractFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified period subtracted.
|
||||
* Returns a copy of this date-time with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new date-time based on this date-time with the specified period subtracted.
|
||||
* This can be used to subtract any period that is defined by a unit, for example to subtract years, months or days.
|
||||
* The unit is responsible for the details of the calculation, including the resolution
|
||||
* of any edge cases in the calculation.
|
||||
* This returns a {@code LocalDateTime}, based on this one, with the amount
|
||||
* in terms of the unit subtracted. If it is not possible to subtract the amount,
|
||||
* because the unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.
|
||||
* See that method for a full description of how addition, and thus subtraction, works.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToSubtract the amount of the unit to subtract from the result, may be negative
|
||||
* @param unit the unit of the period to subtract, not null
|
||||
* @return a {@code LocalDateTime} based on this date-time with the specified period subtracted, not null
|
||||
* @throws DateTimeException if the unit cannot be added to this type
|
||||
* @param unit the unit of the amount to subtract, not null
|
||||
* @return a {@code LocalDateTime} based on this date-time with the specified amount subtracted, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public LocalDateTime minus(long amountToSubtract, TemporalUnit unit) {
|
||||
@ -1472,8 +1514,12 @@ public final class LocalDateTime
|
||||
* @throws DateTimeException if unable to query (defined by the query)
|
||||
* @throws ArithmeticException if numeric overflow occurs (defined by the query)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override // override for Javadoc
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.localDate()) {
|
||||
return (R) date;
|
||||
}
|
||||
return ChronoLocalDateTime.super.query(query);
|
||||
}
|
||||
|
||||
@ -1523,14 +1569,15 @@ public final class LocalDateTime
|
||||
* For example, the period in months between 2012-06-15T00:00 and 2012-08-14T23:59
|
||||
* will only be one month as it is one minute short of two months.
|
||||
* <p>
|
||||
* This method operates in association with {@link TemporalUnit#between}.
|
||||
* The result of this method is a {@code long} representing the amount of
|
||||
* the specified unit. By contrast, the result of {@code between} is an
|
||||
* object that can be used directly in addition/subtraction:
|
||||
* There are two equivalent ways of using this method.
|
||||
* The first is to invoke this method.
|
||||
* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
|
||||
* <pre>
|
||||
* long period = start.periodUntil(end, MONTHS); // this method
|
||||
* dateTime.plus(MONTHS.between(start, end)); // use in plus/minus
|
||||
* // these two lines are equivalent
|
||||
* amount = start.periodUntil(end, MONTHS);
|
||||
* amount = MONTHS.between(start, end);
|
||||
* </pre>
|
||||
* The choice should be made based on which makes the code more readable.
|
||||
* <p>
|
||||
* The calculation is implemented in this method for {@link ChronoUnit}.
|
||||
* The units {@code NANOS}, {@code MICROS}, {@code MILLIS}, {@code SECONDS},
|
||||
@ -1580,17 +1627,15 @@ public final class LocalDateTime
|
||||
}
|
||||
return date.periodUntil(endDate, unit);
|
||||
}
|
||||
return unit.between(this, endDateTime).getAmount();
|
||||
return unit.between(this, endDateTime);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns an offset date-time formed from this date-time and the specified offset.
|
||||
* Combines this time with a date to create an {@code OffsetTime}.
|
||||
* <p>
|
||||
* This combines this date-time with the specified offset to form an {@code OffsetDateTime}.
|
||||
* This returns an {@code OffsetTime} formed from this time at the specified offset.
|
||||
* All possible combinations of date-time and offset are valid.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param offset the offset to combine with, not null
|
||||
* @return the offset date-time formed from this date-time and the specified offset, not null
|
||||
@ -1600,9 +1645,10 @@ public final class LocalDateTime
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a zoned date-time formed from this date-time and the specified time-zone.
|
||||
* Combines this time with a time-zone to create a {@code ZonedDateTime}.
|
||||
* <p>
|
||||
* This creates a zoned date-time matching the input date-time as closely as possible.
|
||||
* This returns a {@code ZonedDateTime} formed from this date-time at the
|
||||
* specified time-zone. The result will match this date-time as closely as possible.
|
||||
* Time-zone rules, such as daylight savings, mean that not every local date-time
|
||||
* is valid for the specified zone, thus the local date-time may be adjusted.
|
||||
* <p>
|
||||
@ -1623,8 +1669,6 @@ public final class LocalDateTime
|
||||
* {@link ZonedDateTime#withLaterOffsetAtOverlap()} on the result of this method.
|
||||
* To throw an exception when there is a gap or overlap, use
|
||||
* {@link ZonedDateTime#ofStrict(LocalDateTime, ZoneOffset, ZoneId)}.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param zone the time-zone to use, not null
|
||||
* @return the zoned date-time formed from this date-time, not null
|
||||
@ -1658,9 +1702,9 @@ public final class LocalDateTime
|
||||
}
|
||||
|
||||
private int compareTo0(LocalDateTime other) {
|
||||
int cmp = date.compareTo0(other.getDate());
|
||||
int cmp = date.compareTo0(other.toLocalDate());
|
||||
if (cmp == 0) {
|
||||
cmp = time.compareTo(other.getTime());
|
||||
cmp = time.compareTo(other.toLocalTime());
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
@ -1810,7 +1854,7 @@ public final class LocalDateTime
|
||||
* Outputs this date-time as a {@code String} using the formatter.
|
||||
* <p>
|
||||
* This date-time will be passed to the formatter
|
||||
* {@link DateTimeFormatter#print(TemporalAccessor) print method}.
|
||||
* {@link DateTimeFormatter#format(TemporalAccessor) format method}.
|
||||
*
|
||||
* @param formatter the formatter to use, not null
|
||||
* @return the formatted date-time string, not null
|
||||
|
||||
@ -76,23 +76,17 @@ import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.time.format.DateTimeBuilder;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatters;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.ChronoZonedDateTime;
|
||||
import java.time.temporal.OffsetTime;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdder;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalSubtractor;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Objects;
|
||||
@ -129,7 +123,7 @@ public final class LocalTime
|
||||
*/
|
||||
public static final LocalTime MIN;
|
||||
/**
|
||||
* The minimum supported {@code LocalTime}, '23:59:59.999999999'.
|
||||
* The maximum supported {@code LocalTime}, '23:59:59.999999999'.
|
||||
* This is the time just before midnight at the end of the day.
|
||||
*/
|
||||
public static final LocalTime MAX;
|
||||
@ -273,21 +267,17 @@ public final class LocalTime
|
||||
// inline OffsetTime factory to avoid creating object and InstantProvider checks
|
||||
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());
|
||||
long localSecond = now.getEpochSecond() + offset.getTotalSeconds(); // overflow caught later
|
||||
int secsOfDay = (int) Math.floorMod(localSecond, SECONDS_PER_DAY);
|
||||
return ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + now.getNano());
|
||||
}
|
||||
|
||||
//------------------------get-----------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code LocalTime} from an hour and minute.
|
||||
* <p>
|
||||
* The second and nanosecond fields will be set to zero by this factory method.
|
||||
* <p>
|
||||
* This factory may return a cached value, but applications must not rely on this.
|
||||
* This returns a {@code LocalTime} with the specified hour and minute.
|
||||
* The second and nanosecond fields will be set to zero.
|
||||
*
|
||||
* @param hour the hour-of-day to represent, from 0 to 23
|
||||
* @param minute the minute-of-hour to represent, from 0 to 59
|
||||
@ -306,9 +296,8 @@ public final class LocalTime
|
||||
/**
|
||||
* Obtains an instance of {@code LocalTime} from an hour, minute and second.
|
||||
* <p>
|
||||
* The nanosecond field will be set to zero by this factory method.
|
||||
* <p>
|
||||
* This factory may return a cached value, but applications must not rely on this.
|
||||
* This returns a {@code LocalTime} with the specified hour, minute and second.
|
||||
* The nanosecond field will be set to zero.
|
||||
*
|
||||
* @param hour the hour-of-day to represent, from 0 to 23
|
||||
* @param minute the minute-of-hour to represent, from 0 to 59
|
||||
@ -329,7 +318,7 @@ public final class LocalTime
|
||||
/**
|
||||
* Obtains an instance of {@code LocalTime} from an hour, minute, second and nanosecond.
|
||||
* <p>
|
||||
* This factory may return a cached value, but applications must not rely on this.
|
||||
* This returns a {@code LocalTime} with the specified hour, minute, second and nanosecond.
|
||||
*
|
||||
* @param hour the hour-of-day to represent, from 0 to 23
|
||||
* @param minute the minute-of-hour to represent, from 0 to 59
|
||||
@ -350,7 +339,8 @@ public final class LocalTime
|
||||
/**
|
||||
* Obtains an instance of {@code LocalTime} from a second-of-day value.
|
||||
* <p>
|
||||
* This factory may return a cached value, but applications must not rely on this.
|
||||
* This returns a {@code LocalTime} with the specified second-of-day.
|
||||
* The nanosecond field will be set to zero.
|
||||
*
|
||||
* @param secondOfDay the second-of-day, from {@code 0} to {@code 24 * 60 * 60 - 1}
|
||||
* @return the local time, not null
|
||||
@ -365,31 +355,10 @@ public final class LocalTime
|
||||
return create(hours, minutes, (int) secondOfDay, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code LocalTime} from a second-of-day value, with
|
||||
* associated nanos of second.
|
||||
* <p>
|
||||
* This factory may return a cached value, but applications must not rely on this.
|
||||
*
|
||||
* @param secondOfDay the second-of-day, from {@code 0} to {@code 24 * 60 * 60 - 1}
|
||||
* @param nanoOfSecond the nano-of-second, from 0 to 999,999,999
|
||||
* @return the local time, not null
|
||||
* @throws DateTimeException if the either input value is invalid
|
||||
*/
|
||||
public static LocalTime ofSecondOfDay(long secondOfDay, int nanoOfSecond) {
|
||||
SECOND_OF_DAY.checkValidValue(secondOfDay);
|
||||
NANO_OF_SECOND.checkValidValue(nanoOfSecond);
|
||||
int hours = (int) (secondOfDay / SECONDS_PER_HOUR);
|
||||
secondOfDay -= hours * SECONDS_PER_HOUR;
|
||||
int minutes = (int) (secondOfDay / SECONDS_PER_MINUTE);
|
||||
secondOfDay -= minutes * SECONDS_PER_MINUTE;
|
||||
return create(hours, minutes, (int) secondOfDay, nanoOfSecond);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code LocalTime} from a nanos-of-day value.
|
||||
* <p>
|
||||
* This factory may return a cached value, but applications must not rely on this.
|
||||
* This returns a {@code LocalTime} with the specified nanosecond-of-day.
|
||||
*
|
||||
* @param nanoOfDay the nano of day, from {@code 0} to {@code 24 * 60 * 60 * 1,000,000,000 - 1}
|
||||
* @return the local time, not null
|
||||
@ -410,10 +379,12 @@ public final class LocalTime
|
||||
/**
|
||||
* Obtains an instance of {@code LocalTime} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code LocalTime}.
|
||||
* This obtains a local time based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code LocalTime}.
|
||||
* <p>
|
||||
* The conversion extracts the {@link ChronoField#NANO_OF_DAY NANO_OF_DAY} field.
|
||||
* The conversion uses the {@link Queries#localTime()} query, which relies
|
||||
* on extracting the {@link ChronoField#NANO_OF_DAY NANO_OF_DAY} field.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used in queries via method reference, {@code LocalTime::from}.
|
||||
@ -423,26 +394,11 @@ public final class LocalTime
|
||||
* @throws DateTimeException if unable to convert to a {@code LocalTime}
|
||||
*/
|
||||
public static LocalTime from(TemporalAccessor temporal) {
|
||||
if (temporal instanceof LocalTime) {
|
||||
return (LocalTime) temporal;
|
||||
} else if (temporal instanceof ChronoLocalDateTime) {
|
||||
return ((ChronoLocalDateTime) temporal).getTime();
|
||||
} else if (temporal instanceof ChronoZonedDateTime) {
|
||||
return ((ChronoZonedDateTime) temporal).getTime();
|
||||
}
|
||||
// handle builder as a special case
|
||||
if (temporal instanceof DateTimeBuilder) {
|
||||
DateTimeBuilder builder = (DateTimeBuilder) temporal;
|
||||
LocalTime time = builder.extract(LocalTime.class);
|
||||
if (time != null) {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
try {
|
||||
return ofNanoOfDay(temporal.getLong(NANO_OF_DAY));
|
||||
} catch (DateTimeException ex) {
|
||||
throw new DateTimeException("Unable to obtain LocalTime from TemporalAccessor: " + temporal.getClass(), ex);
|
||||
LocalTime time = temporal.query(Queries.localTime());
|
||||
if (time == null) {
|
||||
throw new DateTimeException("Unable to obtain LocalTime from TemporalAccessor: " + temporal.getClass());
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -450,14 +406,14 @@ public final class LocalTime
|
||||
* Obtains an instance of {@code LocalTime} from a text string such as {@code 10:15}.
|
||||
* <p>
|
||||
* The string must represent a valid time and is parsed using
|
||||
* {@link java.time.format.DateTimeFormatters#isoLocalTime()}.
|
||||
* {@link java.time.format.DateTimeFormatter#ISO_LOCAL_TIME}.
|
||||
*
|
||||
* @param text the text to parse such as "10:15:30", not null
|
||||
* @return the parsed local time, not null
|
||||
* @throws DateTimeParseException if the text cannot be parsed
|
||||
*/
|
||||
public static LocalTime parse(CharSequence text) {
|
||||
return parse(text, DateTimeFormatters.isoLocalTime());
|
||||
return parse(text, DateTimeFormatter.ISO_LOCAL_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -539,7 +495,7 @@ public final class LocalTime
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -551,7 +507,7 @@ public final class LocalTime
|
||||
if (field instanceof ChronoField) {
|
||||
return ((ChronoField) field).isTimeField();
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -568,7 +524,7 @@ public final class LocalTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -596,7 +552,7 @@ public final class LocalTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -626,7 +582,7 @@ public final class LocalTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -646,7 +602,7 @@ public final class LocalTime
|
||||
}
|
||||
return get0(field);
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
private int get0(TemporalField field) {
|
||||
@ -711,7 +667,7 @@ public final class LocalTime
|
||||
/**
|
||||
* Returns an adjusted copy of this time.
|
||||
* <p>
|
||||
* This returns a new {@code LocalTime}, based on this one, with the time adjusted.
|
||||
* This returns a {@code LocalTime}, based on this one, with the time adjusted.
|
||||
* The adjustment takes place using the specified adjuster strategy object.
|
||||
* Read the documentation of the adjuster to understand what adjustment will be made.
|
||||
* <p>
|
||||
@ -741,7 +697,7 @@ public final class LocalTime
|
||||
/**
|
||||
* Returns a copy of this time with the specified field set to a new value.
|
||||
* <p>
|
||||
* This returns a new {@code LocalTime}, based on this one, with the value
|
||||
* This returns a {@code LocalTime}, based on this one, with the value
|
||||
* for the specified field changed.
|
||||
* This can be used to change any supported field, such as the hour, minute or second.
|
||||
* If it is not possible to set the value, because the field is not supported or for
|
||||
@ -807,7 +763,7 @@ public final class LocalTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doWith(Temporal, long)}
|
||||
* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the field determines
|
||||
* whether and how to adjust the instant.
|
||||
* <p>
|
||||
@ -843,7 +799,7 @@ public final class LocalTime
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doWith(this, newValue);
|
||||
return field.adjustInto(this, newValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -924,8 +880,10 @@ public final class LocalTime
|
||||
* For example, truncating with the {@link ChronoUnit#MINUTES minutes} unit
|
||||
* will set the second-of-minute and nano-of-second field to zero.
|
||||
* <p>
|
||||
* Not all units are accepted. The {@link ChronoUnit#DAYS days} unit and time
|
||||
* units with an exact duration can be used, other units throw an exception.
|
||||
* The unit must have a {@linkplain TemporalUnit#getDuration() duration}
|
||||
* that divides into the length of a standard day without remainder.
|
||||
* This includes all supplied time units on {@link ChronoUnit} and
|
||||
* {@link ChronoUnit#DAYS DAYS}. Other units throw an exception.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
@ -936,56 +894,98 @@ public final class LocalTime
|
||||
public LocalTime truncatedTo(TemporalUnit unit) {
|
||||
if (unit == ChronoUnit.NANOS) {
|
||||
return this;
|
||||
} else if (unit == ChronoUnit.DAYS) {
|
||||
return MIDNIGHT;
|
||||
} else if (unit.isDurationEstimated()) {
|
||||
throw new DateTimeException("Unit must not have an estimated duration");
|
||||
}
|
||||
Duration unitDur = unit.getDuration();
|
||||
if (unitDur.getSeconds() > SECONDS_PER_DAY) {
|
||||
throw new DateTimeException("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");
|
||||
}
|
||||
long nod = toNanoOfDay();
|
||||
long dur = unit.getDuration().toNanos();
|
||||
if (dur >= NANOS_PER_DAY) {
|
||||
throw new DateTimeException("Unit must not be a date unit");
|
||||
}
|
||||
nod = (nod / dur) * dur;
|
||||
return ofNanoOfDay(nod);
|
||||
return ofNanoOfDay((nod / dur) * dur);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this date with the specified period added.
|
||||
* Returns a copy of this time with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new time based on this time with the specified period added.
|
||||
* The adder is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalAdder} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #plus(long, TemporalUnit)}.
|
||||
* This returns a {@code LocalTime}, based on this one, with the specified amount added.
|
||||
* The amount is typically {@link Duration} but may be any other type implementing
|
||||
* the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free
|
||||
* to implement the addition in any way it wishes, however it typically
|
||||
* calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param adder the adder to use, not null
|
||||
* @param amountToAdd the amount to add, not null
|
||||
* @return a {@code LocalTime} based on this time with the addition made, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public LocalTime plus(TemporalAdder adder) {
|
||||
return (LocalTime) adder.addTo(this);
|
||||
public LocalTime plus(TemporalAmount amountToAdd) {
|
||||
return (LocalTime) amountToAdd.addTo(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this time with the specified period added.
|
||||
* Returns a copy of this time with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new time based on this time with the specified period added.
|
||||
* This can be used to add any period that is defined by a unit, for example to add hours, minutes or seconds.
|
||||
* The unit is responsible for the details of the calculation, including the resolution
|
||||
* of any edge cases in the calculation.
|
||||
* This returns a {@code LocalTime}, based on this one, with the amount
|
||||
* in terms of the unit added. If it is not possible to add the amount, because the
|
||||
* unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoUnit} then the addition is implemented here.
|
||||
* The supported fields behave as follows:
|
||||
* <ul>
|
||||
* <li>{@code NANOS} -
|
||||
* Returns a {@code LocalTime} with the specified number of nanoseconds added.
|
||||
* This is equivalent to {@link #plusNanos(long)}.
|
||||
* <li>{@code MICROS} -
|
||||
* Returns a {@code LocalTime} with the specified number of microseconds added.
|
||||
* This is equivalent to {@link #plusNanos(long)} with the amount
|
||||
* multiplied by 1,000.
|
||||
* <li>{@code MILLIS} -
|
||||
* Returns a {@code LocalTime} with the specified number of milliseconds added.
|
||||
* This is equivalent to {@link #plusNanos(long)} with the amount
|
||||
* multiplied by 1,000,000.
|
||||
* <li>{@code SECONDS} -
|
||||
* Returns a {@code LocalTime} with the specified number of seconds added.
|
||||
* This is equivalent to {@link #plusSeconds(long)}.
|
||||
* <li>{@code MINUTES} -
|
||||
* Returns a {@code LocalTime} with the specified number of minutes added.
|
||||
* This is equivalent to {@link #plusMinutes(long)}.
|
||||
* <li>{@code HOURS} -
|
||||
* Returns a {@code LocalTime} with the specified number of hours added.
|
||||
* This is equivalent to {@link #plusHours(long)}.
|
||||
* <li>{@code HALF_DAYS} -
|
||||
* Returns a {@code LocalTime} with the specified number of half-days added.
|
||||
* This is equivalent to {@link #plusHours(long)} with the amount
|
||||
* multiplied by 12.
|
||||
* <li>{@code DAYS} -
|
||||
* Returns a {@code LocalTime} with the specified number of days added.
|
||||
* This returns {@code this} time.
|
||||
* </ul>
|
||||
* <p>
|
||||
* All other {@code ChronoUnit} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoUnit}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the unit determines
|
||||
* whether and how to perform the addition.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToAdd the amount of the unit to add to the result, may be negative
|
||||
* @param unit the unit of the period to add, not null
|
||||
* @return a {@code LocalTime} based on this time with the specified period added, not null
|
||||
* @throws DateTimeException if the unit cannot be added to this type
|
||||
* @param unit the unit of the amount to add, not null
|
||||
* @return a {@code LocalTime} based on this time with the specified amount added, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public LocalTime plus(long amountToAdd, TemporalUnit unit) {
|
||||
@ -1003,7 +1003,7 @@ public final class LocalTime
|
||||
}
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
return unit.doPlus(this, amountToAdd);
|
||||
return unit.addTo(this, amountToAdd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -1107,40 +1107,47 @@ public final class LocalTime
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this time with the specified period subtracted.
|
||||
* Returns a copy of this time with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new time based on this time with the specified period subtracted.
|
||||
* The subtractor is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalSubtractor} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #minus(long, TemporalUnit)}.
|
||||
* This returns a {@code LocalTime}, based on this one, with the specified amount subtracted.
|
||||
* The amount is typically {@link Duration} but may be any other type implementing
|
||||
* the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free
|
||||
* to implement the subtraction in any way it wishes, however it typically
|
||||
* calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully subtracted.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param subtractor the subtractor to use, not null
|
||||
* @param amountToSubtract the amount to subtract, not null
|
||||
* @return a {@code LocalTime} based on this time with the subtraction made, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public LocalTime minus(TemporalSubtractor subtractor) {
|
||||
return (LocalTime) subtractor.subtractFrom(this);
|
||||
public LocalTime minus(TemporalAmount amountToSubtract) {
|
||||
return (LocalTime) amountToSubtract.subtractFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this time with the specified period subtracted.
|
||||
* Returns a copy of this time with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new time based on this time with the specified period subtracted.
|
||||
* This can be used to subtract any period that is defined by a unit, for example to subtract hours, minutes or seconds.
|
||||
* The unit is responsible for the details of the calculation, including the resolution
|
||||
* of any edge cases in the calculation.
|
||||
* This returns a {@code LocalTime}, based on this one, with the amount
|
||||
* in terms of the unit subtracted. If it is not possible to subtract the amount,
|
||||
* because the unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.
|
||||
* See that method for a full description of how addition, and thus subtraction, works.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToSubtract the amount of the unit to subtract from the result, may be negative
|
||||
* @param unit the unit of the period to subtract, not null
|
||||
* @return a {@code LocalTime} based on this time with the specified period subtracted, not null
|
||||
* @throws DateTimeException if the unit cannot be added to this type
|
||||
* @param unit the unit of the amount to subtract, not null
|
||||
* @return a {@code LocalTime} based on this time with the specified amount subtracted, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public LocalTime minus(long amountToSubtract, TemporalUnit unit) {
|
||||
@ -1230,13 +1237,17 @@ public final class LocalTime
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.precision()) {
|
||||
if (query == Queries.chronology() || query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
|
||||
return null;
|
||||
} else if (query == Queries.localTime()) {
|
||||
return (R) this;
|
||||
} else if (query == Queries.localDate()) {
|
||||
return null;
|
||||
} else if (query == Queries.precision()) {
|
||||
return (R) NANOS;
|
||||
}
|
||||
// inline TemporalAccessor.super.query(query) as an optimization
|
||||
if (query == Queries.chrono() || query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
|
||||
return null;
|
||||
}
|
||||
// non-JDK classes are not permitted to make this optimization
|
||||
return query.queryFrom(this);
|
||||
}
|
||||
|
||||
@ -1285,14 +1296,15 @@ public final class LocalTime
|
||||
* For example, the period in hours between 11:30 and 13:29 will only
|
||||
* be one hour as it is one minute short of two hours.
|
||||
* <p>
|
||||
* This method operates in association with {@link TemporalUnit#between}.
|
||||
* The result of this method is a {@code long} representing the amount of
|
||||
* the specified unit. By contrast, the result of {@code between} is an
|
||||
* object that can be used directly in addition/subtraction:
|
||||
* There are two equivalent ways of using this method.
|
||||
* The first is to invoke this method.
|
||||
* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
|
||||
* <pre>
|
||||
* long period = start.periodUntil(end, HOURS); // this method
|
||||
* dateTime.plus(HOURS.between(start, end)); // use in plus/minus
|
||||
* // these two lines are equivalent
|
||||
* amount = start.periodUntil(end, MINUTES);
|
||||
* amount = MINUTES.between(start, end);
|
||||
* </pre>
|
||||
* The choice should be made based on which makes the code more readable.
|
||||
* <p>
|
||||
* The calculation is implemented in this method for {@link ChronoUnit}.
|
||||
* The units {@code NANOS}, {@code MICROS}, {@code MILLIS}, {@code SECONDS},
|
||||
@ -1332,17 +1344,15 @@ public final class LocalTime
|
||||
}
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
return unit.between(this, endTime).getAmount();
|
||||
return unit.between(this, endTime);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a local date-time formed from this time at the specified date.
|
||||
* Combines this time with a date to create a {@code LocalDateTime}.
|
||||
* <p>
|
||||
* This combines this time with the specified date to form a {@code LocalDateTime}.
|
||||
* This returns a {@code LocalDateTime} formed from this time at the specified date.
|
||||
* All possible combinations of date and time are valid.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param date the date to combine with, not null
|
||||
* @return the local date-time formed from this time and the specified date, not null
|
||||
@ -1352,12 +1362,10 @@ public final class LocalTime
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an offset time formed from this time and the specified offset.
|
||||
* Combines this time with a date to create an {@code OffsetTime}.
|
||||
* <p>
|
||||
* This combines this time with the specified offset to form an {@code OffsetTime}.
|
||||
* This returns an {@code OffsetTime} formed from this time at the specified offset.
|
||||
* All possible combinations of time and offset are valid.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param offset the offset to combine with, not null
|
||||
* @return the offset time formed from this time and the specified offset, not null
|
||||
@ -1529,7 +1537,7 @@ public final class LocalTime
|
||||
* Outputs this time as a {@code String} using the formatter.
|
||||
* <p>
|
||||
* This time will be passed to the formatter
|
||||
* {@link DateTimeFormatter#print(TemporalAccessor) print method}.
|
||||
* {@link DateTimeFormatter#format(TemporalAccessor) format method}.
|
||||
*
|
||||
* @param formatter the formatter to use, not null
|
||||
* @return the formatted time string, not null
|
||||
@ -1537,7 +1545,7 @@ public final class LocalTime
|
||||
*/
|
||||
public String toString(DateTimeFormatter formatter) {
|
||||
Objects.requireNonNull(formatter, "formatter");
|
||||
return formatter.print(this);
|
||||
return formatter.format(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
@ -64,11 +64,11 @@ package java.time;
|
||||
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
|
||||
import static java.time.temporal.ChronoUnit.MONTHS;
|
||||
|
||||
import java.time.chrono.Chronology;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.TextStyle;
|
||||
import java.time.temporal.Chrono;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ISOChrono;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
@ -192,8 +192,9 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
|
||||
/**
|
||||
* Obtains an instance of {@code Month} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code Month}.
|
||||
* This obtains a month based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code Month}.
|
||||
* <p>
|
||||
* The conversion extracts the {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} field.
|
||||
* The extraction is only permitted if the temporal object has an ISO
|
||||
@ -211,7 +212,7 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
|
||||
return (Month) temporal;
|
||||
}
|
||||
try {
|
||||
if (ISOChrono.INSTANCE.equals(Chrono.from(temporal)) == false) {
|
||||
if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) {
|
||||
temporal = LocalDate.from(temporal);
|
||||
}
|
||||
return of(temporal.get(MONTH_OF_YEAR));
|
||||
@ -237,8 +238,9 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
|
||||
/**
|
||||
* Gets the textual representation, such as 'Jan' or 'December'.
|
||||
* <p>
|
||||
* This returns the textual name used to identify the month-of-year.
|
||||
* The parameters control the length of the returned text and the locale.
|
||||
* This returns the textual name used to identify the month-of-year,
|
||||
* suitable for presentation to the user.
|
||||
* The parameters control the style of the returned text and the locale.
|
||||
* <p>
|
||||
* If no textual mapping is found then the {@link #getValue() numeric value} is returned.
|
||||
*
|
||||
@ -246,8 +248,8 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
|
||||
* @param locale the locale to use, not null
|
||||
* @return the text value of the month-of-year, not null
|
||||
*/
|
||||
public String getText(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendText(MONTH_OF_YEAR, style).toFormatter(locale).print(this);
|
||||
public String getDisplayName(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendText(MONTH_OF_YEAR, style).toFormatter(locale).format(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -263,7 +265,7 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -275,7 +277,7 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
|
||||
if (field instanceof ChronoField) {
|
||||
return field == MONTH_OF_YEAR;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -291,7 +293,7 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -320,15 +322,13 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the 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 ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
@ -351,7 +351,7 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -367,7 +367,7 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
|
||||
} else if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -554,8 +554,8 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.chrono()) {
|
||||
return (R) ISOChrono.INSTANCE;
|
||||
if (query == Queries.chronology()) {
|
||||
return (R) IsoChronology.INSTANCE;
|
||||
} else if (query == Queries.precision()) {
|
||||
return (R) MONTHS;
|
||||
}
|
||||
@ -599,7 +599,7 @@ public enum Month implements TemporalAccessor, TemporalAdjuster {
|
||||
*/
|
||||
@Override
|
||||
public Temporal adjustInto(Temporal temporal) {
|
||||
if (Chrono.from(temporal).equals(ISOChrono.INSTANCE) == false) {
|
||||
if (Chronology.from(temporal).equals(IsoChronology.INSTANCE) == false) {
|
||||
throw new DateTimeException("Adjustment only supported on ISO date-time");
|
||||
}
|
||||
return temporal.with(MONTH_OF_YEAR, getValue());
|
||||
|
||||
@ -59,7 +59,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time;
|
||||
|
||||
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
|
||||
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
|
||||
@ -70,14 +70,19 @@ import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.time.ZoneId;
|
||||
import java.time.chrono.Chronology;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -198,8 +203,8 @@ public final class MonthDay
|
||||
* @param month the month-of-year to represent, not null
|
||||
* @param dayOfMonth the day-of-month to represent, from 1 to 31
|
||||
* @return the month-day, not null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month
|
||||
*/
|
||||
public static MonthDay of(Month month, int dayOfMonth) {
|
||||
Objects.requireNonNull(month, "month");
|
||||
@ -224,8 +229,8 @@ public final class MonthDay
|
||||
* @param month the month-of-year to represent, from 1 (January) to 12 (December)
|
||||
* @param dayOfMonth the day-of-month to represent, from 1 to 31
|
||||
* @return the month-day, not null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month
|
||||
*/
|
||||
public static MonthDay of(int month, int dayOfMonth) {
|
||||
return of(Month.of(month), dayOfMonth);
|
||||
@ -235,8 +240,9 @@ public final class MonthDay
|
||||
/**
|
||||
* Obtains an instance of {@code MonthDay} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code MonthDay}.
|
||||
* This obtains a month-day based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code MonthDay}.
|
||||
* <p>
|
||||
* The conversion extracts the {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} and
|
||||
* {@link ChronoField#DAY_OF_MONTH DAY_OF_MONTH} fields.
|
||||
@ -254,7 +260,7 @@ public final class MonthDay
|
||||
return (MonthDay) temporal;
|
||||
}
|
||||
try {
|
||||
if (ISOChrono.INSTANCE.equals(Chrono.from(temporal)) == false) {
|
||||
if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) {
|
||||
temporal = LocalDate.from(temporal);
|
||||
}
|
||||
return of(temporal.get(MONTH_OF_YEAR), temporal.get(DAY_OF_MONTH));
|
||||
@ -314,8 +320,6 @@ public final class MonthDay
|
||||
* {@link #get(TemporalField) get} methods will throw an exception.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoField} then the query is implemented here.
|
||||
* The {@link #isSupported(TemporalField) supported fields} will return valid
|
||||
* values based on this date-time.
|
||||
* The supported fields are:
|
||||
* <ul>
|
||||
* <li>{@code MONTH_OF_YEAR}
|
||||
@ -324,7 +328,7 @@ public final class MonthDay
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -336,7 +340,7 @@ public final class MonthDay
|
||||
if (field instanceof ChronoField) {
|
||||
return field == MONTH_OF_YEAR || field == DAY_OF_MONTH;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -353,7 +357,7 @@ public final class MonthDay
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -385,7 +389,7 @@ public final class MonthDay
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -412,7 +416,7 @@ public final class MonthDay
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -431,10 +435,24 @@ public final class MonthDay
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the month-of-year field from 1 to 12.
|
||||
* <p>
|
||||
* This method returns the month as an {@code int} from 1 to 12.
|
||||
* Application code is frequently clearer if the enum {@link Month}
|
||||
* is used by calling {@link #getMonth()}.
|
||||
*
|
||||
* @return the month-of-year, from 1 to 12
|
||||
* @see #getMonth()
|
||||
*/
|
||||
public int getMonthValue() {
|
||||
return month;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the month-of-year field using the {@code Month} enum.
|
||||
* <p>
|
||||
@ -444,6 +462,7 @@ public final class MonthDay
|
||||
* provides the {@link Month#getValue() int value}.
|
||||
*
|
||||
* @return the month-of-year, not null
|
||||
* @see #getMonthValue()
|
||||
*/
|
||||
public Month getMonth() {
|
||||
return Month.of(month);
|
||||
@ -524,8 +543,8 @@ public final class MonthDay
|
||||
*
|
||||
* @param dayOfMonth the day-of-month to set in the return month-day, from 1 to 31
|
||||
* @return a {@code MonthDay} based on this month-day with the requested day, not null
|
||||
* @throws DateTimeException if the day-of-month value is invalid
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month
|
||||
* @throws DateTimeException if the day-of-month value is invalid,
|
||||
* or if the day-of-month is invalid for the month
|
||||
*/
|
||||
public MonthDay withDayOfMonth(int dayOfMonth) {
|
||||
if (dayOfMonth == this.day) {
|
||||
@ -556,8 +575,8 @@ public final class MonthDay
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.chrono()) {
|
||||
return (R) ISOChrono.INSTANCE;
|
||||
if (query == Queries.chronology()) {
|
||||
return (R) IsoChronology.INSTANCE;
|
||||
}
|
||||
return TemporalAccessor.super.query(query);
|
||||
}
|
||||
@ -591,7 +610,7 @@ public final class MonthDay
|
||||
*/
|
||||
@Override
|
||||
public Temporal adjustInto(Temporal temporal) {
|
||||
if (Chrono.from(temporal).equals(ISOChrono.INSTANCE) == false) {
|
||||
if (Chronology.from(temporal).equals(IsoChronology.INSTANCE) == false) {
|
||||
throw new DateTimeException("Adjustment only supported on ISO date-time");
|
||||
}
|
||||
temporal = temporal.with(MONTH_OF_YEAR, month);
|
||||
@ -600,9 +619,10 @@ public final class MonthDay
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a date formed from this month-day at the specified year.
|
||||
* Combines this month-day with a year to create a {@code LocalDate}.
|
||||
* <p>
|
||||
* This returns a {@code LocalDate} formed from this month-day and the specified year.
|
||||
* <p>
|
||||
* This combines this month-day and the specified year to form a {@code LocalDate}.
|
||||
* A month-day of February 29th will be adjusted to February 28th in the resulting
|
||||
* date if the year is not a leap year.
|
||||
* <p>
|
||||
@ -610,7 +630,7 @@ public final class MonthDay
|
||||
*
|
||||
* @param year the year to use, from MIN_YEAR to MAX_YEAR
|
||||
* @return the local date formed from this month-day and the specified year, not null
|
||||
* @see Year#atMonthDay(MonthDay)
|
||||
* @throws DateTimeException if the year is outside the valid range of years
|
||||
*/
|
||||
public LocalDate atYear(int year) {
|
||||
return LocalDate.of(year, month, isValidYear(year) ? day : 28);
|
||||
@ -626,6 +646,7 @@ public final class MonthDay
|
||||
* @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) {
|
||||
int cmp = (month - other.month);
|
||||
if (cmp == 0) {
|
||||
@ -705,7 +726,7 @@ public final class MonthDay
|
||||
* Outputs this month-day as a {@code String} using the formatter.
|
||||
* <p>
|
||||
* This month-day will be passed to the formatter
|
||||
* {@link DateTimeFormatter#print(TemporalAccessor) print method}.
|
||||
* {@link DateTimeFormatter#format(TemporalAccessor) format method}.
|
||||
*
|
||||
* @param formatter the formatter to use, not null
|
||||
* @return the formatted month-day string, not null
|
||||
@ -713,7 +734,7 @@ public final class MonthDay
|
||||
*/
|
||||
public String toString(DateTimeFormatter formatter) {
|
||||
Objects.requireNonNull(formatter, "formatter");
|
||||
return formatter.print(this);
|
||||
return formatter.format(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -721,7 +742,7 @@ public final class MonthDay
|
||||
* Writes the object using a
|
||||
* <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
|
||||
* <pre>
|
||||
* out.writeByte(6); // identifies this as a Year
|
||||
* out.writeByte(13); // identifies this as a MonthDay
|
||||
* out.writeByte(month);
|
||||
* out.writeByte(day);
|
||||
* </pre>
|
||||
@ -59,7 +59,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time;
|
||||
|
||||
import static java.time.temporal.ChronoField.EPOCH_DAY;
|
||||
import static java.time.temporal.ChronoField.INSTANT_SECONDS;
|
||||
@ -73,20 +73,20 @@ import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Month;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatters;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.time.zone.ZoneRules;
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
@ -151,7 +151,7 @@ public final class OffsetDateTime
|
||||
public int compare(OffsetDateTime datetime1, OffsetDateTime datetime2) {
|
||||
int cmp = Long.compare(datetime1.toEpochSecond(), datetime2.toEpochSecond());
|
||||
if (cmp == 0) {
|
||||
cmp = Long.compare(datetime1.getTime().toNanoOfDay(), datetime2.getTime().toNanoOfDay());
|
||||
cmp = Long.compare(datetime1.toLocalTime().toNanoOfDay(), datetime2.toLocalTime().toNanoOfDay());
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
@ -253,18 +253,34 @@ public final class OffsetDateTime
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code OffsetDateTime} from a {@code ZonedDateTime}.
|
||||
* Obtains an instance of {@code OffsetDateTime} from a year, month, day,
|
||||
* hour, minute, second, nanosecond and offset.
|
||||
* <p>
|
||||
* This creates an offset date-time with the same local date-time and offset as
|
||||
* the zoned date-time. The result will have the same instant as the input.
|
||||
* This creates an offset date-time with the seven specified fields.
|
||||
* <p>
|
||||
* This method exists primarily for writing test cases.
|
||||
* Non test-code will typically use other methods to create an offset time.
|
||||
* {@code LocalDateTime} has five additional convenience variants of the
|
||||
* equivalent factory method taking fewer arguments.
|
||||
* They are not provided here to reduce the footprint of the API.
|
||||
*
|
||||
* @param zonedDateTime the zoned date-time to convert from, not null
|
||||
* @param year the year to represent, from MIN_YEAR to MAX_YEAR
|
||||
* @param month the month-of-year to represent, from 1 (January) to 12 (December)
|
||||
* @param dayOfMonth the day-of-month to represent, from 1 to 31
|
||||
* @param hour the hour-of-day to represent, from 0 to 23
|
||||
* @param minute the minute-of-hour to represent, from 0 to 59
|
||||
* @param second the second-of-minute to represent, from 0 to 59
|
||||
* @param nanoOfSecond the nano-of-second to represent, from 0 to 999,999,999
|
||||
* @param offset the zone offset, not null
|
||||
* @return the offset date-time, not null
|
||||
* @throws DateTimeException if the result exceeds the supported range
|
||||
* @throws DateTimeException if the value of any field is out of range, or
|
||||
* if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static OffsetDateTime of(ZonedDateTime zonedDateTime) {
|
||||
Objects.requireNonNull(zonedDateTime, "zonedDateTime");
|
||||
return new OffsetDateTime(zonedDateTime.getDateTime(), zonedDateTime.getOffset());
|
||||
public static OffsetDateTime of(
|
||||
int year, int month, int dayOfMonth,
|
||||
int hour, int minute, int second, int nanoOfSecond, ZoneOffset offset) {
|
||||
LocalDateTime dt = LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nanoOfSecond);
|
||||
return new OffsetDateTime(dt, offset);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -293,11 +309,16 @@ public final class OffsetDateTime
|
||||
/**
|
||||
* Obtains an instance of {@code OffsetDateTime} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code OffsetDateTime}.
|
||||
* This obtains an offset date-time based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code OffsetDateTime}.
|
||||
* <p>
|
||||
* The conversion extracts and combines {@code LocalDateTime} and {@code ZoneOffset}.
|
||||
* If that fails it will try to extract and combine {@code Instant} and {@code ZoneOffset}.
|
||||
* The conversion will first obtain a {@code ZoneOffset} from the temporal object.
|
||||
* It will then try to obtain a {@code LocalDateTime}, falling back to an {@code Instant} if necessary.
|
||||
* The result will be the combination of {@code ZoneOffset} with either
|
||||
* with {@code LocalDateTime} or {@code Instant}.
|
||||
* Implementations are permitted to perform optimizations such as accessing
|
||||
* those fields that are equivalent to the relevant objects.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used in queries via method reference, {@code OffsetDateTime::from}.
|
||||
@ -330,14 +351,14 @@ public final class OffsetDateTime
|
||||
* such as {@code 2007-12-03T10:15:30+01:00}.
|
||||
* <p>
|
||||
* The string must represent a valid date-time and is parsed using
|
||||
* {@link java.time.format.DateTimeFormatters#isoOffsetDateTime()}.
|
||||
* {@link java.time.format.DateTimeFormatter#ISO_OFFSET_DATE_TIME}.
|
||||
*
|
||||
* @param text the text to parse such as "2007-12-03T10:15:30+01:00", not null
|
||||
* @return the parsed offset date-time, not null
|
||||
* @throws DateTimeParseException if the text cannot be parsed
|
||||
*/
|
||||
public static OffsetDateTime parse(CharSequence text) {
|
||||
return parse(text, DateTimeFormatters.isoOffsetDateTime());
|
||||
return parse(text, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -425,7 +446,7 @@ public final class OffsetDateTime
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -434,7 +455,7 @@ public final class OffsetDateTime
|
||||
*/
|
||||
@Override
|
||||
public boolean isSupported(TemporalField field) {
|
||||
return field instanceof ChronoField || (field != null && field.doIsSupported(this));
|
||||
return field instanceof ChronoField || (field != null && field.isSupportedBy(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -451,7 +472,7 @@ public final class OffsetDateTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -467,7 +488,7 @@ public final class OffsetDateTime
|
||||
}
|
||||
return dateTime.range(field);
|
||||
}
|
||||
return field.doRange(this);
|
||||
return field.rangeRefinedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -486,7 +507,7 @@ public final class OffsetDateTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -520,7 +541,7 @@ public final class OffsetDateTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -538,7 +559,7 @@ public final class OffsetDateTime
|
||||
}
|
||||
return dateTime.getLong(field);
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -611,7 +632,7 @@ public final class OffsetDateTime
|
||||
*
|
||||
* @return the local date-time part of this date-time, not null
|
||||
*/
|
||||
public LocalDateTime getDateTime() {
|
||||
public LocalDateTime toLocalDateTime() {
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
@ -624,8 +645,8 @@ public final class OffsetDateTime
|
||||
*
|
||||
* @return the date part of this date-time, not null
|
||||
*/
|
||||
public LocalDate getDate() {
|
||||
return dateTime.getDate();
|
||||
public LocalDate toLocalDate() {
|
||||
return dateTime.toLocalDate();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -634,7 +655,7 @@ public final class OffsetDateTime
|
||||
* This method returns the primitive {@code int} value for the year.
|
||||
* <p>
|
||||
* The year returned by this method is proleptic as per {@code get(YEAR)}.
|
||||
* To obtain the year-of-era, use {@code get(YEAR_OF_ERA}.
|
||||
* To obtain the year-of-era, use {@code get(YEAR_OF_ERA)}.
|
||||
*
|
||||
* @return the year, from MIN_YEAR to MAX_YEAR
|
||||
*/
|
||||
@ -719,8 +740,8 @@ public final class OffsetDateTime
|
||||
*
|
||||
* @return the time part of this date-time, not null
|
||||
*/
|
||||
public LocalTime getTime() {
|
||||
return dateTime.getTime();
|
||||
public LocalTime toLocalTime() {
|
||||
return dateTime.toLocalTime();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -763,7 +784,7 @@ public final class OffsetDateTime
|
||||
/**
|
||||
* Returns an adjusted copy of this date-time.
|
||||
* <p>
|
||||
* This returns a new {@code OffsetDateTime}, based on this one, with the date-time adjusted.
|
||||
* This returns an {@code OffsetDateTime}, based on this one, with the date-time adjusted.
|
||||
* The adjustment takes place using the specified adjuster strategy object.
|
||||
* Read the documentation of the adjuster to understand what adjustment will be made.
|
||||
* <p>
|
||||
@ -772,7 +793,7 @@ public final class OffsetDateTime
|
||||
* A selection of common adjustments is provided in {@link java.time.temporal.Adjusters}.
|
||||
* These include finding the "last day of the month" and "next Wednesday".
|
||||
* Key date-time classes also implement the {@code TemporalAdjuster} interface,
|
||||
* such as {@link Month} and {@link java.time.temporal.MonthDay MonthDay}.
|
||||
* such as {@link Month} and {@link java.time.MonthDay MonthDay}.
|
||||
* The adjuster is responsible for handling special cases, such as the varying
|
||||
* lengths of month and leap years.
|
||||
* <p>
|
||||
@ -821,7 +842,7 @@ public final class OffsetDateTime
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified field set to a new value.
|
||||
* <p>
|
||||
* This returns a new {@code OffsetDateTime}, based on this one, with the value
|
||||
* TThis returns an {@code OffsetDateTime}, based on this one, with the value
|
||||
* for the specified field changed.
|
||||
* This can be used to change any supported field, such as the year, month or day-of-month.
|
||||
* If it is not possible to set the value, because the field is not supported or for
|
||||
@ -849,7 +870,7 @@ public final class OffsetDateTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doWith(Temporal, long)}
|
||||
* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the field determines
|
||||
* whether and how to adjust the instant.
|
||||
* <p>
|
||||
@ -873,7 +894,7 @@ public final class OffsetDateTime
|
||||
}
|
||||
return with(dateTime.with(field, newValue), offset);
|
||||
}
|
||||
return field.doWith(this, newValue);
|
||||
return field.adjustInto(this, newValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -916,8 +937,8 @@ public final class OffsetDateTime
|
||||
*
|
||||
* @param dayOfMonth the day-of-month to set in the result, from 1 to 28-31
|
||||
* @return an {@code OffsetDateTime} based on this date-time with the requested day, not null
|
||||
* @throws DateTimeException if the day-of-month value is invalid
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
* @throws DateTimeException if the day-of-month value is invalid,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public OffsetDateTime withDayOfMonth(int dayOfMonth) {
|
||||
return with(dateTime.withDayOfMonth(dayOfMonth), offset);
|
||||
@ -931,8 +952,8 @@ public final class OffsetDateTime
|
||||
*
|
||||
* @param dayOfYear the day-of-year to set in the result, from 1 to 365-366
|
||||
* @return an {@code OffsetDateTime} based on this date with the requested day, not null
|
||||
* @throws DateTimeException if the day-of-year value is invalid
|
||||
* @throws DateTimeException if the day-of-year is invalid for the year
|
||||
* @throws DateTimeException if the day-of-year value is invalid,
|
||||
* or if the day-of-year is invalid for the year
|
||||
*/
|
||||
public OffsetDateTime withDayOfYear(int dayOfYear) {
|
||||
return with(dateTime.withDayOfYear(dayOfYear), offset);
|
||||
@ -1008,8 +1029,10 @@ public final class OffsetDateTime
|
||||
* For example, truncating with the {@link ChronoUnit#MINUTES minutes} unit
|
||||
* will set the second-of-minute and nano-of-second field to zero.
|
||||
* <p>
|
||||
* Not all units are accepted. The {@link ChronoUnit#DAYS days} unit and time
|
||||
* units with an exact duration can be used, other units throw an exception.
|
||||
* The unit must have a {@linkplain TemporalUnit#getDuration() duration}
|
||||
* that divides into the length of a standard day without remainder.
|
||||
* This includes all supplied time units on {@link ChronoUnit} and
|
||||
* {@link ChronoUnit#DAYS DAYS}. Other units throw an exception.
|
||||
* <p>
|
||||
* The offset does not affect the calculation and will be the same in the result.
|
||||
* <p>
|
||||
@ -1025,49 +1048,60 @@ public final class OffsetDateTime
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified period added.
|
||||
* Returns a copy of this date-time with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new date-time based on this time with the specified period added.
|
||||
* The adder is typically {@link java.time.Period} but may be any other type implementing
|
||||
* the {@link TemporalAdder} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #plus(long, TemporalUnit)}.
|
||||
* The offset is not part of the calculation and will be unchanged in the result.
|
||||
* This returns an {@code OffsetDateTime}, based on this one, with the specified amount added.
|
||||
* The amount is typically {@link Period} or {@link Duration} but may be
|
||||
* any other type implementing the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free
|
||||
* to implement the addition in any way it wishes, however it typically
|
||||
* calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param adder the adder to use, not null
|
||||
* @param amountToAdd the amount to add, not null
|
||||
* @return an {@code OffsetDateTime} based on this date-time with the addition made, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public OffsetDateTime plus(TemporalAdder adder) {
|
||||
return (OffsetDateTime) adder.addTo(this);
|
||||
public OffsetDateTime plus(TemporalAmount amountToAdd) {
|
||||
return (OffsetDateTime) amountToAdd.addTo(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified period added.
|
||||
* Returns a copy of this date-time with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new date-time based on this date-time with the specified period added.
|
||||
* This can be used to add any period that is defined by a unit, for example to add years, months or days.
|
||||
* The unit is responsible for the details of the calculation, including the resolution
|
||||
* of any edge cases in the calculation.
|
||||
* This returns an {@code OffsetDateTime}, based on this one, with the amount
|
||||
* in terms of the unit added. If it is not possible to add the amount, because the
|
||||
* unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoUnit} then the addition is implemented by
|
||||
* {@link LocalDateTime#plus(long, TemporalUnit)}.
|
||||
* The offset is not part of the calculation and will be unchanged in the result.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoUnit}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the unit determines
|
||||
* whether and how to perform the addition.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToAdd the amount of the unit to add to the result, may be negative
|
||||
* @param unit the unit of the period to add, not null
|
||||
* @return an {@code OffsetDateTime} based on this date-time with the specified period added, not null
|
||||
* @throws DateTimeException if the unit cannot be added to this type
|
||||
* @param unit the unit of the amount to add, not null
|
||||
* @return an {@code OffsetDateTime} based on this date-time with the specified amount added, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public OffsetDateTime plus(long amountToAdd, TemporalUnit unit) {
|
||||
if (unit instanceof ChronoUnit) {
|
||||
return with(dateTime.plus(amountToAdd, unit), offset);
|
||||
}
|
||||
return unit.doPlus(this, amountToAdd);
|
||||
return unit.addTo(this, amountToAdd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -1211,41 +1245,47 @@ public final class OffsetDateTime
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified period subtracted.
|
||||
* Returns a copy of this date-time with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new date-time based on this time with the specified period subtracted.
|
||||
* The subtractor is typically {@link java.time.Period} but may be any other type implementing
|
||||
* the {@link TemporalSubtractor} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #minus(long, TemporalUnit)}.
|
||||
* The offset is not part of the calculation and will be unchanged in the result.
|
||||
* This returns an {@code OffsetDateTime}, based on this one, with the specified amount subtracted.
|
||||
* The amount is typically {@link Period} or {@link Duration} but may be
|
||||
* any other type implementing the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free
|
||||
* to implement the subtraction in any way it wishes, however it typically
|
||||
* calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully subtracted.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param subtractor the subtractor to use, not null
|
||||
* @param amountToSubtract the amount to subtract, not null
|
||||
* @return an {@code OffsetDateTime} based on this date-time with the subtraction made, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public OffsetDateTime minus(TemporalSubtractor subtractor) {
|
||||
return (OffsetDateTime) subtractor.subtractFrom(this);
|
||||
public OffsetDateTime minus(TemporalAmount amountToSubtract) {
|
||||
return (OffsetDateTime) amountToSubtract.subtractFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified period subtracted.
|
||||
* Returns a copy of this date-time with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new date-time based on this date-time with the specified period subtracted.
|
||||
* This can be used to subtract any period that is defined by a unit, for example to subtract years, months or days.
|
||||
* The unit is responsible for the details of the calculation, including the resolution
|
||||
* of any edge cases in the calculation.
|
||||
* The offset is not part of the calculation and will be unchanged in the result.
|
||||
* This returns an {@code OffsetDateTime}, based on this one, with the amount
|
||||
* in terms of the unit subtracted. If it is not possible to subtract the amount,
|
||||
* because the unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.
|
||||
* See that method for a full description of how addition, and thus subtraction, works.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToSubtract the amount of the unit to subtract from the result, may be negative
|
||||
* @param unit the unit of the period to subtract, not null
|
||||
* @return an {@code OffsetDateTime} based on this date-time with the specified period subtracted, not null
|
||||
* @param unit the unit of the amount to subtract, not null
|
||||
* @return an {@code OffsetDateTime} based on this date-time with the specified amount subtracted, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public OffsetDateTime minus(long amountToSubtract, TemporalUnit unit) {
|
||||
@ -1413,14 +1453,22 @@ public final class OffsetDateTime
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.chrono()) {
|
||||
return (R) getDate().getChrono();
|
||||
if (query == Queries.offset() || query == Queries.zone()) {
|
||||
return (R) getOffset();
|
||||
} else if (query == Queries.zoneId()) {
|
||||
return null;
|
||||
} else if (query == Queries.localDate()) {
|
||||
return (R) toLocalDate();
|
||||
} else if (query == Queries.localTime()) {
|
||||
return (R) toLocalTime();
|
||||
} else if (query == Queries.chronology()) {
|
||||
return (R) IsoChronology.INSTANCE;
|
||||
} else if (query == Queries.precision()) {
|
||||
return (R) NANOS;
|
||||
} else if (query == Queries.offset() || query == Queries.zone()) {
|
||||
return (R) getOffset();
|
||||
}
|
||||
return Temporal.super.query(query);
|
||||
// inline TemporalAccessor.super.query(query) as an optimization
|
||||
// non-JDK classes are not permitted to make this optimization
|
||||
return query.queryFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1453,8 +1501,8 @@ public final class OffsetDateTime
|
||||
public Temporal adjustInto(Temporal temporal) {
|
||||
return temporal
|
||||
.with(OFFSET_SECONDS, getOffset().getTotalSeconds())
|
||||
.with(EPOCH_DAY, getDate().toEpochDay())
|
||||
.with(NANO_OF_DAY, getTime().toNanoOfDay());
|
||||
.with(EPOCH_DAY, toLocalDate().toEpochDay())
|
||||
.with(NANO_OF_DAY, toLocalTime().toNanoOfDay());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1476,14 +1524,15 @@ public final class OffsetDateTime
|
||||
* For example, the period in months between 2012-06-15T00:00Z and 2012-08-14T23:59Z
|
||||
* will only be one month as it is one minute short of two months.
|
||||
* <p>
|
||||
* This method operates in association with {@link TemporalUnit#between}.
|
||||
* The result of this method is a {@code long} representing the amount of
|
||||
* the specified unit. By contrast, the result of {@code between} is an
|
||||
* object that can be used directly in addition/subtraction:
|
||||
* There are two equivalent ways of using this method.
|
||||
* The first is to invoke this method.
|
||||
* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
|
||||
* <pre>
|
||||
* long period = start.periodUntil(end, MONTHS); // this method
|
||||
* dateTime.plus(MONTHS.between(start, end)); // use in plus/minus
|
||||
* // these two lines are equivalent
|
||||
* amount = start.periodUntil(end, MONTHS);
|
||||
* amount = MONTHS.between(start, end);
|
||||
* </pre>
|
||||
* The choice should be made based on which makes the code more readable.
|
||||
* <p>
|
||||
* The calculation is implemented in this method for {@link ChronoUnit}.
|
||||
* The units {@code NANOS}, {@code MICROS}, {@code MILLIS}, {@code SECONDS},
|
||||
@ -1516,22 +1565,21 @@ public final class OffsetDateTime
|
||||
end = end.withOffsetSameInstant(offset);
|
||||
return dateTime.periodUntil(end.dateTime, unit);
|
||||
}
|
||||
return unit.between(this, endDateTime).getAmount();
|
||||
return unit.between(this, endDateTime);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a zoned date-time formed from the instant represented by this
|
||||
* date-time and the specified zone ID.
|
||||
* Combines this date-time with a time-zone to create a {@code ZonedDateTime}
|
||||
* ensuring that the result has the same instant.
|
||||
* <p>
|
||||
* This returns a {@code ZonedDateTime} formed from this date-time and the specified time-zone.
|
||||
* This conversion will ignore the visible local date-time and use the underlying instant instead.
|
||||
* This avoids any problems with local time-line gaps or overlaps.
|
||||
* The result might have different values for fields such as hour, minute an even day.
|
||||
* <p>
|
||||
* To attempt to retain the values of the fields, use {@link #atZoneSimilarLocal(ZoneId)}.
|
||||
* To use the offset as the zone ID, use {@link #toZonedDateTime()}.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param zone the time-zone to use, not null
|
||||
* @return the zoned date-time formed from this date-time, not null
|
||||
@ -1541,7 +1589,11 @@ public final class OffsetDateTime
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a zoned date-time formed from this date-time and the specified zone ID.
|
||||
* Combines this date-time with a time-zone to create a {@code ZonedDateTime}
|
||||
* trying to keep the same local date and time.
|
||||
* <p>
|
||||
* This returns a {@code ZonedDateTime} formed from this date-time and the specified time-zone.
|
||||
* Where possible, the result will have the same local date-time as this object.
|
||||
* <p>
|
||||
* Time-zone rules, such as daylight savings, mean that not every time on the
|
||||
* local time-line exists. If the local date-time is in a gap or overlap according to
|
||||
@ -1556,8 +1608,6 @@ public final class OffsetDateTime
|
||||
* To create a zoned date-time at the same instant irrespective of the local time-line,
|
||||
* use {@link #atZoneSameInstant(ZoneId)}.
|
||||
* To use the offset as the zone ID, use {@link #toZonedDateTime()}.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param zone the time-zone to use, not null
|
||||
* @return the zoned date-time formed from this date and the earliest valid time for the zone, not null
|
||||
@ -1567,17 +1617,6 @@ public final class OffsetDateTime
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Converts this date-time to an {@code OffsetDate}.
|
||||
* <p>
|
||||
* This returns an offset date with the same local date and offset.
|
||||
*
|
||||
* @return an OffsetDate representing the date and offset, not null
|
||||
*/
|
||||
public OffsetDate toOffsetDate() {
|
||||
return OffsetDate.of(dateTime.getDate(), offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this date-time to an {@code OffsetTime}.
|
||||
* <p>
|
||||
@ -1586,7 +1625,7 @@ public final class OffsetDateTime
|
||||
* @return an OffsetTime representing the time and offset, not null
|
||||
*/
|
||||
public OffsetTime toOffsetTime() {
|
||||
return OffsetTime.of(dateTime.getTime(), offset);
|
||||
return OffsetTime.of(dateTime.toLocalTime(), offset);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1606,6 +1645,9 @@ public final class OffsetDateTime
|
||||
|
||||
/**
|
||||
* Converts this date-time to an {@code Instant}.
|
||||
* <p>
|
||||
* This returns an {@code Instant} representing the same point on the
|
||||
* time-line as this date-time.
|
||||
*
|
||||
* @return an {@code Instant} representing the same instant, not null
|
||||
*/
|
||||
@ -1653,13 +1695,13 @@ public final class OffsetDateTime
|
||||
@Override
|
||||
public int compareTo(OffsetDateTime other) {
|
||||
if (getOffset().equals(other.getOffset())) {
|
||||
return getDateTime().compareTo(other.getDateTime());
|
||||
return toLocalDateTime().compareTo(other.toLocalDateTime());
|
||||
}
|
||||
int cmp = Long.compare(toEpochSecond(), other.toEpochSecond());
|
||||
if (cmp == 0) {
|
||||
cmp = getTime().getNano() - other.getTime().getNano();
|
||||
cmp = toLocalTime().getNano() - other.toLocalTime().getNano();
|
||||
if (cmp == 0) {
|
||||
cmp = getDateTime().compareTo(other.getDateTime());
|
||||
cmp = toLocalDateTime().compareTo(other.toLocalDateTime());
|
||||
}
|
||||
}
|
||||
return cmp;
|
||||
@ -1680,7 +1722,7 @@ public final class OffsetDateTime
|
||||
long thisEpochSec = toEpochSecond();
|
||||
long otherEpochSec = other.toEpochSecond();
|
||||
return thisEpochSec > otherEpochSec ||
|
||||
(thisEpochSec == otherEpochSec && getTime().getNano() > other.getTime().getNano());
|
||||
(thisEpochSec == otherEpochSec && toLocalTime().getNano() > other.toLocalTime().getNano());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1697,7 +1739,7 @@ public final class OffsetDateTime
|
||||
long thisEpochSec = toEpochSecond();
|
||||
long otherEpochSec = other.toEpochSecond();
|
||||
return thisEpochSec < otherEpochSec ||
|
||||
(thisEpochSec == otherEpochSec && getTime().getNano() < other.getTime().getNano());
|
||||
(thisEpochSec == otherEpochSec && toLocalTime().getNano() < other.toLocalTime().getNano());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1712,7 +1754,7 @@ public final class OffsetDateTime
|
||||
*/
|
||||
public boolean isEqual(OffsetDateTime other) {
|
||||
return toEpochSecond() == other.toEpochSecond() &&
|
||||
getTime().getNano() == other.getTime().getNano();
|
||||
toLocalTime().getNano() == other.toLocalTime().getNano();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -1774,7 +1816,7 @@ public final class OffsetDateTime
|
||||
* Outputs this date-time as a {@code String} using the formatter.
|
||||
* <p>
|
||||
* This date-time will be passed to the formatter
|
||||
* {@link DateTimeFormatter#print(TemporalAccessor) print method}.
|
||||
* {@link DateTimeFormatter#format(TemporalAccessor) format method}.
|
||||
*
|
||||
* @param formatter the formatter to use, not null
|
||||
* @return the formatted date-time string, not null
|
||||
@ -1782,7 +1824,7 @@ public final class OffsetDateTime
|
||||
*/
|
||||
public String toString(DateTimeFormatter formatter) {
|
||||
Objects.requireNonNull(formatter, "formatter");
|
||||
return formatter.print(this);
|
||||
return formatter.format(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -1790,7 +1832,7 @@ public final class OffsetDateTime
|
||||
* Writes the object using a
|
||||
* <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
|
||||
* <pre>
|
||||
* out.writeByte(3); // identifies this as a OffsetDateTime
|
||||
* out.writeByte(10); // identifies this as a OffsetDateTime
|
||||
* out.writeObject(dateTime);
|
||||
* out.writeObject(offset);
|
||||
* </pre>
|
||||
@ -59,14 +59,14 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time;
|
||||
|
||||
import static java.time.LocalTime.NANOS_PER_HOUR;
|
||||
import static java.time.LocalTime.NANOS_PER_MINUTE;
|
||||
import static java.time.LocalTime.NANOS_PER_SECOND;
|
||||
import static java.time.LocalTime.SECONDS_PER_DAY;
|
||||
import static java.time.temporal.ChronoField.NANO_OF_DAY;
|
||||
import static java.time.temporal.ChronoField.OFFSET_SECONDS;
|
||||
import static java.time.temporal.ChronoLocalDateTimeImpl.NANOS_PER_HOUR;
|
||||
import static java.time.temporal.ChronoLocalDateTimeImpl.NANOS_PER_MINUTE;
|
||||
import static java.time.temporal.ChronoLocalDateTimeImpl.NANOS_PER_SECOND;
|
||||
import static java.time.temporal.ChronoLocalDateTimeImpl.SECONDS_PER_DAY;
|
||||
import static java.time.temporal.ChronoUnit.NANOS;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -75,16 +75,19 @@ import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatters;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.time.zone.ZoneRules;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -202,6 +205,29 @@ public final class OffsetTime
|
||||
return new OffsetTime(time, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code OffsetTime} from an hour, minute, second and nanosecond.
|
||||
* <p>
|
||||
* This creates an offset time with the four specified fields.
|
||||
* <p>
|
||||
* This method exists primarily for writing test cases.
|
||||
* Non test-code will typically use other methods to create an offset time.
|
||||
* {@code LocalTime} has two additional convenience variants of the
|
||||
* equivalent factory method taking fewer arguments.
|
||||
* They are not provided here to reduce the footprint of the API.
|
||||
*
|
||||
* @param hour the hour-of-day to represent, from 0 to 23
|
||||
* @param minute the minute-of-hour to represent, from 0 to 59
|
||||
* @param second the second-of-minute to represent, from 0 to 59
|
||||
* @param nanoOfSecond the nano-of-second to represent, from 0 to 999,999,999
|
||||
* @param offset the zone offset, not null
|
||||
* @return the offset time, not null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
*/
|
||||
public static OffsetTime of(int hour, int minute, int second, int nanoOfSecond, ZoneOffset offset) {
|
||||
return new OffsetTime(LocalTime.of(hour, minute, second, nanoOfSecond), offset);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code OffsetTime} from an {@code Instant} and zone ID.
|
||||
@ -223,12 +249,9 @@ public final class OffsetTime
|
||||
Objects.requireNonNull(zone, "zone");
|
||||
ZoneRules rules = zone.getRules();
|
||||
ZoneOffset offset = rules.getOffset(instant);
|
||||
long secsOfDay = instant.getEpochSecond() % SECONDS_PER_DAY;
|
||||
secsOfDay = (secsOfDay + offset.getTotalSeconds()) % SECONDS_PER_DAY;
|
||||
if (secsOfDay < 0) {
|
||||
secsOfDay += SECONDS_PER_DAY;
|
||||
}
|
||||
LocalTime time = LocalTime.ofSecondOfDay(secsOfDay, instant.getNano());
|
||||
long localSecond = instant.getEpochSecond() + offset.getTotalSeconds(); // overflow caught later
|
||||
int secsOfDay = (int) Math.floorMod(localSecond, SECONDS_PER_DAY);
|
||||
LocalTime time = LocalTime.ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + instant.getNano());
|
||||
return new OffsetTime(time, offset);
|
||||
}
|
||||
|
||||
@ -236,10 +259,14 @@ public final class OffsetTime
|
||||
/**
|
||||
* Obtains an instance of {@code OffsetTime} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code OffsetTime}.
|
||||
* This obtains an offset time based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code OffsetTime}.
|
||||
* <p>
|
||||
* The conversion extracts and combines {@code LocalTime} and {@code ZoneOffset}.
|
||||
* The conversion extracts and combines the {@code ZoneOffset} and the
|
||||
* {@code LocalTime} from the temporal object.
|
||||
* Implementations are permitted to perform optimizations such as accessing
|
||||
* those fields that are equivalent to the relevant objects.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used in queries via method reference, {@code OffsetTime::from}.
|
||||
@ -266,14 +293,14 @@ public final class OffsetTime
|
||||
* Obtains an instance of {@code OffsetTime} from a text string such as {@code 10:15:30+01:00}.
|
||||
* <p>
|
||||
* The string must represent a valid time and is parsed using
|
||||
* {@link java.time.format.DateTimeFormatters#isoOffsetTime()}.
|
||||
* {@link java.time.format.DateTimeFormatter#ISO_OFFSET_TIME}.
|
||||
*
|
||||
* @param text the text to parse such as "10:15:30+01:00", not null
|
||||
* @return the parsed local time, not null
|
||||
* @throws DateTimeParseException if the text cannot be parsed
|
||||
*/
|
||||
public static OffsetTime parse(CharSequence text) {
|
||||
return parse(text, DateTimeFormatters.isoOffsetTime());
|
||||
return parse(text, DateTimeFormatter.ISO_OFFSET_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -347,7 +374,7 @@ public final class OffsetTime
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -359,7 +386,7 @@ public final class OffsetTime
|
||||
if (field instanceof ChronoField) {
|
||||
return ((ChronoField) field).isTimeField() || field == OFFSET_SECONDS;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -376,7 +403,7 @@ public final class OffsetTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -392,7 +419,7 @@ public final class OffsetTime
|
||||
}
|
||||
return time.range(field);
|
||||
}
|
||||
return field.doRange(this);
|
||||
return field.rangeRefinedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -410,7 +437,7 @@ public final class OffsetTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -437,7 +464,7 @@ public final class OffsetTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -450,11 +477,11 @@ public final class OffsetTime
|
||||
public long getLong(TemporalField field) {
|
||||
if (field instanceof ChronoField) {
|
||||
if (field == OFFSET_SECONDS) {
|
||||
return getOffset().getTotalSeconds();
|
||||
return offset.getTotalSeconds();
|
||||
}
|
||||
return time.getLong(field);
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -526,7 +553,7 @@ public final class OffsetTime
|
||||
*
|
||||
* @return the time part of this date-time, not null
|
||||
*/
|
||||
public LocalTime getTime() {
|
||||
public LocalTime toLocalTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
@ -571,7 +598,7 @@ public final class OffsetTime
|
||||
/**
|
||||
* Returns an adjusted copy of this time.
|
||||
* <p>
|
||||
* This returns a new {@code OffsetTime}, based on this one, with the time adjusted.
|
||||
* This returns an {@code OffsetTime}, based on this one, with the time adjusted.
|
||||
* The adjustment takes place using the specified adjuster strategy object.
|
||||
* Read the documentation of the adjuster to understand what adjustment will be made.
|
||||
* <p>
|
||||
@ -612,7 +639,7 @@ public final class OffsetTime
|
||||
/**
|
||||
* Returns a copy of this time with the specified field set to a new value.
|
||||
* <p>
|
||||
* This returns a new {@code OffsetTime}, based on this one, with the value
|
||||
* This returns an {@code OffsetTime}, based on this one, with the value
|
||||
* for the specified field changed.
|
||||
* This can be used to change any supported field, such as the hour, minute or second.
|
||||
* If it is not possible to set the value, because the field is not supported or for
|
||||
@ -631,7 +658,7 @@ public final class OffsetTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doWith(Temporal, long)}
|
||||
* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the field determines
|
||||
* whether and how to adjust the instant.
|
||||
* <p>
|
||||
@ -652,7 +679,7 @@ public final class OffsetTime
|
||||
}
|
||||
return with(time.with(field, newValue), offset);
|
||||
}
|
||||
return field.doWith(this, newValue);
|
||||
return field.adjustInto(this, newValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -725,8 +752,10 @@ public final class OffsetTime
|
||||
* For example, truncating with the {@link ChronoUnit#MINUTES minutes} unit
|
||||
* will set the second-of-minute and nano-of-second field to zero.
|
||||
* <p>
|
||||
* Not all units are accepted. The {@link ChronoUnit#DAYS days} unit and time
|
||||
* units with an exact duration can be used, other units throw an exception.
|
||||
* The unit must have a {@linkplain TemporalUnit#getDuration() duration}
|
||||
* that divides into the length of a standard day without remainder.
|
||||
* This includes all supplied time units on {@link ChronoUnit} and
|
||||
* {@link ChronoUnit#DAYS DAYS}. Other units throw an exception.
|
||||
* <p>
|
||||
* The offset does not affect the calculation and will be the same in the result.
|
||||
* <p>
|
||||
@ -742,49 +771,60 @@ public final class OffsetTime
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this date with the specified period added.
|
||||
* Returns a copy of this time with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new time based on this time with the specified period added.
|
||||
* The adder is typically {@link java.time.Period} but may be any other type implementing
|
||||
* the {@link TemporalAdder} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #plus(long, TemporalUnit)}.
|
||||
* The offset is not part of the calculation and will be unchanged in the result.
|
||||
* This returns an {@code OffsetTime}, based on this one, with the specified amount added.
|
||||
* The amount is typically {@link Duration} but may be any other type implementing
|
||||
* the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free
|
||||
* to implement the addition in any way it wishes, however it typically
|
||||
* calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param adder the adder to use, not null
|
||||
* @param amountToAdd the amount to add, not null
|
||||
* @return an {@code OffsetTime} based on this time with the addition made, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public OffsetTime plus(TemporalAdder adder) {
|
||||
return (OffsetTime) adder.addTo(this);
|
||||
public OffsetTime plus(TemporalAmount amountToAdd) {
|
||||
return (OffsetTime) amountToAdd.addTo(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this time with the specified period added.
|
||||
* Returns a copy of this time with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new time based on this time with the specified period added.
|
||||
* This can be used to add any period that is defined by a unit, for example to add hours, minutes or seconds.
|
||||
* The unit is responsible for the details of the calculation, including the resolution
|
||||
* of any edge cases in the calculation.
|
||||
* This returns an {@code OffsetTime}, based on this one, with the amount
|
||||
* in terms of the unit added. If it is not possible to add the amount, because the
|
||||
* unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoUnit} then the addition is implemented by
|
||||
* {@link LocalTime#plus(long, TemporalUnit)}.
|
||||
* The offset is not part of the calculation and will be unchanged in the result.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoUnit}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the unit determines
|
||||
* whether and how to perform the addition.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToAdd the amount of the unit to add to the result, may be negative
|
||||
* @param unit the unit of the period to add, not null
|
||||
* @return an {@code OffsetTime} based on this time with the specified period added, not null
|
||||
* @throws DateTimeException if the unit cannot be added to this type
|
||||
* @param unit the unit of the amount to add, not null
|
||||
* @return an {@code OffsetTime} based on this time with the specified amount added, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public OffsetTime plus(long amountToAdd, TemporalUnit unit) {
|
||||
if (unit instanceof ChronoUnit) {
|
||||
return with(time.plus(amountToAdd, unit), offset);
|
||||
}
|
||||
return unit.doPlus(this, amountToAdd);
|
||||
return unit.addTo(this, amountToAdd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -850,42 +890,47 @@ public final class OffsetTime
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this time with the specified period subtracted.
|
||||
* Returns a copy of this time with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new time based on this time with the specified period subtracted.
|
||||
* The subtractor is typically {@link java.time.Period} but may be any other type implementing
|
||||
* the {@link TemporalSubtractor} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #minus(long, TemporalUnit)}.
|
||||
* The offset is not part of the calculation and will be unchanged in the result.
|
||||
* This returns an {@code OffsetTime}, based on this one, with the specified amount subtracted.
|
||||
* The amount is typically {@link Duration} but may be any other type implementing
|
||||
* the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free
|
||||
* to implement the subtraction in any way it wishes, however it typically
|
||||
* calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully subtracted.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param subtractor the subtractor to use, not null
|
||||
* @param amountToSubtract the amount to subtract, not null
|
||||
* @return an {@code OffsetTime} based on this time with the subtraction made, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public OffsetTime minus(TemporalSubtractor subtractor) {
|
||||
return (OffsetTime) subtractor.subtractFrom(this);
|
||||
public OffsetTime minus(TemporalAmount amountToSubtract) {
|
||||
return (OffsetTime) amountToSubtract.subtractFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this time with the specified period subtracted.
|
||||
* Returns a copy of this time with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new time based on this time with the specified period subtracted.
|
||||
* This can be used to subtract any period that is defined by a unit, for example to subtract hours, minutes or seconds.
|
||||
* The unit is responsible for the details of the calculation, including the resolution
|
||||
* of any edge cases in the calculation.
|
||||
* The offset is not part of the calculation and will be unchanged in the result.
|
||||
* This returns an {@code OffsetTime}, based on this one, with the amount
|
||||
* in terms of the unit subtracted. If it is not possible to subtract the amount,
|
||||
* because the unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.
|
||||
* See that method for a full description of how addition, and thus subtraction, works.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToSubtract the amount of the unit to subtract from the result, may be negative
|
||||
* @param unit the unit of the period to subtract, not null
|
||||
* @return an {@code OffsetTime} based on this time with the specified period subtracted, not null
|
||||
* @throws DateTimeException if the unit cannot be added to this type
|
||||
* @param unit the unit of the amount to subtract, not null
|
||||
* @return an {@code OffsetTime} based on this time with the specified amount subtracted, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public OffsetTime minus(long amountToSubtract, TemporalUnit unit) {
|
||||
@ -975,12 +1020,18 @@ public final class OffsetTime
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.precision()) {
|
||||
if (query == Queries.offset() || query == Queries.zone()) {
|
||||
return (R) offset;
|
||||
} else if (query == Queries.zoneId() | query == Queries.chronology() || query == Queries.localDate()) {
|
||||
return null;
|
||||
} else if (query == Queries.localTime()) {
|
||||
return (R) time;
|
||||
} else if (query == Queries.precision()) {
|
||||
return (R) NANOS;
|
||||
} else if (query == Queries.offset() || query == Queries.zone()) {
|
||||
return (R) getOffset();
|
||||
}
|
||||
return Temporal.super.query(query);
|
||||
// inline TemporalAccessor.super.query(query) as an optimization
|
||||
// non-JDK classes are not permitted to make this optimization
|
||||
return query.queryFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1012,7 +1063,7 @@ public final class OffsetTime
|
||||
@Override
|
||||
public Temporal adjustInto(Temporal temporal) {
|
||||
return temporal
|
||||
.with(OFFSET_SECONDS, getOffset().getTotalSeconds())
|
||||
.with(OFFSET_SECONDS, offset.getTotalSeconds())
|
||||
.with(NANO_OF_DAY, time.toNanoOfDay());
|
||||
}
|
||||
|
||||
@ -1035,14 +1086,15 @@ public final class OffsetTime
|
||||
* For example, the period in hours between 11:30Z and 13:29Z will only
|
||||
* be one hour as it is one minute short of two hours.
|
||||
* <p>
|
||||
* This method operates in association with {@link TemporalUnit#between}.
|
||||
* The result of this method is a {@code long} representing the amount of
|
||||
* the specified unit. By contrast, the result of {@code between} is an
|
||||
* object that can be used directly in addition/subtraction:
|
||||
* There are two equivalent ways of using this method.
|
||||
* The first is to invoke this method.
|
||||
* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
|
||||
* <pre>
|
||||
* long period = start.periodUntil(end, HOURS); // this method
|
||||
* dateTime.plus(HOURS.between(start, end)); // use in plus/minus
|
||||
* // these two lines are equivalent
|
||||
* amount = start.periodUntil(end, MINUTES);
|
||||
* amount = MINUTES.between(start, end);
|
||||
* </pre>
|
||||
* The choice should be made based on which makes the code more readable.
|
||||
* <p>
|
||||
* The calculation is implemented in this method for {@link ChronoUnit}.
|
||||
* The units {@code NANOS}, {@code MICROS}, {@code MILLIS}, {@code SECONDS},
|
||||
@ -1082,17 +1134,15 @@ public final class OffsetTime
|
||||
}
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
return unit.between(this, endTime).getAmount();
|
||||
return unit.between(this, endTime);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns an offset date-time formed from this time at the specified date.
|
||||
* Combines this date with a time to create an {@code OffsetDateTime}.
|
||||
* <p>
|
||||
* This combines this time with the specified date to form an {@code OffsetDateTime}.
|
||||
* This returns an {@code OffsetDateTime} formed from this time and the specified date.
|
||||
* All possible combinations of date and time are valid.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param date the date to combine with, not null
|
||||
* @return the offset date-time formed from this time and the specified date, not null
|
||||
@ -1261,7 +1311,7 @@ public final class OffsetTime
|
||||
* Outputs this time as a {@code String} using the formatter.
|
||||
* <p>
|
||||
* This time will be passed to the formatter
|
||||
* {@link DateTimeFormatter#print(TemporalAccessor) print method}.
|
||||
* {@link DateTimeFormatter#format(TemporalAccessor) format method}.
|
||||
*
|
||||
* @param formatter the formatter to use, not null
|
||||
* @return the formatted time string, not null
|
||||
@ -1269,7 +1319,7 @@ public final class OffsetTime
|
||||
*/
|
||||
public String toString(DateTimeFormatter formatter) {
|
||||
Objects.requireNonNull(formatter, "formatter");
|
||||
return formatter.print(this);
|
||||
return formatter.format(this);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@ -1277,7 +1327,7 @@ public final class OffsetTime
|
||||
* Writes the object using a
|
||||
* <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
|
||||
* <pre>
|
||||
* out.writeByte(2); // identifies this as a OffsetDateTime
|
||||
* out.writeByte(9); // identifies this as a OffsetDateTime
|
||||
* out.writeObject(time);
|
||||
* out.writeObject(offset);
|
||||
* </pre>
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,307 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Copyright (c) 2009-2012, Stephen Colebourne & Michael Nascimento Santos
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of JSR-310 nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time;
|
||||
|
||||
import java.time.format.DateTimeParseException;
|
||||
|
||||
/**
|
||||
* A period parser that creates an instance of {@code Period} from a string.
|
||||
* This parses the ISO-8601 period format {@code PnYnMnDTnHnMn.nS}.
|
||||
* <p>
|
||||
* This class is mutable and intended for use by a single thread.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
final class PeriodParser {
|
||||
|
||||
/**
|
||||
* Used to validate the correct sequence of tokens.
|
||||
*/
|
||||
private static final String TOKEN_SEQUENCE = "PYMDTHMS";
|
||||
/**
|
||||
* The standard string representing a zero period.
|
||||
*/
|
||||
private static final String ZERO = "PT0S";
|
||||
|
||||
/**
|
||||
* The number of years.
|
||||
*/
|
||||
private int years;
|
||||
/**
|
||||
* The number of months.
|
||||
*/
|
||||
private int months;
|
||||
/**
|
||||
* The number of days.
|
||||
*/
|
||||
private int days;
|
||||
/**
|
||||
* The number of hours.
|
||||
*/
|
||||
private int hours;
|
||||
/**
|
||||
* The number of minutes.
|
||||
*/
|
||||
private int minutes;
|
||||
/**
|
||||
* The number of seconds.
|
||||
*/
|
||||
private int seconds;
|
||||
/**
|
||||
* The number of nanoseconds.
|
||||
*/
|
||||
private long nanos;
|
||||
/**
|
||||
* Whether the seconds were negative.
|
||||
*/
|
||||
private boolean negativeSecs;
|
||||
/**
|
||||
* Parser position index.
|
||||
*/
|
||||
private int index;
|
||||
/**
|
||||
* Original text.
|
||||
*/
|
||||
private CharSequence text;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param text the text to parse, not null
|
||||
*/
|
||||
PeriodParser(CharSequence text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Performs the parse.
|
||||
* <p>
|
||||
* This parses the text set in the constructor in the format PnYnMnDTnHnMn.nS.
|
||||
*
|
||||
* @return the created Period, not null
|
||||
* @throws DateTimeParseException if the text cannot be parsed to a Period
|
||||
*/
|
||||
Period parse() {
|
||||
// force to upper case and coerce the comma to dot
|
||||
|
||||
String s = text.toString().toUpperCase().replace(',', '.');
|
||||
// check for zero and skip parse
|
||||
if (ZERO.equals(s)) {
|
||||
return Period.ZERO;
|
||||
}
|
||||
if (s.length() < 3 || s.charAt(0) != 'P') {
|
||||
throw new DateTimeParseException("Period could not be parsed: " + text, text, 0);
|
||||
}
|
||||
validateCharactersAndOrdering(s, text);
|
||||
|
||||
// strip off the leading P
|
||||
String[] datetime = s.substring(1).split("T");
|
||||
switch (datetime.length) {
|
||||
case 2:
|
||||
parseDate(datetime[0], 1);
|
||||
parseTime(datetime[1], datetime[0].length() + 2);
|
||||
break;
|
||||
case 1:
|
||||
parseDate(datetime[0], 1);
|
||||
break;
|
||||
}
|
||||
return toPeriod();
|
||||
}
|
||||
|
||||
private void parseDate(String s, int baseIndex) {
|
||||
index = 0;
|
||||
while (index < s.length()) {
|
||||
String value = parseNumber(s);
|
||||
if (index < s.length()) {
|
||||
char c = s.charAt(index);
|
||||
switch(c) {
|
||||
case 'Y': years = parseInt(value, baseIndex) ; break;
|
||||
case 'M': months = parseInt(value, baseIndex) ; break;
|
||||
case 'D': days = parseInt(value, baseIndex) ; break;
|
||||
default:
|
||||
throw new DateTimeParseException("Period could not be parsed, unrecognized letter '" +
|
||||
c + ": " + text, text, baseIndex + index);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseTime(String s, int baseIndex) {
|
||||
index = 0;
|
||||
s = prepareTime(s, baseIndex);
|
||||
while (index < s.length()) {
|
||||
String value = parseNumber(s);
|
||||
if (index < s.length()) {
|
||||
char c = s.charAt(index);
|
||||
switch(c) {
|
||||
case 'H': hours = parseInt(value, baseIndex) ; break;
|
||||
case 'M': minutes = parseInt(value, baseIndex) ; break;
|
||||
case 'S': seconds = parseInt(value, baseIndex) ; break;
|
||||
case 'N': nanos = parseNanos(value, baseIndex); break;
|
||||
default:
|
||||
throw new DateTimeParseException("Period could not be parsed, unrecognized letter '" +
|
||||
c + "': " + text, text, baseIndex + index);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long parseNanos(String s, int baseIndex) {
|
||||
if (s.length() > 9) {
|
||||
throw new DateTimeParseException("Period could not be parsed, nanosecond range exceeded: " +
|
||||
text, text, baseIndex + index - s.length());
|
||||
}
|
||||
// pad to the right to create 10**9, then trim
|
||||
return Long.parseLong((s + "000000000").substring(0, 9));
|
||||
}
|
||||
|
||||
private String prepareTime(String s, int baseIndex) {
|
||||
if (s.contains(".")) {
|
||||
int i = s.indexOf(".") + 1;
|
||||
|
||||
// verify that the first character after the dot is a digit
|
||||
if (Character.isDigit(s.charAt(i))) {
|
||||
i++;
|
||||
} else {
|
||||
throw new DateTimeParseException("Period could not be parsed, invalid decimal number: " +
|
||||
text, text, baseIndex + index);
|
||||
}
|
||||
|
||||
// verify that only digits follow the decimal point followed by an S
|
||||
while (i < s.length()) {
|
||||
// || !Character.isDigit(s.charAt(i))
|
||||
char c = s.charAt(i);
|
||||
if (Character.isDigit(c) || c == 'S') {
|
||||
i++;
|
||||
} else {
|
||||
throw new DateTimeParseException("Period could not be parsed, invalid decimal number: " +
|
||||
text, text, baseIndex + index);
|
||||
}
|
||||
}
|
||||
s = s.replace('S', 'N').replace('.', 'S');
|
||||
if (s.contains("-0S")) {
|
||||
negativeSecs = true;
|
||||
s = s.replace("-0S", "0S");
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
private int parseInt(String s, int baseIndex) {
|
||||
try {
|
||||
int value = Integer.parseInt(s);
|
||||
if (s.charAt(0) == '-' && value == 0) {
|
||||
throw new DateTimeParseException("Period could not be parsed, invalid number '" +
|
||||
s + "': " + text, text, baseIndex + index - s.length());
|
||||
}
|
||||
return value;
|
||||
} catch (NumberFormatException ex) {
|
||||
throw new DateTimeParseException("Period could not be parsed, invalid number '" +
|
||||
s + "': " + text, text, baseIndex + index - s.length());
|
||||
}
|
||||
}
|
||||
|
||||
private String parseNumber(String s) {
|
||||
int start = index;
|
||||
while (index < s.length()) {
|
||||
char c = s.charAt(index);
|
||||
if ((c < '0' || c > '9') && c != '-') {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return s.substring(start, index);
|
||||
}
|
||||
|
||||
private void validateCharactersAndOrdering(String s, CharSequence text) {
|
||||
char[] chars = s.toCharArray();
|
||||
int tokenPos = 0;
|
||||
boolean lastLetter = false;
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
if (tokenPos >= TOKEN_SEQUENCE.length()) {
|
||||
throw new DateTimeParseException("Period could not be parsed, characters after last 'S': " + text, text, i);
|
||||
}
|
||||
char c = chars[i];
|
||||
if ((c < '0' || c > '9') && c != '-' && c != '.') {
|
||||
tokenPos = TOKEN_SEQUENCE.indexOf(c, tokenPos);
|
||||
if (tokenPos < 0) {
|
||||
throw new DateTimeParseException("Period could not be parsed, invalid character '" + c + "': " + text, text, i);
|
||||
}
|
||||
tokenPos++;
|
||||
lastLetter = true;
|
||||
} else {
|
||||
lastLetter = false;
|
||||
}
|
||||
}
|
||||
if (lastLetter == false) {
|
||||
throw new DateTimeParseException("Period could not be parsed, invalid last character: " + text, text, s.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
private Period toPeriod() {
|
||||
return Period.of(years, months, days, hours, minutes, seconds, negativeSecs || seconds < 0 ? -nanos : nanos);
|
||||
}
|
||||
|
||||
}
|
||||
@ -56,8 +56,6 @@
|
||||
*/
|
||||
package java.time;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.InvalidClassException;
|
||||
@ -103,6 +101,12 @@ final class Ser implements Externalizable {
|
||||
static final byte ZONE_DATE_TIME_TYPE = 6;
|
||||
static final byte ZONE_REGION_TYPE = 7;
|
||||
static final byte ZONE_OFFSET_TYPE = 8;
|
||||
static final byte OFFSET_TIME_TYPE = 9;
|
||||
static final byte OFFSET_DATE_TIME_TYPE = 10;
|
||||
static final byte YEAR_TYPE = 11;
|
||||
static final byte YEAR_MONTH_TYPE = 12;
|
||||
static final byte MONTH_DAY_TYPE = 13;
|
||||
static final byte PERIOD_TYPE = 14;
|
||||
|
||||
/** The type being serialized. */
|
||||
private byte type;
|
||||
@ -132,11 +136,12 @@ final class Ser implements Externalizable {
|
||||
*
|
||||
* @param out the data stream to write to, not null
|
||||
*/
|
||||
@Override
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
writeInternal(type, object, out);
|
||||
}
|
||||
|
||||
static void writeInternal(byte type, Object object, DataOutput out) throws IOException {
|
||||
static void writeInternal(byte type, Object object, ObjectOutput out) throws IOException {
|
||||
out.writeByte(type);
|
||||
switch (type) {
|
||||
case DURATION_TYPE:
|
||||
@ -163,6 +168,24 @@ final class Ser implements Externalizable {
|
||||
case ZONE_DATE_TIME_TYPE:
|
||||
((ZonedDateTime) object).writeExternal(out);
|
||||
break;
|
||||
case OFFSET_TIME_TYPE:
|
||||
((OffsetTime) object).writeExternal(out);
|
||||
break;
|
||||
case OFFSET_DATE_TIME_TYPE:
|
||||
((OffsetDateTime) object).writeExternal(out);
|
||||
break;
|
||||
case YEAR_TYPE:
|
||||
((Year) object).writeExternal(out);
|
||||
break;
|
||||
case YEAR_MONTH_TYPE:
|
||||
((YearMonth) object).writeExternal(out);
|
||||
break;
|
||||
case MONTH_DAY_TYPE:
|
||||
((MonthDay) object).writeExternal(out);
|
||||
break;
|
||||
case PERIOD_TYPE:
|
||||
((Period) object).writeExternal(out);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidClassException("Unknown serialized type");
|
||||
}
|
||||
@ -174,17 +197,17 @@ final class Ser implements Externalizable {
|
||||
*
|
||||
* @param in the data to read, not null
|
||||
*/
|
||||
public void readExternal(ObjectInput in) throws IOException {
|
||||
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
type = in.readByte();
|
||||
object = readInternal(type, in);
|
||||
}
|
||||
|
||||
static Object read(DataInput in) throws IOException {
|
||||
static Object read(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
byte type = in.readByte();
|
||||
return readInternal(type, in);
|
||||
}
|
||||
|
||||
private static Object readInternal(byte type, DataInput in) throws IOException {
|
||||
private static Object readInternal(byte type, ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
switch (type) {
|
||||
case DURATION_TYPE: return Duration.readExternal(in);
|
||||
case INSTANT_TYPE: return Instant.readExternal(in);
|
||||
@ -194,6 +217,12 @@ final class Ser implements Externalizable {
|
||||
case ZONE_DATE_TIME_TYPE: return ZonedDateTime.readExternal(in);
|
||||
case ZONE_OFFSET_TYPE: return ZoneOffset.readExternal(in);
|
||||
case ZONE_REGION_TYPE: return ZoneRegion.readExternal(in);
|
||||
case OFFSET_TIME_TYPE: return OffsetTime.readExternal(in);
|
||||
case OFFSET_DATE_TIME_TYPE: return OffsetDateTime.readExternal(in);
|
||||
case YEAR_TYPE: return Year.readExternal(in);
|
||||
case YEAR_MONTH_TYPE: return YearMonth.readExternal(in);
|
||||
case MONTH_DAY_TYPE: return MonthDay.readExternal(in);
|
||||
case PERIOD_TYPE: return Period.readExternal(in);
|
||||
default:
|
||||
throw new StreamCorruptedException("Unknown serialized type");
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time;
|
||||
|
||||
import static java.time.temporal.ChronoField.ERA;
|
||||
import static java.time.temporal.ChronoField.YEAR;
|
||||
@ -72,15 +72,23 @@ import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.time.ZoneId;
|
||||
import java.time.chrono.Chronology;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.format.SignStyle;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -211,8 +219,9 @@ public final class Year
|
||||
/**
|
||||
* Obtains an instance of {@code Year} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code Year}.
|
||||
* This obtains a year based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code Year}.
|
||||
* <p>
|
||||
* The conversion extracts the {@link ChronoField#YEAR year} field.
|
||||
* The extraction is only permitted if the temporal object has an ISO
|
||||
@ -230,7 +239,7 @@ public final class Year
|
||||
return (Year) temporal;
|
||||
}
|
||||
try {
|
||||
if (ISOChrono.INSTANCE.equals(Chrono.from(temporal)) == false) {
|
||||
if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) {
|
||||
temporal = LocalDate.from(temporal);
|
||||
}
|
||||
return of(temporal.get(YEAR));
|
||||
@ -324,8 +333,6 @@ public final class Year
|
||||
* {@link #get(TemporalField) get} methods will throw an exception.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoField} then the query is implemented here.
|
||||
* The {@link #isSupported(TemporalField) supported fields} will return valid
|
||||
* values based on this date-time.
|
||||
* The supported fields are:
|
||||
* <ul>
|
||||
* <li>{@code YEAR_OF_ERA}
|
||||
@ -335,7 +342,7 @@ public final class Year
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -347,7 +354,7 @@ public final class Year
|
||||
if (field instanceof ChronoField) {
|
||||
return field == YEAR || field == YEAR_OF_ERA || field == ERA;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -364,7 +371,7 @@ public final class Year
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -394,7 +401,7 @@ public final class Year
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -421,7 +428,7 @@ public final class Year
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -440,7 +447,7 @@ public final class Year
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -492,7 +499,7 @@ public final class Year
|
||||
/**
|
||||
* Returns an adjusted copy of this year.
|
||||
* <p>
|
||||
* This returns a new {@code Year}, based on this one, with the year adjusted.
|
||||
* This returns a {@code Year}, based on this one, with the year adjusted.
|
||||
* The adjustment takes place using the specified adjuster strategy object.
|
||||
* Read the documentation of the adjuster to understand what adjustment will be made.
|
||||
* <p>
|
||||
@ -515,7 +522,7 @@ public final class Year
|
||||
/**
|
||||
* Returns a copy of this year with the specified field set to a new value.
|
||||
* <p>
|
||||
* This returns a new {@code Year}, based on this one, with the value
|
||||
* This returns a {@code Year}, based on this one, with the value
|
||||
* for the specified field changed.
|
||||
* If it is not possible to set the value, because the field is not supported or for
|
||||
* some other reason, an exception is thrown.
|
||||
@ -540,7 +547,7 @@ public final class Year
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doWith(Temporal, long)}
|
||||
* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the field determines
|
||||
* whether and how to adjust the instant.
|
||||
* <p>
|
||||
@ -564,35 +571,81 @@ public final class Year
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doWith(this, newValue);
|
||||
return field.adjustInto(this, newValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this year with the specified period added.
|
||||
* Returns a copy of this year with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new year based on this year with the specified period added.
|
||||
* The adder is typically {@link java.time.Period} but may be any other type implementing
|
||||
* the {@link TemporalAdder} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #plus(long, TemporalUnit)}.
|
||||
* This returns a {@code Year}, based on this one, with the specified amount added.
|
||||
* The amount is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free
|
||||
* to implement the addition in any way it wishes, however it typically
|
||||
* calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param adder the adder to use, not null
|
||||
* @param amountToAdd the amount to add, not null
|
||||
* @return a {@code Year} based on this year with the addition made, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public Year plus(TemporalAdder adder) {
|
||||
return (Year) adder.addTo(this);
|
||||
public Year plus(TemporalAmount amountToAdd) {
|
||||
return (Year) amountToAdd.addTo(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
* Returns a copy of this year with the specified amount added.
|
||||
* <p>
|
||||
* This returns a {@code Year}, based on this one, with the amount
|
||||
* in terms of the unit added. If it is not possible to add the amount, because the
|
||||
* unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoUnit} then the addition is implemented here.
|
||||
* The supported fields behave as follows:
|
||||
* <ul>
|
||||
* <li>{@code YEARS} -
|
||||
* Returns a {@code Year} with the specified number of years added.
|
||||
* This is equivalent to {@link #plusYears(long)}.
|
||||
* <li>{@code DECADES} -
|
||||
* Returns a {@code Year} with the specified number of decades added.
|
||||
* This is equivalent to calling {@link #plusYears(long)} with the amount
|
||||
* multiplied by 10.
|
||||
* <li>{@code CENTURIES} -
|
||||
* Returns a {@code Year} with the specified number of centuries added.
|
||||
* This is equivalent to calling {@link #plusYears(long)} with the amount
|
||||
* multiplied by 100.
|
||||
* <li>{@code MILLENNIA} -
|
||||
* Returns a {@code Year} with the specified number of millennia added.
|
||||
* This is equivalent to calling {@link #plusYears(long)} with the amount
|
||||
* multiplied by 1,000.
|
||||
* <li>{@code ERAS} -
|
||||
* Returns a {@code Year} with the specified number of eras added.
|
||||
* Only two eras are supported so the amount must be one, zero or minus one.
|
||||
* If the amount is non-zero then the year is changed such that the year-of-era
|
||||
* is unchanged.
|
||||
* </ul>
|
||||
* <p>
|
||||
* All other {@code ChronoUnit} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoUnit}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the unit determines
|
||||
* whether and how to perform the addition.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToAdd the amount of the unit to add to the result, may be negative
|
||||
* @param unit the unit of the amount to add, not null
|
||||
* @return a {@code Year} based on this year with the specified amount added, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public Year plus(long amountToAdd, TemporalUnit unit) {
|
||||
@ -606,7 +659,7 @@ public final class Year
|
||||
}
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
return unit.doPlus(this, amountToAdd);
|
||||
return unit.addTo(this, amountToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -627,30 +680,47 @@ public final class Year
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this year with the specified period subtracted.
|
||||
* Returns a copy of this year with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new year based on this year with the specified period subtracted.
|
||||
* The subtractor is typically {@link java.time.Period} but may be any other type implementing
|
||||
* the {@link TemporalSubtractor} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #minus(long, TemporalUnit)}.
|
||||
* This returns a {@code Year}, based on this one, with the specified amount subtracted.
|
||||
* The amount is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free
|
||||
* to implement the subtraction in any way it wishes, however it typically
|
||||
* calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully subtracted.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param subtractor the subtractor to use, not null
|
||||
* @param amountToSubtract the amount to subtract, not null
|
||||
* @return a {@code Year} based on this year with the subtraction made, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public Year minus(TemporalSubtractor subtractor) {
|
||||
return (Year) subtractor.subtractFrom(this);
|
||||
public Year minus(TemporalAmount amountToSubtract) {
|
||||
return (Year) amountToSubtract.subtractFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
* Returns a copy of this year-month with the specified amount subtracted.
|
||||
* <p>
|
||||
* This returns a {@code YearMonth}, based on this one, with the amount
|
||||
* in terms of the unit subtracted. If it is not possible to subtract the amount,
|
||||
* because the unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.
|
||||
* See that method for a full description of how addition, and thus subtraction, works.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToSubtract the amount of the unit to subtract from the result, may be negative
|
||||
* @param unit the unit of the amount to subtract, not null
|
||||
* @return a {@code YearMonth} based on this year-month with the specified amount subtracted, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public Year minus(long amountToSubtract, TemporalUnit unit) {
|
||||
@ -692,8 +762,8 @@ public final class Year
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.chrono()) {
|
||||
return (R) ISOChrono.INSTANCE;
|
||||
if (query == Queries.chronology()) {
|
||||
return (R) IsoChronology.INSTANCE;
|
||||
} else if (query == Queries.precision()) {
|
||||
return (R) YEARS;
|
||||
}
|
||||
@ -728,7 +798,7 @@ public final class Year
|
||||
*/
|
||||
@Override
|
||||
public Temporal adjustInto(Temporal temporal) {
|
||||
if (Chrono.from(temporal).equals(ISOChrono.INSTANCE) == false) {
|
||||
if (Chronology.from(temporal).equals(IsoChronology.INSTANCE) == false) {
|
||||
throw new DateTimeException("Adjustment only supported on ISO date-time");
|
||||
}
|
||||
return temporal.with(YEAR, year);
|
||||
@ -750,14 +820,15 @@ public final class Year
|
||||
* For example, the period in decades between 2012 and 2031
|
||||
* will only be one decade as it is one year short of two decades.
|
||||
* <p>
|
||||
* This method operates in association with {@link TemporalUnit#between}.
|
||||
* The result of this method is a {@code long} representing the amount of
|
||||
* the specified unit. By contrast, the result of {@code between} is an
|
||||
* object that can be used directly in addition/subtraction:
|
||||
* There are two equivalent ways of using this method.
|
||||
* The first is to invoke this method.
|
||||
* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
|
||||
* <pre>
|
||||
* long period = start.periodUntil(end, YEARS); // this method
|
||||
* dateTime.plus(YEARS.between(start, end)); // use in plus/minus
|
||||
* // these two lines are equivalent
|
||||
* amount = start.periodUntil(end, YEARS);
|
||||
* amount = YEARS.between(start, end);
|
||||
* </pre>
|
||||
* The choice should be made based on which makes the code more readable.
|
||||
* <p>
|
||||
* The calculation is implemented in this method for {@link ChronoUnit}.
|
||||
* The units {@code YEARS}, {@code DECADES}, {@code CENTURIES},
|
||||
@ -795,38 +866,36 @@ public final class Year
|
||||
}
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
return unit.between(this, endYear).getAmount();
|
||||
return unit.between(this, endYear);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a date formed from this year at the specified day-of-year.
|
||||
* Combines this year with a day-of-year to create a {@code LocalDate}.
|
||||
* <p>
|
||||
* This returns a {@code LocalDate} formed from this year and the specified day-of-year.
|
||||
* <p>
|
||||
* This combines this year and the specified day-of-year to form a {@code LocalDate}.
|
||||
* The day-of-year value 366 is only valid in a leap year.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param dayOfYear the day-of-year to use, not null
|
||||
* @return the local date formed from this year and the specified date of year, not null
|
||||
* @throws DateTimeException if the day of year is 366 and this is not a leap year
|
||||
* @throws DateTimeException if the day of year is zero or less, 366 or greater or equal
|
||||
* to 366 and this is not a leap year
|
||||
*/
|
||||
public LocalDate atDay(int dayOfYear) {
|
||||
return LocalDate.ofYearDay(year, dayOfYear);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a year-month formed from this year at the specified month.
|
||||
* Combines this year with a month to create a {@code YearMonth}.
|
||||
* <p>
|
||||
* This combines this year and the specified month to form a {@code YearMonth}.
|
||||
* This returns a {@code YearMonth} formed from this year and the specified month.
|
||||
* All possible combinations of year and month are valid.
|
||||
* <p>
|
||||
* This method can be used as part of a chain to produce a date:
|
||||
* <pre>
|
||||
* LocalDate date = year.atMonth(month).atDay(day);
|
||||
* </pre>
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param month the month-of-year to use, not null
|
||||
* @return the year-month formed from this year and the specified month, not null
|
||||
@ -836,39 +905,37 @@ public final class Year
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a year-month formed from this year at the specified month.
|
||||
* Combines this year with a month to create a {@code YearMonth}.
|
||||
* <p>
|
||||
* This combines this year and the specified month to form a {@code YearMonth}.
|
||||
* This returns a {@code YearMonth} formed from this year and the specified month.
|
||||
* All possible combinations of year and month are valid.
|
||||
* <p>
|
||||
* This method can be used as part of a chain to produce a date:
|
||||
* <pre>
|
||||
* LocalDate date = year.atMonth(month).atDay(day);
|
||||
* </pre>
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param month the month-of-year to use, from 1 (January) to 12 (December)
|
||||
* @return the year-month formed from this year and the specified month, not null
|
||||
* @throws DateTimeException if the month is invalid
|
||||
*/
|
||||
public YearMonth atMonth(int month) {
|
||||
return YearMonth.of(year, month);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a date formed from this year at the specified month-day.
|
||||
* Combines this year with a month-day to create a {@code LocalDate}.
|
||||
* <p>
|
||||
* This combines this year and the specified month-day to form a {@code LocalDate}.
|
||||
* The month-day value of February 29th is only valid in a leap year.
|
||||
* This returns a {@code LocalDate} formed from this year and the specified month-day.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
* A month-day of February 29th will be adjusted to February 28th in the resulting
|
||||
* date if the year is not a leap year.
|
||||
*
|
||||
* @param monthDay the month-day to use, not null
|
||||
* @return the local date formed from this year and the specified month-day, not null
|
||||
* @throws DateTimeException if the month-day is February 29th and this is not a leap year
|
||||
*/
|
||||
public LocalDate atMonthDay(MonthDay monthDay) {
|
||||
return LocalDate.of(year, monthDay.getMonth(), monthDay.getDayOfMonth());
|
||||
return monthDay.atYear(year);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -881,6 +948,7 @@ public final class Year
|
||||
* @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) {
|
||||
return year - other.year;
|
||||
}
|
||||
@ -950,7 +1018,7 @@ public final class Year
|
||||
* Outputs this year as a {@code String} using the formatter.
|
||||
* <p>
|
||||
* This year will be passed to the formatter
|
||||
* {@link DateTimeFormatter#print(TemporalAccessor) print method}.
|
||||
* {@link DateTimeFormatter#format(TemporalAccessor) format method}.
|
||||
*
|
||||
* @param formatter the formatter to use, not null
|
||||
* @return the formatted year string, not null
|
||||
@ -958,7 +1026,7 @@ public final class Year
|
||||
*/
|
||||
public String toString(DateTimeFormatter formatter) {
|
||||
Objects.requireNonNull(formatter, "formatter");
|
||||
return formatter.print(this);
|
||||
return formatter.format(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -966,7 +1034,7 @@ public final class Year
|
||||
* Writes the object using a
|
||||
* <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
|
||||
* <pre>
|
||||
* out.writeByte(4); // identifies this as a Year
|
||||
* out.writeByte(11); // identifies this as a Year
|
||||
* out.writeInt(year);
|
||||
* </pre>
|
||||
*
|
||||
@ -59,7 +59,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time;
|
||||
|
||||
import static java.time.temporal.ChronoField.EPOCH_MONTH;
|
||||
import static java.time.temporal.ChronoField.ERA;
|
||||
@ -74,15 +74,23 @@ import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Month;
|
||||
import java.time.ZoneId;
|
||||
import java.time.chrono.Chronology;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.format.SignStyle;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -212,8 +220,9 @@ public final class YearMonth
|
||||
/**
|
||||
* Obtains an instance of {@code YearMonth} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code YearMonth}.
|
||||
* This obtains a year-month based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code YearMonth}.
|
||||
* <p>
|
||||
* The conversion extracts the {@link ChronoField#YEAR YEAR} and
|
||||
* {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} fields.
|
||||
@ -232,7 +241,7 @@ public final class YearMonth
|
||||
return (YearMonth) temporal;
|
||||
}
|
||||
try {
|
||||
if (ISOChrono.INSTANCE.equals(Chrono.from(temporal)) == false) {
|
||||
if (IsoChronology.INSTANCE.equals(Chronology.from(temporal)) == false) {
|
||||
temporal = LocalDate.from(temporal);
|
||||
}
|
||||
return of(temporal.get(YEAR), temporal.get(MONTH_OF_YEAR));
|
||||
@ -308,8 +317,6 @@ public final class YearMonth
|
||||
* {@link #get(TemporalField) get} methods will throw an exception.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoField} then the query is implemented here.
|
||||
* The {@link #isSupported(TemporalField) supported fields} will return valid
|
||||
* values based on this date-time.
|
||||
* The supported fields are:
|
||||
* <ul>
|
||||
* <li>{@code MONTH_OF_YEAR}
|
||||
@ -321,7 +328,7 @@ public final class YearMonth
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -334,7 +341,7 @@ public final class YearMonth
|
||||
return field == YEAR || field == MONTH_OF_YEAR ||
|
||||
field == EPOCH_MONTH || field == YEAR_OF_ERA || field == ERA;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -351,7 +358,7 @@ public final class YearMonth
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -382,7 +389,7 @@ public final class YearMonth
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -409,7 +416,7 @@ public final class YearMonth
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -430,7 +437,7 @@ public final class YearMonth
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
private long getEpochMonth() {
|
||||
@ -451,6 +458,20 @@ public final class YearMonth
|
||||
return year;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the month-of-year field from 1 to 12.
|
||||
* <p>
|
||||
* This method returns the month as an {@code int} from 1 to 12.
|
||||
* Application code is frequently clearer if the enum {@link Month}
|
||||
* is used by calling {@link #getMonth()}.
|
||||
*
|
||||
* @return the month-of-year, from 1 to 12
|
||||
* @see #getMonth()
|
||||
*/
|
||||
public int getMonthValue() {
|
||||
return month;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the month-of-year field using the {@code Month} enum.
|
||||
* <p>
|
||||
@ -460,6 +481,7 @@ public final class YearMonth
|
||||
* provides the {@link Month#getValue() int value}.
|
||||
*
|
||||
* @return the month-of-year, not null
|
||||
* @see #getMonthValue()
|
||||
*/
|
||||
public Month getMonth() {
|
||||
return Month.of(month);
|
||||
@ -485,7 +507,7 @@ public final class YearMonth
|
||||
* @return true if the year is leap, false otherwise
|
||||
*/
|
||||
public boolean isLeapYear() {
|
||||
return ISOChrono.INSTANCE.isLeapYear(year);
|
||||
return IsoChronology.INSTANCE.isLeapYear(year);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -528,7 +550,7 @@ public final class YearMonth
|
||||
/**
|
||||
* Returns an adjusted copy of this year-month.
|
||||
* <p>
|
||||
* This returns a new {@code YearMonth}, based on this one, with the year-month adjusted.
|
||||
* This returns a {@code YearMonth}, based on this one, with the year-month adjusted.
|
||||
* The adjustment takes place using the specified adjuster strategy object.
|
||||
* Read the documentation of the adjuster to understand what adjustment will be made.
|
||||
* <p>
|
||||
@ -555,7 +577,7 @@ public final class YearMonth
|
||||
/**
|
||||
* Returns a copy of this year-month with the specified field set to a new value.
|
||||
* <p>
|
||||
* This returns a new {@code YearMonth}, based on this one, with the value
|
||||
* This returns a {@code YearMonth}, based on this one, with the value
|
||||
* for the specified field changed.
|
||||
* This can be used to change any supported field, such as the year or month.
|
||||
* If it is not possible to set the value, because the field is not supported or for
|
||||
@ -587,7 +609,7 @@ public final class YearMonth
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doWith(Temporal, long)}
|
||||
* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the field determines
|
||||
* whether and how to adjust the instant.
|
||||
* <p>
|
||||
@ -613,7 +635,7 @@ public final class YearMonth
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doWith(this, newValue);
|
||||
return field.adjustInto(this, newValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -647,30 +669,79 @@ public final class YearMonth
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this year-month with the specified period added.
|
||||
* Returns a copy of this year-month with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new year-month based on this year-month with the specified period added.
|
||||
* The adder is typically {@link java.time.Period} but may be any other type implementing
|
||||
* the {@link TemporalAdder} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #plus(long, TemporalUnit)}.
|
||||
* This returns a {@code YearMonth}, based on this one, with the specified amount added.
|
||||
* The amount is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free
|
||||
* to implement the addition in any way it wishes, however it typically
|
||||
* calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param adder the adder to use, not null
|
||||
* @param amountToAdd the amount to add, not null
|
||||
* @return a {@code YearMonth} based on this year-month with the addition made, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public YearMonth plus(TemporalAdder adder) {
|
||||
return (YearMonth) adder.addTo(this);
|
||||
public YearMonth plus(TemporalAmount amountToAdd) {
|
||||
return (YearMonth) amountToAdd.addTo(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
* Returns a copy of this year-month with the specified amount added.
|
||||
* <p>
|
||||
* This returns a {@code YearMonth}, based on this one, with the amount
|
||||
* in terms of the unit added. If it is not possible to add the amount, because the
|
||||
* unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoUnit} then the addition is implemented here.
|
||||
* The supported fields behave as follows:
|
||||
* <ul>
|
||||
* <li>{@code MONTHS} -
|
||||
* Returns a {@code YearMonth} with the specified number of months added.
|
||||
* This is equivalent to {@link #plusMonths(long)}.
|
||||
* <li>{@code YEARS} -
|
||||
* Returns a {@code YearMonth} with the specified number of years added.
|
||||
* This is equivalent to {@link #plusYears(long)}.
|
||||
* <li>{@code DECADES} -
|
||||
* Returns a {@code YearMonth} with the specified number of decades added.
|
||||
* This is equivalent to calling {@link #plusYears(long)} with the amount
|
||||
* multiplied by 10.
|
||||
* <li>{@code CENTURIES} -
|
||||
* Returns a {@code YearMonth} with the specified number of centuries added.
|
||||
* This is equivalent to calling {@link #plusYears(long)} with the amount
|
||||
* multiplied by 100.
|
||||
* <li>{@code MILLENNIA} -
|
||||
* Returns a {@code YearMonth} with the specified number of millennia added.
|
||||
* This is equivalent to calling {@link #plusYears(long)} with the amount
|
||||
* multiplied by 1,000.
|
||||
* <li>{@code ERAS} -
|
||||
* Returns a {@code YearMonth} with the specified number of eras added.
|
||||
* Only two eras are supported so the amount must be one, zero or minus one.
|
||||
* If the amount is non-zero then the year is changed such that the year-of-era
|
||||
* is unchanged.
|
||||
* </ul>
|
||||
* <p>
|
||||
* All other {@code ChronoUnit} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoUnit}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the unit determines
|
||||
* whether and how to perform the addition.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToAdd the amount of the unit to add to the result, may be negative
|
||||
* @param unit the unit of the amount to add, not null
|
||||
* @return a {@code YearMonth} based on this year-month with the specified amount added, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public YearMonth plus(long amountToAdd, TemporalUnit unit) {
|
||||
@ -685,7 +756,7 @@ public final class YearMonth
|
||||
}
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
return unit.doPlus(this, amountToAdd);
|
||||
return unit.addTo(this, amountToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -727,30 +798,47 @@ public final class YearMonth
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this year-month with the specified period subtracted.
|
||||
* Returns a copy of this year-month with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new year-month based on this year-month with the specified period subtracted.
|
||||
* The subtractor is typically {@link java.time.Period} but may be any other type implementing
|
||||
* the {@link TemporalSubtractor} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #minus(long, TemporalUnit)}.
|
||||
* This returns a {@code YearMonth}, based on this one, with the specified amount subtracted.
|
||||
* The amount is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free
|
||||
* to implement the subtraction in any way it wishes, however it typically
|
||||
* calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully subtracted.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param subtractor the subtractor to use, not null
|
||||
* @param amountToSubtract the amount to subtract, not null
|
||||
* @return a {@code YearMonth} based on this year-month with the subtraction made, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public YearMonth minus(TemporalSubtractor subtractor) {
|
||||
return (YearMonth) subtractor.subtractFrom(this);
|
||||
public YearMonth minus(TemporalAmount amountToSubtract) {
|
||||
return (YearMonth) amountToSubtract.subtractFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
* Returns a copy of this year-month with the specified amount subtracted.
|
||||
* <p>
|
||||
* This returns a {@code YearMonth}, based on this one, with the amount
|
||||
* in terms of the unit subtracted. If it is not possible to subtract the amount,
|
||||
* because the unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.
|
||||
* See that method for a full description of how addition, and thus subtraction, works.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToSubtract the amount of the unit to subtract from the result, may be negative
|
||||
* @param unit the unit of the amount to subtract, not null
|
||||
* @return a {@code YearMonth} based on this year-month with the specified amount subtracted, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public YearMonth minus(long amountToSubtract, TemporalUnit unit) {
|
||||
@ -805,8 +893,8 @@ public final class YearMonth
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.chrono()) {
|
||||
return (R) ISOChrono.INSTANCE;
|
||||
if (query == Queries.chronology()) {
|
||||
return (R) IsoChronology.INSTANCE;
|
||||
} else if (query == Queries.precision()) {
|
||||
return (R) MONTHS;
|
||||
}
|
||||
@ -841,7 +929,7 @@ public final class YearMonth
|
||||
*/
|
||||
@Override
|
||||
public Temporal adjustInto(Temporal temporal) {
|
||||
if (Chrono.from(temporal).equals(ISOChrono.INSTANCE) == false) {
|
||||
if (Chronology.from(temporal).equals(IsoChronology.INSTANCE) == false) {
|
||||
throw new DateTimeException("Adjustment only supported on ISO date-time");
|
||||
}
|
||||
return temporal.with(EPOCH_MONTH, getEpochMonth());
|
||||
@ -863,14 +951,15 @@ public final class YearMonth
|
||||
* For example, the period in decades between 2012-06 and 2032-05
|
||||
* will only be one decade as it is one month short of two decades.
|
||||
* <p>
|
||||
* This method operates in association with {@link TemporalUnit#between}.
|
||||
* The result of this method is a {@code long} representing the amount of
|
||||
* the specified unit. By contrast, the result of {@code between} is an
|
||||
* object that can be used directly in addition/subtraction:
|
||||
* There are two equivalent ways of using this method.
|
||||
* The first is to invoke this method.
|
||||
* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
|
||||
* <pre>
|
||||
* long period = start.periodUntil(end, YEARS); // this method
|
||||
* dateTime.plus(YEARS.between(start, end)); // use in plus/minus
|
||||
* // these two lines are equivalent
|
||||
* amount = start.periodUntil(end, MONTHS);
|
||||
* amount = MONTHS.between(start, end);
|
||||
* </pre>
|
||||
* The choice should be made based on which makes the code more readable.
|
||||
* <p>
|
||||
* The calculation is implemented in this method for {@link ChronoUnit}.
|
||||
* The units {@code MONTHS}, {@code YEARS}, {@code DECADES},
|
||||
@ -909,32 +998,49 @@ public final class YearMonth
|
||||
}
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
return unit.between(this, endYearMonth).getAmount();
|
||||
return unit.between(this, endYearMonth);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a date formed from this year-month at the specified day-of-month.
|
||||
* Combines this year-month with a day-of-month to create a {@code LocalDate}.
|
||||
* <p>
|
||||
* This returns a {@code LocalDate} formed from this year-month and the specified day-of-month.
|
||||
* <p>
|
||||
* This combines this year-month and the specified day-of-month to form a {@code LocalDate}.
|
||||
* The day-of-month value must be valid for the year-month.
|
||||
* <p>
|
||||
* This method can be used as part of a chain to produce a date:
|
||||
* <pre>
|
||||
* LocalDate date = year.atMonth(month).atDay(day);
|
||||
* </pre>
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param dayOfMonth the day-of-month to use, from 1 to 31
|
||||
* @return the date formed from this year-month and the specified day, not null
|
||||
* @throws DateTimeException when the day is invalid for the year-month
|
||||
* @throws DateTimeException if the day is invalid for the year-month
|
||||
* @see #isValidDay(int)
|
||||
*/
|
||||
public LocalDate atDay(int dayOfMonth) {
|
||||
return LocalDate.of(year, month, dayOfMonth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code LocalDate} at the end of the month.
|
||||
* <p>
|
||||
* This returns a {@code LocalDate} based on this year-month.
|
||||
* The day-of-month is set to the last valid day of the month, taking
|
||||
* into account leap years.
|
||||
* <p>
|
||||
* This method can be used as part of a chain to produce a date:
|
||||
* <pre>
|
||||
* LocalDate date = year.atMonth(month).atEndOfMonth();
|
||||
* </pre>
|
||||
*
|
||||
* @return the last valid date of this year-month, not null
|
||||
*/
|
||||
public LocalDate atEndOfMonth() {
|
||||
return LocalDate.of(year, month, lengthOfMonth());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Compares this year-month to another year-month.
|
||||
@ -1035,7 +1141,7 @@ public final class YearMonth
|
||||
* Outputs this year-month as a {@code String} using the formatter.
|
||||
* <p>
|
||||
* This year-month will be passed to the formatter
|
||||
* {@link DateTimeFormatter#print(TemporalAccessor) print method}.
|
||||
* {@link DateTimeFormatter#format(TemporalAccessor) format method}.
|
||||
*
|
||||
* @param formatter the formatter to use, not null
|
||||
* @return the formatted year-month string, not null
|
||||
@ -1043,7 +1149,7 @@ public final class YearMonth
|
||||
*/
|
||||
public String toString(DateTimeFormatter formatter) {
|
||||
Objects.requireNonNull(formatter, "formatter");
|
||||
return formatter.print(this);
|
||||
return formatter.format(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -1051,7 +1157,7 @@ public final class YearMonth
|
||||
* Writes the object using a
|
||||
* <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
|
||||
* <pre>
|
||||
* out.writeByte(5); // identifies this as a Year
|
||||
* out.writeByte(12); // identifies this as a YearMonth
|
||||
* out.writeInt(year);
|
||||
* out.writeByte(month);
|
||||
* </pre>
|
||||
@ -71,6 +71,7 @@ import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.zone.ZoneRules;
|
||||
import java.time.zone.ZoneRulesException;
|
||||
import java.time.zone.ZoneRulesProvider;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@ -111,10 +112,11 @@ import java.util.TimeZone;
|
||||
* The ID is unique within the system.
|
||||
* The formats for offset and region IDs differ.
|
||||
* <p>
|
||||
* An ID is parsed as an offset ID if it starts with 'UTC', 'GMT', '+' or '-', or
|
||||
* is a single letter.
|
||||
* For example, 'Z', '+02:00', '-05:00', 'UTC+05' and 'GMT-6' are all valid offset IDs.
|
||||
* Note that some IDs, such as 'D' or '+ABC' meet the criteria, but are invalid.
|
||||
* An ID is parsed as an offset ID if it starts with 'UTC', 'GMT', 'UT' '+' or '-', or
|
||||
* is a single letter. For example, 'Z', '+02:00', '-05:00', 'UTC+05', 'GMT-6' and
|
||||
* 'UT+01:00' are all valid offset IDs.
|
||||
* Note that some IDs, such as 'D' or '+ABC' meet the criteria to be parsed as offset IDs,
|
||||
* but have an invalid offset.
|
||||
* <p>
|
||||
* All other IDs are considered to be region IDs.
|
||||
* <p>
|
||||
@ -126,11 +128,11 @@ import java.util.TimeZone;
|
||||
* The default group is the IANA Time Zone Database (TZDB).
|
||||
* Other organizations include IATA (the airline industry body) and Microsoft.
|
||||
* <p>
|
||||
* Each group defines its own format for region ID.
|
||||
* Each group defines its own format for the region ID it provides.
|
||||
* The TZDB group defines IDs such as 'Europe/London' or 'America/New_York'.
|
||||
* TZDB IDs take precedence over other groups.
|
||||
* <p>
|
||||
* It is strongly recommended that the group name is included in all Ids supplied by
|
||||
* It is strongly recommended that the group name is included in all IDs supplied by
|
||||
* groups other than TZDB to avoid conflicts. For example, IATA airline time-zone
|
||||
* region IDs are typically the same as the three letter airport code.
|
||||
* However, the airport of Utrecht has the code 'UTC', which is obviously a conflict.
|
||||
@ -140,7 +142,7 @@ import java.util.TimeZone;
|
||||
* <h3>Specification for implementors</h3>
|
||||
* This abstract class has two implementations, both of which are immutable and thread-safe.
|
||||
* One implementation models region-based IDs, the other is {@code ZoneOffset} modelling
|
||||
* offset-based IDs.
|
||||
* offset-based IDs. This difference is visible in serialization.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
@ -151,8 +153,8 @@ public abstract class ZoneId implements Serializable {
|
||||
* <p>
|
||||
* This maps as follows:
|
||||
* <p><ul>
|
||||
* <li>EST - America/Indianapolis</li>
|
||||
* <li>MST - America/Phoenix</li>
|
||||
* <li>EST - America/New_York</li>
|
||||
* <li>MST - America/Denver</li>
|
||||
* <li>HST - Pacific/Honolulu</li>
|
||||
* <li>ACT - Australia/Darwin</li>
|
||||
* <li>AET - Australia/Sydney</li>
|
||||
@ -248,8 +250,8 @@ public abstract class ZoneId implements Serializable {
|
||||
base.put("SST", "Pacific/Guadalcanal");
|
||||
base.put("VST", "Asia/Ho_Chi_Minh");
|
||||
Map<String, String> pre = new HashMap<>(base);
|
||||
pre.put("EST", "America/Indianapolis");
|
||||
pre.put("MST", "America/Phoenix");
|
||||
pre.put("EST", "America/New_York");
|
||||
pre.put("MST", "America/Denver");
|
||||
pre.put("HST", "Pacific/Honolulu");
|
||||
OLD_IDS_PRE_2005 = Collections.unmodifiableMap(pre);
|
||||
Map<String, String> post = new HashMap<>(base);
|
||||
@ -273,7 +275,7 @@ public abstract class ZoneId implements Serializable {
|
||||
*
|
||||
* @return the zone ID, not null
|
||||
* @throws DateTimeException if the converted zone ID has an invalid format
|
||||
* @throws java.time.zone.ZoneRulesException if the converted zone region ID cannot be found
|
||||
* @throws ZoneRulesException if the converted zone region ID cannot be found
|
||||
*/
|
||||
public static ZoneId systemDefault() {
|
||||
return ZoneId.of(TimeZone.getDefault().getID(), OLD_IDS_POST_2005);
|
||||
@ -294,7 +296,7 @@ public abstract class ZoneId implements Serializable {
|
||||
* @param aliasMap a map of alias zone IDs (typically abbreviations) to real zone IDs, not null
|
||||
* @return the zone ID, not null
|
||||
* @throws DateTimeException if the zone ID has an invalid format
|
||||
* @throws java.time.zone.ZoneRulesException if the zone region ID cannot be found
|
||||
* @throws ZoneRulesException if the zone ID is a region ID that cannot be found
|
||||
*/
|
||||
public static ZoneId of(String zoneId, Map<String, String> aliasMap) {
|
||||
Objects.requireNonNull(zoneId, "zoneId");
|
||||
@ -311,22 +313,22 @@ public abstract class ZoneId implements Serializable {
|
||||
* This method parses the ID, applies any appropriate normalization, and validates it
|
||||
* against the known set of IDs for which rules are available.
|
||||
* <p>
|
||||
* An ID is parsed as though it is an offset ID if it starts with 'UTC', 'GMT', '+'
|
||||
* An ID is parsed as though it is an offset ID if it starts with 'UTC', 'GMT', 'UT', '+'
|
||||
* or '-', or if it has less then two letters.
|
||||
* The offset of {@link ZoneOffset#UTC zero} may be represented in multiple ways,
|
||||
* including 'Z', 'UTC', 'GMT', 'UTC0' 'GMT0', '+00:00', '-00:00' and 'UTC+00:00'.
|
||||
* The offset of {@linkplain ZoneOffset#UTC zero} may be represented in multiple ways,
|
||||
* including 'Z', 'UTC', 'GMT', 'UT', 'UTC0', 'GMT0', 'UT0', '+00:00', '-00:00' and 'UTC+00:00'.
|
||||
* <p>
|
||||
* Eight forms of ID are recognized, where '{offset}' means to parse using {@link ZoneOffset#of(String)}:
|
||||
* Six forms of ID are recognized:
|
||||
* <p><ul>
|
||||
* <li><code>{offset}</code> - a {@link ZoneOffset} ID, such as 'Z' or '+02:00'
|
||||
* <li><code>UTC</code> - alternate form of a {@code ZoneOffset} ID equal to 'Z'
|
||||
* <li><code>UTC0</code> - alternate form of a {@code ZoneOffset} ID equal to 'Z'
|
||||
* <li><code>UTC{offset}</code> - alternate form of a {@code ZoneOffset} ID equal to '{offset}'
|
||||
* <li><code>GMT</code> - alternate form of a {@code ZoneOffset} ID equal to 'Z'
|
||||
* <li><code>GMT0</code> - alternate form of a {@code ZoneOffset} ID equal to 'Z'
|
||||
* <li><code>GMT{offset}</code> - alternate form of a {@code ZoneOffset} ID equal to '{offset}'r
|
||||
* <li><code>Z</code> - an offset of zero, which is {@code ZoneOffset.UTC}
|
||||
* <li><code>{offset}</code> - a {@code ZoneOffset} ID, such as '+02:00'
|
||||
* <li><code>{utcPrefix}</code> - a {@code ZoneOffset} ID equal to 'Z'
|
||||
* <li><code>{utcPrefix}0</code> - a {@code ZoneOffset} ID equal to 'Z'
|
||||
* <li><code>{utcPrefix}{offset}</code> - a {@code ZoneOffset} ID equal to '{offset}'
|
||||
* <li><code>{regionID}</code> - full region ID, loaded from configuration
|
||||
* </ul><p>
|
||||
* The {offset} is a valid format for {@link ZoneOffset#of(String)}, excluding 'Z'.
|
||||
* The {utcPrefix} is 'UTC', 'GMT' or 'UT'.
|
||||
* Region IDs must match the regular expression <code>[A-Za-z][A-Za-z0-9~/._+-]+</code>.
|
||||
* <p>
|
||||
* The detailed format of the region ID depends on the group supplying the data.
|
||||
@ -337,25 +339,52 @@ public abstract class ZoneId implements Serializable {
|
||||
* @param zoneId the time-zone ID, not null
|
||||
* @return the zone ID, not null
|
||||
* @throws DateTimeException if the zone ID has an invalid format
|
||||
* @throws java.time.zone.ZoneRulesException if the zone region ID cannot be found
|
||||
* @throws ZoneRulesException if the zone ID is a region ID that cannot be found
|
||||
*/
|
||||
public static ZoneId of(String zoneId) {
|
||||
Objects.requireNonNull(zoneId, "zoneId");
|
||||
if (zoneId.length() <= 1 || zoneId.startsWith("+") || zoneId.startsWith("-")) {
|
||||
return ZoneOffset.of(zoneId);
|
||||
} else if (zoneId.startsWith("UTC") || zoneId.startsWith("GMT")) {
|
||||
if (zoneId.length() == 3 || (zoneId.length() == 4 && zoneId.charAt(3) == '0')) {
|
||||
return ZoneOffset.UTC;
|
||||
}
|
||||
return ZoneOffset.of(zoneId.substring(3));
|
||||
return ofWithPrefix(zoneId, 3);
|
||||
} else if (zoneId.startsWith("UT")) {
|
||||
return ofWithPrefix(zoneId, 2);
|
||||
}
|
||||
return ZoneRegion.ofId(zoneId, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse once a prefix is established.
|
||||
*
|
||||
* @param zoneId the time-zone ID, not null
|
||||
* @param prefixLength the length of the prefix, 2 or 3
|
||||
* @return the zone ID, not null
|
||||
* @return the zone ID, not null
|
||||
* @throws DateTimeException if the zone ID has an invalid format
|
||||
*/
|
||||
private static ZoneId ofWithPrefix(String zoneId, int prefixLength) {
|
||||
if (zoneId.length() == prefixLength ||
|
||||
(zoneId.length() == prefixLength + 1 && zoneId.charAt(prefixLength) == '0')) {
|
||||
return ZoneOffset.UTC;
|
||||
}
|
||||
if (zoneId.charAt(prefixLength) == '+' || zoneId.charAt(prefixLength) == '-') {
|
||||
try {
|
||||
return ZoneOffset.of(zoneId.substring(prefixLength));
|
||||
} catch (DateTimeException ex) {
|
||||
throw new DateTimeException("Invalid ID for offset-based ZoneId: " + zoneId, ex);
|
||||
}
|
||||
}
|
||||
throw new DateTimeException("Invalid ID for offset-based ZoneId: " + zoneId);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code ZoneId} from a temporal object.
|
||||
* <p>
|
||||
* This obtains a zone based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code ZoneId}.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code ZoneId}.
|
||||
* <p>
|
||||
@ -417,7 +446,7 @@ public abstract class ZoneId implements Serializable {
|
||||
* {@link ZoneOffset} will always return a set of rules where the offset never changes.
|
||||
*
|
||||
* @return the rules, not null
|
||||
* @throws DateTimeException if no rules are available for this ID
|
||||
* @throws ZoneRulesException if no rules are available for this ID
|
||||
*/
|
||||
public abstract ZoneRules getRules();
|
||||
|
||||
@ -426,7 +455,9 @@ public abstract class ZoneId implements Serializable {
|
||||
* Gets the textual representation of the zone, such as 'British Time' or
|
||||
* '+02:00'.
|
||||
* <p>
|
||||
* This returns a textual description for the time-zone ID.
|
||||
* This returns the textual name used to identify the time-zone ID,
|
||||
* suitable for presentation to the user.
|
||||
* The parameters control the style of the returned text and the locale.
|
||||
* <p>
|
||||
* If no textual mapping is found then the {@link #getId() full ID} is returned.
|
||||
*
|
||||
@ -434,8 +465,8 @@ public abstract class ZoneId implements Serializable {
|
||||
* @param locale the locale to use, not null
|
||||
* @return the text value of the zone, not null
|
||||
*/
|
||||
public String getText(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendZoneText(style).toFormatter(locale).print(new TemporalAccessor() {
|
||||
public String getDisplayName(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendZoneText(style).toFormatter(locale).format(new TemporalAccessor() {
|
||||
@Override
|
||||
public boolean isSupported(TemporalField field) {
|
||||
return false;
|
||||
|
||||
@ -61,6 +61,9 @@
|
||||
*/
|
||||
package java.time;
|
||||
|
||||
import static java.time.LocalTime.MINUTES_PER_HOUR;
|
||||
import static java.time.LocalTime.SECONDS_PER_HOUR;
|
||||
import static java.time.LocalTime.SECONDS_PER_MINUTE;
|
||||
import static java.time.temporal.ChronoField.OFFSET_SECONDS;
|
||||
|
||||
import java.io.DataInput;
|
||||
@ -125,18 +128,6 @@ public final class ZoneOffset
|
||||
/** Cache of time-zone offset by ID. */
|
||||
private static final ConcurrentMap<String, ZoneOffset> ID_CACHE = new ConcurrentHashMap<>(16, 0.75f, 4);
|
||||
|
||||
/**
|
||||
* The number of seconds per hour.
|
||||
*/
|
||||
private static final int SECONDS_PER_HOUR = 60 * 60;
|
||||
/**
|
||||
* The number of seconds per minute.
|
||||
*/
|
||||
private static final int SECONDS_PER_MINUTE = 60;
|
||||
/**
|
||||
* The number of minutes per hour.
|
||||
*/
|
||||
private static final int MINUTES_PER_HOUR = 60;
|
||||
/**
|
||||
* The abs maximum seconds.
|
||||
*/
|
||||
@ -239,11 +230,11 @@ public final class ZoneOffset
|
||||
seconds = parseNumber(offsetId, 7, true);
|
||||
break;
|
||||
default:
|
||||
throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid");
|
||||
throw new DateTimeException("Invalid ID for ZoneOffset, invalid format: " + offsetId);
|
||||
}
|
||||
char first = offsetId.charAt(0);
|
||||
if (first != '+' && first != '-') {
|
||||
throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid: Plus/minus not found when expected");
|
||||
throw new DateTimeException("Invalid ID for ZoneOffset, plus/minus not found when expected: " + offsetId);
|
||||
}
|
||||
if (first == '-') {
|
||||
return ofHoursMinutesSeconds(-hours, -minutes, -seconds);
|
||||
@ -262,12 +253,12 @@ public final class ZoneOffset
|
||||
*/
|
||||
private static int parseNumber(CharSequence offsetId, int pos, boolean precededByColon) {
|
||||
if (precededByColon && offsetId.charAt(pos - 1) != ':') {
|
||||
throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid: Colon not found when expected");
|
||||
throw new DateTimeException("Invalid ID for ZoneOffset, colon not found when expected: " + offsetId);
|
||||
}
|
||||
char ch1 = offsetId.charAt(pos);
|
||||
char ch2 = offsetId.charAt(pos + 1);
|
||||
if (ch1 < '0' || ch1 > '9' || ch2 < '0' || ch2 > '9') {
|
||||
throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid: Non numeric characters found");
|
||||
throw new DateTimeException("Invalid ID for ZoneOffset, non numeric characters found: " + offsetId);
|
||||
}
|
||||
return (ch1 - 48) * 10 + (ch2 - 48);
|
||||
}
|
||||
@ -324,10 +315,15 @@ public final class ZoneOffset
|
||||
/**
|
||||
* Obtains an instance of {@code ZoneOffset} from a temporal object.
|
||||
* <p>
|
||||
* This obtains an offset based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code ZoneOffset}.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code ZoneOffset}.
|
||||
* <p>
|
||||
* The conversion extracts the {@link ChronoField#OFFSET_SECONDS offset-seconds} field.
|
||||
* The conversion uses the {@link Queries#offset()} query, which relies
|
||||
* on extracting the {@link ChronoField#OFFSET_SECONDS OFFSET_SECONDS} field.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used in queries via method reference, {@code ZoneOffset::from}.
|
||||
@ -337,14 +333,11 @@ public final class ZoneOffset
|
||||
* @throws DateTimeException if unable to convert to an {@code ZoneOffset}
|
||||
*/
|
||||
public static ZoneOffset from(TemporalAccessor temporal) {
|
||||
if (temporal instanceof ZoneOffset) {
|
||||
return (ZoneOffset) temporal;
|
||||
}
|
||||
try {
|
||||
return ofTotalSeconds(temporal.get(OFFSET_SECONDS));
|
||||
} catch (DateTimeException ex) {
|
||||
throw new DateTimeException("Unable to obtain ZoneOffset from TemporalAccessor: " + temporal.getClass(), ex);
|
||||
ZoneOffset offset = temporal.query(Queries.offset());
|
||||
if (offset == null) {
|
||||
throw new DateTimeException("Unable to obtain ZoneOffset from TemporalAccessor: " + temporal.getClass());
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -515,7 +508,7 @@ public final class ZoneOffset
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -527,7 +520,7 @@ public final class ZoneOffset
|
||||
if (field instanceof ChronoField) {
|
||||
return field == OFFSET_SECONDS;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -544,7 +537,7 @@ public final class ZoneOffset
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -570,7 +563,7 @@ public final class ZoneOffset
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -601,7 +594,7 @@ public final class ZoneOffset
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -617,7 +610,7 @@ public final class ZoneOffset
|
||||
} else if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
@ -113,7 +113,7 @@ final class ZoneRegion extends ZoneId implements Serializable {
|
||||
* if the time-zone has available rules.
|
||||
* <p>
|
||||
* This method parses the ID and applies any appropriate normalization.
|
||||
* It does not validate the ID against the known set of IDsfor which rules are available.
|
||||
* It does not validate the ID against the known set of IDs for which rules are available.
|
||||
* <p>
|
||||
* This method is intended for advanced use cases.
|
||||
* For example, consider a system that always retrieves time-zone rules from a remote server.
|
||||
@ -135,18 +135,20 @@ final class ZoneRegion extends ZoneId implements Serializable {
|
||||
* @param checkAvailable whether to check if the zone ID is available
|
||||
* @return the zone ID, not null
|
||||
* @throws DateTimeException if the ID format is invalid
|
||||
* @throws DateTimeException if checking availability and the ID cannot be found
|
||||
* @throws ZoneRulesException if checking availability and the ID cannot be found
|
||||
*/
|
||||
static ZoneRegion ofId(String zoneId, boolean checkAvailable) {
|
||||
Objects.requireNonNull(zoneId, "zoneId");
|
||||
if (zoneId.length() < 2 || zoneId.startsWith("UTC") ||
|
||||
zoneId.startsWith("GMT") || (PATTERN.matcher(zoneId).matches() == false)) {
|
||||
throw new DateTimeException("ZoneId format is not a valid region format");
|
||||
if (zoneId.length() < 2 ||
|
||||
zoneId.startsWith("UT") || // includes UTC
|
||||
zoneId.startsWith("GMT") ||
|
||||
(PATTERN.matcher(zoneId).matches() == false)) {
|
||||
throw new DateTimeException("Invalid ID for region-based ZoneId, invalid format: " + zoneId);
|
||||
}
|
||||
ZoneRules rules = null;
|
||||
try {
|
||||
// always attempt load for better behavior after deserialization
|
||||
rules = ZoneRulesProvider.getRules(zoneId);
|
||||
rules = ZoneRulesProvider.getRules(zoneId, true);
|
||||
} catch (ZoneRulesException ex) {
|
||||
if (checkAvailable) {
|
||||
throw ex;
|
||||
@ -176,8 +178,8 @@ final class ZoneRegion extends ZoneId implements Serializable {
|
||||
@Override
|
||||
public ZoneRules getRules() {
|
||||
// additional query for group provider when null allows for possibility
|
||||
// that the provider was added after the ZoneId was created
|
||||
return (rules != null ? rules : ZoneRulesProvider.getRules(id));
|
||||
// that the provider was updated after the ZoneId was created
|
||||
return (rules != null ? rules : ZoneRulesProvider.getRules(id, false));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
@ -65,27 +65,24 @@ import static java.time.temporal.ChronoField.INSTANT_SECONDS;
|
||||
import static java.time.temporal.ChronoField.NANO_OF_SECOND;
|
||||
import static java.time.temporal.ChronoField.OFFSET_SECONDS;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.InvalidObjectException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.time.chrono.ChronoZonedDateTime;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatters;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.ChronoZonedDateTime;
|
||||
import java.time.temporal.ISOChrono;
|
||||
import java.time.temporal.OffsetDateTime;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdder;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalSubtractor;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.time.zone.ZoneOffsetTransition;
|
||||
@ -152,7 +149,7 @@ import java.util.Objects;
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class ZonedDateTime
|
||||
implements Temporal, ChronoZonedDateTime<ISOChrono>, Serializable {
|
||||
implements Temporal, ChronoZonedDateTime<LocalDate>, Serializable {
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
@ -225,6 +222,36 @@ public final class ZonedDateTime
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code ZonedDateTime} from a local date and time.
|
||||
* <p>
|
||||
* This creates a zoned date-time matching the input local date and time as closely as possible.
|
||||
* Time-zone rules, such as daylight savings, mean that not every local date-time
|
||||
* is valid for the specified zone, thus the local date-time may be adjusted.
|
||||
* <p>
|
||||
* The local date time and first combined to form a local date-time.
|
||||
* The local date-time is then resolved to a single instant on the time-line.
|
||||
* This is achieved by finding a valid offset from UTC/Greenwich for the local
|
||||
* date-time as defined by the {@link ZoneRules rules} of the zone ID.
|
||||
*<p>
|
||||
* In most cases, there is only one valid offset for a local date-time.
|
||||
* In the case of an overlap, when clocks are set back, there are two valid offsets.
|
||||
* This method uses the earlier offset typically corresponding to "summer".
|
||||
* <p>
|
||||
* In the case of a gap, when clocks jump forward, there is no valid offset.
|
||||
* Instead, the local date-time is adjusted to be later by the length of the gap.
|
||||
* For a typical one hour daylight savings change, the local date-time will be
|
||||
* moved one hour later into the offset typically corresponding to "summer".
|
||||
*
|
||||
* @param date the local date, not null
|
||||
* @param time the local time, not null
|
||||
* @param zone the time-zone, not null
|
||||
* @return the offset date-time, not null
|
||||
*/
|
||||
public static ZonedDateTime of(LocalDate date, LocalTime time, ZoneId zone) {
|
||||
return of(LocalDateTime.of(date, time), zone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code ZonedDateTime} from a local date-time.
|
||||
* <p>
|
||||
@ -253,6 +280,53 @@ public final class ZonedDateTime
|
||||
return ofLocal(localDateTime, zone, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code ZonedDateTime} from a year, month, day,
|
||||
* hour, minute, second, nanosecond and time-zone.
|
||||
* <p>
|
||||
* This creates a zoned date-time matching the local date-time of the seven
|
||||
* specified fields as closely as possible.
|
||||
* Time-zone rules, such as daylight savings, mean that not every local date-time
|
||||
* is valid for the specified zone, thus the local date-time may be adjusted.
|
||||
* <p>
|
||||
* The local date-time is resolved to a single instant on the time-line.
|
||||
* This is achieved by finding a valid offset from UTC/Greenwich for the local
|
||||
* date-time as defined by the {@link ZoneRules rules} of the zone ID.
|
||||
*<p>
|
||||
* In most cases, there is only one valid offset for a local date-time.
|
||||
* In the case of an overlap, when clocks are set back, there are two valid offsets.
|
||||
* This method uses the earlier offset typically corresponding to "summer".
|
||||
* <p>
|
||||
* In the case of a gap, when clocks jump forward, there is no valid offset.
|
||||
* Instead, the local date-time is adjusted to be later by the length of the gap.
|
||||
* For a typical one hour daylight savings change, the local date-time will be
|
||||
* moved one hour later into the offset typically corresponding to "summer".
|
||||
* <p>
|
||||
* This method exists primarily for writing test cases.
|
||||
* Non test-code will typically use other methods to create an offset time.
|
||||
* {@code LocalDateTime} has five additional convenience variants of the
|
||||
* equivalent factory method taking fewer arguments.
|
||||
* They are not provided here to reduce the footprint of the API.
|
||||
*
|
||||
* @param year the year to represent, from MIN_YEAR to MAX_YEAR
|
||||
* @param month the month-of-year to represent, from 1 (January) to 12 (December)
|
||||
* @param dayOfMonth the day-of-month to represent, from 1 to 31
|
||||
* @param hour the hour-of-day to represent, from 0 to 23
|
||||
* @param minute the minute-of-hour to represent, from 0 to 59
|
||||
* @param second the second-of-minute to represent, from 0 to 59
|
||||
* @param nanoOfSecond the nano-of-second to represent, from 0 to 999,999,999
|
||||
* @param zone the time-zone, not null
|
||||
* @return the offset date-time, not null
|
||||
* @throws DateTimeException if the value of any field is out of range, or
|
||||
* if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static ZonedDateTime of(
|
||||
int year, int month, int dayOfMonth,
|
||||
int hour, int minute, int second, int nanoOfSecond, ZoneId zone) {
|
||||
LocalDateTime dt = LocalDateTime.of(year, month, dayOfMonth, hour, minute, second, nanoOfSecond);
|
||||
return ofLocal(dt, zone, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code ZonedDateTime} from a local date-time
|
||||
* using the preferred offset if possible.
|
||||
@ -436,13 +510,17 @@ public final class ZonedDateTime
|
||||
/**
|
||||
* Obtains an instance of {@code ZonedDateTime} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code ZonedDateTime}.
|
||||
* This obtains a zoned date-time based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code ZonedDateTime}.
|
||||
* <p>
|
||||
* The conversion will first obtain a {@code ZoneId}. It will then try to obtain an instant.
|
||||
* If that fails it will try to obtain a local date-time.
|
||||
* The zoned date time will either be a combination of {@code ZoneId} and instant,
|
||||
* or {@code ZoneId} and local date-time.
|
||||
* The conversion will first obtain a {@code ZoneId} from the temporal object,
|
||||
* falling back to a {@code ZoneOffset} if necessary. It will then try to obtain
|
||||
* an {@code Instant}, falling back to a {@code LocalDateTime} if necessary.
|
||||
* The result will be either the combination of {@code ZoneId} or {@code ZoneOffset}
|
||||
* with {@code Instant} or {@code LocalDateTime}.
|
||||
* Implementations are permitted to perform optimizations such as accessing
|
||||
* those fields that are equivalent to the relevant objects.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used in queries via method reference, {@code ZonedDateTime::from}.
|
||||
@ -477,14 +555,14 @@ public final class ZonedDateTime
|
||||
* {@code 2007-12-03T10:15:30+01:00[Europe/Paris]}.
|
||||
* <p>
|
||||
* The string must represent a valid date-time and is parsed using
|
||||
* {@link java.time.format.DateTimeFormatters#isoZonedDateTime()}.
|
||||
* {@link java.time.format.DateTimeFormatter#ISO_ZONED_DATE_TIME}.
|
||||
*
|
||||
* @param text the text to parse such as "2007-12-03T10:15:30+01:00[Europe/Paris]", not null
|
||||
* @return the parsed zoned date-time, not null
|
||||
* @throws DateTimeParseException if the text cannot be parsed
|
||||
*/
|
||||
public static ZonedDateTime parse(CharSequence text) {
|
||||
return parse(text, DateTimeFormatters.isoZonedDateTime());
|
||||
return parse(text, DateTimeFormatter.ISO_ZONED_DATE_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -595,7 +673,7 @@ public final class ZonedDateTime
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -604,7 +682,7 @@ public final class ZonedDateTime
|
||||
*/
|
||||
@Override
|
||||
public boolean isSupported(TemporalField field) {
|
||||
return field instanceof ChronoField || (field != null && field.doIsSupported(this));
|
||||
return field instanceof ChronoField || (field != null && field.isSupportedBy(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -621,7 +699,7 @@ public final class ZonedDateTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -637,7 +715,7 @@ public final class ZonedDateTime
|
||||
}
|
||||
return dateTime.range(field);
|
||||
}
|
||||
return field.doRange(this);
|
||||
return field.rangeRefinedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -656,7 +734,7 @@ public final class ZonedDateTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -690,7 +768,7 @@ public final class ZonedDateTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -708,7 +786,7 @@ public final class ZonedDateTime
|
||||
}
|
||||
return dateTime.getLong(field);
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -770,7 +848,7 @@ public final class ZonedDateTime
|
||||
*/
|
||||
@Override
|
||||
public ZonedDateTime withLaterOffsetAtOverlap() {
|
||||
ZoneOffsetTransition trans = getZone().getRules().getTransition(getDateTime());
|
||||
ZoneOffsetTransition trans = getZone().getRules().getTransition(toLocalDateTime());
|
||||
if (trans != null) {
|
||||
ZoneOffset laterOffset = trans.getOffsetAfter();
|
||||
if (laterOffset.equals(offset) == false) {
|
||||
@ -859,7 +937,7 @@ public final class ZonedDateTime
|
||||
* as most protocols, such as ISO-8601, only handle offsets,
|
||||
* and not region-based zone IDs.
|
||||
* <p>
|
||||
* This is equivalent to {@code ZonedDateTime.of(zdt.getDateTime(), zdt.getOffset())}.
|
||||
* This is equivalent to {@code ZonedDateTime.of(zdt.toLocalDateTime(), zdt.getOffset())}.
|
||||
*
|
||||
* @return a {@code ZonedDateTime} with the zone ID set to the offset, not null
|
||||
*/
|
||||
@ -877,7 +955,7 @@ public final class ZonedDateTime
|
||||
* @return the local date-time part of this date-time, not null
|
||||
*/
|
||||
@Override // override for return type
|
||||
public LocalDateTime getDateTime() {
|
||||
public LocalDateTime toLocalDateTime() {
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
@ -891,8 +969,8 @@ public final class ZonedDateTime
|
||||
* @return the date part of this date-time, not null
|
||||
*/
|
||||
@Override // override for return type
|
||||
public LocalDate getDate() {
|
||||
return dateTime.getDate();
|
||||
public LocalDate toLocalDate() {
|
||||
return dateTime.toLocalDate();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -901,7 +979,7 @@ public final class ZonedDateTime
|
||||
* This method returns the primitive {@code int} value for the year.
|
||||
* <p>
|
||||
* The year returned by this method is proleptic as per {@code get(YEAR)}.
|
||||
* To obtain the year-of-era, use {@code get(YEAR_OF_ERA}.
|
||||
* To obtain the year-of-era, use {@code get(YEAR_OF_ERA)}.
|
||||
*
|
||||
* @return the year, from MIN_YEAR to MAX_YEAR
|
||||
*/
|
||||
@ -987,8 +1065,8 @@ public final class ZonedDateTime
|
||||
* @return the time part of this date-time, not null
|
||||
*/
|
||||
@Override // override for Javadoc and performance
|
||||
public LocalTime getTime() {
|
||||
return dateTime.getTime();
|
||||
public LocalTime toLocalTime() {
|
||||
return dateTime.toLocalTime();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1031,7 +1109,7 @@ public final class ZonedDateTime
|
||||
/**
|
||||
* Returns an adjusted copy of this date-time.
|
||||
* <p>
|
||||
* This returns a new {@code ZonedDateTime}, based on this one, with the date-time adjusted.
|
||||
* This returns a {@code ZonedDateTime}, based on this one, with the date-time adjusted.
|
||||
* The adjustment takes place using the specified adjuster strategy object.
|
||||
* Read the documentation of the adjuster to understand what adjustment will be made.
|
||||
* <p>
|
||||
@ -1040,7 +1118,7 @@ public final class ZonedDateTime
|
||||
* A selection of common adjustments is provided in {@link java.time.temporal.Adjusters}.
|
||||
* These include finding the "last day of the month" and "next Wednesday".
|
||||
* Key date-time classes also implement the {@code TemporalAdjuster} interface,
|
||||
* such as {@link Month} and {@link java.time.temporal.MonthDay MonthDay}.
|
||||
* such as {@link Month} and {@link java.time.MonthDay MonthDay}.
|
||||
* The adjuster is responsible for handling special cases, such as the varying
|
||||
* lengths of month and leap years.
|
||||
* <p>
|
||||
@ -1084,9 +1162,9 @@ public final class ZonedDateTime
|
||||
public ZonedDateTime with(TemporalAdjuster adjuster) {
|
||||
// optimizations
|
||||
if (adjuster instanceof LocalDate) {
|
||||
return resolveLocal(LocalDateTime.of((LocalDate) adjuster, dateTime.getTime()));
|
||||
return resolveLocal(LocalDateTime.of((LocalDate) adjuster, dateTime.toLocalTime()));
|
||||
} else if (adjuster instanceof LocalTime) {
|
||||
return resolveLocal(LocalDateTime.of(dateTime.getDate(), (LocalTime) adjuster));
|
||||
return resolveLocal(LocalDateTime.of(dateTime.toLocalDate(), (LocalTime) adjuster));
|
||||
} else if (adjuster instanceof LocalDateTime) {
|
||||
return resolveLocal((LocalDateTime) adjuster);
|
||||
} else if (adjuster instanceof Instant) {
|
||||
@ -1101,7 +1179,7 @@ public final class ZonedDateTime
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified field set to a new value.
|
||||
* <p>
|
||||
* This returns a new {@code ZonedDateTime}, based on this one, with the value
|
||||
* This returns a {@code ZonedDateTime}, based on this one, with the value
|
||||
* for the specified field changed.
|
||||
* This can be used to change any supported field, such as the year, month or day-of-month.
|
||||
* If it is not possible to set the value, because the field is not supported or for
|
||||
@ -1139,7 +1217,7 @@ public final class ZonedDateTime
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doWith(Temporal, long)}
|
||||
* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the field determines
|
||||
* whether and how to adjust the instant.
|
||||
* <p>
|
||||
@ -1164,7 +1242,7 @@ public final class ZonedDateTime
|
||||
}
|
||||
return resolveLocal(dateTime.with(field, newValue));
|
||||
}
|
||||
return field.doWith(this, newValue);
|
||||
return field.adjustInto(this, newValue);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -1228,8 +1306,8 @@ public final class ZonedDateTime
|
||||
*
|
||||
* @param dayOfMonth the day-of-month to set in the result, from 1 to 28-31
|
||||
* @return a {@code ZonedDateTime} based on this date-time with the requested day, not null
|
||||
* @throws DateTimeException if the day-of-month value is invalid
|
||||
* @throws DateTimeException if the day-of-month is invalid for the month-year
|
||||
* @throws DateTimeException if the day-of-month value is invalid,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public ZonedDateTime withDayOfMonth(int dayOfMonth) {
|
||||
return resolveLocal(dateTime.withDayOfMonth(dayOfMonth));
|
||||
@ -1251,8 +1329,8 @@ public final class ZonedDateTime
|
||||
*
|
||||
* @param dayOfYear the day-of-year to set in the result, from 1 to 365-366
|
||||
* @return a {@code ZonedDateTime} based on this date with the requested day, not null
|
||||
* @throws DateTimeException if the day-of-year value is invalid
|
||||
* @throws DateTimeException if the day-of-year is invalid for the year
|
||||
* @throws DateTimeException if the day-of-year value is invalid,
|
||||
* or if the day-of-year is invalid for the year
|
||||
*/
|
||||
public ZonedDateTime withDayOfYear(int dayOfYear) {
|
||||
return resolveLocal(dateTime.withDayOfYear(dayOfYear));
|
||||
@ -1356,8 +1434,10 @@ public final class ZonedDateTime
|
||||
* For example, truncating with the {@link ChronoUnit#MINUTES minutes} unit
|
||||
* will set the second-of-minute and nano-of-second field to zero.
|
||||
* <p>
|
||||
* Not all units are accepted. The {@link ChronoUnit#DAYS days} unit and time
|
||||
* units with an exact duration can be used, other units throw an exception.
|
||||
* The unit must have a {@linkplain TemporalUnit#getDuration() duration}
|
||||
* that divides into the length of a standard day without remainder.
|
||||
* This includes all supplied time units on {@link ChronoUnit} and
|
||||
* {@link ChronoUnit#DAYS DAYS}. Other units throw an exception.
|
||||
* <p>
|
||||
* This operates on the local time-line,
|
||||
* {@link LocalDateTime#truncatedTo(java.time.temporal.TemporalUnit) truncating}
|
||||
@ -1380,34 +1460,39 @@ public final class ZonedDateTime
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified period added.
|
||||
* Returns a copy of this date-time with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new date-time based on this time with the specified period added.
|
||||
* The adder is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalAdder} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #plus(long, TemporalUnit)}.
|
||||
* This returns a {@code ZonedDateTime}, based on this one, with the specified amount added.
|
||||
* The amount is typically {@link Period} or {@link Duration} but may be
|
||||
* any other type implementing the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free
|
||||
* to implement the addition in any way it wishes, however it typically
|
||||
* calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully added.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param adder the adder to use, not null
|
||||
* @param amountToAdd the amount to add, not null
|
||||
* @return a {@code ZonedDateTime} based on this date-time with the addition made, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public ZonedDateTime plus(TemporalAdder adder) {
|
||||
return (ZonedDateTime) adder.addTo(this);
|
||||
public ZonedDateTime plus(TemporalAmount amountToAdd) {
|
||||
return (ZonedDateTime) amountToAdd.addTo(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified period added.
|
||||
* Returns a copy of this date-time with the specified amount added.
|
||||
* <p>
|
||||
* This method returns a new date-time based on this date-time with the specified period added.
|
||||
* This can be used to add any period that is defined by a unit, for example to add years, months or days.
|
||||
* The unit is responsible for the details of the calculation, including the resolution
|
||||
* of any edge cases in the calculation.
|
||||
* This returns a {@code ZonedDateTime}, based on this one, with the amount
|
||||
* in terms of the unit added. If it is not possible to add the amount, because the
|
||||
* unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* If the field is a {@link ChronoUnit} then the addition is implemented here.
|
||||
* The zone is not part of the calculation and will be unchanged in the result.
|
||||
* The calculation for date and time units differ.
|
||||
* <p>
|
||||
* Date units operate on the local time-line.
|
||||
@ -1422,12 +1507,18 @@ public final class ZonedDateTime
|
||||
* The conversion uses {@link #ofInstant(LocalDateTime, ZoneOffset, ZoneId)}
|
||||
* with the offset before the addition.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoUnit}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
|
||||
* passing {@code this} as the argument. In this case, the unit determines
|
||||
* whether and how to perform the addition.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToAdd the amount of the unit to add to the result, may be negative
|
||||
* @param unit the unit of the period to add, not null
|
||||
* @return a {@code ZonedDateTime} based on this date-time with the specified period added, not null
|
||||
* @throws DateTimeException if the unit cannot be added to this type
|
||||
* @param unit the unit of the amount to add, not null
|
||||
* @return a {@code ZonedDateTime} based on this date-time with the specified amount added, not null
|
||||
* @throws DateTimeException if the addition cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public ZonedDateTime plus(long amountToAdd, TemporalUnit unit) {
|
||||
@ -1439,7 +1530,7 @@ public final class ZonedDateTime
|
||||
return resolveInstant(dateTime.plus(amountToAdd, unit));
|
||||
}
|
||||
}
|
||||
return unit.doPlus(this, amountToAdd);
|
||||
return unit.addTo(this, amountToAdd);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -1616,33 +1707,36 @@ public final class ZonedDateTime
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified period subtracted.
|
||||
* Returns a copy of this date-time with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new date-time based on this time with the specified period subtracted.
|
||||
* The subtractor is typically {@link Period} but may be any other type implementing
|
||||
* the {@link TemporalSubtractor} interface.
|
||||
* The calculation is delegated to the specified adjuster, which typically calls
|
||||
* back to {@link #minus(long, TemporalUnit)}.
|
||||
* This returns a {@code ZonedDateTime}, based on this one, with the specified amount subtracted.
|
||||
* The amount is typically {@link Period} or {@link Duration} but may be
|
||||
* any other type implementing the {@link TemporalAmount} interface.
|
||||
* <p>
|
||||
* The calculation is delegated to the amount object by calling
|
||||
* {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free
|
||||
* to implement the subtraction in any way it wishes, however it typically
|
||||
* calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation
|
||||
* of the amount implementation to determine if it can be successfully subtracted.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param subtractor the subtractor to use, not null
|
||||
* @param amountToSubtract the amount to subtract, not null
|
||||
* @return a {@code ZonedDateTime} based on this date-time with the subtraction made, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public ZonedDateTime minus(TemporalSubtractor subtractor) {
|
||||
return (ZonedDateTime) subtractor.subtractFrom(this);
|
||||
public ZonedDateTime minus(TemporalAmount amountToSubtract) {
|
||||
return (ZonedDateTime) amountToSubtract.subtractFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this date-time with the specified period subtracted.
|
||||
* Returns a copy of this date-time with the specified amount subtracted.
|
||||
* <p>
|
||||
* This method returns a new date-time based on this date-time with the specified period subtracted.
|
||||
* This can be used to subtract any period that is defined by a unit, for example to subtract years, months or days.
|
||||
* The unit is responsible for the details of the calculation, including the resolution
|
||||
* of any edge cases in the calculation.
|
||||
* This returns a {@code ZonedDateTime}, based on this one, with the amount
|
||||
* in terms of the unit subtracted. If it is not possible to subtract the amount,
|
||||
* because the unit is not supported or for some other reason, an exception is thrown.
|
||||
* <p>
|
||||
* The calculation for date and time units differ.
|
||||
* <p>
|
||||
@ -1658,12 +1752,16 @@ public final class ZonedDateTime
|
||||
* The conversion uses {@link #ofInstant(LocalDateTime, ZoneOffset, ZoneId)}
|
||||
* with the offset before the subtraction.
|
||||
* <p>
|
||||
* This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.
|
||||
* See that method for a full description of how addition, and thus subtraction, works.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param amountToSubtract the amount of the unit to subtract from the result, may be negative
|
||||
* @param unit the unit of the period to subtract, not null
|
||||
* @return a {@code ZonedDateTime} based on this date-time with the specified period subtracted, not null
|
||||
* @throws DateTimeException if the unit cannot be added to this type
|
||||
* @param unit the unit of the amount to subtract, not null
|
||||
* @return a {@code ZonedDateTime} based on this date-time with the specified amount subtracted, not null
|
||||
* @throws DateTimeException if the subtraction cannot be made
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
@Override
|
||||
public ZonedDateTime minus(long amountToSubtract, TemporalUnit unit) {
|
||||
@ -1885,14 +1983,15 @@ public final class ZonedDateTime
|
||||
* For example, the period in months between 2012-06-15T00:00Z and 2012-08-14T23:59Z
|
||||
* will only be one month as it is one minute short of two months.
|
||||
* <p>
|
||||
* This method operates in association with {@link TemporalUnit#between}.
|
||||
* The result of this method is a {@code long} representing the amount of
|
||||
* the specified unit. By contrast, the result of {@code between} is an
|
||||
* object that can be used directly in addition/subtraction:
|
||||
* There are two equivalent ways of using this method.
|
||||
* The first is to invoke this method.
|
||||
* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
|
||||
* <pre>
|
||||
* long period = start.periodUntil(end, MONTHS); // this method
|
||||
* dateTime.plus(MONTHS.between(start, end)); // use in plus/minus
|
||||
* // these two lines are equivalent
|
||||
* amount = start.periodUntil(end, MONTHS);
|
||||
* amount = MONTHS.between(start, end);
|
||||
* </pre>
|
||||
* The choice should be made based on which makes the code more readable.
|
||||
* <p>
|
||||
* The calculation is implemented in this method for {@link ChronoUnit}.
|
||||
* The units {@code NANOS}, {@code MICROS}, {@code MILLIS}, {@code SECONDS},
|
||||
@ -1944,7 +2043,7 @@ public final class ZonedDateTime
|
||||
return toOffsetDateTime().periodUntil(end.toOffsetDateTime(), unit);
|
||||
}
|
||||
}
|
||||
return unit.between(this, endDateTime).getAmount();
|
||||
return unit.between(this, endDateTime);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -2018,7 +2117,7 @@ public final class ZonedDateTime
|
||||
* Outputs this date-time as a {@code String} using the formatter.
|
||||
* <p>
|
||||
* This date will be passed to the formatter
|
||||
* {@link DateTimeFormatter#print(TemporalAccessor) print method}.
|
||||
* {@link DateTimeFormatter#format(TemporalAccessor) format method}.
|
||||
*
|
||||
* @param formatter the formatter to use, not null
|
||||
* @return the formatted date-time string, not null
|
||||
@ -2061,7 +2160,7 @@ public final class ZonedDateTime
|
||||
zone.write(out);
|
||||
}
|
||||
|
||||
static ZonedDateTime readExternal(DataInput in) throws IOException {
|
||||
static ZonedDateTime readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
LocalDateTime dateTime = LocalDateTime.readExternal(in);
|
||||
ZoneOffset offset = ZoneOffset.readExternal(in);
|
||||
ZoneId zone = (ZoneId) Ser.read(in);
|
||||
|
||||
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of JSR-310 nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Support for calendar systems other than the default ISO.
|
||||
* </p>
|
||||
* <p>
|
||||
* The main API is based around the calendar system defined in ISO-8601.
|
||||
* This package provides support for alternate systems.
|
||||
* </p>
|
||||
* <p>
|
||||
* The supported calendar systems includes:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>{@link java.time.calendar.HijrahChrono Hijrah calendar}</li>
|
||||
* <li>{@link java.time.calendar.JapaneseChrono Japanese calendar}</li>
|
||||
* <li>{@link java.time.calendar.MinguoChrono Minguo calendar}</li>
|
||||
* <li>{@link java.time.calendar.ThaiBuddhistChrono Thai Buddhist calendar}</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* It is intended that applications use the main API whenever possible,
|
||||
* including code to read and write from a persistent data store,
|
||||
* such as a database, and to send dates and times across a network.
|
||||
* This package is then used at the user interface level to deal with
|
||||
* localized input/output.
|
||||
* See {@link java.time.temporal.ChronoLocalDate ChronoLocalDate}
|
||||
* for a full discussion of the issues.
|
||||
* </p>
|
||||
*
|
||||
* <h3>Example</h3>
|
||||
* <p>
|
||||
* This example creates and uses a date in a non-ISO calendar system.
|
||||
* </p>
|
||||
* <pre>
|
||||
* // Print the Thai Buddhist date
|
||||
* ChronoLocalDate<ThaiBuddhistChrono> now1 = ThaiBuddhistChrono.INSTANCE.dateNow();
|
||||
* int day = now1.get(ChronoField.DAY_OF_MONTH);
|
||||
* int dow = now1.get(ChronoField.DAY_OF_WEEK);
|
||||
* int month = now1.get(ChronoField.MONTH_OF_YEAR);
|
||||
* int year = now1.get(ChronoField.YEAR);
|
||||
* System.out.printf(" Today is %s %s %d-%s-%d%n", now1.getChrono().getId(),
|
||||
* dow, day, month, year);
|
||||
*
|
||||
* // Enumerate the list of available calendars and print today for each
|
||||
* Set<Chrono<?>> chronos = Chrono.getAvailableChronologies();
|
||||
* for (Chrono<?> chrono : chronos) {
|
||||
* ChronoLocalDate<?> date = chrono.dateNow();
|
||||
* System.out.printf(" %20s: %s%n", chrono.getId(), date.toString());
|
||||
* }
|
||||
*
|
||||
* // Print today's date and the last day of the year for the Thai Buddhist Calendar.
|
||||
* ChronoLocalDate<ThaiBuddhistChrono> first = now1
|
||||
* .with(ChronoField.DAY_OF_MONTH, 1)
|
||||
* .with(ChronoField.MONTH_OF_YEAR, 1);
|
||||
* ChronoLocalDate<ThaiBuddhistChrono> last = first
|
||||
* .plus(1, ChronoUnit.YEARS)
|
||||
* .minus(1, ChronoUnit.DAYS);
|
||||
* System.out.printf(" %s: 1st of year: %s; end of year: %s%n", last.getChrono().getId(),
|
||||
* first, last);
|
||||
* </pre>
|
||||
*
|
||||
* <h3>Package specification</h3>
|
||||
* <p>
|
||||
* Unless otherwise noted, passing a null argument to a constructor or method in any class or interface
|
||||
* in this package will cause a {@link java.lang.NullPointerException NullPointerException} to be thrown.
|
||||
* The Javadoc "@param" definition is used to summarise the null-behavior.
|
||||
* The "@throws {@link java.lang.NullPointerException}" is not explicitly documented in each method.
|
||||
* </p>
|
||||
* <p>
|
||||
* All calculations should check for numeric overflow and throw either an {@link java.lang.ArithmeticException}
|
||||
* or a {@link java.time.DateTimeException}.
|
||||
* </p>
|
||||
* @since JDK1.8
|
||||
*/
|
||||
package java.time.calendar;
|
||||
@ -54,7 +54,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
|
||||
import static java.time.temporal.ChronoField.ERA;
|
||||
@ -65,9 +65,9 @@ import java.io.Serializable;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.temporal.Chrono;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.ChronoLocalDateTime;
|
||||
import java.time.chrono.Chronology;
|
||||
import java.time.chrono.ChronoLocalDate;
|
||||
import java.time.chrono.ChronoLocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
@ -80,7 +80,7 @@ import java.time.temporal.TemporalUnit;
|
||||
* For example, the Japanese, Minguo, Thai Buddhist and others.
|
||||
* <p>
|
||||
* {@code ChronoLocalDate} is built on the generic concepts of year, month and day.
|
||||
* The calendar system, represented by a {@link java.time.temporal.Chrono}, expresses the relationship between
|
||||
* The calendar system, represented by a {@link java.time.chrono.Chronology}, expresses the relationship between
|
||||
* the fields and this class allows the resulting date to be manipulated.
|
||||
* <p>
|
||||
* Note that not all calendar systems are suitable for use with this class.
|
||||
@ -95,52 +95,52 @@ import java.time.temporal.TemporalUnit;
|
||||
* <pre>
|
||||
* System.out.printf("Example()%n");
|
||||
* // Enumerate the list of available calendars and print today for each
|
||||
* Set<Chrono> chronos = Chrono.getAvailableChronologies();
|
||||
* for (Chrono chrono : chronos) {
|
||||
* Set<Chronology> chronos = Chronology.getAvailableChronologies();
|
||||
* for (Chronology chrono : chronos) {
|
||||
* ChronoLocalDate<?> date = chrono.dateNow();
|
||||
* System.out.printf(" %20s: %s%n", chrono.getID(), date.toString());
|
||||
* }
|
||||
*
|
||||
* // Print the Hijrah date and calendar
|
||||
* ChronoLocalDate<?> date = Chrono.of("Hijrah").dateNow();
|
||||
* ChronoLocalDate<?> date = Chronology.of("Hijrah").dateNow();
|
||||
* int day = date.get(ChronoField.DAY_OF_MONTH);
|
||||
* int dow = date.get(ChronoField.DAY_OF_WEEK);
|
||||
* int month = date.get(ChronoField.MONTH_OF_YEAR);
|
||||
* int year = date.get(ChronoField.YEAR);
|
||||
* System.out.printf(" Today is %s %s %d-%s-%d%n", date.getChrono().getID(),
|
||||
* System.out.printf(" Today is %s %s %d-%s-%d%n", date.getChronology().getID(),
|
||||
* dow, day, month, year);
|
||||
|
||||
* // Print today's date and the last day of the year
|
||||
* ChronoLocalDate<?> now1 = Chrono.of("Hijrah").dateNow();
|
||||
* ChronoLocalDate<?> now1 = Chronology.of("Hijrah").dateNow();
|
||||
* ChronoLocalDate<?> first = now1.with(ChronoField.DAY_OF_MONTH, 1)
|
||||
* .with(ChronoField.MONTH_OF_YEAR, 1);
|
||||
* ChronoLocalDate<?> last = first.plus(1, ChronoUnit.YEARS)
|
||||
* .minus(1, ChronoUnit.DAYS);
|
||||
* System.out.printf(" Today is %s: start: %s; end: %s%n", last.getChrono().getID(),
|
||||
* System.out.printf(" Today is %s: start: %s; end: %s%n", last.getChronology().getID(),
|
||||
* first, last);
|
||||
* </pre>
|
||||
*
|
||||
* <h3>Adding Calendars</h3>
|
||||
* <p> The set of calendars is extensible by defining a subclass of {@link ChronoLocalDate}
|
||||
* to represent a date instance and an implementation of {@code Chrono}
|
||||
* to represent a date instance and an implementation of {@code Chronology}
|
||||
* to be the factory for the ChronoLocalDate subclass.
|
||||
* </p>
|
||||
* <p> To permit the discovery of the additional calendar types the implementation of
|
||||
* {@code Chrono} must be registered as a Service implementing the {@code Chrono} interface
|
||||
* {@code Chronology} must be registered as a Service implementing the {@code Chronology} interface
|
||||
* in the {@code META-INF/Services} file as per the specification of {@link java.util.ServiceLoader}.
|
||||
* The subclass must function according to the {@code Chrono} class description and must provide its
|
||||
* {@link java.time.temporal.Chrono#getId() chronlogy ID} and {@link Chrono#getCalendarType() calendar type}. </p>
|
||||
* The subclass must function according to the {@code Chronology} class description and must provide its
|
||||
* {@link java.time.chrono.Chronology#getId() chronlogy ID} and {@link Chronology#getCalendarType() calendar type}. </p>
|
||||
*
|
||||
* <h3>Specification for implementors</h3>
|
||||
* This abstract class must be implemented with care to ensure other classes operate correctly.
|
||||
* All implementations that can be instantiated must be final, immutable and thread-safe.
|
||||
* Subclasses should be Serializable wherever possible.
|
||||
*
|
||||
* @param <C> the chronology of this date
|
||||
* @param <D> the ChronoLocalDate of this date-time
|
||||
* @since 1.8
|
||||
*/
|
||||
abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
implements ChronoLocalDate<C>, Temporal, TemporalAdjuster, Serializable {
|
||||
abstract class ChronoDateImpl<D extends ChronoLocalDate<D>>
|
||||
implements ChronoLocalDate<D>, Temporal, TemporalAdjuster, Serializable {
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
@ -155,7 +155,7 @@ abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoLocalDate<C> plus(long amountToAdd, TemporalUnit unit) {
|
||||
public D plus(long amountToAdd, TemporalUnit unit) {
|
||||
if (unit instanceof ChronoUnit) {
|
||||
ChronoUnit f = (ChronoUnit) unit;
|
||||
switch (f) {
|
||||
@ -188,7 +188,7 @@ abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
* @return a date based on this one with the years added, not null
|
||||
* @throws DateTimeException if the result exceeds the supported date range
|
||||
*/
|
||||
abstract ChronoDateImpl<C> plusYears(long yearsToAdd);
|
||||
abstract D plusYears(long yearsToAdd);
|
||||
|
||||
/**
|
||||
* Returns a copy of this date with the specified period in months added.
|
||||
@ -204,7 +204,7 @@ abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
* @return a date based on this one with the months added, not null
|
||||
* @throws DateTimeException if the result exceeds the supported date range
|
||||
*/
|
||||
abstract ChronoDateImpl<C> plusMonths(long monthsToAdd);
|
||||
abstract D plusMonths(long monthsToAdd);
|
||||
|
||||
/**
|
||||
* Returns a copy of this date with the specified period in weeks added.
|
||||
@ -221,7 +221,7 @@ abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
* @return a date based on this one with the weeks added, not null
|
||||
* @throws DateTimeException if the result exceeds the supported date range
|
||||
*/
|
||||
ChronoDateImpl<C> plusWeeks(long weeksToAdd) {
|
||||
D plusWeeks(long weeksToAdd) {
|
||||
return plusDays(Math.multiplyExact(weeksToAdd, 7));
|
||||
}
|
||||
|
||||
@ -236,7 +236,7 @@ abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
* @return a date based on this one with the days added, not null
|
||||
* @throws DateTimeException if the result exceeds the supported date range
|
||||
*/
|
||||
abstract ChronoDateImpl<C> plusDays(long daysToAdd);
|
||||
abstract D plusDays(long daysToAdd);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@ -255,8 +255,8 @@ abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
* @return a date based on this one with the years subtracted, not null
|
||||
* @throws DateTimeException if the result exceeds the supported date range
|
||||
*/
|
||||
ChronoDateImpl<C> minusYears(long yearsToSubtract) {
|
||||
return (yearsToSubtract == Long.MIN_VALUE ? plusYears(Long.MAX_VALUE).plusYears(1) : plusYears(-yearsToSubtract));
|
||||
D minusYears(long yearsToSubtract) {
|
||||
return (yearsToSubtract == Long.MIN_VALUE ? ((ChronoDateImpl<D>)plusYears(Long.MAX_VALUE)).plusYears(1) : plusYears(-yearsToSubtract));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -275,8 +275,8 @@ abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
* @return a date based on this one with the months subtracted, not null
|
||||
* @throws DateTimeException if the result exceeds the supported date range
|
||||
*/
|
||||
ChronoDateImpl<C> minusMonths(long monthsToSubtract) {
|
||||
return (monthsToSubtract == Long.MIN_VALUE ? plusMonths(Long.MAX_VALUE).plusMonths(1) : plusMonths(-monthsToSubtract));
|
||||
D minusMonths(long monthsToSubtract) {
|
||||
return (monthsToSubtract == Long.MIN_VALUE ? ((ChronoDateImpl<D>)plusMonths(Long.MAX_VALUE)).plusMonths(1) : plusMonths(-monthsToSubtract));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -294,8 +294,8 @@ abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
* @return a date based on this one with the weeks subtracted, not null
|
||||
* @throws DateTimeException if the result exceeds the supported date range
|
||||
*/
|
||||
ChronoDateImpl<C> minusWeeks(long weeksToSubtract) {
|
||||
return (weeksToSubtract == Long.MIN_VALUE ? plusWeeks(Long.MAX_VALUE).plusWeeks(1) : plusWeeks(-weeksToSubtract));
|
||||
D minusWeeks(long weeksToSubtract) {
|
||||
return (weeksToSubtract == Long.MIN_VALUE ? ((ChronoDateImpl<D>)plusWeeks(Long.MAX_VALUE)).plusWeeks(1) : plusWeeks(-weeksToSubtract));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -311,13 +311,8 @@ abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
* @return a date based on this one with the days subtracted, not null
|
||||
* @throws DateTimeException if the result exceeds the supported date range
|
||||
*/
|
||||
ChronoDateImpl<C> minusDays(long daysToSubtract) {
|
||||
return (daysToSubtract == Long.MIN_VALUE ? plusDays(Long.MAX_VALUE).plusDays(1) : plusDays(-daysToSubtract));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ChronoLocalDateTime<C> atTime(LocalTime localTime) {
|
||||
return Chrono.dateTime(this, localTime);
|
||||
D minusDays(long daysToSubtract) {
|
||||
return (daysToSubtract == Long.MIN_VALUE ? ((ChronoDateImpl<D>)plusDays(Long.MAX_VALUE)).plusDays(1) : plusDays(-daysToSubtract));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -332,13 +327,13 @@ abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
throw new DateTimeException("Unable to calculate period between objects of two different types");
|
||||
}
|
||||
ChronoLocalDate<?> end = (ChronoLocalDate<?>) endDateTime;
|
||||
if (getChrono().equals(end.getChrono()) == false) {
|
||||
if (getChronology().equals(end.getChronology()) == false) {
|
||||
throw new DateTimeException("Unable to calculate period between two different chronologies");
|
||||
}
|
||||
if (unit instanceof ChronoUnit) {
|
||||
return LocalDate.from(this).periodUntil(end, unit); // TODO: this is wrong
|
||||
}
|
||||
return unit.between(this, endDateTime).getAmount();
|
||||
return unit.between(this, endDateTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -355,7 +350,7 @@ abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
@Override
|
||||
public int hashCode() {
|
||||
long epDay = toEpochDay();
|
||||
return getChrono().hashCode() ^ ((int) (epDay ^ (epDay >>> 32)));
|
||||
return getChronology().hashCode() ^ ((int) (epDay ^ (epDay >>> 32)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -365,7 +360,7 @@ abstract class ChronoDateImpl<C extends Chrono<C>>
|
||||
long moy = getLong(MONTH_OF_YEAR);
|
||||
long dom = getLong(DAY_OF_MONTH);
|
||||
StringBuilder buf = new StringBuilder(30);
|
||||
buf.append(getChrono().toString())
|
||||
buf.append(getChronology().toString())
|
||||
.append(" ")
|
||||
.append(getEra())
|
||||
.append(" ")
|
||||
@ -59,7 +59,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.EPOCH_DAY;
|
||||
import static java.time.temporal.ChronoField.ERA;
|
||||
@ -69,7 +69,18 @@ import static java.time.temporal.ChronoUnit.DAYS;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Period;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -81,7 +92,7 @@ import java.util.Objects;
|
||||
* as {@link LocalDate}, not this interface.</b>
|
||||
* <p>
|
||||
* A {@code ChronoLocalDate} is the abstract representation of a date where the
|
||||
* {@code Chrono chronology}, or calendar system, is pluggable.
|
||||
* {@code Chronology chronology}, or calendar system, is pluggable.
|
||||
* The date is defined in terms of fields expressed by {@link TemporalField},
|
||||
* where most common implementations are defined in {@link ChronoField}.
|
||||
* The chronology defines how the calendar system operates and the meaning of
|
||||
@ -93,7 +104,7 @@ import java.util.Objects;
|
||||
* calendar systems. The rationale for this is explored in the following documentation.
|
||||
* <p>
|
||||
* The primary use case where this interface should be used is where the generic
|
||||
* type parameter {@code <C>} is fully defined as a specific chronology.
|
||||
* type parameter {@code <D>} is fully defined as a specific chronology.
|
||||
* In that case, the assumptions of that chronology are known at development
|
||||
* time and specified in the code.
|
||||
* <p>
|
||||
@ -229,12 +240,12 @@ import java.util.Objects;
|
||||
* Subclasses should be Serializable wherever possible.
|
||||
* <p>
|
||||
* Additional calendar systems may be added to the system.
|
||||
* See {@link Chrono} for more details.
|
||||
* See {@link Chronology} for more details.
|
||||
*
|
||||
* @param <C> the chronology of this date
|
||||
* @param <D> the concrete type for the date
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
public interface ChronoLocalDate<D extends ChronoLocalDate<D>>
|
||||
extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDate<?>> {
|
||||
|
||||
/**
|
||||
@ -262,12 +273,12 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
/**
|
||||
* Gets the chronology of this date.
|
||||
* <p>
|
||||
* The {@code Chrono} represents the calendar system in use.
|
||||
* The {@code Chronology} represents the calendar system in use.
|
||||
* The era and other fields in {@link ChronoField} are defined by the chronology.
|
||||
*
|
||||
* @return the chronology, not null
|
||||
*/
|
||||
C getChrono();
|
||||
Chronology getChronology();
|
||||
|
||||
/**
|
||||
* Gets the era, as defined by the chronology.
|
||||
@ -275,17 +286,17 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
* The era is, conceptually, the largest division of the time-line.
|
||||
* Most calendar systems have a single epoch dividing the time-line into two eras.
|
||||
* However, some have multiple eras, such as one for the reign of each leader.
|
||||
* The exact meaning is determined by the {@code Chrono}.
|
||||
* The exact meaning is determined by the {@code Chronology}.
|
||||
* <p>
|
||||
* All correctly implemented {@code Era} classes are singletons, thus it
|
||||
* is valid code to write {@code date.getEra() == SomeChrono.ERA_NAME)}.
|
||||
* <p>
|
||||
* This default implementation uses {@link Chrono#eraOf(int)}.
|
||||
* This default implementation uses {@link Chronology#eraOf(int)}.
|
||||
*
|
||||
* @return the chronology specific era constant applicable at this date, not null
|
||||
*/
|
||||
public default Era<C> getEra() {
|
||||
return getChrono().eraOf(get(ERA));
|
||||
public default Era getEra() {
|
||||
return getChronology().eraOf(get(ERA));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -295,12 +306,12 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
* The exact meaning is determined by the chronology with the constraint that
|
||||
* a leap-year must imply a year-length longer than a non leap-year.
|
||||
* <p>
|
||||
* This default implementation uses {@link Chrono#isLeapYear(long)}.
|
||||
* This default implementation uses {@link Chronology#isLeapYear(long)}.
|
||||
*
|
||||
* @return true if this date is in a leap year, false otherwise
|
||||
*/
|
||||
public default boolean isLeapYear() {
|
||||
return getChrono().isLeapYear(getLong(YEAR));
|
||||
return getChronology().isLeapYear(getLong(YEAR));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -330,7 +341,7 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
if (field instanceof ChronoField) {
|
||||
return ((ChronoField) field).isDateField();
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -341,8 +352,8 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoLocalDate<C> with(TemporalAdjuster adjuster) {
|
||||
return getChrono().ensureChronoLocalDate(Temporal.super.with(adjuster));
|
||||
public default D with(TemporalAdjuster adjuster) {
|
||||
return (D) getChronology().ensureChronoLocalDate(Temporal.super.with(adjuster));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -351,11 +362,11 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoLocalDate<C> with(TemporalField field, long newValue) {
|
||||
public default D with(TemporalField field, long newValue) {
|
||||
if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return getChrono().ensureChronoLocalDate(field.doWith(this, newValue));
|
||||
return (D) getChronology().ensureChronoLocalDate(field.adjustInto(this, newValue));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -364,8 +375,8 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoLocalDate<C> plus(TemporalAdder adder) {
|
||||
return getChrono().ensureChronoLocalDate(Temporal.super.plus(adder));
|
||||
public default D plus(TemporalAmount amount) {
|
||||
return (D) getChronology().ensureChronoLocalDate(Temporal.super.plus(amount));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -374,11 +385,11 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoLocalDate<C> plus(long amountToAdd, TemporalUnit unit) {
|
||||
public default D plus(long amountToAdd, TemporalUnit unit) {
|
||||
if (unit instanceof ChronoUnit) {
|
||||
throw new DateTimeException("Unsupported unit: " + unit.getName());
|
||||
}
|
||||
return getChrono().ensureChronoLocalDate(unit.doPlus(this, amountToAdd));
|
||||
return (D) getChronology().ensureChronoLocalDate(unit.addTo(this, amountToAdd));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -387,8 +398,8 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoLocalDate<C> minus(TemporalSubtractor subtractor) {
|
||||
return getChrono().ensureChronoLocalDate(Temporal.super.minus(subtractor));
|
||||
public default D minus(TemporalAmount amount) {
|
||||
return (D) getChronology().ensureChronoLocalDate(Temporal.super.minus(amount));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -397,8 +408,8 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoLocalDate<C> minus(long amountToSubtract, TemporalUnit unit) {
|
||||
return getChrono().ensureChronoLocalDate(Temporal.super.minus(amountToSubtract, unit));
|
||||
public default D minus(long amountToSubtract, TemporalUnit unit) {
|
||||
return (D) getChronology().ensureChronoLocalDate(Temporal.super.minus(amountToSubtract, unit));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -423,16 +434,17 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public default <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.chrono()) {
|
||||
return (R) getChrono();
|
||||
}
|
||||
if (query == Queries.precision()) {
|
||||
if (query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
|
||||
return null;
|
||||
} else if (query == Queries.localTime()) {
|
||||
return null;
|
||||
} else if (query == Queries.chronology()) {
|
||||
return (R) getChronology();
|
||||
} else if (query == Queries.precision()) {
|
||||
return (R) DAYS;
|
||||
}
|
||||
// inline TemporalAccessor.super.query(query) as an optimization
|
||||
if (query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
|
||||
return null;
|
||||
}
|
||||
// non-JDK classes are not permitted to make this optimization
|
||||
return query.queryFrom(this);
|
||||
}
|
||||
|
||||
@ -479,14 +491,15 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
* For example, the period in days between two dates can be calculated
|
||||
* using {@code startDate.periodUntil(endDate, DAYS)}.
|
||||
* <p>
|
||||
* This method operates in association with {@link TemporalUnit#between}.
|
||||
* The result of this method is a {@code long} representing the amount of
|
||||
* the specified unit. By contrast, the result of {@code between} is an
|
||||
* object that can be used directly in addition/subtraction:
|
||||
* There are two equivalent ways of using this method.
|
||||
* The first is to invoke this method.
|
||||
* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
|
||||
* <pre>
|
||||
* long period = start.periodUntil(end, MONTHS); // this method
|
||||
* dateTime.plus(MONTHS.between(start, end)); // use in plus/minus
|
||||
* // these two lines are equivalent
|
||||
* amount = start.periodUntil(end, MONTHS);
|
||||
* amount = MONTHS.between(start, end);
|
||||
* </pre>
|
||||
* The choice should be made based on which makes the code more readable.
|
||||
* <p>
|
||||
* The calculation is implemented in this method for {@link ChronoUnit}.
|
||||
* The units {@code DAYS}, {@code WEEKS}, {@code MONTHS}, {@code YEARS},
|
||||
@ -511,22 +524,40 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
@Override // override for Javadoc
|
||||
public abstract long periodUntil(Temporal endDate, TemporalUnit unit);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a date-time formed from this date at the specified time.
|
||||
* Calculates the period between this date and another date as a {@code Period}.
|
||||
* <p>
|
||||
* This merges the two objects - {@code this} and the specified time -
|
||||
* to form an instance of {@code ChronoLocalDateTime}.
|
||||
* This calculates the period between two dates in terms of years, months and days.
|
||||
* The start and end points are {@code this} and the specified date.
|
||||
* The result will be negative if the end is before the start.
|
||||
* <p>
|
||||
* The calculation is performed using the the chronology of this date.
|
||||
* If necessary, the input date will be converted to match.
|
||||
* <p>
|
||||
* The result of this method can be a negative period if the end is before the start.
|
||||
* The negative sign will be the same in each of year, month and day.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param endDate the end date, exclusive, which may be in any chronology, not null
|
||||
* @return the period between this date and the end date, not null
|
||||
* @throws DateTimeException if the period cannot be calculated
|
||||
* @throws ArithmeticException if numeric overflow occurs
|
||||
*/
|
||||
public abstract Period periodUntil(ChronoLocalDate<?> endDate);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Combines this date with a time to create a {@code ChronoLocalDateTime}.
|
||||
* <p>
|
||||
* This default implementation creates the date-time.
|
||||
* This returns a {@code ChronoLocalDateTime} formed from this date at the specified time.
|
||||
* All possible combinations of date and time are valid.
|
||||
*
|
||||
* @param localTime the local time to use, not null
|
||||
* @return the local date-time formed from this date and the specified time, not null
|
||||
*/
|
||||
public default ChronoLocalDateTime<C> atTime(LocalTime localTime) {
|
||||
return Chrono.dateTime(this, localTime);
|
||||
public default ChronoLocalDateTime<D> atTime(LocalTime localTime) {
|
||||
return (ChronoLocalDateTime<D>)ChronoLocalDateTimeImpl.of(this, localTime);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -578,7 +609,7 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
public default int compareTo(ChronoLocalDate<?> other) {
|
||||
int cmp = Long.compare(toEpochDay(), other.toEpochDay());
|
||||
if (cmp == 0) {
|
||||
cmp = getChrono().compareTo(other.getChrono());
|
||||
cmp = getChronology().compareTo(other.getChronology());
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
@ -676,7 +707,7 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
* <p>
|
||||
* The default implementation must behave as follows:
|
||||
* <pre>
|
||||
* return formatter.print(this);
|
||||
* return formatter.format(this);
|
||||
* </pre>
|
||||
*
|
||||
* @param formatter the formatter to use, not null
|
||||
@ -685,7 +716,7 @@ public interface ChronoLocalDate<C extends Chrono<C>>
|
||||
*/
|
||||
public default String toString(DateTimeFormatter formatter) {
|
||||
Objects.requireNonNull(formatter, "formatter");
|
||||
return formatter.print(this);
|
||||
return formatter.format(this);
|
||||
}
|
||||
|
||||
}
|
||||
@ -59,7 +59,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.EPOCH_DAY;
|
||||
import static java.time.temporal.ChronoField.NANO_OF_DAY;
|
||||
@ -72,6 +72,15 @@ import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.zone.ZoneRules;
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
@ -84,7 +93,7 @@ import java.util.Objects;
|
||||
* as {@link LocalDateTime}, not this interface.</b>
|
||||
* <p>
|
||||
* A {@code ChronoLocalDateTime} is the abstract representation of a local date-time
|
||||
* where the {@code Chrono chronology}, or calendar system, is pluggable.
|
||||
* where the {@code Chronology chronology}, or calendar system, is pluggable.
|
||||
* The date-time is defined in terms of fields expressed by {@link TemporalField},
|
||||
* where most common implementations are defined in {@link ChronoField}.
|
||||
* The chronology defines how the calendar system operates and the meaning of
|
||||
@ -103,10 +112,10 @@ import java.util.Objects;
|
||||
* All implementations that can be instantiated must be final, immutable and thread-safe.
|
||||
* Subclasses should be Serializable wherever possible.
|
||||
*
|
||||
* @param <C> the chronology of this date-time
|
||||
* @param <D> the concrete type for the date of this date-time
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
public interface ChronoLocalDateTime<D extends ChronoLocalDate<D>>
|
||||
extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDateTime<?>> {
|
||||
|
||||
/**
|
||||
@ -125,9 +134,9 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
new Comparator<ChronoLocalDateTime<?>>() {
|
||||
@Override
|
||||
public int compare(ChronoLocalDateTime<?> datetime1, ChronoLocalDateTime<?> datetime2) {
|
||||
int cmp = Long.compare(datetime1.getDate().toEpochDay(), datetime2.getDate().toEpochDay());
|
||||
int cmp = Long.compare(datetime1.toLocalDate().toEpochDay(), datetime2.toLocalDate().toEpochDay());
|
||||
if (cmp == 0) {
|
||||
cmp = Long.compare(datetime1.getTime().toNanoOfDay(), datetime2.getTime().toNanoOfDay());
|
||||
cmp = Long.compare(datetime1.toLocalTime().toNanoOfDay(), datetime2.toLocalTime().toNanoOfDay());
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
@ -141,7 +150,7 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
*
|
||||
* @return the date part of this date-time, not null
|
||||
*/
|
||||
ChronoLocalDate<C> getDate() ;
|
||||
D toLocalDate() ;
|
||||
|
||||
/**
|
||||
* Gets the local time part of this date-time.
|
||||
@ -151,8 +160,10 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
*
|
||||
* @return the time part of this date-time, not null
|
||||
*/
|
||||
LocalTime getTime();
|
||||
LocalTime toLocalTime();
|
||||
|
||||
@Override // Override to provide javadoc
|
||||
public boolean isSupported(TemporalField field);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// override for covariant return type
|
||||
@ -162,8 +173,8 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoLocalDateTime<C> with(TemporalAdjuster adjuster) {
|
||||
return getDate().getChrono().ensureChronoLocalDateTime(Temporal.super.with(adjuster));
|
||||
public default ChronoLocalDateTime<D> with(TemporalAdjuster adjuster) {
|
||||
return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.with(adjuster)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,7 +183,7 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
ChronoLocalDateTime<C> with(TemporalField field, long newValue);
|
||||
ChronoLocalDateTime<D> with(TemporalField field, long newValue);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@ -180,8 +191,8 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoLocalDateTime<C> plus(TemporalAdder adder) {
|
||||
return getDate().getChrono().ensureChronoLocalDateTime(Temporal.super.plus(adder));
|
||||
public default ChronoLocalDateTime<D> plus(TemporalAmount amount) {
|
||||
return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.plus(amount)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -190,7 +201,7 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
ChronoLocalDateTime<C> plus(long amountToAdd, TemporalUnit unit);
|
||||
ChronoLocalDateTime<D> plus(long amountToAdd, TemporalUnit unit);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@ -198,8 +209,8 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoLocalDateTime<C> minus(TemporalSubtractor subtractor) {
|
||||
return getDate().getChrono().ensureChronoLocalDateTime(Temporal.super.minus(subtractor));
|
||||
public default ChronoLocalDateTime<D> minus(TemporalAmount amount) {
|
||||
return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.minus(amount)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -208,8 +219,8 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoLocalDateTime<C> minus(long amountToSubtract, TemporalUnit unit) {
|
||||
return getDate().getChrono().ensureChronoLocalDateTime(Temporal.super.minus(amountToSubtract, unit));
|
||||
public default ChronoLocalDateTime<D> minus(long amountToSubtract, TemporalUnit unit) {
|
||||
return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.minus(amountToSubtract, unit)));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -234,16 +245,17 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public default <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.chrono()) {
|
||||
return (R) getDate().getChrono();
|
||||
}
|
||||
if (query == Queries.precision()) {
|
||||
if (query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
|
||||
return null;
|
||||
} else if (query == Queries.localTime()) {
|
||||
return (R) toLocalTime();
|
||||
} else if (query == Queries.chronology()) {
|
||||
return (R) toLocalDate().getChronology();
|
||||
} else if (query == Queries.precision()) {
|
||||
return (R) NANOS;
|
||||
}
|
||||
// inline TemporalAccessor.super.query(query) as an optimization
|
||||
if (query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
|
||||
return null;
|
||||
}
|
||||
// non-JDK classes are not permitted to make this optimization
|
||||
return query.queryFrom(this);
|
||||
}
|
||||
|
||||
@ -275,15 +287,16 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
@Override
|
||||
public default Temporal adjustInto(Temporal temporal) {
|
||||
return temporal
|
||||
.with(EPOCH_DAY, getDate().toEpochDay())
|
||||
.with(NANO_OF_DAY, getTime().toNanoOfDay());
|
||||
.with(EPOCH_DAY, toLocalDate().toEpochDay())
|
||||
.with(NANO_OF_DAY, toLocalTime().toNanoOfDay());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a zoned date-time formed from this date-time and the specified time-zone.
|
||||
* Combines this time with a time-zone to create a {@code ChronoZonedDateTime}.
|
||||
* <p>
|
||||
* This creates a zoned date-time matching the input date-time as closely as possible.
|
||||
* This returns a {@code ChronoZonedDateTime} formed from this date-time at the
|
||||
* specified time-zone. The result will match this date-time as closely as possible.
|
||||
* Time-zone rules, such as daylight savings, mean that not every local date-time
|
||||
* is valid for the specified zone, thus the local date-time may be adjusted.
|
||||
* <p>
|
||||
@ -302,13 +315,11 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
* <p>
|
||||
* To obtain the later offset during an overlap, call
|
||||
* {@link ChronoZonedDateTime#withLaterOffsetAtOverlap()} on the result of this method.
|
||||
* <p>
|
||||
* This instance is immutable and unaffected by this method call.
|
||||
*
|
||||
* @param zone the time-zone to use, not null
|
||||
* @return the zoned date-time formed from this date-time, not null
|
||||
*/
|
||||
ChronoZonedDateTime<C> atZone(ZoneId zone);
|
||||
ChronoZonedDateTime<D> atZone(ZoneId zone);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@ -324,7 +335,7 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
* @return an {@code Instant} representing the same instant, not null
|
||||
*/
|
||||
public default Instant toInstant(ZoneOffset offset) {
|
||||
return Instant.ofEpochSecond(toEpochSecond(offset), getTime().getNano());
|
||||
return Instant.ofEpochSecond(toEpochSecond(offset), toLocalTime().getNano());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -343,8 +354,8 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
*/
|
||||
public default long toEpochSecond(ZoneOffset offset) {
|
||||
Objects.requireNonNull(offset, "offset");
|
||||
long epochDay = getDate().toEpochDay();
|
||||
long secs = epochDay * 86400 + getTime().toSecondOfDay();
|
||||
long epochDay = toLocalDate().toEpochDay();
|
||||
long secs = epochDay * 86400 + toLocalTime().toSecondOfDay();
|
||||
secs -= offset.getTotalSeconds();
|
||||
return secs;
|
||||
}
|
||||
@ -378,11 +389,11 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
*/
|
||||
@Override
|
||||
public default int compareTo(ChronoLocalDateTime<?> other) {
|
||||
int cmp = getDate().compareTo(other.getDate());
|
||||
int cmp = toLocalDate().compareTo(other.toLocalDate());
|
||||
if (cmp == 0) {
|
||||
cmp = getTime().compareTo(other.getTime());
|
||||
cmp = toLocalTime().compareTo(other.toLocalTime());
|
||||
if (cmp == 0) {
|
||||
cmp = getDate().getChrono().compareTo(other.getDate().getChrono());
|
||||
cmp = toLocalDate().getChronology().compareTo(other.toLocalDate().getChronology());
|
||||
}
|
||||
}
|
||||
return cmp;
|
||||
@ -403,10 +414,10 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
* @return true if this is after the specified date-time
|
||||
*/
|
||||
public default boolean isAfter(ChronoLocalDateTime<?> other) {
|
||||
long thisEpDay = this.getDate().toEpochDay();
|
||||
long otherEpDay = other.getDate().toEpochDay();
|
||||
long thisEpDay = this.toLocalDate().toEpochDay();
|
||||
long otherEpDay = other.toLocalDate().toEpochDay();
|
||||
return thisEpDay > otherEpDay ||
|
||||
(thisEpDay == otherEpDay && this.getTime().toNanoOfDay() > other.getTime().toNanoOfDay());
|
||||
(thisEpDay == otherEpDay && this.toLocalTime().toNanoOfDay() > other.toLocalTime().toNanoOfDay());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -424,10 +435,10 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
* @return true if this is before the specified date-time
|
||||
*/
|
||||
public default boolean isBefore(ChronoLocalDateTime<?> other) {
|
||||
long thisEpDay = this.getDate().toEpochDay();
|
||||
long otherEpDay = other.getDate().toEpochDay();
|
||||
long thisEpDay = this.toLocalDate().toEpochDay();
|
||||
long otherEpDay = other.toLocalDate().toEpochDay();
|
||||
return thisEpDay < otherEpDay ||
|
||||
(thisEpDay == otherEpDay && this.getTime().toNanoOfDay() < other.getTime().toNanoOfDay());
|
||||
(thisEpDay == otherEpDay && this.toLocalTime().toNanoOfDay() < other.toLocalTime().toNanoOfDay());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -446,8 +457,8 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
*/
|
||||
public default boolean isEqual(ChronoLocalDateTime<?> other) {
|
||||
// Do the time check first, it is cheaper than computing EPOCH day.
|
||||
return this.getTime().toNanoOfDay() == other.getTime().toNanoOfDay() &&
|
||||
this.getDate().toEpochDay() == other.getDate().toEpochDay();
|
||||
return this.toLocalTime().toNanoOfDay() == other.toLocalTime().toNanoOfDay() &&
|
||||
this.toLocalDate().toEpochDay() == other.toLocalDate().toEpochDay();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -485,7 +496,7 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
* <p>
|
||||
* The default implementation must behave as follows:
|
||||
* <pre>
|
||||
* return formatter.print(this);
|
||||
* return formatter.format(this);
|
||||
* </pre>
|
||||
*
|
||||
* @param formatter the formatter to use, not null
|
||||
@ -494,6 +505,6 @@ public interface ChronoLocalDateTime<C extends Chrono<C>>
|
||||
*/
|
||||
public default String toString(DateTimeFormatter formatter) {
|
||||
Objects.requireNonNull(formatter, "formatter");
|
||||
return formatter.print(this);
|
||||
return formatter.format(this);
|
||||
}
|
||||
}
|
||||
@ -59,7 +59,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.EPOCH_DAY;
|
||||
|
||||
@ -72,6 +72,13 @@ import java.io.Serializable;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@ -88,11 +95,11 @@ import java.util.Objects;
|
||||
* <h3>Specification for implementors</h3>
|
||||
* This class is immutable and thread-safe.
|
||||
*
|
||||
* @param <C> the chronology of this date
|
||||
* @param <D> the concrete type for the date of this date-time
|
||||
* @since 1.8
|
||||
*/
|
||||
final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
implements ChronoLocalDateTime<C>, Temporal, TemporalAdjuster, Serializable {
|
||||
final class ChronoLocalDateTimeImpl<D extends ChronoLocalDate<D>>
|
||||
implements ChronoLocalDateTime<D>, Temporal, TemporalAdjuster, Serializable {
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
@ -150,7 +157,7 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
/**
|
||||
* The date part.
|
||||
*/
|
||||
private final ChronoLocalDate<C> date;
|
||||
private final D date;
|
||||
/**
|
||||
* The time part.
|
||||
*/
|
||||
@ -164,8 +171,8 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
* @param time the local time, not null
|
||||
* @return the local date-time, not null
|
||||
*/
|
||||
static <R extends Chrono<R>> ChronoLocalDateTimeImpl<R> of(ChronoLocalDate<R> date, LocalTime time) {
|
||||
return new ChronoLocalDateTimeImpl<>(date, time);
|
||||
static ChronoLocalDateTimeImpl<?> of(ChronoLocalDate<?> date, LocalTime time) {
|
||||
return new ChronoLocalDateTimeImpl(date, time);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,7 +181,7 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
* @param date the date part of the date-time, not null
|
||||
* @param time the time part of the date-time, not null
|
||||
*/
|
||||
private ChronoLocalDateTimeImpl(ChronoLocalDate<C> date, LocalTime time) {
|
||||
private ChronoLocalDateTimeImpl(D date, LocalTime time) {
|
||||
Objects.requireNonNull(date, "date");
|
||||
Objects.requireNonNull(time, "time");
|
||||
this.date = date;
|
||||
@ -189,23 +196,23 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
* @param newTime the time of the new date-time, not null
|
||||
* @return the date-time, not null
|
||||
*/
|
||||
private ChronoLocalDateTimeImpl<C> with(Temporal newDate, LocalTime newTime) {
|
||||
private ChronoLocalDateTimeImpl<D> with(Temporal newDate, LocalTime newTime) {
|
||||
if (date == newDate && time == newTime) {
|
||||
return this;
|
||||
}
|
||||
// Validate that the new Temporal is a ChronoLocalDate (and not something else)
|
||||
ChronoLocalDate<C> cd = date.getChrono().ensureChronoLocalDate(newDate);
|
||||
return new ChronoLocalDateTimeImpl<>(cd, newTime);
|
||||
D cd = (D)date.getChronology().ensureChronoLocalDate(newDate);
|
||||
return new ChronoLocalDateTimeImpl<>((D)cd, newTime);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoLocalDate<C> getDate() {
|
||||
public D toLocalDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalTime getTime() {
|
||||
public LocalTime toLocalTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
@ -216,7 +223,7 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
ChronoField f = (ChronoField) field;
|
||||
return f.isDateField() || f.isTimeField();
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -225,7 +232,7 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
ChronoField f = (ChronoField) field;
|
||||
return (f.isTimeField() ? time.range(field) : date.range(field));
|
||||
}
|
||||
return field.doRange(this);
|
||||
return field.rangeRefinedBy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -243,26 +250,26 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
ChronoField f = (ChronoField) field;
|
||||
return (f.isTimeField() ? time.getLong(field) : date.getLong(field));
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public ChronoLocalDateTimeImpl<C> with(TemporalAdjuster adjuster) {
|
||||
public ChronoLocalDateTimeImpl<D> with(TemporalAdjuster adjuster) {
|
||||
if (adjuster instanceof ChronoLocalDate) {
|
||||
// The Chrono is checked in with(date,time)
|
||||
return with((ChronoLocalDate<C>) adjuster, time);
|
||||
// The Chronology is checked in with(date,time)
|
||||
return with((ChronoLocalDate<D>) adjuster, time);
|
||||
} else if (adjuster instanceof LocalTime) {
|
||||
return with(date, (LocalTime) adjuster);
|
||||
} else if (adjuster instanceof ChronoLocalDateTimeImpl) {
|
||||
return date.getChrono().ensureChronoLocalDateTime((ChronoLocalDateTimeImpl<?>) adjuster);
|
||||
return (ChronoLocalDateTimeImpl<D>)(date.getChronology().ensureChronoLocalDateTime((ChronoLocalDateTimeImpl<?>) adjuster));
|
||||
}
|
||||
return date.getChrono().ensureChronoLocalDateTime((ChronoLocalDateTimeImpl<?>) adjuster.adjustInto(this));
|
||||
return (ChronoLocalDateTimeImpl<D>)(date.getChronology().ensureChronoLocalDateTime((ChronoLocalDateTimeImpl<?>) adjuster.adjustInto(this)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDateTimeImpl<C> with(TemporalField field, long newValue) {
|
||||
public ChronoLocalDateTimeImpl<D> with(TemporalField field, long newValue) {
|
||||
if (field instanceof ChronoField) {
|
||||
ChronoField f = (ChronoField) field;
|
||||
if (f.isTimeField()) {
|
||||
@ -271,12 +278,12 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
return with(date.with(field, newValue), time);
|
||||
}
|
||||
}
|
||||
return date.getChrono().ensureChronoLocalDateTime(field.doWith(this, newValue));
|
||||
return (ChronoLocalDateTimeImpl<D>)(date.getChronology().ensureChronoLocalDateTime(field.adjustInto(this, newValue)));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoLocalDateTimeImpl<C> plus(long amountToAdd, TemporalUnit unit) {
|
||||
public ChronoLocalDateTimeImpl<D> plus(long amountToAdd, TemporalUnit unit) {
|
||||
if (unit instanceof ChronoUnit) {
|
||||
ChronoUnit f = (ChronoUnit) unit;
|
||||
switch (f) {
|
||||
@ -290,31 +297,31 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
}
|
||||
return with(date.plus(amountToAdd, unit), time);
|
||||
}
|
||||
return date.getChrono().ensureChronoLocalDateTime(unit.doPlus(this, amountToAdd));
|
||||
return (ChronoLocalDateTimeImpl<D>)(date.getChronology().ensureChronoLocalDateTime(unit.addTo(this, amountToAdd)));
|
||||
}
|
||||
|
||||
private ChronoLocalDateTimeImpl<C> plusDays(long days) {
|
||||
private ChronoLocalDateTimeImpl<D> plusDays(long days) {
|
||||
return with(date.plus(days, ChronoUnit.DAYS), time);
|
||||
}
|
||||
|
||||
private ChronoLocalDateTimeImpl<C> plusHours(long hours) {
|
||||
private ChronoLocalDateTimeImpl<D> plusHours(long hours) {
|
||||
return plusWithOverflow(date, hours, 0, 0, 0);
|
||||
}
|
||||
|
||||
private ChronoLocalDateTimeImpl<C> plusMinutes(long minutes) {
|
||||
private ChronoLocalDateTimeImpl<D> plusMinutes(long minutes) {
|
||||
return plusWithOverflow(date, 0, minutes, 0, 0);
|
||||
}
|
||||
|
||||
ChronoLocalDateTimeImpl<C> plusSeconds(long seconds) {
|
||||
ChronoLocalDateTimeImpl<D> plusSeconds(long seconds) {
|
||||
return plusWithOverflow(date, 0, 0, seconds, 0);
|
||||
}
|
||||
|
||||
private ChronoLocalDateTimeImpl<C> plusNanos(long nanos) {
|
||||
private ChronoLocalDateTimeImpl<D> plusNanos(long nanos) {
|
||||
return plusWithOverflow(date, 0, 0, 0, nanos);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
private ChronoLocalDateTimeImpl<C> plusWithOverflow(ChronoLocalDate<C> newDate, long hours, long minutes, long seconds, long nanos) {
|
||||
private ChronoLocalDateTimeImpl<D> plusWithOverflow(ChronoLocalDate<?> newDate, long hours, long minutes, long seconds, long nanos) {
|
||||
// 9223372036854775808 long, 2147483648 int
|
||||
if ((hours | minutes | seconds | nanos) == 0) {
|
||||
return with(newDate, time);
|
||||
@ -337,7 +344,7 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoZonedDateTime<C> atZone(ZoneId zone) {
|
||||
public ChronoZonedDateTime<D> atZone(ZoneId zone) {
|
||||
return ChronoZonedDateTimeImpl.ofBest(this, zone, null);
|
||||
}
|
||||
|
||||
@ -348,8 +355,8 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
throw new DateTimeException("Unable to calculate period between objects of two different types");
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
ChronoLocalDateTime<C> end = (ChronoLocalDateTime<C>) endDateTime;
|
||||
if (getDate().getChrono().equals(end.getDate().getChrono()) == false) {
|
||||
ChronoLocalDateTime<D> end = (ChronoLocalDateTime<D>) endDateTime;
|
||||
if (toLocalDate().getChronology().equals(end.toLocalDate().getChronology()) == false) {
|
||||
throw new DateTimeException("Unable to calculate period between two different chronologies");
|
||||
}
|
||||
if (unit instanceof ChronoUnit) {
|
||||
@ -365,15 +372,15 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
case HOURS: amount = Math.multiplyExact(amount, HOURS_PER_DAY); break;
|
||||
case HALF_DAYS: amount = Math.multiplyExact(amount, 2); break;
|
||||
}
|
||||
return Math.addExact(amount, time.periodUntil(end.getTime(), unit));
|
||||
return Math.addExact(amount, time.periodUntil(end.toLocalTime(), unit));
|
||||
}
|
||||
ChronoLocalDate<C> endDate = end.getDate();
|
||||
if (end.getTime().isBefore(time)) {
|
||||
endDate = endDate.minus(1, ChronoUnit.DAYS);
|
||||
D endDate = end.toLocalDate();
|
||||
if (end.toLocalTime().isBefore(time)) {
|
||||
endDate = (D)endDate.minus(1, ChronoUnit.DAYS);
|
||||
}
|
||||
return date.periodUntil(endDate, unit);
|
||||
}
|
||||
return unit.between(this, endDateTime).getAmount();
|
||||
return unit.between(this, endDateTime);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -396,7 +403,7 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
}
|
||||
|
||||
static ChronoLocalDateTime<?> readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
ChronoLocalDate<?> date = (ChronoLocalDate<?>) in.readObject();
|
||||
ChronoLocalDate date = (ChronoLocalDate) in.readObject();
|
||||
LocalTime time = (LocalTime) in.readObject();
|
||||
return date.atTime(time);
|
||||
}
|
||||
@ -415,12 +422,12 @@ final class ChronoLocalDateTimeImpl<C extends Chrono<C>>
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getDate().hashCode() ^ getTime().hashCode();
|
||||
return toLocalDate().hashCode() ^ toLocalTime().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getDate().toString() + 'T' + getTime().toString();
|
||||
return toLocalDate().toString() + 'T' + toLocalTime().toString();
|
||||
}
|
||||
|
||||
}
|
||||
@ -59,7 +59,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.INSTANT_SECONDS;
|
||||
import static java.time.temporal.ChronoField.OFFSET_SECONDS;
|
||||
@ -72,6 +72,16 @@ import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Comparator;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -83,7 +93,7 @@ import java.util.Objects;
|
||||
* as {@link ZonedDateTime}, not this interface.</b>
|
||||
* <p>
|
||||
* A {@code ChronoZonedDateTime} is the abstract representation of an offset date-time
|
||||
* where the {@code Chrono chronology}, or calendar system, is pluggable.
|
||||
* where the {@code Chronology chronology}, or calendar system, is pluggable.
|
||||
* The date-time is defined in terms of fields expressed by {@link TemporalField},
|
||||
* where most common implementations are defined in {@link ChronoField}.
|
||||
* The chronology defines how the calendar system operates and the meaning of
|
||||
@ -102,10 +112,10 @@ import java.util.Objects;
|
||||
* All implementations that can be instantiated must be final, immutable and thread-safe.
|
||||
* Subclasses should be Serializable wherever possible.
|
||||
*
|
||||
* @param <C> the chronology of this date-time
|
||||
* @param <D> the concrete type for the date of this date-time
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
public interface ChronoZonedDateTime<D extends ChronoLocalDate<D>>
|
||||
extends Temporal, Comparable<ChronoZonedDateTime<?>> {
|
||||
|
||||
/**
|
||||
@ -125,7 +135,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
public int compare(ChronoZonedDateTime<?> datetime1, ChronoZonedDateTime<?> datetime2) {
|
||||
int cmp = Long.compare(datetime1.toEpochSecond(), datetime2.toEpochSecond());
|
||||
if (cmp == 0) {
|
||||
cmp = Long.compare(datetime1.getTime().toNanoOfDay(), datetime2.getTime().toNanoOfDay());
|
||||
cmp = Long.compare(datetime1.toLocalTime().toNanoOfDay(), datetime2.toLocalTime().toNanoOfDay());
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
@ -137,9 +147,9 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
if (field == INSTANT_SECONDS || field == OFFSET_SECONDS) {
|
||||
return field.range();
|
||||
}
|
||||
return getDateTime().range(field);
|
||||
return toLocalDateTime().range(field);
|
||||
}
|
||||
return field.doRange(this);
|
||||
return field.rangeRefinedBy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -149,7 +159,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
case INSTANT_SECONDS: throw new DateTimeException("Field too large for an int: " + field);
|
||||
case OFFSET_SECONDS: return getOffset().getTotalSeconds();
|
||||
}
|
||||
return getDateTime().get(field);
|
||||
return toLocalDateTime().get(field);
|
||||
}
|
||||
return Temporal.super.get(field);
|
||||
}
|
||||
@ -161,9 +171,9 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
case INSTANT_SECONDS: return toEpochSecond();
|
||||
case OFFSET_SECONDS: return getOffset().getTotalSeconds();
|
||||
}
|
||||
return getDateTime().getLong(field);
|
||||
return toLocalDateTime().getLong(field);
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,8 +184,8 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
*
|
||||
* @return the date part of this date-time, not null
|
||||
*/
|
||||
public default ChronoLocalDate<C> getDate() {
|
||||
return getDateTime().getDate();
|
||||
public default D toLocalDate() {
|
||||
return toLocalDateTime().toLocalDate();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -186,8 +196,8 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
*
|
||||
* @return the time part of this date-time, not null
|
||||
*/
|
||||
public default LocalTime getTime() {
|
||||
return getDateTime().getTime();
|
||||
public default LocalTime toLocalTime() {
|
||||
return toLocalDateTime().toLocalTime();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,7 +208,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
*
|
||||
* @return the local date-time part of this date-time, not null
|
||||
*/
|
||||
ChronoLocalDateTime<C> getDateTime();
|
||||
ChronoLocalDateTime<D> toLocalDateTime();
|
||||
|
||||
/**
|
||||
* Gets the zone offset, such as '+01:00'.
|
||||
@ -237,7 +247,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
* @throws DateTimeException if no rules can be found for the zone
|
||||
* @throws DateTimeException if no rules are valid for this date-time
|
||||
*/
|
||||
ChronoZonedDateTime<C> withEarlierOffsetAtOverlap();
|
||||
ChronoZonedDateTime<D> withEarlierOffsetAtOverlap();
|
||||
|
||||
/**
|
||||
* Returns a copy of this date-time changing the zone offset to the
|
||||
@ -257,7 +267,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
* @throws DateTimeException if no rules can be found for the zone
|
||||
* @throws DateTimeException if no rules are valid for this date-time
|
||||
*/
|
||||
ChronoZonedDateTime<C> withLaterOffsetAtOverlap();
|
||||
ChronoZonedDateTime<D> withLaterOffsetAtOverlap();
|
||||
|
||||
/**
|
||||
* Returns a copy of this ZonedDateTime with a different time-zone,
|
||||
@ -274,7 +284,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
* @param zone the time-zone to change to, not null
|
||||
* @return a {@code ChronoZonedDateTime} based on this date-time with the requested zone, not null
|
||||
*/
|
||||
ChronoZonedDateTime<C> withZoneSameLocal(ZoneId zone);
|
||||
ChronoZonedDateTime<D> withZoneSameLocal(ZoneId zone);
|
||||
|
||||
/**
|
||||
* Returns a copy of this date-time with a different time-zone,
|
||||
@ -293,7 +303,10 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
* @return a {@code ChronoZonedDateTime} based on this date-time with the requested zone, not null
|
||||
* @throws DateTimeException if the result exceeds the supported date range
|
||||
*/
|
||||
ChronoZonedDateTime<C> withZoneSameInstant(ZoneId zone);
|
||||
ChronoZonedDateTime<D> withZoneSameInstant(ZoneId zone);
|
||||
|
||||
@Override // Override to provide javadoc
|
||||
public boolean isSupported(TemporalField field);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// override for covariant return type
|
||||
@ -303,8 +316,8 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoZonedDateTime<C> with(TemporalAdjuster adjuster) {
|
||||
return getDate().getChrono().ensureChronoZonedDateTime(Temporal.super.with(adjuster));
|
||||
public default ChronoZonedDateTime<D> with(TemporalAdjuster adjuster) {
|
||||
return (ChronoZonedDateTime<D>)(toLocalDate().getChronology().ensureChronoZonedDateTime(Temporal.super.with(adjuster)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -313,7 +326,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
ChronoZonedDateTime<C> with(TemporalField field, long newValue);
|
||||
ChronoZonedDateTime<D> with(TemporalField field, long newValue);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@ -321,8 +334,8 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoZonedDateTime<C> plus(TemporalAdder adder) {
|
||||
return getDate().getChrono().ensureChronoZonedDateTime(Temporal.super.plus(adder));
|
||||
public default ChronoZonedDateTime<D> plus(TemporalAmount amount) {
|
||||
return (ChronoZonedDateTime<D>)(toLocalDate().getChronology().ensureChronoZonedDateTime(Temporal.super.plus(amount)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -331,7 +344,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
ChronoZonedDateTime<C> plus(long amountToAdd, TemporalUnit unit);
|
||||
ChronoZonedDateTime<D> plus(long amountToAdd, TemporalUnit unit);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@ -339,8 +352,8 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoZonedDateTime<C> minus(TemporalSubtractor subtractor) {
|
||||
return getDate().getChrono().ensureChronoZonedDateTime(Temporal.super.minus(subtractor));
|
||||
public default ChronoZonedDateTime<D> minus(TemporalAmount amount) {
|
||||
return (ChronoZonedDateTime<D>)(toLocalDate().getChronology().ensureChronoZonedDateTime(Temporal.super.minus(amount)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -349,8 +362,8 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public default ChronoZonedDateTime<C> minus(long amountToSubtract, TemporalUnit unit) {
|
||||
return getDate().getChrono().ensureChronoZonedDateTime(Temporal.super.minus(amountToSubtract, unit));
|
||||
public default ChronoZonedDateTime<D> minus(long amountToSubtract, TemporalUnit unit) {
|
||||
return (ChronoZonedDateTime<D>)(toLocalDate().getChronology().ensureChronoZonedDateTime(Temporal.super.minus(amountToSubtract, unit)));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -377,14 +390,17 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
public default <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.zone() || query == Queries.zoneId()) {
|
||||
return (R) getZone();
|
||||
} else if (query == Queries.chrono()) {
|
||||
return (R) getDate().getChrono();
|
||||
} else if (query == Queries.precision()) {
|
||||
return (R) NANOS;
|
||||
} else if (query == Queries.offset()) {
|
||||
return (R) getOffset();
|
||||
} else if (query == Queries.localTime()) {
|
||||
return (R) toLocalTime();
|
||||
} else if (query == Queries.chronology()) {
|
||||
return (R) toLocalDate().getChronology();
|
||||
} else if (query == Queries.precision()) {
|
||||
return (R) NANOS;
|
||||
}
|
||||
// inline TemporalAccessor.super.query(query) as an optimization
|
||||
// non-JDK classes are not permitted to make this optimization
|
||||
return query.queryFrom(this);
|
||||
}
|
||||
|
||||
@ -392,20 +408,22 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
/**
|
||||
* Converts this date-time to an {@code Instant}.
|
||||
* <p>
|
||||
* This combines the {@linkplain #getDateTime() local date-time} and
|
||||
* {@linkplain #getOffset() offset} to form an {@code Instant}.
|
||||
* This returns an {@code Instant} representing the same point on the
|
||||
* time-line as this date-time. The calculation combines the
|
||||
* {@linkplain #toLocalDateTime() local date-time} and
|
||||
* {@linkplain #getOffset() offset}.
|
||||
*
|
||||
* @return an {@code Instant} representing the same instant, not null
|
||||
*/
|
||||
public default Instant toInstant() {
|
||||
return Instant.ofEpochSecond(toEpochSecond(), getTime().getNano());
|
||||
return Instant.ofEpochSecond(toEpochSecond(), toLocalTime().getNano());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this date-time to the number of seconds from the epoch
|
||||
* of 1970-01-01T00:00:00Z.
|
||||
* <p>
|
||||
* This uses the {@linkplain #getDateTime() local date-time} and
|
||||
* This uses the {@linkplain #toLocalDateTime() local date-time} and
|
||||
* {@linkplain #getOffset() offset} to calculate the epoch-second value,
|
||||
* which is the number of elapsed seconds from 1970-01-01T00:00:00Z.
|
||||
* Instants on the time-line after the epoch are positive, earlier are negative.
|
||||
@ -413,8 +431,8 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
* @return the number of seconds from the epoch of 1970-01-01T00:00:00Z
|
||||
*/
|
||||
public default long toEpochSecond() {
|
||||
long epochDay = getDate().toEpochDay();
|
||||
long secs = epochDay * 86400 + getTime().toSecondOfDay();
|
||||
long epochDay = toLocalDate().toEpochDay();
|
||||
long secs = epochDay * 86400 + toLocalTime().toSecondOfDay();
|
||||
secs -= getOffset().getTotalSeconds();
|
||||
return secs;
|
||||
}
|
||||
@ -439,13 +457,13 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
public default int compareTo(ChronoZonedDateTime<?> other) {
|
||||
int cmp = Long.compare(toEpochSecond(), other.toEpochSecond());
|
||||
if (cmp == 0) {
|
||||
cmp = getTime().getNano() - other.getTime().getNano();
|
||||
cmp = toLocalTime().getNano() - other.toLocalTime().getNano();
|
||||
if (cmp == 0) {
|
||||
cmp = getDateTime().compareTo(other.getDateTime());
|
||||
cmp = toLocalDateTime().compareTo(other.toLocalDateTime());
|
||||
if (cmp == 0) {
|
||||
cmp = getZone().getId().compareTo(other.getZone().getId());
|
||||
if (cmp == 0) {
|
||||
cmp = getDate().getChrono().compareTo(other.getDate().getChrono());
|
||||
cmp = toLocalDate().getChronology().compareTo(other.toLocalDate().getChronology());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -470,7 +488,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
long thisEpochSec = toEpochSecond();
|
||||
long otherEpochSec = other.toEpochSecond();
|
||||
return thisEpochSec < otherEpochSec ||
|
||||
(thisEpochSec == otherEpochSec && getTime().getNano() < other.getTime().getNano());
|
||||
(thisEpochSec == otherEpochSec && toLocalTime().getNano() < other.toLocalTime().getNano());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -490,7 +508,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
long thisEpochSec = toEpochSecond();
|
||||
long otherEpochSec = other.toEpochSecond();
|
||||
return thisEpochSec > otherEpochSec ||
|
||||
(thisEpochSec == otherEpochSec && getTime().getNano() > other.getTime().getNano());
|
||||
(thisEpochSec == otherEpochSec && toLocalTime().getNano() > other.toLocalTime().getNano());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -508,7 +526,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
*/
|
||||
public default boolean isEqual(ChronoZonedDateTime<?> other) {
|
||||
return toEpochSecond() == other.toEpochSecond() &&
|
||||
getTime().getNano() == other.getTime().getNano();
|
||||
toLocalTime().getNano() == other.toLocalTime().getNano();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -549,7 +567,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
* <p>
|
||||
* The default implementation must behave as follows:
|
||||
* <pre>
|
||||
* return formatter.print(this);
|
||||
* return formatter.format(this);
|
||||
* </pre>
|
||||
*
|
||||
* @param formatter the formatter to use, not null
|
||||
@ -558,7 +576,7 @@ public interface ChronoZonedDateTime<C extends Chrono<C>>
|
||||
*/
|
||||
public default String toString(DateTimeFormatter formatter) {
|
||||
Objects.requireNonNull(formatter, "formatter");
|
||||
return formatter.print(this);
|
||||
return formatter.format(this);
|
||||
}
|
||||
|
||||
}
|
||||
@ -59,7 +59,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoUnit.SECONDS;
|
||||
|
||||
@ -74,6 +74,11 @@ import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.zone.ZoneOffsetTransition;
|
||||
import java.time.zone.ZoneRules;
|
||||
import java.util.List;
|
||||
@ -93,11 +98,11 @@ import java.util.Objects;
|
||||
* <h3>Specification for implementors</h3>
|
||||
* This class is immutable and thread-safe.
|
||||
*
|
||||
* @param <C> the chronology of this date
|
||||
* @param <D> the concrete type for the date of this date-time
|
||||
* @since 1.8
|
||||
*/
|
||||
final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
implements ChronoZonedDateTime<C>, Serializable {
|
||||
final class ChronoZonedDateTimeImpl<D extends ChronoLocalDate<D>>
|
||||
implements ChronoZonedDateTime<D>, Serializable {
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
@ -107,7 +112,7 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
/**
|
||||
* The local date-time.
|
||||
*/
|
||||
private final ChronoLocalDateTimeImpl<C> dateTime;
|
||||
private final ChronoLocalDateTimeImpl<D> dateTime;
|
||||
/**
|
||||
* The zone offset.
|
||||
*/
|
||||
@ -126,12 +131,12 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
* @param preferredOffset the zone offset, null if no preference
|
||||
* @return the zoned date-time, not null
|
||||
*/
|
||||
static <R extends Chrono<R>> ChronoZonedDateTime<R> ofBest(
|
||||
static <R extends ChronoLocalDate<R>> ChronoZonedDateTime<R> ofBest(
|
||||
ChronoLocalDateTimeImpl<R> localDateTime, ZoneId zone, ZoneOffset preferredOffset) {
|
||||
Objects.requireNonNull(localDateTime, "localDateTime");
|
||||
Objects.requireNonNull(zone, "zone");
|
||||
if (zone instanceof ZoneOffset) {
|
||||
return new ChronoZonedDateTimeImpl<R>(localDateTime, (ZoneOffset) zone, zone);
|
||||
return new ChronoZonedDateTimeImpl<>(localDateTime, (ZoneOffset) zone, zone);
|
||||
}
|
||||
ZoneRules rules = zone.getRules();
|
||||
LocalDateTime isoLDT = LocalDateTime.from(localDateTime);
|
||||
@ -151,7 +156,7 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
}
|
||||
}
|
||||
Objects.requireNonNull(offset, "offset"); // protect against bad ZoneRules
|
||||
return new ChronoZonedDateTimeImpl<R>(localDateTime, offset, zone);
|
||||
return new ChronoZonedDateTimeImpl<>(localDateTime, offset, zone);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -162,13 +167,13 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
* @param zone the zone identifier, not null
|
||||
* @return the zoned date-time, not null
|
||||
*/
|
||||
static <R extends Chrono<R>> ChronoZonedDateTimeImpl<R> ofInstant(Chrono<R> chrono, Instant instant, ZoneId zone) {
|
||||
static ChronoZonedDateTimeImpl<?> ofInstant(Chronology chrono, Instant instant, ZoneId zone) {
|
||||
ZoneRules rules = zone.getRules();
|
||||
ZoneOffset offset = rules.getOffset(instant);
|
||||
Objects.requireNonNull(offset, "offset"); // protect against bad ZoneRules
|
||||
LocalDateTime ldt = LocalDateTime.ofEpochSecond(instant.getEpochSecond(), instant.getNano(), offset);
|
||||
ChronoLocalDateTimeImpl<R> cldt = (ChronoLocalDateTimeImpl<R>) chrono.localDateTime(ldt);
|
||||
return new ChronoZonedDateTimeImpl<R>(cldt, offset, zone);
|
||||
ChronoLocalDateTimeImpl<?> cldt = (ChronoLocalDateTimeImpl<?>) chrono.localDateTime(ldt);
|
||||
return new ChronoZonedDateTimeImpl(cldt, offset, zone);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -178,8 +183,8 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
* @param zone the time-zone to use, validated not null
|
||||
* @return the zoned date-time, validated not null
|
||||
*/
|
||||
private ChronoZonedDateTimeImpl<C> create(Instant instant, ZoneId zone) {
|
||||
return ofInstant(getDate().getChrono(), instant, zone);
|
||||
private ChronoZonedDateTimeImpl<D> create(Instant instant, ZoneId zone) {
|
||||
return (ChronoZonedDateTimeImpl<D>)ofInstant(toLocalDate().getChronology(), instant, zone);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -190,7 +195,7 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
* @param offset the zone offset, not null
|
||||
* @param zone the zone ID, not null
|
||||
*/
|
||||
private ChronoZonedDateTimeImpl(ChronoLocalDateTimeImpl<C> dateTime, ZoneOffset offset, ZoneId zone) {
|
||||
private ChronoZonedDateTimeImpl(ChronoLocalDateTimeImpl<D> dateTime, ZoneOffset offset, ZoneId zone) {
|
||||
this.dateTime = Objects.requireNonNull(dateTime, "dateTime");
|
||||
this.offset = Objects.requireNonNull(offset, "offset");
|
||||
this.zone = Objects.requireNonNull(zone, "zone");
|
||||
@ -202,24 +207,24 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoZonedDateTime<C> withEarlierOffsetAtOverlap() {
|
||||
public ChronoZonedDateTime<D> withEarlierOffsetAtOverlap() {
|
||||
ZoneOffsetTransition trans = getZone().getRules().getTransition(LocalDateTime.from(this));
|
||||
if (trans != null && trans.isOverlap()) {
|
||||
ZoneOffset earlierOffset = trans.getOffsetBefore();
|
||||
if (earlierOffset.equals(offset) == false) {
|
||||
return new ChronoZonedDateTimeImpl<C>(dateTime, earlierOffset, zone);
|
||||
return new ChronoZonedDateTimeImpl<D>(dateTime, earlierOffset, zone);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoZonedDateTime<C> withLaterOffsetAtOverlap() {
|
||||
public ChronoZonedDateTime<D> withLaterOffsetAtOverlap() {
|
||||
ZoneOffsetTransition trans = getZone().getRules().getTransition(LocalDateTime.from(this));
|
||||
if (trans != null) {
|
||||
ZoneOffset offset = trans.getOffsetAfter();
|
||||
if (offset.equals(getOffset()) == false) {
|
||||
return new ChronoZonedDateTimeImpl<C>(dateTime, offset, zone);
|
||||
return new ChronoZonedDateTimeImpl<D>(dateTime, offset, zone);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
@ -227,7 +232,7 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoLocalDateTime<C> getDateTime() {
|
||||
public ChronoLocalDateTime<D> toLocalDateTime() {
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
@ -235,12 +240,12 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
return zone;
|
||||
}
|
||||
|
||||
public ChronoZonedDateTime<C> withZoneSameLocal(ZoneId zone) {
|
||||
public ChronoZonedDateTime<D> withZoneSameLocal(ZoneId zone) {
|
||||
return ofBest(dateTime, zone, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoZonedDateTime<C> withZoneSameInstant(ZoneId zone) {
|
||||
public ChronoZonedDateTime<D> withZoneSameInstant(ZoneId zone) {
|
||||
Objects.requireNonNull(zone, "zone");
|
||||
return this.zone.equals(zone) ? this : create(dateTime.toInstant(offset), zone);
|
||||
}
|
||||
@ -248,12 +253,12 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public boolean isSupported(TemporalField field) {
|
||||
return field instanceof ChronoField || (field != null && field.doIsSupported(this));
|
||||
return field instanceof ChronoField || (field != null && field.isSupportedBy(this));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoZonedDateTime<C> with(TemporalField field, long newValue) {
|
||||
public ChronoZonedDateTime<D> with(TemporalField field, long newValue) {
|
||||
if (field instanceof ChronoField) {
|
||||
ChronoField f = (ChronoField) field;
|
||||
switch (f) {
|
||||
@ -265,16 +270,16 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
}
|
||||
return ofBest(dateTime.with(field, newValue), zone, offset);
|
||||
}
|
||||
return getDate().getChrono().ensureChronoZonedDateTime(field.doWith(this, newValue));
|
||||
return (ChronoZonedDateTime<D>)(toLocalDate().getChronology().ensureChronoZonedDateTime(field.adjustInto(this, newValue)));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoZonedDateTime<C> plus(long amountToAdd, TemporalUnit unit) {
|
||||
public ChronoZonedDateTime<D> plus(long amountToAdd, TemporalUnit unit) {
|
||||
if (unit instanceof ChronoUnit) {
|
||||
return with(dateTime.plus(amountToAdd, unit));
|
||||
}
|
||||
return getDate().getChrono().ensureChronoZonedDateTime(unit.doPlus(this, amountToAdd)); /// TODO: Generics replacement Risk!
|
||||
return (ChronoZonedDateTime<D>)(toLocalDate().getChronology().ensureChronoZonedDateTime(unit.addTo(this, amountToAdd))); /// TODO: Generics replacement Risk!
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -284,15 +289,15 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
throw new DateTimeException("Unable to calculate period between objects of two different types");
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
ChronoZonedDateTime<C> end = (ChronoZonedDateTime<C>) endDateTime;
|
||||
if (getDate().getChrono().equals(end.getDate().getChrono()) == false) {
|
||||
ChronoZonedDateTime<D> end = (ChronoZonedDateTime<D>) endDateTime;
|
||||
if (toLocalDate().getChronology().equals(end.toLocalDate().getChronology()) == false) {
|
||||
throw new DateTimeException("Unable to calculate period between two different chronologies");
|
||||
}
|
||||
if (unit instanceof ChronoUnit) {
|
||||
end = end.withZoneSameInstant(offset);
|
||||
return dateTime.periodUntil(end.getDateTime(), unit);
|
||||
return dateTime.periodUntil(end.toLocalDateTime(), unit);
|
||||
}
|
||||
return unit.between(this, endDateTime).getAmount();
|
||||
return unit.between(this, endDateTime);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -337,12 +342,12 @@ final class ChronoZonedDateTimeImpl<C extends Chrono<C>>
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getDateTime().hashCode() ^ getOffset().hashCode() ^ Integer.rotateLeft(getZone().hashCode(), 3);
|
||||
return toLocalDateTime().hashCode() ^ getOffset().hashCode() ^ Integer.rotateLeft(getZone().hashCode(), 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String str = getDateTime().toString() + getOffset().toString();
|
||||
String str = toLocalDateTime().toString() + getOffset().toString();
|
||||
if (getOffset() != getZone()) {
|
||||
str += '[' + getZone().toString() + ']';
|
||||
}
|
||||
@ -59,7 +59,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time.chrono;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@ -72,12 +72,19 @@ import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.calendar.HijrahChrono;
|
||||
import java.time.calendar.JapaneseChrono;
|
||||
import java.time.calendar.MinguoChrono;
|
||||
import java.time.calendar.ThaiBuddhistChrono;
|
||||
import java.time.chrono.HijrahChronology;
|
||||
import java.time.chrono.JapaneseChronology;
|
||||
import java.time.chrono.MinguoChronology;
|
||||
import java.time.chrono.ThaiBuddhistChronology;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.TextStyle;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -95,30 +102,30 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* <p>
|
||||
* Most other calendar systems also operate on the shared concepts of year, month and day,
|
||||
* linked to the cycles of the Earth around the Sun, and the Moon around the Earth.
|
||||
* These shared concepts are defined by {@link ChronoField} and are availalbe
|
||||
* for use by any {@code Chrono} implementation:
|
||||
* These shared concepts are defined by {@link ChronoField} and are available
|
||||
* for use by any {@code Chronology} implementation:
|
||||
* <pre>
|
||||
* LocalDate isoDate = ...
|
||||
* ChronoLocalDate<ThaiBuddhistChrono> thaiDate = ...
|
||||
* ChronoLocalDate<ThaiBuddhistChronology> thaiDate = ...
|
||||
* int isoYear = isoDate.get(ChronoField.YEAR);
|
||||
* int thaiYear = thaiDate.get(ChronoField.YEAR);
|
||||
* </pre>
|
||||
* As shown, although the date objects are in different calendar systems, represented by different
|
||||
* {@code Chrono} instances, both can be queried using the same constant on {@code ChronoField}.
|
||||
* {@code Chronology} instances, both can be queried using the same constant on {@code ChronoField}.
|
||||
* For a full discussion of the implications of this, see {@link ChronoLocalDate}.
|
||||
* In general, the advice is to use the known ISO-based {@code LocalDate}, rather than
|
||||
* {@code ChronoLocalDate}.
|
||||
* <p>
|
||||
* While a {@code Chrono} object typically uses {@code ChronoField} and is based on
|
||||
* While a {@code Chronology} object typically uses {@code ChronoField} and is based on
|
||||
* an era, year-of-era, month-of-year, day-of-month model of a date, this is not required.
|
||||
* A {@code Chrono} instance may represent a totally different kind of calendar system,
|
||||
* A {@code Chronology} instance may represent a totally different kind of calendar system,
|
||||
* such as the Mayan.
|
||||
* <p>
|
||||
* In practical terms, the {@code Chrono} instance also acts as a factory.
|
||||
* In practical terms, the {@code Chronology} instance also acts as a factory.
|
||||
* The {@link #of(String)} method allows an instance to be looked up by identifier,
|
||||
* while the {@link #ofLocale(Locale)} method allows lookup by locale.
|
||||
* <p>
|
||||
* The {@code Chrono} instance provides a set of methods to create {@code ChronoLocalDate} instances.
|
||||
* The {@code Chronology} instance provides a set of methods to create {@code ChronoLocalDate} instances.
|
||||
* The date classes are used to manipulate specific dates.
|
||||
* <p><ul>
|
||||
* <li> {@link #dateNow() dateNow()}
|
||||
@ -131,16 +138,16 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* <li> {@link #date(TemporalAccessor) date(TemporalAccessor)}
|
||||
* </ul><p>
|
||||
*
|
||||
* <p id="addcalendars">Adding New Calendars</p>
|
||||
* <h3 id="addcalendars">Adding New Calendars</h3>
|
||||
* The set of available chronologies can be extended by applications.
|
||||
* Adding a new calendar system requires the writing of an implementation of
|
||||
* {@code Chrono}, {@code ChronoLocalDate} and {@code Era}.
|
||||
* {@code Chronology}, {@code ChronoLocalDate} and {@code Era}.
|
||||
* The majority of the logic specific to the calendar system will be in
|
||||
* {@code ChronoLocalDate}. The {@code Chrono} subclass acts as a factory.
|
||||
* {@code ChronoLocalDate}. The {@code Chronology} subclass acts as a factory.
|
||||
* <p>
|
||||
* To permit the discovery of additional chronologies, the {@link java.util.ServiceLoader ServiceLoader}
|
||||
* is used. A file must be added to the {@code META-INF/services} directory with the
|
||||
* name 'java.time.temporal.Chrono' listing the implementation classes.
|
||||
* name 'java.time.chrono.Chronology' listing the implementation classes.
|
||||
* See the ServiceLoader for more details on service loading.
|
||||
* For lookup by id or calendarType, the system provided calendars are found
|
||||
* first followed by application provided calendars.
|
||||
@ -155,28 +162,27 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* All implementations that can be instantiated must be final, immutable and thread-safe.
|
||||
* Subclasses should be Serializable wherever possible.
|
||||
*
|
||||
* @param <C> the type of the implementing subclass
|
||||
* @since 1.8
|
||||
*/
|
||||
public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?>> {
|
||||
public abstract class Chronology implements Comparable<Chronology> {
|
||||
|
||||
/**
|
||||
* Map of available calendars by ID.
|
||||
*/
|
||||
private static final ConcurrentHashMap<String, Chrono<?>> CHRONOS_BY_ID = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<String, Chronology> CHRONOS_BY_ID = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* Map of available calendars by calendar type.
|
||||
*/
|
||||
private static final ConcurrentHashMap<String, Chrono<?>> CHRONOS_BY_TYPE = new ConcurrentHashMap<>();
|
||||
private static final ConcurrentHashMap<String, Chronology> CHRONOS_BY_TYPE = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Register a Chrono by ID and type for lookup by {@link #of(java.lang.String)}.
|
||||
* Register a Chronology by ID and type for lookup by {@link #of(java.lang.String)}.
|
||||
* Chronos must not be registered until they are completely constructed.
|
||||
* Specifically, not in the constructor of Chrono.
|
||||
* Specifically, not in the constructor of Chronology.
|
||||
* @param chrono the chronology to register; not null
|
||||
*/
|
||||
private static void registerChrono(Chrono chrono) {
|
||||
Chrono<?> prev = CHRONOS_BY_ID.putIfAbsent(chrono.getId(), chrono);
|
||||
private static void registerChrono(Chronology chrono) {
|
||||
Chronology prev = CHRONOS_BY_ID.putIfAbsent(chrono.getId(), chrono);
|
||||
if (prev == null) {
|
||||
String type = chrono.getCalendarType();
|
||||
if (type != null) {
|
||||
@ -186,17 +192,17 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization of the maps from id and type to Chrono.
|
||||
* Initialization of the maps from id and type to Chronology.
|
||||
* The ServiceLoader is used to find and register any implementations
|
||||
* of {@link javax.time.temporal.Chrono} found in the bootclass loader.
|
||||
* of {@link java.time.chrono.Chronology} found in the bootclass loader.
|
||||
* The built-in chronologies are registered explicitly.
|
||||
* Calendars configured via the Thread's context classloader are local
|
||||
* to that thread and are ignored.
|
||||
* <p>
|
||||
* The initialization is done only once using the registration
|
||||
* of the ISOChrono as the test and the final step.
|
||||
* of the IsoChronology as the test and the final step.
|
||||
* Multiple threads may perform the initialization concurrently.
|
||||
* Only the first registration of each Chrono is retained by the
|
||||
* Only the first registration of each Chronology is retained by the
|
||||
* ConcurrentHashMap.
|
||||
* @return true if the cache was initialized
|
||||
*/
|
||||
@ -204,19 +210,19 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
if (CHRONOS_BY_ID.get("ISO") == null) {
|
||||
// Initialization is incomplete
|
||||
@SuppressWarnings("rawtypes")
|
||||
ServiceLoader<Chrono> loader = ServiceLoader.load(Chrono.class, null);
|
||||
for (Chrono<?> chrono : loader) {
|
||||
ServiceLoader<Chronology> loader = ServiceLoader.load(Chronology.class, null);
|
||||
for (Chronology chrono : loader) {
|
||||
registerChrono(chrono);
|
||||
}
|
||||
|
||||
// Register these calendars; the ServiceLoader configuration is not used
|
||||
registerChrono(HijrahChrono.INSTANCE);
|
||||
registerChrono(JapaneseChrono.INSTANCE);
|
||||
registerChrono(MinguoChrono.INSTANCE);
|
||||
registerChrono(ThaiBuddhistChrono.INSTANCE);
|
||||
registerChrono(HijrahChronology.INSTANCE);
|
||||
registerChrono(JapaneseChronology.INSTANCE);
|
||||
registerChrono(MinguoChronology.INSTANCE);
|
||||
registerChrono(ThaiBuddhistChronology.INSTANCE);
|
||||
|
||||
// finally, register ISOChrono to mark initialization is complete
|
||||
registerChrono(ISOChrono.INSTANCE);
|
||||
// finally, register IsoChronology to mark initialization is complete
|
||||
registerChrono(IsoChronology.INSTANCE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -224,61 +230,89 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code Chrono} from a temporal object.
|
||||
* Obtains an instance of {@code Chronology} from a temporal object.
|
||||
* <p>
|
||||
* A {@code TemporalAccessor} represents some form of date and time information.
|
||||
* This factory converts the arbitrary temporal object to an instance of {@code Chrono}.
|
||||
* If the specified temporal object does not have a chronology, {@link ISOChrono} is returned.
|
||||
* This obtains a chronology based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code Chronology}.
|
||||
* <p>
|
||||
* The conversion will obtain the chronology using {@link Queries#chrono()}.
|
||||
* The conversion will obtain the chronology using {@link Queries#chronology()}.
|
||||
* If the specified temporal object does not have a chronology, {@link IsoChronology} is returned.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used in queries via method reference, {@code Chrono::from}.
|
||||
* allowing it to be used in queries via method reference, {@code Chronology::from}.
|
||||
*
|
||||
* @param temporal the temporal to convert, not null
|
||||
* @return the chronology, not null
|
||||
* @throws DateTimeException if unable to convert to an {@code Chrono}
|
||||
* @throws DateTimeException if unable to convert to an {@code Chronology}
|
||||
*/
|
||||
public static Chrono<?> from(TemporalAccessor temporal) {
|
||||
public static Chronology from(TemporalAccessor temporal) {
|
||||
Objects.requireNonNull(temporal, "temporal");
|
||||
Chrono<?> obj = temporal.query(Queries.chrono());
|
||||
return (obj != null ? obj : ISOChrono.INSTANCE);
|
||||
Chronology obj = temporal.query(Queries.chronology());
|
||||
return (obj != null ? obj : IsoChronology.INSTANCE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code Chrono} from a locale.
|
||||
* Obtains an instance of {@code Chronology} from a locale.
|
||||
* <p>
|
||||
* The locale can be used to identify a calendar.
|
||||
* This uses {@link Locale#getUnicodeLocaleType(String)} to obtain the "ca" key
|
||||
* to identify the calendar system.
|
||||
* This returns a {@code Chronology} based on the specified locale,
|
||||
* typically returning {@code IsoChronology}. Other calendar systems
|
||||
* are only returned if they are explicitly selected within the locale.
|
||||
* <p>
|
||||
* If the locale does not contain calendar system information, the standard
|
||||
* ISO calendar system is used.
|
||||
* The {@link Locale} class provide access to a range of information useful
|
||||
* for localizing an application. This includes the language and region,
|
||||
* such as "en-GB" for English as used in Great Britain.
|
||||
* <p>
|
||||
* The {@code Locale} class also supports an extension mechanism that
|
||||
* can be used to identify a calendar system. The mechanism is a form
|
||||
* of key-value pairs, where the calendar system has the key "ca".
|
||||
* For example, the locale "en-JP-u-ca-japanese" represents the English
|
||||
* language as used in Japan with the Japanese calendar system.
|
||||
* <p>
|
||||
* This method finds the desired calendar system by in a manner equivalent
|
||||
* to passing "ca" to {@link Locale#getUnicodeLocaleType(String)}.
|
||||
* If the "ca" key is not present, then {@code IsoChronology} is returned.
|
||||
* <p>
|
||||
* Note that the behavior of this method differs from the older
|
||||
* {@link java.util.Calendar#getInstance(Locale)} method.
|
||||
* If that method receives a locale of "th_TH" it will return {@code BuddhistCalendar}.
|
||||
* By contrast, this method will return {@code IsoChronology}.
|
||||
* Passing the locale "th-TH-u-ca-buddhist" into either method will
|
||||
* result in the Thai Buddhist calendar system and is therefore the
|
||||
* recommended approach going forward for Thai calendar system localization.
|
||||
* <p>
|
||||
* A similar, but simpler, situation occurs for the Japanese calendar system.
|
||||
* The locale "jp_JP_JP" has previously been used to access the calendar.
|
||||
* However, unlike the Thai locale, "ja_JP_JP" is automatically converted by
|
||||
* {@code Locale} to the modern and recommended form of "ja-JP-u-ca-japanese".
|
||||
* Thus, there is no difference in behavior between this method and
|
||||
* {@code Calendar#getInstance(Locale)}.
|
||||
*
|
||||
* @param locale the locale to use to obtain the calendar system, not null
|
||||
* @return the calendar system associated with the locale, not null
|
||||
* @throws DateTimeException if the locale-specified calendar cannot be found
|
||||
*/
|
||||
public static Chrono<?> ofLocale(Locale locale) {
|
||||
public static Chronology ofLocale(Locale locale) {
|
||||
Objects.requireNonNull(locale, "locale");
|
||||
String type = locale.getUnicodeLocaleType("ca");
|
||||
if (type == null) {
|
||||
return ISOChrono.INSTANCE;
|
||||
} else if ("iso".equals(type) || "iso8601".equals(type)) {
|
||||
return ISOChrono.INSTANCE;
|
||||
} else {
|
||||
Chrono<?> chrono = CHRONOS_BY_TYPE.get(type);
|
||||
if (chrono == null) {
|
||||
throw new DateTimeException("Unknown calendar system: " + type);
|
||||
}
|
||||
return chrono;
|
||||
if (type == null || "iso".equals(type) || "iso8601".equals(type)) {
|
||||
return IsoChronology.INSTANCE;
|
||||
}
|
||||
// Not pre-defined; lookup by the type
|
||||
do {
|
||||
Chronology chrono = CHRONOS_BY_TYPE.get(type);
|
||||
if (chrono != null) {
|
||||
return chrono;
|
||||
}
|
||||
// If not found, do the initialization (once) and repeat the lookup
|
||||
} while (initCache());
|
||||
throw new DateTimeException("Unknown calendar system: " + type);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code Chrono} from a chronology ID or
|
||||
* Obtains an instance of {@code Chronology} from a chronology ID or
|
||||
* calendar system type.
|
||||
* <p>
|
||||
* This returns a chronology based on either the ID or the type.
|
||||
@ -296,21 +330,21 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @return the chronology with the identifier requested, not null
|
||||
* @throws DateTimeException if the chronology cannot be found
|
||||
*/
|
||||
public static Chrono<?> of(String id) {
|
||||
public static Chronology of(String id) {
|
||||
Objects.requireNonNull(id, "id");
|
||||
do {
|
||||
Chrono chrono = of0(id);
|
||||
Chronology chrono = of0(id);
|
||||
if (chrono != null) {
|
||||
return chrono;
|
||||
}
|
||||
// If not found, do the initialization (once) and repeat the lookup
|
||||
} while (initCache());
|
||||
|
||||
// Look for a Chrono using ServiceLoader of the Thread's ContextClassLoader
|
||||
// Look for a Chronology using ServiceLoader of the Thread's ContextClassLoader
|
||||
// Application provided Chronologies must not be cached
|
||||
@SuppressWarnings("rawtypes")
|
||||
ServiceLoader<Chrono> loader = ServiceLoader.load(Chrono.class);
|
||||
for (Chrono<?> chrono : loader) {
|
||||
ServiceLoader<Chronology> loader = ServiceLoader.load(Chronology.class);
|
||||
for (Chronology chrono : loader) {
|
||||
if (id.equals(chrono.getId()) || id.equals(chrono.getCalendarType())) {
|
||||
return chrono;
|
||||
}
|
||||
@ -319,14 +353,14 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code Chrono} from a chronology ID or
|
||||
* Obtains an instance of {@code Chronology} from a chronology ID or
|
||||
* calendar system type.
|
||||
*
|
||||
* @param id the chronology ID or calendar system type, not null
|
||||
* @return the chronology with the identifier requested, or {@code null} if not found
|
||||
*/
|
||||
private static Chrono<?> of0(String id) {
|
||||
Chrono<?> chrono = CHRONOS_BY_ID.get(id);
|
||||
private static Chronology of0(String id) {
|
||||
Chronology chrono = CHRONOS_BY_ID.get(id);
|
||||
if (chrono == null) {
|
||||
chrono = CHRONOS_BY_TYPE.get(id);
|
||||
}
|
||||
@ -336,50 +370,31 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
/**
|
||||
* Returns the available chronologies.
|
||||
* <p>
|
||||
* Each returned {@code Chrono} is available for use in the system.
|
||||
* Each returned {@code Chronology} is available for use in the system.
|
||||
* The set of chronologies includes the system chronologies and
|
||||
* any chronologies provided by the application via ServiceLoader
|
||||
* configuration.
|
||||
*
|
||||
* @return the independent, modifiable set of the available chronology IDs, not null
|
||||
*/
|
||||
public static Set<Chrono<?>> getAvailableChronologies() {
|
||||
public static Set<Chronology> getAvailableChronologies() {
|
||||
initCache(); // force initialization
|
||||
HashSet<Chrono<?>> chronos = new HashSet<>(CHRONOS_BY_ID.values());
|
||||
HashSet<Chronology> chronos = new HashSet(CHRONOS_BY_ID.values());
|
||||
|
||||
/// Add in Chronologies from the ServiceLoader configuration
|
||||
@SuppressWarnings("rawtypes")
|
||||
ServiceLoader<Chrono> loader = ServiceLoader.load(Chrono.class);
|
||||
for (Chrono<?> chrono : loader) {
|
||||
ServiceLoader<Chronology> loader = ServiceLoader.load(Chronology.class);
|
||||
for (Chronology chrono : loader) {
|
||||
chronos.add(chrono);
|
||||
}
|
||||
return chronos;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains a local date-time from the a date and time.
|
||||
* <p>
|
||||
* This combines a {@link ChronoLocalDate}, which provides the {@code Chrono},
|
||||
* with a {@link LocalTime} to produce a {@link ChronoLocalDateTime}.
|
||||
* <p>
|
||||
* This method is intended for chronology implementations.
|
||||
* It uses a standard implementation that is shared for all chronologies.
|
||||
*
|
||||
* @param <R> the chronology of the date
|
||||
* @param date the date, not null
|
||||
* @param time the time, not null
|
||||
* @return the local date-time combining the input date and time, not null
|
||||
*/
|
||||
public static <R extends Chrono<R>> ChronoLocalDateTime<R> dateTime(ChronoLocalDate<R> date, LocalTime time) {
|
||||
return ChronoLocalDateTimeImpl.of(date, time);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Creates an instance.
|
||||
*/
|
||||
protected Chrono() {
|
||||
protected Chronology() {
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -389,13 +404,13 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @param temporal a date-time to cast, not null
|
||||
* @return the date-time checked and cast to {@code ChronoLocalDate}, not null
|
||||
* @throws ClassCastException if the date-time cannot be cast to ChronoLocalDate
|
||||
* or the chronology is not equal this Chrono
|
||||
* or the chronology is not equal this Chronology
|
||||
*/
|
||||
ChronoLocalDate<C> ensureChronoLocalDate(Temporal temporal) {
|
||||
ChronoLocalDate ensureChronoLocalDate(Temporal temporal) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ChronoLocalDate<C> other = (ChronoLocalDate<C>) temporal;
|
||||
if (this.equals(other.getChrono()) == false) {
|
||||
throw new ClassCastException("Chrono mismatch, expected: " + getId() + ", actual: " + other.getChrono().getId());
|
||||
ChronoLocalDate other = (ChronoLocalDate) temporal;
|
||||
if (this.equals(other.getChronology()) == false) {
|
||||
throw new ClassCastException("Chronology mismatch, expected: " + getId() + ", actual: " + other.getChronology().getId());
|
||||
}
|
||||
return other;
|
||||
}
|
||||
@ -406,14 +421,14 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @param temporal a date-time to cast, not null
|
||||
* @return the date-time checked and cast to {@code ChronoLocalDateTime}, not null
|
||||
* @throws ClassCastException if the date-time cannot be cast to ChronoLocalDateTimeImpl
|
||||
* or the chronology is not equal this Chrono
|
||||
* or the chronology is not equal this Chronology
|
||||
*/
|
||||
ChronoLocalDateTimeImpl<C> ensureChronoLocalDateTime(Temporal temporal) {
|
||||
ChronoLocalDateTimeImpl<?> ensureChronoLocalDateTime(Temporal temporal) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ChronoLocalDateTimeImpl<C> other = (ChronoLocalDateTimeImpl<C>) temporal;
|
||||
if (this.equals(other.getDate().getChrono()) == false) {
|
||||
throw new ClassCastException("Chrono mismatch, required: " + getId()
|
||||
+ ", supplied: " + other.getDate().getChrono().getId());
|
||||
ChronoLocalDateTimeImpl<?> other = (ChronoLocalDateTimeImpl<?>) temporal;
|
||||
if (this.equals(other.toLocalDate().getChronology()) == false) {
|
||||
throw new ClassCastException("Chronology mismatch, required: " + getId()
|
||||
+ ", supplied: " + other.toLocalDate().getChronology().getId());
|
||||
}
|
||||
return other;
|
||||
}
|
||||
@ -424,14 +439,14 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @param temporal a date-time to cast, not null
|
||||
* @return the date-time checked and cast to {@code ChronoZonedDateTimeImpl}, not null
|
||||
* @throws ClassCastException if the date-time cannot be cast to ChronoZonedDateTimeImpl
|
||||
* or the chronology is not equal this Chrono
|
||||
* or the chronology is not equal this Chronology
|
||||
*/
|
||||
ChronoZonedDateTimeImpl<C> ensureChronoZonedDateTime(Temporal temporal) {
|
||||
ChronoZonedDateTimeImpl<?> ensureChronoZonedDateTime(Temporal temporal) {
|
||||
@SuppressWarnings("unchecked")
|
||||
ChronoZonedDateTimeImpl<C> other = (ChronoZonedDateTimeImpl<C>) temporal;
|
||||
if (this.equals(other.getDate().getChrono()) == false) {
|
||||
throw new ClassCastException("Chrono mismatch, required: " + getId()
|
||||
+ ", supplied: " + other.getDate().getChrono().getId());
|
||||
ChronoZonedDateTimeImpl<?> other = (ChronoZonedDateTimeImpl<?>) temporal;
|
||||
if (this.equals(other.toLocalDate().getChronology()) == false) {
|
||||
throw new ClassCastException("Chronology mismatch, required: " + getId()
|
||||
+ ", supplied: " + other.toLocalDate().getChronology().getId());
|
||||
}
|
||||
return other;
|
||||
}
|
||||
@ -440,8 +455,8 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
/**
|
||||
* Gets the ID of the chronology.
|
||||
* <p>
|
||||
* The ID uniquely identifies the {@code Chrono}.
|
||||
* It can be used to lookup the {@code Chrono} using {@link #of(String)}.
|
||||
* The ID uniquely identifies the {@code Chronology}.
|
||||
* It can be used to lookup the {@code Chronology} using {@link #of(String)}.
|
||||
*
|
||||
* @return the chronology ID, not null
|
||||
* @see #getCalendarType()
|
||||
@ -453,7 +468,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* <p>
|
||||
* The calendar type is an identifier defined by the
|
||||
* <em>Unicode Locale Data Markup Language (LDML)</em> specification.
|
||||
* It can be used to lookup the {@code Chrono} using {@link #of(String)}.
|
||||
* 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'.
|
||||
*
|
||||
@ -474,7 +489,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @return the local date in this chronology, not null
|
||||
* @throws DateTimeException if unable to create the date
|
||||
*/
|
||||
public ChronoLocalDate<C> date(Era<C> era, int yearOfEra, int month, int dayOfMonth) {
|
||||
public ChronoLocalDate date(Era era, int yearOfEra, int month, int dayOfMonth) {
|
||||
return date(prolepticYear(era, yearOfEra), month, dayOfMonth);
|
||||
}
|
||||
|
||||
@ -488,7 +503,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @return the local date in this chronology, not null
|
||||
* @throws DateTimeException if unable to create the date
|
||||
*/
|
||||
public abstract ChronoLocalDate<C> date(int prolepticYear, int month, int dayOfMonth);
|
||||
public abstract ChronoLocalDate date(int prolepticYear, int month, int dayOfMonth);
|
||||
|
||||
/**
|
||||
* Obtains a local date in this chronology from the era, year-of-era and
|
||||
@ -500,7 +515,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @return the local date in this chronology, not null
|
||||
* @throws DateTimeException if unable to create the date
|
||||
*/
|
||||
public ChronoLocalDate<C> dateYearDay(Era<C> era, int yearOfEra, int dayOfYear) {
|
||||
public ChronoLocalDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
|
||||
return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
|
||||
}
|
||||
|
||||
@ -513,21 +528,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @return the local date in this chronology, not null
|
||||
* @throws DateTimeException if unable to create the date
|
||||
*/
|
||||
public abstract ChronoLocalDate<C> dateYearDay(int prolepticYear, int dayOfYear);
|
||||
|
||||
/**
|
||||
* Obtains a local date in this chronology from another temporal object.
|
||||
* <p>
|
||||
* This creates a date in this chronology based on the specified {@code TemporalAccessor}.
|
||||
* <p>
|
||||
* The standard mechanism for conversion between date types is the
|
||||
* {@link ChronoField#EPOCH_DAY local epoch-day} field.
|
||||
*
|
||||
* @param temporal the temporal object to convert, not null
|
||||
* @return the local date in this chronology, not null
|
||||
* @throws DateTimeException if unable to create the date
|
||||
*/
|
||||
public abstract ChronoLocalDate<C> date(TemporalAccessor temporal);
|
||||
public abstract ChronoLocalDate dateYearDay(int prolepticYear, int dayOfYear);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@ -544,7 +545,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @return the current local date using the system clock and default time-zone, not null
|
||||
* @throws DateTimeException if unable to create the date
|
||||
*/
|
||||
public ChronoLocalDate<C> dateNow() {
|
||||
public ChronoLocalDate dateNow() {
|
||||
return dateNow(Clock.systemDefaultZone());
|
||||
}
|
||||
|
||||
@ -561,7 +562,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @return the current local date using the system clock, not null
|
||||
* @throws DateTimeException if unable to create the date
|
||||
*/
|
||||
public ChronoLocalDate<C> dateNow(ZoneId zone) {
|
||||
public ChronoLocalDate dateNow(ZoneId zone) {
|
||||
return dateNow(Clock.system(zone));
|
||||
}
|
||||
|
||||
@ -576,27 +577,52 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @return the current local date, not null
|
||||
* @throws DateTimeException if unable to create the date
|
||||
*/
|
||||
public ChronoLocalDate<C> dateNow(Clock clock) {
|
||||
public ChronoLocalDate dateNow(Clock clock) {
|
||||
Objects.requireNonNull(clock, "clock");
|
||||
return date(LocalDate.now(clock));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains a local date in this chronology from another temporal object.
|
||||
* <p>
|
||||
* This creates a date in this chronology based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code ChronoLocalDate}.
|
||||
* <p>
|
||||
* The conversion typically uses the {@link ChronoField#EPOCH_DAY EPOCH_DAY}
|
||||
* field, which is standardized across calendar systems.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used as a query via method reference, {@code aChronology::date}.
|
||||
*
|
||||
* @param temporal the temporal object to convert, not null
|
||||
* @return the local date in this chronology, not null
|
||||
* @throws DateTimeException if unable to create the date
|
||||
*/
|
||||
public abstract ChronoLocalDate date(TemporalAccessor temporal);
|
||||
|
||||
/**
|
||||
* Obtains a local date-time in this chronology from another temporal object.
|
||||
* <p>
|
||||
* This creates a date-time in this chronology based on the specified {@code TemporalAccessor}.
|
||||
* This creates a date-time in this chronology based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code ChronoLocalDateTime}.
|
||||
* <p>
|
||||
* The date of the date-time should be equivalent to that obtained by calling
|
||||
* {@link #date(TemporalAccessor)}.
|
||||
* The standard mechanism for conversion between time types is the
|
||||
* {@link ChronoField#NANO_OF_DAY nano-of-day} field.
|
||||
* The conversion extracts and combines the {@code ChronoLocalDate} and the
|
||||
* {@code LocalTime} from the temporal object.
|
||||
* Implementations are permitted to perform optimizations such as accessing
|
||||
* those fields that are equivalent to the relevant objects.
|
||||
* The result uses this chronology.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used as a query via method reference, {@code aChronology::localDateTime}.
|
||||
*
|
||||
* @param temporal the temporal object to convert, not null
|
||||
* @return the local date-time in this chronology, not null
|
||||
* @throws DateTimeException if unable to create the date-time
|
||||
*/
|
||||
public ChronoLocalDateTime<C> localDateTime(TemporalAccessor temporal) {
|
||||
public ChronoLocalDateTime<?> localDateTime(TemporalAccessor temporal) {
|
||||
try {
|
||||
return date(temporal).atTime(LocalTime.from(temporal));
|
||||
} catch (DateTimeException ex) {
|
||||
@ -605,19 +631,29 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a zoned date-time in this chronology from another temporal object.
|
||||
* Obtains a {@code ChronoZonedDateTime} in this chronology from another temporal object.
|
||||
* <p>
|
||||
* This creates a date-time in this chronology based on the specified {@code TemporalAccessor}.
|
||||
* This creates a zoned date-time in this chronology based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code ChronoZonedDateTime}.
|
||||
* <p>
|
||||
* This should obtain a {@code ZoneId} using {@link ZoneId#from(TemporalAccessor)}.
|
||||
* The date-time should be obtained by obtaining an {@code Instant}.
|
||||
* If that fails, the local date-time should be used.
|
||||
* The conversion will first obtain a {@code ZoneId} from the temporal object,
|
||||
* falling back to a {@code ZoneOffset} if necessary. It will then try to obtain
|
||||
* an {@code Instant}, falling back to a {@code ChronoLocalDateTime} if necessary.
|
||||
* The result will be either the combination of {@code ZoneId} or {@code ZoneOffset}
|
||||
* with {@code Instant} or {@code ChronoLocalDateTime}.
|
||||
* Implementations are permitted to perform optimizations such as accessing
|
||||
* those fields that are equivalent to the relevant objects.
|
||||
* The result uses this chronology.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used as a query via method reference, {@code aChronology::zonedDateTime}.
|
||||
*
|
||||
* @param temporal the temporal object to convert, not null
|
||||
* @return the zoned date-time in this chronology, not null
|
||||
* @throws DateTimeException if unable to create the date-time
|
||||
*/
|
||||
public ChronoZonedDateTime<C> zonedDateTime(TemporalAccessor temporal) {
|
||||
public ChronoZonedDateTime<?> zonedDateTime(TemporalAccessor temporal) {
|
||||
try {
|
||||
ZoneId zone = ZoneId.from(temporal);
|
||||
try {
|
||||
@ -625,7 +661,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
return zonedDateTime(instant, zone);
|
||||
|
||||
} catch (DateTimeException ex1) {
|
||||
ChronoLocalDateTimeImpl<C> cldt = ensureChronoLocalDateTime(localDateTime(temporal));
|
||||
ChronoLocalDateTimeImpl cldt = ensureChronoLocalDateTime(localDateTime(temporal));
|
||||
return ChronoZonedDateTimeImpl.ofBest(cldt, zone, null);
|
||||
}
|
||||
} catch (DateTimeException ex) {
|
||||
@ -634,7 +670,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a zoned date-time in this chronology from an {@code Instant}.
|
||||
* Obtains a {@code ChronoZonedDateTime} in this chronology from an {@code Instant}.
|
||||
* <p>
|
||||
* This creates a zoned date-time with the same instant as that specified.
|
||||
*
|
||||
@ -643,7 +679,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @return the zoned date-time, not null
|
||||
* @throws DateTimeException if the result exceeds the supported range
|
||||
*/
|
||||
public ChronoZonedDateTime<C> zonedDateTime(Instant instant, ZoneId zone) {
|
||||
public ChronoZonedDateTime<?> zonedDateTime(Instant instant, ZoneId zone) {
|
||||
return ChronoZonedDateTimeImpl.ofInstant(this, instant, zone);
|
||||
}
|
||||
|
||||
@ -673,7 +709,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @return the proleptic-year
|
||||
* @throws DateTimeException if unable to convert
|
||||
*/
|
||||
public abstract int prolepticYear(Era<C> era, int yearOfEra);
|
||||
public abstract int prolepticYear(Era era, int yearOfEra);
|
||||
|
||||
/**
|
||||
* Creates the chronology era object from the numeric value.
|
||||
@ -694,7 +730,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @return the calendar system era, not null
|
||||
* @throws DateTimeException if unable to create the era
|
||||
*/
|
||||
public abstract Era<C> eraOf(int eraValue);
|
||||
public abstract Era eraOf(int eraValue);
|
||||
|
||||
/**
|
||||
* Gets the list of eras for the chronology.
|
||||
@ -705,7 +741,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
*
|
||||
* @return the list of eras for the chronology, may be immutable, not null
|
||||
*/
|
||||
public abstract List<Era<C>> eras();
|
||||
public abstract List<Era> eras();
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@ -730,15 +766,16 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
/**
|
||||
* Gets the textual representation of this chronology.
|
||||
* <p>
|
||||
* This returns the textual name used to identify the chronology.
|
||||
* This returns the textual name used to identify the chronology,
|
||||
* suitable for presentation to the user.
|
||||
* The parameters control the style of the returned text and the locale.
|
||||
*
|
||||
* @param style the style of the text required, not null
|
||||
* @param locale the locale to use, not null
|
||||
* @return the text value of the chronology, not null
|
||||
*/
|
||||
public String getText(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendChronoText(style).toFormatter(locale).print(new TemporalAccessor() {
|
||||
public String getDisplayName(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendChronologyText(style).toFormatter(locale).format(new TemporalAccessor() {
|
||||
@Override
|
||||
public boolean isSupported(TemporalField field) {
|
||||
return false;
|
||||
@ -750,8 +787,8 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.chrono()) {
|
||||
return (R) Chrono.this;
|
||||
if (query == Queries.chronology()) {
|
||||
return (R) Chronology.this;
|
||||
}
|
||||
return TemporalAccessor.super.query(query);
|
||||
}
|
||||
@ -773,7 +810,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* @return the comparator value, negative if less, positive if greater
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Chrono<?> other) {
|
||||
public int compareTo(Chronology other) {
|
||||
return getId().compareTo(other.getId());
|
||||
}
|
||||
|
||||
@ -782,7 +819,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* <p>
|
||||
* The comparison is based on the entire state of the object.
|
||||
* <p>
|
||||
* The default implementation checks the type and calls {@link #compareTo(Chrono)}.
|
||||
* The default implementation checks the type and calls {@link #compareTo(Chronology)}.
|
||||
*
|
||||
* @param obj the object to check, null returns false
|
||||
* @return true if this is equal to the other chronology
|
||||
@ -792,8 +829,8 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Chrono) {
|
||||
return compareTo((Chrono<?>) obj) == 0;
|
||||
if (obj instanceof Chronology) {
|
||||
return compareTo((Chronology) obj) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -827,7 +864,7 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
* Writes the object using a
|
||||
* <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
|
||||
* <pre>
|
||||
* out.writeByte(7); // identifies this as a Chrono
|
||||
* out.writeByte(7); // identifies this as a Chronology
|
||||
* out.writeUTF(chronoId);
|
||||
* </pre>
|
||||
*
|
||||
@ -850,9 +887,9 @@ public abstract class Chrono<C extends Chrono<C>> implements Comparable<Chrono<?
|
||||
out.writeUTF(getId());
|
||||
}
|
||||
|
||||
static Chrono<?> readExternal(DataInput in) throws IOException {
|
||||
static Chronology readExternal(DataInput in) throws IOException {
|
||||
String id = in.readUTF();
|
||||
return Chrono.of(id);
|
||||
return Chronology.of(id);
|
||||
}
|
||||
|
||||
}
|
||||
@ -59,7 +59,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.ERA;
|
||||
import static java.time.temporal.ChronoUnit.ERAS;
|
||||
@ -67,6 +67,14 @@ import static java.time.temporal.ChronoUnit.ERAS;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.TextStyle;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
@ -77,7 +85,7 @@ import java.util.Locale;
|
||||
* of each leader.
|
||||
* In all cases, the era is conceptually the largest division of the time-line.
|
||||
* Each chronology defines the Era's that are known Eras and a
|
||||
* {@link Chrono#eras Chrono.eras} to get the valid eras.
|
||||
* {@link Chronology#eras Chronology.eras} to get the valid eras.
|
||||
* <p>
|
||||
* For example, the Thai Buddhist calendar system divides time into two eras,
|
||||
* before and after a single date. By contrast, the Japanese calendar system
|
||||
@ -90,10 +98,9 @@ import java.util.Locale;
|
||||
* All implementations must be singletons - final, immutable and thread-safe.
|
||||
* It is recommended to use an enum whenever possible.
|
||||
*
|
||||
* @param <C> the chronology of the era
|
||||
* @since 1.8
|
||||
*/
|
||||
public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdjuster {
|
||||
public interface Era extends TemporalAccessor, TemporalAdjuster {
|
||||
|
||||
/**
|
||||
* Gets the numeric value associated with the era as defined by the chronology.
|
||||
@ -116,12 +123,12 @@ public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdju
|
||||
/**
|
||||
* Gets the chronology of this era.
|
||||
* <p>
|
||||
* The {@code Chrono} represents the calendar system in use.
|
||||
* The {@code Chronology} represents the calendar system in use.
|
||||
* This always returns the standard form of the chronology.
|
||||
*
|
||||
* @return the chronology, not null
|
||||
*/
|
||||
C getChrono();
|
||||
Chronology getChronology();
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@ -129,18 +136,18 @@ public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdju
|
||||
* <p>
|
||||
* This era is combined with the given date fields to form a date.
|
||||
* The year specified must be the year-of-era.
|
||||
* Methods to create a date from the proleptic-year are on {@code Chrono}.
|
||||
* Methods to create a date from the proleptic-year are on {@code Chronology}.
|
||||
* This always uses the standard form of the chronology.
|
||||
* <p>
|
||||
* This default implementation invokes the factory method on {@link Chrono}.
|
||||
* This default implementation invokes the factory method on {@link Chronology}.
|
||||
*
|
||||
* @param yearOfEra the calendar system year-of-era
|
||||
* @param month the calendar system month-of-year
|
||||
* @param day the calendar system day-of-month
|
||||
* @return a local date based on this era and the specified year-of-era, month and day
|
||||
*/
|
||||
public default ChronoLocalDate<C> date(int yearOfEra, int month, int day) {
|
||||
return getChrono().date(this, yearOfEra, month, day);
|
||||
public default ChronoLocalDate date(int yearOfEra, int month, int day) {
|
||||
return getChronology().date(this, yearOfEra, month, day);
|
||||
}
|
||||
|
||||
|
||||
@ -149,17 +156,17 @@ public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdju
|
||||
* <p>
|
||||
* This era is combined with the given date fields to form a date.
|
||||
* The year specified must be the year-of-era.
|
||||
* Methods to create a date from the proleptic-year are on {@code Chrono}.
|
||||
* Methods to create a date from the proleptic-year are on {@code Chronology}.
|
||||
* This always uses the standard form of the chronology.
|
||||
* <p>
|
||||
* This default implementation invokes the factory method on {@link Chrono}.
|
||||
* This default implementation invokes the factory method on {@link Chronology}.
|
||||
*
|
||||
* @param yearOfEra the calendar system year-of-era
|
||||
* @param dayOfYear the calendar system day-of-year
|
||||
* @return a local date based on this era and the specified year-of-era and day-of-year
|
||||
*/
|
||||
public default ChronoLocalDate<C> dateYearDay(int yearOfEra, int dayOfYear) {
|
||||
return getChrono().dateYearDay(this, yearOfEra, dayOfYear);
|
||||
public default ChronoLocalDate dateYearDay(int yearOfEra, int dayOfYear) {
|
||||
return getChronology().dateYearDay(this, yearOfEra, dayOfYear);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -175,7 +182,7 @@ public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdju
|
||||
* All other {@code ChronoField} instances will return false.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the field is supported is determined by the field.
|
||||
*
|
||||
@ -187,7 +194,7 @@ public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdju
|
||||
if (field instanceof ChronoField) {
|
||||
return field == ERA;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
return field != null && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -203,7 +210,7 @@ public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdju
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
|
||||
* passing {@code this} as the argument.
|
||||
* Whether the range can be obtained is determined by the field.
|
||||
*
|
||||
@ -229,7 +236,7 @@ public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdju
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -258,7 +265,7 @@ public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdju
|
||||
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
|
||||
* <p>
|
||||
* If the field is not a {@code ChronoField}, then the result of this method
|
||||
* is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
|
||||
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
|
||||
* passing {@code this} as the argument. Whether the value can be obtained,
|
||||
* and what the value represents, is determined by the field.
|
||||
*
|
||||
@ -274,7 +281,7 @@ public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdju
|
||||
} else if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -299,8 +306,8 @@ public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdju
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public default <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.chrono()) {
|
||||
return (R) getChrono();
|
||||
if (query == Queries.chronology()) {
|
||||
return (R) getChronology();
|
||||
} else if (query == Queries.precision()) {
|
||||
return (R) ERAS;
|
||||
}
|
||||
@ -340,7 +347,8 @@ public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdju
|
||||
/**
|
||||
* Gets the textual representation of this era.
|
||||
* <p>
|
||||
* This returns the textual name used to identify the era.
|
||||
* This returns the textual name used to identify the era,
|
||||
* suitable for presentation to the user.
|
||||
* The parameters control the style of the returned text and the locale.
|
||||
* <p>
|
||||
* If no textual mapping is found then the {@link #getValue() numeric value} is returned.
|
||||
@ -351,8 +359,8 @@ public interface Era<C extends Chrono<C>> extends TemporalAccessor, TemporalAdju
|
||||
* @param locale the locale to use, not null
|
||||
* @return the text value of the era, not null
|
||||
*/
|
||||
public default String getText(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendText(ERA, style).toFormatter(locale).print(this);
|
||||
public default String getDisplayName(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendText(ERA, style).toFormatter(locale).format(this);
|
||||
}
|
||||
|
||||
// NOTE: methods to convert year-of-era/proleptic-year cannot be here as they may depend on month/day (Japanese)
|
||||
@ -55,18 +55,19 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.EPOCH_DAY;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.text.ParseException;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.temporal.Chrono;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.Era;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Arrays;
|
||||
@ -175,7 +176,7 @@ import java.util.Locale;
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializable {
|
||||
public final class HijrahChronology extends Chronology implements Serializable {
|
||||
|
||||
/**
|
||||
* The Hijrah Calendar id.
|
||||
@ -191,11 +192,11 @@ public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializ
|
||||
* The singleton instance for the era before the current one - Before Hijrah -
|
||||
* which has the value 0.
|
||||
*/
|
||||
public static final Era<HijrahChrono> ERA_BEFORE_AH = HijrahEra.BEFORE_AH;
|
||||
public static final Era ERA_BEFORE_AH = HijrahEra.BEFORE_AH;
|
||||
/**
|
||||
* The singleton instance for the current era - Hijrah - which has the value 1.
|
||||
*/
|
||||
public static final Era<HijrahChrono> ERA_AH = HijrahEra.AH;
|
||||
public static final Era ERA_AH = HijrahEra.AH;
|
||||
/**
|
||||
* Serialization version.
|
||||
*/
|
||||
@ -419,7 +420,7 @@ public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializ
|
||||
* Singleton instance of the Hijrah chronology.
|
||||
* Must be initialized after the rest of the static initialization.
|
||||
*/
|
||||
public static final HijrahChrono INSTANCE;
|
||||
public static final HijrahChronology INSTANCE;
|
||||
|
||||
/**
|
||||
* Name data.
|
||||
@ -439,10 +440,10 @@ public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializ
|
||||
|
||||
DEFAULT_CYCLE_YEARS = Arrays.copyOf(CYCLEYEAR_START_DATE, CYCLEYEAR_START_DATE.length);
|
||||
|
||||
INSTANCE = new HijrahChrono();
|
||||
INSTANCE = new HijrahChronology();
|
||||
|
||||
String extraCalendars = java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction("java.time.calendar.HijrahCalendars"));
|
||||
new sun.security.action.GetPropertyAction("java.time.chrono.HijrahCalendars"));
|
||||
if (extraCalendars != null) {
|
||||
try {
|
||||
// Split on whitespace
|
||||
@ -451,7 +452,7 @@ public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializ
|
||||
if (!cal.isEmpty()) {
|
||||
// Split on the delimiter between typeId "-" calendarType
|
||||
String[] type = cal.split("-");
|
||||
Chrono<?> cal2 = new HijrahChrono(type[0], type.length > 1 ? type[1] : type[0]);
|
||||
Chronology cal2 = new HijrahChronology(type[0], type.length > 1 ? type[1] : type[0]);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
@ -464,15 +465,15 @@ public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializ
|
||||
/**
|
||||
* Restricted constructor.
|
||||
*/
|
||||
private HijrahChrono() {
|
||||
private HijrahChronology() {
|
||||
this("Hijrah", "islamicc");
|
||||
}
|
||||
/**
|
||||
* Constructor for name and type HijrahChrono.
|
||||
* Constructor for name and type HijrahChronology.
|
||||
* @param id the id of the calendar
|
||||
* @param calendarType the calendar type
|
||||
*/
|
||||
private HijrahChrono(String id, String calendarType) {
|
||||
private HijrahChronology(String id, String calendarType) {
|
||||
this.typeId = id;
|
||||
this.calendarType = calendarType;
|
||||
|
||||
@ -507,8 +508,8 @@ public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializ
|
||||
/**
|
||||
* Gets the ID of the chronology - 'Hijrah'.
|
||||
* <p>
|
||||
* The ID uniquely identifies the {@code Chrono}.
|
||||
* It can be used to lookup the {@code Chrono} using {@link #of(String)}.
|
||||
* The ID uniquely identifies the {@code Chronology}.
|
||||
* It can be used to lookup the {@code Chronology} using {@link #of(String)}.
|
||||
*
|
||||
* @return the chronology ID - 'Hijrah'
|
||||
* @see #getCalendarType()
|
||||
@ -523,7 +524,7 @@ public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializ
|
||||
* <p>
|
||||
* The calendar type is an identifier defined by the
|
||||
* <em>Unicode Locale Data Markup Language (LDML)</em> specification.
|
||||
* It can be used to lookup the {@code Chrono} using {@link #of(String)}.
|
||||
* 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'.
|
||||
*
|
||||
@ -537,23 +538,64 @@ public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializ
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoLocalDate<HijrahChrono> date(int prolepticYear, int month, int dayOfMonth) {
|
||||
public HijrahDate date(int prolepticYear, int month, int dayOfMonth) {
|
||||
return HijrahDate.of(this, prolepticYear, month, dayOfMonth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<HijrahChrono> dateYearDay(int prolepticYear, int dayOfYear) {
|
||||
public HijrahDate dateYearDay(int prolepticYear, int dayOfYear) {
|
||||
return HijrahDate.of(this, prolepticYear, 1, 1).plusDays(dayOfYear - 1); // TODO better
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<HijrahChrono> date(TemporalAccessor temporal) {
|
||||
public HijrahDate date(TemporalAccessor temporal) {
|
||||
if (temporal instanceof HijrahDate) {
|
||||
return (HijrahDate) temporal;
|
||||
}
|
||||
return HijrahDate.ofEpochDay(this, temporal.getLong(EPOCH_DAY));
|
||||
}
|
||||
|
||||
@Override
|
||||
public HijrahDate date(Era era, int yearOfEra, int month, int dayOfMonth) {
|
||||
return date(prolepticYear(era, yearOfEra), month, dayOfMonth);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public HijrahDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
|
||||
return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HijrahDate dateNow() {
|
||||
return dateNow(Clock.systemDefaultZone());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HijrahDate dateNow(ZoneId zone) {
|
||||
return dateNow(Clock.system(zone));
|
||||
}
|
||||
|
||||
@Override
|
||||
public HijrahDate dateNow(Clock clock) {
|
||||
return date(LocalDate.now(clock));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDateTime<HijrahDate> localDateTime(TemporalAccessor temporal) {
|
||||
return (ChronoLocalDateTime<HijrahDate>)super.localDateTime(temporal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoZonedDateTime<HijrahDate> zonedDateTime(TemporalAccessor temporal) {
|
||||
return (ChronoZonedDateTime<HijrahDate>)super.zonedDateTime(temporal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoZonedDateTime<HijrahDate> zonedDateTime(Instant instant, ZoneId zone) {
|
||||
return (ChronoZonedDateTime<HijrahDate>)super.zonedDateTime(instant, zone);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public boolean isLeapYear(long prolepticYear) {
|
||||
@ -569,7 +611,7 @@ public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializ
|
||||
}
|
||||
|
||||
@Override
|
||||
public int prolepticYear(Era<HijrahChrono> era, int yearOfEra) {
|
||||
public int prolepticYear(Era era, int yearOfEra) {
|
||||
if (era instanceof HijrahEra == false) {
|
||||
throw new DateTimeException("Era must be HijrahEra");
|
||||
}
|
||||
@ -577,7 +619,7 @@ public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializ
|
||||
}
|
||||
|
||||
@Override
|
||||
public Era<HijrahChrono> eraOf(int eraValue) {
|
||||
public Era eraOf(int eraValue) {
|
||||
switch (eraValue) {
|
||||
case 0:
|
||||
return HijrahEra.BEFORE_AH;
|
||||
@ -589,8 +631,8 @@ public final class HijrahChrono extends Chrono<HijrahChrono> implements Serializ
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Era<HijrahChrono>> eras() {
|
||||
return Arrays.<Era<HijrahChrono>>asList(HijrahEra.values());
|
||||
public List<Era> eras() {
|
||||
return Arrays.<Era>asList(HijrahEra.values());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -54,7 +54,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH;
|
||||
import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR;
|
||||
@ -68,19 +68,27 @@ import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Period;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A date in the Hijrah calendar system.
|
||||
* <p>
|
||||
* This implements {@code ChronoLocalDate} for the {@link HijrahChrono Hijrah calendar}.
|
||||
* This date operates using the {@linkplain HijrahChronology Hijrah calendar}.
|
||||
* <p>
|
||||
* The Hijrah calendar has a different total of days in a year than
|
||||
* Gregorian calendar, and a month is based on the period of a complete
|
||||
@ -116,11 +124,9 @@ import java.util.Objects;
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
final class HijrahDate
|
||||
extends ChronoDateImpl<HijrahChrono>
|
||||
implements ChronoLocalDate<HijrahChrono>, Serializable {
|
||||
// this class is package-scoped so that future conversion to public
|
||||
// would not change serialization
|
||||
public final class HijrahDate
|
||||
extends ChronoDateImpl<HijrahDate>
|
||||
implements ChronoLocalDate<HijrahDate>, Serializable {
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
@ -130,7 +136,7 @@ final class HijrahDate
|
||||
/**
|
||||
* The Chronology of this HijrahDate.
|
||||
*/
|
||||
private final HijrahChrono chrono;
|
||||
private final HijrahChronology chrono;
|
||||
/**
|
||||
* The era.
|
||||
*/
|
||||
@ -177,7 +183,7 @@ final class HijrahDate
|
||||
* @return the Hijrah date, never null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
*/
|
||||
static HijrahDate of(HijrahChrono chrono, int prolepticYear, int monthOfYear, int dayOfMonth) {
|
||||
static HijrahDate of(HijrahChronology chrono, int prolepticYear, int monthOfYear, int dayOfMonth) {
|
||||
return (prolepticYear >= 1) ?
|
||||
HijrahDate.of(chrono, HijrahEra.AH, prolepticYear, monthOfYear, dayOfMonth) :
|
||||
HijrahDate.of(chrono, HijrahEra.BEFORE_AH, 1 - prolepticYear, monthOfYear, dayOfMonth);
|
||||
@ -194,7 +200,7 @@ final class HijrahDate
|
||||
* @return the Hijrah date, never null
|
||||
* @throws DateTimeException if the value of any field is out of range
|
||||
*/
|
||||
private static HijrahDate of(HijrahChrono chrono, HijrahEra era, int yearOfEra, int monthOfYear, int dayOfMonth) {
|
||||
private static HijrahDate of(HijrahChronology chrono, HijrahEra era, int yearOfEra, int monthOfYear, int dayOfMonth) {
|
||||
Objects.requireNonNull(era, "era");
|
||||
chrono.checkValidYearOfEra(yearOfEra);
|
||||
chrono.checkValidMonth(monthOfYear);
|
||||
@ -203,28 +209,103 @@ final class HijrahDate
|
||||
return new HijrahDate(chrono, gregorianDays);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an instance of {@code HijrahDate} from a date.
|
||||
*
|
||||
* @param date the date to use, not null
|
||||
* @return the Hijrah date, never null
|
||||
* @throws DateTimeException if the year is invalid
|
||||
*/
|
||||
private static HijrahDate of(HijrahChrono chrono, LocalDate date) {
|
||||
long gregorianDays = date.toEpochDay();
|
||||
return new HijrahDate(chrono, gregorianDays);
|
||||
}
|
||||
|
||||
static HijrahDate ofEpochDay(HijrahChrono chrono, long epochDay) {
|
||||
static HijrahDate ofEpochDay(HijrahChronology chrono, long epochDay) {
|
||||
return new HijrahDate(chrono, epochDay);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains the current {@code HijrahDate} from the system clock in the default time-zone.
|
||||
* <p>
|
||||
* This will query the {@link Clock#systemDefaultZone() system clock} in the default
|
||||
* time-zone to obtain the current date.
|
||||
* <p>
|
||||
* Using this method will prevent the ability to use an alternate clock for testing
|
||||
* because the clock is hard-coded.
|
||||
*
|
||||
* @return the current date using the system clock and default time-zone, not null
|
||||
*/
|
||||
public static HijrahDate now() {
|
||||
return now(Clock.systemDefaultZone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current {@code HijrahDate} from the system clock in the specified time-zone.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* Using this method will prevent the ability to use an alternate clock for testing
|
||||
* because the clock is hard-coded.
|
||||
*
|
||||
* @param zone the zone ID to use, not null
|
||||
* @return the current date using the system clock, not null
|
||||
*/
|
||||
public static HijrahDate now(ZoneId zone) {
|
||||
return now(Clock.system(zone));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current {@code HijrahDate} from the specified clock.
|
||||
* <p>
|
||||
* 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 {@linkplain Clock dependency injection}.
|
||||
*
|
||||
* @param clock the clock to use, not null
|
||||
* @return the current date, not null
|
||||
* @throws DateTimeException if the current date cannot be obtained
|
||||
*/
|
||||
public static HijrahDate now(Clock clock) {
|
||||
return HijrahChronology.INSTANCE.date(LocalDate.now(clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code HijrahDate} representing a date in the Hijrah calendar
|
||||
* system from the proleptic-year, month-of-year and day-of-month fields.
|
||||
* <p>
|
||||
* This returns a {@code HijrahDate} with the specified fields.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param prolepticYear the Hijrah proleptic-year
|
||||
* @param month the Hijrah month-of-year, from 1 to 12
|
||||
* @param dayOfMonth the Hijrah day-of-month, from 1 to 30
|
||||
* @return the date in Hijrah calendar system, not null
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static HijrahDate of(int prolepticYear, int month, int dayOfMonth) {
|
||||
return HijrahChronology.INSTANCE.date(prolepticYear, month, dayOfMonth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code HijrahDate} from a temporal object.
|
||||
* <p>
|
||||
* This obtains a date in the Hijrah calendar system based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code HijrahDate}.
|
||||
* <p>
|
||||
* The conversion typically uses the {@link ChronoField#EPOCH_DAY EPOCH_DAY}
|
||||
* field, which is standardized across calendar systems.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used as a query via method reference, {@code HijrahDate::from}.
|
||||
*
|
||||
* @param temporal the temporal object to convert, not null
|
||||
* @return the date in Hijrah calendar system, not null
|
||||
* @throws DateTimeException if unable to convert to a {@code HijrahDate}
|
||||
*/
|
||||
public static HijrahDate from(TemporalAccessor temporal) {
|
||||
return HijrahChronology.INSTANCE.date(temporal);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Constructs an instance with the specified date.
|
||||
*
|
||||
* @param gregorianDay the number of days from 0001/01/01 (Gregorian), caller calculated
|
||||
*/
|
||||
private HijrahDate(HijrahChrono chrono, long gregorianDay) {
|
||||
private HijrahDate(HijrahChronology chrono, long gregorianDay) {
|
||||
this.chrono = chrono;
|
||||
int[] dateInfo = chrono.getHijrahDateInfo(gregorianDay);
|
||||
|
||||
@ -245,7 +326,7 @@ final class HijrahDate
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public HijrahChrono getChrono() {
|
||||
public HijrahChronology getChronology() {
|
||||
return chrono;
|
||||
}
|
||||
|
||||
@ -260,11 +341,16 @@ final class HijrahDate
|
||||
case ALIGNED_WEEK_OF_MONTH: return ValueRange.of(1, 5); // TODO
|
||||
case YEAR_OF_ERA: return ValueRange.of(1, 1000); // TODO
|
||||
}
|
||||
return getChrono().range(f);
|
||||
return getChronology().range(f);
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doRange(this);
|
||||
return field.rangeRefinedBy(this);
|
||||
}
|
||||
|
||||
@Override // Override for javadoc
|
||||
public int get(TemporalField field) {
|
||||
return super.get(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -286,7 +372,7 @@ final class HijrahDate
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -322,17 +408,41 @@ final class HijrahDate
|
||||
return HijrahDate.of(chrono, yearOfEra, month, day);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public HijrahDate with(TemporalAdjuster adjuster) {
|
||||
return (HijrahDate)super.with(adjuster);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public HijrahDate plus(TemporalAmount amount) {
|
||||
return (HijrahDate)super.plus(amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public HijrahDate minus(TemporalAmount amount) {
|
||||
return (HijrahDate)super.minus(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long toEpochDay() {
|
||||
return chrono.getGregorianEpochDay(yearOfEra, monthOfYear, dayOfMonth);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public HijrahEra getEra() {
|
||||
return this.era;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Checks if the year is a leap year, according to the Hijrah calendar system rules.
|
||||
@ -346,7 +456,7 @@ final class HijrahDate
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public HijrahDate plusYears(long years) {
|
||||
HijrahDate plusYears(long years) {
|
||||
if (years == 0) {
|
||||
return this;
|
||||
}
|
||||
@ -355,7 +465,7 @@ final class HijrahDate
|
||||
}
|
||||
|
||||
@Override
|
||||
public HijrahDate plusMonths(long months) {
|
||||
HijrahDate plusMonths(long months) {
|
||||
if (months == 0) {
|
||||
return this;
|
||||
}
|
||||
@ -372,10 +482,45 @@ final class HijrahDate
|
||||
}
|
||||
|
||||
@Override
|
||||
public HijrahDate plusDays(long days) {
|
||||
HijrahDate plusWeeks(long weeksToAdd) {
|
||||
return (HijrahDate)super.plusWeeks(weeksToAdd);
|
||||
}
|
||||
|
||||
@Override
|
||||
HijrahDate plusDays(long days) {
|
||||
return new HijrahDate(chrono, this.gregorianEpochDay + days);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HijrahDate plus(long amountToAdd, TemporalUnit unit) {
|
||||
return (HijrahDate)super.plus(amountToAdd, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HijrahDate minus(long amountToSubtract, TemporalUnit unit) {
|
||||
return (HijrahDate)super.minus(amountToSubtract, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
HijrahDate minusYears(long yearsToSubtract) {
|
||||
return (HijrahDate)super.minusYears(yearsToSubtract);
|
||||
}
|
||||
|
||||
@Override
|
||||
HijrahDate minusMonths(long monthsToSubtract) {
|
||||
return (HijrahDate)super.minusMonths(monthsToSubtract);
|
||||
}
|
||||
|
||||
@Override
|
||||
HijrahDate minusWeeks(long weeksToSubtract) {
|
||||
return (HijrahDate)super.minusWeeks(weeksToSubtract);
|
||||
}
|
||||
|
||||
@Override
|
||||
HijrahDate minusDays(long daysToSubtract) {
|
||||
return (HijrahDate)super.minusDays(daysToSubtract);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns month days from the beginning of year.
|
||||
*
|
||||
@ -410,13 +555,37 @@ final class HijrahDate
|
||||
return chrono.getYearLength(yearOfEra); // TODO: proleptic year
|
||||
}
|
||||
|
||||
@Override // for javadoc and covariant return type
|
||||
public final ChronoLocalDateTime<HijrahDate> atTime(LocalTime localTime) {
|
||||
return (ChronoLocalDateTime<HijrahDate>)super.atTime(localTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Period periodUntil(ChronoLocalDate<?> endDate) {
|
||||
// TODO: untested
|
||||
HijrahDate end = (HijrahDate) getChronology().date(endDate);
|
||||
long totalMonths = (end.yearOfEra - this.yearOfEra) * 12 + (end.monthOfYear - this.monthOfYear); // safe
|
||||
int days = end.dayOfMonth - this.dayOfMonth;
|
||||
if (totalMonths > 0 && days < 0) {
|
||||
totalMonths--;
|
||||
HijrahDate calcDate = this.plusMonths(totalMonths);
|
||||
days = (int) (end.toEpochDay() - calcDate.toEpochDay()); // safe
|
||||
} else if (totalMonths < 0 && days > 0) {
|
||||
totalMonths++;
|
||||
days -= end.lengthOfMonth();
|
||||
}
|
||||
long years = totalMonths / 12; // safe
|
||||
int months = (int) (totalMonths % 12); // safe
|
||||
return Period.of(Math.toIntExact(years), months, days);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
private Object writeReplace() {
|
||||
return new Ser(Ser.HIJRAH_DATE_TYPE, this);
|
||||
}
|
||||
|
||||
void writeExternal(ObjectOutput out) throws IOException {
|
||||
// HijrahChrono is implicit in the Hijrah_DATE_TYPE
|
||||
// HijrahChronology is implicit in the Hijrah_DATE_TYPE
|
||||
out.writeObject(chrono);
|
||||
out.writeInt(get(YEAR));
|
||||
out.writeByte(get(MONTH_OF_YEAR));
|
||||
@ -434,8 +603,8 @@ final class HijrahDate
|
||||
return this;
|
||||
}
|
||||
|
||||
static ChronoLocalDate<HijrahChrono> readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
HijrahChrono chrono = (HijrahChrono)in.readObject();
|
||||
static ChronoLocalDate<HijrahDate> readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
HijrahChronology chrono = (HijrahChronology)in.readObject();
|
||||
int year = in.readInt();
|
||||
int month = in.readByte();
|
||||
int dayOfMonth = in.readByte();
|
||||
@ -54,7 +54,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@ -67,9 +67,8 @@ import java.nio.file.FileSystems;
|
||||
import java.security.AccessController;
|
||||
import java.text.ParseException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatters;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Block;
|
||||
|
||||
@ -85,7 +84,7 @@ import java.util.function.Block;
|
||||
* The deviation files are named {@code "hijrah_" + ID}.
|
||||
* <p>
|
||||
* The deviation file for a calendar can be overridden by defining the
|
||||
* property {@code java.time.calendar.HijrahChrono.File.hijrah_<ID>}
|
||||
* property {@code java.time.chrono.HijrahChronology.File.hijrah_<ID>}
|
||||
* with the full pathname of the deviation file.
|
||||
* <p>
|
||||
* The deviation file is read line by line:
|
||||
@ -133,7 +132,7 @@ final class HijrahDeviationReader {
|
||||
* @throws ParseException if the format of the configuration file is wrong.
|
||||
*/
|
||||
static boolean readDeviation(String typeId, String calendarType,
|
||||
Block<HijrahChrono.Deviation> block) throws IOException, ParseException {
|
||||
Block<HijrahChronology.Deviation> block) throws IOException, ParseException {
|
||||
InputStream is = getConfigFileInputStream(typeId);
|
||||
if (is != null) {
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
|
||||
@ -141,7 +140,7 @@ final class HijrahDeviationReader {
|
||||
int num = 0;
|
||||
while ((line = br.readLine()) != null) {
|
||||
num++;
|
||||
HijrahChrono.Deviation entry = parseLine(line, num);
|
||||
HijrahChronology.Deviation entry = parseLine(line, num);
|
||||
if (entry != null) {
|
||||
block.accept(entry);
|
||||
}
|
||||
@ -160,7 +159,7 @@ final class HijrahDeviationReader {
|
||||
* @return an Entry or null if the line is empty.
|
||||
* @throws ParseException if line has incorrect format.
|
||||
*/
|
||||
private static HijrahChrono.Deviation parseLine(final String line, final int num) throws ParseException {
|
||||
private static HijrahChronology.Deviation parseLine(final String line, final int num) throws ParseException {
|
||||
int hash = line.indexOf("#");
|
||||
String nocomment = (hash < 0) ? line : line.substring(0, hash);
|
||||
String[] split = nocomment.split("\\s");
|
||||
@ -174,16 +173,16 @@ final class HijrahDeviationReader {
|
||||
//element [0] is a date
|
||||
//element [1] is the offset
|
||||
|
||||
LocalDate isoDate = DateTimeFormatters.pattern("MMM-dd-yyyy").parse(split[0], LocalDate::from);
|
||||
LocalDate isoDate = DateTimeFormatter.ofPattern("MMM-dd-yyyy").parse(split[0], LocalDate::from);
|
||||
int offset = Integer.valueOf(split[1]);
|
||||
|
||||
// Convert date to HijrahDate using the default Islamic Calendar
|
||||
|
||||
ChronoLocalDate<HijrahChrono> hijrahDate = HijrahChrono.INSTANCE.date(isoDate);
|
||||
HijrahDate hijrahDate = HijrahChronology.INSTANCE.date(isoDate);
|
||||
|
||||
int year = hijrahDate.get(ChronoField.YEAR);
|
||||
int month = hijrahDate.get(ChronoField.MONTH_OF_YEAR);
|
||||
return new HijrahChrono.Deviation(year, month, year, month, offset);
|
||||
return new HijrahChronology.Deviation(year, month, year, month, offset);
|
||||
}
|
||||
|
||||
|
||||
@ -198,8 +197,8 @@ final class HijrahDeviationReader {
|
||||
* </pre> The default location and file name can be overridden by setting
|
||||
* following two Java system properties.
|
||||
* <pre>
|
||||
* Location: java.time.calendar.HijrahDate.deviationConfigDir
|
||||
* File name: java.time.calendar.HijrahDate.File. + typeid
|
||||
* Location: java.time.chrono.HijrahDate.deviationConfigDir
|
||||
* File name: java.time.chrono.HijrahDate.File. + typeid
|
||||
* </pre> Regarding the file format, see readDeviationConfig() method for
|
||||
* details.
|
||||
*
|
||||
@ -209,10 +208,9 @@ final class HijrahDeviationReader {
|
||||
*/
|
||||
private static InputStream getConfigFileInputStream(final String typeId) throws IOException {
|
||||
try {
|
||||
InputStream stream =
|
||||
(InputStream)AccessController
|
||||
.doPrivileged((java.security.PrivilegedExceptionAction) () -> {
|
||||
String propFilename = "java.time.calendar.HijrahChrono.File." + typeId;
|
||||
InputStream stream = AccessController
|
||||
.doPrivileged((java.security.PrivilegedExceptionAction<InputStream>) () -> {
|
||||
String propFilename = "java.time.chrono.HijrahChronology.File." + typeId;
|
||||
String filename = System.getProperty(propFilename);
|
||||
File file = null;
|
||||
if (filename != null) {
|
||||
@ -54,23 +54,12 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
|
||||
import static java.time.temporal.ChronoField.ERA;
|
||||
package java.time.chrono;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.TextStyle;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.Era;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* An era in the Hijrah calendar system.
|
||||
@ -86,7 +75,7 @@ import java.util.Locale;
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
enum HijrahEra implements Era<HijrahChrono> {
|
||||
enum HijrahEra implements Era {
|
||||
|
||||
/**
|
||||
* The singleton instance for the era before the current one, 'Before Anno Hegirae',
|
||||
@ -135,71 +124,23 @@ enum HijrahEra implements Era<HijrahChrono> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public HijrahChrono getChrono() {
|
||||
return HijrahChrono.INSTANCE;
|
||||
public HijrahChronology getChronology() {
|
||||
return HijrahChronology.INSTANCE;
|
||||
}
|
||||
|
||||
// JDK8 default methods:
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoLocalDate<HijrahChrono> date(int year, int month, int day) {
|
||||
return getChrono().date(this, year, month, day);
|
||||
public HijrahDate date(int year, int month, int day) {
|
||||
return (HijrahDate)(getChronology().date(this, year, month, day));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<HijrahChrono> dateYearDay(int year, int dayOfYear) {
|
||||
return getChrono().dateYearDay(this, year, dayOfYear);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public boolean isSupported(TemporalField field) {
|
||||
if (field instanceof ChronoField) {
|
||||
return field == ERA;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueRange range(TemporalField field) {
|
||||
if (field == ERA) {
|
||||
return field.range();
|
||||
} else if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doRange(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get(TemporalField field) {
|
||||
if (field == ERA) {
|
||||
return getValue();
|
||||
}
|
||||
return range(field).checkValidIntValue(getLong(field), field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(TemporalField field) {
|
||||
if (field == ERA) {
|
||||
return getValue();
|
||||
} else if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
public HijrahDate dateYearDay(int year, int dayOfYear) {
|
||||
return (HijrahDate)(getChronology().dateYearDay(this, year, dayOfYear));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@Override
|
||||
public Temporal adjustInto(Temporal temporal) {
|
||||
return temporal.with(ERA, getValue());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public String getText(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendText(ERA, style).toFormatter(locale).print(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the proleptic year from this era and year of era.
|
||||
*
|
||||
@ -59,7 +59,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time.chrono;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
@ -69,6 +69,9 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -102,26 +105,26 @@ import java.util.Objects;
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class ISOChrono extends Chrono<ISOChrono> implements Serializable {
|
||||
public final class IsoChronology extends Chronology implements Serializable {
|
||||
|
||||
/**
|
||||
* Singleton instance of the ISO chronology.
|
||||
*/
|
||||
public static final ISOChrono INSTANCE = new ISOChrono();
|
||||
public static final IsoChronology INSTANCE = new IsoChronology();
|
||||
/**
|
||||
* The singleton instance for the era BCE - 'Before Current Era'.
|
||||
* The 'ISO' part of the name emphasizes that this differs from the BCE
|
||||
* era in the Gregorian calendar system.
|
||||
* This has the numeric value of {@code 0}.
|
||||
*/
|
||||
public static final Era<ISOChrono> ERA_BCE = ISOEra.BCE;
|
||||
public static final Era ERA_BCE = IsoEra.BCE;
|
||||
/**
|
||||
* The singleton instance for the era CE - 'Current Era'.
|
||||
* The 'ISO' part of the name emphasizes that this differs from the CE
|
||||
* era in the Gregorian calendar system.
|
||||
* This has the numeric value of {@code 1}.
|
||||
*/
|
||||
public static final Era<ISOChrono> ERA_CE = ISOEra.CE;
|
||||
public static final Era ERA_CE = IsoEra.CE;
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
@ -131,7 +134,7 @@ public final class ISOChrono extends Chrono<ISOChrono> implements Serializable {
|
||||
/**
|
||||
* Restricted constructor.
|
||||
*/
|
||||
private ISOChrono() {
|
||||
private IsoChronology() {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,8 +150,8 @@ public final class ISOChrono extends Chrono<ISOChrono> implements Serializable {
|
||||
/**
|
||||
* Gets the ID of the chronology - 'ISO'.
|
||||
* <p>
|
||||
* The ID uniquely identifies the {@code Chrono}.
|
||||
* It can be used to lookup the {@code Chrono} using {@link #of(String)}.
|
||||
* 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()
|
||||
@ -163,7 +166,7 @@ public final class ISOChrono extends Chrono<ISOChrono> implements Serializable {
|
||||
* <p>
|
||||
* The calendar type is an identifier defined by the
|
||||
* <em>Unicode Locale Data Markup Language (LDML)</em> specification.
|
||||
* It can be used to lookup the {@code Chrono} using {@link #of(String)}.
|
||||
* 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'.
|
||||
*
|
||||
@ -188,7 +191,7 @@ public final class ISOChrono extends Chrono<ISOChrono> implements Serializable {
|
||||
* @throws DateTimeException if unable to create the date
|
||||
*/
|
||||
@Override // override with covariant return type
|
||||
public LocalDate date(Era<ISOChrono> era, int yearOfEra, int month, int dayOfMonth) {
|
||||
public LocalDate date(Era era, int yearOfEra, int month, int dayOfMonth) {
|
||||
return date(prolepticYear(era, yearOfEra), month, dayOfMonth);
|
||||
}
|
||||
|
||||
@ -219,7 +222,7 @@ public final class ISOChrono extends Chrono<ISOChrono> implements Serializable {
|
||||
* @throws DateTimeException if unable to create the date
|
||||
*/
|
||||
@Override // override with covariant return type
|
||||
public LocalDate dateYearDay(Era<ISOChrono> era, int yearOfEra, int dayOfYear) {
|
||||
public LocalDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
|
||||
return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
|
||||
}
|
||||
|
||||
@ -291,6 +294,7 @@ public final class ISOChrono extends Chrono<ISOChrono> implements Serializable {
|
||||
* @return the zoned date-time, not null
|
||||
* @throws DateTimeException if the result exceeds the supported range
|
||||
*/
|
||||
@Override
|
||||
public ZonedDateTime zonedDateTime(Instant instant, ZoneId zone) {
|
||||
return ZonedDateTime.ofInstant(instant, zone);
|
||||
}
|
||||
@ -373,21 +377,21 @@ public final class ISOChrono extends Chrono<ISOChrono> implements Serializable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int prolepticYear(Era<ISOChrono> era, int yearOfEra) {
|
||||
if (era instanceof ISOEra == false) {
|
||||
throw new DateTimeException("Era must be ISOEra");
|
||||
public int prolepticYear(Era era, int yearOfEra) {
|
||||
if (era instanceof IsoEra == false) {
|
||||
throw new DateTimeException("Era must be IsoEra");
|
||||
}
|
||||
return (era == ISOEra.CE ? yearOfEra : 1 - yearOfEra);
|
||||
return (era == IsoEra.CE ? yearOfEra : 1 - yearOfEra);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Era<ISOChrono> eraOf(int eraValue) {
|
||||
return ISOEra.of(eraValue);
|
||||
public Era eraOf(int eraValue) {
|
||||
return IsoEra.of(eraValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Era<ISOChrono>> eras() {
|
||||
return Arrays.<Era<ISOChrono>>asList(ISOEra.values());
|
||||
public List<Era> eras() {
|
||||
return Arrays.<Era>asList(IsoEra.values());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -59,14 +59,11 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.temporal;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.ERA;
|
||||
|
||||
import java.time.DateTimeException;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.TextStyle;
|
||||
import java.util.Locale;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* An era in the ISO calendar system.
|
||||
@ -75,7 +72,7 @@ import java.util.Locale;
|
||||
* A definition has therefore been created with two eras - 'Current era' (CE) for
|
||||
* years from 0001-01-01 (ISO) and 'Before current era' (BCE) for years before that.
|
||||
* <p>
|
||||
* <b>Do not use {@code ordinal()} to obtain the numeric representation of {@code ISOEra}.
|
||||
* <b>Do not use {@code ordinal()} to obtain the numeric representation of {@code IsoEra}.
|
||||
* Use {@code getValue()} instead.</b>
|
||||
*
|
||||
* <h3>Specification for implementors</h3>
|
||||
@ -83,7 +80,7 @@ import java.util.Locale;
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
enum ISOEra implements Era<ISOChrono> {
|
||||
enum IsoEra implements Era {
|
||||
|
||||
/**
|
||||
* The singleton instance for the era BCE, 'Before Current Era'.
|
||||
@ -102,16 +99,16 @@ enum ISOEra implements Era<ISOChrono> {
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code ISOEra} from an {@code int} value.
|
||||
* Obtains an instance of {@code IsoEra} from an {@code int} value.
|
||||
* <p>
|
||||
* {@code ISOEra} is an enum representing the ISO eras of BCE/CE.
|
||||
* {@code IsoEra} is an enum representing the ISO eras of BCE/CE.
|
||||
* This factory allows the enum to be obtained from the {@code int} value.
|
||||
*
|
||||
* @param era the BCE/CE value to represent, from 0 (BCE) to 1 (CE)
|
||||
* @return the era singleton, not null
|
||||
* @throws DateTimeException if the value is invalid
|
||||
*/
|
||||
public static ISOEra of(int era) {
|
||||
public static IsoEra of(int era) {
|
||||
switch (era) {
|
||||
case 0:
|
||||
return BCE;
|
||||
@ -136,69 +133,20 @@ enum ISOEra implements Era<ISOChrono> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISOChrono getChrono() {
|
||||
return ISOChrono.INSTANCE;
|
||||
public IsoChronology getChronology() {
|
||||
return IsoChronology.INSTANCE;
|
||||
}
|
||||
|
||||
// JDK8 default methods:
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoLocalDate<ISOChrono> date(int year, int month, int day) {
|
||||
return getChrono().date(this, year, month, day);
|
||||
public LocalDate date(int year, int month, int day) {
|
||||
return getChronology().date(this, year, month, day);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<ISOChrono> dateYearDay(int year, int dayOfYear) {
|
||||
return getChrono().dateYearDay(this, year, dayOfYear);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public boolean isSupported(TemporalField field) {
|
||||
if (field instanceof ChronoField) {
|
||||
return field == ERA;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueRange range(TemporalField field) {
|
||||
if (field == ERA) {
|
||||
return field.range();
|
||||
} else if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doRange(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get(TemporalField field) {
|
||||
if (field == ERA) {
|
||||
return getValue();
|
||||
}
|
||||
return range(field).checkValidIntValue(getLong(field), field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(TemporalField field) {
|
||||
if (field == ERA) {
|
||||
return getValue();
|
||||
} else if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@Override
|
||||
public Temporal adjustInto(Temporal temporal) {
|
||||
return temporal.with(ERA, getValue());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public String getText(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendText(ERA, style).toFormatter(locale).print(this);
|
||||
public LocalDate dateYearDay(int year, int dayOfYear) {
|
||||
return getChronology().dateYearDay(this, year, dayOfYear);
|
||||
}
|
||||
|
||||
}
|
||||
@ -54,25 +54,22 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.Chrono;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.Era;
|
||||
import java.time.temporal.ISOChrono;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.time.temporal.Year;
|
||||
import java.time.Year;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import sun.util.calendar.CalendarSystem;
|
||||
import sun.util.calendar.LocalGregorianCalendar;
|
||||
@ -93,7 +90,7 @@ import sun.util.calendar.LocalGregorianCalendar;
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class JapaneseChrono extends Chrono<JapaneseChrono> implements Serializable {
|
||||
public final class JapaneseChronology extends Chronology implements Serializable {
|
||||
// TODO: definition for unknown era may break requirement that year-of-era >= 1
|
||||
|
||||
static final LocalGregorianCalendar JCAL =
|
||||
@ -105,33 +102,33 @@ public final class JapaneseChrono extends Chrono<JapaneseChrono> implements Seri
|
||||
/**
|
||||
* Singleton instance for Japanese chronology.
|
||||
*/
|
||||
public static final JapaneseChrono INSTANCE = new JapaneseChrono();
|
||||
public static final JapaneseChronology INSTANCE = new JapaneseChronology();
|
||||
|
||||
/**
|
||||
* The singleton instance for the before Meiji era ( - 1868-09-07)
|
||||
* which has the value -999.
|
||||
*/
|
||||
public static final Era<JapaneseChrono> ERA_SEIREKI = JapaneseEra.SEIREKI;
|
||||
public static final Era ERA_SEIREKI = JapaneseEra.SEIREKI;
|
||||
/**
|
||||
* The singleton instance for the Meiji era (1868-09-08 - 1912-07-29)
|
||||
* which has the value -1.
|
||||
*/
|
||||
public static final Era<JapaneseChrono> ERA_MEIJI = JapaneseEra.MEIJI;
|
||||
public static final Era ERA_MEIJI = JapaneseEra.MEIJI;
|
||||
/**
|
||||
* The singleton instance for the Taisho era (1912-07-30 - 1926-12-24)
|
||||
* which has the value 0.
|
||||
*/
|
||||
public static final Era<JapaneseChrono> ERA_TAISHO = JapaneseEra.TAISHO;
|
||||
public static final Era ERA_TAISHO = JapaneseEra.TAISHO;
|
||||
/**
|
||||
* The singleton instance for the Showa era (1926-12-25 - 1989-01-07)
|
||||
* which has the value 1.
|
||||
*/
|
||||
public static final Era<JapaneseChrono> ERA_SHOWA = JapaneseEra.SHOWA;
|
||||
public static final Era ERA_SHOWA = JapaneseEra.SHOWA;
|
||||
/**
|
||||
* The singleton instance for the Heisei era (1989-01-08 - current)
|
||||
* which has the value 2.
|
||||
*/
|
||||
public static final Era<JapaneseChrono> ERA_HEISEI = JapaneseEra.HEISEI;
|
||||
public static final Era ERA_HEISEI = JapaneseEra.HEISEI;
|
||||
/**
|
||||
* Serialization version.
|
||||
*/
|
||||
@ -141,7 +138,7 @@ public final class JapaneseChrono extends Chrono<JapaneseChrono> implements Seri
|
||||
/**
|
||||
* Restricted constructor.
|
||||
*/
|
||||
private JapaneseChrono() {
|
||||
private JapaneseChronology() {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -157,8 +154,8 @@ public final class JapaneseChrono extends Chrono<JapaneseChrono> implements Seri
|
||||
/**
|
||||
* Gets the ID of the chronology - 'Japanese'.
|
||||
* <p>
|
||||
* The ID uniquely identifies the {@code Chrono}.
|
||||
* It can be used to lookup the {@code Chrono} using {@link #of(String)}.
|
||||
* The ID uniquely identifies the {@code Chronology}.
|
||||
* It can be used to lookup the {@code Chronology} using {@link #of(String)}.
|
||||
*
|
||||
* @return the chronology ID - 'Japanese'
|
||||
* @see #getCalendarType()
|
||||
@ -173,7 +170,7 @@ public final class JapaneseChrono extends Chrono<JapaneseChrono> implements Seri
|
||||
* <p>
|
||||
* The calendar type is an identifier defined by the
|
||||
* <em>Unicode Locale Data Markup Language (LDML)</em> specification.
|
||||
* It can be used to lookup the {@code Chrono} using {@link #of(String)}.
|
||||
* 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'.
|
||||
*
|
||||
@ -187,7 +184,7 @@ public final class JapaneseChrono extends Chrono<JapaneseChrono> implements Seri
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoLocalDate<JapaneseChrono> date(Era<JapaneseChrono> era, int yearOfEra, int month, int dayOfMonth) {
|
||||
public JapaneseDate date(Era era, int yearOfEra, int month, int dayOfMonth) {
|
||||
if (era instanceof JapaneseEra == false) {
|
||||
throw new DateTimeException("Era must be JapaneseEra");
|
||||
}
|
||||
@ -195,24 +192,59 @@ public final class JapaneseChrono extends Chrono<JapaneseChrono> implements Seri
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<JapaneseChrono> date(int prolepticYear, int month, int dayOfMonth) {
|
||||
public JapaneseDate date(int prolepticYear, int month, int dayOfMonth) {
|
||||
return new JapaneseDate(LocalDate.of(prolepticYear, month, dayOfMonth));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<JapaneseChrono> dateYearDay(int prolepticYear, int dayOfYear) {
|
||||
public JapaneseDate dateYearDay(int prolepticYear, int dayOfYear) {
|
||||
LocalDate date = LocalDate.ofYearDay(prolepticYear, dayOfYear);
|
||||
return date(prolepticYear, date.getMonthValue(), date.getDayOfMonth());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<JapaneseChrono> date(TemporalAccessor temporal) {
|
||||
public JapaneseDate date(TemporalAccessor temporal) {
|
||||
if (temporal instanceof JapaneseDate) {
|
||||
return (JapaneseDate) temporal;
|
||||
}
|
||||
return new JapaneseDate(LocalDate.from(temporal));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JapaneseDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
|
||||
return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JapaneseDate dateNow() {
|
||||
return dateNow(Clock.systemDefaultZone());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JapaneseDate dateNow(ZoneId zone) {
|
||||
return dateNow(Clock.system(zone));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JapaneseDate dateNow(Clock clock) {
|
||||
return date(LocalDate.now(clock));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDateTime<JapaneseDate> localDateTime(TemporalAccessor temporal) {
|
||||
return (ChronoLocalDateTime<JapaneseDate>)super.localDateTime(temporal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoZonedDateTime<JapaneseDate> zonedDateTime(TemporalAccessor temporal) {
|
||||
return (ChronoZonedDateTime<JapaneseDate>)super.zonedDateTime(temporal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoZonedDateTime<JapaneseDate> zonedDateTime(Instant instant, ZoneId zone) {
|
||||
return (ChronoZonedDateTime<JapaneseDate>)super.zonedDateTime(instant, zone);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Checks if the specified year is a leap year.
|
||||
@ -226,11 +258,11 @@ public final class JapaneseChrono extends Chrono<JapaneseChrono> implements Seri
|
||||
*/
|
||||
@Override
|
||||
public boolean isLeapYear(long prolepticYear) {
|
||||
return ISOChrono.INSTANCE.isLeapYear(prolepticYear);
|
||||
return IsoChronology.INSTANCE.isLeapYear(prolepticYear);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int prolepticYear(Era<JapaneseChrono> era, int yearOfEra) {
|
||||
public int prolepticYear(Era era, int yearOfEra) {
|
||||
if (era instanceof JapaneseEra == false) {
|
||||
throw new DateTimeException("Era must be JapaneseEra");
|
||||
}
|
||||
@ -261,13 +293,13 @@ public final class JapaneseChrono extends Chrono<JapaneseChrono> implements Seri
|
||||
* @throws DateTimeException if {@code eraValue} is invalid
|
||||
*/
|
||||
@Override
|
||||
public Era<JapaneseChrono> eraOf(int eraValue) {
|
||||
public Era eraOf(int eraValue) {
|
||||
return JapaneseEra.of(eraValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Era<JapaneseChrono>> eras() {
|
||||
return Arrays.<Era<JapaneseChrono>>asList(JapaneseEra.values());
|
||||
public List<Era> eras() {
|
||||
return Arrays.<Era>asList(JapaneseEra.values());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -54,7 +54,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
|
||||
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
|
||||
@ -63,13 +63,20 @@ import static java.time.temporal.ChronoField.YEAR;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Period;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Calendar;
|
||||
import java.util.Objects;
|
||||
@ -79,19 +86,27 @@ import sun.util.calendar.LocalGregorianCalendar;
|
||||
/**
|
||||
* A date in the Japanese Imperial calendar system.
|
||||
* <p>
|
||||
* This implements {@code ChronoLocalDate} for the
|
||||
* {@linkplain JapaneseChrono Japanese Imperial calendar}.
|
||||
* This date operates using the {@linkplain JapaneseChronology Japanese Imperial calendar}.
|
||||
* This calendar system is primarily used in Japan.
|
||||
* <p>
|
||||
* The Japanese Imperial calendar system is the same as the ISO calendar system
|
||||
* apart from the era-based year numbering. The proleptic-year is defined to be
|
||||
* equal to the ISO proleptic-year.
|
||||
* <p>
|
||||
* For example, the Japanese year "Heisei 24" corresponds to ISO year "2012".<br>
|
||||
* Calling {@code japaneseDate.get(YEAR_OF_ERA)} will return 24.<br>
|
||||
* Calling {@code japaneseDate.get(YEAR)} will return 2012.<br>
|
||||
* Calling {@code japaneseDate.get(ERA)} will return 2, corresponding to
|
||||
* {@code JapaneseChronology.ERA_HEISEI}.<br>
|
||||
*
|
||||
* <h3>Specification for implementors</h3>
|
||||
* This class is immutable and thread-safe.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
final class JapaneseDate
|
||||
extends ChronoDateImpl<JapaneseChrono>
|
||||
implements ChronoLocalDate<JapaneseChrono>, Serializable {
|
||||
// this class is package-scoped so that future conversion to public
|
||||
// would not change serialization
|
||||
public final class JapaneseDate
|
||||
extends ChronoDateImpl<JapaneseDate>
|
||||
implements ChronoLocalDate<JapaneseDate>, Serializable {
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
@ -111,29 +126,159 @@ final class JapaneseDate
|
||||
*/
|
||||
private transient int yearOfEra;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains an instance of {@code JapaneseDate} from the era, year-of-era,
|
||||
* month-of-year and day-of-month.
|
||||
* Obtains the current {@code JapaneseDate} from the system clock in the default time-zone.
|
||||
* <p>
|
||||
* This will query the {@link Clock#systemDefaultZone() system clock} in the default
|
||||
* time-zone to obtain the current date.
|
||||
* <p>
|
||||
* Using this method will prevent the ability to use an alternate clock for testing
|
||||
* because the clock is hard-coded.
|
||||
*
|
||||
* @param era the era to represent, not null
|
||||
* @param yearOfEra the year-of-era to represent
|
||||
* @param month the month-of-year to represent
|
||||
* @param dayOfMonth the day-of-month to represent, from 1 to 31
|
||||
* @return the Japanese date, never null
|
||||
* @throws DateTimeException if the value of any field is out of range, or
|
||||
* if the day-of-month is invalid for the month-year
|
||||
* @return the current date using the system clock and default time-zone, not null
|
||||
*/
|
||||
public static JapaneseDate now() {
|
||||
return now(Clock.systemDefaultZone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current {@code JapaneseDate} from the system clock in the specified time-zone.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* Using this method will prevent the ability to use an alternate clock for testing
|
||||
* because the clock is hard-coded.
|
||||
*
|
||||
* @param zone the zone ID to use, not null
|
||||
* @return the current date using the system clock, not null
|
||||
*/
|
||||
public static JapaneseDate now(ZoneId zone) {
|
||||
return now(Clock.system(zone));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current {@code JapaneseDate} from the specified clock.
|
||||
* <p>
|
||||
* 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 {@linkplain Clock dependency injection}.
|
||||
*
|
||||
* @param clock the clock to use, not null
|
||||
* @return the current date, not null
|
||||
* @throws DateTimeException if the current date cannot be obtained
|
||||
*/
|
||||
public static JapaneseDate now(Clock clock) {
|
||||
return JapaneseChronology.INSTANCE.date(LocalDate.now(clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code JapaneseDate} representing a date in the Japanese calendar
|
||||
* system from the era, year-of-era, month-of-year and day-of-month fields.
|
||||
* <p>
|
||||
* This returns a {@code JapaneseDate} with the specified fields.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param era the Japanese era, not null
|
||||
* @param yearOfEra the Japanese year-of-era
|
||||
* @param month the Japanese month-of-year, from 1 to 12
|
||||
* @param dayOfMonth the Japanese day-of-month, from 1 to 31
|
||||
* @return the date in Japanese calendar system, not null
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year,
|
||||
* or if the date is not a Japanese era
|
||||
*/
|
||||
public static JapaneseDate of(Era era, int yearOfEra, int month, int dayOfMonth) {
|
||||
if (era instanceof JapaneseEra == false) {
|
||||
throw new DateTimeException("Era must be JapaneseEra");
|
||||
}
|
||||
return JapaneseDate.of((JapaneseEra) era, yearOfEra, month, dayOfMonth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code JapaneseDate} representing a date in the Japanese calendar
|
||||
* system from the proleptic-year, month-of-year and day-of-month fields.
|
||||
* <p>
|
||||
* This returns a {@code JapaneseDate} with the specified fields.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param prolepticYear the Japanese proleptic-year
|
||||
* @param month the Japanese month-of-year, from 1 to 12
|
||||
* @param dayOfMonth the Japanese day-of-month, from 1 to 31
|
||||
* @return the date in Japanese calendar system, not null
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static JapaneseDate of(int prolepticYear, int month, int dayOfMonth) {
|
||||
return new JapaneseDate(LocalDate.of(prolepticYear, month, dayOfMonth));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code JapaneseDate} representing a date in the Japanese calendar
|
||||
* system from the proleptic-year and day-of-year fields.
|
||||
* <p>
|
||||
* This returns a {@code JapaneseDate} with the specified fields.
|
||||
* The day must be valid for the year, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param prolepticYear the chronology proleptic-year
|
||||
* @param dayOfYear the chronology day-of-year, from 1 to 366
|
||||
* @return the date in Japanese calendar system, not null
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-year is invalid for the year
|
||||
*/
|
||||
public static JapaneseDate ofYearDay(int prolepticYear, int dayOfYear) {
|
||||
LocalDate date = LocalDate.ofYearDay(prolepticYear, dayOfYear);
|
||||
return of(prolepticYear, date.getMonthValue(), date.getDayOfMonth());
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code JapaneseDate} representing a date in the Japanese calendar
|
||||
* system from the era, year-of-era, month-of-year and day-of-month fields.
|
||||
* <p>
|
||||
* This returns a {@code JapaneseDate} with the specified fields.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param era the Japanese era, not null
|
||||
* @param yearOfEra the Japanese year-of-era
|
||||
* @param month the Japanese month-of-year, from 1 to 12
|
||||
* @param dayOfMonth the Japanese day-of-month, from 1 to 31
|
||||
* @return the date in Japanese calendar system, not null
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
static JapaneseDate of(JapaneseEra era, int yearOfEra, int month, int dayOfMonth) {
|
||||
Objects.requireNonNull(era, "era");
|
||||
LocalGregorianCalendar.Date jdate = JapaneseChrono.JCAL.newCalendarDate(null);
|
||||
LocalGregorianCalendar.Date jdate = JapaneseChronology.JCAL.newCalendarDate(null);
|
||||
jdate.setEra(era.getPrivateEra()).setDate(yearOfEra, month, dayOfMonth);
|
||||
if (!JapaneseChrono.JCAL.validate(jdate)) {
|
||||
if (!JapaneseChronology.JCAL.validate(jdate)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
LocalDate date = LocalDate.of(jdate.getNormalizedYear(), month, dayOfMonth);
|
||||
return new JapaneseDate(era, yearOfEra, date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code JapaneseDate} from a temporal object.
|
||||
* <p>
|
||||
* This obtains a date in the Japanese calendar system based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code JapaneseDate}.
|
||||
* <p>
|
||||
* The conversion typically uses the {@link ChronoField#EPOCH_DAY EPOCH_DAY}
|
||||
* field, which is standardized across calendar systems.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used as a query via method reference, {@code JapaneseDate::from}.
|
||||
*
|
||||
* @param temporal the temporal object to convert, not null
|
||||
* @return the date in Japanese calendar system, not null
|
||||
* @throws DateTimeException if unable to convert to a {@code JapaneseDate}
|
||||
*/
|
||||
public static JapaneseDate from(TemporalAccessor temporal) {
|
||||
return JapaneseChronology.INSTANCE.date(temporal);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Creates an instance from an ISO date.
|
||||
@ -163,8 +308,8 @@ final class JapaneseDate
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public JapaneseChrono getChrono() {
|
||||
return JapaneseChrono.INSTANCE;
|
||||
public JapaneseChronology getChronology() {
|
||||
return JapaneseChronology.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -183,15 +328,15 @@ final class JapaneseDate
|
||||
case YEAR_OF_ERA:
|
||||
return actualRange(Calendar.YEAR);
|
||||
}
|
||||
return getChrono().range(f);
|
||||
return getChronology().range(f);
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doRange(this);
|
||||
return field.rangeRefinedBy(this);
|
||||
}
|
||||
|
||||
private ValueRange actualRange(int calendarField) {
|
||||
Calendar jcal = Calendar.getInstance(JapaneseChrono.LOCALE);
|
||||
Calendar jcal = Calendar.getInstance(JapaneseChronology.LOCALE);
|
||||
jcal.set(Calendar.ERA, era.getValue() + JapaneseEra.ERA_OFFSET);
|
||||
jcal.set(yearOfEra, isoDate.getMonthValue() - 1, isoDate.getDayOfMonth());
|
||||
return ValueRange.of(jcal.getActualMinimum(calendarField),
|
||||
@ -208,13 +353,13 @@ final class JapaneseDate
|
||||
return era.getValue();
|
||||
case DAY_OF_YEAR: {
|
||||
LocalGregorianCalendar.Date jdate = toPrivateJapaneseDate(isoDate);
|
||||
return JapaneseChrono.JCAL.getDayOfYear(jdate);
|
||||
return JapaneseChronology.JCAL.getDayOfYear(jdate);
|
||||
}
|
||||
}
|
||||
// TODO: review other fields
|
||||
return isoDate.getLong(field);
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -224,14 +369,14 @@ final class JapaneseDate
|
||||
* @return a {@code LocalGregorianCalendar.Date}, not null
|
||||
*/
|
||||
private static LocalGregorianCalendar.Date toPrivateJapaneseDate(LocalDate isoDate) {
|
||||
LocalGregorianCalendar.Date jdate = JapaneseChrono.JCAL.newCalendarDate(null);
|
||||
LocalGregorianCalendar.Date jdate = JapaneseChronology.JCAL.newCalendarDate(null);
|
||||
sun.util.calendar.Era sunEra = JapaneseEra.privateEraFrom(isoDate);
|
||||
int year = isoDate.getYear();
|
||||
if (sunEra != null) {
|
||||
year -= sunEra.getSinceDate().getYear() - 1;
|
||||
}
|
||||
jdate.setEra(sunEra).setYear(year).setMonth(isoDate.getMonthValue()).setDayOfMonth(isoDate.getDayOfMonth());
|
||||
JapaneseChrono.JCAL.normalize(jdate);
|
||||
JapaneseChronology.JCAL.normalize(jdate);
|
||||
return jdate;
|
||||
}
|
||||
|
||||
@ -266,6 +411,40 @@ final class JapaneseDate
|
||||
return (JapaneseDate) ChronoLocalDate.super.with(field, newValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Era getEra() {
|
||||
return era;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public JapaneseDate with(TemporalAdjuster adjuster) {
|
||||
return (JapaneseDate)super.with(adjuster);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public JapaneseDate plus(TemporalAmount amount) {
|
||||
return (JapaneseDate)super.plus(amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public JapaneseDate minus(TemporalAmount amount) {
|
||||
return (JapaneseDate)super.minus(amount);
|
||||
}
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a copy of this date with the year altered.
|
||||
@ -282,7 +461,7 @@ final class JapaneseDate
|
||||
* @throws DateTimeException if {@code year} is invalid
|
||||
*/
|
||||
private JapaneseDate withYear(JapaneseEra era, int yearOfEra) {
|
||||
int year = JapaneseChrono.INSTANCE.prolepticYear(era, yearOfEra);
|
||||
int year = JapaneseChronology.INSTANCE.prolepticYear(era, yearOfEra);
|
||||
return with(isoDate.withYear(year));
|
||||
}
|
||||
|
||||
@ -314,15 +493,60 @@ final class JapaneseDate
|
||||
return with(isoDate.plusMonths(months));
|
||||
}
|
||||
|
||||
@Override
|
||||
JapaneseDate plusWeeks(long weeksToAdd) {
|
||||
return with(isoDate.plusWeeks(weeksToAdd));
|
||||
}
|
||||
|
||||
@Override
|
||||
JapaneseDate plusDays(long days) {
|
||||
return with(isoDate.plusDays(days));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JapaneseDate plus(long amountToAdd, TemporalUnit unit) {
|
||||
return (JapaneseDate)super.plus(amountToAdd, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JapaneseDate minus(long amountToAdd, TemporalUnit unit) {
|
||||
return (JapaneseDate)super.minus(amountToAdd, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
JapaneseDate minusYears(long yearsToSubtract) {
|
||||
return (JapaneseDate)super.minusYears(yearsToSubtract);
|
||||
}
|
||||
|
||||
@Override
|
||||
JapaneseDate minusMonths(long monthsToSubtract) {
|
||||
return (JapaneseDate)super.minusMonths(monthsToSubtract);
|
||||
}
|
||||
|
||||
@Override
|
||||
JapaneseDate minusWeeks(long weeksToSubtract) {
|
||||
return (JapaneseDate)super.minusWeeks(weeksToSubtract);
|
||||
}
|
||||
|
||||
@Override
|
||||
JapaneseDate minusDays(long daysToSubtract) {
|
||||
return (JapaneseDate)super.minusDays(daysToSubtract);
|
||||
}
|
||||
|
||||
private JapaneseDate with(LocalDate newDate) {
|
||||
return (newDate.equals(isoDate) ? this : new JapaneseDate(newDate));
|
||||
}
|
||||
|
||||
@Override // for javadoc and covariant return type
|
||||
public final ChronoLocalDateTime<JapaneseDate> atTime(LocalTime localTime) {
|
||||
return (ChronoLocalDateTime<JapaneseDate>)super.atTime(localTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Period periodUntil(ChronoLocalDate<?> endDate) {
|
||||
return isoDate.periodUntil(endDate);
|
||||
}
|
||||
|
||||
@Override // override for performance
|
||||
public long toEpochDay() {
|
||||
return isoDate.toEpochDay();
|
||||
@ -343,13 +567,13 @@ final class JapaneseDate
|
||||
|
||||
@Override // override for performance
|
||||
public int hashCode() {
|
||||
return getChrono().getId().hashCode() ^ isoDate.hashCode();
|
||||
return getChronology().getId().hashCode() ^ isoDate.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (era == JapaneseEra.SEIREKI) {
|
||||
return getChrono().getId() + " " + isoDate.toString();
|
||||
return getChronology().getId() + " " + isoDate.toString();
|
||||
}
|
||||
return super.toString();
|
||||
}
|
||||
@ -360,18 +584,17 @@ final class JapaneseDate
|
||||
}
|
||||
|
||||
void writeExternal(DataOutput out) throws IOException {
|
||||
// JapaneseChrono is implicit in the JAPANESE_DATE_TYPE
|
||||
// JapaneseChronology is implicit in the JAPANESE_DATE_TYPE
|
||||
out.writeInt(get(YEAR));
|
||||
out.writeByte(get(MONTH_OF_YEAR));
|
||||
out.writeByte(get(DAY_OF_MONTH));
|
||||
}
|
||||
|
||||
static ChronoLocalDate<JapaneseChrono> readExternal(DataInput in) throws IOException {
|
||||
static JapaneseDate readExternal(DataInput in) throws IOException {
|
||||
int year = in.readInt();
|
||||
int month = in.readByte();
|
||||
int dayOfMonth = in.readByte();
|
||||
return JapaneseChrono.INSTANCE.date(year, month, dayOfMonth);
|
||||
return JapaneseChronology.INSTANCE.date(year, month, dayOfMonth);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -54,7 +54,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@ -64,7 +64,6 @@ import java.io.ObjectStreamException;
|
||||
import java.io.Serializable;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.Era;
|
||||
import java.util.Arrays;
|
||||
|
||||
import sun.util.calendar.CalendarDate;
|
||||
@ -86,7 +85,7 @@ import sun.util.calendar.CalendarDate;
|
||||
* @since 1.8
|
||||
*/
|
||||
final class JapaneseEra
|
||||
implements Era<JapaneseChrono>, Serializable {
|
||||
implements Era, Serializable {
|
||||
|
||||
// The offset value to 0-based index from the era value.
|
||||
// i.e., getValue() + ERA_OFFSET == 0-based index; except that -999 is mapped to zero
|
||||
@ -133,7 +132,7 @@ final class JapaneseEra
|
||||
private static final JapaneseEra[] KNOWN_ERAS;
|
||||
|
||||
static {
|
||||
sun.util.calendar.Era[] sunEras = JapaneseChrono.JCAL.getEras();
|
||||
sun.util.calendar.Era[] sunEras = JapaneseChronology.JCAL.getEras();
|
||||
ERA_CONFIG = new sun.util.calendar.Era[sunEras.length + 1];
|
||||
for (int i = 1; i < ERA_CONFIG.length; i++) {
|
||||
ERA_CONFIG[i] = sunEras[i - 1];
|
||||
@ -292,8 +291,8 @@ final class JapaneseEra
|
||||
}
|
||||
|
||||
@Override
|
||||
public JapaneseChrono getChrono() {
|
||||
return JapaneseChrono.INSTANCE;
|
||||
public JapaneseChronology getChronology() {
|
||||
return JapaneseChronology.INSTANCE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -54,18 +54,17 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.YEAR;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.Chrono;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.Era;
|
||||
import java.time.temporal.ISOChrono;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Arrays;
|
||||
@ -77,7 +76,7 @@ import java.util.Locale;
|
||||
* <p>
|
||||
* This chronology defines the rules of the Minguo calendar system.
|
||||
* This calendar system is primarily used in the Republic of China, often known as Taiwan.
|
||||
* Dates are aligned such that {@code 0001-01-01 (Minguo)} is {@code 1911-01-01 (ISO)}.
|
||||
* Dates are aligned such that {@code 0001-01-01 (Minguo)} is {@code 1912-01-01 (ISO)}.
|
||||
* <p>
|
||||
* The fields are defined as follows:
|
||||
* <p><ul>
|
||||
@ -100,22 +99,22 @@ import java.util.Locale;
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class MinguoChrono extends Chrono<MinguoChrono> implements Serializable {
|
||||
public final class MinguoChronology extends Chronology implements Serializable {
|
||||
|
||||
/**
|
||||
* Singleton instance for the Minguo chronology.
|
||||
*/
|
||||
public static final MinguoChrono INSTANCE = new MinguoChrono();
|
||||
public static final MinguoChronology INSTANCE = new MinguoChronology();
|
||||
|
||||
/**
|
||||
* The singleton instance for the era ROC.
|
||||
*/
|
||||
public static final Era<MinguoChrono> ERA_ROC = MinguoEra.ROC;
|
||||
public static final Era ERA_ROC = MinguoEra.ROC;
|
||||
|
||||
/**
|
||||
* The singleton instance for the era BEFORE_ROC.
|
||||
*/
|
||||
public static final Era<MinguoChrono> ERA_BEFORE_ROC = MinguoEra.BEFORE_ROC;
|
||||
public static final Era ERA_BEFORE_ROC = MinguoEra.BEFORE_ROC;
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
@ -129,7 +128,7 @@ public final class MinguoChrono extends Chrono<MinguoChrono> implements Serializ
|
||||
/**
|
||||
* Restricted constructor.
|
||||
*/
|
||||
private MinguoChrono() {
|
||||
private MinguoChronology() {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,8 +144,8 @@ public final class MinguoChrono extends Chrono<MinguoChrono> implements Serializ
|
||||
/**
|
||||
* Gets the ID of the chronology - 'Minguo'.
|
||||
* <p>
|
||||
* The ID uniquely identifies the {@code Chrono}.
|
||||
* It can be used to lookup the {@code Chrono} using {@link #of(String)}.
|
||||
* The ID uniquely identifies the {@code Chronology}.
|
||||
* It can be used to lookup the {@code Chronology} using {@link #of(String)}.
|
||||
*
|
||||
* @return the chronology ID - 'Minguo'
|
||||
* @see #getCalendarType()
|
||||
@ -161,7 +160,7 @@ public final class MinguoChrono extends Chrono<MinguoChrono> implements Serializ
|
||||
* <p>
|
||||
* The calendar type is an identifier defined by the
|
||||
* <em>Unicode Locale Data Markup Language (LDML)</em> specification.
|
||||
* It can be used to lookup the {@code Chrono} using {@link #of(String)}.
|
||||
* 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'.
|
||||
*
|
||||
@ -175,22 +174,62 @@ public final class MinguoChrono extends Chrono<MinguoChrono> implements Serializ
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoLocalDate<MinguoChrono> date(int prolepticYear, int month, int dayOfMonth) {
|
||||
public MinguoDate date(int prolepticYear, int month, int dayOfMonth) {
|
||||
return new MinguoDate(LocalDate.of(prolepticYear + YEARS_DIFFERENCE, month, dayOfMonth));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<MinguoChrono> dateYearDay(int prolepticYear, int dayOfYear) {
|
||||
public MinguoDate dateYearDay(int prolepticYear, int dayOfYear) {
|
||||
return new MinguoDate(LocalDate.ofYearDay(prolepticYear + YEARS_DIFFERENCE, dayOfYear));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<MinguoChrono> date(TemporalAccessor temporal) {
|
||||
public MinguoDate date(TemporalAccessor temporal) {
|
||||
if (temporal instanceof MinguoDate) {
|
||||
return (MinguoDate) temporal;
|
||||
}
|
||||
return new MinguoDate(LocalDate.from(temporal));
|
||||
}
|
||||
@Override
|
||||
public MinguoDate date(Era era, int yearOfEra, int month, int dayOfMonth) {
|
||||
return date(prolepticYear(era, yearOfEra), month, dayOfMonth);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinguoDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
|
||||
return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinguoDate dateNow() {
|
||||
return dateNow(Clock.systemDefaultZone());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinguoDate dateNow(ZoneId zone) {
|
||||
return dateNow(Clock.system(zone));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinguoDate dateNow(Clock clock) {
|
||||
return date(LocalDate.now(clock));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDateTime<MinguoDate> localDateTime(TemporalAccessor temporal) {
|
||||
return (ChronoLocalDateTime<MinguoDate>)super.localDateTime(temporal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoZonedDateTime<MinguoDate> zonedDateTime(TemporalAccessor temporal) {
|
||||
return (ChronoZonedDateTime<MinguoDate>)super.zonedDateTime(temporal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoZonedDateTime<MinguoDate> zonedDateTime(Instant instant, ZoneId zone) {
|
||||
return (ChronoZonedDateTime<MinguoDate>)super.zonedDateTime(instant, zone);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@ -205,11 +244,11 @@ public final class MinguoChrono extends Chrono<MinguoChrono> implements Serializ
|
||||
*/
|
||||
@Override
|
||||
public boolean isLeapYear(long prolepticYear) {
|
||||
return ISOChrono.INSTANCE.isLeapYear(prolepticYear + YEARS_DIFFERENCE);
|
||||
return IsoChronology.INSTANCE.isLeapYear(prolepticYear + YEARS_DIFFERENCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int prolepticYear(Era<MinguoChrono> era, int yearOfEra) {
|
||||
public int prolepticYear(Era era, int yearOfEra) {
|
||||
if (era instanceof MinguoEra == false) {
|
||||
throw new DateTimeException("Era must be MinguoEra");
|
||||
}
|
||||
@ -217,13 +256,13 @@ public final class MinguoChrono extends Chrono<MinguoChrono> implements Serializ
|
||||
}
|
||||
|
||||
@Override
|
||||
public Era<MinguoChrono> eraOf(int eraValue) {
|
||||
public Era eraOf(int eraValue) {
|
||||
return MinguoEra.of(eraValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Era<MinguoChrono>> eras() {
|
||||
return Arrays.<Era<MinguoChrono>>asList(MinguoEra.values());
|
||||
public List<Era> eras() {
|
||||
return Arrays.<Era>asList(MinguoEra.values());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -54,9 +54,9 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.calendar.MinguoChrono.YEARS_DIFFERENCE;
|
||||
import static java.time.chrono.MinguoChronology.YEARS_DIFFERENCE;
|
||||
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
|
||||
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
|
||||
import static java.time.temporal.ChronoField.YEAR;
|
||||
@ -65,29 +65,37 @@ import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Period;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A date in the Minguo calendar system.
|
||||
* <p>
|
||||
* This implements {@code ChronoLocalDate} for the {@link MinguoChrono Minguo calendar}.
|
||||
* This date operates using the {@linkplain MinguoChronology Minguo calendar}.
|
||||
* This calendar system is primarily used in the Republic of China, often known as Taiwan.
|
||||
* Dates are aligned such that {@code 0001-01-01 (Minguo)} is {@code 1912-01-01 (ISO)}.
|
||||
*
|
||||
* <h3>Specification for implementors</h3>
|
||||
* This class is immutable and thread-safe.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
final class MinguoDate
|
||||
extends ChronoDateImpl<MinguoChrono>
|
||||
implements ChronoLocalDate<MinguoChrono>, Serializable {
|
||||
// this class is package-scoped so that future conversion to public
|
||||
// would not change serialization
|
||||
public final class MinguoDate
|
||||
extends ChronoDateImpl<MinguoDate>
|
||||
implements ChronoLocalDate<MinguoDate>, Serializable {
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
@ -99,6 +107,93 @@ final class MinguoDate
|
||||
*/
|
||||
private final LocalDate isoDate;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains the current {@code MinguoDate} from the system clock in the default time-zone.
|
||||
* <p>
|
||||
* This will query the {@link Clock#systemDefaultZone() system clock} in the default
|
||||
* time-zone to obtain the current date.
|
||||
* <p>
|
||||
* Using this method will prevent the ability to use an alternate clock for testing
|
||||
* because the clock is hard-coded.
|
||||
*
|
||||
* @return the current date using the system clock and default time-zone, not null
|
||||
*/
|
||||
public static MinguoDate now() {
|
||||
return now(Clock.systemDefaultZone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current {@code MinguoDate} from the system clock in the specified time-zone.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* Using this method will prevent the ability to use an alternate clock for testing
|
||||
* because the clock is hard-coded.
|
||||
*
|
||||
* @param zone the zone ID to use, not null
|
||||
* @return the current date using the system clock, not null
|
||||
*/
|
||||
public static MinguoDate now(ZoneId zone) {
|
||||
return now(Clock.system(zone));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current {@code MinguoDate} from the specified clock.
|
||||
* <p>
|
||||
* 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 {@linkplain Clock dependency injection}.
|
||||
*
|
||||
* @param clock the clock to use, not null
|
||||
* @return the current date, not null
|
||||
* @throws DateTimeException if the current date cannot be obtained
|
||||
*/
|
||||
public static MinguoDate now(Clock clock) {
|
||||
return MinguoChronology.INSTANCE.date(LocalDate.now(clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code MinguoDate} representing a date in the Minguo calendar
|
||||
* system from the proleptic-year, month-of-year and day-of-month fields.
|
||||
* <p>
|
||||
* This returns a {@code MinguoDate} with the specified fields.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param prolepticYear the Minguo proleptic-year
|
||||
* @param month the Minguo month-of-year, from 1 to 12
|
||||
* @param dayOfMonth the Minguo day-of-month, from 1 to 31
|
||||
* @return the date in Minguo calendar system, not null
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static MinguoDate of(int prolepticYear, int month, int dayOfMonth) {
|
||||
return new MinguoDate(LocalDate.of(prolepticYear + YEARS_DIFFERENCE, month, dayOfMonth));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code MinguoDate} from a temporal object.
|
||||
* <p>
|
||||
* This obtains a date in the Minguo calendar system based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code MinguoDate}.
|
||||
* <p>
|
||||
* The conversion typically uses the {@link ChronoField#EPOCH_DAY EPOCH_DAY}
|
||||
* field, which is standardized across calendar systems.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used as a query via method reference, {@code MinguoDate::from}.
|
||||
*
|
||||
* @param temporal the temporal object to convert, not null
|
||||
* @return the date in Minguo calendar system, not null
|
||||
* @throws DateTimeException if unable to convert to a {@code MinguoDate}
|
||||
*/
|
||||
public static MinguoDate from(TemporalAccessor temporal) {
|
||||
return MinguoChronology.INSTANCE.date(temporal);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Creates an instance from an ISO date.
|
||||
*
|
||||
@ -111,8 +206,8 @@ final class MinguoDate
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public MinguoChrono getChrono() {
|
||||
return MinguoChrono.INSTANCE;
|
||||
public MinguoChronology getChronology() {
|
||||
return MinguoChronology.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -136,11 +231,11 @@ final class MinguoDate
|
||||
return ValueRange.of(1, max);
|
||||
}
|
||||
}
|
||||
return getChrono().range(f);
|
||||
return getChronology().range(f);
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doRange(this);
|
||||
return field.rangeRefinedBy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -158,7 +253,7 @@ final class MinguoDate
|
||||
}
|
||||
return isoDate.getLong(field);
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
private int getProlepticYear() {
|
||||
@ -194,6 +289,36 @@ final class MinguoDate
|
||||
return (MinguoDate) ChronoLocalDate.super.with(field, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public MinguoDate with(TemporalAdjuster adjuster) {
|
||||
return (MinguoDate)super.with(adjuster);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public MinguoDate plus(TemporalAmount amount) {
|
||||
return (MinguoDate)super.plus(amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public MinguoDate minus(TemporalAmount amount) {
|
||||
return (MinguoDate)super.minus(amount);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
MinguoDate plusYears(long years) {
|
||||
@ -210,10 +335,55 @@ final class MinguoDate
|
||||
return with(isoDate.plusDays(days));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinguoDate plus(long amountToAdd, TemporalUnit unit) {
|
||||
return (MinguoDate)super.plus(amountToAdd, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinguoDate minus(long amountToAdd, TemporalUnit unit) {
|
||||
return (MinguoDate)super.minus(amountToAdd, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
MinguoDate plusWeeks(long weeksToAdd) {
|
||||
return (MinguoDate)super.plusWeeks(weeksToAdd);
|
||||
}
|
||||
|
||||
@Override
|
||||
MinguoDate minusYears(long yearsToSubtract) {
|
||||
return (MinguoDate)super.minusYears(yearsToSubtract);
|
||||
}
|
||||
|
||||
@Override
|
||||
MinguoDate minusMonths(long monthsToSubtract) {
|
||||
return (MinguoDate)super.minusMonths(monthsToSubtract);
|
||||
}
|
||||
|
||||
@Override
|
||||
MinguoDate minusWeeks(long weeksToSubtract) {
|
||||
return (MinguoDate)super.minusWeeks(weeksToSubtract);
|
||||
}
|
||||
|
||||
@Override
|
||||
MinguoDate minusDays(long daysToSubtract) {
|
||||
return (MinguoDate)super.minusDays(daysToSubtract);
|
||||
}
|
||||
|
||||
private MinguoDate with(LocalDate newDate) {
|
||||
return (newDate.equals(isoDate) ? this : new MinguoDate(newDate));
|
||||
}
|
||||
|
||||
@Override // for javadoc and covariant return type
|
||||
public final ChronoLocalDateTime<MinguoDate> atTime(LocalTime localTime) {
|
||||
return (ChronoLocalDateTime<MinguoDate>)super.atTime(localTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Period periodUntil(ChronoLocalDate<?> endDate) {
|
||||
return isoDate.periodUntil(endDate);
|
||||
}
|
||||
|
||||
@Override // override for performance
|
||||
public long toEpochDay() {
|
||||
return isoDate.toEpochDay();
|
||||
@ -234,7 +404,7 @@ final class MinguoDate
|
||||
|
||||
@Override // override for performance
|
||||
public int hashCode() {
|
||||
return getChrono().getId().hashCode() ^ isoDate.hashCode();
|
||||
return getChronology().getId().hashCode() ^ isoDate.hashCode();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -243,19 +413,17 @@ final class MinguoDate
|
||||
}
|
||||
|
||||
void writeExternal(DataOutput out) throws IOException {
|
||||
// MinguoChrono is implicit in the MINGUO_DATE_TYPE
|
||||
// MinguoChronology is implicit in the MINGUO_DATE_TYPE
|
||||
out.writeInt(get(YEAR));
|
||||
out.writeByte(get(MONTH_OF_YEAR));
|
||||
out.writeByte(get(DAY_OF_MONTH));
|
||||
|
||||
}
|
||||
|
||||
static ChronoLocalDate<MinguoChrono> readExternal(DataInput in) throws IOException {
|
||||
static ChronoLocalDate readExternal(DataInput in) throws IOException {
|
||||
int year = in.readInt();
|
||||
int month = in.readByte();
|
||||
int dayOfMonth = in.readByte();
|
||||
return MinguoChrono.INSTANCE.date(year, month, dayOfMonth);
|
||||
return MinguoChronology.INSTANCE.date(year, month, dayOfMonth);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -54,23 +54,12 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
|
||||
import static java.time.temporal.ChronoField.ERA;
|
||||
package java.time.chrono;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.TextStyle;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.Era;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* An era in the Minguo calendar system.
|
||||
@ -86,7 +75,7 @@ import java.util.Locale;
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
enum MinguoEra implements Era<MinguoChrono> {
|
||||
enum MinguoEra implements Era {
|
||||
|
||||
/**
|
||||
* The singleton instance for the era BEFORE_ROC, 'Before Republic of China'.
|
||||
@ -135,72 +124,23 @@ enum MinguoEra implements Era<MinguoChrono> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinguoChrono getChrono() {
|
||||
return MinguoChrono.INSTANCE;
|
||||
public MinguoChronology getChronology() {
|
||||
return MinguoChronology.INSTANCE;
|
||||
}
|
||||
|
||||
// JDK8 default methods:
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoLocalDate<MinguoChrono> date(int year, int month, int day) {
|
||||
return getChrono().date(this, year, month, day);
|
||||
public MinguoDate date(int year, int month, int day) {
|
||||
return (MinguoDate)(getChronology().date(this, year, month, day));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<MinguoChrono> dateYearDay(int year, int dayOfYear) {
|
||||
return getChrono().dateYearDay(this, year, dayOfYear);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public boolean isSupported(TemporalField field) {
|
||||
if (field instanceof ChronoField) {
|
||||
return field == ERA;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueRange range(TemporalField field) {
|
||||
if (field == ERA) {
|
||||
return field.range();
|
||||
} else if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doRange(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get(TemporalField field) {
|
||||
if (field == ERA) {
|
||||
return getValue();
|
||||
}
|
||||
return range(field).checkValidIntValue(getLong(field), field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(TemporalField field) {
|
||||
if (field == ERA) {
|
||||
return getValue();
|
||||
} else if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
public MinguoDate dateYearDay(int year, int dayOfYear) {
|
||||
return (MinguoDate)(getChronology().dateYearDay(this, year, dayOfYear));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@Override
|
||||
public Temporal adjustInto(Temporal temporal) {
|
||||
return temporal.with(ERA, getValue());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public String getText(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendText(ERA, style).toFormatter(locale).print(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
private Object writeReplace() {
|
||||
return new Ser(Ser.MINGUO_ERA_TYPE, this);
|
||||
}
|
||||
@ -54,7 +54,7 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
@ -72,7 +72,7 @@ import java.time.LocalDateTime;
|
||||
* This class wraps the object being serialized, and takes a byte representing the type of the class to
|
||||
* be serialized. This byte can also be used for versioning the serialization format. In this case another
|
||||
* byte flag would be used in order to specify an alternative version of the type format.
|
||||
* For example {@code JAPANESE_DATE_TYPE_VERSION_2 = 21}.
|
||||
* For example {@code CHRONO_TYPE_VERSION_2 = 21}
|
||||
* <p>
|
||||
* In order to serialise the object it writes its byte and then calls back to the appropriate class where
|
||||
* the serialisation is performed. In order to deserialise the object it read in the type byte, switching
|
||||
@ -94,16 +94,19 @@ final class Ser implements Externalizable {
|
||||
/**
|
||||
* Serialization version.
|
||||
*/
|
||||
private static final long serialVersionUID = 7857518227608961174L;
|
||||
private static final long serialVersionUID = -6103370247208168577L;
|
||||
|
||||
static final byte JAPANESE_DATE_TYPE = 1;
|
||||
static final byte JAPANESE_ERA_TYPE = 2;
|
||||
static final byte HIJRAH_DATE_TYPE = 3;
|
||||
static final byte HIJRAH_ERA_TYPE = 4;
|
||||
static final byte MINGUO_DATE_TYPE = 5;
|
||||
static final byte MINGUO_ERA_TYPE = 6;
|
||||
static final byte THAIBUDDHIST_DATE_TYPE = 7;
|
||||
static final byte THAIBUDDHIST_ERA_TYPE = 8;
|
||||
static final byte CHRONO_TYPE = 1;
|
||||
static final byte CHRONO_LOCAL_DATE_TIME_TYPE = 2;
|
||||
static final byte CHRONO_ZONE_DATE_TIME_TYPE = 3;
|
||||
static final byte JAPANESE_DATE_TYPE = 4;
|
||||
static final byte JAPANESE_ERA_TYPE = 5;
|
||||
static final byte HIJRAH_DATE_TYPE = 6;
|
||||
static final byte HIJRAH_ERA_TYPE = 7;
|
||||
static final byte MINGUO_DATE_TYPE = 8;
|
||||
static final byte MINGUO_ERA_TYPE = 9;
|
||||
static final byte THAIBUDDHIST_DATE_TYPE = 10;
|
||||
static final byte THAIBUDDHIST_ERA_TYPE = 11;
|
||||
|
||||
/** The type being serialized. */
|
||||
private byte type;
|
||||
@ -141,6 +144,15 @@ final class Ser implements Externalizable {
|
||||
private static void writeInternal(byte type, Object object, ObjectOutput out) throws IOException {
|
||||
out.writeByte(type);
|
||||
switch (type) {
|
||||
case CHRONO_TYPE:
|
||||
((Chronology) object).writeExternal(out);
|
||||
break;
|
||||
case CHRONO_LOCAL_DATE_TIME_TYPE:
|
||||
((ChronoLocalDateTimeImpl<?>) object).writeExternal(out);
|
||||
break;
|
||||
case CHRONO_ZONE_DATE_TIME_TYPE:
|
||||
((ChronoZonedDateTimeImpl<?>) object).writeExternal(out);
|
||||
break;
|
||||
case JAPANESE_DATE_TYPE:
|
||||
((JapaneseDate) object).writeExternal(out);
|
||||
break;
|
||||
@ -189,6 +201,9 @@ final class Ser implements Externalizable {
|
||||
|
||||
private static Object readInternal(byte type, ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
switch (type) {
|
||||
case CHRONO_TYPE: return Chronology.readExternal(in);
|
||||
case CHRONO_LOCAL_DATE_TIME_TYPE: return ChronoLocalDateTimeImpl.readExternal(in);
|
||||
case CHRONO_ZONE_DATE_TIME_TYPE: return ChronoZonedDateTimeImpl.readExternal(in);
|
||||
case JAPANESE_DATE_TYPE: return JapaneseDate.readExternal(in);
|
||||
case JAPANESE_ERA_TYPE: return JapaneseEra.readExternal(in);
|
||||
case HIJRAH_DATE_TYPE: return HijrahDate.readExternal(in);
|
||||
@ -197,8 +212,7 @@ final class Ser implements Externalizable {
|
||||
case MINGUO_ERA_TYPE: return MinguoEra.readExternal(in);
|
||||
case THAIBUDDHIST_DATE_TYPE: return ThaiBuddhistDate.readExternal(in);
|
||||
case THAIBUDDHIST_ERA_TYPE: return ThaiBuddhistEra.readExternal(in);
|
||||
default:
|
||||
throw new StreamCorruptedException("Unknown serialized type");
|
||||
default: throw new StreamCorruptedException("Unknown serialized type");
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,18 +54,17 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.YEAR;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.Chrono;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.Era;
|
||||
import java.time.temporal.ISOChrono;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Arrays;
|
||||
@ -101,21 +100,21 @@ import java.util.Locale;
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class ThaiBuddhistChrono extends Chrono<ThaiBuddhistChrono> implements Serializable {
|
||||
public final class ThaiBuddhistChronology extends Chronology implements Serializable {
|
||||
|
||||
/**
|
||||
* Singleton instance of the Buddhist chronology.
|
||||
*/
|
||||
public static final ThaiBuddhistChrono INSTANCE = new ThaiBuddhistChrono();
|
||||
public static final ThaiBuddhistChronology INSTANCE = new ThaiBuddhistChronology();
|
||||
/**
|
||||
* The singleton instance for the era before the current one - Before Buddhist -
|
||||
* which has the value 0.
|
||||
*/
|
||||
public static final Era<ThaiBuddhistChrono> ERA_BEFORE_BE = ThaiBuddhistEra.BEFORE_BE;
|
||||
public static final Era ERA_BEFORE_BE = ThaiBuddhistEra.BEFORE_BE;
|
||||
/**
|
||||
* The singleton instance for the current era - Buddhist - which has the value 1.
|
||||
*/
|
||||
public static final Era<ThaiBuddhistChrono> ERA_BE = ThaiBuddhistEra.BE;
|
||||
public static final Era ERA_BE = ThaiBuddhistEra.BE;
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
@ -164,7 +163,7 @@ public final class ThaiBuddhistChrono extends Chrono<ThaiBuddhistChrono> impleme
|
||||
/**
|
||||
* Restricted constructor.
|
||||
*/
|
||||
private ThaiBuddhistChrono() {
|
||||
private ThaiBuddhistChronology() {
|
||||
}
|
||||
|
||||
/**
|
||||
@ -180,8 +179,8 @@ public final class ThaiBuddhistChrono extends Chrono<ThaiBuddhistChrono> impleme
|
||||
/**
|
||||
* Gets the ID of the chronology - 'ThaiBuddhist'.
|
||||
* <p>
|
||||
* The ID uniquely identifies the {@code Chrono}.
|
||||
* It can be used to lookup the {@code Chrono} using {@link #of(String)}.
|
||||
* The ID uniquely identifies the {@code Chronology}.
|
||||
* It can be used to lookup the {@code Chronology} using {@link #of(String)}.
|
||||
*
|
||||
* @return the chronology ID - 'ThaiBuddhist'
|
||||
* @see #getCalendarType()
|
||||
@ -196,7 +195,7 @@ public final class ThaiBuddhistChrono extends Chrono<ThaiBuddhistChrono> impleme
|
||||
* <p>
|
||||
* The calendar type is an identifier defined by the
|
||||
* <em>Unicode Locale Data Markup Language (LDML)</em> specification.
|
||||
* It can be used to lookup the {@code Chrono} using {@link #of(String)}.
|
||||
* 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'.
|
||||
*
|
||||
@ -210,22 +209,62 @@ public final class ThaiBuddhistChrono extends Chrono<ThaiBuddhistChrono> impleme
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoLocalDate<ThaiBuddhistChrono> date(int prolepticYear, int month, int dayOfMonth) {
|
||||
public ThaiBuddhistDate date(int prolepticYear, int month, int dayOfMonth) {
|
||||
return new ThaiBuddhistDate(LocalDate.of(prolepticYear - YEARS_DIFFERENCE, month, dayOfMonth));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<ThaiBuddhistChrono> dateYearDay(int prolepticYear, int dayOfYear) {
|
||||
public ThaiBuddhistDate dateYearDay(int prolepticYear, int dayOfYear) {
|
||||
return new ThaiBuddhistDate(LocalDate.ofYearDay(prolepticYear - YEARS_DIFFERENCE, dayOfYear));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<ThaiBuddhistChrono> date(TemporalAccessor temporal) {
|
||||
public ThaiBuddhistDate date(TemporalAccessor temporal) {
|
||||
if (temporal instanceof ThaiBuddhistDate) {
|
||||
return (ThaiBuddhistDate) temporal;
|
||||
}
|
||||
return new ThaiBuddhistDate(LocalDate.from(temporal));
|
||||
}
|
||||
@Override
|
||||
public ThaiBuddhistDate date(Era era, int yearOfEra, int month, int dayOfMonth) {
|
||||
return date(prolepticYear(era, yearOfEra), month, dayOfMonth);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThaiBuddhistDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
|
||||
return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThaiBuddhistDate dateNow() {
|
||||
return dateNow(Clock.systemDefaultZone());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThaiBuddhistDate dateNow(ZoneId zone) {
|
||||
return dateNow(Clock.system(zone));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThaiBuddhistDate dateNow(Clock clock) {
|
||||
return date(LocalDate.now(clock));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDateTime<ThaiBuddhistDate> localDateTime(TemporalAccessor temporal) {
|
||||
return (ChronoLocalDateTime<ThaiBuddhistDate>)super.localDateTime(temporal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoZonedDateTime<ThaiBuddhistDate> zonedDateTime(TemporalAccessor temporal) {
|
||||
return (ChronoZonedDateTime<ThaiBuddhistDate>)super.zonedDateTime(temporal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoZonedDateTime<ThaiBuddhistDate> zonedDateTime(Instant instant, ZoneId zone) {
|
||||
return (ChronoZonedDateTime<ThaiBuddhistDate>)super.zonedDateTime(instant, zone);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@ -240,11 +279,11 @@ public final class ThaiBuddhistChrono extends Chrono<ThaiBuddhistChrono> impleme
|
||||
*/
|
||||
@Override
|
||||
public boolean isLeapYear(long prolepticYear) {
|
||||
return ISOChrono.INSTANCE.isLeapYear(prolepticYear - YEARS_DIFFERENCE);
|
||||
return IsoChronology.INSTANCE.isLeapYear(prolepticYear - YEARS_DIFFERENCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int prolepticYear(Era<ThaiBuddhistChrono> era, int yearOfEra) {
|
||||
public int prolepticYear(Era era, int yearOfEra) {
|
||||
if (era instanceof ThaiBuddhistEra == false) {
|
||||
throw new DateTimeException("Era must be BuddhistEra");
|
||||
}
|
||||
@ -252,13 +291,13 @@ public final class ThaiBuddhistChrono extends Chrono<ThaiBuddhistChrono> impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
public Era<ThaiBuddhistChrono> eraOf(int eraValue) {
|
||||
public Era eraOf(int eraValue) {
|
||||
return ThaiBuddhistEra.of(eraValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Era<ThaiBuddhistChrono>> eras() {
|
||||
return Arrays.<Era<ThaiBuddhistChrono>>asList(ThaiBuddhistEra.values());
|
||||
public List<Era> eras() {
|
||||
return Arrays.<Era>asList(ThaiBuddhistEra.values());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -54,9 +54,9 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.calendar.ThaiBuddhistChrono.YEARS_DIFFERENCE;
|
||||
import static java.time.chrono.ThaiBuddhistChronology.YEARS_DIFFERENCE;
|
||||
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
|
||||
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
|
||||
import static java.time.temporal.ChronoField.YEAR;
|
||||
@ -65,29 +65,37 @@ import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.time.Clock;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Period;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalAdjuster;
|
||||
import java.time.temporal.TemporalAmount;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A date in the Thai Buddhist calendar system.
|
||||
* <p>
|
||||
* This implements {@code ChronoLocalDate} for the {@link ThaiBuddhistChrono Thai Buddhist calendar}.
|
||||
* This date operates using the {@linkplain ThaiBuddhistChronology Thai Buddhist calendar}.
|
||||
* This calendar system is primarily used in Thailand.
|
||||
* Dates are aligned such that {@code 2484-01-01 (Buddhist)} is {@code 1941-01-01 (ISO)}.
|
||||
*
|
||||
* <h3>Specification for implementors</h3>
|
||||
* This class is immutable and thread-safe.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
final class ThaiBuddhistDate
|
||||
extends ChronoDateImpl<ThaiBuddhistChrono>
|
||||
implements ChronoLocalDate<ThaiBuddhistChrono>, Serializable {
|
||||
// this class is package-scoped so that future conversion to public
|
||||
// would not change serialization
|
||||
public final class ThaiBuddhistDate
|
||||
extends ChronoDateImpl<ThaiBuddhistDate>
|
||||
implements ChronoLocalDate<ThaiBuddhistDate>, Serializable {
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
@ -99,6 +107,93 @@ final class ThaiBuddhistDate
|
||||
*/
|
||||
private final LocalDate isoDate;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Obtains the current {@code ThaiBuddhistDate} from the system clock in the default time-zone.
|
||||
* <p>
|
||||
* This will query the {@link Clock#systemDefaultZone() system clock} in the default
|
||||
* time-zone to obtain the current date.
|
||||
* <p>
|
||||
* Using this method will prevent the ability to use an alternate clock for testing
|
||||
* because the clock is hard-coded.
|
||||
*
|
||||
* @return the current date using the system clock and default time-zone, not null
|
||||
*/
|
||||
public static ThaiBuddhistDate now() {
|
||||
return now(Clock.systemDefaultZone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current {@code ThaiBuddhistDate} from the system clock in the specified time-zone.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* Using this method will prevent the ability to use an alternate clock for testing
|
||||
* because the clock is hard-coded.
|
||||
*
|
||||
* @param zone the zone ID to use, not null
|
||||
* @return the current date using the system clock, not null
|
||||
*/
|
||||
public static ThaiBuddhistDate now(ZoneId zone) {
|
||||
return now(Clock.system(zone));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the current {@code ThaiBuddhistDate} from the specified clock.
|
||||
* <p>
|
||||
* 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 {@linkplain Clock dependency injection}.
|
||||
*
|
||||
* @param clock the clock to use, not null
|
||||
* @return the current date, not null
|
||||
* @throws DateTimeException if the current date cannot be obtained
|
||||
*/
|
||||
public static ThaiBuddhistDate now(Clock clock) {
|
||||
return ThaiBuddhistChronology.INSTANCE.date(LocalDate.now(clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code ThaiBuddhistDate} representing a date in the Thai Buddhist calendar
|
||||
* system from the proleptic-year, month-of-year and day-of-month fields.
|
||||
* <p>
|
||||
* This returns a {@code ThaiBuddhistDate} with the specified fields.
|
||||
* The day must be valid for the year and month, otherwise an exception will be thrown.
|
||||
*
|
||||
* @param prolepticYear the Thai Buddhist proleptic-year
|
||||
* @param month the Thai Buddhist month-of-year, from 1 to 12
|
||||
* @param dayOfMonth the Thai Buddhist day-of-month, from 1 to 31
|
||||
* @return the date in Thai Buddhist calendar system, not null
|
||||
* @throws DateTimeException if the value of any field is out of range,
|
||||
* or if the day-of-month is invalid for the month-year
|
||||
*/
|
||||
public static ThaiBuddhistDate of(int prolepticYear, int month, int dayOfMonth) {
|
||||
return new ThaiBuddhistDate(LocalDate.of(prolepticYear - YEARS_DIFFERENCE, month, dayOfMonth));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@code ThaiBuddhistDate} from a temporal object.
|
||||
* <p>
|
||||
* This obtains a date in the Thai Buddhist calendar system based on the specified temporal.
|
||||
* A {@code TemporalAccessor} represents an arbitrary set of date and time information,
|
||||
* which this factory converts to an instance of {@code ThaiBuddhistDate}.
|
||||
* <p>
|
||||
* The conversion typically uses the {@link ChronoField#EPOCH_DAY EPOCH_DAY}
|
||||
* field, which is standardized across calendar systems.
|
||||
* <p>
|
||||
* This method matches the signature of the functional interface {@link TemporalQuery}
|
||||
* allowing it to be used as a query via method reference, {@code ThaiBuddhistDate::from}.
|
||||
*
|
||||
* @param temporal the temporal object to convert, not null
|
||||
* @return the date in Thai Buddhist calendar system, not null
|
||||
* @throws DateTimeException if unable to convert to a {@code ThaiBuddhistDate}
|
||||
*/
|
||||
public static ThaiBuddhistDate from(TemporalAccessor temporal) {
|
||||
return ThaiBuddhistChronology.INSTANCE.date(temporal);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Creates an instance from an ISO date.
|
||||
*
|
||||
@ -111,8 +206,8 @@ final class ThaiBuddhistDate
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ThaiBuddhistChrono getChrono() {
|
||||
return ThaiBuddhistChrono.INSTANCE;
|
||||
public ThaiBuddhistChronology getChronology() {
|
||||
return ThaiBuddhistChronology.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -136,11 +231,11 @@ final class ThaiBuddhistDate
|
||||
return ValueRange.of(1, max);
|
||||
}
|
||||
}
|
||||
return getChrono().range(f);
|
||||
return getChronology().range(f);
|
||||
}
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doRange(this);
|
||||
return field.rangeRefinedBy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -158,7 +253,7 @@ final class ThaiBuddhistDate
|
||||
}
|
||||
return isoDate.getLong(field);
|
||||
}
|
||||
return field.doGet(this);
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
private int getProlepticYear() {
|
||||
@ -194,6 +289,36 @@ final class ThaiBuddhistDate
|
||||
return (ThaiBuddhistDate) ChronoLocalDate.super.with(field, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public ThaiBuddhistDate with(TemporalAdjuster adjuster) {
|
||||
return (ThaiBuddhistDate)super.with(adjuster);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public ThaiBuddhistDate plus(TemporalAmount amount) {
|
||||
return (ThaiBuddhistDate)super.plus(amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws DateTimeException {@inheritDoc}
|
||||
* @throws ArithmeticException {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public ThaiBuddhistDate minus(TemporalAmount amount) {
|
||||
return (ThaiBuddhistDate)super.minus(amount);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
ThaiBuddhistDate plusYears(long years) {
|
||||
@ -205,15 +330,60 @@ final class ThaiBuddhistDate
|
||||
return with(isoDate.plusMonths(months));
|
||||
}
|
||||
|
||||
@Override
|
||||
ThaiBuddhistDate plusWeeks(long weeksToAdd) {
|
||||
return (ThaiBuddhistDate)super.plusWeeks(weeksToAdd);
|
||||
}
|
||||
|
||||
@Override
|
||||
ThaiBuddhistDate plusDays(long days) {
|
||||
return with(isoDate.plusDays(days));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThaiBuddhistDate plus(long amountToAdd, TemporalUnit unit) {
|
||||
return (ThaiBuddhistDate)super.plus(amountToAdd, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThaiBuddhistDate minus(long amountToAdd, TemporalUnit unit) {
|
||||
return (ThaiBuddhistDate)super.minus(amountToAdd, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
ThaiBuddhistDate minusYears(long yearsToSubtract) {
|
||||
return (ThaiBuddhistDate)super.minusYears(yearsToSubtract);
|
||||
}
|
||||
|
||||
@Override
|
||||
ThaiBuddhistDate minusMonths(long monthsToSubtract) {
|
||||
return (ThaiBuddhistDate)super.minusMonths(monthsToSubtract);
|
||||
}
|
||||
|
||||
@Override
|
||||
ThaiBuddhistDate minusWeeks(long weeksToSubtract) {
|
||||
return (ThaiBuddhistDate)super.minusWeeks(weeksToSubtract);
|
||||
}
|
||||
|
||||
@Override
|
||||
ThaiBuddhistDate minusDays(long daysToSubtract) {
|
||||
return (ThaiBuddhistDate)super.minusDays(daysToSubtract);
|
||||
}
|
||||
|
||||
private ThaiBuddhistDate with(LocalDate newDate) {
|
||||
return (newDate.equals(isoDate) ? this : new ThaiBuddhistDate(newDate));
|
||||
}
|
||||
|
||||
@Override // for javadoc and covariant return type
|
||||
public final ChronoLocalDateTime<ThaiBuddhistDate> atTime(LocalTime localTime) {
|
||||
return (ChronoLocalDateTime<ThaiBuddhistDate>)super.atTime(localTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Period periodUntil(ChronoLocalDate<?> endDate) {
|
||||
return isoDate.periodUntil(endDate);
|
||||
}
|
||||
|
||||
@Override // override for performance
|
||||
public long toEpochDay() {
|
||||
return isoDate.toEpochDay();
|
||||
@ -234,7 +404,7 @@ final class ThaiBuddhistDate
|
||||
|
||||
@Override // override for performance
|
||||
public int hashCode() {
|
||||
return getChrono().getId().hashCode() ^ isoDate.hashCode();
|
||||
return getChronology().getId().hashCode() ^ isoDate.hashCode();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -243,17 +413,17 @@ final class ThaiBuddhistDate
|
||||
}
|
||||
|
||||
void writeExternal(DataOutput out) throws IOException {
|
||||
// MinguoChrono is implicit in the THAIBUDDHIST_DATE_TYPE
|
||||
// ThaiBuddhistChronology is implicit in the THAIBUDDHIST_DATE_TYPE
|
||||
out.writeInt(this.get(YEAR));
|
||||
out.writeByte(this.get(MONTH_OF_YEAR));
|
||||
out.writeByte(this.get(DAY_OF_MONTH));
|
||||
}
|
||||
|
||||
static ChronoLocalDate<ThaiBuddhistChrono> readExternal(DataInput in) throws IOException {
|
||||
static ThaiBuddhistDate readExternal(DataInput in) throws IOException {
|
||||
int year = in.readInt();
|
||||
int month = in.readByte();
|
||||
int dayOfMonth = in.readByte();
|
||||
return ThaiBuddhistChrono.INSTANCE.date(year, month, dayOfMonth);
|
||||
return ThaiBuddhistChronology.INSTANCE.date(year, month, dayOfMonth);
|
||||
}
|
||||
|
||||
}
|
||||
@ -54,23 +54,13 @@
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package java.time.calendar;
|
||||
package java.time.chrono;
|
||||
|
||||
import static java.time.temporal.ChronoField.ERA;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.TextStyle;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoLocalDate;
|
||||
import java.time.temporal.Era;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* An era in the Thai Buddhist calendar system.
|
||||
@ -85,7 +75,7 @@ import java.util.Locale;
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
enum ThaiBuddhistEra implements Era<ThaiBuddhistChrono> {
|
||||
enum ThaiBuddhistEra implements Era {
|
||||
|
||||
/**
|
||||
* The singleton instance for the era before the current one, 'Before Buddhist Era',
|
||||
@ -134,69 +124,20 @@ enum ThaiBuddhistEra implements Era<ThaiBuddhistChrono> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThaiBuddhistChrono getChrono() {
|
||||
return ThaiBuddhistChrono.INSTANCE;
|
||||
public ThaiBuddhistChronology getChronology() {
|
||||
return ThaiBuddhistChronology.INSTANCE;
|
||||
}
|
||||
|
||||
// JDK8 default methods:
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public ChronoLocalDate<ThaiBuddhistChrono> date(int year, int month, int day) {
|
||||
return getChrono().date(this, year, month, day);
|
||||
public ThaiBuddhistDate date(int year, int month, int day) {
|
||||
return (ThaiBuddhistDate)(getChronology().date(this, year, month, day));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChronoLocalDate<ThaiBuddhistChrono> dateYearDay(int year, int dayOfYear) {
|
||||
return getChrono().dateYearDay(this, year, dayOfYear);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public boolean isSupported(TemporalField field) {
|
||||
if (field instanceof ChronoField) {
|
||||
return field == ERA;
|
||||
}
|
||||
return field != null && field.doIsSupported(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueRange range(TemporalField field) {
|
||||
if (field == ERA) {
|
||||
return field.range();
|
||||
} else if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doRange(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get(TemporalField field) {
|
||||
if (field == ERA) {
|
||||
return getValue();
|
||||
}
|
||||
return range(field).checkValidIntValue(getLong(field), field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(TemporalField field) {
|
||||
if (field == ERA) {
|
||||
return getValue();
|
||||
} else if (field instanceof ChronoField) {
|
||||
throw new DateTimeException("Unsupported field: " + field.getName());
|
||||
}
|
||||
return field.doGet(this);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@Override
|
||||
public Temporal adjustInto(Temporal temporal) {
|
||||
return temporal.with(ERA, getValue());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public String getText(TextStyle style, Locale locale) {
|
||||
return new DateTimeFormatterBuilder().appendText(ERA, style).toFormatter(locale).print(this);
|
||||
public ThaiBuddhistDate dateYearDay(int year, int dayOfYear) {
|
||||
return (ThaiBuddhistDate)(getChronology().dateYearDay(this, year, dayOfYear));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
171
jdk/src/share/classes/java/time/chrono/package-info.java
Normal file
171
jdk/src/share/classes/java/time/chrono/package-info.java
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file:
|
||||
*
|
||||
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of JSR-310 nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Generic API for calendar systems other than the default ISO.
|
||||
* </p>
|
||||
* <p>
|
||||
* The main API is based around the calendar system defined in ISO-8601.
|
||||
* However, there are other calendar systems, and this package provides basic support for them.
|
||||
* The alternate calendars are provided in the {@link java.time.chrono} package.
|
||||
* </p>
|
||||
* <p>
|
||||
* A calendar system is defined by the {@link java.time.chrono.Chronology} interface,
|
||||
* while a date in a calendar system is defined by the {@link java.time.chrono.ChronoLocalDate} interface.
|
||||
* </p>
|
||||
* <p>
|
||||
* It is intended that applications use the main API whenever possible, including code to read and write
|
||||
* from a persistent data store, such as a database, and to send dates and times across a network.
|
||||
* The "chrono" classes are then used at the user interface level to deal with localized input/output.
|
||||
* See {@link java.time.chrono.ChronoLocalDate ChronoLocalDate}
|
||||
* for a full discussion of the issues.
|
||||
* </p>
|
||||
* <p>
|
||||
* Using non-ISO calendar systems in an application introduces significant extra complexity.
|
||||
* Ensure that the warnings and recommendations in {@code ChronoLocalDate} have been read before
|
||||
* working with the "chrono" interfaces.
|
||||
* </p>
|
||||
* <p>
|
||||
* The supported calendar systems includes:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>{@link java.time.chrono.HijrahChronology Hijrah calendar}</li>
|
||||
* <li>{@link java.time.chrono.JapaneseChronology Japanese calendar}</li>
|
||||
* <li>{@link java.time.chrono.MinguoChronology Minguo calendar}</li>
|
||||
* <li>{@link java.time.chrono.ThaiBuddhistChronology Thai Buddhist calendar}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>Example</h3>
|
||||
* <p>
|
||||
* This example lists todays date for all of the available calendars.
|
||||
* </p>
|
||||
* <pre>
|
||||
* // Enumerate the list of available calendars and print todays date for each.
|
||||
* Set<Chronology> chronos = Chronology.getAvailableChronologies();
|
||||
* for (Chronology chrono : chronos) {
|
||||
* ChronoLocalDate<?> date = chrono.dateNow();
|
||||
* System.out.printf(" %20s: %s%n", chrono.getId(), date.toString());
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* This example creates and uses a date in a named non-ISO calendar system.
|
||||
* </p>
|
||||
* <pre>
|
||||
* // Print the Thai Buddhist date
|
||||
* ChronoLocalDate<?> now1 = Chronology.of("ThaiBuddhist").dateNow();
|
||||
* int day = now1.get(ChronoField.DAY_OF_MONTH);
|
||||
* int dow = now1.get(ChronoField.DAY_OF_WEEK);
|
||||
* int month = now1.get(ChronoField.MONTH_OF_YEAR);
|
||||
* int year = now1.get(ChronoField.YEAR);
|
||||
* System.out.printf(" Today is %s %s %d-%s-%d%n", now1.getChronology().getId(),
|
||||
* dow, day, month, year);
|
||||
* // Print today's date and the last day of the year for the Thai Buddhist Calendar.
|
||||
* ChronoLocalDate<?> first = now1
|
||||
* .with(ChronoField.DAY_OF_MONTH, 1)
|
||||
* .with(ChronoField.MONTH_OF_YEAR, 1);
|
||||
* ChronoLocalDate<?> last = first
|
||||
* .plus(1, ChronoUnit.YEARS)
|
||||
* .minus(1, ChronoUnit.DAYS);
|
||||
* System.out.printf(" %s: 1st of year: %s; end of year: %s%n", last.getChronology().getId(),
|
||||
* first, last);
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* This example creates and uses a date in a specific ThaiBuddhist calendar system.
|
||||
* </p>
|
||||
* <pre>
|
||||
* // Print the Thai Buddhist date
|
||||
* ThaiBuddhistDate now1 = ThaiBuddhistDate.now();
|
||||
* int day = now1.get(ChronoField.DAY_OF_MONTH);
|
||||
* int dow = now1.get(ChronoField.DAY_OF_WEEK);
|
||||
* int month = now1.get(ChronoField.MONTH_OF_YEAR);
|
||||
* int year = now1.get(ChronoField.YEAR);
|
||||
* System.out.printf(" Today is %s %s %d-%s-%d%n", now1.getChronology().getId(),
|
||||
* dow, day, month, year);
|
||||
*
|
||||
* // Print today's date and the last day of the year for the Thai Buddhist Calendar.
|
||||
* ThaiBuddhistDate first = now1
|
||||
* .with(ChronoField.DAY_OF_MONTH, 1)
|
||||
* .with(ChronoField.MONTH_OF_YEAR, 1);
|
||||
* ThaiBuddhistDate last = first
|
||||
* .plus(1, ChronoUnit.YEARS)
|
||||
* .minus(1, ChronoUnit.DAYS);
|
||||
* System.out.printf(" %s: 1st of year: %s; end of year: %s%n", last.getChronology().getId(),
|
||||
* first, last);
|
||||
* </pre>
|
||||
*
|
||||
* <h3>Package specification</h3>
|
||||
* <p>
|
||||
* Unless otherwise noted, passing a null argument to a constructor or method in any class or interface
|
||||
* in this package will cause a {@link java.lang.NullPointerException NullPointerException} to be thrown.
|
||||
* The Javadoc "@param" definition is used to summarise the null-behavior.
|
||||
* The "@throws {@link java.lang.NullPointerException}" is not explicitly documented in each method.
|
||||
* </p>
|
||||
* <p>
|
||||
* All calculations should check for numeric overflow and throw either an {@link java.lang.ArithmeticException}
|
||||
* or a {@link java.time.DateTimeException}.
|
||||
* </p>
|
||||
* @since JDK1.8
|
||||
*/
|
||||
package java.time.chrono;
|
||||
@ -74,9 +74,9 @@ import static java.time.temporal.ChronoField.DAY_OF_WEEK;
|
||||
import static java.time.temporal.ChronoField.DAY_OF_YEAR;
|
||||
import static java.time.temporal.ChronoField.EPOCH_DAY;
|
||||
import static java.time.temporal.ChronoField.EPOCH_MONTH;
|
||||
import static java.time.temporal.ChronoField.ERA;
|
||||
import static java.time.temporal.ChronoField.HOUR_OF_AMPM;
|
||||
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
|
||||
import static java.time.temporal.ChronoField.INSTANT_SECONDS;
|
||||
import static java.time.temporal.ChronoField.MICRO_OF_DAY;
|
||||
import static java.time.temporal.ChronoField.MICRO_OF_SECOND;
|
||||
import static java.time.temporal.ChronoField.MILLI_OF_DAY;
|
||||
@ -86,34 +86,33 @@ import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
|
||||
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
|
||||
import static java.time.temporal.ChronoField.NANO_OF_DAY;
|
||||
import static java.time.temporal.ChronoField.NANO_OF_SECOND;
|
||||
import static java.time.temporal.ChronoField.OFFSET_SECONDS;
|
||||
import static java.time.temporal.ChronoField.SECOND_OF_DAY;
|
||||
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
|
||||
import static java.time.temporal.ChronoField.YEAR;
|
||||
import static java.time.temporal.ChronoField.YEAR_OF_ERA;
|
||||
|
||||
import java.time.DateTimeException;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.temporal.Chrono;
|
||||
import java.time.chrono.ChronoLocalDate;
|
||||
import java.time.chrono.Chronology;
|
||||
import java.time.chrono.Era;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.chrono.JapaneseChronology;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.Queries;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Builder that can holds date and time fields and related date and time objects.
|
||||
@ -121,12 +120,11 @@ import java.util.Set;
|
||||
* <b>This class still needs major revision before JDK1.8 ships.</b>
|
||||
* <p>
|
||||
* The builder is used to hold onto different elements of date and time.
|
||||
* It is designed as two separate maps:
|
||||
* It holds two kinds of object:
|
||||
* <p><ul>
|
||||
* <li>from {@link java.time.temporal.TemporalField} to {@code long} value, where the value may be
|
||||
* outside the valid range for the field
|
||||
* <li>from {@code Class} to {@link java.time.temporal.TemporalAccessor}, holding larger scale objects
|
||||
* like {@code LocalDateTime}.
|
||||
* <li>a {@code Map} from {@link TemporalField} to {@code long} value, where the
|
||||
* value may be outside the valid range for the field
|
||||
* <li>a list of objects, such as {@code Chronology} or {@code ZoneId}
|
||||
* </ul><p>
|
||||
*
|
||||
* <h3>Specification for implementors</h3>
|
||||
@ -135,7 +133,7 @@ import java.util.Set;
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class DateTimeBuilder
|
||||
final class DateTimeBuilder
|
||||
implements TemporalAccessor, Cloneable {
|
||||
|
||||
/**
|
||||
@ -147,9 +145,21 @@ public final class DateTimeBuilder
|
||||
*/
|
||||
private final EnumMap<ChronoField, Long> standardFields = new EnumMap<ChronoField, Long>(ChronoField.class);
|
||||
/**
|
||||
* The list of complete date-time objects.
|
||||
* The chronology.
|
||||
*/
|
||||
private final List<Object> objects = new ArrayList<>(2);
|
||||
private Chronology chrono;
|
||||
/**
|
||||
* The zone.
|
||||
*/
|
||||
private ZoneId zone;
|
||||
/**
|
||||
* The date.
|
||||
*/
|
||||
private LocalDate date;
|
||||
/**
|
||||
* The time.
|
||||
*/
|
||||
private LocalTime time;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
@ -158,74 +168,7 @@ public final class DateTimeBuilder
|
||||
public DateTimeBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of the builder with a single field-value.
|
||||
* <p>
|
||||
* This is equivalent to using {@link #addFieldValue(TemporalField, long)} on an empty builder.
|
||||
*
|
||||
* @param field the field to add, not null
|
||||
* @param value the value to add, not null
|
||||
*/
|
||||
public DateTimeBuilder(TemporalField field, long value) {
|
||||
addFieldValue(field, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of the builder.
|
||||
*
|
||||
* @param zone the zone, may be null
|
||||
* @param chrono the chronology, may be null
|
||||
*/
|
||||
public DateTimeBuilder(ZoneId zone, Chrono<?> chrono) {
|
||||
if (zone != null) {
|
||||
objects.add(zone);
|
||||
}
|
||||
if (chrono != null) {
|
||||
objects.add(chrono);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the map of field-value pairs in the builder.
|
||||
*
|
||||
* @return a modifiable copy of the field-value map, not null
|
||||
*/
|
||||
public Map<TemporalField, Long> getFieldValueMap() {
|
||||
Map<TemporalField, Long> map = new HashMap<TemporalField, Long>(standardFields);
|
||||
if (otherFields != null) {
|
||||
map.putAll(otherFields);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the specified field is present in the builder.
|
||||
*
|
||||
* @param field the field to find in the field-value map, not null
|
||||
* @return true if the field is present
|
||||
*/
|
||||
public boolean containsFieldValue(TemporalField field) {
|
||||
Objects.requireNonNull(field, "field");
|
||||
return standardFields.containsKey(field) || (otherFields != null && otherFields.containsKey(field));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the specified field from the builder.
|
||||
*
|
||||
* @param field the field to query in the field-value map, not null
|
||||
* @return the value of the field, may be out of range
|
||||
* @throws DateTimeException if the field is not present
|
||||
*/
|
||||
public long getFieldValue(TemporalField field) {
|
||||
Objects.requireNonNull(field, "field");
|
||||
Long value = getFieldValue0(field);
|
||||
if (value == null) {
|
||||
throw new DateTimeException("Field not found: " + field);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private Long getFieldValue0(TemporalField field) {
|
||||
if (field instanceof ChronoField) {
|
||||
return standardFields.get(field);
|
||||
@ -235,18 +178,6 @@ public final class DateTimeBuilder
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the specified field from the builder ensuring it is valid.
|
||||
*
|
||||
* @param field the field to query in the field-value map, not null
|
||||
* @return the value of the field, may be out of range
|
||||
* @throws DateTimeException if the field is not present
|
||||
*/
|
||||
public long getValidFieldValue(TemporalField field) {
|
||||
long value = getFieldValue(field);
|
||||
return field.range().checkValidValue(value, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a field-value pair to the builder.
|
||||
* <p>
|
||||
@ -261,7 +192,7 @@ public final class DateTimeBuilder
|
||||
* @return {@code this}, for method chaining
|
||||
* @throws DateTimeException if the field is already present with a different value
|
||||
*/
|
||||
public DateTimeBuilder addFieldValue(TemporalField field, long value) {
|
||||
DateTimeBuilder addFieldValue(TemporalField field, long value) {
|
||||
Objects.requireNonNull(field, "field");
|
||||
Long old = getFieldValue0(field); // check first for better error message
|
||||
if (old != null && old.longValue() != value) {
|
||||
@ -282,125 +213,21 @@ public final class DateTimeBuilder
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a field-value pair from the builder.
|
||||
* <p>
|
||||
* This removes a field, which must exist, from the builder.
|
||||
* See {@link #removeFieldValues(TemporalField...)} for a version which does not throw an exception
|
||||
*
|
||||
* @param field the field to remove, not null
|
||||
* @return the previous value of the field
|
||||
* @throws DateTimeException if the field is not found
|
||||
*/
|
||||
public long removeFieldValue(TemporalField field) {
|
||||
Objects.requireNonNull(field, "field");
|
||||
Long value = null;
|
||||
if (field instanceof ChronoField) {
|
||||
value = standardFields.remove(field);
|
||||
} else if (otherFields != null) {
|
||||
value = otherFields.remove(field);
|
||||
}
|
||||
if (value == null) {
|
||||
throw new DateTimeException("Field not found: " + field);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Removes a list of fields from the builder.
|
||||
* <p>
|
||||
* This removes the specified fields from the builder.
|
||||
* No exception is thrown if the fields are not present.
|
||||
*
|
||||
* @param fields the fields to remove, not null
|
||||
*/
|
||||
public void removeFieldValues(TemporalField... fields) {
|
||||
for (TemporalField field : fields) {
|
||||
if (field instanceof ChronoField) {
|
||||
standardFields.remove(field);
|
||||
} else if (otherFields != null) {
|
||||
otherFields.remove(field);
|
||||
}
|
||||
}
|
||||
void addObject(Chronology chrono) {
|
||||
this.chrono = chrono;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries a list of fields from the builder.
|
||||
* <p>
|
||||
* This gets the value of the specified fields from the builder into
|
||||
* an array where the positions match the order of the fields.
|
||||
* If a field is not present, the array will contain null in that position.
|
||||
*
|
||||
* @param fields the fields to query, not null
|
||||
* @return the array of field values, not null
|
||||
*/
|
||||
public Long[] queryFieldValues(TemporalField... fields) {
|
||||
Long[] values = new Long[fields.length];
|
||||
int i = 0;
|
||||
for (TemporalField field : fields) {
|
||||
values[i++] = getFieldValue0(field);
|
||||
}
|
||||
return values;
|
||||
void addObject(ZoneId zone) {
|
||||
this.zone = zone;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the list of date-time objects in the builder.
|
||||
* <p>
|
||||
* This map is intended for use with {@link ZoneOffset} and {@link ZoneId}.
|
||||
* The returned map is live and may be edited.
|
||||
*
|
||||
* @return the editable list of date-time objects, not null
|
||||
*/
|
||||
public List<Object> getCalendricalList() {
|
||||
return objects;
|
||||
void addObject(LocalDate date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a date-time object to the builder.
|
||||
* <p>
|
||||
* This adds a date-time object to the builder.
|
||||
* If the object is a {@code DateTimeBuilder}, each field is added using {@link #addFieldValue}.
|
||||
* If the object is not already present, then the object is added.
|
||||
* If the object is already present and it is equal to that specified, no action occurs.
|
||||
* If the object is already present and it is not equal to that specified, then an exception is thrown.
|
||||
*
|
||||
* @param object the object to add, not null
|
||||
* @return {@code this}, for method chaining
|
||||
* @throws DateTimeException if the field is already present with a different value
|
||||
*/
|
||||
public DateTimeBuilder addCalendrical(Object object) {
|
||||
Objects.requireNonNull(object, "object");
|
||||
// special case
|
||||
if (object instanceof DateTimeBuilder) {
|
||||
DateTimeBuilder dtb = (DateTimeBuilder) object;
|
||||
for (TemporalField field : dtb.getFieldValueMap().keySet()) {
|
||||
addFieldValue(field, dtb.getFieldValue(field));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
if (object instanceof Instant) {
|
||||
addFieldValue(INSTANT_SECONDS, ((Instant) object).getEpochSecond());
|
||||
addFieldValue(NANO_OF_SECOND, ((Instant) object).getNano());
|
||||
} else {
|
||||
objects.add(object);
|
||||
}
|
||||
// TODO
|
||||
// // preserve state of builder until validated
|
||||
// Class<?> cls = dateTime.extract(Class.class);
|
||||
// if (cls == null) {
|
||||
// throw new DateTimeException("Invalid dateTime, unable to extract Class");
|
||||
// }
|
||||
// Object obj = objects.get(cls);
|
||||
// if (obj != null) {
|
||||
// if (obj.equals(dateTime) == false) {
|
||||
// throw new DateTimeException("Conflict found: " + dateTime.getClass().getSimpleName() + " " + obj + " differs from " + dateTime + ": " + this);
|
||||
// }
|
||||
// } else {
|
||||
// objects.put(cls, dateTime);
|
||||
// }
|
||||
return this;
|
||||
void addObject(LocalTime time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -413,21 +240,7 @@ public final class DateTimeBuilder
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public DateTimeBuilder resolve() {
|
||||
splitObjects();
|
||||
// handle unusual fields
|
||||
if (otherFields != null) {
|
||||
outer:
|
||||
while (true) {
|
||||
Set<Entry<TemporalField, Long>> entrySet = new HashSet<>(otherFields.entrySet());
|
||||
for (Entry<TemporalField, Long> entry : entrySet) {
|
||||
if (entry.getKey().resolve(this, entry.getValue())) {
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
DateTimeBuilder resolve() {
|
||||
// handle standard fields
|
||||
mergeDate();
|
||||
mergeTime();
|
||||
@ -441,11 +254,39 @@ public final class DateTimeBuilder
|
||||
return;
|
||||
}
|
||||
|
||||
// normalize fields
|
||||
if (standardFields.containsKey(EPOCH_MONTH)) {
|
||||
long em = standardFields.remove(EPOCH_MONTH);
|
||||
addFieldValue(MONTH_OF_YEAR, (em % 12) + 1);
|
||||
addFieldValue(YEAR, (em / 12) + 1970);
|
||||
Era era = null;
|
||||
if (chrono == IsoChronology.INSTANCE) {
|
||||
// normalize fields
|
||||
if (standardFields.containsKey(EPOCH_MONTH)) {
|
||||
long em = standardFields.remove(EPOCH_MONTH);
|
||||
addFieldValue(MONTH_OF_YEAR, (em % 12) + 1);
|
||||
addFieldValue(YEAR, (em / 12) + 1970);
|
||||
}
|
||||
} else {
|
||||
// TODO: revisit EPOCH_MONTH calculation in non-ISO chronology
|
||||
// Handle EPOCH_MONTH here for non-ISO Chronology
|
||||
if (standardFields.containsKey(EPOCH_MONTH)) {
|
||||
long em = standardFields.remove(EPOCH_MONTH);
|
||||
ChronoLocalDate<?> chronoDate = chrono.date(LocalDate.ofEpochDay(0L));
|
||||
chronoDate = chronoDate.plus(em, ChronoUnit.MONTHS);
|
||||
LocalDate date = LocalDate.ofEpochDay(chronoDate.toEpochDay());
|
||||
checkDate(date);
|
||||
return;
|
||||
}
|
||||
List<Era> eras = chrono.eras();
|
||||
if (!eras.isEmpty()) {
|
||||
if (standardFields.containsKey(ERA)) {
|
||||
long index = standardFields.remove(ERA);
|
||||
era = chrono.eraOf((int) index);
|
||||
} else {
|
||||
era = eras.get(eras.size() - 1); // current Era
|
||||
}
|
||||
if (standardFields.containsKey(YEAR_OF_ERA)) {
|
||||
Long y = standardFields.remove(YEAR_OF_ERA);
|
||||
putFieldValue0(YEAR, y);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// build date
|
||||
@ -455,7 +296,19 @@ public final class DateTimeBuilder
|
||||
int y = Math.toIntExact(standardFields.remove(YEAR));
|
||||
int moy = Math.toIntExact(standardFields.remove(MONTH_OF_YEAR));
|
||||
int dom = Math.toIntExact(standardFields.remove(DAY_OF_MONTH));
|
||||
checkDate(LocalDate.of(y, moy, dom));
|
||||
LocalDate date;
|
||||
if (chrono == IsoChronology.INSTANCE) {
|
||||
date = LocalDate.of(y, moy, dom);
|
||||
} else {
|
||||
ChronoLocalDate<?> chronoDate;
|
||||
if (era == null) {
|
||||
chronoDate = chrono.date(y, moy, dom);
|
||||
} else {
|
||||
chronoDate = era.date(y, moy, dom);
|
||||
}
|
||||
date = LocalDate.ofEpochDay(chronoDate.toEpochDay());
|
||||
}
|
||||
checkDate(date);
|
||||
return;
|
||||
}
|
||||
if (standardFields.containsKey(ALIGNED_WEEK_OF_MONTH)) {
|
||||
@ -464,7 +317,20 @@ public final class DateTimeBuilder
|
||||
int moy = Math.toIntExact(standardFields.remove(MONTH_OF_YEAR));
|
||||
int aw = Math.toIntExact(standardFields.remove(ALIGNED_WEEK_OF_MONTH));
|
||||
int ad = Math.toIntExact(standardFields.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH));
|
||||
checkDate(LocalDate.of(y, moy, 1).plusDays((aw - 1) * 7 + (ad - 1)));
|
||||
LocalDate date;
|
||||
if (chrono == IsoChronology.INSTANCE) {
|
||||
date = LocalDate.of(y, moy, 1).plusDays((aw - 1) * 7 + (ad - 1));
|
||||
} else {
|
||||
ChronoLocalDate<?> chronoDate;
|
||||
if (era == null) {
|
||||
chronoDate = chrono.date(y, moy, 1);
|
||||
} else {
|
||||
chronoDate = era.date(y, moy, 1);
|
||||
}
|
||||
chronoDate = chronoDate.plus((aw - 1) * 7 + (ad - 1), ChronoUnit.DAYS);
|
||||
date = LocalDate.ofEpochDay(chronoDate.toEpochDay());
|
||||
}
|
||||
checkDate(date);
|
||||
return;
|
||||
}
|
||||
if (standardFields.containsKey(DAY_OF_WEEK)) {
|
||||
@ -472,7 +338,20 @@ public final class DateTimeBuilder
|
||||
int moy = Math.toIntExact(standardFields.remove(MONTH_OF_YEAR));
|
||||
int aw = Math.toIntExact(standardFields.remove(ALIGNED_WEEK_OF_MONTH));
|
||||
int dow = Math.toIntExact(standardFields.remove(DAY_OF_WEEK));
|
||||
checkDate(LocalDate.of(y, moy, 1).plusDays((aw - 1) * 7).with(nextOrSame(DayOfWeek.of(dow))));
|
||||
LocalDate date;
|
||||
if (chrono == IsoChronology.INSTANCE) {
|
||||
date = LocalDate.of(y, moy, 1).plusDays((aw - 1) * 7).with(nextOrSame(DayOfWeek.of(dow)));
|
||||
} else {
|
||||
ChronoLocalDate<?> chronoDate;
|
||||
if (era == null) {
|
||||
chronoDate = chrono.date(y, moy, 1);
|
||||
} else {
|
||||
chronoDate = era.date(y, moy, 1);
|
||||
}
|
||||
chronoDate = chronoDate.plus((aw - 1) * 7, ChronoUnit.DAYS).with(nextOrSame(DayOfWeek.of(dow)));
|
||||
date = LocalDate.ofEpochDay(chronoDate.toEpochDay());
|
||||
}
|
||||
checkDate(date);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -480,7 +359,19 @@ public final class DateTimeBuilder
|
||||
if (standardFields.containsKey(DAY_OF_YEAR)) {
|
||||
int y = Math.toIntExact(standardFields.remove(YEAR));
|
||||
int doy = Math.toIntExact(standardFields.remove(DAY_OF_YEAR));
|
||||
checkDate(LocalDate.ofYearDay(y, doy));
|
||||
LocalDate date;
|
||||
if (chrono == IsoChronology.INSTANCE) {
|
||||
date = LocalDate.ofYearDay(y, doy);
|
||||
} else {
|
||||
ChronoLocalDate<?> chronoDate;
|
||||
if (era == null) {
|
||||
chronoDate = chrono.dateYearDay(y, doy);
|
||||
} else {
|
||||
chronoDate = era.dateYearDay(y, doy);
|
||||
}
|
||||
date = LocalDate.ofEpochDay(chronoDate.toEpochDay());
|
||||
}
|
||||
checkDate(date);
|
||||
return;
|
||||
}
|
||||
if (standardFields.containsKey(ALIGNED_WEEK_OF_YEAR)) {
|
||||
@ -488,14 +379,40 @@ public final class DateTimeBuilder
|
||||
int y = Math.toIntExact(standardFields.remove(YEAR));
|
||||
int aw = Math.toIntExact(standardFields.remove(ALIGNED_WEEK_OF_YEAR));
|
||||
int ad = Math.toIntExact(standardFields.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR));
|
||||
checkDate(LocalDate.of(y, 1, 1).plusDays((aw - 1) * 7 + (ad - 1)));
|
||||
LocalDate date;
|
||||
if (chrono == IsoChronology.INSTANCE) {
|
||||
date = LocalDate.of(y, 1, 1).plusDays((aw - 1) * 7 + (ad - 1));
|
||||
} else {
|
||||
ChronoLocalDate<?> chronoDate;
|
||||
if (era == null) {
|
||||
chronoDate = chrono.dateYearDay(y, 1);
|
||||
} else {
|
||||
chronoDate = era.dateYearDay(y, 1);
|
||||
}
|
||||
chronoDate = chronoDate.plus((aw - 1) * 7 + (ad - 1), ChronoUnit.DAYS);
|
||||
date = LocalDate.ofEpochDay(chronoDate.toEpochDay());
|
||||
}
|
||||
checkDate(date);
|
||||
return;
|
||||
}
|
||||
if (standardFields.containsKey(DAY_OF_WEEK)) {
|
||||
int y = Math.toIntExact(standardFields.remove(YEAR));
|
||||
int aw = Math.toIntExact(standardFields.remove(ALIGNED_WEEK_OF_YEAR));
|
||||
int dow = Math.toIntExact(standardFields.remove(DAY_OF_WEEK));
|
||||
checkDate(LocalDate.of(y, 1, 1).plusDays((aw - 1) * 7).with(nextOrSame(DayOfWeek.of(dow))));
|
||||
LocalDate date;
|
||||
if (chrono == IsoChronology.INSTANCE) {
|
||||
date = LocalDate.of(y, 1, 1).plusDays((aw - 1) * 7).with(nextOrSame(DayOfWeek.of(dow)));
|
||||
} else {
|
||||
ChronoLocalDate<?> chronoDate;
|
||||
if (era == null) {
|
||||
chronoDate = chrono.dateYearDay(y, 1);
|
||||
} else {
|
||||
chronoDate = era.dateYearDay(y, 1);
|
||||
}
|
||||
chronoDate = chronoDate.plus((aw - 1) * 7, ChronoUnit.DAYS).with(nextOrSame(DayOfWeek.of(dow)));
|
||||
date = LocalDate.ofEpochDay(chronoDate.toEpochDay());
|
||||
}
|
||||
checkDate(date);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -503,9 +420,7 @@ public final class DateTimeBuilder
|
||||
}
|
||||
|
||||
private void checkDate(LocalDate date) {
|
||||
// TODO: this doesn't handle aligned weeks over into next month which would otherwise be valid
|
||||
|
||||
addCalendrical(date);
|
||||
addObject(date);
|
||||
for (ChronoField field : standardFields.keySet()) {
|
||||
long val1;
|
||||
try {
|
||||
@ -594,96 +509,66 @@ public final class DateTimeBuilder
|
||||
int somVal = Math.toIntExact(som);
|
||||
if (nos != null) {
|
||||
int nosVal = Math.toIntExact(nos);
|
||||
addCalendrical(LocalTime.of(hodVal, mohVal, somVal, nosVal));
|
||||
addObject(LocalTime.of(hodVal, mohVal, somVal, nosVal));
|
||||
} else {
|
||||
addCalendrical(LocalTime.of(hodVal, mohVal, somVal));
|
||||
addObject(LocalTime.of(hodVal, mohVal, somVal));
|
||||
}
|
||||
} else {
|
||||
addCalendrical(LocalTime.of(hodVal, mohVal));
|
||||
addObject(LocalTime.of(hodVal, mohVal));
|
||||
}
|
||||
} else {
|
||||
addCalendrical(LocalTime.of(hodVal, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void splitObjects() {
|
||||
List<Object> objectsToAdd = new ArrayList<>();
|
||||
for (Object object : objects) {
|
||||
if (object instanceof LocalDate || object instanceof LocalTime ||
|
||||
object instanceof ZoneId || object instanceof Chrono) {
|
||||
continue;
|
||||
}
|
||||
if (object instanceof ZoneOffset || object instanceof Instant) {
|
||||
objectsToAdd.add(object);
|
||||
|
||||
} else if (object instanceof TemporalAccessor) {
|
||||
// TODO
|
||||
// TemporalAccessor dt = (TemporalAccessor) object;
|
||||
// objectsToAdd.add(dt.extract(LocalDate.class));
|
||||
// objectsToAdd.add(dt.extract(LocalTime.class));
|
||||
// objectsToAdd.add(dt.extract(ZoneId.class));
|
||||
// objectsToAdd.add(dt.extract(Chrono.class));
|
||||
}
|
||||
}
|
||||
for (Object object : objectsToAdd) {
|
||||
if (object != null) {
|
||||
addCalendrical(object);
|
||||
addObject(LocalTime.of(hodVal, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.zoneId()) {
|
||||
return (R) extract(ZoneId.class);
|
||||
public boolean isSupported(TemporalField field) {
|
||||
if (field == null) {
|
||||
return false;
|
||||
}
|
||||
if (query == Queries.offset()) {
|
||||
ZoneOffset offset = extract(ZoneOffset.class);
|
||||
if (offset == null && standardFields.containsKey(OFFSET_SECONDS)) {
|
||||
offset = ZoneOffset.ofTotalSeconds(Math.toIntExact(standardFields.get(OFFSET_SECONDS)));
|
||||
return standardFields.containsKey(field) ||
|
||||
(otherFields != null && otherFields.containsKey(field)) ||
|
||||
(date != null && date.isSupported(field)) ||
|
||||
(time != null && time.isSupported(field));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(TemporalField field) {
|
||||
Objects.requireNonNull(field, "field");
|
||||
Long value = getFieldValue0(field);
|
||||
if (value == null) {
|
||||
if (date != null && date.isSupported(field)) {
|
||||
return date.getLong(field);
|
||||
}
|
||||
return (R) offset;
|
||||
if (time != null && time.isSupported(field)) {
|
||||
return time.getLong(field);
|
||||
}
|
||||
throw new DateTimeException("Field not found: " + field);
|
||||
}
|
||||
if (query == Queries.chrono()) {
|
||||
return extract(Chrono.class);
|
||||
}
|
||||
// incomplete, so no need to handle PRECISION
|
||||
return TemporalAccessor.super.query(query);
|
||||
return value;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R> R extract(Class<?> type) {
|
||||
R result = null;
|
||||
for (Object obj : objects) {
|
||||
if (type.isInstance(obj)) {
|
||||
if (result != null && result.equals(obj) == false) {
|
||||
throw new DateTimeException("Conflict found: " + type.getSimpleName() + " differs " + result + " vs " + obj + ": " + this);
|
||||
}
|
||||
result = (R) obj;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Clones this builder, creating a new independent copy referring to the
|
||||
* same map of fields and objects.
|
||||
*
|
||||
* @return the cloned builder, not null
|
||||
*/
|
||||
@Override
|
||||
public DateTimeBuilder clone() {
|
||||
DateTimeBuilder dtb = new DateTimeBuilder();
|
||||
dtb.objects.addAll(this.objects);
|
||||
dtb.standardFields.putAll(this.standardFields);
|
||||
dtb.standardFields.putAll(this.standardFields);
|
||||
if (this.otherFields != null) {
|
||||
dtb.otherFields.putAll(this.otherFields);
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == Queries.zoneId()) {
|
||||
return (R) zone;
|
||||
} else if (query == Queries.chronology()) {
|
||||
return (R) chrono;
|
||||
} else if (query == Queries.localDate()) {
|
||||
return (R) date;
|
||||
} else if (query == Queries.localTime()) {
|
||||
return (R) time;
|
||||
} else if (query == Queries.zone() || query == Queries.offset()) {
|
||||
return query.queryFrom(this);
|
||||
} else if (query == Queries.precision()) {
|
||||
return null; // not a complete date/time
|
||||
}
|
||||
return dtb;
|
||||
// inline TemporalAccessor.super.query(query) as an optimization
|
||||
// non-JDK classes are not permitted to make this optimization
|
||||
return query.queryFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@ -691,29 +576,20 @@ public final class DateTimeBuilder
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
buf.append("DateTimeBuilder[");
|
||||
Map<TemporalField, Long> fields = getFieldValueMap();
|
||||
Map<TemporalField, Long> fields = new HashMap<>();
|
||||
fields.putAll(standardFields);
|
||||
if (otherFields != null) {
|
||||
fields.putAll(otherFields);
|
||||
}
|
||||
if (fields.size() > 0) {
|
||||
buf.append("fields=").append(fields);
|
||||
}
|
||||
if (objects.size() > 0) {
|
||||
if (fields.size() > 0) {
|
||||
buf.append(", ");
|
||||
}
|
||||
buf.append("objects=").append(objects);
|
||||
}
|
||||
buf.append(", ").append(chrono);
|
||||
buf.append(", ").append(zone);
|
||||
buf.append(", ").append(date);
|
||||
buf.append(", ").append(time);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public boolean isSupported(TemporalField field) {
|
||||
return field != null && containsFieldValue(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(TemporalField field) {
|
||||
return getFieldValue(field);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user