001    /* Time.java -- Wrapper around java.util.Date
002       Copyright (C) 1999, 2000, 2003, 2004, 2005  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.sql;
040    
041    import java.text.DecimalFormat;
042    import java.text.ParseException;
043    import java.text.SimpleDateFormat;
044    
045    /**
046     * This class is a wrapper around java.util.Date to allow the JDBC
047     * driver to identify the value as a SQL Timestamp.  Note that this
048     * class also adds an additional field for nano-seconds, and so
049     * is not completely identical to <code>java.util.Date</code> as
050     * the <code>java.sql.Date</code> and <code>java.sql.Time</code>
051     * classes are.
052     *
053     * @author Aaron M. Renn (arenn@urbanophile.com)
054     */
055    public class Timestamp extends java.util.Date
056    {
057      static final long serialVersionUID = 2745179027874758501L;
058    
059      /**
060       * Used for parsing and formatting this date.
061       */
062      private static SimpleDateFormat dateFormat =
063        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
064      private static DecimalFormat decimalFormat = new DecimalFormat("000000000");
065      private static StringBuffer sbuf = new StringBuffer(29);
066    
067      /**
068        * The nanosecond value for this object
069        */
070      private int nanos;
071    
072      /**
073       * This method returns a new instance of this class by parsing a
074       * date in JDBC format into a Java date.
075       *
076       * @param str The string to parse.
077       * @return The resulting <code>java.sql.Timestamp</code> value.
078       */
079      public static Timestamp valueOf(String str)
080      {
081        int nanos = 0;
082        int dot = str.indexOf('.');
083        if (dot != -1)
084          {
085            if (str.lastIndexOf('.') != dot)
086              throw new IllegalArgumentException(str);
087    
088            int len = str.length() - dot - 1;
089            if (len < 1 || len > 9)
090              throw new IllegalArgumentException(str);
091    
092            nanos = Integer.parseInt(str.substring(dot + 1));
093            for (int i = len; i < 9; i++)
094              nanos *= 10;
095    
096            str = str.substring(0, dot);
097    
098          }
099    
100        try
101          {
102            java.util.Date d;
103            synchronized (dateFormat)
104              {
105                d = (java.util.Date) dateFormat.parseObject(str);
106              }
107    
108            if (d == null)
109              throw new IllegalArgumentException(str);
110    
111            Timestamp ts = new Timestamp(d.getTime() + nanos / 1000000);
112            ts.nanos = nanos;
113            return ts;
114          }
115        catch (ParseException e)
116          {
117            throw new IllegalArgumentException(str);
118          }
119      }
120    
121      /**
122       * This method initializes a new instance of this class with the
123       * specified year, month, and day.
124       *
125       * @param year The year for this Timestamp (year - 1900)
126       * @param month The month for this Timestamp (0-11)
127       * @param day The day for this Timestamp (1-31)
128       * @param hour The hour for this Timestamp (0-23)
129       * @param minute The minute for this Timestamp (0-59)
130       * @param second The second for this Timestamp (0-59)
131       * @param nanos The nanosecond value for this Timestamp (0 to 999,999,9999)
132       * @deprecated
133       */
134      public Timestamp(int year, int month, int day, int hour, int minute,
135        int second, int nanos)
136      {
137        super(year, month, day, hour, minute, second);
138        this.nanos = nanos;
139      }
140    
141      /**
142       * This method initializes a new instance of this class with the
143       * specified time value representing the number of milliseconds since
144       * Jan 1, 1970 at 12:00 midnight GMT.
145       *
146       * @param date The time value to intialize this <code>Time</code> to.
147       */
148      public Timestamp(long date)
149      {
150        super(date - (date % 1000));
151        nanos = (int) (date % 1000) * 1000000;
152      }
153    
154      /**
155       * Return the value of this Timestamp as the number of milliseconds
156       * since Jan 1, 1970 at 12:00 midnight GMT.
157       */
158      public long getTime()
159      {
160        return super.getTime() + (nanos / 1000000);
161      }
162    
163      /**
164       * This method returns this date in JDBC format.
165       *
166       * @return This date as a string.
167       */
168      public String toString()
169      {
170        synchronized (dateFormat)
171          {
172            sbuf.setLength(0);
173            dateFormat.format(this, sbuf, null);
174            sbuf.append('.');
175            decimalFormat.format(nanos, sbuf, null);
176            int end = sbuf.length() - 1;
177            while (end > 20 && sbuf.charAt(end) == '0')
178              end--;
179            return sbuf.substring(0, end + 1);
180          }
181      }
182    
183      /**
184        * This method returns the nanosecond value for this object.
185        * @return The nanosecond value for this object.
186        */
187      public int getNanos()
188      {
189        return nanos;
190      }
191    
192      /**
193       * This method sets the nanosecond value for this object.
194       *
195       * @param nanos The nanosecond value for this object.
196       */
197      public void setNanos(int nanos)
198      {
199        this.nanos = nanos;
200      }
201    
202      /**
203       * This methods tests whether this object is earlier than the specified
204       * object.
205       *
206       * @param ts The other <code>Timestamp</code> to test against.
207       * @return <code>true</code> if this object is earlier than the other object,
208       *         <code>false</code> otherwise.
209       */
210      public boolean before(Timestamp ts)
211      {
212        long time1 = getTime();
213        long time2 = ts.getTime();
214        if (time1 < time2 || (time1 == time2 && getNanos() < ts.getNanos()))
215          return true;
216        return false;
217      }
218    
219      /**
220       * This methods tests whether this object is later than the specified
221       * object.
222       *
223       * @param ts The other <code>Timestamp</code> to test against.
224       *
225       * @return <code>true</code> if this object is later than the other object,
226       * <code>false</code> otherwise.
227       */
228      public boolean after(Timestamp ts)
229      {
230        long time1 = getTime();
231        long time2 = ts.getTime();
232        if (time1 > time2 || (time1 == time2 && getNanos() > ts.getNanos()))
233          return true;
234        return false;
235      }
236    
237      /**
238       * This method these the specified <code>Object</code> for equality
239       * against this object.  This will be true if an only if the specified
240       * object is an instance of <code>Timestamp</code> and has the same
241       * time value fields.
242       *
243       * @param obj The object to test against for equality.
244       *
245       * @return <code>true</code> if the specified object is equal to this
246       * object, <code>false</code> otherwise.
247       */
248      public boolean equals(Object obj)
249      {
250        if (!(obj instanceof Timestamp))
251          return false;
252    
253        return equals((Timestamp) obj);
254      }
255    
256      /**
257       * This method tests the specified timestamp for equality against this
258       * object.  This will be true if and only if the specified object is
259       * not <code>null</code> and contains all the same time value fields
260       * as this object.
261       *
262       * @param ts The <code>Timestamp</code> to test against for equality.
263       *
264       * @return <code>true</code> if the specified object is equal to this
265       * object, <code>false</code> otherwise.
266       */
267      public boolean equals(Timestamp ts)
268      {
269        if (ts == null)
270          return false;
271    
272        if (ts.getTime() != getTime())
273          return false;
274    
275        if (ts.getNanos() != getNanos())
276          return false;
277    
278        return true;
279      }
280    
281      /**
282       * Compares this <code>Timestamp</code> to another one.
283       *
284       * @param ts The other Timestamp.
285       * @return <code>0</code>, if both <code>Timestamp</code>'s represent exactly
286       *         the same date, a negative value if this <code>Timestamp</code> is
287       *         before the specified <code>Timestamp</code> and a positive value
288       *         otherwise.
289       * @since 1.2
290       */
291      public int compareTo(Timestamp ts)
292      {
293        int s = super.compareTo((java.util.Date) ts);
294        if (s != 0)
295          return s;
296        // If Date components were equal, then we check the nanoseconds.
297        return nanos - ts.nanos;
298      }
299    
300      /**
301       * Compares this <code>Timestamp</code> to another one. This behaves like
302       * <code>compareTo(Timestamp)</code>, but it may throw a
303       * <code>ClassCastException</code>, if the specified object is not of type
304       * <code>Timestamp</code>.
305       *
306       * @param obj The object to compare with.
307       * @return <code>0</code>, if both <code>Timestamp</code>'s represent exactly
308       *         the same date, a negative value if this <code>Timestamp</code> is
309       *         before the specified <code>Timestamp</code> and a positive value
310       *         otherwise.
311       * @exception ClassCastException if obj is not of type Timestamp.
312       * @see #compareTo(Timestamp)
313       * @since 1.2
314       */
315      public int compareTo(java.util.Date obj)
316      {
317        return compareTo((Timestamp) obj);
318      }
319    }