Skip to content

Commit f9e6383

Browse files
author
Sagar Agarwal
committed
resolved cl comments
1 parent 1e5f593 commit f9e6383

File tree

13 files changed

+290
-214
lines changed

13 files changed

+290
-214
lines changed

google-cloud-spanner/pom.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -364,11 +364,6 @@
364364
<version>${graal-sdk.version}</version>
365365
<scope>provided</scope>
366366
</dependency>
367-
<dependency>
368-
<groupId>com.google.auto.value</groupId>
369-
<artifactId>auto-value</artifactId>
370-
<version>1.10.4</version>
371-
</dependency>
372367

373368
<!-- Test dependencies -->
374369
<dependency>

google-cloud-spanner/src/main/java/com/google/cloud/spanner/GrpcStruct.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ protected Date getDateInternal(int columnIndex) {
513513
return (Date) rowData.get(columnIndex);
514514
}
515515

516+
@Override
516517
protected Interval getIntervalInternal(int columnIndex) {
517518
ensureDecoded(columnIndex);
518519
return (Interval) rowData.get(columnIndex);
Lines changed: 110 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2021 Google LLC
2+
* Copyright 2024 Google LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
1616

1717
package com.google.cloud.spanner;
1818

19-
import com.google.auto.value.AutoValue;
2019
import com.google.errorprone.annotations.Immutable;
2120
import java.io.Serializable;
2221
import java.math.BigDecimal;
@@ -25,9 +24,21 @@
2524
import java.util.regex.Pattern;
2625
import org.jetbrains.annotations.NotNull;
2726

28-
@AutoValue
27+
/**
28+
* Represents the time duration as a combination of months, days and nanoseconds. Nanoseconds are
29+
* broken into two components microseconds and nanoFractions, where nanoFractions can range from
30+
* [-999, 999]. Internally, Spanner supports Interval value with the following range of individual
31+
* fields: months: [-120000, 120000] days: [-3660000, 3660000] nanoseconds: [-316224000000000000000,
32+
* 316224000000000000000] Interval value created outside the specified domain will return error when
33+
* sent to Spanner backend.
34+
*/
2935
@Immutable
30-
public abstract class Interval implements Serializable {
36+
public class Interval implements Serializable {
37+
private final int months;
38+
private final int days;
39+
private final long microseconds;
40+
private final short nanoFractions;
41+
3142
public static final long MONTHS_PER_YEAR = 12;
3243
public static final long DAYS_PER_MONTH = 30;
3344
public static final long HOURS_PER_DAY = 24;
@@ -48,103 +59,110 @@ public abstract class Interval implements Serializable {
4859
BigInteger.valueOf(MICROS_PER_MINUTE * NANOS_PER_MICRO);
4960
public static final BigInteger NANOS_PER_HOUR =
5061
BigInteger.valueOf(MICROS_PER_HOUR * NANOS_PER_MICRO);
62+
public static final Interval ZERO = Interval.builder().build();
5163

64+
/** Regex to ISO8601 formatted interval. `P[n]Y[n]M[n]DT[n]H[n]M[n(.[fraction])]S` */
5265
private static final Pattern INTERVAL_PATTERN =
5366
Pattern.compile(
5467
"^P(?!$)(-?\\d+Y)?(-?\\d+M)?(-?\\d+D)?(T(?=-?.?\\d)(-?\\d+H)?(-?\\d+M)?(-?((\\d+(\\.\\d{1,9})?)|(\\.\\d{1,9}))S)?)?$");
5568

69+
private Interval(int months, int days, long microseconds, short nanoFractions) {
70+
this.months = months;
71+
this.days = days;
72+
this.microseconds = microseconds;
73+
this.nanoFractions = nanoFractions;
74+
}
75+
5676
/** Returns the months component of the interval. */
57-
public abstract int months();
77+
public int getMonths() {
78+
return months;
79+
}
5880

5981
/** Returns the days component of the interval. */
60-
public abstract int days();
82+
public int getDays() {
83+
return days;
84+
}
6185

6286
/** Returns the microseconds component of the interval. */
63-
public abstract long micros();
87+
public long getMicroseconds() {
88+
return microseconds;
89+
}
6490

6591
/** Returns the nanoFractions component of the interval. */
66-
public abstract short nanoFractions();
67-
68-
public static Builder builder() {
69-
return new AutoValue_Interval.Builder();
92+
public short getNanoFractions() {
93+
return nanoFractions;
7094
}
7195

72-
/** Returns the nanoseconds component of the interval. */
73-
public BigInteger nanos() {
74-
return BigInteger.valueOf(micros())
96+
/** Returns the microseconds and nanoFraction of the Interval combined as nanoseconds. */
97+
public BigInteger getNanoseconds() {
98+
return BigInteger.valueOf(getMicroseconds())
7599
.multiply(BigInteger.valueOf(NANOS_PER_MICRO))
76-
.add(BigInteger.valueOf(nanoFractions()));
100+
.add(BigInteger.valueOf(getNanoFractions()));
101+
}
102+
103+
public static Builder builder() {
104+
return new Builder();
77105
}
78106

79-
/** Returns the total microseconds represented by the interval. */
80-
public long getAsMicros() {
81-
return months() * MICROS_PER_MONTH + days() * MICROS_PER_DAY + micros();
107+
/**
108+
* Returns the total microseconds represented by the interval. It combines months, days and
109+
* microseconds fields of the interval into microseconds.
110+
*/
111+
public long getAsMicroseconds() {
112+
return Math.addExact(
113+
Math.addExact(
114+
Math.multiplyExact(getMonths(), MICROS_PER_MONTH),
115+
Math.multiplyExact(getDays(), MICROS_PER_DAY)),
116+
getMicroseconds());
82117
}
83118

84-
/** Returns the total nanoseconds represented by the interval. */
85-
public BigInteger getAsNanos() {
86-
return BigInteger.valueOf(getAsMicros())
119+
/**
120+
* Returns the total nanoseconds represented by the interval. It combines months, days,
121+
* microseconds and nanoFractions fields of the interval into nanoseconds.
122+
*/
123+
public BigInteger getAsNanoseconds() {
124+
return BigInteger.valueOf(getAsMicroseconds())
87125
.multiply(BigInteger.valueOf(NANOS_PER_MICRO))
88-
.add(BigInteger.valueOf(nanoFractions()));
126+
.add(BigInteger.valueOf(getNanoFractions()));
89127
}
90128

91129
/** Creates an interval with specified number of months. */
92130
public static Interval ofMonths(int months) {
93-
return builder().setMonths(months).setDays(0).setMicros(0).setNanoFractions((short) 0).build();
131+
return builder().setMonths(months).build();
94132
}
95133

96134
/** Creates an interval with specified number of days. */
97135
public static Interval ofDays(int days) {
98-
return builder().setMonths(0).setDays(days).setMicros(0).setNanoFractions((short) 0).build();
136+
return builder().setDays(days).build();
99137
}
100138

101139
/** Creates an interval with specified number of seconds. */
102140
public static Interval ofSeconds(long seconds) {
103-
return builder()
104-
.setMonths(0)
105-
.setDays(0)
106-
.setMicros(seconds * MICROS_PER_SECOND)
107-
.setNanoFractions((short) 0)
108-
.build();
141+
return builder().setMicroseconds(seconds * MICROS_PER_SECOND).build();
109142
}
110143

111144
/** Creates an interval with specified number of milliseconds. */
112145
public static Interval ofMilliseconds(long milliseconds) {
113-
return builder()
114-
.setMonths(0)
115-
.setDays(0)
116-
.setMicros(milliseconds * MICROS_PER_MILLI)
117-
.setNanoFractions((short) 0)
118-
.build();
146+
return builder().setMicroseconds(milliseconds * MICROS_PER_MILLI).build();
119147
}
120148

121149
/** Creates an interval with specified number of microseconds. */
122-
public static Interval ofMicros(long micros) {
123-
return builder().months(0).days(0).micros(micros).nanoFractions((short) 0).build();
150+
public static Interval ofMicroseconds(long micros) {
151+
return builder().setMicroseconds(micros).build();
124152
}
125153

126154
/** Creates an interval with specified number of nanoseconds. */
127-
public static Interval ofNanos(@NotNull BigInteger nanos) {
155+
public static Interval ofNanoseconds(@NotNull BigInteger nanos) {
128156
BigInteger micros = nanos.divide(BigInteger.valueOf(NANOS_PER_MICRO));
129157
BigInteger nanoFractions = nanos.subtract(micros.multiply(BigInteger.valueOf(NANOS_PER_MICRO)));
130158
long microsValue = micros.longValueExact();
131159
short nanoFractionsValue = nanoFractions.shortValueExact();
132-
return builder()
133-
.setMonths(0)
134-
.setDays(0)
135-
.setMicros(microsValue)
136-
.setNanoFractions(nanoFractionsValue)
137-
.build();
160+
return builder().setMicroseconds(microsValue).setNanoFractions(nanoFractionsValue).build();
138161
}
139162

140163
/** Creates an interval with specified number of months, days and microseconds. */
141164
public static Interval fromMonthsDaysMicros(int months, int days, long micros) {
142-
return builder()
143-
.setMonths(months)
144-
.setDays(days)
145-
.setMicros(micros)
146-
.setNanoFractions((short) 0)
147-
.build();
165+
return builder().setMonths(months).setDays(days).setMicroseconds(micros).build();
148166
}
149167

150168
/** Creates an interval with specified number of months, days and nanoseconds. */
@@ -157,7 +175,7 @@ public static Interval fromMonthsDaysNanos(int months, int days, BigInteger nano
157175
return builder()
158176
.setMonths(months)
159177
.setDays(days)
160-
.setMicros(micros)
178+
.setMicroseconds(micros)
161179
.setNanoFractions(nanoFractions)
162180
.build();
163181
}
@@ -195,17 +213,21 @@ public static Interval parseFromString(String interval) {
195213
return Interval.builder()
196214
.setMonths(Math.toIntExact(totalMonths))
197215
.setDays(Math.toIntExact(days))
198-
.setMicros(totalMicros.longValueExact())
216+
.setMicroseconds(totalMicros.longValueExact())
199217
.setNanoFractions(nanoFractions.shortValueExact())
200218
.build();
201219
}
202220

203221
/** Converts Interval to ISO8601 Duration Formatted String. */
204-
public String ToISO8601() {
222+
public String toISO8601() {
223+
if (this.equals(ZERO)) {
224+
return "P0Y";
225+
}
226+
205227
StringBuilder result = new StringBuilder();
206228
result.append("P");
207229

208-
long months = this.months();
230+
long months = this.getMonths();
209231
long years = months / MONTHS_PER_YEAR;
210232
months = months - years * MONTHS_PER_YEAR;
211233

@@ -217,11 +239,11 @@ public String ToISO8601() {
217239
result.append(String.format("%dM", months));
218240
}
219241

220-
if (this.days() != 0) {
221-
result.append(String.format("%dD", this.days()));
242+
if (this.getDays() != 0) {
243+
result.append(String.format("%dD", this.getDays()));
222244
}
223245

224-
BigInteger nanos = this.nanos();
246+
BigInteger nanos = this.getNanoseconds();
225247
BigInteger zero = BigInteger.valueOf(0);
226248
if (nanos.compareTo(zero) != 0) {
227249
result.append("T");
@@ -245,16 +267,12 @@ public String ToISO8601() {
245267
}
246268
}
247269

248-
if (result.length() == 1) {
249-
result.append("0Y");
250-
}
251-
252270
return result.toString();
253271
}
254272

255-
/** Creates an interval which representing 0-duration. */
256-
public static Interval zeroInterval() {
257-
return builder().setMonths(0).setDays(0).setMicros(0).setNanoFractions((short) 0).build();
273+
@Override
274+
public String toString() {
275+
return toISO8601();
258276
}
259277

260278
@Override
@@ -264,53 +282,56 @@ public boolean equals(Object rhs) {
264282
}
265283

266284
Interval anotherInterval = (Interval) rhs;
267-
return months() == anotherInterval.months()
268-
&& days() == anotherInterval.days()
269-
&& nanos().equals(anotherInterval.nanos());
285+
return getMonths() == anotherInterval.getMonths()
286+
&& getDays() == anotherInterval.getDays()
287+
&& getNanoseconds().equals(anotherInterval.getNanoseconds());
270288
}
271289

272290
@Override
273291
public int hashCode() {
274292
int result = 17;
275-
result = 31 * result + Long.valueOf(months()).hashCode();
276-
result = 31 * result + Long.valueOf(days()).hashCode();
277-
result = 31 * result + nanos().hashCode();
293+
result = 31 * result + Long.valueOf(getMonths()).hashCode();
294+
result = 31 * result + Long.valueOf(getDays()).hashCode();
295+
result = 31 * result + getNanoseconds().hashCode();
278296
return result;
279297
}
280298

281-
@AutoValue.Builder
282-
public abstract static class Builder {
283-
abstract Builder months(int months);
284-
285-
abstract Builder days(int days);
299+
public static class Builder {
300+
private int months = 0;
301+
private int days = 0;
302+
private long microseconds = 0;
303+
private short nanoFractions = 0;
286304

287-
abstract Builder micros(long micros);
288-
289-
abstract Builder nanoFractions(short nanoFractions);
290-
291-
public Builder setMonths(int months) {
292-
return months(months);
305+
Builder setMonths(int months) {
306+
this.months = months;
307+
return this;
293308
}
294309

295-
public Builder setDays(int days) {
296-
return days(days);
310+
Builder setDays(int days) {
311+
this.days = days;
312+
return this;
297313
}
298314

299-
public Builder setMicros(long micros) {
300-
return micros(micros);
315+
Builder setMicroseconds(long microseconds) {
316+
this.microseconds = microseconds;
317+
return this;
301318
}
302319

303-
public Builder setNanoFractions(short nanoFractions) {
320+
Builder setNanoFractions(short nanoFractions) {
304321
if (nanoFractions <= -NANOS_PER_MICRO || nanoFractions >= NANOS_PER_MICRO) {
305322
throw SpannerExceptionFactory.newSpannerException(
306323
ErrorCode.INVALID_ARGUMENT,
307324
String.format(
308325
"NanoFractions must be between:[-%d, %d]",
309326
NANOS_PER_MICRO - 1, NANOS_PER_MICRO - 1));
310327
}
311-
return nanoFractions(nanoFractions);
328+
329+
this.nanoFractions = nanoFractions;
330+
return this;
312331
}
313332

314-
public abstract Interval build();
333+
public Interval build() {
334+
return new Interval(months, days, microseconds, nanoFractions);
335+
}
315336
}
316337
}

0 commit comments

Comments
 (0)