From 510da196d762d7a267e2be5186e6259187d50262 Mon Sep 17 00:00:00 2001 From: ctingue Date: Thu, 26 May 2016 07:21:39 -0700 Subject: [PATCH] Follow-up changes to TimeOfYear from [] ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=123316677 --- .../registry/model/common/TimeOfYear.java | 51 ++++++++++--------- .../registry/model/common/TimeOfYearTest.java | 34 +++++-------- 2 files changed, 39 insertions(+), 46 deletions(-) diff --git a/java/google/registry/model/common/TimeOfYear.java b/java/google/registry/model/common/TimeOfYear.java index 86bd59d59..c49709cd2 100644 --- a/java/google/registry/model/common/TimeOfYear.java +++ b/java/google/registry/model/common/TimeOfYear.java @@ -14,14 +14,17 @@ package google.registry.model.common; +import static com.google.common.collect.DiscreteDomain.integers; import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.START_OF_TIME; import static google.registry.util.DateTimeUtils.isAtOrAfter; import static google.registry.util.DateTimeUtils.isBeforeOrAt; +import static org.joda.time.DateTimeZone.UTC; +import com.google.common.base.Function; import com.google.common.base.Splitter; -import com.google.common.collect.BoundType; -import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ContiguousSet; +import com.google.common.collect.FluentIterable; import com.google.common.collect.Range; import com.googlecode.objectify.annotation.Embed; @@ -72,40 +75,37 @@ public class TimeOfYear extends ImmutableObject { } /** - * Returns an {@link ImmutableSet} of {@link DateTime}s of every recurrence of this particular + * Returns an {@link Iterable} of {@link DateTime}s of every recurrence of this particular * time of year within a given {@link Range} (usually one spanning many years). + * + *

WARNING: This can return a potentially very large {@link Iterable} if {@code END_OF_TIME} + * is used as the upper endpoint of the range. */ - public ImmutableSet getInstancesInRange(Range range) { + public Iterable getInstancesInRange(Range range) { // In registry world, all dates are within START_OF_TIME and END_OF_TIME, so restrict any // ranges without bounds to our notion of zero-to-infinity. - Range normalizedRange = Range.range( - range.hasLowerBound() ? range.lowerEndpoint() : START_OF_TIME, - range.hasLowerBound() ? range.lowerBoundType() : BoundType.CLOSED, - range.hasUpperBound() ? range.upperEndpoint() : END_OF_TIME, - range.hasUpperBound() ? range.upperBoundType() : BoundType.CLOSED); - ImmutableSet.Builder instances = ImmutableSet.builder(); - // This produces a greedy year range, but the edge cases will be handled appropriately via - // Range.contains(). - for (int year = normalizedRange.lowerEndpoint().getYear(); - year <= normalizedRange.upperEndpoint().getYear(); - year++) { - DateTime candidate = getDateTimeWithSameYear(normalizedRange.lowerEndpoint()).withYear(year); - if (normalizedRange.contains(candidate)) { - instances.add(candidate); - } - } - return instances.build(); + Range normalizedRange = range.intersection(Range.closed(START_OF_TIME, END_OF_TIME)); + Range yearRange = Range.closed( + normalizedRange.lowerEndpoint().getYear(), + normalizedRange.upperEndpoint().getYear()); + return FluentIterable.from(ContiguousSet.create(yearRange, integers())) + .transform(new Function() { + @Override + public DateTime apply(Integer year) { + return getDateTimeWithYear(year); + }}) + .filter(normalizedRange); } /** Get the first {@link DateTime} with this month/day/millis that is at or after the start. */ public DateTime getNextInstanceAtOrAfter(DateTime start) { - DateTime withSameYear = getDateTimeWithSameYear(start); + DateTime withSameYear = getDateTimeWithYear(start.getYear()); return isAtOrAfter(withSameYear, start) ? withSameYear : withSameYear.plusYears(1); } /** Get the first {@link DateTime} with this month/day/millis that is at or before the end. */ public DateTime getLastInstanceBeforeOrAt(DateTime end) { - DateTime withSameYear = getDateTimeWithSameYear(end); + DateTime withSameYear = getDateTimeWithYear(end.getYear()); return isBeforeOrAt(withSameYear, end) ? withSameYear : withSameYear.minusYears(1); } @@ -113,11 +113,12 @@ public class TimeOfYear extends ImmutableObject { * Return a new datetime with the same year as the parameter but projected to the month, day, and * time of day of this object. */ - private DateTime getDateTimeWithSameYear(DateTime date) { + private DateTime getDateTimeWithYear(int year) { List monthDayMillis = Splitter.on(' ').splitToList(timeString); // Do not be clever and use Ints.stringConverter here. That does radix guessing, and bad things // will happen because of the leading zeroes. - return date + return new DateTime(0, UTC) + .withYear(year) .withMonthOfYear(Integer.parseInt(monthDayMillis.get(0))) .withDayOfMonth(Integer.parseInt(monthDayMillis.get(1))) .withMillisOfDay(Integer.parseInt(monthDayMillis.get(2))); diff --git a/javatests/google/registry/model/common/TimeOfYearTest.java b/javatests/google/registry/model/common/TimeOfYearTest.java index 1b03d6b98..0f8439906 100644 --- a/javatests/google/registry/model/common/TimeOfYearTest.java +++ b/javatests/google/registry/model/common/TimeOfYearTest.java @@ -70,15 +70,14 @@ public class TimeOfYearTest { DateTime startDate = DateTime.parse("2012-05-01T00:00:00Z"); DateTime endDate = DateTime.parse("2016-05-01T00:00:00Z"); TimeOfYear timeOfYear = TimeOfYear.fromDateTime(DateTime.parse("2012-05-01T00:00:00Z")); - ImmutableSet actual = - timeOfYear.getInstancesInRange(Range.closed(startDate, endDate)); ImmutableSet expected = ImmutableSet.of( DateTime.parse("2012-05-01T00:00:00Z"), DateTime.parse("2013-05-01T00:00:00Z"), DateTime.parse("2014-05-01T00:00:00Z"), DateTime.parse("2015-05-01T00:00:00Z"), DateTime.parse("2016-05-01T00:00:00Z")); - assertThat(actual).containsExactlyElementsIn(expected); + assertThat(timeOfYear.getInstancesInRange(Range.closed(startDate, endDate))) + .containsExactlyElementsIn(expected); } @Test @@ -86,14 +85,13 @@ public class TimeOfYearTest { DateTime startDate = DateTime.parse("2012-05-01T00:00:00Z"); DateTime endDate = DateTime.parse("2016-05-01T00:00:00Z"); TimeOfYear timeOfYear = TimeOfYear.fromDateTime(DateTime.parse("2012-05-01T00:00:00Z")); - ImmutableSet actual = - timeOfYear.getInstancesInRange(Range.openClosed(startDate, endDate)); ImmutableSet expected = ImmutableSet.of( DateTime.parse("2013-05-01T00:00:00Z"), DateTime.parse("2014-05-01T00:00:00Z"), DateTime.parse("2015-05-01T00:00:00Z"), DateTime.parse("2016-05-01T00:00:00Z")); - assertThat(actual).containsExactlyElementsIn(expected); + assertThat(timeOfYear.getInstancesInRange(Range.openClosed(startDate, endDate))) + .containsExactlyElementsIn(expected); } @Test @@ -101,14 +99,13 @@ public class TimeOfYearTest { DateTime startDate = DateTime.parse("2012-05-01T00:00:00Z"); DateTime endDate = DateTime.parse("2016-05-01T00:00:00Z"); TimeOfYear timeOfYear = TimeOfYear.fromDateTime(DateTime.parse("2012-05-01T00:00:00Z")); - ImmutableSet actual = - timeOfYear.getInstancesInRange(Range.closedOpen(startDate, endDate)); ImmutableSet expected = ImmutableSet.of( DateTime.parse("2012-05-01T00:00:00Z"), DateTime.parse("2013-05-01T00:00:00Z"), DateTime.parse("2014-05-01T00:00:00Z"), DateTime.parse("2015-05-01T00:00:00Z")); - assertThat(actual).containsExactlyElementsIn(expected); + assertThat(timeOfYear.getInstancesInRange(Range.closedOpen(startDate, endDate))) + .containsExactlyElementsIn(expected); } @Test @@ -116,37 +113,34 @@ public class TimeOfYearTest { DateTime startDate = DateTime.parse("2012-05-01T00:00:00Z"); DateTime endDate = DateTime.parse("2016-05-01T00:00:00Z"); TimeOfYear timeOfYear = TimeOfYear.fromDateTime(DateTime.parse("2012-05-01T00:00:00Z")); - ImmutableSet actual = - timeOfYear.getInstancesInRange(Range.open(startDate, endDate)); ImmutableSet expected = ImmutableSet.of( DateTime.parse("2013-05-01T00:00:00Z"), DateTime.parse("2014-05-01T00:00:00Z"), DateTime.parse("2015-05-01T00:00:00Z")); - assertThat(actual).containsExactlyElementsIn(expected); + assertThat(timeOfYear.getInstancesInRange(Range.open(startDate, endDate))) + .containsExactlyElementsIn(expected); } @Test public void testSuccess_getInstancesInRange_normalizedLowerBound() { TimeOfYear timeOfYear = TimeOfYear.fromDateTime(START_OF_TIME); - ImmutableSet actual = - timeOfYear.getInstancesInRange(Range.atMost(START_OF_TIME.plusYears(2))); ImmutableSet expected = ImmutableSet.of( START_OF_TIME, START_OF_TIME.plusYears(1), START_OF_TIME.plusYears(2)); - assertThat(actual).containsExactlyElementsIn(expected); + assertThat(timeOfYear.getInstancesInRange(Range.atMost(START_OF_TIME.plusYears(2)))) + .containsExactlyElementsIn(expected); } @Test public void testSuccess_getInstancesInRange_normalizedUpperBound() { TimeOfYear timeOfYear = TimeOfYear.fromDateTime(END_OF_TIME); - ImmutableSet actual = - timeOfYear.getInstancesInRange(Range.atLeast(END_OF_TIME.minusYears(2))); ImmutableSet expected = ImmutableSet.of( END_OF_TIME.minusYears(2), END_OF_TIME.minusYears(1), END_OF_TIME); - assertThat(actual).containsExactlyElementsIn(expected); + assertThat(timeOfYear.getInstancesInRange(Range.atLeast(END_OF_TIME.minusYears(2)))) + .containsExactlyElementsIn(expected); } @Test @@ -154,8 +148,6 @@ public class TimeOfYearTest { DateTime startDate = DateTime.parse("2012-05-01T00:00:00Z"); DateTime endDate = DateTime.parse("2013-02-01T00:00:00Z"); TimeOfYear timeOfYear = TimeOfYear.fromDateTime(DateTime.parse("2012-03-01T00:00:00Z")); - ImmutableSet actual = - timeOfYear.getInstancesInRange(Range.closed(startDate, endDate)); - assertThat(actual).isEmpty(); + assertThat(timeOfYear.getInstancesInRange(Range.closed(startDate, endDate))).isEmpty(); } }