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