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 }