Skip to content

Commit ff3be6f

Browse files
committed
Change Timestamp to not use jodatime classes for parsing/formatting
1 parent 4d62a9c commit ff3be6f

1 file changed

Lines changed: 16 additions & 43 deletions

File tree

google-cloud-core/src/main/java/com/google/cloud/Timestamp.java

Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,20 @@
1818

1919
import static com.google.common.base.Preconditions.checkArgument;
2020

21-
import com.google.common.base.Strings;
2221
import com.google.protobuf.util.Timestamps;
2322
import java.io.Serializable;
2423
import java.util.Date;
2524
import java.util.Objects;
2625
import java.util.concurrent.TimeUnit;
27-
import java.util.regex.Matcher;
28-
import java.util.regex.Pattern;
29-
import org.joda.time.chrono.GregorianChronology;
30-
import org.joda.time.format.DateTimeFormatter;
31-
import org.joda.time.format.ISODateTimeFormat;
26+
import org.threeten.bp.Instant;
27+
import org.threeten.bp.LocalDateTime;
28+
import org.threeten.bp.ZoneOffset;
29+
import org.threeten.bp.chrono.IsoChronology;
30+
import org.threeten.bp.format.DateTimeFormatter;
3231

3332
/**
34-
* Represents a timestamp with nanosecond precision. Timestamps cover the range
35-
* [0001-01-01, 9999-12-31].
33+
* Represents a timestamp with nanosecond precision. Timestamps cover the range [0001-01-01,
34+
* 9999-12-31].
3635
*
3736
* <p>{@code Timestamp} instances are immutable.
3837
*/
@@ -47,13 +46,8 @@ public final class Timestamp implements Comparable<Timestamp>, Serializable {
4746
public static final Timestamp MAX_VALUE =
4847
new Timestamp(253402300799L, (int) TimeUnit.SECONDS.toNanos(1) - 1);
4948

50-
/** Regexp to split timestamps into date-hour-minute-second and fractional second components. */
51-
private static final Pattern FORMAT_REGEXP = Pattern.compile("([^\\.]*)(\\.\\d{0,9})?Z");
52-
53-
private static final long NANOS_PER_SECOND = TimeUnit.SECONDS.toNanos(1);
54-
5549
private static final DateTimeFormatter format =
56-
ISODateTimeFormat.dateHourMinuteSecond().withChronology(GregorianChronology.getInstanceUTC());
50+
DateTimeFormatter.ISO_LOCAL_DATE_TIME.withChronology(IsoChronology.INSTANCE);
5751

5852
private final long seconds;
5953
private final int nanos;
@@ -85,8 +79,8 @@ public static Timestamp ofTimeSecondsAndNanos(long seconds, int nanos) {
8579
*/
8680
public static Timestamp ofTimeMicroseconds(long microseconds) {
8781
long seconds = TimeUnit.MICROSECONDS.toSeconds(microseconds);
88-
int nanos = (int) TimeUnit.MICROSECONDS.toNanos(
89-
microseconds - TimeUnit.SECONDS.toMicros(seconds));
82+
int nanos =
83+
(int) TimeUnit.MICROSECONDS.toNanos(microseconds - TimeUnit.SECONDS.toMicros(seconds));
9084
checkArgument(
9185
Timestamps.isValid(seconds, nanos), "timestamp out of range: %s, %s", seconds, nanos);
9286
return new Timestamp(seconds, nanos);
@@ -101,10 +95,7 @@ public static Timestamp of(Date date) {
10195
return ofTimeMicroseconds(TimeUnit.MILLISECONDS.toMicros(date.getTime()));
10296
}
10397

104-
105-
/**
106-
* Creates an instance with current time.
107-
*/
98+
/** Creates an instance with current time. */
10899
public static Timestamp now() {
109100
java.sql.Timestamp date = new java.sql.Timestamp(System.currentTimeMillis());
110101
return of(date);
@@ -148,9 +139,7 @@ public int compareTo(Timestamp other) {
148139
return r;
149140
}
150141

151-
/**
152-
* Creates an instance of Timestamp from {@code com.google.protobuf.Timestamp}.
153-
*/
142+
/** Creates an instance of Timestamp from {@code com.google.protobuf.Timestamp}. */
154143
public static Timestamp fromProto(com.google.protobuf.Timestamp proto) {
155144
return new Timestamp(proto.getSeconds(), proto.getNanos());
156145
}
@@ -168,28 +157,12 @@ public com.google.protobuf.Timestamp toProto() {
168157
* the timezone offset (always ends in "Z").
169158
*/
170159
public static Timestamp parseTimestamp(String timestamp) {
171-
Matcher matcher = FORMAT_REGEXP.matcher(timestamp);
172-
if (!matcher.matches()) {
173-
throw new IllegalArgumentException("Cannot parse input: " + timestamp);
174-
}
175-
String secondsPart = matcher.group(1);
176-
String nanosPart = matcher.group(2);
177-
long seconds;
178-
seconds = format.parseMillis(secondsPart) / 1000;
179-
int nanos = 0;
180-
if (nanosPart != null) {
181-
String padded = Strings.padEnd(nanosPart.substring(1), 9, '0');
182-
nanos = Integer.parseInt(padded);
183-
if (nanos >= TimeUnit.SECONDS.toNanos(1)) {
184-
throw new IllegalArgumentException(
185-
"Cannot parse input: " + timestamp + " (nanos out of range)");
186-
}
187-
}
188-
return ofTimeSecondsAndNanos(seconds, nanos);
160+
Instant instant = Instant.parse(timestamp);
161+
return ofTimeSecondsAndNanos(instant.getEpochSecond(), instant.getNano());
189162
}
190163

191-
StringBuilder toString(StringBuilder b) {
192-
format.printTo(b, seconds * 1000);
164+
private StringBuilder toString(StringBuilder b) {
165+
format.formatTo(LocalDateTime.ofEpochSecond(seconds, 0, ZoneOffset.UTC), b);
193166
if (nanos != 0) {
194167
b.append(String.format(".%09d", nanos));
195168
}

0 commit comments

Comments
 (0)