| /* |
| * Copyright 2008 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package java.sql; |
| |
| /** |
| * An implementation of java.sql.Timestame. Derived from |
| * http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Timestamp.html. This is |
| * basically just regular Date decorated with a nanoseconds field. |
| */ |
| public class Timestamp extends java.util.Date { |
| |
| public static Timestamp valueOf(String s) { |
| String[] components = s.split(" "); |
| if (components.length != 2) { |
| throw new IllegalArgumentException("Invalid escape format: " + s); |
| } |
| |
| String[] timeComponents = components[1].split("\\."); |
| boolean hasNanos = true; |
| int nanos = 0; |
| |
| if (timeComponents.length == 1) { |
| // Allow timestamps without .fffffffff nanoseconds field |
| hasNanos = false; |
| } else if (timeComponents.length != 2) { |
| throw new IllegalArgumentException("Invalid escape format: " + s); |
| } |
| |
| Date d = Date.valueOf(components[0]); |
| Time t = Time.valueOf(timeComponents[0]); |
| if (hasNanos) { |
| String nanosString = timeComponents[1]; |
| int len = nanosString.length(); |
| assert(len > 0); // len must be > 0 if hasNanos is true |
| if (len > 9) { |
| throw new IllegalArgumentException("Invalid escape format: " + s); |
| } |
| |
| // Pad zeros on the right up to a total of 9 digits |
| if (len < 9) { |
| nanosString += "00000000".substring(len - 1); |
| } |
| |
| try { |
| nanos = Integer.valueOf(nanosString); |
| } catch (NumberFormatException e) { |
| throw new IllegalArgumentException("Invalid escape format: " + s); |
| } |
| } |
| |
| return new Timestamp(d.getYear(), d.getMonth(), d.getDate(), t.getHours(), |
| t.getMinutes(), t.getSeconds(), nanos); |
| } |
| |
| private static String padNine(int value) { |
| StringBuffer toReturn = new StringBuffer("000000000"); |
| assert toReturn.length() == 9; |
| |
| String asString = String.valueOf(value); |
| toReturn = toReturn.replace(9 - asString.length(), 9, asString); |
| |
| assert toReturn.length() == 9; |
| return toReturn.toString(); |
| } |
| |
| /** |
| * Stores the nanosecond resolution of the timestamp; must be kept in sync |
| * with the sub-second part of Date.millis. |
| */ |
| private int nanos; |
| |
| @Deprecated |
| public Timestamp(int year, int month, int date, int hour, int minute, |
| int second, int nano) { |
| super(year, month, date, hour, minute, second); |
| setNanos(nano); |
| } |
| |
| public Timestamp(long time) { |
| super(time); |
| |
| // Seed the milliseconds in nanos |
| nanos = (((int) (time % 1000)) * 1000000); |
| } |
| |
| public boolean after(Timestamp ts) { |
| return (getTime() > ts.getTime()) |
| || (getTime() == ts.getTime() && getNanos() > ts.getNanos()); |
| } |
| |
| public boolean before(Timestamp ts) { |
| return (getTime() < ts.getTime()) |
| || (getTime() == ts.getTime() && getNanos() < ts.getNanos()); |
| } |
| |
| @Override |
| public int compareTo(java.util.Date o) { |
| // JavaDoc says a ClassCastException is correct behavior |
| return compareTo((Timestamp) o); |
| } |
| |
| public int compareTo(Timestamp o) { |
| int delta = (int) (getTime() - o.getTime()); |
| return delta == 0 ? getNanos() - o.getNanos() : delta; |
| } |
| |
| @Override |
| public boolean equals(Object ts) { |
| // Timestamps can't be compared to java.util.Date |
| // This is known to not be symmetric, which follows the JRE. |
| return ts instanceof Timestamp ? equals((Timestamp) ts) : false; |
| } |
| |
| public boolean equals(Timestamp ts) { |
| return (getTime() == ts.getTime() && getNanos() == ts.getNanos()); |
| } |
| |
| public int getNanos() { |
| return nanos; |
| } |
| |
| @Override |
| public long getTime() { |
| return super.getTime(); |
| } |
| |
| @Override |
| public int hashCode() { |
| // This is correct, per the Javadoc |
| return super.hashCode(); |
| } |
| |
| public void setNanos(int n) { |
| if (n < 0 || n > 999999999) { |
| throw new IllegalArgumentException("nanos out of range " + n); |
| } |
| |
| nanos = n; |
| // Clear the sub-second part of the date; replace with new nanos. |
| super.setTime((getTime() / 1000) * 1000 + (nanos / 1000000)); |
| } |
| |
| @Override |
| public void setTime(long time) { |
| super.setTime(time); |
| nanos = (((int) (time % 1000)) * 1000000); |
| } |
| |
| @Override |
| public String toString() { |
| return String.valueOf(1900 + getYear()) + "-" + padTwo(1 + getMonth()) |
| + "-" + padTwo(getDate()) + " " + padTwo(getHours()) + ":" |
| + padTwo(getMinutes()) + ":" + padTwo(getSeconds()) + "." |
| + padNine(getNanos()); |
| } |
| } |