mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8187443: Forest Consolidation: Move files to unified layout
Reviewed-by: darcy, ihse
This commit is contained in:
parent
270fe13182
commit
3789983e89
56923 changed files with 3 additions and 15727 deletions
2208
src/java.base/share/classes/java/time/format/DateTimeFormatter.java
Normal file
2208
src/java.base/share/classes/java/time/format/DateTimeFormatter.java
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,438 @@
|
|||
/*
|
||||
* 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) 2008-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.format;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.time.chrono.Chronology;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Context object used during date and time parsing.
|
||||
* <p>
|
||||
* This class represents the current state of the parse.
|
||||
* It has the ability to store and retrieve the parsed values and manage optional segments.
|
||||
* It also provides key information to the parsing methods.
|
||||
* <p>
|
||||
* Once parsing is complete, the {@link #toUnresolved()} is used to obtain the unresolved
|
||||
* result data. The {@link #toResolved()} is used to obtain the resolved result.
|
||||
*
|
||||
* @implSpec
|
||||
* This class is a mutable context intended for use from a single thread.
|
||||
* Usage of the class is thread-safe within standard parsing as a new instance of this class
|
||||
* is automatically created for each parse and parsing is single-threaded
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
final class DateTimeParseContext {
|
||||
|
||||
/**
|
||||
* The formatter, not null.
|
||||
*/
|
||||
private DateTimeFormatter formatter;
|
||||
/**
|
||||
* Whether to parse using case sensitively.
|
||||
*/
|
||||
private boolean caseSensitive = true;
|
||||
/**
|
||||
* Whether to parse using strict rules.
|
||||
*/
|
||||
private boolean strict = true;
|
||||
/**
|
||||
* The list of parsed data.
|
||||
*/
|
||||
private final ArrayList<Parsed> parsed = new ArrayList<>();
|
||||
/**
|
||||
* List of Consumers<Chronology> to be notified if the Chronology changes.
|
||||
*/
|
||||
private ArrayList<Consumer<Chronology>> chronoListeners = null;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the context.
|
||||
*
|
||||
* @param formatter the formatter controlling the parse, not null
|
||||
*/
|
||||
DateTimeParseContext(DateTimeFormatter formatter) {
|
||||
super();
|
||||
this.formatter = formatter;
|
||||
parsed.add(new Parsed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of this context.
|
||||
* This retains the case sensitive and strict flags.
|
||||
*/
|
||||
DateTimeParseContext copy() {
|
||||
DateTimeParseContext newContext = new DateTimeParseContext(formatter);
|
||||
newContext.caseSensitive = caseSensitive;
|
||||
newContext.strict = strict;
|
||||
return newContext;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the locale.
|
||||
* <p>
|
||||
* This locale is used to control localization in the parse except
|
||||
* where localization is controlled by the DecimalStyle.
|
||||
*
|
||||
* @return the locale, not null
|
||||
*/
|
||||
Locale getLocale() {
|
||||
return formatter.getLocale();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DecimalStyle.
|
||||
* <p>
|
||||
* The DecimalStyle controls the numeric parsing.
|
||||
*
|
||||
* @return the DecimalStyle, not null
|
||||
*/
|
||||
DecimalStyle getDecimalStyle() {
|
||||
return formatter.getDecimalStyle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the effective chronology during parsing.
|
||||
*
|
||||
* @return the effective parsing chronology, not null
|
||||
*/
|
||||
Chronology getEffectiveChronology() {
|
||||
Chronology chrono = currentParsed().chrono;
|
||||
if (chrono == null) {
|
||||
chrono = formatter.getChronology();
|
||||
if (chrono == null) {
|
||||
chrono = IsoChronology.INSTANCE;
|
||||
}
|
||||
}
|
||||
return chrono;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Checks if parsing is case sensitive.
|
||||
*
|
||||
* @return true if parsing is case sensitive, false if case insensitive
|
||||
*/
|
||||
boolean isCaseSensitive() {
|
||||
return caseSensitive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the parsing is case sensitive or not.
|
||||
*
|
||||
* @param caseSensitive changes the parsing to be case sensitive or not from now on
|
||||
*/
|
||||
void setCaseSensitive(boolean caseSensitive) {
|
||||
this.caseSensitive = caseSensitive;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Helper to compare two {@code CharSequence} instances.
|
||||
* This uses {@link #isCaseSensitive()}.
|
||||
*
|
||||
* @param cs1 the first character sequence, not null
|
||||
* @param offset1 the offset into the first sequence, valid
|
||||
* @param cs2 the second character sequence, not null
|
||||
* @param offset2 the offset into the second sequence, valid
|
||||
* @param length the length to check, valid
|
||||
* @return true if equal
|
||||
*/
|
||||
boolean subSequenceEquals(CharSequence cs1, int offset1, CharSequence cs2, int offset2, int length) {
|
||||
if (offset1 + length > cs1.length() || offset2 + length > cs2.length()) {
|
||||
return false;
|
||||
}
|
||||
if (isCaseSensitive()) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
char ch1 = cs1.charAt(offset1 + i);
|
||||
char ch2 = cs2.charAt(offset2 + i);
|
||||
if (ch1 != ch2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < length; i++) {
|
||||
char ch1 = cs1.charAt(offset1 + i);
|
||||
char ch2 = cs2.charAt(offset2 + i);
|
||||
if (ch1 != ch2 && Character.toUpperCase(ch1) != Character.toUpperCase(ch2) &&
|
||||
Character.toLowerCase(ch1) != Character.toLowerCase(ch2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to compare two {@code char}.
|
||||
* This uses {@link #isCaseSensitive()}.
|
||||
*
|
||||
* @param ch1 the first character
|
||||
* @param ch2 the second character
|
||||
* @return true if equal
|
||||
*/
|
||||
boolean charEquals(char ch1, char ch2) {
|
||||
if (isCaseSensitive()) {
|
||||
return ch1 == ch2;
|
||||
}
|
||||
return charEqualsIgnoreCase(ch1, ch2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two characters ignoring case.
|
||||
*
|
||||
* @param c1 the first
|
||||
* @param c2 the second
|
||||
* @return true if equal
|
||||
*/
|
||||
static boolean charEqualsIgnoreCase(char c1, char c2) {
|
||||
return c1 == c2 ||
|
||||
Character.toUpperCase(c1) == Character.toUpperCase(c2) ||
|
||||
Character.toLowerCase(c1) == Character.toLowerCase(c2);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Checks if parsing is strict.
|
||||
* <p>
|
||||
* Strict parsing requires exact matching of the text and sign styles.
|
||||
*
|
||||
* @return true if parsing is strict, false if lenient
|
||||
*/
|
||||
boolean isStrict() {
|
||||
return strict;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether parsing is strict or lenient.
|
||||
*
|
||||
* @param strict changes the parsing to be strict or lenient from now on
|
||||
*/
|
||||
void setStrict(boolean strict) {
|
||||
this.strict = strict;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Starts the parsing of an optional segment of the input.
|
||||
*/
|
||||
void startOptional() {
|
||||
parsed.add(currentParsed().copy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the parsing of an optional segment of the input.
|
||||
*
|
||||
* @param successful whether the optional segment was successfully parsed
|
||||
*/
|
||||
void endOptional(boolean successful) {
|
||||
if (successful) {
|
||||
parsed.remove(parsed.size() - 2);
|
||||
} else {
|
||||
parsed.remove(parsed.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the currently active temporal objects.
|
||||
*
|
||||
* @return the current temporal objects, not null
|
||||
*/
|
||||
private Parsed currentParsed() {
|
||||
return parsed.get(parsed.size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unresolved result of the parse.
|
||||
*
|
||||
* @return the result of the parse, not null
|
||||
*/
|
||||
Parsed toUnresolved() {
|
||||
return currentParsed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the resolved result of the parse.
|
||||
*
|
||||
* @return the result of the parse, not null
|
||||
*/
|
||||
TemporalAccessor toResolved(ResolverStyle resolverStyle, Set<TemporalField> resolverFields) {
|
||||
Parsed parsed = currentParsed();
|
||||
parsed.chrono = getEffectiveChronology();
|
||||
parsed.zone = (parsed.zone != null ? parsed.zone : formatter.getZone());
|
||||
return parsed.resolve(resolverStyle, resolverFields);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the first value that was parsed for the specified field.
|
||||
* <p>
|
||||
* This searches the results of the parse, returning the first value found
|
||||
* for the specified field. No attempt is made to derive a value.
|
||||
* The field may have an out of range value.
|
||||
* For example, the day-of-month might be set to 50, or the hour to 1000.
|
||||
*
|
||||
* @param field the field to query from the map, null returns null
|
||||
* @return the value mapped to the specified field, null if field was not parsed
|
||||
*/
|
||||
Long getParsed(TemporalField field) {
|
||||
return currentParsed().fieldValues.get(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the parsed field.
|
||||
* <p>
|
||||
* This stores a field-value pair that has been parsed.
|
||||
* The value stored may be out of range for the field - no checks are performed.
|
||||
*
|
||||
* @param field the field to set in the field-value map, not null
|
||||
* @param value the value to set in the field-value map
|
||||
* @param errorPos the position of the field being parsed
|
||||
* @param successPos the position after the field being parsed
|
||||
* @return the new position
|
||||
*/
|
||||
int setParsedField(TemporalField field, long value, int errorPos, int successPos) {
|
||||
Objects.requireNonNull(field, "field");
|
||||
Long old = currentParsed().fieldValues.put(field, value);
|
||||
return (old != null && old.longValue() != value) ? ~errorPos : successPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the parsed chronology.
|
||||
* <p>
|
||||
* This stores the chronology that has been parsed.
|
||||
* No validation is performed other than ensuring it is not null.
|
||||
* <p>
|
||||
* The list of listeners is copied and cleared so that each
|
||||
* listener is called only once. A listener can add itself again
|
||||
* if it needs to be notified of future changes.
|
||||
*
|
||||
* @param chrono the parsed chronology, not null
|
||||
*/
|
||||
void setParsed(Chronology chrono) {
|
||||
Objects.requireNonNull(chrono, "chrono");
|
||||
currentParsed().chrono = chrono;
|
||||
if (chronoListeners != null && !chronoListeners.isEmpty()) {
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
Consumer<Chronology>[] tmp = new Consumer[1];
|
||||
Consumer<Chronology>[] listeners = chronoListeners.toArray(tmp);
|
||||
chronoListeners.clear();
|
||||
for (Consumer<Chronology> l : listeners) {
|
||||
l.accept(chrono);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Consumer<Chronology> to the list of listeners to be notified
|
||||
* if the Chronology changes.
|
||||
* @param listener a Consumer<Chronology> to be called when Chronology changes
|
||||
*/
|
||||
void addChronoChangedListener(Consumer<Chronology> listener) {
|
||||
if (chronoListeners == null) {
|
||||
chronoListeners = new ArrayList<>();
|
||||
}
|
||||
chronoListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the parsed zone.
|
||||
* <p>
|
||||
* This stores the zone that has been parsed.
|
||||
* No validation is performed other than ensuring it is not null.
|
||||
*
|
||||
* @param zone the parsed zone, not null
|
||||
*/
|
||||
void setParsed(ZoneId zone) {
|
||||
Objects.requireNonNull(zone, "zone");
|
||||
currentParsed().zone = zone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the parsed leap second.
|
||||
*/
|
||||
void setParsedLeapSecond() {
|
||||
currentParsed().leapSecond = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a string version of the context for debugging.
|
||||
*
|
||||
* @return a string representation of the context data, not null
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return currentParsed().toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* 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) 2008-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.format;
|
||||
|
||||
import java.time.DateTimeException;
|
||||
|
||||
/**
|
||||
* An exception thrown when an error occurs during parsing.
|
||||
* <p>
|
||||
* This exception includes the text being parsed and the error index.
|
||||
*
|
||||
* @implSpec
|
||||
* This class is intended for use in a single thread.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public class DateTimeParseException extends DateTimeException {
|
||||
|
||||
/**
|
||||
* Serialization version.
|
||||
*/
|
||||
private static final long serialVersionUID = 4304633501674722597L;
|
||||
|
||||
/**
|
||||
* The text that was being parsed.
|
||||
*/
|
||||
private final String parsedString;
|
||||
/**
|
||||
* The error index in the text.
|
||||
*/
|
||||
private final int errorIndex;
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified message.
|
||||
*
|
||||
* @param message the message to use for this exception, may be null
|
||||
* @param parsedData the parsed text, should not be null
|
||||
* @param errorIndex the index in the parsed string that was invalid, should be a valid index
|
||||
*/
|
||||
public DateTimeParseException(String message, CharSequence parsedData, int errorIndex) {
|
||||
super(message);
|
||||
this.parsedString = parsedData.toString();
|
||||
this.errorIndex = errorIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified message and cause.
|
||||
*
|
||||
* @param message the message to use for this exception, may be null
|
||||
* @param parsedData the parsed text, should not be null
|
||||
* @param errorIndex the index in the parsed string that was invalid, should be a valid index
|
||||
* @param cause the cause exception, may be null
|
||||
*/
|
||||
public DateTimeParseException(String message, CharSequence parsedData, int errorIndex, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.parsedString = parsedData.toString();
|
||||
this.errorIndex = errorIndex;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns the string that was being parsed.
|
||||
*
|
||||
* @return the string that was being parsed, should not be null.
|
||||
*/
|
||||
public String getParsedString() {
|
||||
return parsedString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index where the error was found.
|
||||
*
|
||||
* @return the index in the parsed string that was invalid, should be a valid index
|
||||
*/
|
||||
public int getErrorIndex() {
|
||||
return errorIndex;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2016, 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) 2011-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.format;
|
||||
|
||||
import static java.time.temporal.ChronoField.EPOCH_DAY;
|
||||
import static java.time.temporal.ChronoField.INSTANT_SECONDS;
|
||||
import static java.time.temporal.ChronoField.OFFSET_SECONDS;
|
||||
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.chrono.ChronoLocalDate;
|
||||
import java.time.chrono.Chronology;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQueries;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.ValueRange;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Context object used during date and time printing.
|
||||
* <p>
|
||||
* This class provides a single wrapper to items used in the format.
|
||||
*
|
||||
* @implSpec
|
||||
* This class is a mutable context intended for use from a single thread.
|
||||
* Usage of the class is thread-safe within standard printing as the framework creates
|
||||
* a new instance of the class for each format and printing is single-threaded.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
final class DateTimePrintContext {
|
||||
|
||||
/**
|
||||
* The temporal being output.
|
||||
*/
|
||||
private TemporalAccessor temporal;
|
||||
/**
|
||||
* The formatter, not null.
|
||||
*/
|
||||
private DateTimeFormatter formatter;
|
||||
/**
|
||||
* Whether the current formatter is optional.
|
||||
*/
|
||||
private int optional;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the context.
|
||||
*
|
||||
* @param temporal the temporal object being output, not null
|
||||
* @param formatter the formatter controlling the format, not null
|
||||
*/
|
||||
DateTimePrintContext(TemporalAccessor temporal, DateTimeFormatter formatter) {
|
||||
super();
|
||||
this.temporal = adjust(temporal, formatter);
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
||||
private static TemporalAccessor adjust(final TemporalAccessor temporal, DateTimeFormatter formatter) {
|
||||
// normal case first (early return is an optimization)
|
||||
Chronology overrideChrono = formatter.getChronology();
|
||||
ZoneId overrideZone = formatter.getZone();
|
||||
if (overrideChrono == null && overrideZone == null) {
|
||||
return temporal;
|
||||
}
|
||||
|
||||
// ensure minimal change (early return is an optimization)
|
||||
Chronology temporalChrono = temporal.query(TemporalQueries.chronology());
|
||||
ZoneId temporalZone = temporal.query(TemporalQueries.zoneId());
|
||||
if (Objects.equals(overrideChrono, temporalChrono)) {
|
||||
overrideChrono = null;
|
||||
}
|
||||
if (Objects.equals(overrideZone, temporalZone)) {
|
||||
overrideZone = null;
|
||||
}
|
||||
if (overrideChrono == null && overrideZone == null) {
|
||||
return temporal;
|
||||
}
|
||||
|
||||
// make adjustment
|
||||
final Chronology effectiveChrono = (overrideChrono != null ? overrideChrono : temporalChrono);
|
||||
if (overrideZone != null) {
|
||||
// if have zone and instant, calculation is simple, defaulting chrono if necessary
|
||||
if (temporal.isSupported(INSTANT_SECONDS)) {
|
||||
Chronology chrono = Objects.requireNonNullElse(effectiveChrono, IsoChronology.INSTANCE);
|
||||
return chrono.zonedDateTime(Instant.from(temporal), overrideZone);
|
||||
}
|
||||
// block changing zone on OffsetTime, and similar problem cases
|
||||
if (overrideZone.normalized() instanceof ZoneOffset && temporal.isSupported(OFFSET_SECONDS) &&
|
||||
temporal.get(OFFSET_SECONDS) != overrideZone.getRules().getOffset(Instant.EPOCH).getTotalSeconds()) {
|
||||
throw new DateTimeException("Unable to apply override zone '" + overrideZone +
|
||||
"' because the temporal object being formatted has a different offset but" +
|
||||
" does not represent an instant: " + temporal);
|
||||
}
|
||||
}
|
||||
final ZoneId effectiveZone = (overrideZone != null ? overrideZone : temporalZone);
|
||||
final ChronoLocalDate effectiveDate;
|
||||
if (overrideChrono != null) {
|
||||
if (temporal.isSupported(EPOCH_DAY)) {
|
||||
effectiveDate = effectiveChrono.date(temporal);
|
||||
} else {
|
||||
// check for date fields other than epoch-day, ignoring case of converting null to ISO
|
||||
if (!(overrideChrono == IsoChronology.INSTANCE && temporalChrono == null)) {
|
||||
for (ChronoField f : ChronoField.values()) {
|
||||
if (f.isDateBased() && temporal.isSupported(f)) {
|
||||
throw new DateTimeException("Unable to apply override chronology '" + overrideChrono +
|
||||
"' because the temporal object being formatted contains date fields but" +
|
||||
" does not represent a whole date: " + temporal);
|
||||
}
|
||||
}
|
||||
}
|
||||
effectiveDate = null;
|
||||
}
|
||||
} else {
|
||||
effectiveDate = null;
|
||||
}
|
||||
|
||||
// combine available data
|
||||
// this is a non-standard temporal that is almost a pure delegate
|
||||
// this better handles map-like underlying temporal instances
|
||||
return new TemporalAccessor() {
|
||||
@Override
|
||||
public boolean isSupported(TemporalField field) {
|
||||
if (effectiveDate != null && field.isDateBased()) {
|
||||
return effectiveDate.isSupported(field);
|
||||
}
|
||||
return temporal.isSupported(field);
|
||||
}
|
||||
@Override
|
||||
public ValueRange range(TemporalField field) {
|
||||
if (effectiveDate != null && field.isDateBased()) {
|
||||
return effectiveDate.range(field);
|
||||
}
|
||||
return temporal.range(field);
|
||||
}
|
||||
@Override
|
||||
public long getLong(TemporalField field) {
|
||||
if (effectiveDate != null && field.isDateBased()) {
|
||||
return effectiveDate.getLong(field);
|
||||
}
|
||||
return temporal.getLong(field);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == TemporalQueries.chronology()) {
|
||||
return (R) effectiveChrono;
|
||||
}
|
||||
if (query == TemporalQueries.zoneId()) {
|
||||
return (R) effectiveZone;
|
||||
}
|
||||
if (query == TemporalQueries.precision()) {
|
||||
return temporal.query(query);
|
||||
}
|
||||
return query.queryFrom(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return temporal +
|
||||
(effectiveChrono != null ? " with chronology " + effectiveChrono : "") +
|
||||
(effectiveZone != null ? " with zone " + effectiveZone : "");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the temporal object being output.
|
||||
*
|
||||
* @return the temporal object, not null
|
||||
*/
|
||||
TemporalAccessor getTemporal() {
|
||||
return temporal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the locale.
|
||||
* <p>
|
||||
* This locale is used to control localization in the format output except
|
||||
* where localization is controlled by the DecimalStyle.
|
||||
*
|
||||
* @return the locale, not null
|
||||
*/
|
||||
Locale getLocale() {
|
||||
return formatter.getLocale();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DecimalStyle.
|
||||
* <p>
|
||||
* The DecimalStyle controls the localization of numeric output.
|
||||
*
|
||||
* @return the DecimalStyle, not null
|
||||
*/
|
||||
DecimalStyle getDecimalStyle() {
|
||||
return formatter.getDecimalStyle();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Starts the printing of an optional segment of the input.
|
||||
*/
|
||||
void startOptional() {
|
||||
this.optional++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the printing of an optional segment of the input.
|
||||
*/
|
||||
void endOptional() {
|
||||
this.optional--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value using a query.
|
||||
*
|
||||
* @param query the query to use, not null
|
||||
* @return the result, null if not found and optional is true
|
||||
* @throws DateTimeException if the type is not available and the section is not optional
|
||||
*/
|
||||
<R> R getValue(TemporalQuery<R> query) {
|
||||
R result = temporal.query(query);
|
||||
if (result == null && optional == 0) {
|
||||
throw new DateTimeException("Unable to extract " +
|
||||
query + " from temporal " + temporal);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the specified field.
|
||||
* <p>
|
||||
* This will return the value for the specified field.
|
||||
*
|
||||
* @param field the field to find, not null
|
||||
* @return the value, null if not found and optional is true
|
||||
* @throws DateTimeException if the field is not available and the section is not optional
|
||||
*/
|
||||
Long getValue(TemporalField field) {
|
||||
if (optional > 0 && !temporal.isSupported(field)) {
|
||||
return null;
|
||||
}
|
||||
return temporal.getLong(field);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a string version of the context for debugging.
|
||||
*
|
||||
* @return a string representation of the context, not null
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return temporal.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,591 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2017, 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) 2011-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.format;
|
||||
|
||||
import static java.time.temporal.ChronoField.AMPM_OF_DAY;
|
||||
import static java.time.temporal.ChronoField.DAY_OF_WEEK;
|
||||
import static java.time.temporal.ChronoField.ERA;
|
||||
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
|
||||
|
||||
import java.time.chrono.Chronology;
|
||||
import java.time.chrono.IsoChronology;
|
||||
import java.time.chrono.JapaneseChronology;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.IsoFields;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.util.AbstractMap.SimpleImmutableEntry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import sun.util.locale.provider.CalendarDataUtility;
|
||||
import sun.util.locale.provider.LocaleProviderAdapter;
|
||||
import sun.util.locale.provider.LocaleResources;
|
||||
|
||||
/**
|
||||
* A provider to obtain the textual form of a date-time field.
|
||||
*
|
||||
* @implSpec
|
||||
* Implementations must be thread-safe.
|
||||
* Implementations should cache the textual information.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
class DateTimeTextProvider {
|
||||
|
||||
/** Cache. */
|
||||
private static final ConcurrentMap<Entry<TemporalField, Locale>, Object> CACHE = new ConcurrentHashMap<>(16, 0.75f, 2);
|
||||
/** Comparator. */
|
||||
private static final Comparator<Entry<String, Long>> COMPARATOR = new Comparator<Entry<String, Long>>() {
|
||||
@Override
|
||||
public int compare(Entry<String, Long> obj1, Entry<String, Long> obj2) {
|
||||
return obj2.getKey().length() - obj1.getKey().length(); // longest to shortest
|
||||
}
|
||||
};
|
||||
|
||||
// Singleton instance
|
||||
private static final DateTimeTextProvider INSTANCE = new DateTimeTextProvider();
|
||||
|
||||
DateTimeTextProvider() {}
|
||||
|
||||
/**
|
||||
* Gets the provider of text.
|
||||
*
|
||||
* @return the provider, not null
|
||||
*/
|
||||
static DateTimeTextProvider getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the text for the specified field, locale and style
|
||||
* for the purpose of formatting.
|
||||
* <p>
|
||||
* The text associated with the value is returned.
|
||||
* The null return value should be used if there is no applicable text, or
|
||||
* if the text would be a numeric representation of the value.
|
||||
*
|
||||
* @param field the field to get text for, not null
|
||||
* @param value the field value to get text for, not null
|
||||
* @param style the style to get text for, not null
|
||||
* @param locale the locale to get text for, not null
|
||||
* @return the text for the field value, null if no text found
|
||||
*/
|
||||
public String getText(TemporalField field, long value, TextStyle style, Locale locale) {
|
||||
Object store = findStore(field, locale);
|
||||
if (store instanceof LocaleStore) {
|
||||
return ((LocaleStore) store).getText(value, style);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the text for the specified chrono, field, locale and style
|
||||
* for the purpose of formatting.
|
||||
* <p>
|
||||
* The text associated with the value is returned.
|
||||
* The null return value should be used if there is no applicable text, or
|
||||
* if the text would be a numeric representation of the value.
|
||||
*
|
||||
* @param chrono the Chronology to get text for, not null
|
||||
* @param field the field to get text for, not null
|
||||
* @param value the field value to get text for, not null
|
||||
* @param style the style to get text for, not null
|
||||
* @param locale the locale to get text for, not null
|
||||
* @return the text for the field value, null if no text found
|
||||
*/
|
||||
public String getText(Chronology chrono, TemporalField field, long value,
|
||||
TextStyle style, Locale locale) {
|
||||
if (chrono == IsoChronology.INSTANCE
|
||||
|| !(field instanceof ChronoField)) {
|
||||
return getText(field, value, style, locale);
|
||||
}
|
||||
|
||||
int fieldIndex;
|
||||
int fieldValue;
|
||||
if (field == ERA) {
|
||||
fieldIndex = Calendar.ERA;
|
||||
if (chrono == JapaneseChronology.INSTANCE) {
|
||||
if (value == -999) {
|
||||
fieldValue = 0;
|
||||
} else {
|
||||
fieldValue = (int) value + 2;
|
||||
}
|
||||
} else {
|
||||
fieldValue = (int) value;
|
||||
}
|
||||
} else if (field == MONTH_OF_YEAR) {
|
||||
fieldIndex = Calendar.MONTH;
|
||||
fieldValue = (int) value - 1;
|
||||
} else if (field == DAY_OF_WEEK) {
|
||||
fieldIndex = Calendar.DAY_OF_WEEK;
|
||||
fieldValue = (int) value + 1;
|
||||
if (fieldValue > 7) {
|
||||
fieldValue = Calendar.SUNDAY;
|
||||
}
|
||||
} else if (field == AMPM_OF_DAY) {
|
||||
fieldIndex = Calendar.AM_PM;
|
||||
fieldValue = (int) value;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return CalendarDataUtility.retrieveJavaTimeFieldValueName(
|
||||
chrono.getCalendarType(), fieldIndex, fieldValue, style.toCalendarStyle(), locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an iterator of text to field for the specified field, locale and style
|
||||
* for the purpose of parsing.
|
||||
* <p>
|
||||
* The iterator must be returned in order from the longest text to the shortest.
|
||||
* <p>
|
||||
* The null return value should be used if there is no applicable parsable text, or
|
||||
* if the text would be a numeric representation of the value.
|
||||
* Text can only be parsed if all the values for that field-style-locale combination are unique.
|
||||
*
|
||||
* @param field the field to get text for, not null
|
||||
* @param style the style to get text for, null for all parsable text
|
||||
* @param locale the locale to get text for, not null
|
||||
* @return the iterator of text to field pairs, in order from longest text to shortest text,
|
||||
* null if the field or style is not parsable
|
||||
*/
|
||||
public Iterator<Entry<String, Long>> getTextIterator(TemporalField field, TextStyle style, Locale locale) {
|
||||
Object store = findStore(field, locale);
|
||||
if (store instanceof LocaleStore) {
|
||||
return ((LocaleStore) store).getTextIterator(style);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an iterator of text to field for the specified chrono, field, locale and style
|
||||
* for the purpose of parsing.
|
||||
* <p>
|
||||
* The iterator must be returned in order from the longest text to the shortest.
|
||||
* <p>
|
||||
* The null return value should be used if there is no applicable parsable text, or
|
||||
* if the text would be a numeric representation of the value.
|
||||
* Text can only be parsed if all the values for that field-style-locale combination are unique.
|
||||
*
|
||||
* @param chrono the Chronology to get text for, not null
|
||||
* @param field the field to get text for, not null
|
||||
* @param style the style to get text for, null for all parsable text
|
||||
* @param locale the locale to get text for, not null
|
||||
* @return the iterator of text to field pairs, in order from longest text to shortest text,
|
||||
* null if the field or style is not parsable
|
||||
*/
|
||||
public Iterator<Entry<String, Long>> getTextIterator(Chronology chrono, TemporalField field,
|
||||
TextStyle style, Locale locale) {
|
||||
if (chrono == IsoChronology.INSTANCE
|
||||
|| !(field instanceof ChronoField)) {
|
||||
return getTextIterator(field, style, locale);
|
||||
}
|
||||
|
||||
int fieldIndex;
|
||||
switch ((ChronoField)field) {
|
||||
case ERA:
|
||||
fieldIndex = Calendar.ERA;
|
||||
break;
|
||||
case MONTH_OF_YEAR:
|
||||
fieldIndex = Calendar.MONTH;
|
||||
break;
|
||||
case DAY_OF_WEEK:
|
||||
fieldIndex = Calendar.DAY_OF_WEEK;
|
||||
break;
|
||||
case AMPM_OF_DAY:
|
||||
fieldIndex = Calendar.AM_PM;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
int calendarStyle = (style == null) ? Calendar.ALL_STYLES : style.toCalendarStyle();
|
||||
Map<String, Integer> map = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
|
||||
chrono.getCalendarType(), fieldIndex, calendarStyle, locale);
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
List<Entry<String, Long>> list = new ArrayList<>(map.size());
|
||||
switch (fieldIndex) {
|
||||
case Calendar.ERA:
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
int era = entry.getValue();
|
||||
if (chrono == JapaneseChronology.INSTANCE) {
|
||||
if (era == 0) {
|
||||
era = -999;
|
||||
} else {
|
||||
era -= 2;
|
||||
}
|
||||
}
|
||||
list.add(createEntry(entry.getKey(), (long)era));
|
||||
}
|
||||
break;
|
||||
case Calendar.MONTH:
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
list.add(createEntry(entry.getKey(), (long)(entry.getValue() + 1)));
|
||||
}
|
||||
break;
|
||||
case Calendar.DAY_OF_WEEK:
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
list.add(createEntry(entry.getKey(), (long)toWeekDay(entry.getValue())));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
||||
list.add(createEntry(entry.getKey(), (long)entry.getValue()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
return list.iterator();
|
||||
}
|
||||
|
||||
private Object findStore(TemporalField field, Locale locale) {
|
||||
Entry<TemporalField, Locale> key = createEntry(field, locale);
|
||||
Object store = CACHE.get(key);
|
||||
if (store == null) {
|
||||
store = createStore(field, locale);
|
||||
CACHE.putIfAbsent(key, store);
|
||||
store = CACHE.get(key);
|
||||
}
|
||||
return store;
|
||||
}
|
||||
|
||||
private static int toWeekDay(int calWeekDay) {
|
||||
if (calWeekDay == Calendar.SUNDAY) {
|
||||
return 7;
|
||||
} else {
|
||||
return calWeekDay - 1;
|
||||
}
|
||||
}
|
||||
|
||||
private Object createStore(TemporalField field, Locale locale) {
|
||||
Map<TextStyle, Map<Long, String>> styleMap = new HashMap<>();
|
||||
if (field == ERA) {
|
||||
for (TextStyle textStyle : TextStyle.values()) {
|
||||
if (textStyle.isStandalone()) {
|
||||
// Stand-alone isn't applicable to era names.
|
||||
continue;
|
||||
}
|
||||
Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
|
||||
"gregory", Calendar.ERA, textStyle.toCalendarStyle(), locale);
|
||||
if (displayNames != null) {
|
||||
Map<Long, String> map = new HashMap<>();
|
||||
for (Entry<String, Integer> entry : displayNames.entrySet()) {
|
||||
map.put((long) entry.getValue(), entry.getKey());
|
||||
}
|
||||
if (!map.isEmpty()) {
|
||||
styleMap.put(textStyle, map);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new LocaleStore(styleMap);
|
||||
}
|
||||
|
||||
if (field == MONTH_OF_YEAR) {
|
||||
for (TextStyle textStyle : TextStyle.values()) {
|
||||
Map<Long, String> map = new HashMap<>();
|
||||
// Narrow names may have duplicated names, such as "J" for January, June, July.
|
||||
// Get names one by one in that case.
|
||||
if ((textStyle.equals(TextStyle.NARROW) ||
|
||||
textStyle.equals(TextStyle.NARROW_STANDALONE))) {
|
||||
for (int month = Calendar.JANUARY; month <= Calendar.DECEMBER; month++) {
|
||||
String name;
|
||||
name = CalendarDataUtility.retrieveJavaTimeFieldValueName(
|
||||
"gregory", Calendar.MONTH,
|
||||
month, textStyle.toCalendarStyle(), locale);
|
||||
if (name == null) {
|
||||
break;
|
||||
}
|
||||
map.put((month + 1L), name);
|
||||
}
|
||||
} else {
|
||||
Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
|
||||
"gregory", Calendar.MONTH, textStyle.toCalendarStyle(), locale);
|
||||
if (displayNames != null) {
|
||||
for (Entry<String, Integer> entry : displayNames.entrySet()) {
|
||||
map.put((long)(entry.getValue() + 1), entry.getKey());
|
||||
}
|
||||
} else {
|
||||
// Although probability is very less, but if other styles have duplicate names.
|
||||
// Get names one by one in that case.
|
||||
for (int month = Calendar.JANUARY; month <= Calendar.DECEMBER; month++) {
|
||||
String name;
|
||||
name = CalendarDataUtility.retrieveJavaTimeFieldValueName(
|
||||
"gregory", Calendar.MONTH, month, textStyle.toCalendarStyle(), locale);
|
||||
if (name == null) {
|
||||
break;
|
||||
}
|
||||
map.put((month + 1L), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!map.isEmpty()) {
|
||||
styleMap.put(textStyle, map);
|
||||
}
|
||||
}
|
||||
return new LocaleStore(styleMap);
|
||||
}
|
||||
|
||||
if (field == DAY_OF_WEEK) {
|
||||
for (TextStyle textStyle : TextStyle.values()) {
|
||||
Map<Long, String> map = new HashMap<>();
|
||||
// Narrow names may have duplicated names, such as "S" for Sunday and Saturday.
|
||||
// Get names one by one in that case.
|
||||
if ((textStyle.equals(TextStyle.NARROW) ||
|
||||
textStyle.equals(TextStyle.NARROW_STANDALONE))) {
|
||||
for (int wday = Calendar.SUNDAY; wday <= Calendar.SATURDAY; wday++) {
|
||||
String name;
|
||||
name = CalendarDataUtility.retrieveJavaTimeFieldValueName(
|
||||
"gregory", Calendar.DAY_OF_WEEK,
|
||||
wday, textStyle.toCalendarStyle(), locale);
|
||||
if (name == null) {
|
||||
break;
|
||||
}
|
||||
map.put((long)toWeekDay(wday), name);
|
||||
}
|
||||
} else {
|
||||
Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
|
||||
"gregory", Calendar.DAY_OF_WEEK, textStyle.toCalendarStyle(), locale);
|
||||
if (displayNames != null) {
|
||||
for (Entry<String, Integer> entry : displayNames.entrySet()) {
|
||||
map.put((long)toWeekDay(entry.getValue()), entry.getKey());
|
||||
}
|
||||
} else {
|
||||
// Although probability is very less, but if other styles have duplicate names.
|
||||
// Get names one by one in that case.
|
||||
for (int wday = Calendar.SUNDAY; wday <= Calendar.SATURDAY; wday++) {
|
||||
String name;
|
||||
name = CalendarDataUtility.retrieveJavaTimeFieldValueName(
|
||||
"gregory", Calendar.DAY_OF_WEEK, wday, textStyle.toCalendarStyle(), locale);
|
||||
if (name == null) {
|
||||
break;
|
||||
}
|
||||
map.put((long)toWeekDay(wday), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!map.isEmpty()) {
|
||||
styleMap.put(textStyle, map);
|
||||
}
|
||||
}
|
||||
return new LocaleStore(styleMap);
|
||||
}
|
||||
|
||||
if (field == AMPM_OF_DAY) {
|
||||
for (TextStyle textStyle : TextStyle.values()) {
|
||||
if (textStyle.isStandalone()) {
|
||||
// Stand-alone isn't applicable to AM/PM.
|
||||
continue;
|
||||
}
|
||||
Map<String, Integer> displayNames = CalendarDataUtility.retrieveJavaTimeFieldValueNames(
|
||||
"gregory", Calendar.AM_PM, textStyle.toCalendarStyle(), locale);
|
||||
if (displayNames != null) {
|
||||
Map<Long, String> map = new HashMap<>();
|
||||
for (Entry<String, Integer> entry : displayNames.entrySet()) {
|
||||
map.put((long) entry.getValue(), entry.getKey());
|
||||
}
|
||||
if (!map.isEmpty()) {
|
||||
styleMap.put(textStyle, map);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new LocaleStore(styleMap);
|
||||
}
|
||||
|
||||
if (field == IsoFields.QUARTER_OF_YEAR) {
|
||||
// The order of keys must correspond to the TextStyle.values() order.
|
||||
final String[] keys = {
|
||||
"QuarterNames",
|
||||
"standalone.QuarterNames",
|
||||
"QuarterAbbreviations",
|
||||
"standalone.QuarterAbbreviations",
|
||||
"QuarterNarrows",
|
||||
"standalone.QuarterNarrows",
|
||||
};
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
String[] names = getLocalizedResource(keys[i], locale);
|
||||
if (names != null) {
|
||||
Map<Long, String> map = new HashMap<>();
|
||||
for (int q = 0; q < names.length; q++) {
|
||||
map.put((long) (q + 1), names[q]);
|
||||
}
|
||||
styleMap.put(TextStyle.values()[i], map);
|
||||
}
|
||||
}
|
||||
return new LocaleStore(styleMap);
|
||||
}
|
||||
|
||||
return ""; // null marker for map
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create an immutable entry.
|
||||
*
|
||||
* @param text the text, not null
|
||||
* @param field the field, not null
|
||||
* @return the entry, not null
|
||||
*/
|
||||
private static <A, B> Entry<A, B> createEntry(A text, B field) {
|
||||
return new SimpleImmutableEntry<>(text, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the localized resource of the given key and locale, or null
|
||||
* if no localized resource is available.
|
||||
*
|
||||
* @param key the key of the localized resource, not null
|
||||
* @param locale the locale, not null
|
||||
* @return the localized resource, or null if not available
|
||||
* @throws NullPointerException if key or locale is null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> T getLocalizedResource(String key, Locale locale) {
|
||||
LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
|
||||
.getLocaleResources(locale);
|
||||
ResourceBundle rb = lr.getJavaTimeFormatData();
|
||||
return rb.containsKey(key) ? (T) rb.getObject(key) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the text for a single locale.
|
||||
* <p>
|
||||
* Some fields have a textual representation, such as day-of-week or month-of-year.
|
||||
* These textual representations can be captured in this class for printing
|
||||
* and parsing.
|
||||
* <p>
|
||||
* This class is immutable and thread-safe.
|
||||
*/
|
||||
static final class LocaleStore {
|
||||
/**
|
||||
* Map of value to text.
|
||||
*/
|
||||
private final Map<TextStyle, Map<Long, String>> valueTextMap;
|
||||
/**
|
||||
* Parsable data.
|
||||
*/
|
||||
private final Map<TextStyle, List<Entry<String, Long>>> parsable;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param valueTextMap the map of values to text to store, assigned and not altered, not null
|
||||
*/
|
||||
LocaleStore(Map<TextStyle, Map<Long, String>> valueTextMap) {
|
||||
this.valueTextMap = valueTextMap;
|
||||
Map<TextStyle, List<Entry<String, Long>>> map = new HashMap<>();
|
||||
List<Entry<String, Long>> allList = new ArrayList<>();
|
||||
for (Map.Entry<TextStyle, Map<Long, String>> vtmEntry : valueTextMap.entrySet()) {
|
||||
Map<String, Entry<String, Long>> reverse = new HashMap<>();
|
||||
for (Map.Entry<Long, String> entry : vtmEntry.getValue().entrySet()) {
|
||||
if (reverse.put(entry.getValue(), createEntry(entry.getValue(), entry.getKey())) != null) {
|
||||
// TODO: BUG: this has no effect
|
||||
continue; // not parsable, try next style
|
||||
}
|
||||
}
|
||||
List<Entry<String, Long>> list = new ArrayList<>(reverse.values());
|
||||
Collections.sort(list, COMPARATOR);
|
||||
map.put(vtmEntry.getKey(), list);
|
||||
allList.addAll(list);
|
||||
map.put(null, allList);
|
||||
}
|
||||
Collections.sort(allList, COMPARATOR);
|
||||
this.parsable = map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the text for the specified field value, locale and style
|
||||
* for the purpose of printing.
|
||||
*
|
||||
* @param value the value to get text for, not null
|
||||
* @param style the style to get text for, not null
|
||||
* @return the text for the field value, null if no text found
|
||||
*/
|
||||
String getText(long value, TextStyle style) {
|
||||
Map<Long, String> map = valueTextMap.get(style);
|
||||
return map != null ? map.get(value) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an iterator of text to field for the specified style for the purpose of parsing.
|
||||
* <p>
|
||||
* The iterator must be returned in order from the longest text to the shortest.
|
||||
*
|
||||
* @param style the style to get text for, null for all parsable text
|
||||
* @return the iterator of text to field pairs, in order from longest text to shortest text,
|
||||
* null if the style is not parsable
|
||||
*/
|
||||
Iterator<Entry<String, Long>> getTextIterator(TextStyle style) {
|
||||
List<Entry<String, Long>> list = parsable.get(style);
|
||||
return list != null ? list.iterator() : null;
|
||||
}
|
||||
}
|
||||
}
|
381
src/java.base/share/classes/java/time/format/DecimalStyle.java
Normal file
381
src/java.base/share/classes/java/time/format/DecimalStyle.java
Normal file
|
@ -0,0 +1,381 @@
|
|||
/*
|
||||
* 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) 2008-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.format;
|
||||
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* Localized decimal style used in date and time formatting.
|
||||
* <p>
|
||||
* A significant part of dealing with dates and times is the localization.
|
||||
* This class acts as a central point for accessing the information.
|
||||
*
|
||||
* @implSpec
|
||||
* This class is immutable and thread-safe.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public final class DecimalStyle {
|
||||
|
||||
/**
|
||||
* The standard set of non-localized decimal style symbols.
|
||||
* <p>
|
||||
* This uses standard ASCII characters for zero, positive, negative and a dot for the decimal point.
|
||||
*/
|
||||
public static final DecimalStyle STANDARD = new DecimalStyle('0', '+', '-', '.');
|
||||
/**
|
||||
* The cache of DecimalStyle instances.
|
||||
*/
|
||||
private static final ConcurrentMap<Locale, DecimalStyle> CACHE = new ConcurrentHashMap<>(16, 0.75f, 2);
|
||||
|
||||
/**
|
||||
* The zero digit.
|
||||
*/
|
||||
private final char zeroDigit;
|
||||
/**
|
||||
* The positive sign.
|
||||
*/
|
||||
private final char positiveSign;
|
||||
/**
|
||||
* The negative sign.
|
||||
*/
|
||||
private final char negativeSign;
|
||||
/**
|
||||
* The decimal separator.
|
||||
*/
|
||||
private final char decimalSeparator;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Lists all the locales that are supported.
|
||||
* <p>
|
||||
* The locale 'en_US' will always be present.
|
||||
*
|
||||
* @return a Set of Locales for which localization is supported
|
||||
*/
|
||||
public static Set<Locale> getAvailableLocales() {
|
||||
Locale[] l = DecimalFormatSymbols.getAvailableLocales();
|
||||
Set<Locale> locales = new HashSet<>(l.length);
|
||||
Collections.addAll(locales, l);
|
||||
return locales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the DecimalStyle for the default
|
||||
* {@link java.util.Locale.Category#FORMAT FORMAT} locale.
|
||||
* <p>
|
||||
* This method provides access to locale sensitive decimal style symbols.
|
||||
* <p>
|
||||
* This is equivalent to calling
|
||||
* {@link #of(Locale)
|
||||
* of(Locale.getDefault(Locale.Category.FORMAT))}.
|
||||
*
|
||||
* @see java.util.Locale.Category#FORMAT
|
||||
* @return the decimal style, not null
|
||||
*/
|
||||
public static DecimalStyle ofDefaultLocale() {
|
||||
return of(Locale.getDefault(Locale.Category.FORMAT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the DecimalStyle for the specified locale.
|
||||
* <p>
|
||||
* This method provides access to locale sensitive decimal style symbols.
|
||||
*
|
||||
* @param locale the locale, not null
|
||||
* @return the decimal style, not null
|
||||
*/
|
||||
public static DecimalStyle of(Locale locale) {
|
||||
Objects.requireNonNull(locale, "locale");
|
||||
DecimalStyle info = CACHE.get(locale);
|
||||
if (info == null) {
|
||||
info = create(locale);
|
||||
CACHE.putIfAbsent(locale, info);
|
||||
info = CACHE.get(locale);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
private static DecimalStyle create(Locale locale) {
|
||||
DecimalFormatSymbols oldSymbols = DecimalFormatSymbols.getInstance(locale);
|
||||
char zeroDigit = oldSymbols.getZeroDigit();
|
||||
char positiveSign = '+';
|
||||
char negativeSign = oldSymbols.getMinusSign();
|
||||
char decimalSeparator = oldSymbols.getDecimalSeparator();
|
||||
if (zeroDigit == '0' && negativeSign == '-' && decimalSeparator == '.') {
|
||||
return STANDARD;
|
||||
}
|
||||
return new DecimalStyle(zeroDigit, positiveSign, negativeSign, decimalSeparator);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Restricted constructor.
|
||||
*
|
||||
* @param zeroChar the character to use for the digit of zero
|
||||
* @param positiveSignChar the character to use for the positive sign
|
||||
* @param negativeSignChar the character to use for the negative sign
|
||||
* @param decimalPointChar the character to use for the decimal point
|
||||
*/
|
||||
private DecimalStyle(char zeroChar, char positiveSignChar, char negativeSignChar, char decimalPointChar) {
|
||||
this.zeroDigit = zeroChar;
|
||||
this.positiveSign = positiveSignChar;
|
||||
this.negativeSign = negativeSignChar;
|
||||
this.decimalSeparator = decimalPointChar;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the character that represents zero.
|
||||
* <p>
|
||||
* The character used to represent digits may vary by culture.
|
||||
* This method specifies the zero character to use, which implies the characters for one to nine.
|
||||
*
|
||||
* @return the character for zero
|
||||
*/
|
||||
public char getZeroDigit() {
|
||||
return zeroDigit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the info with a new character that represents zero.
|
||||
* <p>
|
||||
* The character used to represent digits may vary by culture.
|
||||
* This method specifies the zero character to use, which implies the characters for one to nine.
|
||||
*
|
||||
* @param zeroDigit the character for zero
|
||||
* @return a copy with a new character that represents zero, not null
|
||||
|
||||
*/
|
||||
public DecimalStyle withZeroDigit(char zeroDigit) {
|
||||
if (zeroDigit == this.zeroDigit) {
|
||||
return this;
|
||||
}
|
||||
return new DecimalStyle(zeroDigit, positiveSign, negativeSign, decimalSeparator);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the character that represents the positive sign.
|
||||
* <p>
|
||||
* The character used to represent a positive number may vary by culture.
|
||||
* This method specifies the character to use.
|
||||
*
|
||||
* @return the character for the positive sign
|
||||
*/
|
||||
public char getPositiveSign() {
|
||||
return positiveSign;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the info with a new character that represents the positive sign.
|
||||
* <p>
|
||||
* The character used to represent a positive number may vary by culture.
|
||||
* This method specifies the character to use.
|
||||
*
|
||||
* @param positiveSign the character for the positive sign
|
||||
* @return a copy with a new character that represents the positive sign, not null
|
||||
*/
|
||||
public DecimalStyle withPositiveSign(char positiveSign) {
|
||||
if (positiveSign == this.positiveSign) {
|
||||
return this;
|
||||
}
|
||||
return new DecimalStyle(zeroDigit, positiveSign, negativeSign, decimalSeparator);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the character that represents the negative sign.
|
||||
* <p>
|
||||
* The character used to represent a negative number may vary by culture.
|
||||
* This method specifies the character to use.
|
||||
*
|
||||
* @return the character for the negative sign
|
||||
*/
|
||||
public char getNegativeSign() {
|
||||
return negativeSign;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the info with a new character that represents the negative sign.
|
||||
* <p>
|
||||
* The character used to represent a negative number may vary by culture.
|
||||
* This method specifies the character to use.
|
||||
*
|
||||
* @param negativeSign the character for the negative sign
|
||||
* @return a copy with a new character that represents the negative sign, not null
|
||||
*/
|
||||
public DecimalStyle withNegativeSign(char negativeSign) {
|
||||
if (negativeSign == this.negativeSign) {
|
||||
return this;
|
||||
}
|
||||
return new DecimalStyle(zeroDigit, positiveSign, negativeSign, decimalSeparator);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Gets the character that represents the decimal point.
|
||||
* <p>
|
||||
* The character used to represent a decimal point may vary by culture.
|
||||
* This method specifies the character to use.
|
||||
*
|
||||
* @return the character for the decimal point
|
||||
*/
|
||||
public char getDecimalSeparator() {
|
||||
return decimalSeparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the info with a new character that represents the decimal point.
|
||||
* <p>
|
||||
* The character used to represent a decimal point may vary by culture.
|
||||
* This method specifies the character to use.
|
||||
*
|
||||
* @param decimalSeparator the character for the decimal point
|
||||
* @return a copy with a new character that represents the decimal point, not null
|
||||
*/
|
||||
public DecimalStyle withDecimalSeparator(char decimalSeparator) {
|
||||
if (decimalSeparator == this.decimalSeparator) {
|
||||
return this;
|
||||
}
|
||||
return new DecimalStyle(zeroDigit, positiveSign, negativeSign, decimalSeparator);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Checks whether the character is a digit, based on the currently set zero character.
|
||||
*
|
||||
* @param ch the character to check
|
||||
* @return the value, 0 to 9, of the character, or -1 if not a digit
|
||||
*/
|
||||
int convertToDigit(char ch) {
|
||||
int val = ch - zeroDigit;
|
||||
return (val >= 0 && val <= 9) ? val : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the input numeric text to the internationalized form using the zero character.
|
||||
*
|
||||
* @param numericText the text, consisting of digits 0 to 9, to convert, not null
|
||||
* @return the internationalized text, not null
|
||||
*/
|
||||
String convertNumberToI18N(String numericText) {
|
||||
if (zeroDigit == '0') {
|
||||
return numericText;
|
||||
}
|
||||
int diff = zeroDigit - '0';
|
||||
char[] array = numericText.toCharArray();
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = (char) (array[i] + diff);
|
||||
}
|
||||
return new String(array);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Checks if this DecimalStyle is equal to another DecimalStyle.
|
||||
*
|
||||
* @param obj the object to check, null returns false
|
||||
* @return true if this is equal to the other date
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof DecimalStyle) {
|
||||
DecimalStyle other = (DecimalStyle) obj;
|
||||
return (zeroDigit == other.zeroDigit && positiveSign == other.positiveSign &&
|
||||
negativeSign == other.negativeSign && decimalSeparator == other.decimalSeparator);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A hash code for this DecimalStyle.
|
||||
*
|
||||
* @return a suitable hash code
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return zeroDigit + positiveSign + negativeSign + decimalSeparator;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Returns a string describing this DecimalStyle.
|
||||
*
|
||||
* @return a string description, not null
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DecimalStyle[" + zeroDigit + positiveSign + negativeSign + decimalSeparator + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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) 2008-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.format;
|
||||
|
||||
/**
|
||||
* Enumeration of the style of a localized date, time or date-time formatter.
|
||||
* <p>
|
||||
* These styles are used when obtaining a date-time style from configuration.
|
||||
* See {@link DateTimeFormatter} and {@link DateTimeFormatterBuilder} for usage.
|
||||
*
|
||||
* @implSpec
|
||||
* This is an immutable and thread-safe enum.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public enum FormatStyle {
|
||||
// ordered from large to small
|
||||
|
||||
/**
|
||||
* Full text style, with the most detail.
|
||||
* For example, the format might be 'Tuesday, April 12, 1952 AD' or '3:30:42pm PST'.
|
||||
*/
|
||||
FULL,
|
||||
/**
|
||||
* Long text style, with lots of detail.
|
||||
* For example, the format might be 'January 12, 1952'.
|
||||
*/
|
||||
LONG,
|
||||
/**
|
||||
* Medium text style, with some detail.
|
||||
* For example, the format might be 'Jan 12, 1952'.
|
||||
*/
|
||||
MEDIUM,
|
||||
/**
|
||||
* Short text style, typically numeric.
|
||||
* For example, the format might be '12.13.52' or '3:30pm'.
|
||||
*/
|
||||
SHORT;
|
||||
|
||||
}
|
687
src/java.base/share/classes/java/time/format/Parsed.java
Normal file
687
src/java.base/share/classes/java/time/format/Parsed.java
Normal file
|
@ -0,0 +1,687 @@
|
|||
/*
|
||||
* Copyright (c) 2012, 2015, 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) 2008-2013, 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.format;
|
||||
|
||||
import static java.time.temporal.ChronoField.AMPM_OF_DAY;
|
||||
import static java.time.temporal.ChronoField.CLOCK_HOUR_OF_AMPM;
|
||||
import static java.time.temporal.ChronoField.CLOCK_HOUR_OF_DAY;
|
||||
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;
|
||||
import static java.time.temporal.ChronoField.MILLI_OF_SECOND;
|
||||
import static java.time.temporal.ChronoField.MINUTE_OF_DAY;
|
||||
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
|
||||
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 java.time.DateTimeException;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.Period;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.chrono.ChronoLocalDate;
|
||||
import java.time.chrono.ChronoLocalDateTime;
|
||||
import java.time.chrono.ChronoZonedDateTime;
|
||||
import java.time.chrono.Chronology;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.time.temporal.TemporalField;
|
||||
import java.time.temporal.TemporalQueries;
|
||||
import java.time.temporal.TemporalQuery;
|
||||
import java.time.temporal.UnsupportedTemporalTypeException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A store of parsed data.
|
||||
* <p>
|
||||
* This class is used during parsing to collect the data. Part of the parsing process
|
||||
* involves handling optional blocks and multiple copies of the data get created to
|
||||
* support the necessary backtracking.
|
||||
* <p>
|
||||
* Once parsing is completed, this class can be used as the resultant {@code TemporalAccessor}.
|
||||
* In most cases, it is only exposed once the fields have been resolved.
|
||||
*
|
||||
* @implSpec
|
||||
* This class is a mutable context intended for use from a single thread.
|
||||
* Usage of the class is thread-safe within standard parsing as a new instance of this class
|
||||
* is automatically created for each parse and parsing is single-threaded
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
final class Parsed implements TemporalAccessor {
|
||||
// some fields are accessed using package scope from DateTimeParseContext
|
||||
|
||||
/**
|
||||
* The parsed fields.
|
||||
*/
|
||||
final Map<TemporalField, Long> fieldValues = new HashMap<>();
|
||||
/**
|
||||
* The parsed zone.
|
||||
*/
|
||||
ZoneId zone;
|
||||
/**
|
||||
* The parsed chronology.
|
||||
*/
|
||||
Chronology chrono;
|
||||
/**
|
||||
* Whether a leap-second is parsed.
|
||||
*/
|
||||
boolean leapSecond;
|
||||
/**
|
||||
* The resolver style to use.
|
||||
*/
|
||||
private ResolverStyle resolverStyle;
|
||||
/**
|
||||
* The resolved date.
|
||||
*/
|
||||
private ChronoLocalDate date;
|
||||
/**
|
||||
* The resolved time.
|
||||
*/
|
||||
private LocalTime time;
|
||||
/**
|
||||
* The excess period from time-only parsing.
|
||||
*/
|
||||
Period excessDays = Period.ZERO;
|
||||
|
||||
/**
|
||||
* Creates an instance.
|
||||
*/
|
||||
Parsed() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy.
|
||||
*/
|
||||
Parsed copy() {
|
||||
// only copy fields used in parsing stage
|
||||
Parsed cloned = new Parsed();
|
||||
cloned.fieldValues.putAll(this.fieldValues);
|
||||
cloned.zone = this.zone;
|
||||
cloned.chrono = this.chrono;
|
||||
cloned.leapSecond = this.leapSecond;
|
||||
return cloned;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public boolean isSupported(TemporalField field) {
|
||||
if (fieldValues.containsKey(field) ||
|
||||
(date != null && date.isSupported(field)) ||
|
||||
(time != null && time.isSupported(field))) {
|
||||
return true;
|
||||
}
|
||||
return field != null && (field instanceof ChronoField == false) && field.isSupportedBy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(TemporalField field) {
|
||||
Objects.requireNonNull(field, "field");
|
||||
Long value = fieldValues.get(field);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
if (date != null && date.isSupported(field)) {
|
||||
return date.getLong(field);
|
||||
}
|
||||
if (time != null && time.isSupported(field)) {
|
||||
return time.getLong(field);
|
||||
}
|
||||
if (field instanceof ChronoField) {
|
||||
throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
|
||||
}
|
||||
return field.getFrom(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> R query(TemporalQuery<R> query) {
|
||||
if (query == TemporalQueries.zoneId()) {
|
||||
return (R) zone;
|
||||
} else if (query == TemporalQueries.chronology()) {
|
||||
return (R) chrono;
|
||||
} else if (query == TemporalQueries.localDate()) {
|
||||
return (R) (date != null ? LocalDate.from(date) : null);
|
||||
} else if (query == TemporalQueries.localTime()) {
|
||||
return (R) time;
|
||||
} else if (query == TemporalQueries.offset()) {
|
||||
Long offsetSecs = fieldValues.get(OFFSET_SECONDS);
|
||||
if (offsetSecs != null) {
|
||||
return (R) ZoneOffset.ofTotalSeconds(offsetSecs.intValue());
|
||||
}
|
||||
if (zone instanceof ZoneOffset) {
|
||||
return (R)zone;
|
||||
}
|
||||
return query.queryFrom(this);
|
||||
} else if (query == TemporalQueries.zone()) {
|
||||
return query.queryFrom(this);
|
||||
} else if (query == TemporalQueries.precision()) {
|
||||
return null; // not a complete date/time
|
||||
}
|
||||
// inline TemporalAccessor.super.query(query) as an optimization
|
||||
// non-JDK classes are not permitted to make this optimization
|
||||
return query.queryFrom(this);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
/**
|
||||
* Resolves the fields in this context.
|
||||
*
|
||||
* @param resolverStyle the resolver style, not null
|
||||
* @param resolverFields the fields to use for resolving, null for all fields
|
||||
* @return this, for method chaining
|
||||
* @throws DateTimeException if resolving one field results in a value for
|
||||
* another field that is in conflict
|
||||
*/
|
||||
TemporalAccessor resolve(ResolverStyle resolverStyle, Set<TemporalField> resolverFields) {
|
||||
if (resolverFields != null) {
|
||||
fieldValues.keySet().retainAll(resolverFields);
|
||||
}
|
||||
this.resolverStyle = resolverStyle;
|
||||
resolveFields();
|
||||
resolveTimeLenient();
|
||||
crossCheck();
|
||||
resolvePeriod();
|
||||
resolveFractional();
|
||||
resolveInstant();
|
||||
return this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
private void resolveFields() {
|
||||
// resolve ChronoField
|
||||
resolveInstantFields();
|
||||
resolveDateFields();
|
||||
resolveTimeFields();
|
||||
|
||||
// if any other fields, handle them
|
||||
// any lenient date resolution should return epoch-day
|
||||
if (fieldValues.size() > 0) {
|
||||
int changedCount = 0;
|
||||
outer:
|
||||
while (changedCount < 50) {
|
||||
for (Map.Entry<TemporalField, Long> entry : fieldValues.entrySet()) {
|
||||
TemporalField targetField = entry.getKey();
|
||||
TemporalAccessor resolvedObject = targetField.resolve(fieldValues, this, resolverStyle);
|
||||
if (resolvedObject != null) {
|
||||
if (resolvedObject instanceof ChronoZonedDateTime) {
|
||||
ChronoZonedDateTime<?> czdt = (ChronoZonedDateTime<?>) resolvedObject;
|
||||
if (zone == null) {
|
||||
zone = czdt.getZone();
|
||||
} else if (zone.equals(czdt.getZone()) == false) {
|
||||
throw new DateTimeException("ChronoZonedDateTime must use the effective parsed zone: " + zone);
|
||||
}
|
||||
resolvedObject = czdt.toLocalDateTime();
|
||||
}
|
||||
if (resolvedObject instanceof ChronoLocalDateTime) {
|
||||
ChronoLocalDateTime<?> cldt = (ChronoLocalDateTime<?>) resolvedObject;
|
||||
updateCheckConflict(cldt.toLocalTime(), Period.ZERO);
|
||||
updateCheckConflict(cldt.toLocalDate());
|
||||
changedCount++;
|
||||
continue outer; // have to restart to avoid concurrent modification
|
||||
}
|
||||
if (resolvedObject instanceof ChronoLocalDate) {
|
||||
updateCheckConflict((ChronoLocalDate) resolvedObject);
|
||||
changedCount++;
|
||||
continue outer; // have to restart to avoid concurrent modification
|
||||
}
|
||||
if (resolvedObject instanceof LocalTime) {
|
||||
updateCheckConflict((LocalTime) resolvedObject, Period.ZERO);
|
||||
changedCount++;
|
||||
continue outer; // have to restart to avoid concurrent modification
|
||||
}
|
||||
throw new DateTimeException("Method resolve() can only return ChronoZonedDateTime, " +
|
||||
"ChronoLocalDateTime, ChronoLocalDate or LocalTime");
|
||||
} else if (fieldValues.containsKey(targetField) == false) {
|
||||
changedCount++;
|
||||
continue outer; // have to restart to avoid concurrent modification
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (changedCount == 50) { // catch infinite loops
|
||||
throw new DateTimeException("One of the parsed fields has an incorrectly implemented resolve method");
|
||||
}
|
||||
// if something changed then have to redo ChronoField resolve
|
||||
if (changedCount > 0) {
|
||||
resolveInstantFields();
|
||||
resolveDateFields();
|
||||
resolveTimeFields();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCheckConflict(TemporalField targetField, TemporalField changeField, Long changeValue) {
|
||||
Long old = fieldValues.put(changeField, changeValue);
|
||||
if (old != null && old.longValue() != changeValue.longValue()) {
|
||||
throw new DateTimeException("Conflict found: " + changeField + " " + old +
|
||||
" differs from " + changeField + " " + changeValue +
|
||||
" while resolving " + targetField);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
private void resolveInstantFields() {
|
||||
// resolve parsed instant seconds to date and time if zone available
|
||||
if (fieldValues.containsKey(INSTANT_SECONDS)) {
|
||||
if (zone != null) {
|
||||
resolveInstantFields0(zone);
|
||||
} else {
|
||||
Long offsetSecs = fieldValues.get(OFFSET_SECONDS);
|
||||
if (offsetSecs != null) {
|
||||
ZoneOffset offset = ZoneOffset.ofTotalSeconds(offsetSecs.intValue());
|
||||
resolveInstantFields0(offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveInstantFields0(ZoneId selectedZone) {
|
||||
Instant instant = Instant.ofEpochSecond(fieldValues.remove(INSTANT_SECONDS));
|
||||
ChronoZonedDateTime<?> zdt = chrono.zonedDateTime(instant, selectedZone);
|
||||
updateCheckConflict(zdt.toLocalDate());
|
||||
updateCheckConflict(INSTANT_SECONDS, SECOND_OF_DAY, (long) zdt.toLocalTime().toSecondOfDay());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
private void resolveDateFields() {
|
||||
updateCheckConflict(chrono.resolveDate(fieldValues, resolverStyle));
|
||||
}
|
||||
|
||||
private void updateCheckConflict(ChronoLocalDate cld) {
|
||||
if (date != null) {
|
||||
if (cld != null && date.equals(cld) == false) {
|
||||
throw new DateTimeException("Conflict found: Fields resolved to two different dates: " + date + " " + cld);
|
||||
}
|
||||
} else if (cld != null) {
|
||||
if (chrono.equals(cld.getChronology()) == false) {
|
||||
throw new DateTimeException("ChronoLocalDate must use the effective parsed chronology: " + chrono);
|
||||
}
|
||||
date = cld;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
private void resolveTimeFields() {
|
||||
// simplify fields
|
||||
if (fieldValues.containsKey(CLOCK_HOUR_OF_DAY)) {
|
||||
// lenient allows anything, smart allows 0-24, strict allows 1-24
|
||||
long ch = fieldValues.remove(CLOCK_HOUR_OF_DAY);
|
||||
if (resolverStyle == ResolverStyle.STRICT || (resolverStyle == ResolverStyle.SMART && ch != 0)) {
|
||||
CLOCK_HOUR_OF_DAY.checkValidValue(ch);
|
||||
}
|
||||
updateCheckConflict(CLOCK_HOUR_OF_DAY, HOUR_OF_DAY, ch == 24 ? 0 : ch);
|
||||
}
|
||||
if (fieldValues.containsKey(CLOCK_HOUR_OF_AMPM)) {
|
||||
// lenient allows anything, smart allows 0-12, strict allows 1-12
|
||||
long ch = fieldValues.remove(CLOCK_HOUR_OF_AMPM);
|
||||
if (resolverStyle == ResolverStyle.STRICT || (resolverStyle == ResolverStyle.SMART && ch != 0)) {
|
||||
CLOCK_HOUR_OF_AMPM.checkValidValue(ch);
|
||||
}
|
||||
updateCheckConflict(CLOCK_HOUR_OF_AMPM, HOUR_OF_AMPM, ch == 12 ? 0 : ch);
|
||||
}
|
||||
if (fieldValues.containsKey(AMPM_OF_DAY) && fieldValues.containsKey(HOUR_OF_AMPM)) {
|
||||
long ap = fieldValues.remove(AMPM_OF_DAY);
|
||||
long hap = fieldValues.remove(HOUR_OF_AMPM);
|
||||
if (resolverStyle == ResolverStyle.LENIENT) {
|
||||
updateCheckConflict(AMPM_OF_DAY, HOUR_OF_DAY, Math.addExact(Math.multiplyExact(ap, 12), hap));
|
||||
} else { // STRICT or SMART
|
||||
AMPM_OF_DAY.checkValidValue(ap);
|
||||
HOUR_OF_AMPM.checkValidValue(ap);
|
||||
updateCheckConflict(AMPM_OF_DAY, HOUR_OF_DAY, ap * 12 + hap);
|
||||
}
|
||||
}
|
||||
if (fieldValues.containsKey(NANO_OF_DAY)) {
|
||||
long nod = fieldValues.remove(NANO_OF_DAY);
|
||||
if (resolverStyle != ResolverStyle.LENIENT) {
|
||||
NANO_OF_DAY.checkValidValue(nod);
|
||||
}
|
||||
updateCheckConflict(NANO_OF_DAY, HOUR_OF_DAY, nod / 3600_000_000_000L);
|
||||
updateCheckConflict(NANO_OF_DAY, MINUTE_OF_HOUR, (nod / 60_000_000_000L) % 60);
|
||||
updateCheckConflict(NANO_OF_DAY, SECOND_OF_MINUTE, (nod / 1_000_000_000L) % 60);
|
||||
updateCheckConflict(NANO_OF_DAY, NANO_OF_SECOND, nod % 1_000_000_000L);
|
||||
}
|
||||
if (fieldValues.containsKey(MICRO_OF_DAY)) {
|
||||
long cod = fieldValues.remove(MICRO_OF_DAY);
|
||||
if (resolverStyle != ResolverStyle.LENIENT) {
|
||||
MICRO_OF_DAY.checkValidValue(cod);
|
||||
}
|
||||
updateCheckConflict(MICRO_OF_DAY, SECOND_OF_DAY, cod / 1_000_000L);
|
||||
updateCheckConflict(MICRO_OF_DAY, MICRO_OF_SECOND, cod % 1_000_000L);
|
||||
}
|
||||
if (fieldValues.containsKey(MILLI_OF_DAY)) {
|
||||
long lod = fieldValues.remove(MILLI_OF_DAY);
|
||||
if (resolverStyle != ResolverStyle.LENIENT) {
|
||||
MILLI_OF_DAY.checkValidValue(lod);
|
||||
}
|
||||
updateCheckConflict(MILLI_OF_DAY, SECOND_OF_DAY, lod / 1_000);
|
||||
updateCheckConflict(MILLI_OF_DAY, MILLI_OF_SECOND, lod % 1_000);
|
||||
}
|
||||
if (fieldValues.containsKey(SECOND_OF_DAY)) {
|
||||
long sod = fieldValues.remove(SECOND_OF_DAY);
|
||||
if (resolverStyle != ResolverStyle.LENIENT) {
|
||||
SECOND_OF_DAY.checkValidValue(sod);
|
||||
}
|
||||
updateCheckConflict(SECOND_OF_DAY, HOUR_OF_DAY, sod / 3600);
|
||||
updateCheckConflict(SECOND_OF_DAY, MINUTE_OF_HOUR, (sod / 60) % 60);
|
||||
updateCheckConflict(SECOND_OF_DAY, SECOND_OF_MINUTE, sod % 60);
|
||||
}
|
||||
if (fieldValues.containsKey(MINUTE_OF_DAY)) {
|
||||
long mod = fieldValues.remove(MINUTE_OF_DAY);
|
||||
if (resolverStyle != ResolverStyle.LENIENT) {
|
||||
MINUTE_OF_DAY.checkValidValue(mod);
|
||||
}
|
||||
updateCheckConflict(MINUTE_OF_DAY, HOUR_OF_DAY, mod / 60);
|
||||
updateCheckConflict(MINUTE_OF_DAY, MINUTE_OF_HOUR, mod % 60);
|
||||
}
|
||||
|
||||
// combine partial second fields strictly, leaving lenient expansion to later
|
||||
if (fieldValues.containsKey(NANO_OF_SECOND)) {
|
||||
long nos = fieldValues.get(NANO_OF_SECOND);
|
||||
if (resolverStyle != ResolverStyle.LENIENT) {
|
||||
NANO_OF_SECOND.checkValidValue(nos);
|
||||
}
|
||||
if (fieldValues.containsKey(MICRO_OF_SECOND)) {
|
||||
long cos = fieldValues.remove(MICRO_OF_SECOND);
|
||||
if (resolverStyle != ResolverStyle.LENIENT) {
|
||||
MICRO_OF_SECOND.checkValidValue(cos);
|
||||
}
|
||||
nos = cos * 1000 + (nos % 1000);
|
||||
updateCheckConflict(MICRO_OF_SECOND, NANO_OF_SECOND, nos);
|
||||
}
|
||||
if (fieldValues.containsKey(MILLI_OF_SECOND)) {
|
||||
long los = fieldValues.remove(MILLI_OF_SECOND);
|
||||
if (resolverStyle != ResolverStyle.LENIENT) {
|
||||
MILLI_OF_SECOND.checkValidValue(los);
|
||||
}
|
||||
updateCheckConflict(MILLI_OF_SECOND, NANO_OF_SECOND, los * 1_000_000L + (nos % 1_000_000L));
|
||||
}
|
||||
}
|
||||
|
||||
// convert to time if all four fields available (optimization)
|
||||
if (fieldValues.containsKey(HOUR_OF_DAY) && fieldValues.containsKey(MINUTE_OF_HOUR) &&
|
||||
fieldValues.containsKey(SECOND_OF_MINUTE) && fieldValues.containsKey(NANO_OF_SECOND)) {
|
||||
long hod = fieldValues.remove(HOUR_OF_DAY);
|
||||
long moh = fieldValues.remove(MINUTE_OF_HOUR);
|
||||
long som = fieldValues.remove(SECOND_OF_MINUTE);
|
||||
long nos = fieldValues.remove(NANO_OF_SECOND);
|
||||
resolveTime(hod, moh, som, nos);
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveTimeLenient() {
|
||||
// leniently create a time from incomplete information
|
||||
// done after everything else as it creates information from nothing
|
||||
// which would break updateCheckConflict(field)
|
||||
|
||||
if (time == null) {
|
||||
// NANO_OF_SECOND merged with MILLI/MICRO above
|
||||
if (fieldValues.containsKey(MILLI_OF_SECOND)) {
|
||||
long los = fieldValues.remove(MILLI_OF_SECOND);
|
||||
if (fieldValues.containsKey(MICRO_OF_SECOND)) {
|
||||
// merge milli-of-second and micro-of-second for better error message
|
||||
long cos = los * 1_000 + (fieldValues.get(MICRO_OF_SECOND) % 1_000);
|
||||
updateCheckConflict(MILLI_OF_SECOND, MICRO_OF_SECOND, cos);
|
||||
fieldValues.remove(MICRO_OF_SECOND);
|
||||
fieldValues.put(NANO_OF_SECOND, cos * 1_000L);
|
||||
} else {
|
||||
// convert milli-of-second to nano-of-second
|
||||
fieldValues.put(NANO_OF_SECOND, los * 1_000_000L);
|
||||
}
|
||||
} else if (fieldValues.containsKey(MICRO_OF_SECOND)) {
|
||||
// convert micro-of-second to nano-of-second
|
||||
long cos = fieldValues.remove(MICRO_OF_SECOND);
|
||||
fieldValues.put(NANO_OF_SECOND, cos * 1_000L);
|
||||
}
|
||||
|
||||
// merge hour/minute/second/nano leniently
|
||||
Long hod = fieldValues.get(HOUR_OF_DAY);
|
||||
if (hod != null) {
|
||||
Long moh = fieldValues.get(MINUTE_OF_HOUR);
|
||||
Long som = fieldValues.get(SECOND_OF_MINUTE);
|
||||
Long nos = fieldValues.get(NANO_OF_SECOND);
|
||||
|
||||
// check for invalid combinations that cannot be defaulted
|
||||
if ((moh == null && (som != null || nos != null)) ||
|
||||
(moh != null && som == null && nos != null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// default as necessary and build time
|
||||
long mohVal = (moh != null ? moh : 0);
|
||||
long somVal = (som != null ? som : 0);
|
||||
long nosVal = (nos != null ? nos : 0);
|
||||
resolveTime(hod, mohVal, somVal, nosVal);
|
||||
fieldValues.remove(HOUR_OF_DAY);
|
||||
fieldValues.remove(MINUTE_OF_HOUR);
|
||||
fieldValues.remove(SECOND_OF_MINUTE);
|
||||
fieldValues.remove(NANO_OF_SECOND);
|
||||
}
|
||||
}
|
||||
|
||||
// validate remaining
|
||||
if (resolverStyle != ResolverStyle.LENIENT && fieldValues.size() > 0) {
|
||||
for (Entry<TemporalField, Long> entry : fieldValues.entrySet()) {
|
||||
TemporalField field = entry.getKey();
|
||||
if (field instanceof ChronoField && field.isTimeBased()) {
|
||||
((ChronoField) field).checkValidValue(entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveTime(long hod, long moh, long som, long nos) {
|
||||
if (resolverStyle == ResolverStyle.LENIENT) {
|
||||
long totalNanos = Math.multiplyExact(hod, 3600_000_000_000L);
|
||||
totalNanos = Math.addExact(totalNanos, Math.multiplyExact(moh, 60_000_000_000L));
|
||||
totalNanos = Math.addExact(totalNanos, Math.multiplyExact(som, 1_000_000_000L));
|
||||
totalNanos = Math.addExact(totalNanos, nos);
|
||||
int excessDays = (int) Math.floorDiv(totalNanos, 86400_000_000_000L); // safe int cast
|
||||
long nod = Math.floorMod(totalNanos, 86400_000_000_000L);
|
||||
updateCheckConflict(LocalTime.ofNanoOfDay(nod), Period.ofDays(excessDays));
|
||||
} else { // STRICT or SMART
|
||||
int mohVal = MINUTE_OF_HOUR.checkValidIntValue(moh);
|
||||
int nosVal = NANO_OF_SECOND.checkValidIntValue(nos);
|
||||
// handle 24:00 end of day
|
||||
if (resolverStyle == ResolverStyle.SMART && hod == 24 && mohVal == 0 && som == 0 && nosVal == 0) {
|
||||
updateCheckConflict(LocalTime.MIDNIGHT, Period.ofDays(1));
|
||||
} else {
|
||||
int hodVal = HOUR_OF_DAY.checkValidIntValue(hod);
|
||||
int somVal = SECOND_OF_MINUTE.checkValidIntValue(som);
|
||||
updateCheckConflict(LocalTime.of(hodVal, mohVal, somVal, nosVal), Period.ZERO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resolvePeriod() {
|
||||
// add whole days if we have both date and time
|
||||
if (date != null && time != null && excessDays.isZero() == false) {
|
||||
date = date.plus(excessDays);
|
||||
excessDays = Period.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveFractional() {
|
||||
// ensure fractional seconds available as ChronoField requires
|
||||
// resolveTimeLenient() will have merged MICRO_OF_SECOND/MILLI_OF_SECOND to NANO_OF_SECOND
|
||||
if (time == null &&
|
||||
(fieldValues.containsKey(INSTANT_SECONDS) ||
|
||||
fieldValues.containsKey(SECOND_OF_DAY) ||
|
||||
fieldValues.containsKey(SECOND_OF_MINUTE))) {
|
||||
if (fieldValues.containsKey(NANO_OF_SECOND)) {
|
||||
long nos = fieldValues.get(NANO_OF_SECOND);
|
||||
fieldValues.put(MICRO_OF_SECOND, nos / 1000);
|
||||
fieldValues.put(MILLI_OF_SECOND, nos / 1000000);
|
||||
} else {
|
||||
fieldValues.put(NANO_OF_SECOND, 0L);
|
||||
fieldValues.put(MICRO_OF_SECOND, 0L);
|
||||
fieldValues.put(MILLI_OF_SECOND, 0L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveInstant() {
|
||||
// add instant seconds if we have date, time and zone
|
||||
// Offset (if present) will be given priority over the zone.
|
||||
if (date != null && time != null) {
|
||||
Long offsetSecs = fieldValues.get(OFFSET_SECONDS);
|
||||
if (offsetSecs != null) {
|
||||
ZoneOffset offset = ZoneOffset.ofTotalSeconds(offsetSecs.intValue());
|
||||
long instant = date.atTime(time).atZone(offset).toEpochSecond();
|
||||
fieldValues.put(INSTANT_SECONDS, instant);
|
||||
} else {
|
||||
if (zone != null) {
|
||||
long instant = date.atTime(time).atZone(zone).toEpochSecond();
|
||||
fieldValues.put(INSTANT_SECONDS, instant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCheckConflict(LocalTime timeToSet, Period periodToSet) {
|
||||
if (time != null) {
|
||||
if (time.equals(timeToSet) == false) {
|
||||
throw new DateTimeException("Conflict found: Fields resolved to different times: " + time + " " + timeToSet);
|
||||
}
|
||||
if (excessDays.isZero() == false && periodToSet.isZero() == false && excessDays.equals(periodToSet) == false) {
|
||||
throw new DateTimeException("Conflict found: Fields resolved to different excess periods: " + excessDays + " " + periodToSet);
|
||||
} else {
|
||||
excessDays = periodToSet;
|
||||
}
|
||||
} else {
|
||||
time = timeToSet;
|
||||
excessDays = periodToSet;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
private void crossCheck() {
|
||||
// only cross-check date, time and date-time
|
||||
// avoid object creation if possible
|
||||
if (date != null) {
|
||||
crossCheck(date);
|
||||
}
|
||||
if (time != null) {
|
||||
crossCheck(time);
|
||||
if (date != null && fieldValues.size() > 0) {
|
||||
crossCheck(date.atTime(time));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void crossCheck(TemporalAccessor target) {
|
||||
for (Iterator<Entry<TemporalField, Long>> it = fieldValues.entrySet().iterator(); it.hasNext(); ) {
|
||||
Entry<TemporalField, Long> entry = it.next();
|
||||
TemporalField field = entry.getKey();
|
||||
if (target.isSupported(field)) {
|
||||
long val1;
|
||||
try {
|
||||
val1 = target.getLong(field);
|
||||
} catch (RuntimeException ex) {
|
||||
continue;
|
||||
}
|
||||
long val2 = entry.getValue();
|
||||
if (val1 != val2) {
|
||||
throw new DateTimeException("Conflict found: Field " + field + " " + val1 +
|
||||
" differs from " + field + " " + val2 + " derived from " + target);
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder(64);
|
||||
buf.append(fieldValues).append(',').append(chrono);
|
||||
if (zone != null) {
|
||||
buf.append(',').append(zone);
|
||||
}
|
||||
if (date != null || time != null) {
|
||||
buf.append(" resolved to ");
|
||||
if (date != null) {
|
||||
buf.append(date);
|
||||
if (time != null) {
|
||||
buf.append('T').append(time);
|
||||
}
|
||||
} else {
|
||||
buf.append(time);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
116
src/java.base/share/classes/java/time/format/ResolverStyle.java
Normal file
116
src/java.base/share/classes/java/time/format/ResolverStyle.java
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 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) 2008-2013, 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.format;
|
||||
|
||||
/**
|
||||
* Enumeration of different ways to resolve dates and times.
|
||||
* <p>
|
||||
* Parsing a text string occurs in two phases.
|
||||
* Phase 1 is a basic text parse according to the fields added to the builder.
|
||||
* Phase 2 resolves the parsed field-value pairs into date and/or time objects.
|
||||
* This style is used to control how phase 2, resolving, happens.
|
||||
*
|
||||
* @implSpec
|
||||
* This is an immutable and thread-safe enum.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public enum ResolverStyle {
|
||||
|
||||
/**
|
||||
* Style to resolve dates and times strictly.
|
||||
* <p>
|
||||
* Using strict resolution will ensure that all parsed values are within
|
||||
* the outer range of valid values for the field. Individual fields may
|
||||
* be further processed for strictness.
|
||||
* <p>
|
||||
* For example, resolving year-month and day-of-month in the ISO calendar
|
||||
* system using strict mode will ensure that the day-of-month is valid
|
||||
* for the year-month, rejecting invalid values.
|
||||
*/
|
||||
STRICT,
|
||||
/**
|
||||
* Style to resolve dates and times in a smart, or intelligent, manner.
|
||||
* <p>
|
||||
* Using smart resolution will perform the sensible default for each
|
||||
* field, which may be the same as strict, the same as lenient, or a third
|
||||
* behavior. Individual fields will interpret this differently.
|
||||
* <p>
|
||||
* For example, resolving year-month and day-of-month in the ISO calendar
|
||||
* system using smart mode will ensure that the day-of-month is from
|
||||
* 1 to 31, converting any value beyond the last valid day-of-month to be
|
||||
* the last valid day-of-month.
|
||||
*/
|
||||
SMART,
|
||||
/**
|
||||
* Style to resolve dates and times leniently.
|
||||
* <p>
|
||||
* Using lenient resolution will resolve the values in an appropriate
|
||||
* lenient manner. Individual fields will interpret this differently.
|
||||
* <p>
|
||||
* For example, lenient mode allows the month in the ISO calendar system
|
||||
* to be outside the range 1 to 12.
|
||||
* For example, month 15 is treated as being 3 months after month 12.
|
||||
*/
|
||||
LENIENT;
|
||||
|
||||
}
|
139
src/java.base/share/classes/java/time/format/SignStyle.java
Normal file
139
src/java.base/share/classes/java/time/format/SignStyle.java
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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) 2008-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.format;
|
||||
|
||||
/**
|
||||
* Enumeration of ways to handle the positive/negative sign.
|
||||
* <p>
|
||||
* The formatting engine allows the positive and negative signs of numbers
|
||||
* to be controlled using this enum.
|
||||
* See {@link DateTimeFormatterBuilder} for usage.
|
||||
*
|
||||
* @implSpec
|
||||
* This is an immutable and thread-safe enum.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public enum SignStyle {
|
||||
|
||||
/**
|
||||
* Style to output the sign only if the value is negative.
|
||||
* <p>
|
||||
* In strict parsing, the negative sign will be accepted and the positive sign rejected.
|
||||
* In lenient parsing, any sign will be accepted.
|
||||
*/
|
||||
NORMAL,
|
||||
/**
|
||||
* Style to always output the sign, where zero will output '+'.
|
||||
* <p>
|
||||
* In strict parsing, the absence of a sign will be rejected.
|
||||
* In lenient parsing, any sign will be accepted, with the absence
|
||||
* of a sign treated as a positive number.
|
||||
*/
|
||||
ALWAYS,
|
||||
/**
|
||||
* Style to never output sign, only outputting the absolute value.
|
||||
* <p>
|
||||
* In strict parsing, any sign will be rejected.
|
||||
* In lenient parsing, any sign will be accepted unless the width is fixed.
|
||||
*/
|
||||
NEVER,
|
||||
/**
|
||||
* Style to block negative values, throwing an exception on printing.
|
||||
* <p>
|
||||
* In strict parsing, any sign will be rejected.
|
||||
* In lenient parsing, any sign will be accepted unless the width is fixed.
|
||||
*/
|
||||
NOT_NEGATIVE,
|
||||
/**
|
||||
* Style to always output the sign if the value exceeds the pad width.
|
||||
* A negative value will always output the '-' sign.
|
||||
* <p>
|
||||
* In strict parsing, the sign will be rejected unless the pad width is exceeded.
|
||||
* In lenient parsing, any sign will be accepted, with the absence
|
||||
* of a sign treated as a positive number.
|
||||
*/
|
||||
EXCEEDS_PAD;
|
||||
|
||||
/**
|
||||
* Parse helper.
|
||||
*
|
||||
* @param positive true if positive sign parsed, false for negative sign
|
||||
* @param strict true if strict, false if lenient
|
||||
* @param fixedWidth true if fixed width, false if not
|
||||
* @return
|
||||
*/
|
||||
boolean parse(boolean positive, boolean strict, boolean fixedWidth) {
|
||||
switch (ordinal()) {
|
||||
case 0: // NORMAL
|
||||
// valid if negative or (positive and lenient)
|
||||
return !positive || !strict;
|
||||
case 1: // ALWAYS
|
||||
case 4: // EXCEEDS_PAD
|
||||
return true;
|
||||
default:
|
||||
// valid if lenient and not fixed width
|
||||
return !strict && !fixedWidth;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
177
src/java.base/share/classes/java/time/format/TextStyle.java
Normal file
177
src/java.base/share/classes/java/time/format/TextStyle.java
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* 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) 2008-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.format;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* Enumeration of the style of text formatting and parsing.
|
||||
* <p>
|
||||
* Text styles define three sizes for the formatted text - 'full', 'short' and 'narrow'.
|
||||
* Each of these three sizes is available in both 'standard' and 'stand-alone' variations.
|
||||
* <p>
|
||||
* The difference between the three sizes is obvious in most languages.
|
||||
* For example, in English the 'full' month is 'January', the 'short' month is 'Jan'
|
||||
* and the 'narrow' month is 'J'. Note that the narrow size is often not unique.
|
||||
* For example, 'January', 'June' and 'July' all have the 'narrow' text 'J'.
|
||||
* <p>
|
||||
* The difference between the 'standard' and 'stand-alone' forms is trickier to describe
|
||||
* as there is no difference in English. However, in other languages there is a difference
|
||||
* in the word used when the text is used alone, as opposed to in a complete date.
|
||||
* For example, the word used for a month when used alone in a date picker is different
|
||||
* to the word used for month in association with a day and year in a date.
|
||||
*
|
||||
* @implSpec
|
||||
* This is immutable and thread-safe enum.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public enum TextStyle {
|
||||
// ordered from large to small
|
||||
// ordered so that bit 0 of the ordinal indicates stand-alone.
|
||||
|
||||
/**
|
||||
* Full text, typically the full description.
|
||||
* For example, day-of-week Monday might output "Monday".
|
||||
*/
|
||||
FULL(Calendar.LONG_FORMAT, 0),
|
||||
/**
|
||||
* Full text for stand-alone use, typically the full description.
|
||||
* For example, day-of-week Monday might output "Monday".
|
||||
*/
|
||||
FULL_STANDALONE(Calendar.LONG_STANDALONE, 0),
|
||||
/**
|
||||
* Short text, typically an abbreviation.
|
||||
* For example, day-of-week Monday might output "Mon".
|
||||
*/
|
||||
SHORT(Calendar.SHORT_FORMAT, 1),
|
||||
/**
|
||||
* Short text for stand-alone use, typically an abbreviation.
|
||||
* For example, day-of-week Monday might output "Mon".
|
||||
*/
|
||||
SHORT_STANDALONE(Calendar.SHORT_STANDALONE, 1),
|
||||
/**
|
||||
* Narrow text, typically a single letter.
|
||||
* For example, day-of-week Monday might output "M".
|
||||
*/
|
||||
NARROW(Calendar.NARROW_FORMAT, 1),
|
||||
/**
|
||||
* Narrow text for stand-alone use, typically a single letter.
|
||||
* For example, day-of-week Monday might output "M".
|
||||
*/
|
||||
NARROW_STANDALONE(Calendar.NARROW_STANDALONE, 1);
|
||||
|
||||
private final int calendarStyle;
|
||||
private final int zoneNameStyleIndex;
|
||||
|
||||
private TextStyle(int calendarStyle, int zoneNameStyleIndex) {
|
||||
this.calendarStyle = calendarStyle;
|
||||
this.zoneNameStyleIndex = zoneNameStyleIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the Style is a stand-alone style.
|
||||
* @return true if the style is a stand-alone style.
|
||||
*/
|
||||
public boolean isStandalone() {
|
||||
return (ordinal() & 1) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stand-alone style with the same size.
|
||||
* @return the stand-alone style with the same size
|
||||
*/
|
||||
public TextStyle asStandalone() {
|
||||
return TextStyle.values()[ordinal() | 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the normal style with the same size.
|
||||
*
|
||||
* @return the normal style with the same size
|
||||
*/
|
||||
public TextStyle asNormal() {
|
||||
return TextStyle.values()[ordinal() & ~1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code Calendar} style corresponding to this {@code TextStyle}.
|
||||
*
|
||||
* @return the corresponding {@code Calendar} style
|
||||
*/
|
||||
int toCalendarStyle() {
|
||||
return calendarStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the relative index value to an element of the {@link
|
||||
* java.text.DateFormatSymbols#getZoneStrings() DateFormatSymbols.getZoneStrings()}
|
||||
* value, 0 for long names and 1 for short names (abbreviations). Note that these values
|
||||
* do <em>not</em> correspond to the {@link java.util.TimeZone#LONG} and {@link
|
||||
* java.util.TimeZone#SHORT} values.
|
||||
*
|
||||
* @return the relative index value to time zone names array
|
||||
*/
|
||||
int zoneNameStyleIndex() {
|
||||
return zoneNameStyleIndex;
|
||||
}
|
||||
}
|
799
src/java.base/share/classes/java/time/format/ZoneName.java
Normal file
799
src/java.base/share/classes/java/time/format/ZoneName.java
Normal file
|
@ -0,0 +1,799 @@
|
|||
/*
|
||||
* Copyright (c) 2013, 2016, 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.
|
||||
*/
|
||||
package java.time.format;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A helper class to map a zone name to metazone and back to the
|
||||
* appropriate zone id for the particular locale.
|
||||
* <p>
|
||||
* The zid<->metazone mappings are based on CLDR metaZones.xml.
|
||||
* The alias mappings are based on Link entries in tzdb data files.
|
||||
*/
|
||||
class ZoneName {
|
||||
|
||||
public static String toZid(String zid, Locale locale) {
|
||||
String mzone = zidToMzone.get(zid);
|
||||
if (mzone == null && aliases.containsKey(zid)) {
|
||||
zid = aliases.get(zid);
|
||||
mzone = zidToMzone.get(zid);
|
||||
}
|
||||
if (mzone != null) {
|
||||
Map<String, String> map = mzoneToZidL.get(mzone);
|
||||
if (map != null && map.containsKey(locale.getCountry())) {
|
||||
zid = map.get(locale.getCountry());
|
||||
} else {
|
||||
zid = mzoneToZid.get(mzone);
|
||||
}
|
||||
}
|
||||
return toZid(zid);
|
||||
}
|
||||
|
||||
public static String toZid(String zid) {
|
||||
if (aliases.containsKey(zid)) {
|
||||
return aliases.get(zid);
|
||||
}
|
||||
return zid;
|
||||
}
|
||||
|
||||
private static final String[] zidMap = new String[] {
|
||||
"Pacific/Rarotonga", "Cook", "Pacific/Rarotonga",
|
||||
"Europe/Tirane", "Europe_Central", "Europe/Paris",
|
||||
"America/Recife", "Brasilia", "America/Sao_Paulo",
|
||||
"America/Argentina/San_Juan", "Argentina", "America/Buenos_Aires",
|
||||
"Asia/Kolkata", "India", "Asia/Calcutta",
|
||||
"America/Guayaquil", "Ecuador", "America/Guayaquil",
|
||||
"Europe/Samara", "Moscow", "Europe/Moscow",
|
||||
"Indian/Antananarivo", "Africa_Eastern", "Africa/Nairobi",
|
||||
"America/Santa_Isabel", "America_Pacific", "America/Los_Angeles",
|
||||
"America/Montserrat", "Atlantic", "America/Halifax",
|
||||
"Pacific/Port_Moresby", "Papua_New_Guinea", "Pacific/Port_Moresby",
|
||||
"Europe/Paris", "Europe_Central", "Europe/Paris",
|
||||
"America/Argentina/Salta", "Argentina", "America/Buenos_Aires",
|
||||
"Asia/Omsk", "Omsk", "Asia/Omsk",
|
||||
"Africa/Ceuta", "Europe_Central", "Europe/Paris",
|
||||
"America/Argentina/San_Luis", "Argentina_Western", "America/Argentina/San_Luis",
|
||||
"America/Atikokan", "America_Eastern", "America/New_York",
|
||||
"Asia/Vladivostok", "Vladivostok", "Asia/Vladivostok",
|
||||
"America/Argentina/Jujuy", "Argentina", "America/Buenos_Aires",
|
||||
"Asia/Almaty", "Kazakhstan_Eastern", "Asia/Almaty",
|
||||
"Atlantic/Canary", "Europe_Western", "Atlantic/Canary",
|
||||
"Asia/Bangkok", "Indochina", "Asia/Saigon",
|
||||
"America/Caracas", "Venezuela", "America/Caracas",
|
||||
"Australia/Hobart", "Australia_Eastern", "Australia/Sydney",
|
||||
"America/Havana", "Cuba", "America/Havana",
|
||||
"Africa/Malabo", "Africa_Western", "Africa/Lagos",
|
||||
"Australia/Lord_Howe", "Lord_Howe", "Australia/Lord_Howe",
|
||||
"Pacific/Fakaofo", "Tokelau", "Pacific/Fakaofo",
|
||||
"America/Matamoros", "America_Central", "America/Chicago",
|
||||
"America/Guadeloupe", "Atlantic", "America/Halifax",
|
||||
"Europe/Helsinki", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Asia/Calcutta", "India", "Asia/Calcutta",
|
||||
"Africa/Kinshasa", "Africa_Western", "Africa/Lagos",
|
||||
"America/Miquelon", "Pierre_Miquelon", "America/Miquelon",
|
||||
"Europe/Athens", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Asia/Novosibirsk", "Novosibirsk", "Asia/Novosibirsk",
|
||||
"Indian/Cocos", "Cocos", "Indian/Cocos",
|
||||
"Africa/Bujumbura", "Africa_Central", "Africa/Maputo",
|
||||
"Europe/Mariehamn", "Europe_Eastern", "Europe/Bucharest",
|
||||
"America/Winnipeg", "America_Central", "America/Chicago",
|
||||
"America/Buenos_Aires", "Argentina", "America/Buenos_Aires",
|
||||
"America/Yellowknife", "America_Mountain", "America/Denver",
|
||||
"Pacific/Midway", "Samoa", "Pacific/Apia",
|
||||
"Africa/Dar_es_Salaam", "Africa_Eastern", "Africa/Nairobi",
|
||||
"Pacific/Tahiti", "Tahiti", "Pacific/Tahiti",
|
||||
"Asia/Gaza", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Australia/Lindeman", "Australia_Eastern", "Australia/Sydney",
|
||||
"Europe/Kaliningrad", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Europe/Bucharest", "Europe_Eastern", "Europe/Bucharest",
|
||||
"America/Lower_Princes", "Atlantic", "America/Halifax",
|
||||
"Pacific/Chuuk", "Truk", "Pacific/Truk",
|
||||
"America/Anchorage", "Alaska", "America/Juneau",
|
||||
"America/Rankin_Inlet", "America_Central", "America/Chicago",
|
||||
"America/Marigot", "Atlantic", "America/Halifax",
|
||||
"Africa/Juba", "Africa_Eastern", "Africa/Nairobi",
|
||||
"Africa/Algiers", "Europe_Central", "Europe/Paris",
|
||||
"Europe/Kiev", "Europe_Eastern", "Europe/Bucharest",
|
||||
"America/Santarem", "Brasilia", "America/Sao_Paulo",
|
||||
"Africa/Brazzaville", "Africa_Western", "Africa/Lagos",
|
||||
"Asia/Choibalsan", "Choibalsan", "Asia/Choibalsan",
|
||||
"Indian/Christmas", "Christmas", "Indian/Christmas",
|
||||
"America/Nassau", "America_Eastern", "America/New_York",
|
||||
"Africa/Tunis", "Europe_Central", "Europe/Paris",
|
||||
"Pacific/Noumea", "New_Caledonia", "Pacific/Noumea",
|
||||
"Africa/El_Aaiun", "Europe_Western", "Atlantic/Canary",
|
||||
"Europe/Sarajevo", "Europe_Central", "Europe/Paris",
|
||||
"America/Campo_Grande", "Amazon", "America/Manaus",
|
||||
"America/Puerto_Rico", "Atlantic", "America/Halifax",
|
||||
"Antarctica/Mawson", "Mawson", "Antarctica/Mawson",
|
||||
"Pacific/Galapagos", "Galapagos", "Pacific/Galapagos",
|
||||
"Asia/Tehran", "Iran", "Asia/Tehran",
|
||||
"America/Port-au-Prince", "America_Eastern", "America/New_York",
|
||||
"America/Scoresbysund", "Greenland_Eastern", "America/Scoresbysund",
|
||||
"Africa/Harare", "Africa_Central", "Africa/Maputo",
|
||||
"America/Dominica", "Atlantic", "America/Halifax",
|
||||
"Europe/Chisinau", "Europe_Eastern", "Europe/Bucharest",
|
||||
"America/Chihuahua", "America_Mountain", "America/Denver",
|
||||
"America/La_Paz", "Bolivia", "America/La_Paz",
|
||||
"Indian/Chagos", "Indian_Ocean", "Indian/Chagos",
|
||||
"Australia/Broken_Hill", "Australia_Central", "Australia/Adelaide",
|
||||
"America/Grenada", "Atlantic", "America/Halifax",
|
||||
"America/North_Dakota/New_Salem", "America_Central", "America/Chicago",
|
||||
"Pacific/Majuro", "Marshall_Islands", "Pacific/Majuro",
|
||||
"Australia/Adelaide", "Australia_Central", "Australia/Adelaide",
|
||||
"Europe/Warsaw", "Europe_Central", "Europe/Paris",
|
||||
"Europe/Vienna", "Europe_Central", "Europe/Paris",
|
||||
"Atlantic/Cape_Verde", "Cape_Verde", "Atlantic/Cape_Verde",
|
||||
"America/Mendoza", "Argentina", "America/Buenos_Aires",
|
||||
"Pacific/Gambier", "Gambier", "Pacific/Gambier",
|
||||
"Europe/Istanbul", "Europe_Eastern", "Europe/Bucharest",
|
||||
"America/Kentucky/Monticello", "America_Eastern", "America/New_York",
|
||||
"America/Chicago", "America_Central", "America/Chicago",
|
||||
"Asia/Ulaanbaatar", "Mongolia", "Asia/Ulaanbaatar",
|
||||
"Indian/Maldives", "Maldives", "Indian/Maldives",
|
||||
"America/Mexico_City", "America_Central", "America/Chicago",
|
||||
"Africa/Asmara", "Africa_Eastern", "Africa/Nairobi",
|
||||
"Asia/Chongqing", "China", "Asia/Shanghai",
|
||||
"America/Argentina/La_Rioja", "Argentina", "America/Buenos_Aires",
|
||||
"America/Tijuana", "America_Pacific", "America/Los_Angeles",
|
||||
"Asia/Harbin", "China", "Asia/Shanghai",
|
||||
"Pacific/Honolulu", "Hawaii_Aleutian", "Pacific/Honolulu",
|
||||
"Atlantic/Azores", "Azores", "Atlantic/Azores",
|
||||
"Indian/Mayotte", "Africa_Eastern", "Africa/Nairobi",
|
||||
"America/Guatemala", "America_Central", "America/Chicago",
|
||||
"America/Indianapolis", "America_Eastern", "America/New_York",
|
||||
"America/Halifax", "Atlantic", "America/Halifax",
|
||||
"America/Resolute", "America_Central", "America/Chicago",
|
||||
"Europe/London", "GMT", "Atlantic/Reykjavik",
|
||||
"America/Hermosillo", "America_Mountain", "America/Denver",
|
||||
"Atlantic/Madeira", "Europe_Western", "Atlantic/Canary",
|
||||
"Europe/Zagreb", "Europe_Central", "Europe/Paris",
|
||||
"America/Boa_Vista", "Amazon", "America/Manaus",
|
||||
"America/Regina", "America_Central", "America/Chicago",
|
||||
"America/Cordoba", "Argentina", "America/Buenos_Aires",
|
||||
"America/Shiprock", "America_Mountain", "America/Denver",
|
||||
"Europe/Luxembourg", "Europe_Central", "Europe/Paris",
|
||||
"America/Cancun", "America_Central", "America/Chicago",
|
||||
"Pacific/Enderbury", "Phoenix_Islands", "Pacific/Enderbury",
|
||||
"Africa/Bissau", "GMT", "Atlantic/Reykjavik",
|
||||
"Antarctica/Vostok", "Vostok", "Antarctica/Vostok",
|
||||
"Pacific/Apia", "Samoa", "Pacific/Apia",
|
||||
"Australia/Perth", "Australia_Western", "Australia/Perth",
|
||||
"America/Juneau", "Alaska", "America/Juneau",
|
||||
"Africa/Mbabane", "Africa_Southern", "Africa/Johannesburg",
|
||||
"Pacific/Niue", "Niue", "Pacific/Niue",
|
||||
"Europe/Zurich", "Europe_Central", "Europe/Paris",
|
||||
"America/Rio_Branco", "Amazon", "America/Manaus",
|
||||
"Africa/Ndjamena", "Africa_Western", "Africa/Lagos",
|
||||
"Asia/Macau", "China", "Asia/Shanghai",
|
||||
"America/Lima", "Peru", "America/Lima",
|
||||
"Africa/Windhoek", "Africa_Western", "Africa/Lagos",
|
||||
"America/Sitka", "Alaska", "America/Juneau",
|
||||
"America/Mazatlan", "America_Mountain", "America/Denver",
|
||||
"Asia/Saigon", "Indochina", "Asia/Saigon",
|
||||
"Asia/Kamchatka", "Magadan", "Asia/Magadan",
|
||||
"America/Menominee", "America_Central", "America/Chicago",
|
||||
"America/Belize", "America_Central", "America/Chicago",
|
||||
"America/Sao_Paulo", "Brasilia", "America/Sao_Paulo",
|
||||
"America/Barbados", "Atlantic", "America/Halifax",
|
||||
"America/Porto_Velho", "Amazon", "America/Manaus",
|
||||
"America/Costa_Rica", "America_Central", "America/Chicago",
|
||||
"Europe/Monaco", "Europe_Central", "Europe/Paris",
|
||||
"Europe/Riga", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Europe/Vatican", "Europe_Central", "Europe/Paris",
|
||||
"Europe/Madrid", "Europe_Central", "Europe/Paris",
|
||||
"Africa/Dakar", "GMT", "Atlantic/Reykjavik",
|
||||
"Asia/Damascus", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Asia/Hong_Kong", "Hong_Kong", "Asia/Hong_Kong",
|
||||
"America/Adak", "Hawaii_Aleutian", "Pacific/Honolulu",
|
||||
"Europe/Vilnius", "Europe_Eastern", "Europe/Bucharest",
|
||||
"America/Indiana/Indianapolis", "America_Eastern", "America/New_York",
|
||||
"Africa/Freetown", "GMT", "Atlantic/Reykjavik",
|
||||
"Atlantic/Reykjavik", "GMT", "Atlantic/Reykjavik",
|
||||
"Asia/Ho_Chi_Minh", "Indochina", "Asia/Saigon",
|
||||
"America/St_Kitts", "Atlantic", "America/Halifax",
|
||||
"America/Martinique", "Atlantic", "America/Halifax",
|
||||
"America/Thule", "Atlantic", "America/Halifax",
|
||||
"America/Asuncion", "Paraguay", "America/Asuncion",
|
||||
"Africa/Luanda", "Africa_Western", "Africa/Lagos",
|
||||
"America/Monterrey", "America_Central", "America/Chicago",
|
||||
"Pacific/Fiji", "Fiji", "Pacific/Fiji",
|
||||
"Africa/Banjul", "GMT", "Atlantic/Reykjavik",
|
||||
"America/Grand_Turk", "America_Eastern", "America/New_York",
|
||||
"Pacific/Pitcairn", "Pitcairn", "Pacific/Pitcairn",
|
||||
"America/Montevideo", "Uruguay", "America/Montevideo",
|
||||
"America/Bahia_Banderas", "America_Central", "America/Chicago",
|
||||
"America/Cayman", "America_Eastern", "America/New_York",
|
||||
"Pacific/Norfolk", "Norfolk", "Pacific/Norfolk",
|
||||
"Africa/Ouagadougou", "GMT", "Atlantic/Reykjavik",
|
||||
"America/Maceio", "Brasilia", "America/Sao_Paulo",
|
||||
"Pacific/Guam", "Chamorro", "Pacific/Saipan",
|
||||
"Africa/Monrovia", "GMT", "Atlantic/Reykjavik",
|
||||
"Africa/Bamako", "GMT", "Atlantic/Reykjavik",
|
||||
"Asia/Colombo", "India", "Asia/Calcutta",
|
||||
"Asia/Urumqi", "China", "Asia/Shanghai",
|
||||
"Asia/Kabul", "Afghanistan", "Asia/Kabul",
|
||||
"America/Yakutat", "Alaska", "America/Juneau",
|
||||
"America/Phoenix", "America_Mountain", "America/Denver",
|
||||
"Asia/Nicosia", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Asia/Phnom_Penh", "Indochina", "Asia/Saigon",
|
||||
"America/Rainy_River", "America_Central", "America/Chicago",
|
||||
"Europe/Uzhgorod", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Pacific/Saipan", "Chamorro", "Pacific/Saipan",
|
||||
"America/St_Vincent", "Atlantic", "America/Halifax",
|
||||
"Europe/Rome", "Europe_Central", "Europe/Paris",
|
||||
"America/Nome", "Alaska", "America/Juneau",
|
||||
"Africa/Mogadishu", "Africa_Eastern", "Africa/Nairobi",
|
||||
"Europe/Zaporozhye", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Pacific/Funafuti", "Tuvalu", "Pacific/Funafuti",
|
||||
"Atlantic/South_Georgia", "South_Georgia", "Atlantic/South_Georgia",
|
||||
"Europe/Skopje", "Europe_Central", "Europe/Paris",
|
||||
"Asia/Yekaterinburg", "Yekaterinburg", "Asia/Yekaterinburg",
|
||||
"Australia/Melbourne", "Australia_Eastern", "Australia/Sydney",
|
||||
"America/Argentina/Cordoba", "Argentina", "America/Buenos_Aires",
|
||||
"Africa/Kigali", "Africa_Central", "Africa/Maputo",
|
||||
"Africa/Blantyre", "Africa_Central", "Africa/Maputo",
|
||||
"Africa/Tripoli", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Africa/Gaborone", "Africa_Central", "Africa/Maputo",
|
||||
"Asia/Kuching", "Malaysia", "Asia/Kuching",
|
||||
"Pacific/Nauru", "Nauru", "Pacific/Nauru",
|
||||
"America/Aruba", "Atlantic", "America/Halifax",
|
||||
"America/Antigua", "Atlantic", "America/Halifax",
|
||||
"Europe/Volgograd", "Volgograd", "Europe/Volgograd",
|
||||
"Africa/Djibouti", "Africa_Eastern", "Africa/Nairobi",
|
||||
"America/Catamarca", "Argentina", "America/Buenos_Aires",
|
||||
"Asia/Manila", "Philippines", "Asia/Manila",
|
||||
"Pacific/Kiritimati", "Line_Islands", "Pacific/Kiritimati",
|
||||
"Asia/Shanghai", "China", "Asia/Shanghai",
|
||||
"Pacific/Truk", "Truk", "Pacific/Truk",
|
||||
"Pacific/Tarawa", "Gilbert_Islands", "Pacific/Tarawa",
|
||||
"Africa/Conakry", "GMT", "Atlantic/Reykjavik",
|
||||
"Asia/Bishkek", "Kyrgystan", "Asia/Bishkek",
|
||||
"Europe/Gibraltar", "Europe_Central", "Europe/Paris",
|
||||
"Asia/Rangoon", "Myanmar", "Asia/Rangoon",
|
||||
"Asia/Baku", "Azerbaijan", "Asia/Baku",
|
||||
"America/Santiago", "Chile", "America/Santiago",
|
||||
"America/El_Salvador", "America_Central", "America/Chicago",
|
||||
"America/Noronha", "Noronha", "America/Noronha",
|
||||
"America/St_Thomas", "Atlantic", "America/Halifax",
|
||||
"Atlantic/St_Helena", "GMT", "Atlantic/Reykjavik",
|
||||
"Asia/Krasnoyarsk", "Krasnoyarsk", "Asia/Krasnoyarsk",
|
||||
"America/Vancouver", "America_Pacific", "America/Los_Angeles",
|
||||
"Europe/Belgrade", "Europe_Central", "Europe/Paris",
|
||||
"America/St_Barthelemy", "Atlantic", "America/Halifax",
|
||||
"Asia/Pontianak", "Indonesia_Western", "Asia/Jakarta",
|
||||
"Africa/Lusaka", "Africa_Central", "Africa/Maputo",
|
||||
"America/Godthab", "Greenland_Western", "America/Godthab",
|
||||
"Asia/Dhaka", "Bangladesh", "Asia/Dhaka",
|
||||
"Asia/Dubai", "Gulf", "Asia/Dubai",
|
||||
"Europe/Moscow", "Moscow", "Europe/Moscow",
|
||||
"America/Louisville", "America_Eastern", "America/New_York",
|
||||
"Australia/Darwin", "Australia_Central", "Australia/Adelaide",
|
||||
"America/Santo_Domingo", "Atlantic", "America/Halifax",
|
||||
"America/Argentina/Ushuaia", "Argentina", "America/Buenos_Aires",
|
||||
"America/Tegucigalpa", "America_Central", "America/Chicago",
|
||||
"Asia/Aden", "Arabian", "Asia/Riyadh",
|
||||
"America/Inuvik", "America_Mountain", "America/Denver",
|
||||
"Asia/Beirut", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Asia/Qatar", "Arabian", "Asia/Riyadh",
|
||||
"Europe/Oslo", "Europe_Central", "Europe/Paris",
|
||||
"Asia/Anadyr", "Magadan", "Asia/Magadan",
|
||||
"Pacific/Palau", "Palau", "Pacific/Palau",
|
||||
"Arctic/Longyearbyen", "Europe_Central", "Europe/Paris",
|
||||
"America/Anguilla", "Atlantic", "America/Halifax",
|
||||
"Asia/Aqtau", "Kazakhstan_Western", "Asia/Aqtobe",
|
||||
"Asia/Yerevan", "Armenia", "Asia/Yerevan",
|
||||
"Africa/Lagos", "Africa_Western", "Africa/Lagos",
|
||||
"America/Denver", "America_Mountain", "America/Denver",
|
||||
"Antarctica/Palmer", "Chile", "America/Santiago",
|
||||
"Europe/Stockholm", "Europe_Central", "Europe/Paris",
|
||||
"America/Bahia", "Brasilia", "America/Sao_Paulo",
|
||||
"America/Danmarkshavn", "GMT", "Atlantic/Reykjavik",
|
||||
"Indian/Mauritius", "Mauritius", "Indian/Mauritius",
|
||||
"Pacific/Chatham", "Chatham", "Pacific/Chatham",
|
||||
"Europe/Prague", "Europe_Central", "Europe/Paris",
|
||||
"America/Blanc-Sablon", "Atlantic", "America/Halifax",
|
||||
"America/Bogota", "Colombia", "America/Bogota",
|
||||
"America/Managua", "America_Central", "America/Chicago",
|
||||
"Pacific/Auckland", "New_Zealand", "Pacific/Auckland",
|
||||
"Atlantic/Faroe", "Europe_Western", "Atlantic/Canary",
|
||||
"America/Cambridge_Bay", "America_Mountain", "America/Denver",
|
||||
"America/Los_Angeles", "America_Pacific", "America/Los_Angeles",
|
||||
"Africa/Khartoum", "Africa_Eastern", "Africa/Nairobi",
|
||||
"Europe/Simferopol", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Australia/Currie", "Australia_Eastern", "Australia/Sydney",
|
||||
"Europe/Guernsey", "GMT", "Atlantic/Reykjavik",
|
||||
"Asia/Thimphu", "Bhutan", "Asia/Thimphu",
|
||||
"America/Eirunepe", "Amazon", "America/Manaus",
|
||||
"Africa/Nairobi", "Africa_Eastern", "Africa/Nairobi",
|
||||
"Asia/Yakutsk", "Yakutsk", "Asia/Yakutsk",
|
||||
"Asia/Yangon", "Myanmar", "Asia/Rangoon",
|
||||
"America/Goose_Bay", "Atlantic", "America/Halifax",
|
||||
"Africa/Maseru", "Africa_Southern", "Africa/Johannesburg",
|
||||
"America/Swift_Current", "America_Central", "America/Chicago",
|
||||
"America/Guyana", "Guyana", "America/Guyana",
|
||||
"Asia/Tokyo", "Japan", "Asia/Tokyo",
|
||||
"Indian/Kerguelen", "French_Southern", "Indian/Kerguelen",
|
||||
"America/Belem", "Brasilia", "America/Sao_Paulo",
|
||||
"Pacific/Wallis", "Wallis", "Pacific/Wallis",
|
||||
"America/Whitehorse", "America_Pacific", "America/Los_Angeles",
|
||||
"America/North_Dakota/Beulah", "America_Central", "America/Chicago",
|
||||
"Asia/Jerusalem", "Israel", "Asia/Jerusalem",
|
||||
"Antarctica/Syowa", "Syowa", "Antarctica/Syowa",
|
||||
"America/Thunder_Bay", "America_Eastern", "America/New_York",
|
||||
"Asia/Brunei", "Brunei", "Asia/Brunei",
|
||||
"America/Metlakatla", "America_Pacific", "America/Los_Angeles",
|
||||
"Asia/Dushanbe", "Tajikistan", "Asia/Dushanbe",
|
||||
"Pacific/Kosrae", "Kosrae", "Pacific/Kosrae",
|
||||
"America/Coral_Harbour", "America_Eastern", "America/New_York",
|
||||
"America/Tortola", "Atlantic", "America/Halifax",
|
||||
"Asia/Karachi", "Pakistan", "Asia/Karachi",
|
||||
"Indian/Reunion", "Reunion", "Indian/Reunion",
|
||||
"America/Detroit", "America_Eastern", "America/New_York",
|
||||
"Australia/Eucla", "Australia_CentralWestern", "Australia/Eucla",
|
||||
"Asia/Seoul", "Korea", "Asia/Seoul",
|
||||
"Asia/Singapore", "Singapore", "Asia/Singapore",
|
||||
"Africa/Casablanca", "Europe_Western", "Atlantic/Canary",
|
||||
"Asia/Dili", "East_Timor", "Asia/Dili",
|
||||
"America/Indiana/Vincennes", "America_Eastern", "America/New_York",
|
||||
"Europe/Dublin", "GMT", "Atlantic/Reykjavik",
|
||||
"America/St_Johns", "Newfoundland", "America/St_Johns",
|
||||
"Antarctica/Macquarie", "Macquarie", "Antarctica/Macquarie",
|
||||
"America/Port_of_Spain", "Atlantic", "America/Halifax",
|
||||
"Europe/Budapest", "Europe_Central", "Europe/Paris",
|
||||
"America/Fortaleza", "Brasilia", "America/Sao_Paulo",
|
||||
"Australia/Brisbane", "Australia_Eastern", "Australia/Sydney",
|
||||
"Atlantic/Bermuda", "Atlantic", "America/Halifax",
|
||||
"Asia/Amman", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Asia/Tashkent", "Uzbekistan", "Asia/Tashkent",
|
||||
"Antarctica/DumontDUrville", "DumontDUrville", "Antarctica/DumontDUrville",
|
||||
"Antarctica/Casey", "Australia_Western", "Australia/Perth",
|
||||
"Asia/Vientiane", "Indochina", "Asia/Saigon",
|
||||
"Pacific/Johnston", "Hawaii_Aleutian", "Pacific/Honolulu",
|
||||
"America/Jamaica", "America_Eastern", "America/New_York",
|
||||
"Africa/Addis_Ababa", "Africa_Eastern", "Africa/Nairobi",
|
||||
"Pacific/Ponape", "Ponape", "Pacific/Ponape",
|
||||
"Europe/Jersey", "GMT", "Atlantic/Reykjavik",
|
||||
"Africa/Lome", "GMT", "Atlantic/Reykjavik",
|
||||
"America/Manaus", "Amazon", "America/Manaus",
|
||||
"Africa/Niamey", "Africa_Western", "Africa/Lagos",
|
||||
"Asia/Kashgar", "China", "Asia/Shanghai",
|
||||
"Pacific/Tongatapu", "Tonga", "Pacific/Tongatapu",
|
||||
"Europe/Minsk", "Europe_Eastern", "Europe/Bucharest",
|
||||
"America/Edmonton", "America_Mountain", "America/Denver",
|
||||
"Asia/Baghdad", "Arabian", "Asia/Riyadh",
|
||||
"Asia/Kathmandu", "Nepal", "Asia/Katmandu",
|
||||
"America/Ojinaga", "America_Mountain", "America/Denver",
|
||||
"Africa/Abidjan", "GMT", "Atlantic/Reykjavik",
|
||||
"America/Indiana/Winamac", "America_Eastern", "America/New_York",
|
||||
"Asia/Qyzylorda", "Kazakhstan_Eastern", "Asia/Almaty",
|
||||
"Australia/Sydney", "Australia_Eastern", "Australia/Sydney",
|
||||
"Asia/Ashgabat", "Turkmenistan", "Asia/Ashgabat",
|
||||
"Europe/Amsterdam", "Europe_Central", "Europe/Paris",
|
||||
"America/Dawson_Creek", "America_Mountain", "America/Denver",
|
||||
"Africa/Cairo", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Asia/Pyongyang", "Korea", "Asia/Seoul",
|
||||
"Africa/Kampala", "Africa_Eastern", "Africa/Nairobi",
|
||||
"America/Araguaina", "Brasilia", "America/Sao_Paulo",
|
||||
"Asia/Novokuznetsk", "Novosibirsk", "Asia/Novosibirsk",
|
||||
"Pacific/Kwajalein", "Marshall_Islands", "Pacific/Majuro",
|
||||
"Africa/Lubumbashi", "Africa_Central", "Africa/Maputo",
|
||||
"Asia/Sakhalin", "Sakhalin", "Asia/Sakhalin",
|
||||
"America/Indiana/Vevay", "America_Eastern", "America/New_York",
|
||||
"Africa/Maputo", "Africa_Central", "Africa/Maputo",
|
||||
"Atlantic/Faeroe", "Europe_Western", "Atlantic/Canary",
|
||||
"America/North_Dakota/Center", "America_Central", "America/Chicago",
|
||||
"Pacific/Wake", "Wake", "Pacific/Wake",
|
||||
"Pacific/Pago_Pago", "Samoa", "Pacific/Apia",
|
||||
"America/Moncton", "Atlantic", "America/Halifax",
|
||||
"Africa/Sao_Tome", "GMT", "Atlantic/Reykjavik",
|
||||
"America/Glace_Bay", "Atlantic", "America/Halifax",
|
||||
"Asia/Jakarta", "Indonesia_Western", "Asia/Jakarta",
|
||||
"Africa/Asmera", "Africa_Eastern", "Africa/Nairobi",
|
||||
"Europe/Lisbon", "Europe_Western", "Atlantic/Canary",
|
||||
"America/Dawson", "America_Pacific", "America/Los_Angeles",
|
||||
"America/Cayenne", "French_Guiana", "America/Cayenne",
|
||||
"Asia/Bahrain", "Arabian", "Asia/Riyadh",
|
||||
"Europe/Malta", "Europe_Central", "Europe/Paris",
|
||||
"America/Indiana/Tell_City", "America_Central", "America/Chicago",
|
||||
"America/Indiana/Petersburg", "America_Eastern", "America/New_York",
|
||||
"Antarctica/Rothera", "Rothera", "Antarctica/Rothera",
|
||||
"Asia/Aqtobe", "Kazakhstan_Western", "Asia/Aqtobe",
|
||||
"Europe/Vaduz", "Europe_Central", "Europe/Paris",
|
||||
"America/Indiana/Marengo", "America_Eastern", "America/New_York",
|
||||
"Europe/Brussels", "Europe_Central", "Europe/Paris",
|
||||
"Europe/Andorra", "Europe_Central", "Europe/Paris",
|
||||
"America/Indiana/Knox", "America_Central", "America/Chicago",
|
||||
"Pacific/Easter", "Easter", "Pacific/Easter",
|
||||
"America/Argentina/Rio_Gallegos", "Argentina", "America/Buenos_Aires",
|
||||
"Asia/Oral", "Kazakhstan_Western", "Asia/Aqtobe",
|
||||
"Europe/Copenhagen", "Europe_Central", "Europe/Paris",
|
||||
"Africa/Johannesburg", "Africa_Southern", "Africa/Johannesburg",
|
||||
"Pacific/Pohnpei", "Ponape", "Pacific/Ponape",
|
||||
"America/Argentina/Tucuman", "Argentina", "America/Buenos_Aires",
|
||||
"America/Toronto", "America_Eastern", "America/New_York",
|
||||
"Asia/Makassar", "Indonesia_Central", "Asia/Makassar",
|
||||
"Europe/Berlin", "Europe_Central", "Europe/Paris",
|
||||
"America/Argentina/Mendoza", "Argentina", "America/Buenos_Aires",
|
||||
"America/Cuiaba", "Amazon", "America/Manaus",
|
||||
"America/Creston", "America_Mountain", "America/Denver",
|
||||
"Asia/Samarkand", "Uzbekistan", "Asia/Tashkent",
|
||||
"Asia/Hovd", "Hovd", "Asia/Hovd",
|
||||
"Europe/Bratislava", "Europe_Central", "Europe/Paris",
|
||||
"Africa/Accra", "GMT", "Atlantic/Reykjavik",
|
||||
"Africa/Douala", "Africa_Western", "Africa/Lagos",
|
||||
"Africa/Nouakchott", "GMT", "Atlantic/Reykjavik",
|
||||
"Europe/Sofia", "Europe_Eastern", "Europe/Bucharest",
|
||||
"Antarctica/Davis", "Davis", "Antarctica/Davis",
|
||||
"Antarctica/McMurdo", "New_Zealand", "Pacific/Auckland",
|
||||
"Europe/San_Marino", "Europe_Central", "Europe/Paris",
|
||||
"Africa/Porto-Novo", "Africa_Western", "Africa/Lagos",
|
||||
"Asia/Jayapura", "Indonesia_Eastern", "Asia/Jayapura",
|
||||
"America/St_Lucia", "Atlantic", "America/Halifax",
|
||||
"America/Nipigon", "America_Eastern", "America/New_York",
|
||||
"America/Argentina/Catamarca", "Argentina", "America/Buenos_Aires",
|
||||
"Europe/Isle_of_Man", "GMT", "Atlantic/Reykjavik",
|
||||
"America/Kentucky/Louisville", "America_Eastern", "America/New_York",
|
||||
"America/Merida", "America_Central", "America/Chicago",
|
||||
"Pacific/Marquesas", "Marquesas", "Pacific/Marquesas",
|
||||
"Asia/Magadan", "Magadan", "Asia/Magadan",
|
||||
"Africa/Libreville", "Africa_Western", "Africa/Lagos",
|
||||
"Pacific/Efate", "Vanuatu", "Pacific/Efate",
|
||||
"Asia/Kuala_Lumpur", "Malaysia", "Asia/Kuching",
|
||||
"America/Iqaluit", "America_Eastern", "America/New_York",
|
||||
"Indian/Comoro", "Africa_Eastern", "Africa/Nairobi",
|
||||
"America/Panama", "America_Eastern", "America/New_York",
|
||||
"Asia/Hebron", "Europe_Eastern", "Europe/Bucharest",
|
||||
"America/Jujuy", "Argentina", "America/Buenos_Aires",
|
||||
"America/Pangnirtung", "America_Eastern", "America/New_York",
|
||||
"Asia/Tbilisi", "Georgia", "Asia/Tbilisi",
|
||||
"Europe/Podgorica", "Europe_Central", "Europe/Paris",
|
||||
"America/Boise", "America_Mountain", "America/Denver",
|
||||
"Asia/Muscat", "Gulf", "Asia/Dubai",
|
||||
"Indian/Mahe", "Seychelles", "Indian/Mahe",
|
||||
"America/Montreal", "America_Eastern", "America/New_York",
|
||||
"Africa/Bangui", "Africa_Western", "Africa/Lagos",
|
||||
"America/Curacao", "Atlantic", "America/Halifax",
|
||||
"Asia/Taipei", "Taipei", "Asia/Taipei",
|
||||
"Europe/Ljubljana", "Europe_Central", "Europe/Paris",
|
||||
"Atlantic/Stanley", "Falkland", "Atlantic/Stanley",
|
||||
"Pacific/Guadalcanal", "Solomon", "Pacific/Guadalcanal",
|
||||
"Asia/Kuwait", "Arabian", "Asia/Riyadh",
|
||||
"Asia/Riyadh", "Arabian", "Asia/Riyadh",
|
||||
"Europe/Tallinn", "Europe_Eastern", "Europe/Bucharest",
|
||||
"America/New_York", "America_Eastern", "America/New_York",
|
||||
"America/Paramaribo", "Suriname", "America/Paramaribo",
|
||||
"America/Argentina/Buenos_Aires", "Argentina", "America/Buenos_Aires",
|
||||
"Asia/Irkutsk", "Irkutsk", "Asia/Irkutsk",
|
||||
"Asia/Katmandu", "Nepal", "Asia/Katmandu",
|
||||
"America/Kralendijk", "Atlantic", "America/Halifax",
|
||||
};
|
||||
private static final String[] mzoneMap = new String[] {
|
||||
"GMT", "ST", "Africa/Sao_Tome",
|
||||
"GMT", "ML", "Africa/Bamako",
|
||||
"GMT", "IE", "Europe/Dublin",
|
||||
"GMT", "SN", "Africa/Dakar",
|
||||
"GMT", "GH", "Africa/Accra",
|
||||
"GMT", "CI", "Africa/Abidjan",
|
||||
"GMT", "BF", "Africa/Ouagadougou",
|
||||
"GMT", "MR", "Africa/Nouakchott",
|
||||
"GMT", "GM", "Africa/Banjul",
|
||||
"GMT", "SL", "Africa/Freetown",
|
||||
"GMT", "GN", "Africa/Conakry",
|
||||
"GMT", "SH", "Atlantic/St_Helena",
|
||||
"GMT", "GB", "Europe/London",
|
||||
"GMT", "LR", "Africa/Monrovia",
|
||||
"GMT", "TG", "Africa/Lome",
|
||||
"Africa_Western", "CF", "Africa/Bangui",
|
||||
"Africa_Western", "NE", "Africa/Niamey",
|
||||
"Africa_Western", "CM", "Africa/Douala",
|
||||
"Africa_Western", "CD", "Africa/Kinshasa",
|
||||
"Africa_Western", "CG", "Africa/Brazzaville",
|
||||
"Africa_Western", "GA", "Africa/Libreville",
|
||||
"Africa_Western", "TD", "Africa/Ndjamena",
|
||||
"Africa_Western", "AO", "Africa/Luanda",
|
||||
"Africa_Western", "GQ", "Africa/Malabo",
|
||||
"Africa_Eastern", "YT", "Indian/Mayotte",
|
||||
"Africa_Eastern", "UG", "Africa/Kampala",
|
||||
"Africa_Eastern", "ET", "Africa/Addis_Ababa",
|
||||
"Africa_Eastern", "MG", "Indian/Antananarivo",
|
||||
"Africa_Eastern", "TZ", "Africa/Dar_es_Salaam",
|
||||
"Africa_Eastern", "SO", "Africa/Mogadishu",
|
||||
"Africa_Eastern", "ER", "Africa/Asmera",
|
||||
"Africa_Eastern", "KM", "Indian/Comoro",
|
||||
"Africa_Eastern", "DJ", "Africa/Djibouti",
|
||||
"Europe_Central", "GI", "Europe/Gibraltar",
|
||||
"Europe_Central", "DK", "Europe/Copenhagen",
|
||||
"Europe_Central", "SE", "Europe/Stockholm",
|
||||
"Europe_Central", "CH", "Europe/Zurich",
|
||||
"Europe_Central", "AL", "Europe/Tirane",
|
||||
"Europe_Central", "RS", "Europe/Belgrade",
|
||||
"Europe_Central", "HU", "Europe/Budapest",
|
||||
"Europe_Central", "MT", "Europe/Malta",
|
||||
"Europe_Central", "PL", "Europe/Warsaw",
|
||||
"Europe_Central", "ME", "Europe/Podgorica",
|
||||
"Europe_Central", "ES", "Europe/Madrid",
|
||||
"Europe_Central", "CZ", "Europe/Prague",
|
||||
"Europe_Central", "IT", "Europe/Rome",
|
||||
"Europe_Central", "SI", "Europe/Ljubljana",
|
||||
"Europe_Central", "LI", "Europe/Vaduz",
|
||||
"Europe_Central", "AT", "Europe/Vienna",
|
||||
"Europe_Central", "VA", "Europe/Vatican",
|
||||
"Europe_Central", "DE", "Europe/Berlin",
|
||||
"Europe_Central", "NO", "Europe/Oslo",
|
||||
"Europe_Central", "SK", "Europe/Bratislava",
|
||||
"Europe_Central", "AD", "Europe/Andorra",
|
||||
"Europe_Central", "SM", "Europe/San_Marino",
|
||||
"Europe_Central", "MK", "Europe/Skopje",
|
||||
"Europe_Central", "TN", "Africa/Tunis",
|
||||
"Europe_Central", "HR", "Europe/Zagreb",
|
||||
"Europe_Central", "NL", "Europe/Amsterdam",
|
||||
"Europe_Central", "BE", "Europe/Brussels",
|
||||
"Europe_Central", "MC", "Europe/Monaco",
|
||||
"Europe_Central", "LU", "Europe/Luxembourg",
|
||||
"Europe_Central", "BA", "Europe/Sarajevo",
|
||||
"China", "MO", "Asia/Macau",
|
||||
"America_Pacific", "MX", "America/Tijuana",
|
||||
"America_Pacific", "CA", "America/Vancouver",
|
||||
"Indochina", "LA", "Asia/Vientiane",
|
||||
"Indochina", "KH", "Asia/Phnom_Penh",
|
||||
"Indochina", "TH", "Asia/Bangkok",
|
||||
"Korea", "KP", "Asia/Pyongyang",
|
||||
"America_Mountain", "MX", "America/Hermosillo",
|
||||
"America_Mountain", "CA", "America/Edmonton",
|
||||
"Africa_Southern", "LS", "Africa/Maseru",
|
||||
"Africa_Southern", "SZ", "Africa/Mbabane",
|
||||
"Chile", "AQ", "Antarctica/Palmer",
|
||||
"New_Zealand", "AQ", "Antarctica/McMurdo",
|
||||
"Gulf", "OM", "Asia/Muscat",
|
||||
"Europe_Western", "FO", "Atlantic/Faeroe",
|
||||
"America_Eastern", "TC", "America/Grand_Turk",
|
||||
"America_Eastern", "CA", "America/Toronto",
|
||||
"America_Eastern", "BS", "America/Nassau",
|
||||
"America_Eastern", "PA", "America/Panama",
|
||||
"America_Eastern", "JM", "America/Jamaica",
|
||||
"America_Eastern", "KY", "America/Cayman",
|
||||
"Africa_Central", "BI", "Africa/Bujumbura",
|
||||
"Africa_Central", "ZM", "Africa/Lusaka",
|
||||
"Africa_Central", "ZW", "Africa/Harare",
|
||||
"Africa_Central", "CD", "Africa/Lubumbashi",
|
||||
"Africa_Central", "BW", "Africa/Gaborone",
|
||||
"Africa_Central", "RW", "Africa/Kigali",
|
||||
"Africa_Central", "MW", "Africa/Blantyre",
|
||||
"America_Central", "MX", "America/Mexico_City",
|
||||
"America_Central", "HN", "America/Tegucigalpa",
|
||||
"America_Central", "CA", "America/Winnipeg",
|
||||
"America_Central", "GT", "America/Guatemala",
|
||||
"America_Central", "SV", "America/El_Salvador",
|
||||
"America_Central", "CR", "America/Costa_Rica",
|
||||
"America_Central", "BZ", "America/Belize",
|
||||
"Atlantic", "MS", "America/Montserrat",
|
||||
"Atlantic", "AG", "America/Antigua",
|
||||
"Atlantic", "TT", "America/Port_of_Spain",
|
||||
"Atlantic", "MQ", "America/Martinique",
|
||||
"Atlantic", "DM", "America/Dominica",
|
||||
"Atlantic", "KN", "America/St_Kitts",
|
||||
"Atlantic", "BM", "Atlantic/Bermuda",
|
||||
"Atlantic", "PR", "America/Puerto_Rico",
|
||||
"Atlantic", "AW", "America/Aruba",
|
||||
"Atlantic", "VG", "America/Tortola",
|
||||
"Atlantic", "GD", "America/Grenada",
|
||||
"Atlantic", "GL", "America/Thule",
|
||||
"Atlantic", "BB", "America/Barbados",
|
||||
"Atlantic", "BQ", "America/Kralendijk",
|
||||
"Atlantic", "SX", "America/Lower_Princes",
|
||||
"Atlantic", "VI", "America/St_Thomas",
|
||||
"Atlantic", "MF", "America/Marigot",
|
||||
"Atlantic", "AI", "America/Anguilla",
|
||||
"Atlantic", "AN", "America/Curacao",
|
||||
"Atlantic", "LC", "America/St_Lucia",
|
||||
"Atlantic", "GP", "America/Guadeloupe",
|
||||
"Atlantic", "VC", "America/St_Vincent",
|
||||
"Arabian", "QA", "Asia/Qatar",
|
||||
"Arabian", "YE", "Asia/Aden",
|
||||
"Arabian", "KW", "Asia/Kuwait",
|
||||
"Arabian", "BH", "Asia/Bahrain",
|
||||
"Arabian", "IQ", "Asia/Baghdad",
|
||||
"India", "LK", "Asia/Colombo",
|
||||
"Europe_Eastern", "SY", "Asia/Damascus",
|
||||
"Europe_Eastern", "BG", "Europe/Sofia",
|
||||
"Europe_Eastern", "GR", "Europe/Athens",
|
||||
"Europe_Eastern", "JO", "Asia/Amman",
|
||||
"Europe_Eastern", "CY", "Asia/Nicosia",
|
||||
"Europe_Eastern", "AX", "Europe/Mariehamn",
|
||||
"Europe_Eastern", "LB", "Asia/Beirut",
|
||||
"Europe_Eastern", "FI", "Europe/Helsinki",
|
||||
"Europe_Eastern", "EG", "Africa/Cairo",
|
||||
"Chamorro", "GU", "Pacific/Guam",
|
||||
};
|
||||
private static final String[] aliasMap = new String[] {
|
||||
"Brazil/Acre", "America/Rio_Branco",
|
||||
"US/Indiana-Starke", "America/Indiana/Knox",
|
||||
"America/Atka", "America/Adak",
|
||||
"America/St_Barthelemy", "America/Guadeloupe",
|
||||
"Australia/North", "Australia/Darwin",
|
||||
"Europe/Zagreb", "Europe/Belgrade",
|
||||
"Etc/Universal", "Etc/UTC",
|
||||
"NZ-CHAT", "Pacific/Chatham",
|
||||
"Asia/Macao", "Asia/Macau",
|
||||
"Pacific/Yap", "Pacific/Chuuk",
|
||||
"Egypt", "Africa/Cairo",
|
||||
"US/Central", "America/Chicago",
|
||||
"Canada/Atlantic", "America/Halifax",
|
||||
"Brazil/East", "America/Sao_Paulo",
|
||||
"America/Cordoba", "America/Argentina/Cordoba",
|
||||
"US/Hawaii", "Pacific/Honolulu",
|
||||
"America/Louisville", "America/Kentucky/Louisville",
|
||||
"America/Shiprock", "America/Denver",
|
||||
"Australia/Canberra", "Australia/Sydney",
|
||||
"Asia/Chungking", "Asia/Chongqing",
|
||||
"Universal", "Etc/UTC",
|
||||
"US/Alaska", "America/Anchorage",
|
||||
"Asia/Ujung_Pandang", "Asia/Makassar",
|
||||
"Japan", "Asia/Tokyo",
|
||||
"Atlantic/Faeroe", "Atlantic/Faroe",
|
||||
"Asia/Istanbul", "Europe/Istanbul",
|
||||
"US/Pacific", "America/Los_Angeles",
|
||||
"Mexico/General", "America/Mexico_City",
|
||||
"Poland", "Europe/Warsaw",
|
||||
"Africa/Asmera", "Africa/Asmara",
|
||||
"Asia/Saigon", "Asia/Ho_Chi_Minh",
|
||||
"US/Michigan", "America/Detroit",
|
||||
"America/Argentina/ComodRivadavia", "America/Argentina/Catamarca",
|
||||
"W-SU", "Europe/Moscow",
|
||||
"Australia/ACT", "Australia/Sydney",
|
||||
"Asia/Calcutta", "Asia/Kolkata",
|
||||
"Arctic/Longyearbyen", "Europe/Oslo",
|
||||
"America/Knox_IN", "America/Indiana/Knox",
|
||||
"ROC", "Asia/Taipei",
|
||||
"Zulu", "Etc/UTC",
|
||||
"Australia/Yancowinna", "Australia/Broken_Hill",
|
||||
"Australia/West", "Australia/Perth",
|
||||
"Singapore", "Asia/Singapore",
|
||||
"Europe/Mariehamn", "Europe/Helsinki",
|
||||
"ROK", "Asia/Seoul",
|
||||
"America/Porto_Acre", "America/Rio_Branco",
|
||||
"Etc/Zulu", "Etc/UTC",
|
||||
"Canada/Yukon", "America/Whitehorse",
|
||||
"Europe/Vatican", "Europe/Rome",
|
||||
"Africa/Timbuktu", "Africa/Bamako",
|
||||
"America/Buenos_Aires", "America/Argentina/Buenos_Aires",
|
||||
"Canada/Pacific", "America/Vancouver",
|
||||
"US/Pacific-New", "America/Los_Angeles",
|
||||
"Mexico/BajaNorte", "America/Tijuana",
|
||||
"Europe/Guernsey", "Europe/London",
|
||||
"Asia/Tel_Aviv", "Asia/Jerusalem",
|
||||
"Chile/Continental", "America/Santiago",
|
||||
"Jamaica", "America/Jamaica",
|
||||
"Mexico/BajaSur", "America/Mazatlan",
|
||||
"Canada/Eastern", "America/Toronto",
|
||||
"Australia/Tasmania", "Australia/Hobart",
|
||||
"NZ", "Pacific/Auckland",
|
||||
"America/Lower_Princes", "America/Curacao",
|
||||
"GMT-", "Etc/GMT",
|
||||
"America/Rosario", "America/Argentina/Cordoba",
|
||||
"Libya", "Africa/Tripoli",
|
||||
"Asia/Ashkhabad", "Asia/Ashgabat",
|
||||
"Australia/NSW", "Australia/Sydney",
|
||||
"America/Marigot", "America/Guadeloupe",
|
||||
"Europe/Bratislava", "Europe/Prague",
|
||||
"Portugal", "Europe/Lisbon",
|
||||
"Etc/GMT-", "Etc/GMT",
|
||||
"Europe/San_Marino", "Europe/Rome",
|
||||
"Europe/Sarajevo", "Europe/Belgrade",
|
||||
"Antarctica/South_Pole", "Antarctica/McMurdo",
|
||||
"Canada/Central", "America/Winnipeg",
|
||||
"Etc/GMT", "Etc/GMT",
|
||||
"Europe/Isle_of_Man", "Europe/London",
|
||||
"America/Fort_Wayne", "America/Indiana/Indianapolis",
|
||||
"Eire", "Europe/Dublin",
|
||||
"America/Coral_Harbour", "America/Atikokan",
|
||||
"Europe/Nicosia", "Asia/Nicosia",
|
||||
"US/Samoa", "Pacific/Pago_Pago",
|
||||
"Hongkong", "Asia/Hong_Kong",
|
||||
"Canada/Saskatchewan", "America/Regina",
|
||||
"Asia/Thimbu", "Asia/Thimphu",
|
||||
"Kwajalein", "Pacific/Kwajalein",
|
||||
"GB", "Europe/London",
|
||||
"Chile/EasterIsland", "Pacific/Easter",
|
||||
"US/East-Indiana", "America/Indiana/Indianapolis",
|
||||
"Australia/LHI", "Australia/Lord_Howe",
|
||||
"Cuba", "America/Havana",
|
||||
"America/Jujuy", "America/Argentina/Jujuy",
|
||||
"US/Mountain", "America/Denver",
|
||||
"Atlantic/Jan_Mayen", "Europe/Oslo",
|
||||
"Europe/Tiraspol", "Europe/Chisinau",
|
||||
"Europe/Podgorica", "Europe/Belgrade",
|
||||
"US/Arizona", "America/Phoenix",
|
||||
"Navajo", "America/Denver",
|
||||
"Etc/Greenwich", "Etc/GMT",
|
||||
"Canada/Mountain", "America/Edmonton",
|
||||
"Iceland", "Atlantic/Reykjavik",
|
||||
"Australia/Victoria", "Australia/Melbourne",
|
||||
"Australia/South", "Australia/Adelaide",
|
||||
"Brazil/West", "America/Manaus",
|
||||
"Pacific/Ponape", "Pacific/Pohnpei",
|
||||
"Europe/Ljubljana", "Europe/Belgrade",
|
||||
"Europe/Jersey", "Europe/London",
|
||||
"Australia/Queensland", "Australia/Brisbane",
|
||||
"UTC", "Etc/UTC",
|
||||
"Canada/Newfoundland", "America/St_Johns",
|
||||
"Europe/Skopje", "Europe/Belgrade",
|
||||
"Canada/East-Saskatchewan", "America/Regina",
|
||||
"PRC", "Asia/Shanghai",
|
||||
"UCT", "Etc/UCT",
|
||||
"America/Mendoza", "America/Argentina/Mendoza",
|
||||
"Israel", "Asia/Jerusalem",
|
||||
"US/Eastern", "America/New_York",
|
||||
"Asia/Ulan_Bator", "Asia/Ulaanbaatar",
|
||||
"Turkey", "Europe/Istanbul",
|
||||
"GMT", "Etc/GMT",
|
||||
"US/Aleutian", "America/Adak",
|
||||
"Brazil/DeNoronha", "America/Noronha",
|
||||
"GB-Eire", "Europe/London",
|
||||
"Asia/Dacca", "Asia/Dhaka",
|
||||
"America/Ensenada", "America/Tijuana",
|
||||
"America/Catamarca", "America/Argentina/Catamarca",
|
||||
"Iran", "Asia/Tehran",
|
||||
"Greenwich", "Etc/GMT",
|
||||
"Pacific/Truk", "Pacific/Chuuk",
|
||||
"Pacific/Samoa", "Pacific/Pago_Pago",
|
||||
"America/Virgin", "America/St_Thomas",
|
||||
"Asia/Katmandu", "Asia/Kathmandu",
|
||||
"America/Indianapolis", "America/Indiana/Indianapolis",
|
||||
"Europe/Belfast", "Europe/London",
|
||||
"America/Kralendijk", "America/Curacao",
|
||||
"Asia/Rangoon", "Asia/Yangon",
|
||||
};
|
||||
|
||||
private static final Map<String, String> zidToMzone = new HashMap<>();
|
||||
private static final Map<String, String> mzoneToZid = new HashMap<>();
|
||||
private static final Map<String, Map<String, String>> mzoneToZidL = new HashMap<>();
|
||||
private static final Map<String, String> aliases = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (int i = 0; i < zidMap.length; i += 3) {
|
||||
zidToMzone.put(zidMap[i], zidMap[i + 1]);
|
||||
mzoneToZid.put(zidMap[i + 1], zidMap[i + 2]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mzoneMap.length; i += 3) {
|
||||
String mzone = mzoneMap[i];
|
||||
Map<String, String> map = mzoneToZidL.get(mzone);
|
||||
if (map == null) {
|
||||
map = new HashMap<>();
|
||||
mzoneToZidL.put(mzone, map);
|
||||
}
|
||||
map.put(mzoneMap[i + 1], mzoneMap[i + 2]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < aliasMap.length; i += 2) {
|
||||
aliases.put(aliasMap[i], aliasMap[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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>
|
||||
* Provides classes to print and parse dates and times.
|
||||
* </p>
|
||||
* <p>
|
||||
* Printing and parsing is based around the
|
||||
* {@link java.time.format.DateTimeFormatter DateTimeFormatter} class.
|
||||
* Instances are generally obtained from
|
||||
* {@link java.time.format.DateTimeFormatter DateTimeFormatter}, however
|
||||
* {@link java.time.format.DateTimeFormatterBuilder DateTimeFormatterBuilder}
|
||||
* can be used if more power is needed.
|
||||
* </p>
|
||||
* <p>
|
||||
* Localization occurs by calling
|
||||
* {@link java.time.format.DateTimeFormatter#withLocale(java.util.Locale) withLocale(Locale)}
|
||||
* on the formatter. Further customization is possible using
|
||||
* {@link java.time.format.DecimalStyle DecimalStyle}.
|
||||
* </p>
|
||||
*
|
||||
* <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 1.8
|
||||
*/
|
||||
package java.time.format;
|
Loading…
Add table
Add a link
Reference in a new issue