001 /*
002 * Copyleft notice: This is public-domain software and documentation
003 * with no restrictions of any kind.
004 * Please feel free to use any of it in any way you want.
005 * This work is distributed in the hope that it will be useful,
006 * but WITHOUT ANY WARRANTY; without even the implied warranty of
007 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
008 */
009
010 package time;
011
012 import java.util.*;
013
014
015
016 /**
017 * <tt>Instant</tt> is the implementation of a fully immutable instant in time.
018 * An instant in time represents an event that have theorically no duration.
019 *
020 * <p>
021 * An Instant represents a point in the universal line of time, which is supposed to be the
022 * same everywhere in the whole Universe. (This is a Newtonian vision of the Time which
023 * is known as approximated since Einstein's Theory of Relativity, which shows
024 * that space and time are linked, but this approximation
025 * is fine for us).
026 *
027 * <p>
028 * Here some examples of famous instants:
029 *
030 * <ul>
031 * <li> the <a href=http://en.wikipedia.org/wiki/Spartacus>revolt of Spartacus</a>,
032 * <li> the <a href=http://www.seds.org/messier/more/m001_sn.html>supernovae of the Crab Nebula</a>,
033 * observed by Chinese astronomers almost 1000 years ago,
034 * <li> the birth of Beethoven,
035 * <li> the first man on Moon.
036 * </ul>
037 *
038 * Instant are conceptualy independant from Human representations of Time (calendar...). They
039 * simply exists by themself.
040 *
041 * <p>
042 * To ensure compatibility with existing classes in Java, <tt>Instant</tt> are implemented
043 * as milliseconds since the Java Epoch of 1970-01-01 00:00:00 GMT, <u>but please note that
044 * this is only an implementation detail</u>. The current implementation is then milliseconds
045 * accurate, but future implementation may offer finer accuracy (nanoseconds).
046 *
047 * <p>
048 * Instants are <tt>Comparable</tt>, and their natural order is the chronological order.
049 *
050 * <p>
051 * Two Instants are equals if they represent the same instant in time (they occur at
052 * exactly the same moment).
053 *
054 * <p>
055 * As <tt>Instant</tt> are immutable, they are fully thread-safe.
056 *
057 * <p>
058 * <p>
059 * <dt><b>Note:</b></dt>
060 * <dd>
061 * Technically, an <tt>Instant</tt> looks like a immutable <tt>java.util.Date</tt>.
062 * But you should
063 * be aware that conceptually, they are very different, since a <tt>java.util.Date</tt> is
064 * supposed to be a <u>date</u>.
065 * </dd>
066 *
067 *
068 * @author Arnaud Roques
069 *
070 * @stereotype "Comparable"
071 *
072 */
073 public final class Instant implements Comparable<Instant>
074 {
075 /**
076 * The famous Epoch. (1970-01-01 00:00:00)
077 */
078 public static final Instant EPOCH = new Instant(0L);
079
080 /**
081 * The minimum value of an Instant, about 292 millions of years before the Epoch.
082 * We cannot have instant before this BIG_BANG.
083 * (This is not the <i>real</i> astrophysical BigBang, which have occured between
084 * 10 and 20 billions of years before the Epoch).
085 */
086 public static final Instant BIG_BANG = new Instant(Long.MIN_VALUE);
087
088 /**
089 * The maximum value of an Instant, which will happen about 292 millions of
090 * years after the Epoch.
091 * This is not the <i>real</i> Apocalypse.
092 */
093 public static final Instant APOCALYPSE = new Instant(Long.MAX_VALUE);
094
095 /**
096 * Number of milliseconds since the Epoch
097 */
098 private final long millis;
099
100 /**
101 * Create a new <tt>Instant</tt>, which represents the current time (now).
102 */
103 public Instant()
104 {
105 this(System.currentTimeMillis());
106 }
107
108 /**
109 * Create a new <tt>Instant</tt>.
110 * This constructor is provided for compatibility with existing code.
111 *
112 * @param millis number of milliseconds since the Epoch of the Instant to create
113 */
114 public Instant(long millis)
115 {
116 this.millis = millis;
117 }
118
119 /**
120 * Create a new <tt>Instant</tt>.
121 * This constructor is provided for compatibility with existing <tt>java.util.Date</tt>.
122 *
123 * @param date Date of the Instant to create.
124 *
125 * @throws NullPointerException if <tt>date</tt> is null.
126 */
127 public Instant(Date date)
128 {
129 this(date.getTime());
130 }
131
132
133 /**
134 * Compare two instants chronogically.
135 *
136 * @param otherInstant the instant to be compared.
137 *
138 * @return the value 0 if the argument instant is equal to this instant;
139 * a value less than 0 if this instant occurs before the instant argument;
140 * and a value greater than 0 if this instant occurs after than the instant argument.
141 *
142 * @throws NullPointerException if <tt>otherInstant</tt> is <tt>null</tt>.
143 */
144 public int compareTo(Instant otherInstant)
145 {
146 if (otherInstant.millis > millis) return 1;
147 if (otherInstant.millis < millis) return -1;
148 assert(equals(otherInstant));
149 return 0;
150 }
151
152
153 /**
154 * Compute the number of milliseconds between this instant and another instant.
155 *
156 * <p>If this instant occurs after the other instant, the result is positive.
157 * If this instant occurs before the other instant, the result is negative.
158 *
159 * @return the number of milliseconds between this instant and another instant.
160 *
161 * @throws NullPointerException if <tt>otherInstant</tt> is <tt>null</tt>.
162 */
163 public long millisBetween(Instant otherInstant)
164 {
165 return getMillis()-otherInstant.getMillis();
166 }
167
168 /**
169 * Compare two instants for equality.
170 * The result is <tt>true</tt> if and only if the argument is not
171 * <tt>null</tt> and is a <tt>Instant</tt> object that represents
172 * the same point in time, (with a millisecond accuracy in this implementation)
173 * , than this object.
174 *
175 * @param obj the object to compare with.
176 * @return <tt>true</tt> if the objects are the same; <tt>false</tt> otherwise.
177 * @hidden
178 */
179 @Override
180 public boolean equals(Object obj)
181 {
182 if (obj==null) return false;
183 if (obj.getClass().equals(getClass())==false) return false;
184 Instant i2 = (Instant) obj;
185 return millis==i2.millis;
186 }
187
188 /**
189 * Returns a hash code value for this object.
190 * @hidden
191 */
192 @Override
193 public int hashCode()
194 {
195 return (int)(this.getMillis()^(this.getMillis() >>> 32));
196 }
197
198 final class ImmutableDate extends Date
199 {
200 ImmutableDate(long millis)
201 {
202 super(millis);
203 }
204
205 @Override public void setTime(long l) { throw new UnsupportedOperationException(); }
206 @Override public void setDate(int i) { throw new UnsupportedOperationException(); }
207 @Override public void setHours(int i) { throw new UnsupportedOperationException(); }
208 @Override public void setMinutes(int i) { throw new UnsupportedOperationException(); }
209 @Override public void setMonth(int i) { throw new UnsupportedOperationException(); }
210 @Override public void setSeconds(int i) { throw new UnsupportedOperationException(); }
211 @Override public void setYear(int i) { throw new UnsupportedOperationException(); }
212 }
213
214
215 /**
216 * Return a <tt>java.util.Date</tt> view of this Instant.
217 *
218 * <p>
219 * The returned date is immutable, as the returned class is a subclass of
220 * <tt>java.util.Date</tt> which all mutating methods
221 * have been overidden to throw a <tt>UnsupportedOperationException</tt>.
222 *
223 * @return the immutable date representing the same instant as this object.
224 */
225 public Date asImmutableDate()
226 {
227 return new ImmutableDate(millis);
228 }
229
230
231 /**
232 * Returns the number of milliseconds since the Epoch represented by this Instant object.
233 *
234 * @return the number of milliseconds since the Epoch represented by this Instant object.
235 */
236 public long getMillis()
237 {
238 return millis;
239 }
240
241 /**
242 * Returns <tt>0L</tt> in this current implementation..
243 *
244 * @return 0L.
245 */
246 public long getNanos()
247 {
248 return 0L;
249 }
250
251
252 /**
253 * Convert this <tt>Instant</tt> to a <tt>String</tt>.
254 *
255 * @return a string representation of this instant
256 * @hidden
257 */
258 @Override
259 public String toString()
260 {
261 return asImmutableDate().toString()+" "+(millis%1000L);
262 }
263 }
264
265