use special enum for DateBucket units

Preparation step for having custom intervals.
This commit is contained in:
2020-09-27 17:06:27 +02:00
parent 78a0b7d70b
commit 10155f9cdb
9 changed files with 82 additions and 90 deletions

View File

@@ -1,6 +1,5 @@
package org.lucares.pdb.datastore.internal; package org.lucares.pdb.datastore.internal;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@@ -8,11 +7,12 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import org.lucares.pdb.api.DateTimeRange; import org.lucares.pdb.api.DateTimeRange;
import org.lucares.utils.DateBucketUnit;
import org.lucares.utils.LongToDateBucket; import org.lucares.utils.LongToDateBucket;
public class DateIndexExtension { public class DateIndexExtension {
private static final LongToDateBucket longToDateBucket = new LongToDateBucket("yyyyMM", ChronoUnit.MONTHS); private static final LongToDateBucket longToDateBucket = new LongToDateBucket("yyyyMM", DateBucketUnit.MONTH);
static Set<String> toDateIndexPrefix(final DateTimeRange dateRange) { static Set<String> toDateIndexPrefix(final DateTimeRange dateRange) {
return longToDateBucket.toDateIndexPrefix(dateRange.getStart(), dateRange.getEnd()); return longToDateBucket.toDateIndexPrefix(dateRange.getStart(), dateRange.getEnd());
@@ -31,7 +31,7 @@ public class DateIndexExtension {
*/ */
static List<ParititionId> toPartitionIds(final DateTimeRange dateRange) { static List<ParititionId> toPartitionIds(final DateTimeRange dateRange) {
final List<String> partitionIds = longToDateBucket.toPartitionIds(dateRange.getStart(), dateRange.getEnd(), final List<String> partitionIds = longToDateBucket.toPartitionIds(dateRange.getStart(), dateRange.getEnd(),
ChronoUnit.MONTHS); DateBucketUnit.MONTH);
final List<ParititionId> result = new ArrayList<>(); final List<ParititionId> result = new ArrayList<>();
for (final String partitionId : partitionIds) { for (final String partitionId : partitionIds) {

View File

@@ -1,6 +1,5 @@
package org.lucares.pdb.plot.api; package org.lucares.pdb.plot.api;
import java.time.temporal.ChronoUnit;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -10,38 +9,6 @@ import org.lucares.pdb.api.DateTimeRange;
import org.lucares.utils.LongToDateBucket; import org.lucares.utils.LongToDateBucket;
public class Interval { public class Interval {
public enum IntervalTimeUnit {
MINUTE, HOUR, DAY, WEEK, MONTH, YEAR;
public static boolean isValid(final String value) {
for (final IntervalTimeUnit e : values()) {
if (e.name().equals(value)) {
return true;
}
}
return false;
}
public ChronoUnit toChronoUnit() {
switch (this) {
case MINUTE:
return ChronoUnit.MINUTES;
case HOUR:
return ChronoUnit.HOURS;
case DAY:
return ChronoUnit.DAYS;
case WEEK:
return ChronoUnit.WEEKS;
case MONTH:
return ChronoUnit.MONTHS;
case YEAR:
return ChronoUnit.YEARS;
default:
throw new IllegalArgumentException("Unexpected value: " + this);
}
}
}
private final IntervalTimeUnit intervalTimeUnit; private final IntervalTimeUnit intervalTimeUnit;
private final int value; private final int value;

View File

@@ -0,0 +1,35 @@
package org.lucares.pdb.plot.api;
import org.lucares.utils.DateBucketUnit;
public enum IntervalTimeUnit {
MINUTE, HOUR, DAY, WEEK, MONTH, YEAR;
public static boolean isValid(final String value) {
for (final IntervalTimeUnit e : values()) {
if (e.name().equals(value)) {
return true;
}
}
return false;
}
public DateBucketUnit toChronoUnit() {
switch (this) {
case MINUTE:
return DateBucketUnit.MINUTE;
case HOUR:
return DateBucketUnit.HOUR;
case DAY:
return DateBucketUnit.DAY;
case WEEK:
return DateBucketUnit.WEEK;
case MONTH:
return DateBucketUnit.MONTH;
case YEAR:
return DateBucketUnit.YEAR;
default:
throw new IllegalArgumentException("Unexpected value: " + this);
}
}
}

View File

@@ -6,9 +6,9 @@ import java.time.temporal.TemporalAdjuster;
public class BeginningOfNextInterval implements TemporalAdjuster { public class BeginningOfNextInterval implements TemporalAdjuster {
private final ChronoUnit unit; private final DateBucketUnit unit;
public BeginningOfNextInterval(final ChronoUnit unit) { public BeginningOfNextInterval(final DateBucketUnit unit) {
this.unit = unit; this.unit = unit;
} }
@@ -19,27 +19,27 @@ public class BeginningOfNextInterval implements TemporalAdjuster {
result = result.with(startOfInterval); result = result.with(startOfInterval);
switch (unit) { switch (unit) {
case MINUTES: { case MINUTE: {
result = result.plus(1, ChronoUnit.MINUTES); result = result.plus(1, ChronoUnit.MINUTES);
break; break;
} }
case HOURS: { case HOUR: {
result = result.plus(1, ChronoUnit.HOURS); result = result.plus(1, ChronoUnit.HOURS);
break; break;
} }
case DAYS: { case DAY: {
result = result.plus(1, ChronoUnit.DAYS); result = result.plus(1, ChronoUnit.DAYS);
break; break;
} }
case WEEKS: { case WEEK: {
result = result.plus(1, ChronoUnit.WEEKS); result = result.plus(1, ChronoUnit.WEEKS);
break; break;
} }
case MONTHS: { case MONTH: {
result = result.plus(1, ChronoUnit.MONTHS); result = result.plus(1, ChronoUnit.MONTHS);
break; break;
} }
case YEARS: { case YEAR: {
result = result.plus(1, ChronoUnit.YEARS); result = result.plus(1, ChronoUnit.YEARS);
break; break;
} }

View File

@@ -0,0 +1,5 @@
package org.lucares.utils;
public enum DateBucketUnit {
MINUTE, HOUR, DAY, WEEK, MONTH, YEAR;
}

View File

@@ -6,9 +6,9 @@ import java.time.temporal.TemporalAdjuster;
public class EndOfInterval implements TemporalAdjuster { public class EndOfInterval implements TemporalAdjuster {
private final ChronoUnit unit; private final DateBucketUnit unit;
public EndOfInterval(final ChronoUnit unit) { public EndOfInterval(final DateBucketUnit unit) {
this.unit = unit; this.unit = unit;
} }

View File

@@ -4,7 +4,6 @@ import java.time.Instant;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
@@ -55,14 +54,14 @@ public class LongToDateBucket {
*/ */
private final DateTimeFormatter datePattern; private final DateTimeFormatter datePattern;
ChronoUnit chronoUnit; DateBucketUnit chronoUnit;
// visible for test // visible for test
final ConcurrentNavigableMap<Long, DatePrefixAndRange> datePrefixCache = new ConcurrentSkipListMap<>(); final ConcurrentNavigableMap<Long, DatePrefixAndRange> datePrefixCache = new ConcurrentSkipListMap<>();
private final AtomicReference<DatePrefixAndRange> lastAccessed = new AtomicReference<>(null); private final AtomicReference<DatePrefixAndRange> lastAccessed = new AtomicReference<>(null);
public LongToDateBucket(final String dateFormatPattern, final ChronoUnit chronoUnit) { public LongToDateBucket(final String dateFormatPattern, final DateBucketUnit chronoUnit) {
this.chronoUnit = chronoUnit; this.chronoUnit = chronoUnit;
this.datePattern = DateTimeFormatter.ofPattern(dateFormatPattern); this.datePattern = DateTimeFormatter.ofPattern(dateFormatPattern);
} }
@@ -118,7 +117,7 @@ public class LongToDateBucket {
* @return * @return
*/ */
public List<String> toPartitionIds(final OffsetDateTime start, final OffsetDateTime end, public List<String> toPartitionIds(final OffsetDateTime start, final OffsetDateTime end,
final ChronoUnit chronoUnit) { final DateBucketUnit chronoUnit) {
final List<String> result = new ArrayList<>(); final List<String> result = new ArrayList<>();
OffsetDateTime current = start; OffsetDateTime current = start;

View File

@@ -1,62 +1,50 @@
package org.lucares.utils; package org.lucares.utils;
import java.time.temporal.ChronoField; import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal; import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster; import java.time.temporal.TemporalAdjuster;
public class StartOfInterval implements TemporalAdjuster { public class StartOfInterval implements TemporalAdjuster {
private final ChronoUnit unit; private final DateBucketUnit unit;
public StartOfInterval(final ChronoUnit unit) { public StartOfInterval(final DateBucketUnit unit) {
this.unit = unit; this.unit = unit;
} }
@Override @Override
public Temporal adjustInto(final Temporal temporal) { public Temporal adjustInto(final Temporal temporal) {
Temporal result = temporal; Temporal result = temporal;
for (final ChronoUnit chronoUnit : ChronoUnit.values()) { result = result.with(ChronoField.NANO_OF_SECOND, 0);
if (chronoUnit.compareTo(unit) >= 0) { result = result.with(ChronoField.MICRO_OF_SECOND, 0);
result = result.with(ChronoField.MILLI_OF_SECOND, 0);
result = result.with(ChronoField.SECOND_OF_MINUTE, 0);
for (final DateBucketUnit dateBucketUnit : DateBucketUnit.values()) {
if (dateBucketUnit.compareTo(unit) >= 0) {
break; break;
} }
switch (chronoUnit) { switch (dateBucketUnit) {
case NANOS: { case MINUTE: {
result = result.with(ChronoField.NANO_OF_SECOND, 0);
break;
}
case MICROS: {
result = result.with(ChronoField.MICRO_OF_SECOND, 0);
break;
}
case MILLIS: {
result = result.with(ChronoField.MILLI_OF_SECOND, 0);
break;
}
case SECONDS: {
result = result.with(ChronoField.SECOND_OF_MINUTE, 0);
break;
}
case MINUTES: {
result = result.with(ChronoField.MINUTE_OF_HOUR, 0); result = result.with(ChronoField.MINUTE_OF_HOUR, 0);
break; break;
} }
case HOURS: { case HOUR: {
result = result.with(ChronoField.HOUR_OF_DAY, 0); result = result.with(ChronoField.HOUR_OF_DAY, 0);
break; break;
} }
case DAYS: { case DAY: {
switch (unit) { switch (unit) {
case WEEKS: { case WEEK: {
result = result.with(ChronoField.DAY_OF_WEEK, 1); result = result.with(ChronoField.DAY_OF_WEEK, 1);
break; break;
} }
case MONTHS: { case MONTH: {
result = result.with(ChronoField.DAY_OF_MONTH, 1); result = result.with(ChronoField.DAY_OF_MONTH, 1);
break; break;
} }
case YEARS: { case YEAR: {
result = result.with(ChronoField.MONTH_OF_YEAR, 1); result = result.with(ChronoField.MONTH_OF_YEAR, 1);
break; break;
} }
@@ -65,15 +53,14 @@ public class StartOfInterval implements TemporalAdjuster {
} }
break; break;
} }
case MONTHS: { case MONTH: {
result = result.with(ChronoField.MONTH_OF_YEAR, 1); result = result.with(ChronoField.MONTH_OF_YEAR, 1);
break; break;
} }
case HALF_DAYS: case WEEK:
case WEEKS:
break; break;
default: default:
throw new IllegalArgumentException("Unexpected value: " + chronoUnit); throw new IllegalArgumentException("Unexpected value: " + dateBucketUnit);
} }
} }

View File

@@ -2,7 +2,6 @@ package org.lucares.utils;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.time.ZoneOffset; import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.DoubleSummaryStatistics; import java.util.DoubleSummaryStatistics;
@@ -49,7 +48,7 @@ public class LongToDateBucketTest {
@MethodSource("provider") @MethodSource("provider")
public void test(final OffsetDateTime start, final OffsetDateTime end, final Set<String> expected) { public void test(final OffsetDateTime start, final OffsetDateTime end, final Set<String> expected) {
final Set<String> actual = new LongToDateBucket("yyyyMM", ChronoUnit.MONTHS).toDateIndexPrefix(start, end); final Set<String> actual = new LongToDateBucket("yyyyMM", DateBucketUnit.MONTH).toDateIndexPrefix(start, end);
Assertions.assertEquals(expected, actual); Assertions.assertEquals(expected, actual);
} }
@@ -60,18 +59,18 @@ public class LongToDateBucketTest {
final OffsetDateTime min_201801 = OffsetDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC); final OffsetDateTime min_201801 = OffsetDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC);
final OffsetDateTime min_201802 = OffsetDateTime.of(2018, 2, 1, 0, 0, 0, 0, ZoneOffset.UTC); final OffsetDateTime min_201802 = OffsetDateTime.of(2018, 2, 1, 0, 0, 0, 0, ZoneOffset.UTC);
final LongToDateBucket longToDateBucket = new LongToDateBucket("yyyyMM", ChronoUnit.MONTHS); final LongToDateBucket longToDateBucket = new LongToDateBucket("yyyyMM", DateBucketUnit.MONTH);
final List<String> dateIndexPrefixesWithEmptyCache = longToDateBucket.toPartitionIds(mid_201712, min_201802, final List<String> dateIndexPrefixesWithEmptyCache = longToDateBucket.toPartitionIds(mid_201712, min_201802,
ChronoUnit.MONTHS); DateBucketUnit.MONTH);
Assertions.assertEquals(Arrays.asList("201712", "201801", "201802"), dateIndexPrefixesWithEmptyCache); Assertions.assertEquals(Arrays.asList("201712", "201801", "201802"), dateIndexPrefixesWithEmptyCache);
final List<String> dateIndexPrefixesWithFilledCache = longToDateBucket.toPartitionIds(mid_201712, min_201801, final List<String> dateIndexPrefixesWithFilledCache = longToDateBucket.toPartitionIds(mid_201712, min_201801,
ChronoUnit.MONTHS); DateBucketUnit.MONTH);
Assertions.assertEquals(Arrays.asList("201712", "201801"), dateIndexPrefixesWithFilledCache); Assertions.assertEquals(Arrays.asList("201712", "201801"), dateIndexPrefixesWithFilledCache);
final List<String> dateIndexPrefixesOneMonth = longToDateBucket.toPartitionIds(mid_201712, mid_201712, final List<String> dateIndexPrefixesOneMonth = longToDateBucket.toPartitionIds(mid_201712, mid_201712,
ChronoUnit.MONTHS); DateBucketUnit.MONTH);
Assertions.assertEquals(Arrays.asList("201712"), dateIndexPrefixesOneMonth); Assertions.assertEquals(Arrays.asList("201712"), dateIndexPrefixesOneMonth);
} }
@@ -84,7 +83,7 @@ public class LongToDateBucketTest {
final long exp_201801 = OffsetDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC).toInstant().toEpochMilli(); final long exp_201801 = OffsetDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC).toInstant().toEpochMilli();
final long exp_201802 = OffsetDateTime.of(2018, 2, 1, 0, 0, 0, 0, ZoneOffset.UTC).toInstant().toEpochMilli(); final long exp_201802 = OffsetDateTime.of(2018, 2, 1, 0, 0, 0, 0, ZoneOffset.UTC).toInstant().toEpochMilli();
final LongToDateBucket longToDateBucket = new LongToDateBucket("yyyyMM", ChronoUnit.MONTHS); final LongToDateBucket longToDateBucket = new LongToDateBucket("yyyyMM", DateBucketUnit.MONTH);
final List<Long> dateIndexEpochMillis = longToDateBucket.toDateIndexEpochMillis(mid_201712, min_201802); final List<Long> dateIndexEpochMillis = longToDateBucket.toDateIndexEpochMillis(mid_201712, min_201802);
Assertions.assertEquals(Arrays.asList(exp_201712, exp_201801, exp_201802), dateIndexEpochMillis); Assertions.assertEquals(Arrays.asList(exp_201712, exp_201801, exp_201802), dateIndexEpochMillis);
@@ -102,7 +101,7 @@ public class LongToDateBucketTest {
final int warmup = 20 * factor; final int warmup = 20 * factor;
final int rounds = warmup + 20; final int rounds = warmup + 20;
final LongToDateBucket longToDateBucket = new LongToDateBucket("yyyyMM", ChronoUnit.MONTHS); final LongToDateBucket longToDateBucket = new LongToDateBucket("yyyyMM", DateBucketUnit.MONTH);
// fill the cache // fill the cache
for (long i = min; i < max; i += 3600 * 24 * 28) { for (long i = min; i < max; i += 3600 * 24 * 28) {