src/share/classes/java/time/ZoneOffset.java
Print this page
*** 59,68 ****
--- 59,71 ----
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time;
+ import static java.time.LocalTime.MINUTES_PER_HOUR;
+ import static java.time.LocalTime.SECONDS_PER_HOUR;
+ import static java.time.LocalTime.SECONDS_PER_MINUTE;
import static java.time.temporal.ChronoField.OFFSET_SECONDS;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
*** 124,145 ****
private static final ConcurrentMap<Integer, ZoneOffset> SECONDS_CACHE = new ConcurrentHashMap<>(16, 0.75f, 4);
/** Cache of time-zone offset by ID. */
private static final ConcurrentMap<String, ZoneOffset> ID_CACHE = new ConcurrentHashMap<>(16, 0.75f, 4);
/**
- * The number of seconds per hour.
- */
- private static final int SECONDS_PER_HOUR = 60 * 60;
- /**
- * The number of seconds per minute.
- */
- private static final int SECONDS_PER_MINUTE = 60;
- /**
- * The number of minutes per hour.
- */
- private static final int MINUTES_PER_HOUR = 60;
- /**
* The abs maximum seconds.
*/
private static final int MAX_SECONDS = 18 * SECONDS_PER_HOUR;
/**
* Serialization version.
--- 127,136 ----
*** 237,251 ****
hours = parseNumber(offsetId, 1, false);
minutes = parseNumber(offsetId, 4, true);
seconds = parseNumber(offsetId, 7, true);
break;
default:
! throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid");
}
char first = offsetId.charAt(0);
if (first != '+' && first != '-') {
! throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid: Plus/minus not found when expected");
}
if (first == '-') {
return ofHoursMinutesSeconds(-hours, -minutes, -seconds);
} else {
return ofHoursMinutesSeconds(hours, minutes, seconds);
--- 228,242 ----
hours = parseNumber(offsetId, 1, false);
minutes = parseNumber(offsetId, 4, true);
seconds = parseNumber(offsetId, 7, true);
break;
default:
! throw new DateTimeException("Invalid ID for ZoneOffset, invalid format: " + offsetId);
}
char first = offsetId.charAt(0);
if (first != '+' && first != '-') {
! throw new DateTimeException("Invalid ID for ZoneOffset, plus/minus not found when expected: " + offsetId);
}
if (first == '-') {
return ofHoursMinutesSeconds(-hours, -minutes, -seconds);
} else {
return ofHoursMinutesSeconds(hours, minutes, seconds);
*** 260,275 ****
* @param precededByColon should this number be prefixed by a precededByColon
* @return the parsed number, from 0 to 99
*/
private static int parseNumber(CharSequence offsetId, int pos, boolean precededByColon) {
if (precededByColon && offsetId.charAt(pos - 1) != ':') {
! throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid: Colon not found when expected");
}
char ch1 = offsetId.charAt(pos);
char ch2 = offsetId.charAt(pos + 1);
if (ch1 < '0' || ch1 > '9' || ch2 < '0' || ch2 > '9') {
! throw new DateTimeException("Zone offset ID '" + offsetId + "' is invalid: Non numeric characters found");
}
return (ch1 - 48) * 10 + (ch2 - 48);
}
//-----------------------------------------------------------------------
--- 251,266 ----
* @param precededByColon should this number be prefixed by a precededByColon
* @return the parsed number, from 0 to 99
*/
private static int parseNumber(CharSequence offsetId, int pos, boolean precededByColon) {
if (precededByColon && offsetId.charAt(pos - 1) != ':') {
! throw new DateTimeException("Invalid ID for ZoneOffset, colon not found when expected: " + offsetId);
}
char ch1 = offsetId.charAt(pos);
char ch2 = offsetId.charAt(pos + 1);
if (ch1 < '0' || ch1 > '9' || ch2 < '0' || ch2 > '9') {
! throw new DateTimeException("Invalid ID for ZoneOffset, non numeric characters found: " + offsetId);
}
return (ch1 - 48) * 10 + (ch2 - 48);
}
//-----------------------------------------------------------------------
*** 322,352 ****
//-----------------------------------------------------------------------
/**
* Obtains an instance of {@code ZoneOffset} from a temporal object.
* <p>
* A {@code TemporalAccessor} represents some form of date and time information.
* This factory converts the arbitrary temporal object to an instance of {@code ZoneOffset}.
* <p>
! * The conversion extracts the {@link ChronoField#OFFSET_SECONDS offset-seconds} field.
* <p>
* This method matches the signature of the functional interface {@link TemporalQuery}
* allowing it to be used in queries via method reference, {@code ZoneOffset::from}.
*
* @param temporal the temporal object to convert, not null
* @return the zone-offset, not null
* @throws DateTimeException if unable to convert to an {@code ZoneOffset}
*/
public static ZoneOffset from(TemporalAccessor temporal) {
! if (temporal instanceof ZoneOffset) {
! return (ZoneOffset) temporal;
! }
! try {
! return ofTotalSeconds(temporal.get(OFFSET_SECONDS));
! } catch (DateTimeException ex) {
! throw new DateTimeException("Unable to obtain ZoneOffset from TemporalAccessor: " + temporal.getClass(), ex);
}
}
//-----------------------------------------------------------------------
/**
* Validates the offset fields.
--- 313,345 ----
//-----------------------------------------------------------------------
/**
* Obtains an instance of {@code ZoneOffset} from a temporal object.
* <p>
+ * This obtains an offset based on the specified temporal.
+ * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
+ * which this factory converts to an instance of {@code ZoneOffset}.
+ * <p>
* A {@code TemporalAccessor} represents some form of date and time information.
* This factory converts the arbitrary temporal object to an instance of {@code ZoneOffset}.
* <p>
! * The conversion uses the {@link Queries#offset()} query, which relies
! * on extracting the {@link ChronoField#OFFSET_SECONDS OFFSET_SECONDS} field.
* <p>
* This method matches the signature of the functional interface {@link TemporalQuery}
* allowing it to be used in queries via method reference, {@code ZoneOffset::from}.
*
* @param temporal the temporal object to convert, not null
* @return the zone-offset, not null
* @throws DateTimeException if unable to convert to an {@code ZoneOffset}
*/
public static ZoneOffset from(TemporalAccessor temporal) {
! ZoneOffset offset = temporal.query(Queries.offset());
! if (offset == null) {
! throw new DateTimeException("Unable to obtain ZoneOffset from TemporalAccessor: " + temporal.getClass());
}
+ return offset;
}
//-----------------------------------------------------------------------
/**
* Validates the offset fields.
*** 513,523 ****
* If the field is a {@link ChronoField} then the query is implemented here.
* The {@code OFFSET_SECONDS} field returns true.
* All other {@code ChronoField} instances will return false.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
! * is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
* passing {@code this} as the argument.
* Whether the field is supported is determined by the field.
*
* @param field the field to check, null returns false
* @return true if the field is supported on this offset, false if not
--- 506,516 ----
* If the field is a {@link ChronoField} then the query is implemented here.
* The {@code OFFSET_SECONDS} field returns true.
* All other {@code ChronoField} instances will return false.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
! * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
* passing {@code this} as the argument.
* Whether the field is supported is determined by the field.
*
* @param field the field to check, null returns false
* @return true if the field is supported on this offset, false if not
*** 525,535 ****
@Override
public boolean isSupported(TemporalField field) {
if (field instanceof ChronoField) {
return field == OFFSET_SECONDS;
}
! return field != null && field.doIsSupported(this);
}
/**
* Gets the range of valid values for the specified field.
* <p>
--- 518,528 ----
@Override
public boolean isSupported(TemporalField field) {
if (field instanceof ChronoField) {
return field == OFFSET_SECONDS;
}
! return field != null && field.isSupportedBy(this);
}
/**
* Gets the range of valid values for the specified field.
* <p>
*** 542,552 ****
* The {@link #isSupported(TemporalField) supported fields} will return
* appropriate range instances.
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
! * is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
* passing {@code this} as the argument.
* Whether the range can be obtained is determined by the field.
*
* @param field the field to query the range for, not null
* @return the range of valid values for the field, not null
--- 535,545 ----
* The {@link #isSupported(TemporalField) supported fields} will return
* appropriate range instances.
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
! * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
* passing {@code this} as the argument.
* Whether the range can be obtained is determined by the field.
*
* @param field the field to query the range for, not null
* @return the range of valid values for the field, not null
*** 568,578 ****
* If the field is a {@link ChronoField} then the query is implemented here.
* The {@code OFFSET_SECONDS} field returns the value of the offset.
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
! * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
* passing {@code this} as the argument. Whether the value can be obtained,
* and what the value represents, is determined by the field.
*
* @param field the field to get, not null
* @return the value for the field
--- 561,571 ----
* If the field is a {@link ChronoField} then the query is implemented here.
* The {@code OFFSET_SECONDS} field returns the value of the offset.
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
! * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
* passing {@code this} as the argument. Whether the value can be obtained,
* and what the value represents, is determined by the field.
*
* @param field the field to get, not null
* @return the value for the field
*** 599,609 ****
* If the field is a {@link ChronoField} then the query is implemented here.
* The {@code OFFSET_SECONDS} field returns the value of the offset.
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
! * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
* passing {@code this} as the argument. Whether the value can be obtained,
* and what the value represents, is determined by the field.
*
* @param field the field to get, not null
* @return the value for the field
--- 592,602 ----
* If the field is a {@link ChronoField} then the query is implemented here.
* The {@code OFFSET_SECONDS} field returns the value of the offset.
* All other {@code ChronoField} instances will throw a {@code DateTimeException}.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
! * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
* passing {@code this} as the argument. Whether the value can be obtained,
* and what the value represents, is determined by the field.
*
* @param field the field to get, not null
* @return the value for the field
*** 615,625 ****
if (field == OFFSET_SECONDS) {
return totalSeconds;
} else if (field instanceof ChronoField) {
throw new DateTimeException("Unsupported field: " + field.getName());
}
! return field.doGet(this);
}
//-----------------------------------------------------------------------
/**
* Queries this offset using the specified query.
--- 608,618 ----
if (field == OFFSET_SECONDS) {
return totalSeconds;
} else if (field instanceof ChronoField) {
throw new DateTimeException("Unsupported field: " + field.getName());
}
! return field.getFrom(this);
}
//-----------------------------------------------------------------------
/**
* Queries this offset using the specified query.