File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\value\ValueTimestamp.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.value;
8
9 import java.math.BigDecimal;
10 import java.sql.Date;
11 import java.sql.PreparedStatement;
12 import java.sql.SQLException;
13 import java.sql.Timestamp;
14 import java.util.Calendar;
15 import java.util.TimeZone;
16 import org.h2.constant.ErrorCode;
17 import org.h2.message.DbException;
18 import org.h2.util.DateTimeUtils;
19 import org.h2.util.MathUtils;
20
21 /**
22 * Implementation of the TIMESTAMP data type.
23 */
24 public class ValueTimestamp extends Value {
25
26 /**
27 * The precision in digits.
28 */
29 public static final int PRECISION = 23;
30
31 /**
32 * The display size of the textual representation of a timestamp.
33 * Example: 2001-01-01 23:59:59.000
34 */
35 static final int DISPLAY_SIZE = 23;
36
37 /**
38 * The default scale for timestamps.
39 */
40 static final int DEFAULT_SCALE = 10;
41
42 private final long dateValue;
43 private final long nanos;
44
45 private ValueTimestamp(long dateValue, long nanos) {
46 this.dateValue = dateValue;
47 this.nanos = nanos;
48 }
49
50 /**
51 * Get or create a date value for the given date.
52 *
53 * @param dateValue the date value
54 * @param nanos the nanoseconds
55 * @return the value
56 */
57 public static ValueTimestamp fromDateValueAndNanos(long dateValue, long nanos) {
58 return (ValueTimestamp) Value.cache(new ValueTimestamp(dateValue, nanos));
59 }
60
61 /**
62 * Get or create a timestamp value for the given timestamp.
63 *
64 * @param timestamp the timestamp
65 * @return the value
66 */
67 public static ValueTimestamp get(Timestamp timestamp) {
68 long ms = timestamp.getTime();
69 long nanos = timestamp.getNanos() % 1000000;
70 long dateValue = DateTimeUtils.dateValueFromDate(ms);
71 nanos += DateTimeUtils.nanosFromDate(ms);
72 return fromDateValueAndNanos(dateValue, nanos);
73 }
74
75 /**
76 * Parse a string to a ValueTimestamp. This method supports the format
77 * +/-year-month-day hour:minute:seconds.fractional and an optional timezone
78 * part.
79 *
80 * @param s the string to parse
81 * @return the date
82 */
83 public static ValueTimestamp parse(String s) {
84 try {
85 return parseTry(s);
86 } catch (Exception e) {
87 throw DbException.get(ErrorCode.INVALID_DATETIME_CONSTANT_2,
88 e, "TIMESTAMP", s);
89 }
90 }
91
92 private static ValueTimestamp parseTry(String s) {
93 int dateEnd = s.indexOf(' ');
94 if (dateEnd < 0) {
95 // ISO 8601 compatibility
96 dateEnd = s.indexOf('T');
97 }
98 int timeStart;
99 if (dateEnd < 0) {
100 dateEnd = s.length();
101 timeStart = -1;
102 } else {
103 timeStart = dateEnd + 1;
104 }
105 long dateValue = DateTimeUtils.parseDateValue(s, 0, dateEnd);
106 long nanos;
107 if (timeStart < 0) {
108 nanos = 0;
109 } else {
110 int timeEnd = s.length();
111 TimeZone tz = null;
112 if (s.endsWith("Z")) {
113 tz = TimeZone.getTimeZone("UTC");
114 timeEnd--;
115 } else {
116 int timeZoneStart = s.indexOf('+', dateEnd);
117 if (timeZoneStart < 0) {
118 timeZoneStart = s.indexOf('-', dateEnd);
119 }
120 if (timeZoneStart >= 0) {
121 String tzName = "GMT" + s.substring(timeZoneStart);
122 tz = TimeZone.getTimeZone(tzName);
123 if (!tz.getID().startsWith(tzName)) {
124 throw new IllegalArgumentException(tzName);
125 }
126 timeEnd = timeZoneStart;
127 } else {
128 timeZoneStart = s.indexOf(' ', dateEnd + 1);
129 if (timeZoneStart > 0) {
130 String tzName = s.substring(timeZoneStart + 1);
131 tz = TimeZone.getTimeZone(tzName);
132 if (!tz.getID().startsWith(tzName)) {
133 throw new IllegalArgumentException(tzName);
134 }
135 timeEnd = timeZoneStart;
136 }
137 }
138 }
139 nanos = DateTimeUtils.parseTimeNanos(s, dateEnd + 1, timeEnd, true);
140 if (tz != null) {
141 int year = DateTimeUtils.yearFromDateValue(dateValue);
142 int month = DateTimeUtils.monthFromDateValue(dateValue);
143 int day = DateTimeUtils.dayFromDateValue(dateValue);
144 long ms = nanos / 1000000;
145 nanos -= ms * 1000000;
146 long second = ms / 1000;
147 ms -= second * 1000;
148 int minute = (int) (second / 60);
149 second -= minute * 60;
150 int hour = minute / 60;
151 minute -= hour * 60;
152 long millis = DateTimeUtils.getMillis(tz, year, month, day, hour, minute, (int) second, (int) ms);
153 ms = DateTimeUtils.convertToLocal(new Date(millis), Calendar.getInstance(TimeZone.getTimeZone("UTC")));
154 long md = DateTimeUtils.MILLIS_PER_DAY;
155 long absoluteDay = (ms >= 0 ? ms : ms - md + 1) / md;
156 ms -= absoluteDay * md;
157 nanos += ms * 1000000;
158 }
159 }
160 return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos);
161 }
162
163 public long getDateValue() {
164 return dateValue;
165 }
166
167 public long getNanos() {
168 return nanos;
169 }
170
171 public Timestamp getTimestamp() {
172 return DateTimeUtils.convertDateValueToTimestamp(dateValue, nanos);
173 }
174
175 public int getType() {
176 return Value.TIMESTAMP;
177 }
178
179 public String getString() {
180 StringBuilder buff = new StringBuilder(DISPLAY_SIZE);
181 ValueDate.appendDate(buff, dateValue);
182 buff.append(' ');
183 ValueTime.appendTime(buff, nanos, true);
184 return buff.toString();
185 }
186
187 public String getSQL() {
188 return "TIMESTAMP '" + getString() + "'";
189 }
190
191 public long getPrecision() {
192 return PRECISION;
193 }
194
195 public int getScale() {
196 return DEFAULT_SCALE;
197 }
198
199 public int getDisplaySize() {
200 return DISPLAY_SIZE;
201 }
202
203 public Value convertScale(boolean onlyToSmallerScale, int targetScale) {
204 if (targetScale >= DEFAULT_SCALE) {
205 return this;
206 }
207 if (targetScale < 0) {
208 throw DbException.getInvalidValueException("scale", targetScale);
209 }
210 long n = nanos;
211 BigDecimal bd = BigDecimal.valueOf(n);
212 bd = bd.movePointLeft(9);
213 bd = MathUtils.setScale(bd, targetScale);
214 bd = bd.movePointRight(9);
215 long n2 = bd.longValue();
216 if (n2 == n) {
217 return this;
218 }
219 return fromDateValueAndNanos(dateValue, n2);
220 }
221
222 protected int compareSecure(Value o, CompareMode mode) {
223 ValueTimestamp t = (ValueTimestamp) o;
224 int c = MathUtils.compareLong(dateValue, t.dateValue);
225 if (c != 0) {
226 return c;
227 }
228 return MathUtils.compareLong(nanos, t.nanos);
229 }
230
231 public boolean equals(Object other) {
232 if (this == other) {
233 return true;
234 } else if (!(other instanceof ValueTimestamp)) {
235 return false;
236 }
237 ValueTimestamp x = (ValueTimestamp) other;
238 return dateValue == x.dateValue && nanos == x.nanos;
239 }
240
241 public int hashCode() {
242 return (int) (dateValue ^ (dateValue >>> 32) ^ nanos ^ (nanos >>> 32));
243 }
244
245 public Object getObject() {
246 return getTimestamp();
247 }
248
249 public void set(PreparedStatement prep, int parameterIndex) throws SQLException {
250 prep.setTimestamp(parameterIndex, getTimestamp());
251 }
252
253 public Value add(Value v) {
254 ValueTimestamp t = (ValueTimestamp) v.convertTo(Value.TIMESTAMP);
255 long d1 = DateTimeUtils.absoluteDayFromDateValue(dateValue);
256 long d2 = DateTimeUtils.absoluteDayFromDateValue(t.dateValue);
257 return DateTimeUtils.normalizeTimestamp(d1 + d2, nanos + t.nanos);
258 }
259
260 public Value subtract(Value v) {
261 ValueTimestamp t = (ValueTimestamp) v.convertTo(Value.TIMESTAMP);
262 long d1 = DateTimeUtils.absoluteDayFromDateValue(dateValue);
263 long d2 = DateTimeUtils.absoluteDayFromDateValue(t.dateValue);
264 return DateTimeUtils.normalizeTimestamp(d1 - d2, nanos - t.nanos);
265 }
266
267 }
268