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