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.io.Serializable; 019 020 import org.joda.convert.FromString; 021 import org.joda.time.base.AbstractInstant; 022 import org.joda.time.chrono.ISOChronology; 023 import org.joda.time.convert.ConverterManager; 024 import org.joda.time.convert.InstantConverter; 025 import org.joda.time.format.DateTimeFormatter; 026 import org.joda.time.format.ISODateTimeFormat; 027 028 /** 029 * Instant is the standard implementation of a fully immutable instant in time. 030 * <p> 031 * <code>Instant</code> is an implementation of {@link ReadableInstant}. 032 * As with all instants, it represents an exact point on the time-line, 033 * but limited to the precision of milliseconds. An <code>Instant</code> 034 * should be used to represent a point in time irrespective of any other 035 * factor, such as chronology or time zone. 036 * <p> 037 * Internally, the class holds one piece of data, the instant as milliseconds 038 * from the Java epoch of 1970-01-01T00:00:00Z. 039 * <p> 040 * For example, an Instant can be used to compare two <code>DateTime</code> 041 * objects irrespective of chronology or time zone. 042 * <pre> 043 * boolean sameInstant = dt1.toInstant().equals(dt2.toInstant()); 044 * </pre> 045 * Note that the following code will also perform the same check: 046 * <pre> 047 * boolean sameInstant = dt1.isEqual(dt2); 048 * </pre> 049 * <p> 050 * Instant is thread-safe and immutable. 051 * 052 * @author Stephen Colebourne 053 * @since 1.0 054 */ 055 public final class Instant 056 extends AbstractInstant 057 implements ReadableInstant, Serializable { 058 059 /** Serialization lock */ 060 private static final long serialVersionUID = 3299096530934209741L; 061 062 /** The millis from 1970-01-01T00:00:00Z */ 063 private final long iMillis; 064 065 //----------------------------------------------------------------------- 066 /** 067 * Obtains an {@code Instant} set to the current system millisecond time. 068 * 069 * @return the current instant, not null 070 * @since 2.0 071 */ 072 public static Instant now() { 073 return new Instant(); 074 } 075 076 //----------------------------------------------------------------------- 077 /** 078 * Parses a {@code Instant} from the specified string. 079 * <p> 080 * This uses {@link ISODateTimeFormat#dateTimeParser()}. 081 * 082 * @param str the string to parse, not null 083 * @since 2.0 084 */ 085 @FromString 086 public static Instant parse(String str) { 087 return parse(str, ISODateTimeFormat.dateTimeParser()); 088 } 089 090 /** 091 * Parses a {@code Instant} from the specified string using a formatter. 092 * 093 * @param str the string to parse, not null 094 * @param formatter the formatter to use, not null 095 * @since 2.0 096 */ 097 public static Instant parse(String str, DateTimeFormatter formatter) { 098 return formatter.parseDateTime(str).toInstant(); 099 } 100 101 //----------------------------------------------------------------------- 102 /** 103 * Constructs an instance set to the current system millisecond time. 104 * 105 * @see #now() 106 */ 107 public Instant() { 108 super(); 109 iMillis = DateTimeUtils.currentTimeMillis(); 110 } 111 112 /** 113 * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z. 114 * 115 * @param instant the milliseconds from 1970-01-01T00:00:00Z 116 */ 117 public Instant(long instant) { 118 super(); 119 iMillis = instant; 120 } 121 122 /** 123 * Constructs an instance from an Object that represents a datetime. 124 * <p> 125 * The recognised object types are defined in {@link ConverterManager} and 126 * include String, Calendar and Date. 127 * 128 * @param instant the datetime object, null means now 129 * @throws IllegalArgumentException if the instant is invalid 130 */ 131 public Instant(Object instant) { 132 super(); 133 InstantConverter converter = ConverterManager.getInstance().getInstantConverter(instant); 134 iMillis = converter.getInstantMillis(instant, ISOChronology.getInstanceUTC()); 135 } 136 137 //----------------------------------------------------------------------- 138 /** 139 * Get this object as an Instant by returning <code>this</code>. 140 * 141 * @return <code>this</code> 142 */ 143 public Instant toInstant() { 144 return this; 145 } 146 147 //----------------------------------------------------------------------- 148 /** 149 * Gets a copy of this instant with different millis. 150 * <p> 151 * The returned object will be either be a new Instant or <code>this</code>. 152 * 153 * @param newMillis the new millis, from 1970-01-01T00:00:00Z 154 * @return a copy of this instant with different millis 155 */ 156 public Instant withMillis(long newMillis) { 157 return (newMillis == iMillis ? this : new Instant(newMillis)); 158 } 159 160 /** 161 * Gets a copy of this instant with the specified duration added. 162 * <p> 163 * If the addition is zero, then <code>this</code> is returned. 164 * 165 * @param durationToAdd the duration to add to this one 166 * @param scalar the amount of times to add, such as -1 to subtract once 167 * @return a copy of this instant with the duration added 168 * @throws ArithmeticException if the new instant exceeds the capacity of a long 169 */ 170 public Instant withDurationAdded(long durationToAdd, int scalar) { 171 if (durationToAdd == 0 || scalar == 0) { 172 return this; 173 } 174 long instant = getChronology().add(getMillis(), durationToAdd, scalar); 175 return withMillis(instant); 176 } 177 178 /** 179 * Gets a copy of this instant with the specified duration added. 180 * <p> 181 * If the addition is zero, then <code>this</code> is returned. 182 * 183 * @param durationToAdd the duration to add to this one, null means zero 184 * @param scalar the amount of times to add, such as -1 to subtract once 185 * @return a copy of this instant with the duration added 186 * @throws ArithmeticException if the new instant exceeds the capacity of a long 187 */ 188 public Instant withDurationAdded(ReadableDuration durationToAdd, int scalar) { 189 if (durationToAdd == null || scalar == 0) { 190 return this; 191 } 192 return withDurationAdded(durationToAdd.getMillis(), scalar); 193 } 194 195 //----------------------------------------------------------------------- 196 /** 197 * Gets a copy of this instant with the specified duration added. 198 * <p> 199 * If the amount is zero or null, then <code>this</code> is returned. 200 * 201 * @param duration the duration to add to this one 202 * @return a copy of this instant with the duration added 203 * @throws ArithmeticException if the new instant exceeds the capacity of a long 204 */ 205 public Instant plus(long duration) { 206 return withDurationAdded(duration, 1); 207 } 208 209 /** 210 * Gets a copy of this instant with the specified duration added. 211 * <p> 212 * If the amount is zero or null, then <code>this</code> is returned. 213 * 214 * @param duration the duration to add to this one, null means zero 215 * @return a copy of this instant with the duration added 216 * @throws ArithmeticException if the new instant exceeds the capacity of a long 217 */ 218 public Instant plus(ReadableDuration duration) { 219 return withDurationAdded(duration, 1); 220 } 221 222 //----------------------------------------------------------------------- 223 /** 224 * Gets a copy of this instant with the specified duration taken away. 225 * <p> 226 * If the amount is zero or null, then <code>this</code> is returned. 227 * 228 * @param duration the duration to reduce this instant by 229 * @return a copy of this instant with the duration taken away 230 * @throws ArithmeticException if the new instant exceeds the capacity of a long 231 */ 232 public Instant minus(long duration) { 233 return withDurationAdded(duration, -1); 234 } 235 236 /** 237 * Gets a copy of this instant with the specified duration taken away. 238 * <p> 239 * If the amount is zero or null, then <code>this</code> is returned. 240 * 241 * @param duration the duration to reduce this instant by 242 * @return a copy of this instant with the duration taken away 243 * @throws ArithmeticException if the new instant exceeds the capacity of a long 244 */ 245 public Instant minus(ReadableDuration duration) { 246 return withDurationAdded(duration, -1); 247 } 248 249 //----------------------------------------------------------------------- 250 /** 251 * Gets the milliseconds of the instant. 252 * 253 * @return the number of milliseconds since 1970-01-01T00:00:00Z 254 */ 255 public long getMillis() { 256 return iMillis; 257 } 258 259 /** 260 * Gets the chronology of the instant, which is ISO in the UTC zone. 261 * <p> 262 * This method returns {@link ISOChronology#getInstanceUTC()} which 263 * corresponds to the definition of the Java epoch 1970-01-01T00:00:00Z. 264 * 265 * @return ISO in the UTC zone 266 */ 267 public Chronology getChronology() { 268 return ISOChronology.getInstanceUTC(); 269 } 270 271 //----------------------------------------------------------------------- 272 /** 273 * Get this object as a DateTime using ISOChronology in the default zone. 274 * <p> 275 * This method returns a DateTime object in the default zone. 276 * This differs from the similarly named method on DateTime, DateMidnight 277 * or MutableDateTime which retains the time zone. The difference is 278 * because Instant really represents a time <i>without</i> a zone, 279 * thus calling this method we really have no zone to 'retain' and 280 * hence expect to switch to the default zone. 281 * <p> 282 * This method definition preserves compatibility with earlier versions 283 * of Joda-Time. 284 * 285 * @return a DateTime using the same millis 286 */ 287 public DateTime toDateTime() { 288 return new DateTime(getMillis(), ISOChronology.getInstance()); 289 } 290 291 /** 292 * Get this object as a DateTime using ISOChronology in the default zone. 293 * This method is identical to <code>toDateTime()</code>. 294 * <p> 295 * This method returns a DateTime object in the default zone. 296 * This differs from the similarly named method on DateTime, DateMidnight 297 * or MutableDateTime which retains the time zone. The difference is 298 * because Instant really represents a time <i>without</i> a zone, 299 * thus calling this method we really have no zone to 'retain' and 300 * hence expect to switch to the default zone. 301 * <p> 302 * This method is deprecated because it is a duplicate of {@link #toDateTime()}. 303 * However, removing it would cause the superclass implementation to be used, 304 * which would create silent bugs in any caller depending on this implementation. 305 * As such, the method itself is not currently planned to be removed. 306 * <p> 307 * This method definition preserves compatibility with earlier versions 308 * of Joda-Time. 309 * 310 * @return a DateTime using the same millis with ISOChronology 311 * @deprecated Use toDateTime() as it is identical 312 */ 313 @Deprecated 314 public DateTime toDateTimeISO() { 315 return toDateTime(); 316 } 317 318 /** 319 * Get this object as a MutableDateTime using ISOChronology in the default zone. 320 * <p> 321 * This method returns a MutableDateTime object in the default zone. 322 * This differs from the similarly named method on DateTime, DateMidnight 323 * or MutableDateTime which retains the time zone. The difference is 324 * because Instant really represents a time <i>without</i> a zone, 325 * thus calling this method we really have no zone to 'retain' and 326 * hence expect to switch to the default zone. 327 * <p> 328 * This method definition preserves compatibility with earlier versions 329 * of Joda-Time. 330 * 331 * @return a MutableDateTime using the same millis 332 */ 333 public MutableDateTime toMutableDateTime() { 334 return new MutableDateTime(getMillis(), ISOChronology.getInstance()); 335 } 336 337 /** 338 * Get this object as a MutableDateTime using ISOChronology in the default zone. 339 * This method is identical to <code>toMutableDateTime()</code>. 340 * <p> 341 * This method returns a MutableDateTime object in the default zone. 342 * This differs from the similarly named method on DateTime, DateMidnight 343 * or MutableDateTime which retains the time zone. The difference is 344 * because Instant really represents a time <i>without</i> a zone, 345 * thus calling this method we really have no zone to 'retain' and 346 * hence expect to switch to the default zone. 347 * <p> 348 * This method is deprecated because it is a duplicate of {@link #toMutableDateTime()}. 349 * However, removing it would cause the superclass implementation to be used, 350 * which would create silent bugs in any caller depending on this implementation. 351 * As such, the method itself is not currently planned to be removed. 352 * <p> 353 * This method definition preserves compatibility with earlier versions 354 * of Joda-Time. 355 * 356 * @return a MutableDateTime using the same millis with ISOChronology 357 * @deprecated Use toMutableDateTime() as it is identical 358 */ 359 @Deprecated 360 public MutableDateTime toMutableDateTimeISO() { 361 return toMutableDateTime(); 362 } 363 364 }