/* * Copyright 2001-2010 Stephen Colebourne * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.joda.time; import java.lang.reflect.Method; import java.text.DateFormatSymbols; import java.util.Locale; import org.joda.time.chrono.ISOChronology; /** * DateTimeUtils provide public utility methods for the date-time library. *
* DateTimeUtils is thread-safe although shared static variables are used. * * @author Stephen Colebourne * @since 1.0 */ public class DateTimeUtils { /** The singleton instance of the system millisecond provider. */ private static final SystemMillisProvider SYSTEM_MILLIS_PROVIDER = new SystemMillisProvider(); /** The millisecond provider currently in use. */ private static volatile MillisProvider cMillisProvider = SYSTEM_MILLIS_PROVIDER; /** * Restrictive constructor */ protected DateTimeUtils() { super(); } //----------------------------------------------------------------------- /** * Gets the current time in milliseconds. *
* By default this returns System.currentTimeMillis()
.
* This may be changed using other methods in this class.
*
* @return the current time in milliseconds from 1970-01-01T00:00:00Z
*/
public static final long currentTimeMillis() {
return cMillisProvider.getMillis();
}
/**
* Resets the current time to return the system time.
*
* This method changes the behaviour of {@link #currentTimeMillis()}. * Whenever the current time is queried, {@link System#currentTimeMillis()} is used. * * @throws SecurityException if the application does not have sufficient security rights */ public static final void setCurrentMillisSystem() throws SecurityException { checkPermission(); cMillisProvider = SYSTEM_MILLIS_PROVIDER; } /** * Sets the current time to return a fixed millisecond time. *
* This method changes the behaviour of {@link #currentTimeMillis()}. * Whenever the current time is queried, the same millisecond time will be returned. * * @param fixedMillis the fixed millisecond time to use * @throws SecurityException if the application does not have sufficient security rights */ public static final void setCurrentMillisFixed(long fixedMillis) throws SecurityException { checkPermission(); cMillisProvider = new FixedMillisProvider(fixedMillis); } /** * Sets the current time to return the system time plus an offset. *
* This method changes the behaviour of {@link #currentTimeMillis()}. * Whenever the current time is queried, {@link System#currentTimeMillis()} is used * and then offset by adding the millisecond value specified here. * * @param offsetMillis the fixed millisecond time to use * @throws SecurityException if the application does not have sufficient security rights */ public static final void setCurrentMillisOffset(long offsetMillis) throws SecurityException { checkPermission(); if (offsetMillis == 0) { cMillisProvider = SYSTEM_MILLIS_PROVIDER; } else { cMillisProvider = new OffsetMillisProvider(offsetMillis); } } /** * Sets the provider of the current time to class specified. *
* This method changes the behaviour of {@link #currentTimeMillis()}. * Whenever the current time is queried, the specified class will be called. * * @param millisProvider the provider of the current time to use, not null * @throws SecurityException if the application does not have sufficient security rights * @since 2.0 */ public static final void setCurrentMillisProvider(MillisProvider millisProvider) throws SecurityException { if (millisProvider == null) { throw new IllegalArgumentException("The MillisProvider must not be null"); } checkPermission(); cMillisProvider = millisProvider; } /** * Checks whether the provider may be changed using permission 'CurrentTime.setProvider'. * * @throws SecurityException if the provider may not be changed */ private static void checkPermission() throws SecurityException { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new JodaTimePermission("CurrentTime.setProvider")); } } //----------------------------------------------------------------------- /** * Gets the millisecond instant from the specified instant object handling null. *
* If the instant object is null
, the {@link #currentTimeMillis()}
* will be returned. Otherwise, the millis from the object are returned.
*
* @param instant the instant to examine, null means now
* @return the time in milliseconds from 1970-01-01T00:00:00Z
*/
public static final long getInstantMillis(ReadableInstant instant) {
if (instant == null) {
return DateTimeUtils.currentTimeMillis();
}
return instant.getMillis();
}
//-----------------------------------------------------------------------
/**
* Gets the chronology from the specified instant object handling null.
*
* If the instant object is null
, or the instant's chronology is
* null
, {@link ISOChronology#getInstance()} will be returned.
* Otherwise, the chronology from the object is returned.
*
* @param instant the instant to examine, null means ISO in the default zone
* @return the chronology, never null
*/
public static final Chronology getInstantChronology(ReadableInstant instant) {
if (instant == null) {
return ISOChronology.getInstance();
}
Chronology chrono = instant.getChronology();
if (chrono == null) {
return ISOChronology.getInstance();
}
return chrono;
}
//-----------------------------------------------------------------------
/**
* Gets the chronology from the specified instant based interval handling null.
*
* The chronology is obtained from the start if that is not null, or from the * end if the start is null. The result is additionally checked, and if still * null then {@link ISOChronology#getInstance()} will be returned. * * @param start the instant to examine and use as the primary source of the chronology * @param end the instant to examine and use as the secondary source of the chronology * @return the chronology, never null */ public static final Chronology getIntervalChronology(ReadableInstant start, ReadableInstant end) { Chronology chrono = null; if (start != null) { chrono = start.getChronology(); } else if (end != null) { chrono = end.getChronology(); } if (chrono == null) { chrono = ISOChronology.getInstance(); } return chrono; } //----------------------------------------------------------------------- /** * Gets the chronology from the specified interval object handling null. *
* If the interval object is null
, or the interval's chronology is
* null
, {@link ISOChronology#getInstance()} will be returned.
* Otherwise, the chronology from the object is returned.
*
* @param interval the interval to examine, null means ISO in the default zone
* @return the chronology, never null
*/
public static final Chronology getIntervalChronology(ReadableInterval interval) {
if (interval == null) {
return ISOChronology.getInstance();
}
Chronology chrono = interval.getChronology();
if (chrono == null) {
return ISOChronology.getInstance();
}
return chrono;
}
//-----------------------------------------------------------------------
/**
* Gets the interval handling null.
*
* If the interval is null
, an interval representing now
* to now in the {@link ISOChronology#getInstance() ISOChronology}
* will be returned. Otherwise, the interval specified is returned.
*
* @param interval the interval to use, null means now to now
* @return the interval, never null
* @since 1.1
*/
public static final ReadableInterval getReadableInterval(ReadableInterval interval) {
if (interval == null) {
long now = DateTimeUtils.currentTimeMillis();
interval = new Interval(now, now);
}
return interval;
}
//-----------------------------------------------------------------------
/**
* Gets the chronology handling null.
*
* If the chronology is null
, {@link ISOChronology#getInstance()}
* will be returned. Otherwise, the chronology is returned.
*
* @param chrono the chronology to use, null means ISO in the default zone
* @return the chronology, never null
*/
public static final Chronology getChronology(Chronology chrono) {
if (chrono == null) {
return ISOChronology.getInstance();
}
return chrono;
}
//-----------------------------------------------------------------------
/**
* Gets the zone handling null.
*
* If the zone is null
, {@link DateTimeZone#getDefault()}
* will be returned. Otherwise, the zone specified is returned.
*
* @param zone the time zone to use, null means the default zone
* @return the time zone, never null
*/
public static final DateTimeZone getZone(DateTimeZone zone) {
if (zone == null) {
return DateTimeZone.getDefault();
}
return zone;
}
//-----------------------------------------------------------------------
/**
* Gets the period type handling null.
*
* If the zone is null
, {@link PeriodType#standard()}
* will be returned. Otherwise, the type specified is returned.
*
* @param type the time zone to use, null means the standard type
* @return the type to use, never null
*/
public static final PeriodType getPeriodType(PeriodType type) {
if (type == null) {
return PeriodType.standard();
}
return type;
}
//-----------------------------------------------------------------------
/**
* Gets the millisecond duration from the specified duration object handling null.
*
* If the duration object is null
, zero will be returned.
* Otherwise, the millis from the object are returned.
*
* @param duration the duration to examine, null means zero
* @return the duration in milliseconds
*/
public static final long getDurationMillis(ReadableDuration duration) {
if (duration == null) {
return 0L;
}
return duration.getMillis();
}
//-----------------------------------------------------------------------
/**
* Checks whether the partial is contiguous.
*
* A partial is contiguous if one field starts where another ends. *
* For example LocalDate
is contiguous because DayOfMonth has
* the same range (Month) as the unit of the next field (MonthOfYear), and
* MonthOfYear has the same range (Year) as the unit of the next field (Year).
*
* Similarly, LocalTime
is contiguous, as it consists of
* MillisOfSecond, SecondOfMinute, MinuteOfHour and HourOfDay (note how
* the names of each field 'join up').
*
* However, a Year/HourOfDay partial is not contiguous because the range * field Day is not equal to the next field Year. * Similarly, a DayOfWeek/DayOfMonth partial is not contiguous because * the range Month is not equal to the next field Day. * * @param partial the partial to check * @return true if the partial is contiguous * @throws IllegalArgumentException if the partial is null * @since 1.1 */ public static final boolean isContiguous(ReadablePartial partial) { if (partial == null) { throw new IllegalArgumentException("Partial must not be null"); } DurationFieldType lastType = null; for (int i = 0; i < partial.size(); i++) { DateTimeField loopField = partial.getField(i); if (i > 0) { if (loopField.getRangeDurationField().getType() != lastType) { return false; } } lastType = loopField.getDurationField().getType(); } return true; } //----------------------------------------------------------------------- /** * Gets the {@link DateFormatSymbols} based on the given locale. *
* If JDK 6 or newer is being used, DateFormatSymbols.getInstance(locale) will * be used in order to allow the use of locales defined as extensions. * Otherwise, new DateFormatSymbols(locale) will be used. * See JDK 6 {@link DateFormatSymbols} for further information. * * @param locale the {@link Locale} used to get the correct {@link DateFormatSymbols} * @return the symbols * @since 2.0 */ public static final DateFormatSymbols getDateFormatSymbols(Locale locale) { try { Method method = DateFormatSymbols.class.getMethod("getInstance", new Class[] {Locale.class}); return (DateFormatSymbols) method.invoke(null, new Object[] {locale}); } catch (Exception ex) { return new DateFormatSymbols(locale); } } //----------------------------------------------------------------------- /** * A millisecond provider, allowing control of the system clock. * * @author Stephen Colebourne * @since 2.0 (previously private) */ public static interface MillisProvider { /** * Gets the current time. *
* Implementations of this method must be thread-safe. * * @return the current time in milliseconds */ long getMillis(); } /** * System millis provider. */ static class SystemMillisProvider implements MillisProvider { /** * Gets the current time. * @return the current time in millis */ public long getMillis() { return System.currentTimeMillis(); } } /** * Fixed millisecond provider. */ static class FixedMillisProvider implements MillisProvider { /** The fixed millis value. */ private final long iMillis; /** * Constructor. * @param offsetMillis the millis offset */ FixedMillisProvider(long fixedMillis) { iMillis = fixedMillis; } /** * Gets the current time. * @return the current time in millis */ public long getMillis() { return iMillis; } } /** * Offset from system millis provider. */ static class OffsetMillisProvider implements MillisProvider { /** The millis offset. */ private final long iMillis; /** * Constructor. * @param offsetMillis the millis offset */ OffsetMillisProvider(long offsetMillis) { iMillis = offsetMillis; } /** * Gets the current time. * @return the current time in millis */ public long getMillis() { return System.currentTimeMillis() + iMillis; } } }