1f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License.  You may obtain a copy of the License at
8f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.sql;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.text.ParsePosition;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.text.SimpleDateFormat;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Date;
23f58ca9d9ff8540a146a0031d5557881f8b66f348Johan Redestigimport java.util.Locale;
24142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilsonimport java.util.regex.Pattern;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A Java representation of the SQL {@code TIMESTAMP} type. It provides the
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * capability of representing the SQL {@code TIMESTAMP} nanosecond value, in
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * addition to the regular date/time value which has millisecond resolution.
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p>
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The {@code Timestamp} class consists of a regular date/time value, where only
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the integral seconds value is stored, plus a nanoseconds value where the
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * fractional seconds are stored.
34142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson * <p>
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The addition of the nanosecond value field to the {@code Timestamp} object
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * makes it significantly different from the {@code java.util.Date} object which
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it extends. Users should be aware that {@code Timestamp} objects are not
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * interchangable with {@code java.util.Date} objects when used outside the
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * confines of the {@code java.sql} package.
40142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson *
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see Date
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see Time
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.util.Date
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class Timestamp extends Date {
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long serialVersionUID = 2745179027874758501L;
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // The nanoseconds time value of the Timestamp
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int nanos;
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
52143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes    // The regex pattern of yyyy-MM-dd HH:mm:ss
5303c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes    private static final String TIME_FORMAT_REGEX = "[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}.*";
54142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a {@code Timestamp} corresponding to the time specified by the
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * supplied values for <i>Year</i>, <i>Month</i>, <i>Date</i>, <i>Hour</i>,
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <i>Minutes</i>, <i>Seconds</i> and <i>Nanoseconds</i>.
59142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson     *
6099b4489d0555c6e0e5df941cbfad4cf250c8f0b8Elliott Hughes     * @deprecated Use the constructor {@link #Timestamp(long)} instead.
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theYear
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            specified as the year minus 1900.
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theMonth
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            specified as an integer in the range [0,11].
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theDate
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            specified as an integer in the range [1,31].
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theHour
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            specified as an integer in the range [0,23].
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theMinute
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            specified as an integer in the range [0,59].
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theSecond
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            specified as an integer in the range [0,59].
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theNano
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            which defines the nanosecond value of the timestamp specified
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            as an integer in the range [0,999'999'999]
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if any of the parameters is out of range.
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @SuppressWarnings("deprecation")
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Deprecated
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Timestamp(int theYear, int theMonth, int theDate, int theHour,
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int theMinute, int theSecond, int theNano)
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throws IllegalArgumentException {
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(theYear, theMonth, theDate, theHour, theMinute, theSecond);
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (theNano < 0 || theNano > 999999999) {
86cff1616012dc0d56c2da9af2b9b1183e76c7e044Elliott Hughes            throw new IllegalArgumentException("ns out of range: " + theNano);
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nanos = theNano;
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a {@code Timestamp} object corresponding to the time represented
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * by a supplied time value.
94f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theTime
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            a time value in the format of milliseconds since the Epoch
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            (January 1 1970 00:00:00.000 GMT).
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Timestamp(long theTime) {
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(theTime);
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Now set the time for this Timestamp object - which deals with the
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * nanosecond value as well as the base time
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
105142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        setTimeImpl(theTime);
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns {@code true} if this timestamp object is later than the supplied
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * timestamp, otherwise returns {@code false}.
111f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theTimestamp
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the timestamp to compare with this timestamp object.
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this {@code Timestamp} object is later than the
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         supplied timestamp, {@code false} otherwise.
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean after(Timestamp theTimestamp) {
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long thisTime = this.getTime();
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long compareTime = theTimestamp.getTime();
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // If the time value is later, the timestamp is later
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (thisTime > compareTime) {
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // If the time value is earlier, the timestamp is not later
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        else if (thisTime < compareTime) {
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Otherwise the time values are equal in which case the nanoseconds
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * value determines whether this timestamp is later...
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        else if (this.getNanos() > theTimestamp.getNanos()) {
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns {@code true} if this {@code Timestamp} object is earlier than the
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * supplied timestamp, otherwise returns {@code false}.
143f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theTimestamp
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the timestamp to compare with this {@code Timestamp} object.
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this {@code Timestamp} object is earlier than the
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         supplied timestamp, {@code false} otherwise.
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean before(Timestamp theTimestamp) {
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long thisTime = this.getTime();
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long compareTime = theTimestamp.getTime();
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // If the time value is later, the timestamp is later
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (thisTime < compareTime) {
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // If the time value is earlier, the timestamp is not later
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        else if (thisTime > compareTime) {
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Otherwise the time values are equal in which case the nanoseconds
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * value determines whether this timestamp is later...
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        else if (this.getNanos() < theTimestamp.getNanos()) {
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return true;
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Compares this {@code Timestamp} object with a supplied {@code Timestamp}
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * object.
175f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theObject
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the timestamp to compare with this {@code Timestamp} object,
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            passed as an {@code Object}.
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return <dd>
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         <dl>
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code 0} if the two {@code Timestamp} objects are equal in time
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         </dl>
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         <dl>
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         a value {@code < 0} if this {@code Timestamp} object is before
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         the supplied {@code Timestamp} and a value
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         </dl>
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         <dl>
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         {@code > 0} if this {@code Timestamp} object is after the
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         supplied {@code Timestamp}
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         </dl>
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         </dd>
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws ClassCastException
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the supplied object is not a {@code Timestamp} object.
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int compareTo(Date theObject) throws ClassCastException {
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return this.compareTo((Timestamp) theObject);
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Compares this {@code Timestamp} object with a supplied {@code Timestamp}
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * object.
203f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theTimestamp
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the timestamp to compare with this {@code Timestamp} object,
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            passed in as a {@code Timestamp}.
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return one of the following:
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         <ul>
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         <li>{@code 0}, if the two {@code Timestamp} objects are
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         equal in time</li>
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         <li>{@code < 0}, if this {@code Timestamp} object is before the
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         supplied {@code Timestamp}</li>
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         <li> {@code > 0}, if this {@code Timestamp} object is after the
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         supplied {@code Timestamp}</li>
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         </ul>
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int compareTo(Timestamp theTimestamp) {
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int result = super.compareTo(theTimestamp);
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (result == 0) {
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int thisNano = this.getNanos();
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int thatNano = theTimestamp.getNanos();
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (thisNano > thatNano) {
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return 1;
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else if (thisNano == thatNano) {
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return 0;
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return -1;
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Tests to see if this timestamp is equal to a supplied object.
235f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theObject
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the object to which this timestamp is compared.
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this {@code Timestamp} object is equal to the
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         supplied {@code Timestamp} object<br>{@code false} if the object
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         is not a {@code Timestamp} object or if the object is a {@code
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         Timestamp} but represents a different instant in time.
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean equals(Object theObject) {
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (theObject instanceof Timestamp) {
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return equals((Timestamp) theObject);
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return false;
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Tests to see if this timestamp is equal to a supplied timestamp.
253f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theTimestamp
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the timestamp to compare with this {@code Timestamp} object,
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            passed as an {@code Object}.
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return {@code true} if this {@code Timestamp} object is equal to the
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         supplied {@code Timestamp} object, {@code false} otherwise.
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean equals(Timestamp theTimestamp) {
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (theTimestamp == null) {
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (this.getTime() == theTimestamp.getTime())
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                && (this.getNanos() == theTimestamp.getNanos());
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets this {@code Timestamp}'s nanosecond value
270f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return The timestamp's nanosecond value, an integer between 0 and
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         999,999,999.
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getNanos() {
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return nanos;
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the time represented by this {@code Timestamp} object, as a long
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * value containing the number of milliseconds since the Epoch (January 1
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * 1970, 00:00:00.000 GMT).
282142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson     *
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the number of milliseconds that have passed since January 1 1970,
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         00:00:00.000 GMT.
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public long getTime() {
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long theTime = super.getTime();
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        theTime = theTime + (nanos / 1000000);
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return theTime;
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the nanosecond value for this {@code Timestamp}.
295142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson     *
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param n
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            number of nanoseconds.
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if number of nanoseconds smaller than 0 or greater than
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             999,999,999.
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setNanos(int n) throws IllegalArgumentException {
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((n < 0) || (n > 999999999)) {
30403c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes            throw new IllegalArgumentException("Value out of range");
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nanos = n;
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the time represented by this {@code Timestamp} object to the
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * supplied time, defined as the number of milliseconds since the Epoch
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * (January 1 1970, 00:00:00.000 GMT).
313142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson     *
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param theTime
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            number of milliseconds since the Epoch (January 1 1970,
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            00:00:00.000 GMT).
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setTime(long theTime) {
320142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        setTimeImpl(theTime);
321142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson    }
322f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
323142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson    private void setTimeImpl(long theTime) {
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Deal with the nanoseconds value. The supplied time is in milliseconds -
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * so we must extract the milliseconds value and multiply by 1000000 to
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * get nanoseconds. Things are more complex if theTime value is
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * negative, since then the time value is the time before the Epoch but
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * the nanoseconds value of the Timestamp must be positive - so we must
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * take the "raw" milliseconds value and subtract it from 1000 to get to
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * the true nanoseconds value Simultaneously, recalculate the time value
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * to the exact nearest second and reset the Date time value
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int milliseconds = (int) (theTime % 1000);
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        theTime = theTime - milliseconds;
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (milliseconds < 0) {
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            theTime = theTime - 1000;
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            milliseconds = 1000 + milliseconds;
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super.setTime(theTime);
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setNanos(milliseconds * 1000000);
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the timestamp formatted as a String in the JDBC Timestamp Escape
346143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes     * format, which is {@code "yyyy-MM-dd HH:mm:ss.nnnnnnnnn"}.
347f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return A string representing the instant defined by the {@code
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         Timestamp}, in JDBC Timestamp escape format.
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @SuppressWarnings("deprecation")
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
354142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        StringBuilder sb = new StringBuilder(29);
355142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson
356142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        format((getYear() + 1900), 4, sb);
357142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        sb.append('-');
358142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        format((getMonth() + 1), 2, sb);
359142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        sb.append('-');
360142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        format(getDate(), 2, sb);
361142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        sb.append(' ');
362142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        format(getHours(), 2, sb);
363142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        sb.append(':');
364142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        format(getMinutes(), 2, sb);
365142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        sb.append(':');
366142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        format(getSeconds(), 2, sb);
367142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        sb.append('.');
368142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        if (nanos == 0) {
369142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson            sb.append('0');
370142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        } else {
371142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson            format(nanos, 9, sb);
372142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson            while (sb.charAt(sb.length() - 1) == '0') {
373142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson                sb.setLength(sb.length() - 1);
374142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson            }
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
376142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson
377142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        return sb.toString();
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
38003c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes    private static final String PADDING = "000000000";
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
382f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    /*
383f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    * Private method to format the time
384f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    */
385f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    private void format(int date, int digits, StringBuilder sb) {
386142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        String str = String.valueOf(date);
387142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        if (digits - str.length() > 0) {
388142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson            sb.append(PADDING.substring(0, digits - str.length()));
389142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        }
390f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        sb.append(str);
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates a {@code Timestamp} object with a time value equal to the time
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * specified by a supplied String holding the time in JDBC timestamp escape
396143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes     * format, which is {@code "yyyy-MM-dd HH:mm:ss.nnnnnnnnn}"
397f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param s
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the {@code String} containing a time in JDBC timestamp escape
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            format.
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return A {@code Timestamp} object with time value as defined by the
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         supplied {@code String}.
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if the provided string is {@code null}.
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static Timestamp valueOf(String s) throws IllegalArgumentException {
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (s == null) {
40803c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes            throw new IllegalArgumentException("Argument cannot be null");
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
41103c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes        // omit trailing whitespace
412142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        s = s.trim();
413142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        if (!Pattern.matches(TIME_FORMAT_REGEX, s)) {
41403c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes            throw badTimestampString(s);
415142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson        }
416142d526f8bf90fb9bb63c637beb5299f39791f55Jesse Wilson
417f58ca9d9ff8540a146a0031d5557881f8b66f348Johan Redestig        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ParsePosition pp = new ParsePosition(0);
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * First parse out the yyyy-MM-dd HH:mm:ss component of the String into
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * a Date object using the SimpleDateFormat. This should stop after the
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * seconds value, according to the definition of SimpleDateFormat.parse,
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * with the ParsePosition indicating the index of the "." which should
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * precede the nanoseconds value
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Date theDate;
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            theDate = df.parse(s, pp);
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (Exception e) {
43103c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes            throw badTimestampString(s);
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (theDate == null) {
43503c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes            throw badTimestampString(s);
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * If we get here, the Date part of the string was OK - now for the
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * nanoseconds value. Strictly, this requires the remaining part of the
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * String to look like ".nnnnnnnnn". However, we accept anything with a
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * '.' followed by 1 to 9 digits - we also accept nothing (no fractions
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * of a second). Anything else is interpreted as incorrect format which
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * will generate an IllegalArgumentException
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int position = pp.getIndex();
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int remaining = s.length() - position;
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int theNanos;
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (remaining == 0) {
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // First, allow for the case where no fraction of a second is given:
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            theNanos = 0;
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /*
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * Case where fraction of a second is specified: Require 1 character
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * plus the "." in the remaining part of the string...
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
45803c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes            if ((s.length() - position) < ".n".length()) {
45903c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes                throw badTimestampString(s);
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /*
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * If we're strict, we should not allow any EXTRA characters after
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * the 9 digits
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
46603c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes            if ((s.length() - position) > ".nnnnnnnnn".length()) {
46703c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes                throw badTimestampString(s);
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Require the next character to be a "."
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (s.charAt(position) != '.') {
47203c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes                throw new NumberFormatException("Bad input string format: expected '.' not '" +
4731f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes                        s.charAt(position) + "' in \"" + s + "\"");
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Get the length of the number string - need to account for the '.'
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int nanoLength = s.length() - position - 1;
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Get the 9 characters following the "." as an integer
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String theNanoString = s.substring(position + 1, position + 1
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    + nanoLength);
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /*
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * We must adjust for the cases where the nanos String was not 9
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * characters long by padding out with zeros
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
48503c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes            theNanoString = theNanoString + "000000000";
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            theNanoString = theNanoString.substring(0, 9);
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                theNanos = Integer.parseInt(theNanoString);
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (Exception e) {
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // If we get here, the string was not a number
49203c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes                throw badTimestampString(s);
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (theNanos < 0 || theNanos > 999999999) {
49703c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes            throw badTimestampString(s);
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        Timestamp theTimestamp = new Timestamp(theDate.getTime());
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        theTimestamp.setNanos(theNanos);
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return theTimestamp;
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
505f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
50603c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes    private static IllegalArgumentException badTimestampString(String s) {
50703c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes        throw new IllegalArgumentException("Timestamp format must be " +
508143e8c9cf91cfc01c3c91c8e93cad661ec7554eeElliott Hughes                "yyyy-MM-dd HH:mm:ss.fffffffff; was '" + s + "'");
50903c0a8e681c776fdba0389ab8593282139afc6d6Elliott Hughes    }
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
511