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 }