001: /*
002: * Copyright 2001-2006 Stephen Colebourne
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.joda.time;
017:
018: import org.joda.time.chrono.ISOChronology;
019:
020: /**
021: * DateTimeUtils provide public utility methods for the datetime library.
022: * <p>
023: * DateTimeUtils is thread-safe although shared static variables are used.
024: *
025: * @author Stephen Colebourne
026: * @since 1.0
027: */
028: public class DateTimeUtils {
029:
030: /** The singleton instance of the system millisecond provider */
031: private static final SystemMillisProvider SYSTEM_MILLIS_PROVIDER = new SystemMillisProvider();
032:
033: /** The millisecond provider currently in use */
034: private static MillisProvider cMillisProvider = SYSTEM_MILLIS_PROVIDER;
035:
036: /**
037: * Restrictive constructor
038: */
039: protected DateTimeUtils() {
040: super ();
041: }
042:
043: //-----------------------------------------------------------------------
044: /**
045: * Gets the current time in milliseconds.
046: * <p>
047: * By default this returns <code>System.currentTimeMillis()</code>.
048: * This may be changed using other methods in this class.
049: *
050: * @return the current time in milliseconds from 1970-01-01T00:00:00Z
051: */
052: public static final long currentTimeMillis() {
053: return cMillisProvider.getMillis();
054: }
055:
056: /**
057: * Resets the current time to return the system time.
058: * <p>
059: * This method changes the behaviour of {@link #currentTimeMillis()}.
060: * Whenever the current time is queried, {@link System#currentTimeMillis()} is used.
061: *
062: * @throws SecurityException if the application does not have sufficient security rights
063: */
064: public static final void setCurrentMillisSystem()
065: throws SecurityException {
066: checkPermission();
067: cMillisProvider = SYSTEM_MILLIS_PROVIDER;
068: }
069:
070: /**
071: * Sets the current time to return a fixed millisecond time.
072: * <p>
073: * This method changes the behaviour of {@link #currentTimeMillis()}.
074: * Whenever the current time is queried, the same millisecond time will be returned.
075: *
076: * @param fixedMillis the fixed millisecond time to use
077: * @throws SecurityException if the application does not have sufficient security rights
078: */
079: public static final void setCurrentMillisFixed(long fixedMillis)
080: throws SecurityException {
081: checkPermission();
082: cMillisProvider = new FixedMillisProvider(fixedMillis);
083: }
084:
085: /**
086: * Sets the current time to return the system time plus an offset.
087: * <p>
088: * This method changes the behaviour of {@link #currentTimeMillis()}.
089: * Whenever the current time is queried, {@link System#currentTimeMillis()} is used
090: * and then offset by adding the millisecond value specified here.
091: *
092: * @param offsetMillis the fixed millisecond time to use
093: * @throws SecurityException if the application does not have sufficient security rights
094: */
095: public static final void setCurrentMillisOffset(long offsetMillis)
096: throws SecurityException {
097: checkPermission();
098: if (offsetMillis == 0) {
099: cMillisProvider = SYSTEM_MILLIS_PROVIDER;
100: } else {
101: cMillisProvider = new OffsetMillisProvider(offsetMillis);
102: }
103: }
104:
105: /**
106: * Checks whether the provider may be changed using permission 'CurrentTime.setProvider'.
107: *
108: * @throws SecurityException if the provider may not be changed
109: */
110: private static void checkPermission() throws SecurityException {
111: SecurityManager sm = System.getSecurityManager();
112: if (sm != null) {
113: sm.checkPermission(new JodaTimePermission(
114: "CurrentTime.setProvider"));
115: }
116: }
117:
118: //-----------------------------------------------------------------------
119: /**
120: * Gets the millisecond instant from the specified instant object handling null.
121: * <p>
122: * If the instant object is <code>null</code>, the {@link #currentTimeMillis()}
123: * will be returned. Otherwise, the millis from the object are returned.
124: *
125: * @param instant the instant to examine, null means now
126: * @return the time in milliseconds from 1970-01-01T00:00:00Z
127: */
128: public static final long getInstantMillis(ReadableInstant instant) {
129: if (instant == null) {
130: return DateTimeUtils.currentTimeMillis();
131: }
132: return instant.getMillis();
133: }
134:
135: //-----------------------------------------------------------------------
136: /**
137: * Gets the chronology from the specified instant object handling null.
138: * <p>
139: * If the instant object is <code>null</code>, or the instant's chronology is
140: * <code>null</code>, {@link ISOChronology#getInstance()} will be returned.
141: * Otherwise, the chronology from the object is returned.
142: *
143: * @param instant the instant to examine, null means ISO in the default zone
144: * @return the chronology, never null
145: */
146: public static final Chronology getInstantChronology(
147: ReadableInstant instant) {
148: if (instant == null) {
149: return ISOChronology.getInstance();
150: }
151: Chronology chrono = instant.getChronology();
152: if (chrono == null) {
153: return ISOChronology.getInstance();
154: }
155: return chrono;
156: }
157:
158: //-----------------------------------------------------------------------
159: /**
160: * Gets the chronology from the specified instant based interval handling null.
161: * <p>
162: * The chronology is obtained from the start if that is not null, or from the
163: * end if the start is null. The result is additionally checked, and if still
164: * null then {@link ISOChronology#getInstance()} will be returned.
165: *
166: * @param start the instant to examine and use as the primary source of the chronology
167: * @param end the instant to examine and use as the secondary source of the chronology
168: * @return the chronology, never null
169: */
170: public static final Chronology getIntervalChronology(
171: ReadableInstant start, ReadableInstant end) {
172: Chronology chrono = null;
173: if (start != null) {
174: chrono = start.getChronology();
175: } else if (end != null) {
176: chrono = end.getChronology();
177: }
178: if (chrono == null) {
179: chrono = ISOChronology.getInstance();
180: }
181: return chrono;
182: }
183:
184: //-----------------------------------------------------------------------
185: /**
186: * Gets the chronology from the specified interval object handling null.
187: * <p>
188: * If the interval object is <code>null</code>, or the interval's chronology is
189: * <code>null</code>, {@link ISOChronology#getInstance()} will be returned.
190: * Otherwise, the chronology from the object is returned.
191: *
192: * @param interval the interval to examine, null means ISO in the default zone
193: * @return the chronology, never null
194: */
195: public static final Chronology getIntervalChronology(
196: ReadableInterval interval) {
197: if (interval == null) {
198: return ISOChronology.getInstance();
199: }
200: Chronology chrono = interval.getChronology();
201: if (chrono == null) {
202: return ISOChronology.getInstance();
203: }
204: return chrono;
205: }
206:
207: //-----------------------------------------------------------------------
208: /**
209: * Gets the interval handling null.
210: * <p>
211: * If the interval is <code>null</code>, an interval representing now
212: * to now in the {@link ISOChronology#getInstance() ISOChronology}
213: * will be returned. Otherwise, the interval specified is returned.
214: *
215: * @param interval the interval to use, null means now to now
216: * @return the interval, never null
217: * @since 1.1
218: */
219: public static final ReadableInterval getReadableInterval(
220: ReadableInterval interval) {
221: if (interval == null) {
222: long now = DateTimeUtils.currentTimeMillis();
223: interval = new Interval(now, now);
224: }
225: return interval;
226: }
227:
228: //-----------------------------------------------------------------------
229: /**
230: * Gets the chronology handling null.
231: * <p>
232: * If the chronology is <code>null</code>, {@link ISOChronology#getInstance()}
233: * will be returned. Otherwise, the chronology is returned.
234: *
235: * @param chrono the chronology to use, null means ISO in the default zone
236: * @return the chronology, never null
237: */
238: public static final Chronology getChronology(Chronology chrono) {
239: if (chrono == null) {
240: return ISOChronology.getInstance();
241: }
242: return chrono;
243: }
244:
245: //-----------------------------------------------------------------------
246: /**
247: * Gets the zone handling null.
248: * <p>
249: * If the zone is <code>null</code>, {@link DateTimeZone#getDefault()}
250: * will be returned. Otherwise, the zone specified is returned.
251: *
252: * @param zone the time zone to use, null means the default zone
253: * @return the time zone, never null
254: */
255: public static final DateTimeZone getZone(DateTimeZone zone) {
256: if (zone == null) {
257: return DateTimeZone.getDefault();
258: }
259: return zone;
260: }
261:
262: //-----------------------------------------------------------------------
263: /**
264: * Gets the period type handling null.
265: * <p>
266: * If the zone is <code>null</code>, {@link PeriodType#standard()}
267: * will be returned. Otherwise, the type specified is returned.
268: *
269: * @param type the time zone to use, null means the standard type
270: * @return the type to use, never null
271: */
272: public static final PeriodType getPeriodType(PeriodType type) {
273: if (type == null) {
274: return PeriodType.standard();
275: }
276: return type;
277: }
278:
279: //-----------------------------------------------------------------------
280: /**
281: * Gets the millisecond duration from the specified duration object handling null.
282: * <p>
283: * If the duration object is <code>null</code>, zero will be returned.
284: * Otherwise, the millis from the object are returned.
285: *
286: * @param duration the duration to examine, null means zero
287: * @return the duration in milliseconds
288: */
289: public static final long getDurationMillis(ReadableDuration duration) {
290: if (duration == null) {
291: return 0L;
292: }
293: return duration.getMillis();
294: }
295:
296: //-----------------------------------------------------------------------
297: /**
298: * Checks whether the partial is contiguous.
299: * <p>
300: * A partial is contiguous if one field starts where another ends.
301: * <p>
302: * For example <code>LocalDate</code> is contiguous because DayOfMonth has
303: * the same range (Month) as the unit of the next field (MonthOfYear), and
304: * MonthOfYear has the same range (Year) as the unit of the next field (Year).
305: * <p>
306: * Similarly, <code>LocalTime</code> is contiguous, as it consists of
307: * MillisOfSecond, SecondOfMinute, MinuteOfHour and HourOfDay (note how
308: * the names of each field 'join up').
309: * <p>
310: * However, a Year/HourOfDay partial is not contiguous because the range
311: * field Day is not equal to the next field Year.
312: * Similarly, a DayOfWeek/DayOfMonth partial is not contiguous because
313: * the range Month is not equal to the next field Day.
314: *
315: * @param partial the partial to check
316: * @return true if the partial is contiguous
317: * @throws IllegalArgumentException if the partial is null
318: * @since 1.1
319: */
320: public static final boolean isContiguous(ReadablePartial partial) {
321: if (partial == null) {
322: throw new IllegalArgumentException(
323: "Partial must not be null");
324: }
325: DurationFieldType lastType = null;
326: for (int i = 0; i < partial.size(); i++) {
327: DateTimeField loopField = partial.getField(i);
328: if (i > 0) {
329: if (loopField.getRangeDurationField().getType() != lastType) {
330: return false;
331: }
332: }
333: lastType = loopField.getDurationField().getType();
334: }
335: return true;
336: }
337:
338: //-----------------------------------------------------------------------
339: /**
340: * Base class defining a millisecond provider.
341: */
342: abstract static class MillisProvider {
343: /**
344: * Gets the current time.
345: * @return the current time in millis
346: */
347: abstract long getMillis();
348: }
349:
350: /**
351: * System millis provider.
352: */
353: static class SystemMillisProvider extends MillisProvider {
354: /**
355: * Gets the current time.
356: * @return the current time in millis
357: */
358: long getMillis() {
359: return System.currentTimeMillis();
360: }
361: }
362:
363: /**
364: * Fixed millisecond provider.
365: */
366: static class FixedMillisProvider extends MillisProvider {
367: /** The fixed millis value. */
368: private final long iMillis;
369:
370: /**
371: * Constructor.
372: * @param offsetMillis the millis offset
373: */
374: FixedMillisProvider(long fixedMillis) {
375: iMillis = fixedMillis;
376: }
377:
378: /**
379: * Gets the current time.
380: * @return the current time in millis
381: */
382: long getMillis() {
383: return iMillis;
384: }
385: }
386:
387: /**
388: * Offset from system millis provider.
389: */
390: static class OffsetMillisProvider extends MillisProvider {
391: /** The millis offset. */
392: private final long iMillis;
393:
394: /**
395: * Constructor.
396: * @param offsetMillis the millis offset
397: */
398: OffsetMillisProvider(long offsetMillis) {
399: iMillis = offsetMillis;
400: }
401:
402: /**
403: * Gets the current time.
404: * @return the current time in millis
405: */
406: long getMillis() {
407: return System.currentTimeMillis() + iMillis;
408: }
409: }
410:
411: }
|