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