Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(363)

Side by Side Diff: third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java

Issue 2590803003: Revert "third_party/protobuf: Update to HEAD (83d681ee2c)" (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Protocol Buffers - Google's data interchange format 1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved. 2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/ 3 // https://developers.google.com/protocol-buffers/
4 // 4 //
5 // Redistribution and use in source and binary forms, with or without 5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are 6 // modification, are permitted provided that the following conditions are
7 // met: 7 // met:
8 // 8 //
9 // * Redistributions of source code must retain the above copyright 9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer. 10 // notice, this list of conditions and the following disclaimer.
(...skipping 17 matching lines...) Expand all
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 30
31 package com.google.protobuf.util; 31 package com.google.protobuf.util;
32 32
33 import com.google.protobuf.Duration; 33 import com.google.protobuf.Duration;
34 import com.google.protobuf.Timestamp; 34 import com.google.protobuf.Timestamp;
35 35
36 import java.math.BigInteger; 36 import java.math.BigInteger;
37 import java.text.ParseException; 37 import java.text.ParseException;
38 import java.text.SimpleDateFormat;
39 import java.util.Date;
40 import java.util.GregorianCalendar;
41 import java.util.TimeZone;
38 42
39 /** 43 /**
40 * Utilities to help create/manipulate Timestamp/Duration 44 * Utilities to help create/manipulate Timestamp/Duration
41 *
42 * @deprecated Use {@link Durations} and {@link Timestamps} instead.
43 */ 45 */
44 @Deprecated 46 public class TimeUtil {
45 public final class TimeUtil {
46 // Timestamp for "0001-01-01T00:00:00Z" 47 // Timestamp for "0001-01-01T00:00:00Z"
47 public static final long TIMESTAMP_SECONDS_MIN = -62135596800L; 48 public static final long TIMESTAMP_SECONDS_MIN = -62135596800L;
48 49
49 // Timestamp for "9999-12-31T23:59:59Z" 50 // Timestamp for "9999-12-31T23:59:59Z"
50 public static final long TIMESTAMP_SECONDS_MAX = 253402300799L; 51 public static final long TIMESTAMP_SECONDS_MAX = 253402300799L;
51 public static final long DURATION_SECONDS_MIN = -315576000000L; 52 public static final long DURATION_SECONDS_MIN = -315576000000L;
52 public static final long DURATION_SECONDS_MAX = 315576000000L; 53 public static final long DURATION_SECONDS_MAX = 315576000000L;
53 54
54 private static final long NANOS_PER_SECOND = 1000000000; 55 private static final long NANOS_PER_SECOND = 1000000000;
56 private static final long NANOS_PER_MILLISECOND = 1000000;
57 private static final long NANOS_PER_MICROSECOND = 1000;
58 private static final long MILLIS_PER_SECOND = 1000;
59 private static final long MICROS_PER_SECOND = 1000000;
60
61 private static final ThreadLocal<SimpleDateFormat> timestampFormat =
62 new ThreadLocal<SimpleDateFormat>() {
63 protected SimpleDateFormat initialValue() {
64 return createTimestampFormat();
65 }
66 };
67
68 private static SimpleDateFormat createTimestampFormat() {
69 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
70 GregorianCalendar calendar =
71 new GregorianCalendar(TimeZone.getTimeZone("UTC"));
72 // We use Proleptic Gregorian Calendar (i.e., Gregorian calendar extends
73 // backwards to year one) for timestamp formating.
74 calendar.setGregorianChange(new Date(Long.MIN_VALUE));
75 sdf.setCalendar(calendar);
76 return sdf;
77 }
55 78
56 private TimeUtil() {} 79 private TimeUtil() {}
57 80
58 /** 81 /**
59 * Convert Timestamp to RFC 3339 date string format. The output will always 82 * Convert Timestamp to RFC 3339 date string format. The output will always
60 * be Z-normalized and uses 3, 6 or 9 fractional digits as required to 83 * be Z-normalized and uses 3, 6 or 9 fractional digits as required to
61 * represent the exact value. Note that Timestamp can only represent time 84 * represent the exact value. Note that Timestamp can only represent time
62 * from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. See 85 * from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. See
63 * https://www.ietf.org/rfc/rfc3339.txt 86 * https://www.ietf.org/rfc/rfc3339.txt
64 * 87 *
65 * <p>Example of generated format: "1972-01-01T10:00:20.021Z" 88 * <p>Example of generated format: "1972-01-01T10:00:20.021Z"
66 * 89 *
67 * @return The string representation of the given timestamp. 90 * @return The string representation of the given timestamp.
68 * @throws IllegalArgumentException if the given timestamp is not in the 91 * @throws IllegalArgumentException if the given timestamp is not in the
69 * valid range. 92 * valid range.
70 * @deprecated Use {@link Timestamps#toString} instead.
71 */ 93 */
72 @Deprecated 94 public static String toString(Timestamp timestamp)
73 public static String toString(Timestamp timestamp) { 95 throws IllegalArgumentException {
74 return Timestamps.toString(timestamp); 96 StringBuilder result = new StringBuilder();
97 // Format the seconds part.
98 if (timestamp.getSeconds() < TIMESTAMP_SECONDS_MIN
99 || timestamp.getSeconds() > TIMESTAMP_SECONDS_MAX) {
100 throw new IllegalArgumentException("Timestamp is out of range.");
101 }
102 Date date = new Date(timestamp.getSeconds() * MILLIS_PER_SECOND);
103 result.append(timestampFormat.get().format(date));
104 // Format the nanos part.
105 if (timestamp.getNanos() < 0 || timestamp.getNanos() >= NANOS_PER_SECOND) {
106 throw new IllegalArgumentException("Timestamp has invalid nanos value.");
107 }
108 if (timestamp.getNanos() != 0) {
109 result.append(".");
110 result.append(formatNanos(timestamp.getNanos()));
111 }
112 result.append("Z");
113 return result.toString();
75 } 114 }
76 115
77 /** 116 /**
78 * Parse from RFC 3339 date string to Timestamp. This method accepts all 117 * Parse from RFC 3339 date string to Timestamp. This method accepts all
79 * outputs of {@link #toString(Timestamp)} and it also accepts any fractional 118 * outputs of {@link #toString(Timestamp)} and it also accepts any fractional
80 * digits (or none) and any offset as long as they fit into nano-seconds 119 * digits (or none) and any offset as long as they fit into nano-seconds
81 * precision. 120 * precision.
82 * 121 *
83 * <p>Example of accepted format: "1972-01-01T10:00:20.021-05:00" 122 * <p>Example of accepted format: "1972-01-01T10:00:20.021-05:00"
84 * 123 *
85 * @return A Timestamp parsed from the string. 124 * @return A Timestamp parsed from the string.
86 * @throws ParseException if parsing fails. 125 * @throws ParseException if parsing fails.
87 * @deprecated Use {@link Timestamps#parse} instead.
88 */ 126 */
89 @Deprecated 127
90 public static Timestamp parseTimestamp(String value) throws ParseException { 128 public static Timestamp parseTimestamp(String value) throws ParseException {
91 return Timestamps.parse(value); 129 int dayOffset = value.indexOf('T');
130 if (dayOffset == -1) {
131 throw new ParseException(
132 "Failed to parse timestamp: invalid timestamp \"" + value + "\"", 0);
133 }
134 int timezoneOffsetPosition = value.indexOf('Z', dayOffset);
135 if (timezoneOffsetPosition == -1) {
136 timezoneOffsetPosition = value.indexOf('+', dayOffset);
137 }
138 if (timezoneOffsetPosition == -1) {
139 timezoneOffsetPosition = value.indexOf('-', dayOffset);
140 }
141 if (timezoneOffsetPosition == -1) {
142 throw new ParseException(
143 "Failed to parse timestamp: missing valid timezone offset.", 0);
144 }
145 // Parse seconds and nanos.
146 String timeValue = value.substring(0, timezoneOffsetPosition);
147 String secondValue = timeValue;
148 String nanoValue = "";
149 int pointPosition = timeValue.indexOf('.');
150 if (pointPosition != -1) {
151 secondValue = timeValue.substring(0, pointPosition);
152 nanoValue = timeValue.substring(pointPosition + 1);
153 }
154 Date date = timestampFormat.get().parse(secondValue);
155 long seconds = date.getTime() / MILLIS_PER_SECOND;
156 int nanos = nanoValue.isEmpty() ? 0 : parseNanos(nanoValue);
157 // Parse timezone offsets.
158 if (value.charAt(timezoneOffsetPosition) == 'Z') {
159 if (value.length() != timezoneOffsetPosition + 1) {
160 throw new ParseException(
161 "Failed to parse timestamp: invalid trailing data \""
162 + value.substring(timezoneOffsetPosition) + "\"", 0);
163 }
164 } else {
165 String offsetValue = value.substring(timezoneOffsetPosition + 1);
166 long offset = parseTimezoneOffset(offsetValue);
167 if (value.charAt(timezoneOffsetPosition) == '+') {
168 seconds -= offset;
169 } else {
170 seconds += offset;
171 }
172 }
173 try {
174 return normalizedTimestamp(seconds, nanos);
175 } catch (IllegalArgumentException e) {
176 throw new ParseException(
177 "Failed to parse timestmap: timestamp is out of range.", 0);
178 }
92 } 179 }
93 180
94 /** 181 /**
95 * Convert Duration to string format. The string format will contains 3, 6, 182 * Convert Duration to string format. The string format will contains 3, 6,
96 * or 9 fractional digits depending on the precision required to represent 183 * or 9 fractional digits depending on the precision required to represent
97 * the exact Duration value. For example: "1s", "1.010s", "1.000000100s", 184 * the exact Duration value. For example: "1s", "1.010s", "1.000000100s",
98 * "-3.100s" The range that can be represented by Duration is from 185 * "-3.100s" The range that can be represented by Duration is from
99 * -315,576,000,000 to +315,576,000,000 inclusive (in seconds). 186 * -315,576,000,000 to +315,576,000,000 inclusive (in seconds).
100 * 187 *
101 * @return The string representation of the given duration. 188 * @return The string representation of the given duration.
102 * @throws IllegalArgumentException if the given duration is not in the valid 189 * @throws IllegalArgumentException if the given duration is not in the valid
103 * range. 190 * range.
104 * @deprecated Use {@link Durations#toString} instead.
105 */ 191 */
106 @Deprecated 192 public static String toString(Duration duration)
107 public static String toString(Duration duration) { 193 throws IllegalArgumentException {
108 return Durations.toString(duration); 194 if (duration.getSeconds() < DURATION_SECONDS_MIN
195 || duration.getSeconds() > DURATION_SECONDS_MAX) {
196 throw new IllegalArgumentException("Duration is out of valid range.");
197 }
198 StringBuilder result = new StringBuilder();
199 long seconds = duration.getSeconds();
200 int nanos = duration.getNanos();
201 if (seconds < 0 || nanos < 0) {
202 if (seconds > 0 || nanos > 0) {
203 throw new IllegalArgumentException(
204 "Invalid duration: seconds value and nanos value must have the same"
205 + "sign.");
206 }
207 result.append("-");
208 seconds = -seconds;
209 nanos = -nanos;
210 }
211 result.append(seconds);
212 if (nanos != 0) {
213 result.append(".");
214 result.append(formatNanos(nanos));
215 }
216 result.append("s");
217 return result.toString();
109 } 218 }
110 219
111 /** 220 /**
112 * Parse from a string to produce a duration. 221 * Parse from a string to produce a duration.
113 * 222 *
114 * @return A Duration parsed from the string. 223 * @return A Duration parsed from the string.
115 * @throws ParseException if parsing fails. 224 * @throws ParseException if parsing fails.
116 * @deprecated Use {@link Durations#parse} instead.
117 */ 225 */
118 @Deprecated
119 public static Duration parseDuration(String value) throws ParseException { 226 public static Duration parseDuration(String value) throws ParseException {
120 return Durations.parse(value); 227 // Must ended with "s".
228 if (value.isEmpty() || value.charAt(value.length() - 1) != 's') {
229 throw new ParseException("Invalid duration string: " + value, 0);
230 }
231 boolean negative = false;
232 if (value.charAt(0) == '-') {
233 negative = true;
234 value = value.substring(1);
235 }
236 String secondValue = value.substring(0, value.length() - 1);
237 String nanoValue = "";
238 int pointPosition = secondValue.indexOf('.');
239 if (pointPosition != -1) {
240 nanoValue = secondValue.substring(pointPosition + 1);
241 secondValue = secondValue.substring(0, pointPosition);
242 }
243 long seconds = Long.parseLong(secondValue);
244 int nanos = nanoValue.isEmpty() ? 0 : parseNanos(nanoValue);
245 if (seconds < 0) {
246 throw new ParseException("Invalid duration string: " + value, 0);
247 }
248 if (negative) {
249 seconds = -seconds;
250 nanos = -nanos;
251 }
252 try {
253 return normalizedDuration(seconds, nanos);
254 } catch (IllegalArgumentException e) {
255 throw new ParseException("Duration value is out of range.", 0);
256 }
121 } 257 }
122 258
123 /** 259 /**
124 * Create a Timestamp from the number of milliseconds elapsed from the epoch. 260 * Create a Timestamp from the number of milliseconds elapsed from the epoch.
125 *
126 * @deprecated Use {@link Timestamps#fromMillis} instead.
127 */ 261 */
128 @Deprecated
129 public static Timestamp createTimestampFromMillis(long milliseconds) { 262 public static Timestamp createTimestampFromMillis(long milliseconds) {
130 return Timestamps.fromMillis(milliseconds); 263 return normalizedTimestamp(milliseconds / MILLIS_PER_SECOND,
264 (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
131 } 265 }
132 266
133 /** 267 /**
134 * Create a Duration from the number of milliseconds. 268 * Create a Duration from the number of milliseconds.
135 *
136 * @deprecated Use {@link Durations#fromMillis} instead.
137 */ 269 */
138 @Deprecated
139 public static Duration createDurationFromMillis(long milliseconds) { 270 public static Duration createDurationFromMillis(long milliseconds) {
140 return Durations.fromMillis(milliseconds); 271 return normalizedDuration(milliseconds / MILLIS_PER_SECOND,
272 (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
141 } 273 }
142 274
143 /** 275 /**
144 * Convert a Timestamp to the number of milliseconds elapsed from the epoch. 276 * Convert a Timestamp to the number of milliseconds elapsed from the epoch.
145 * 277 *
146 * <p>The result will be rounded down to the nearest millisecond. E.g., if the 278 * <p>The result will be rounded down to the nearest millisecond. E.g., if the
147 * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded 279 * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded
148 * to -1 millisecond. 280 * to -1 millisecond.
149 *
150 * @deprecated Use {@link Timestamps#toMillis} instead.
151 */ 281 */
152 @Deprecated
153 public static long toMillis(Timestamp timestamp) { 282 public static long toMillis(Timestamp timestamp) {
154 return Timestamps.toMillis(timestamp); 283 return timestamp.getSeconds() * MILLIS_PER_SECOND + timestamp.getNanos()
284 / NANOS_PER_MILLISECOND;
155 } 285 }
156 286
157 /** 287 /**
158 * Convert a Duration to the number of milliseconds.The result will be 288 * Convert a Duration to the number of milliseconds.The result will be
159 * rounded towards 0 to the nearest millisecond. E.g., if the duration 289 * rounded towards 0 to the nearest millisecond. E.g., if the duration
160 * represents -1 nanosecond, it will be rounded to 0. 290 * represents -1 nanosecond, it will be rounded to 0.
161 *
162 * @deprecated Use {@link Durations#toMillis} instead.
163 */ 291 */
164 @Deprecated
165 public static long toMillis(Duration duration) { 292 public static long toMillis(Duration duration) {
166 return Durations.toMillis(duration); 293 return duration.getSeconds() * MILLIS_PER_SECOND + duration.getNanos()
294 / NANOS_PER_MILLISECOND;
167 } 295 }
168 296
169 /** 297 /**
170 * Create a Timestamp from the number of microseconds elapsed from the epoch. 298 * Create a Timestamp from the number of microseconds elapsed from the epoch.
171 *
172 * @deprecated Use {@link Timestamps#fromMicros} instead.
173 */ 299 */
174 @Deprecated
175 public static Timestamp createTimestampFromMicros(long microseconds) { 300 public static Timestamp createTimestampFromMicros(long microseconds) {
176 return Timestamps.fromMicros(microseconds); 301 return normalizedTimestamp(microseconds / MICROS_PER_SECOND,
302 (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
177 } 303 }
178 304
179 /** 305 /**
180 * Create a Duration from the number of microseconds. 306 * Create a Duration from the number of microseconds.
181 *
182 * @deprecated Use {@link Durations#fromMicros} instead.
183 */ 307 */
184 @Deprecated
185 public static Duration createDurationFromMicros(long microseconds) { 308 public static Duration createDurationFromMicros(long microseconds) {
186 return Durations.fromMicros(microseconds); 309 return normalizedDuration(microseconds / MICROS_PER_SECOND,
310 (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
187 } 311 }
188 312
189 /** 313 /**
190 * Convert a Timestamp to the number of microseconds elapsed from the epoch. 314 * Convert a Timestamp to the number of microseconds elapsed from the epoch.
191 * 315 *
192 * <p>The result will be rounded down to the nearest microsecond. E.g., if the 316 * <p>The result will be rounded down to the nearest microsecond. E.g., if the
193 * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded 317 * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded
194 * to -1 millisecond. 318 * to -1 millisecond.
195 *
196 * @deprecated Use {@link Timestamps#toMicros} instead.
197 */ 319 */
198 @Deprecated
199 public static long toMicros(Timestamp timestamp) { 320 public static long toMicros(Timestamp timestamp) {
200 return Timestamps.toMicros(timestamp); 321 return timestamp.getSeconds() * MICROS_PER_SECOND + timestamp.getNanos()
322 / NANOS_PER_MICROSECOND;
201 } 323 }
202 324
203 /** 325 /**
204 * Convert a Duration to the number of microseconds.The result will be 326 * Convert a Duration to the number of microseconds.The result will be
205 * rounded towards 0 to the nearest microseconds. E.g., if the duration 327 * rounded towards 0 to the nearest microseconds. E.g., if the duration
206 * represents -1 nanosecond, it will be rounded to 0. 328 * represents -1 nanosecond, it will be rounded to 0.
207 *
208 * @deprecated Use {@link Durations#toMicros} instead.
209 */ 329 */
210 @Deprecated
211 public static long toMicros(Duration duration) { 330 public static long toMicros(Duration duration) {
212 return Durations.toMicros(duration); 331 return duration.getSeconds() * MICROS_PER_SECOND + duration.getNanos()
332 / NANOS_PER_MICROSECOND;
213 } 333 }
214 334
215 /** 335 /**
216 * Create a Timestamp from the number of nanoseconds elapsed from the epoch. 336 * Create a Timestamp from the number of nanoseconds elapsed from the epoch.
217 *
218 * @deprecated Use {@link Timestamps#fromNanos} instead.
219 */ 337 */
220 @Deprecated
221 public static Timestamp createTimestampFromNanos(long nanoseconds) { 338 public static Timestamp createTimestampFromNanos(long nanoseconds) {
222 return Timestamps.fromNanos(nanoseconds); 339 return normalizedTimestamp(nanoseconds / NANOS_PER_SECOND,
340 (int) (nanoseconds % NANOS_PER_SECOND));
223 } 341 }
224 342
225 /** 343 /**
226 * Create a Duration from the number of nanoseconds. 344 * Create a Duration from the number of nanoseconds.
227 *
228 * @deprecated Use {@link Durations#fromNanos} instead.
229 */ 345 */
230 @Deprecated
231 public static Duration createDurationFromNanos(long nanoseconds) { 346 public static Duration createDurationFromNanos(long nanoseconds) {
232 return Durations.fromNanos(nanoseconds); 347 return normalizedDuration(nanoseconds / NANOS_PER_SECOND,
348 (int) (nanoseconds % NANOS_PER_SECOND));
233 } 349 }
234 350
235 /** 351 /**
236 * Convert a Timestamp to the number of nanoseconds elapsed from the epoch. 352 * Convert a Timestamp to the number of nanoseconds elapsed from the epoch.
237 *
238 * @deprecated Use {@link Timestamps#toNanos} instead.
239 */ 353 */
240 @Deprecated
241 public static long toNanos(Timestamp timestamp) { 354 public static long toNanos(Timestamp timestamp) {
242 return Timestamps.toNanos(timestamp); 355 return timestamp.getSeconds() * NANOS_PER_SECOND + timestamp.getNanos();
243 } 356 }
244 357
245 /** 358 /**
246 * Convert a Duration to the number of nanoseconds. 359 * Convert a Duration to the number of nanoseconds.
247 *
248 * @deprecated Use {@link Durations#toNanos} instead.
249 */ 360 */
250 @Deprecated
251 public static long toNanos(Duration duration) { 361 public static long toNanos(Duration duration) {
252 return Durations.toNanos(duration); 362 return duration.getSeconds() * NANOS_PER_SECOND + duration.getNanos();
253 } 363 }
254 364
255 /** 365 /**
256 * Get the current time. 366 * Get the current time.
257 *
258 * @deprecated Use {@code Timestamps.fromMillis(System.currentTimeMillis())} i nstead.
259 */ 367 */
260 @Deprecated
261 public static Timestamp getCurrentTime() { 368 public static Timestamp getCurrentTime() {
262 return Timestamps.fromMillis(System.currentTimeMillis()); 369 return createTimestampFromMillis(System.currentTimeMillis());
263 } 370 }
264 371
265 /** 372 /**
266 * Get the epoch. 373 * Get the epoch.
267 *
268 * @deprecated Use {@code Timestamps.fromMillis(0)} instead.
269 */ 374 */
270 @Deprecated
271 public static Timestamp getEpoch() { 375 public static Timestamp getEpoch() {
272 return Timestamp.getDefaultInstance(); 376 return Timestamp.getDefaultInstance();
273 } 377 }
274 378
275 /** 379 /**
276 * Calculate the difference between two timestamps. 380 * Calculate the difference between two timestamps.
277 *
278 * @deprecated Use {@link Timestamps#between} instead.
279 */ 381 */
280 @Deprecated
281 public static Duration distance(Timestamp from, Timestamp to) { 382 public static Duration distance(Timestamp from, Timestamp to) {
282 return Timestamps.between(from, to); 383 return normalizedDuration(to.getSeconds() - from.getSeconds(),
384 to.getNanos() - from.getNanos());
283 } 385 }
284 386
285 /** 387 /**
286 * Add a duration to a timestamp. 388 * Add a duration to a timestamp.
287 *
288 * @deprecated Use {@link Timestamps#add} instead.
289 */ 389 */
290 @Deprecated
291 public static Timestamp add(Timestamp start, Duration length) { 390 public static Timestamp add(Timestamp start, Duration length) {
292 return Timestamps.add(start, length); 391 return normalizedTimestamp(start.getSeconds() + length.getSeconds(),
392 start.getNanos() + length.getNanos());
293 } 393 }
294 394
295 /** 395 /**
296 * Subtract a duration from a timestamp. 396 * Subtract a duration from a timestamp.
297 *
298 * @deprecated Use {@link Timestamps#subtract} instead.
299 */ 397 */
300 @Deprecated
301 public static Timestamp subtract(Timestamp start, Duration length) { 398 public static Timestamp subtract(Timestamp start, Duration length) {
302 return Timestamps.subtract(start, length); 399 return normalizedTimestamp(start.getSeconds() - length.getSeconds(),
400 start.getNanos() - length.getNanos());
303 } 401 }
304 402
305 /** 403 /**
306 * Add two durations. 404 * Add two durations.
307 *
308 * @deprecated Use {@link Durations#add} instead.
309 */ 405 */
310 @Deprecated
311 public static Duration add(Duration d1, Duration d2) { 406 public static Duration add(Duration d1, Duration d2) {
312 return Durations.add(d1, d2); 407 return normalizedDuration(d1.getSeconds() + d2.getSeconds(),
408 d1.getNanos() + d2.getNanos());
313 } 409 }
314 410
315 /** 411 /**
316 * Subtract a duration from another. 412 * Subtract a duration from another.
317 *
318 * @deprecated Use {@link Durations#subtract} instead.
319 */ 413 */
320 @Deprecated
321 public static Duration subtract(Duration d1, Duration d2) { 414 public static Duration subtract(Duration d1, Duration d2) {
322 return Durations.subtract(d1, d2); 415 return normalizedDuration(d1.getSeconds() - d2.getSeconds(),
416 d1.getNanos() - d2.getNanos());
323 } 417 }
324 418
325 // Multiplications and divisions. 419 // Multiplications and divisions.
326 420
327 // TODO(kak): Delete this.
328 public static Duration multiply(Duration duration, double times) { 421 public static Duration multiply(Duration duration, double times) {
329 double result = duration.getSeconds() * times + duration.getNanos() * times / 1000000000.0; 422 double result = duration.getSeconds() * times + duration.getNanos() * times
423 / 1000000000.0;
330 if (result < Long.MIN_VALUE || result > Long.MAX_VALUE) { 424 if (result < Long.MIN_VALUE || result > Long.MAX_VALUE) {
331 throw new IllegalArgumentException("Result is out of valid range."); 425 throw new IllegalArgumentException("Result is out of valid range.");
332 } 426 }
333 long seconds = (long) result; 427 long seconds = (long) result;
334 int nanos = (int) ((result - seconds) * 1000000000); 428 int nanos = (int) ((result - seconds) * 1000000000);
335 return normalizedDuration(seconds, nanos); 429 return normalizedDuration(seconds, nanos);
336 } 430 }
337 431
338 // TODO(kak): Delete this.
339 public static Duration divide(Duration duration, double value) { 432 public static Duration divide(Duration duration, double value) {
340 return multiply(duration, 1.0 / value); 433 return multiply(duration, 1.0 / value);
341 } 434 }
342 435
343 // TODO(kak): Delete this.
344 public static Duration multiply(Duration duration, long times) { 436 public static Duration multiply(Duration duration, long times) {
345 return createDurationFromBigInteger(toBigInteger(duration).multiply(toBigInt eger(times))); 437 return createDurationFromBigInteger(
438 toBigInteger(duration).multiply(toBigInteger(times)));
346 } 439 }
347 440
348 // TODO(kak): Delete this.
349 public static Duration divide(Duration duration, long times) { 441 public static Duration divide(Duration duration, long times) {
350 return createDurationFromBigInteger(toBigInteger(duration).divide(toBigInteg er(times))); 442 return createDurationFromBigInteger(
443 toBigInteger(duration).divide(toBigInteger(times)));
351 } 444 }
352 445
353 // TODO(kak): Delete this.
354 public static long divide(Duration d1, Duration d2) { 446 public static long divide(Duration d1, Duration d2) {
355 return toBigInteger(d1).divide(toBigInteger(d2)).longValue(); 447 return toBigInteger(d1).divide(toBigInteger(d2)).longValue();
356 } 448 }
357 449
358 // TODO(kak): Delete this.
359 public static Duration remainder(Duration d1, Duration d2) { 450 public static Duration remainder(Duration d1, Duration d2) {
360 return createDurationFromBigInteger(toBigInteger(d1).remainder(toBigInteger( d2))); 451 return createDurationFromBigInteger(
452 toBigInteger(d1).remainder(toBigInteger(d2)));
361 } 453 }
362 454
363 private static final BigInteger NANOS_PER_SECOND_BIG_INTEGER = 455 private static final BigInteger NANOS_PER_SECOND_BIG_INTEGER =
364 new BigInteger(String.valueOf(NANOS_PER_SECOND)); 456 new BigInteger(String.valueOf(NANOS_PER_SECOND));
365 457
366 private static BigInteger toBigInteger(Duration duration) { 458 private static BigInteger toBigInteger(Duration duration) {
367 return toBigInteger(duration.getSeconds()) 459 return toBigInteger(duration.getSeconds())
368 .multiply(NANOS_PER_SECOND_BIG_INTEGER) 460 .multiply(NANOS_PER_SECOND_BIG_INTEGER)
369 .add(toBigInteger(duration.getNanos())); 461 .add(toBigInteger(duration.getNanos()));
370 } 462 }
371 463
372 private static BigInteger toBigInteger(long value) { 464 private static BigInteger toBigInteger(long value) {
373 return new BigInteger(String.valueOf(value)); 465 return new BigInteger(String.valueOf(value));
374 } 466 }
375 467
376 private static Duration createDurationFromBigInteger(BigInteger value) { 468 private static Duration createDurationFromBigInteger(BigInteger value) {
377 long seconds = value.divide(new BigInteger(String.valueOf(NANOS_PER_SECOND)) ).longValue(); 469 long seconds = value.divide(
378 int nanos = value.remainder(new BigInteger(String.valueOf(NANOS_PER_SECOND)) ).intValue(); 470 new BigInteger(String.valueOf(NANOS_PER_SECOND))).longValue();
471 int nanos = value.remainder(
472 new BigInteger(String.valueOf(NANOS_PER_SECOND))).intValue();
379 return normalizedDuration(seconds, nanos); 473 return normalizedDuration(seconds, nanos);
474
380 } 475 }
381 476
382 private static Duration normalizedDuration(long seconds, int nanos) { 477 private static Duration normalizedDuration(long seconds, int nanos) {
383 if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) { 478 if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
384 seconds += nanos / NANOS_PER_SECOND; 479 seconds += nanos / NANOS_PER_SECOND;
385 nanos %= NANOS_PER_SECOND; 480 nanos %= NANOS_PER_SECOND;
386 } 481 }
387 if (seconds > 0 && nanos < 0) { 482 if (seconds > 0 && nanos < 0) {
388 nanos += NANOS_PER_SECOND; 483 nanos += NANOS_PER_SECOND;
389 seconds -= 1; 484 seconds -= 1;
390 } 485 }
391 if (seconds < 0 && nanos > 0) { 486 if (seconds < 0 && nanos > 0) {
392 nanos -= NANOS_PER_SECOND; 487 nanos -= NANOS_PER_SECOND;
393 seconds += 1; 488 seconds += 1;
394 } 489 }
395 if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) { 490 if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) {
396 throw new IllegalArgumentException("Duration is out of valid range."); 491 throw new IllegalArgumentException("Duration is out of valid range.");
397 } 492 }
398 return Duration.newBuilder().setSeconds(seconds).setNanos(nanos).build(); 493 return Duration.newBuilder().setSeconds(seconds).setNanos(nanos).build();
399 } 494 }
495
496 private static Timestamp normalizedTimestamp(long seconds, int nanos) {
497 if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
498 seconds += nanos / NANOS_PER_SECOND;
499 nanos %= NANOS_PER_SECOND;
500 }
501 if (nanos < 0) {
502 nanos += NANOS_PER_SECOND;
503 seconds -= 1;
504 }
505 if (seconds < TIMESTAMP_SECONDS_MIN || seconds > TIMESTAMP_SECONDS_MAX) {
506 throw new IllegalArgumentException("Timestamp is out of valid range.");
507 }
508 return Timestamp.newBuilder().setSeconds(seconds).setNanos(nanos).build();
509 }
510
511 /**
512 * Format the nano part of a timestamp or a duration.
513 */
514 private static String formatNanos(int nanos) {
515 assert nanos >= 1 && nanos <= 999999999;
516 // Determine whether to use 3, 6, or 9 digits for the nano part.
517 if (nanos % NANOS_PER_MILLISECOND == 0) {
518 return String.format("%1$03d", nanos / NANOS_PER_MILLISECOND);
519 } else if (nanos % NANOS_PER_MICROSECOND == 0) {
520 return String.format("%1$06d", nanos / NANOS_PER_MICROSECOND);
521 } else {
522 return String.format("%1$09d", nanos);
523 }
524 }
525
526 private static int parseNanos(String value) throws ParseException {
527 int result = 0;
528 for (int i = 0; i < 9; ++i) {
529 result = result * 10;
530 if (i < value.length()) {
531 if (value.charAt(i) < '0' || value.charAt(i) > '9') {
532 throw new ParseException("Invalid nanosecnds.", 0);
533 }
534 result += value.charAt(i) - '0';
535 }
536 }
537 return result;
538 }
539
540 private static long parseTimezoneOffset(String value) throws ParseException {
541 int pos = value.indexOf(':');
542 if (pos == -1) {
543 throw new ParseException("Invalid offset value: " + value, 0);
544 }
545 String hours = value.substring(0, pos);
546 String minutes = value.substring(pos + 1);
547 return (Long.parseLong(hours) * 60 + Long.parseLong(minutes)) * 60;
548 }
400 } 549 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698