Save This Page
Home » openjdk-7 » java » sql » [javadoc | source]
    1   /*
    2    * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.sql;
   27   
   28   import java.util.StringTokenizer;
   29   
   30   /**
   31    * <P>A thin wrapper around <code>java.util.Date</code> that allows
   32    * the JDBC API to identify this as an SQL <code>TIMESTAMP</code> value.
   33    * It adds the ability
   34    * to hold the SQL <code>TIMESTAMP</code> fractional seconds value, by allowing
   35    * the specification of fractional seconds to a precision of nanoseconds.
   36    * A Timestamp also provides formatting and
   37    * parsing operations to support the JDBC escape syntax for timestamp values.
   38    *
   39    * <p>The precision of a Timestamp object is calculated to be either:
   40    * <ul>
   41    * <li><code>19 </code>, which is the number of characters in yyyy-mm-dd hh:mm:ss
   42    * <li> <code> 20 + s </code>, which is the number
   43    * of characters in the yyyy-mm-dd hh:mm:ss.[fff...] and <code>s</code> represents  the scale of the given Timestamp,
   44    * its fractional seconds precision.
   45    *</ul>
   46    *
   47    * <P><B>Note:</B> This type is a composite of a <code>java.util.Date</code> and a
   48    * separate nanoseconds value. Only integral seconds are stored in the
   49    * <code>java.util.Date</code> component. The fractional seconds - the nanos - are
   50    * separate.  The <code>Timestamp.equals(Object)</code> method never returns
   51    * <code>true</code> when passed an object
   52    * that isn't an instance of <code>java.sql.Timestamp</code>,
   53    * because the nanos component of a date is unknown.
   54    * As a result, the <code>Timestamp.equals(Object)</code>
   55    * method is not symmetric with respect to the
   56    * <code>java.util.Date.equals(Object)</code>
   57    * method.  Also, the <code>hashCode</code> method uses the underlying
   58    * <code>java.util.Date</code>
   59    * implementation and therefore does not include nanos in its computation.
   60    * <P>
   61    * Due to the differences between the <code>Timestamp</code> class
   62    * and the <code>java.util.Date</code>
   63    * class mentioned above, it is recommended that code not view
   64    * <code>Timestamp</code> values generically as an instance of
   65    * <code>java.util.Date</code>.  The
   66    * inheritance relationship between <code>Timestamp</code>
   67    * and <code>java.util.Date</code> really
   68    * denotes implementation inheritance, and not type inheritance.
   69    */
   70   public class Timestamp extends java.util.Date {
   71   
   72       /**
   73        * Constructs a <code>Timestamp</code> object initialized
   74        * with the given values.
   75        *
   76        * @param year the year minus 1900
   77        * @param month 0 to 11
   78        * @param date 1 to 31
   79        * @param hour 0 to 23
   80        * @param minute 0 to 59
   81        * @param second 0 to 59
   82        * @param nano 0 to 999,999,999
   83        * @deprecated instead use the constructor <code>Timestamp(long millis)</code>
   84        * @exception IllegalArgumentException if the nano argument is out of bounds
   85        */
   86       @Deprecated
   87       public Timestamp(int year, int month, int date,
   88                        int hour, int minute, int second, int nano) {
   89           super(year, month, date, hour, minute, second);
   90           if (nano > 999999999 || nano < 0) {
   91               throw new IllegalArgumentException("nanos > 999999999 or < 0");
   92           }
   93           nanos = nano;
   94       }
   95   
   96       /**
   97        * Constructs a <code>Timestamp</code> object
   98        * using a milliseconds time value. The
   99        * integral seconds are stored in the underlying date value; the
  100        * fractional seconds are stored in the <code>nanos</code> field of
  101        * the <code>Timestamp</code> object.
  102        *
  103        * @param time milliseconds since January 1, 1970, 00:00:00 GMT.
  104        *        A negative number is the number of milliseconds before
  105        *         January 1, 1970, 00:00:00 GMT.
  106        * @see java.util.Calendar
  107        */
  108       public Timestamp(long time) {
  109           super((time/1000)*1000);
  110           nanos = (int)((time%1000) * 1000000);
  111           if (nanos < 0) {
  112               nanos = 1000000000 + nanos;
  113               super.setTime(((time/1000)-1)*1000);
  114           }
  115       }
  116   
  117       /**
  118        * Sets this <code>Timestamp</code> object to represent a point in time that is
  119        * <tt>time</tt> milliseconds after January 1, 1970 00:00:00 GMT.
  120        *
  121        * @param time   the number of milliseconds.
  122        * @see #getTime
  123        * @see #Timestamp(long time)
  124        * @see java.util.Calendar
  125        */
  126       public void setTime(long time) {
  127           super.setTime((time/1000)*1000);
  128           nanos = (int)((time%1000) * 1000000);
  129           if (nanos < 0) {
  130               nanos = 1000000000 + nanos;
  131               super.setTime(((time/1000)-1)*1000);
  132           }
  133       }
  134   
  135       /**
  136        * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
  137        * represented by this <code>Timestamp</code> object.
  138        *
  139        * @return  the number of milliseconds since January 1, 1970, 00:00:00 GMT
  140        *          represented by this date.
  141        * @see #setTime
  142        */
  143       public long getTime() {
  144           long time = super.getTime();
  145           return (time + (nanos / 1000000));
  146       }
  147   
  148   
  149       /**
  150        * @serial
  151        */
  152       private int nanos;
  153   
  154       /**
  155        * Converts a <code>String</code> object in JDBC timestamp escape format to a
  156        * <code>Timestamp</code> value.
  157        *
  158        * @param s timestamp in format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>.  The
  159        * fractional seconds may be omitted. The leading zero for <code>mm</code>
  160        * and <code>dd</code> may also be omitted.
  161        *
  162        * @return corresponding <code>Timestamp</code> value
  163        * @exception java.lang.IllegalArgumentException if the given argument
  164        * does not have the format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>
  165        */
  166       public static Timestamp valueOf(String s) {
  167           final int YEAR_LENGTH = 4;
  168           final int MONTH_LENGTH = 2;
  169           final int DAY_LENGTH = 2;
  170           final int MAX_MONTH = 12;
  171           final int MAX_DAY = 31;
  172           String date_s;
  173           String time_s;
  174           String nanos_s;
  175           int year = 0;
  176           int month = 0;
  177           int day = 0;
  178           int hour;
  179           int minute;
  180           int second;
  181           int a_nanos = 0;
  182           int firstDash;
  183           int secondDash;
  184           int dividingSpace;
  185           int firstColon = 0;
  186           int secondColon = 0;
  187           int period = 0;
  188           String formatError = "Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]";
  189           String zeros = "000000000";
  190           String delimiterDate = "-";
  191           String delimiterTime = ":";
  192   
  193           if (s == null) throw new java.lang.IllegalArgumentException("null string");
  194   
  195           // Split the string into date and time components
  196           s = s.trim();
  197           dividingSpace = s.indexOf(' ');
  198           if (dividingSpace > 0) {
  199               date_s = s.substring(0,dividingSpace);
  200               time_s = s.substring(dividingSpace+1);
  201           } else {
  202               throw new java.lang.IllegalArgumentException(formatError);
  203           }
  204   
  205           // Parse the date
  206           firstDash = date_s.indexOf('-');
  207           secondDash = date_s.indexOf('-', firstDash+1);
  208   
  209           // Parse the time
  210           if (time_s == null)
  211               throw new java.lang.IllegalArgumentException(formatError);
  212           firstColon = time_s.indexOf(':');
  213           secondColon = time_s.indexOf(':', firstColon+1);
  214           period = time_s.indexOf('.', secondColon+1);
  215   
  216           // Convert the date
  217           boolean parsedDate = false;
  218           if ((firstDash > 0) && (secondDash > 0) && (secondDash < date_s.length() - 1)) {
  219               String yyyy = date_s.substring(0, firstDash);
  220               String mm = date_s.substring(firstDash + 1, secondDash);
  221               String dd = date_s.substring(secondDash + 1);
  222               if (yyyy.length() == YEAR_LENGTH &&
  223                       (mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
  224                       (dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
  225                    year = Integer.parseInt(yyyy);
  226                    month = Integer.parseInt(mm);
  227                    day = Integer.parseInt(dd);
  228   
  229                   if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
  230                       parsedDate = true;
  231                   }
  232               }
  233           }
  234           if (! parsedDate) {
  235               throw new java.lang.IllegalArgumentException(formatError);
  236           }
  237   
  238           // Convert the time; default missing nanos
  239           if ((firstColon > 0) & (secondColon > 0) &
  240               (secondColon < time_s.length()-1)) {
  241               hour = Integer.parseInt(time_s.substring(0, firstColon));
  242               minute =
  243                   Integer.parseInt(time_s.substring(firstColon+1, secondColon));
  244               if ((period > 0) & (period < time_s.length()-1)) {
  245                   second =
  246                       Integer.parseInt(time_s.substring(secondColon+1, period));
  247                   nanos_s = time_s.substring(period+1);
  248                   if (nanos_s.length() > 9)
  249                       throw new java.lang.IllegalArgumentException(formatError);
  250                   if (!Character.isDigit(nanos_s.charAt(0)))
  251                       throw new java.lang.IllegalArgumentException(formatError);
  252                   nanos_s = nanos_s + zeros.substring(0,9-nanos_s.length());
  253                   a_nanos = Integer.parseInt(nanos_s);
  254               } else if (period > 0) {
  255                   throw new java.lang.IllegalArgumentException(formatError);
  256               } else {
  257                   second = Integer.parseInt(time_s.substring(secondColon+1));
  258               }
  259           } else {
  260               throw new java.lang.IllegalArgumentException(formatError);
  261           }
  262   
  263           return new Timestamp(year - 1900, month - 1, day, hour, minute, second, a_nanos);
  264       }
  265   
  266       /**
  267        * Formats a timestamp in JDBC timestamp escape format.
  268        *         <code>yyyy-mm-dd hh:mm:ss.fffffffff</code>,
  269        * where <code>ffffffffff</code> indicates nanoseconds.
  270        * <P>
  271        * @return a <code>String</code> object in
  272        *           <code>yyyy-mm-dd hh:mm:ss.fffffffff</code> format
  273        */
  274       public String toString () {
  275   
  276           int year = super.getYear() + 1900;
  277           int month = super.getMonth() + 1;
  278           int day = super.getDate();
  279           int hour = super.getHours();
  280           int minute = super.getMinutes();
  281           int second = super.getSeconds();
  282           String yearString;
  283           String monthString;
  284           String dayString;
  285           String hourString;
  286           String minuteString;
  287           String secondString;
  288           String nanosString;
  289           String zeros = "000000000";
  290           String yearZeros = "0000";
  291           StringBuffer timestampBuf;
  292   
  293           if (year < 1000) {
  294               // Add leading zeros
  295               yearString = "" + year;
  296               yearString = yearZeros.substring(0, (4-yearString.length())) +
  297                   yearString;
  298           } else {
  299               yearString = "" + year;
  300           }
  301           if (month < 10) {
  302               monthString = "0" + month;
  303           } else {
  304               monthString = Integer.toString(month);
  305           }
  306           if (day < 10) {
  307               dayString = "0" + day;
  308           } else {
  309               dayString = Integer.toString(day);
  310           }
  311           if (hour < 10) {
  312               hourString = "0" + hour;
  313           } else {
  314               hourString = Integer.toString(hour);
  315           }
  316           if (minute < 10) {
  317               minuteString = "0" + minute;
  318           } else {
  319               minuteString = Integer.toString(minute);
  320           }
  321           if (second < 10) {
  322               secondString = "0" + second;
  323           } else {
  324               secondString = Integer.toString(second);
  325           }
  326           if (nanos == 0) {
  327               nanosString = "0";
  328           } else {
  329               nanosString = Integer.toString(nanos);
  330   
  331               // Add leading zeros
  332               nanosString = zeros.substring(0, (9-nanosString.length())) +
  333                   nanosString;
  334   
  335               // Truncate trailing zeros
  336               char[] nanosChar = new char[nanosString.length()];
  337               nanosString.getChars(0, nanosString.length(), nanosChar, 0);
  338               int truncIndex = 8;
  339               while (nanosChar[truncIndex] == '0') {
  340                   truncIndex--;
  341               }
  342   
  343               nanosString = new String(nanosChar, 0, truncIndex + 1);
  344           }
  345   
  346           // do a string buffer here instead.
  347           timestampBuf = new StringBuffer(20+nanosString.length());
  348           timestampBuf.append(yearString);
  349           timestampBuf.append("-");
  350           timestampBuf.append(monthString);
  351           timestampBuf.append("-");
  352           timestampBuf.append(dayString);
  353           timestampBuf.append(" ");
  354           timestampBuf.append(hourString);
  355           timestampBuf.append(":");
  356           timestampBuf.append(minuteString);
  357           timestampBuf.append(":");
  358           timestampBuf.append(secondString);
  359           timestampBuf.append(".");
  360           timestampBuf.append(nanosString);
  361   
  362           return (timestampBuf.toString());
  363       }
  364   
  365       /**
  366        * Gets this <code>Timestamp</code> object's <code>nanos</code> value.
  367        *
  368        * @return this <code>Timestamp</code> object's fractional seconds component
  369        * @see #setNanos
  370        */
  371       public int getNanos() {
  372           return nanos;
  373       }
  374   
  375       /**
  376        * Sets this <code>Timestamp</code> object's <code>nanos</code> field
  377        * to the given value.
  378        *
  379        * @param n the new fractional seconds component
  380        * @exception java.lang.IllegalArgumentException if the given argument
  381        *            is greater than 999999999 or less than 0
  382        * @see #getNanos
  383        */
  384       public void setNanos(int n) {
  385           if (n > 999999999 || n < 0) {
  386               throw new IllegalArgumentException("nanos > 999999999 or < 0");
  387           }
  388           nanos = n;
  389       }
  390   
  391       /**
  392        * Tests to see if this <code>Timestamp</code> object is
  393        * equal to the given <code>Timestamp</code> object.
  394        *
  395        * @param ts the <code>Timestamp</code> value to compare with
  396        * @return <code>true</code> if the given <code>Timestamp</code>
  397        *         object is equal to this <code>Timestamp</code> object;
  398        *         <code>false</code> otherwise
  399        */
  400       public boolean equals(Timestamp ts) {
  401           if (super.equals(ts)) {
  402               if  (nanos == ts.nanos) {
  403                   return true;
  404               } else {
  405                   return false;
  406               }
  407           } else {
  408               return false;
  409           }
  410       }
  411   
  412       /**
  413        * Tests to see if this <code>Timestamp</code> object is
  414        * equal to the given object.
  415        *
  416        * This version of the method <code>equals</code> has been added
  417        * to fix the incorrect
  418        * signature of <code>Timestamp.equals(Timestamp)</code> and to preserve backward
  419        * compatibility with existing class files.
  420        *
  421        * Note: This method is not symmetric with respect to the
  422        * <code>equals(Object)</code> method in the base class.
  423        *
  424        * @param ts the <code>Object</code> value to compare with
  425        * @return <code>true</code> if the given <code>Object</code> is an instance
  426        *         of a <code>Timestamp</code> that
  427        *         is equal to this <code>Timestamp</code> object;
  428        *         <code>false</code> otherwise
  429        */
  430       public boolean equals(java.lang.Object ts) {
  431         if (ts instanceof Timestamp) {
  432           return this.equals((Timestamp)ts);
  433         } else {
  434           return false;
  435         }
  436       }
  437   
  438       /**
  439        * Indicates whether this <code>Timestamp</code> object is
  440        * earlier than the given <code>Timestamp</code> object.
  441        *
  442        * @param ts the <code>Timestamp</code> value to compare with
  443        * @return <code>true</code> if this <code>Timestamp</code> object is earlier;
  444        *        <code>false</code> otherwise
  445        */
  446       public boolean before(Timestamp ts) {
  447           return compareTo(ts) < 0;
  448       }
  449   
  450       /**
  451        * Indicates whether this <code>Timestamp</code> object is
  452        * later than the given <code>Timestamp</code> object.
  453        *
  454        * @param ts the <code>Timestamp</code> value to compare with
  455        * @return <code>true</code> if this <code>Timestamp</code> object is later;
  456        *        <code>false</code> otherwise
  457        */
  458       public boolean after(Timestamp ts) {
  459           return compareTo(ts) > 0;
  460       }
  461   
  462       /**
  463        * Compares this <code>Timestamp</code> object to the given
  464        * <code>Timestamp</code> object.
  465        *
  466        * @param   ts   the <code>Timestamp</code> object to be compared to
  467        *                this <code>Timestamp</code> object
  468        * @return  the value <code>0</code> if the two <code>Timestamp</code>
  469        *          objects are equal; a value less than <code>0</code> if this
  470        *          <code>Timestamp</code> object is before the given argument;
  471        *          and a value greater than <code>0</code> if this
  472        *          <code>Timestamp</code> object is after the given argument.
  473        * @since   1.4
  474        */
  475       public int compareTo(Timestamp ts) {
  476           long thisTime = this.getTime();
  477           long anotherTime = ts.getTime();
  478           int i = (thisTime<anotherTime ? -1 :(thisTime==anotherTime?0 :1));
  479           if (i == 0) {
  480               if (nanos > ts.nanos) {
  481                       return 1;
  482               } else if (nanos < ts.nanos) {
  483                   return -1;
  484               }
  485           }
  486           return i;
  487   
  488       }
  489   
  490       /**
  491        * Compares this <code>Timestamp</code> object to the given
  492        * <code>Date</code> object.
  493        *
  494        * @param o the <code>Date</code> to be compared to
  495        *          this <code>Timestamp</code> object
  496        * @return  the value <code>0</code> if this <code>Timestamp</code> object
  497        *          and the given object are equal; a value less than <code>0</code>
  498        *          if this  <code>Timestamp</code> object is before the given argument;
  499        *          and a value greater than <code>0</code> if this
  500        *          <code>Timestamp</code> object is after the given argument.
  501        *
  502        * @since   1.5
  503        */
  504       public int compareTo(java.util.Date o) {
  505          if(o instanceof Timestamp) {
  506               // When Timestamp instance compare it with a Timestamp
  507               // Hence it is basically calling this.compareTo((Timestamp))o);
  508               // Note typecasting is safe because o is instance of Timestamp
  509              return compareTo((Timestamp)o);
  510         } else {
  511               // When Date doing a o.compareTo(this)
  512               // will give wrong results.
  513             Timestamp ts = new Timestamp(o.getTime());
  514             return this.compareTo(ts);
  515         }
  516       }
  517   
  518       /**
  519        * {@inheritDoc}
  520        *
  521        * The {@code hashCode} method uses the underlying {@code java.util.Date}
  522        * implementation and therefore does not include nanos in its computation.
  523        *
  524        */
  525       @Override
  526       public int hashCode() {
  527           return super.hashCode();
  528       }
  529   
  530       static final long serialVersionUID = 2745179027874758501L;
  531   
  532   }

Save This Page
Home » openjdk-7 » java » sql » [javadoc | source]