Skip to content

Commit d8c62aa

Browse files
committed
feat(data): add until time argument skewing
During building the Request instance via RequestBuilder, we need to skew the time of an until argument a bit. - For Day granularity, it's necessary to include the complete given day. - For Second granularity, it's necessary to add second to avoid exclusion of elements because of micro/nanosecond timestamps in databases. - For Lenient, we want to the complete day, too - that's why it's lenient. Adds a test for the skewing.
1 parent 7fcec13 commit d8c62aa

2 files changed

Lines changed: 76 additions & 0 deletions

File tree

xoai-data-provider/src/main/java/io/gdcc/xoai/dataprovider/repository/RepositoryConfiguration.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,14 @@
1717
import io.gdcc.xoai.xml.WriterContext;
1818

1919
import java.time.Instant;
20+
import java.time.LocalDate;
21+
import java.time.LocalTime;
22+
import java.time.ZoneId;
23+
import java.time.ZoneOffset;
2024
import java.util.ArrayList;
2125
import java.util.Collections;
2226
import java.util.List;
27+
import java.util.Objects;
2328

2429
import static java.util.Arrays.asList;
2530

@@ -87,6 +92,28 @@ public Granularity getGranularity() {
8792
throw new InternalOAIException("Granularity has not been configured");
8893
return granularity;
8994
}
95+
96+
/**
97+
* Skew an instant to end of day (granularity Day or Lenient) or by a second (granularity Second).
98+
* This is necessary for two reasons:
99+
* 1. Day granularity must be inclusive, so we can't leave an "until" at start of day.
100+
* 2. Lenient granularity must work like day in this case, as we cannot be sure which is meant.
101+
* 3. Second granularity needs skipping a second to avoid not returning {@link io.gdcc.xoai.dataprovider.model.Item}
102+
* from the repository that use an SQL timestamp with nanosecond granularity (so ...:00.5829 would not be
103+
* found when asking for all until ...:00.000)
104+
*
105+
* @param timestamp The timestamp to skew a little
106+
* @return The skewed timestamp
107+
*/
108+
public Instant skewUntil(Instant timestamp) {
109+
Objects.requireNonNull(timestamp, "Skewing an 'until' date must not be used with null");
110+
switch (getGranularity()) {
111+
case Day:
112+
case Lenient: return LocalDate.ofInstant(timestamp, ZoneId.of("UTC")).atTime(LocalTime.MAX).toInstant(ZoneOffset.UTC);
113+
case Second: return timestamp.plusSeconds(1);
114+
default: return timestamp;
115+
}
116+
}
90117

91118
public DeletedRecord getDeleteMethod() {
92119
if (deleteMethod == null)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.gdcc.xoai.dataprovider.repository;
2+
3+
import io.gdcc.xoai.model.oaipmh.Granularity;
4+
import io.gdcc.xoai.services.api.DateProvider;
5+
import org.junit.jupiter.params.ParameterizedTest;
6+
import org.junit.jupiter.params.provider.Arguments;
7+
import org.junit.jupiter.params.provider.MethodSource;
8+
9+
import java.time.Instant;
10+
import java.time.LocalDateTime;
11+
import java.time.ZoneOffset;
12+
import java.util.stream.Stream;
13+
14+
import static org.junit.jupiter.api.Assertions.*;
15+
16+
class RepositoryConfigurationTest {
17+
18+
private static Stream<Arguments> skews() {
19+
return Stream.of(
20+
Arguments.of(
21+
LocalDateTime.of(2022, 5, 19,10,0,0, 123).toInstant(ZoneOffset.UTC),
22+
Granularity.Second,
23+
"2022-05-19T10:00:01Z",
24+
"2022-05-19T10:00:01Z"
25+
),
26+
Arguments.of(
27+
LocalDateTime.of(2022, 5, 19,10,0,0, 123).toInstant(ZoneOffset.UTC),
28+
Granularity.Day,
29+
"2022-05-19",
30+
"2022-05-19T23:59:59Z"
31+
)
32+
);
33+
}
34+
35+
@ParameterizedTest
36+
@MethodSource("skews")
37+
void skewUntil(Instant timestamp, Granularity granularity, String expected, String expectedAtSecondGranularity) {
38+
// given
39+
RepositoryConfiguration config = RepositoryConfiguration.defaults().withGranularity(granularity);
40+
41+
// when
42+
Instant skewedTime = config.skewUntil(timestamp);
43+
44+
// then
45+
assertTrue(skewedTime.isAfter(timestamp));
46+
assertEquals(expected, DateProvider.format(skewedTime, granularity));
47+
assertEquals(expectedAtSecondGranularity, DateProvider.format(skewedTime, Granularity.Second));
48+
}
49+
}

0 commit comments

Comments
 (0)