001/* Time.java -- Wrapper around java.util.Date
002   Copyright (C) 1999, 2000, 2003, 2004, 2005  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.sql;
040
041import java.text.DecimalFormat;
042import java.text.ParseException;
043import 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 */
055public 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}