1 | /* |
2 | * Copyright 2001-2006 Stephen Colebourne |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | package org.joda.time; |
17 | |
18 | import org.joda.time.chrono.ISOChronology; |
19 | |
20 | /** |
21 | * DateTimeUtils provide public utility methods for the datetime library. |
22 | * <p> |
23 | * DateTimeUtils is thread-safe although shared static variables are used. |
24 | * |
25 | * @author Stephen Colebourne |
26 | * @since 1.0 |
27 | */ |
28 | public class DateTimeUtils { |
29 | |
30 | /** The singleton instance of the system millisecond provider */ |
31 | private static final SystemMillisProvider SYSTEM_MILLIS_PROVIDER = new SystemMillisProvider(); |
32 | |
33 | /** The millisecond provider currently in use */ |
34 | private static MillisProvider cMillisProvider = SYSTEM_MILLIS_PROVIDER; |
35 | |
36 | /** |
37 | * Restrictive constructor |
38 | */ |
39 | protected DateTimeUtils() { |
40 | super(); |
41 | } |
42 | |
43 | //----------------------------------------------------------------------- |
44 | /** |
45 | * Gets the current time in milliseconds. |
46 | * <p> |
47 | * By default this returns <code>System.currentTimeMillis()</code>. |
48 | * This may be changed using other methods in this class. |
49 | * |
50 | * @return the current time in milliseconds from 1970-01-01T00:00:00Z |
51 | */ |
52 | public static final long currentTimeMillis() { |
53 | return cMillisProvider.getMillis(); |
54 | } |
55 | |
56 | /** |
57 | * Resets the current time to return the system time. |
58 | * <p> |
59 | * This method changes the behaviour of {@link #currentTimeMillis()}. |
60 | * Whenever the current time is queried, {@link System#currentTimeMillis()} is used. |
61 | * |
62 | * @throws SecurityException if the application does not have sufficient security rights |
63 | */ |
64 | public static final void setCurrentMillisSystem() throws SecurityException { |
65 | checkPermission(); |
66 | cMillisProvider = SYSTEM_MILLIS_PROVIDER; |
67 | } |
68 | |
69 | /** |
70 | * Sets the current time to return a fixed millisecond time. |
71 | * <p> |
72 | * This method changes the behaviour of {@link #currentTimeMillis()}. |
73 | * Whenever the current time is queried, the same millisecond time will be returned. |
74 | * |
75 | * @param fixedMillis the fixed millisecond time to use |
76 | * @throws SecurityException if the application does not have sufficient security rights |
77 | */ |
78 | public static final void setCurrentMillisFixed(long fixedMillis) throws SecurityException { |
79 | checkPermission(); |
80 | cMillisProvider = new FixedMillisProvider(fixedMillis); |
81 | } |
82 | |
83 | /** |
84 | * Sets the current time to return the system time plus an offset. |
85 | * <p> |
86 | * This method changes the behaviour of {@link #currentTimeMillis()}. |
87 | * Whenever the current time is queried, {@link System#currentTimeMillis()} is used |
88 | * and then offset by adding the millisecond value specified here. |
89 | * |
90 | * @param offsetMillis the fixed millisecond time to use |
91 | * @throws SecurityException if the application does not have sufficient security rights |
92 | */ |
93 | public static final void setCurrentMillisOffset(long offsetMillis) throws SecurityException { |
94 | checkPermission(); |
95 | if (offsetMillis == 0) { |
96 | cMillisProvider = SYSTEM_MILLIS_PROVIDER; |
97 | } else { |
98 | cMillisProvider = new OffsetMillisProvider(offsetMillis); |
99 | } |
100 | } |
101 | |
102 | /** |
103 | * Checks whether the provider may be changed using permission 'CurrentTime.setProvider'. |
104 | * |
105 | * @throws SecurityException if the provider may not be changed |
106 | */ |
107 | private static void checkPermission() throws SecurityException { |
108 | SecurityManager sm = System.getSecurityManager(); |
109 | if (sm != null) { |
110 | sm.checkPermission(new JodaTimePermission("CurrentTime.setProvider")); |
111 | } |
112 | } |
113 | |
114 | //----------------------------------------------------------------------- |
115 | /** |
116 | * Gets the millisecond instant from the specified instant object handling null. |
117 | * <p> |
118 | * If the instant object is <code>null</code>, the {@link #currentTimeMillis()} |
119 | * will be returned. Otherwise, the millis from the object are returned. |
120 | * |
121 | * @param instant the instant to examine, null means now |
122 | * @return the time in milliseconds from 1970-01-01T00:00:00Z |
123 | */ |
124 | public static final long getInstantMillis(ReadableInstant instant) { |
125 | if (instant == null) { |
126 | return DateTimeUtils.currentTimeMillis(); |
127 | } |
128 | return instant.getMillis(); |
129 | } |
130 | |
131 | //----------------------------------------------------------------------- |
132 | /** |
133 | * Gets the chronology from the specified instant object handling null. |
134 | * <p> |
135 | * If the instant object is <code>null</code>, or the instant's chronology is |
136 | * <code>null</code>, {@link ISOChronology#getInstance()} will be returned. |
137 | * Otherwise, the chronology from the object is returned. |
138 | * |
139 | * @param instant the instant to examine, null means ISO in the default zone |
140 | * @return the chronology, never null |
141 | */ |
142 | public static final Chronology getInstantChronology(ReadableInstant instant) { |
143 | if (instant == null) { |
144 | return ISOChronology.getInstance(); |
145 | } |
146 | Chronology chrono = instant.getChronology(); |
147 | if (chrono == null) { |
148 | return ISOChronology.getInstance(); |
149 | } |
150 | return chrono; |
151 | } |
152 | |
153 | //----------------------------------------------------------------------- |
154 | /** |
155 | * Gets the chronology from the specified instant based interval handling null. |
156 | * <p> |
157 | * The chronology is obtained from the start if that is not null, or from the |
158 | * end if the start is null. The result is additionally checked, and if still |
159 | * null then {@link ISOChronology#getInstance()} will be returned. |
160 | * |
161 | * @param start the instant to examine and use as the primary source of the chronology |
162 | * @param end the instant to examine and use as the secondary source of the chronology |
163 | * @return the chronology, never null |
164 | */ |
165 | public static final Chronology getIntervalChronology(ReadableInstant start, ReadableInstant end) { |
166 | Chronology chrono = null; |
167 | if (start != null) { |
168 | chrono = start.getChronology(); |
169 | } else if (end != null) { |
170 | chrono = end.getChronology(); |
171 | } |
172 | if (chrono == null) { |
173 | chrono = ISOChronology.getInstance(); |
174 | } |
175 | return chrono; |
176 | } |
177 | |
178 | //----------------------------------------------------------------------- |
179 | /** |
180 | * Gets the chronology from the specified interval object handling null. |
181 | * <p> |
182 | * If the interval object is <code>null</code>, or the interval's chronology is |
183 | * <code>null</code>, {@link ISOChronology#getInstance()} will be returned. |
184 | * Otherwise, the chronology from the object is returned. |
185 | * |
186 | * @param interval the interval to examine, null means ISO in the default zone |
187 | * @return the chronology, never null |
188 | */ |
189 | public static final Chronology getIntervalChronology(ReadableInterval interval) { |
190 | if (interval == null) { |
191 | return ISOChronology.getInstance(); |
192 | } |
193 | Chronology chrono = interval.getChronology(); |
194 | if (chrono == null) { |
195 | return ISOChronology.getInstance(); |
196 | } |
197 | return chrono; |
198 | } |
199 | |
200 | //----------------------------------------------------------------------- |
201 | /** |
202 | * Gets the interval handling null. |
203 | * <p> |
204 | * If the interval is <code>null</code>, an interval representing now |
205 | * to now in the {@link ISOChronology#getInstance() ISOChronology} |
206 | * will be returned. Otherwise, the interval specified is returned. |
207 | * |
208 | * @param interval the interval to use, null means now to now |
209 | * @return the interval, never null |
210 | * @since 1.1 |
211 | */ |
212 | public static final ReadableInterval getReadableInterval(ReadableInterval interval) { |
213 | if (interval == null) { |
214 | long now = DateTimeUtils.currentTimeMillis(); |
215 | interval = new Interval(now, now); |
216 | } |
217 | return interval; |
218 | } |
219 | |
220 | //----------------------------------------------------------------------- |
221 | /** |
222 | * Gets the chronology handling null. |
223 | * <p> |
224 | * If the chronology is <code>null</code>, {@link ISOChronology#getInstance()} |
225 | * will be returned. Otherwise, the chronology is returned. |
226 | * |
227 | * @param chrono the chronology to use, null means ISO in the default zone |
228 | * @return the chronology, never null |
229 | */ |
230 | public static final Chronology getChronology(Chronology chrono) { |
231 | if (chrono == null) { |
232 | return ISOChronology.getInstance(); |
233 | } |
234 | return chrono; |
235 | } |
236 | |
237 | //----------------------------------------------------------------------- |
238 | /** |
239 | * Gets the zone handling null. |
240 | * <p> |
241 | * If the zone is <code>null</code>, {@link DateTimeZone#getDefault()} |
242 | * will be returned. Otherwise, the zone specified is returned. |
243 | * |
244 | * @param zone the time zone to use, null means the default zone |
245 | * @return the time zone, never null |
246 | */ |
247 | public static final DateTimeZone getZone(DateTimeZone zone) { |
248 | if (zone == null) { |
249 | return DateTimeZone.getDefault(); |
250 | } |
251 | return zone; |
252 | } |
253 | |
254 | //----------------------------------------------------------------------- |
255 | /** |
256 | * Gets the period type handling null. |
257 | * <p> |
258 | * If the zone is <code>null</code>, {@link PeriodType#standard()} |
259 | * will be returned. Otherwise, the type specified is returned. |
260 | * |
261 | * @param type the time zone to use, null means the standard type |
262 | * @return the type to use, never null |
263 | */ |
264 | public static final PeriodType getPeriodType(PeriodType type) { |
265 | if (type == null) { |
266 | return PeriodType.standard(); |
267 | } |
268 | return type; |
269 | } |
270 | |
271 | //----------------------------------------------------------------------- |
272 | /** |
273 | * Gets the millisecond duration from the specified duration object handling null. |
274 | * <p> |
275 | * If the duration object is <code>null</code>, zero will be returned. |
276 | * Otherwise, the millis from the object are returned. |
277 | * |
278 | * @param duration the duration to examine, null means zero |
279 | * @return the duration in milliseconds |
280 | */ |
281 | public static final long getDurationMillis(ReadableDuration duration) { |
282 | if (duration == null) { |
283 | return 0L; |
284 | } |
285 | return duration.getMillis(); |
286 | } |
287 | |
288 | //----------------------------------------------------------------------- |
289 | /** |
290 | * Checks whether the partial is contiguous. |
291 | * <p> |
292 | * A partial is contiguous if one field starts where another ends. |
293 | * <p> |
294 | * For example <code>LocalDate</code> is contiguous because DayOfMonth has |
295 | * the same range (Month) as the unit of the next field (MonthOfYear), and |
296 | * MonthOfYear has the same range (Year) as the unit of the next field (Year). |
297 | * <p> |
298 | * Similarly, <code>LocalTime</code> is contiguous, as it consists of |
299 | * MillisOfSecond, SecondOfMinute, MinuteOfHour and HourOfDay (note how |
300 | * the names of each field 'join up'). |
301 | * <p> |
302 | * However, a Year/HourOfDay partial is not contiguous because the range |
303 | * field Day is not equal to the next field Year. |
304 | * Similarly, a DayOfWeek/DayOfMonth partial is not contiguous because |
305 | * the range Month is not equal to the next field Day. |
306 | * |
307 | * @param partial the partial to check |
308 | * @return true if the partial is contiguous |
309 | * @throws IllegalArgumentException if the partial is null |
310 | * @since 1.1 |
311 | */ |
312 | public static final boolean isContiguous(ReadablePartial partial) { |
313 | if (partial == null) { |
314 | throw new IllegalArgumentException("Partial must not be null"); |
315 | } |
316 | DurationFieldType lastType = null; |
317 | for (int i = 0; i < partial.size(); i++) { |
318 | DateTimeField loopField = partial.getField(i); |
319 | if (i > 0) { |
320 | if (loopField.getRangeDurationField().getType() != lastType) { |
321 | return false; |
322 | } |
323 | } |
324 | lastType = loopField.getDurationField().getType(); |
325 | } |
326 | return true; |
327 | } |
328 | |
329 | //----------------------------------------------------------------------- |
330 | /** |
331 | * Base class defining a millisecond provider. |
332 | */ |
333 | abstract static class MillisProvider { |
334 | /** |
335 | * Gets the current time. |
336 | * @return the current time in millis |
337 | */ |
338 | abstract long getMillis(); |
339 | } |
340 | |
341 | /** |
342 | * System millis provider. |
343 | */ |
344 | static class SystemMillisProvider extends MillisProvider { |
345 | /** |
346 | * Gets the current time. |
347 | * @return the current time in millis |
348 | */ |
349 | long getMillis() { |
350 | return System.currentTimeMillis(); |
351 | } |
352 | } |
353 | |
354 | /** |
355 | * Fixed millisecond provider. |
356 | */ |
357 | static class FixedMillisProvider extends MillisProvider { |
358 | /** The fixed millis value. */ |
359 | private final long iMillis; |
360 | |
361 | /** |
362 | * Constructor. |
363 | * @param offsetMillis the millis offset |
364 | */ |
365 | FixedMillisProvider(long fixedMillis) { |
366 | iMillis = fixedMillis; |
367 | } |
368 | |
369 | /** |
370 | * Gets the current time. |
371 | * @return the current time in millis |
372 | */ |
373 | long getMillis() { |
374 | return iMillis; |
375 | } |
376 | } |
377 | |
378 | /** |
379 | * Offset from system millis provider. |
380 | */ |
381 | static class OffsetMillisProvider extends MillisProvider { |
382 | /** The millis offset. */ |
383 | private final long iMillis; |
384 | |
385 | /** |
386 | * Constructor. |
387 | * @param offsetMillis the millis offset |
388 | */ |
389 | OffsetMillisProvider(long offsetMillis) { |
390 | iMillis = offsetMillis; |
391 | } |
392 | |
393 | /** |
394 | * Gets the current time. |
395 | * @return the current time in millis |
396 | */ |
397 | long getMillis() { |
398 | return System.currentTimeMillis() + iMillis; |
399 | } |
400 | } |
401 | |
402 | } |