Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/sql/Timestamp.java
38829 views
/*1* Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.sql;2627import java.time.Instant;28import java.time.LocalDateTime;29import java.util.StringTokenizer;3031/**32* <P>A thin wrapper around <code>java.util.Date</code> that allows33* the JDBC API to identify this as an SQL <code>TIMESTAMP</code> value.34* It adds the ability35* to hold the SQL <code>TIMESTAMP</code> fractional seconds value, by allowing36* the specification of fractional seconds to a precision of nanoseconds.37* A Timestamp also provides formatting and38* parsing operations to support the JDBC escape syntax for timestamp values.39*40* <p>The precision of a Timestamp object is calculated to be either:41* <ul>42* <li><code>19 </code>, which is the number of characters in yyyy-mm-dd hh:mm:ss43* <li> <code> 20 + s </code>, which is the number44* of characters in the yyyy-mm-dd hh:mm:ss.[fff...] and <code>s</code> represents the scale of the given Timestamp,45* its fractional seconds precision.46*</ul>47*48* <P><B>Note:</B> This type is a composite of a <code>java.util.Date</code> and a49* separate nanoseconds value. Only integral seconds are stored in the50* <code>java.util.Date</code> component. The fractional seconds - the nanos - are51* separate. The <code>Timestamp.equals(Object)</code> method never returns52* <code>true</code> when passed an object53* that isn't an instance of <code>java.sql.Timestamp</code>,54* because the nanos component of a date is unknown.55* As a result, the <code>Timestamp.equals(Object)</code>56* method is not symmetric with respect to the57* <code>java.util.Date.equals(Object)</code>58* method. Also, the <code>hashCode</code> method uses the underlying59* <code>java.util.Date</code>60* implementation and therefore does not include nanos in its computation.61* <P>62* Due to the differences between the <code>Timestamp</code> class63* and the <code>java.util.Date</code>64* class mentioned above, it is recommended that code not view65* <code>Timestamp</code> values generically as an instance of66* <code>java.util.Date</code>. The67* inheritance relationship between <code>Timestamp</code>68* and <code>java.util.Date</code> really69* denotes implementation inheritance, and not type inheritance.70*/71public class Timestamp extends java.util.Date {7273/**74* Constructs a <code>Timestamp</code> object initialized75* with the given values.76*77* @param year the year minus 190078* @param month 0 to 1179* @param date 1 to 3180* @param hour 0 to 2381* @param minute 0 to 5982* @param second 0 to 5983* @param nano 0 to 999,999,99984* @deprecated instead use the constructor <code>Timestamp(long millis)</code>85* @exception IllegalArgumentException if the nano argument is out of bounds86*/87@Deprecated88public Timestamp(int year, int month, int date,89int hour, int minute, int second, int nano) {90super(year, month, date, hour, minute, second);91if (nano > 999999999 || nano < 0) {92throw new IllegalArgumentException("nanos > 999999999 or < 0");93}94nanos = nano;95}9697/**98* Constructs a <code>Timestamp</code> object99* using a milliseconds time value. The100* integral seconds are stored in the underlying date value; the101* fractional seconds are stored in the <code>nanos</code> field of102* the <code>Timestamp</code> object.103*104* @param time milliseconds since January 1, 1970, 00:00:00 GMT.105* A negative number is the number of milliseconds before106* January 1, 1970, 00:00:00 GMT.107* @see java.util.Calendar108*/109public Timestamp(long time) {110super((time/1000)*1000);111nanos = (int)((time%1000) * 1000000);112if (nanos < 0) {113nanos = 1000000000 + nanos;114super.setTime(((time/1000)-1)*1000);115}116}117118/**119* Sets this <code>Timestamp</code> object to represent a point in time that is120* <tt>time</tt> milliseconds after January 1, 1970 00:00:00 GMT.121*122* @param time the number of milliseconds.123* @see #getTime124* @see #Timestamp(long time)125* @see java.util.Calendar126*/127public void setTime(long time) {128super.setTime((time/1000)*1000);129nanos = (int)((time%1000) * 1000000);130if (nanos < 0) {131nanos = 1000000000 + nanos;132super.setTime(((time/1000)-1)*1000);133}134}135136/**137* Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT138* represented by this <code>Timestamp</code> object.139*140* @return the number of milliseconds since January 1, 1970, 00:00:00 GMT141* represented by this date.142* @see #setTime143*/144public long getTime() {145long time = super.getTime();146return (time + (nanos / 1000000));147}148149150/**151* @serial152*/153private int nanos;154155/**156* Converts a <code>String</code> object in JDBC timestamp escape format to a157* <code>Timestamp</code> value.158*159* @param s timestamp in format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>. The160* fractional seconds may be omitted. The leading zero for <code>mm</code>161* and <code>dd</code> may also be omitted.162*163* @return corresponding <code>Timestamp</code> value164* @exception java.lang.IllegalArgumentException if the given argument165* does not have the format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>166*/167public static Timestamp valueOf(String s) {168final int YEAR_LENGTH = 4;169final int MONTH_LENGTH = 2;170final int DAY_LENGTH = 2;171final int MAX_MONTH = 12;172final int MAX_DAY = 31;173String date_s;174String time_s;175String nanos_s;176int year = 0;177int month = 0;178int day = 0;179int hour;180int minute;181int second;182int a_nanos = 0;183int firstDash;184int secondDash;185int dividingSpace;186int firstColon = 0;187int secondColon = 0;188int period = 0;189String formatError = "Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]";190String zeros = "000000000";191String delimiterDate = "-";192String delimiterTime = ":";193194if (s == null) throw new java.lang.IllegalArgumentException("null string");195196// Split the string into date and time components197s = s.trim();198dividingSpace = s.indexOf(' ');199if (dividingSpace > 0) {200date_s = s.substring(0,dividingSpace);201time_s = s.substring(dividingSpace+1);202} else {203throw new java.lang.IllegalArgumentException(formatError);204}205206// Parse the date207firstDash = date_s.indexOf('-');208secondDash = date_s.indexOf('-', firstDash+1);209210// Parse the time211if (time_s == null)212throw new java.lang.IllegalArgumentException(formatError);213firstColon = time_s.indexOf(':');214secondColon = time_s.indexOf(':', firstColon+1);215period = time_s.indexOf('.', secondColon+1);216217// Convert the date218boolean parsedDate = false;219if ((firstDash > 0) && (secondDash > 0) && (secondDash < date_s.length() - 1)) {220String yyyy = date_s.substring(0, firstDash);221String mm = date_s.substring(firstDash + 1, secondDash);222String dd = date_s.substring(secondDash + 1);223if (yyyy.length() == YEAR_LENGTH &&224(mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&225(dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {226year = Integer.parseInt(yyyy);227month = Integer.parseInt(mm);228day = Integer.parseInt(dd);229230if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {231parsedDate = true;232}233}234}235if (! parsedDate) {236throw new java.lang.IllegalArgumentException(formatError);237}238239// Convert the time; default missing nanos240if ((firstColon > 0) & (secondColon > 0) &241(secondColon < time_s.length()-1)) {242hour = Integer.parseInt(time_s.substring(0, firstColon));243minute =244Integer.parseInt(time_s.substring(firstColon+1, secondColon));245if ((period > 0) & (period < time_s.length()-1)) {246second =247Integer.parseInt(time_s.substring(secondColon+1, period));248nanos_s = time_s.substring(period+1);249if (nanos_s.length() > 9)250throw new java.lang.IllegalArgumentException(formatError);251if (!Character.isDigit(nanos_s.charAt(0)))252throw new java.lang.IllegalArgumentException(formatError);253nanos_s = nanos_s + zeros.substring(0,9-nanos_s.length());254a_nanos = Integer.parseInt(nanos_s);255} else if (period > 0) {256throw new java.lang.IllegalArgumentException(formatError);257} else {258second = Integer.parseInt(time_s.substring(secondColon+1));259}260} else {261throw new java.lang.IllegalArgumentException(formatError);262}263264return new Timestamp(year - 1900, month - 1, day, hour, minute, second, a_nanos);265}266267/**268* Formats a timestamp in JDBC timestamp escape format.269* <code>yyyy-mm-dd hh:mm:ss.fffffffff</code>,270* where <code>ffffffffff</code> indicates nanoseconds.271* <P>272* @return a <code>String</code> object in273* <code>yyyy-mm-dd hh:mm:ss.fffffffff</code> format274*/275@SuppressWarnings("deprecation")276public String toString () {277278int year = super.getYear() + 1900;279int month = super.getMonth() + 1;280int day = super.getDate();281int hour = super.getHours();282int minute = super.getMinutes();283int second = super.getSeconds();284String yearString;285String monthString;286String dayString;287String hourString;288String minuteString;289String secondString;290String nanosString;291String zeros = "000000000";292String yearZeros = "0000";293StringBuffer timestampBuf;294295if (year < 1000) {296// Add leading zeros297yearString = "" + year;298yearString = yearZeros.substring(0, (4-yearString.length())) +299yearString;300} else {301yearString = "" + year;302}303if (month < 10) {304monthString = "0" + month;305} else {306monthString = Integer.toString(month);307}308if (day < 10) {309dayString = "0" + day;310} else {311dayString = Integer.toString(day);312}313if (hour < 10) {314hourString = "0" + hour;315} else {316hourString = Integer.toString(hour);317}318if (minute < 10) {319minuteString = "0" + minute;320} else {321minuteString = Integer.toString(minute);322}323if (second < 10) {324secondString = "0" + second;325} else {326secondString = Integer.toString(second);327}328if (nanos == 0) {329nanosString = "0";330} else {331nanosString = Integer.toString(nanos);332333// Add leading zeros334nanosString = zeros.substring(0, (9-nanosString.length())) +335nanosString;336337// Truncate trailing zeros338char[] nanosChar = new char[nanosString.length()];339nanosString.getChars(0, nanosString.length(), nanosChar, 0);340int truncIndex = 8;341while (nanosChar[truncIndex] == '0') {342truncIndex--;343}344345nanosString = new String(nanosChar, 0, truncIndex + 1);346}347348// do a string buffer here instead.349timestampBuf = new StringBuffer(20+nanosString.length());350timestampBuf.append(yearString);351timestampBuf.append("-");352timestampBuf.append(monthString);353timestampBuf.append("-");354timestampBuf.append(dayString);355timestampBuf.append(" ");356timestampBuf.append(hourString);357timestampBuf.append(":");358timestampBuf.append(minuteString);359timestampBuf.append(":");360timestampBuf.append(secondString);361timestampBuf.append(".");362timestampBuf.append(nanosString);363364return (timestampBuf.toString());365}366367/**368* Gets this <code>Timestamp</code> object's <code>nanos</code> value.369*370* @return this <code>Timestamp</code> object's fractional seconds component371* @see #setNanos372*/373public int getNanos() {374return nanos;375}376377/**378* Sets this <code>Timestamp</code> object's <code>nanos</code> field379* to the given value.380*381* @param n the new fractional seconds component382* @exception java.lang.IllegalArgumentException if the given argument383* is greater than 999999999 or less than 0384* @see #getNanos385*/386public void setNanos(int n) {387if (n > 999999999 || n < 0) {388throw new IllegalArgumentException("nanos > 999999999 or < 0");389}390nanos = n;391}392393/**394* Tests to see if this <code>Timestamp</code> object is395* equal to the given <code>Timestamp</code> object.396*397* @param ts the <code>Timestamp</code> value to compare with398* @return <code>true</code> if the given <code>Timestamp</code>399* object is equal to this <code>Timestamp</code> object;400* <code>false</code> otherwise401*/402public boolean equals(Timestamp ts) {403if (super.equals(ts)) {404if (nanos == ts.nanos) {405return true;406} else {407return false;408}409} else {410return false;411}412}413414/**415* Tests to see if this <code>Timestamp</code> object is416* equal to the given object.417*418* This version of the method <code>equals</code> has been added419* to fix the incorrect420* signature of <code>Timestamp.equals(Timestamp)</code> and to preserve backward421* compatibility with existing class files.422*423* Note: This method is not symmetric with respect to the424* <code>equals(Object)</code> method in the base class.425*426* @param ts the <code>Object</code> value to compare with427* @return <code>true</code> if the given <code>Object</code> is an instance428* of a <code>Timestamp</code> that429* is equal to this <code>Timestamp</code> object;430* <code>false</code> otherwise431*/432public boolean equals(java.lang.Object ts) {433if (ts instanceof Timestamp) {434return this.equals((Timestamp)ts);435} else {436return false;437}438}439440/**441* Indicates whether this <code>Timestamp</code> object is442* earlier than the given <code>Timestamp</code> object.443*444* @param ts the <code>Timestamp</code> value to compare with445* @return <code>true</code> if this <code>Timestamp</code> object is earlier;446* <code>false</code> otherwise447*/448public boolean before(Timestamp ts) {449return compareTo(ts) < 0;450}451452/**453* Indicates whether this <code>Timestamp</code> object is454* later than the given <code>Timestamp</code> object.455*456* @param ts the <code>Timestamp</code> value to compare with457* @return <code>true</code> if this <code>Timestamp</code> object is later;458* <code>false</code> otherwise459*/460public boolean after(Timestamp ts) {461return compareTo(ts) > 0;462}463464/**465* Compares this <code>Timestamp</code> object to the given466* <code>Timestamp</code> object.467*468* @param ts the <code>Timestamp</code> object to be compared to469* this <code>Timestamp</code> object470* @return the value <code>0</code> if the two <code>Timestamp</code>471* objects are equal; a value less than <code>0</code> if this472* <code>Timestamp</code> object is before the given argument;473* and a value greater than <code>0</code> if this474* <code>Timestamp</code> object is after the given argument.475* @since 1.4476*/477public int compareTo(Timestamp ts) {478long thisTime = this.getTime();479long anotherTime = ts.getTime();480int i = (thisTime<anotherTime ? -1 :(thisTime==anotherTime?0 :1));481if (i == 0) {482if (nanos > ts.nanos) {483return 1;484} else if (nanos < ts.nanos) {485return -1;486}487}488return i;489}490491/**492* Compares this <code>Timestamp</code> object to the given493* <code>Date</code> object.494*495* @param o the <code>Date</code> to be compared to496* this <code>Timestamp</code> object497* @return the value <code>0</code> if this <code>Timestamp</code> object498* and the given object are equal; a value less than <code>0</code>499* if this <code>Timestamp</code> object is before the given argument;500* and a value greater than <code>0</code> if this501* <code>Timestamp</code> object is after the given argument.502*503* @since 1.5504*/505public int compareTo(java.util.Date o) {506if(o instanceof Timestamp) {507// When Timestamp instance compare it with a Timestamp508// Hence it is basically calling this.compareTo((Timestamp))o);509// Note typecasting is safe because o is instance of Timestamp510return compareTo((Timestamp)o);511} else {512// When Date doing a o.compareTo(this)513// will give wrong results.514Timestamp ts = new Timestamp(o.getTime());515return this.compareTo(ts);516}517}518519/**520* {@inheritDoc}521*522* The {@code hashCode} method uses the underlying {@code java.util.Date}523* implementation and therefore does not include nanos in its computation.524*525*/526@Override527public int hashCode() {528return super.hashCode();529}530531static final long serialVersionUID = 2745179027874758501L;532533private static final int MILLIS_PER_SECOND = 1000;534535/**536* Obtains an instance of {@code Timestamp} from a {@code LocalDateTime}537* object, with the same year, month, day of month, hours, minutes,538* seconds and nanos date-time value as the provided {@code LocalDateTime}.539* <p>540* The provided {@code LocalDateTime} is interpreted as the local541* date-time in the local time zone.542*543* @param dateTime a {@code LocalDateTime} to convert544* @return a {@code Timestamp} object545* @exception NullPointerException if {@code dateTime} is null.546* @since 1.8547*/548@SuppressWarnings("deprecation")549public static Timestamp valueOf(LocalDateTime dateTime) {550return new Timestamp(dateTime.getYear() - 1900,551dateTime.getMonthValue() - 1,552dateTime.getDayOfMonth(),553dateTime.getHour(),554dateTime.getMinute(),555dateTime.getSecond(),556dateTime.getNano());557}558559/**560* Converts this {@code Timestamp} object to a {@code LocalDateTime}.561* <p>562* The conversion creates a {@code LocalDateTime} that represents the563* same year, month, day of month, hours, minutes, seconds and nanos564* date-time value as this {@code Timestamp} in the local time zone.565*566* @return a {@code LocalDateTime} object representing the same date-time value567* @since 1.8568*/569@SuppressWarnings("deprecation")570public LocalDateTime toLocalDateTime() {571return LocalDateTime.of(getYear() + 1900,572getMonth() + 1,573getDate(),574getHours(),575getMinutes(),576getSeconds(),577getNanos());578}579580/**581* Obtains an instance of {@code Timestamp} from an {@link Instant} object.582* <p>583* {@code Instant} can store points on the time-line further in the future584* and further in the past than {@code Date}. In this scenario, this method585* will throw an exception.586*587* @param instant the instant to convert588* @return an {@code Timestamp} representing the same point on the time-line as589* the provided instant590* @exception NullPointerException if {@code instant} is null.591* @exception IllegalArgumentException if the instant is too large to592* represent as a {@code Timesamp}593* @since 1.8594*/595public static Timestamp from(Instant instant) {596try {597Timestamp stamp = new Timestamp(instant.getEpochSecond() * MILLIS_PER_SECOND);598stamp.nanos = instant.getNano();599return stamp;600} catch (ArithmeticException ex) {601throw new IllegalArgumentException(ex);602}603}604605/**606* Converts this {@code Timestamp} object to an {@code Instant}.607* <p>608* The conversion creates an {@code Instant} that represents the same609* point on the time-line as this {@code Timestamp}.610*611* @return an instant representing the same point on the time-line612* @since 1.8613*/614@Override615public Instant toInstant() {616return Instant.ofEpochSecond(super.getTime() / MILLIS_PER_SECOND, nanos);617}618}619620621