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 }