From 60e84e72d7430f083bc5ad483e284d3c92fc6280 Mon Sep 17 00:00:00 2001 From: Ben McIlwain Date: Tue, 31 Mar 2026 16:30:29 -0400 Subject: [PATCH] Begin migration of joda DateTime to java.time.Instant (#2992) java.time has been around since Java 8 and was based on joda DateTime, so this is an overdue migration. We're migrating specifically to Instant in most places rather than ZonedDateTime because we were always using DateTimes in UTC to reference a specific instant, which is exactly what Instants are for. ZonedDateTime set to UTC may still be useful in some places that are heavy on date math (especially in tests). There is a lot more work to be done after this, but I wanted to put together a manual PR showing my overall approach for how to do the migration that I can then hopefully follow along with AI to continue making these changes throughout the codebase. The basic approach is to migrate a small number of methods at a time, marking the old methods as @Deprecated when possible (not always possible because of @InlineMe restrictions). This PR doesn't yet migrate any DateTime fields in the model classes, so that's the one remaining type of refactor to figure out after this. We won't be changing how any of the data is actually stored in the database. BUG= http://b/496985355 --- .../main/java/google/registry/util/Clock.java | 5 ++ .../google/registry/util/DateTimeUtils.java | 89 ++++++++++++++++++- .../google/registry/util/SystemClock.java | 6 ++ .../google/registry/testing/FakeClock.java | 6 ++ .../batch/BulkDomainTransferAction.java | 6 +- .../batch/DeleteExpiredDomainsAction.java | 3 +- .../registry/batch/RelockDomainAction.java | 2 +- .../ExpandBillingRecurrencesPipeline.java | 3 +- .../registry/flows/ResourceFlowUtils.java | 11 ++- .../flows/domain/DomainDeleteFlow.java | 4 +- .../flows/domain/DomainFlowUtils.java | 6 +- .../registry/flows/domain/DomainInfoFlow.java | 4 +- .../flows/domain/DomainRenewFlow.java | 7 +- .../domain/DomainRestoreRequestFlow.java | 4 +- .../domain/DomainTransferApproveFlow.java | 13 ++- .../flows/domain/DomainTransferQueryFlow.java | 11 ++- .../domain/DomainTransferRejectFlow.java | 11 ++- .../domain/DomainTransferRequestFlow.java | 15 ++-- .../flows/domain/DomainTransferUtils.java | 6 +- .../flows/domain/DomainUpdateFlow.java | 2 +- .../registry/flows/host/HostInfoFlow.java | 2 +- .../google/registry/model/EppResource.java | 20 ++++- .../registry/model/EppResourceUtils.java | 9 +- .../registry/model/ForeignKeyUtils.java | 35 +++++++- .../registry/model/ResourceTransferUtils.java | 4 +- .../model/billing/BillingCancellation.java | 2 +- .../google/registry/model/domain/Domain.java | 8 ++ .../registry/model/domain/DomainBase.java | 64 ++++++++----- .../model/domain/GracePeriodBase.java | 10 ++- .../google/registry/model/host/HostBase.java | 10 ++- .../registry/model/poll/PollMessage.java | 2 +- .../model/transfer/BaseTransferObject.java | 10 ++- .../model/transfer/DomainTransferData.java | 10 ++- .../JpaTransactionManagerImpl.java | 11 ++- .../transaction/TransactionManager.java | 5 ++ .../google/registry/rdap/RdapActionBase.java | 3 +- .../registry/rdap/RdapJsonFormatter.java | 10 ++- .../registry/rde/DomainToXjcConverter.java | 8 +- .../registry/rde/HostToXjcConverter.java | 2 +- .../tools/GenerateDnsReportCommand.java | 4 +- .../registry/tools/RenewDomainCommand.java | 2 +- .../tools/UniformRapidSuspensionCommand.java | 2 +- .../registry/tools/UnrenewDomainCommand.java | 11 +-- .../tools/UpdateRecurrenceCommand.java | 9 +- .../batch/DeleteExpiredDomainsActionTest.java | 3 +- .../batch/DeleteProberDataActionTest.java | 11 +-- .../ResaveAllEppResourcesPipelineTest.java | 7 +- .../flows/EppLifecycleDomainTest.java | 2 +- .../google/registry/flows/FlowTestCase.java | 2 +- .../flows/domain/DomainCreateFlowTest.java | 8 +- .../flows/domain/DomainDeleteFlowTest.java | 10 +-- .../flows/domain/DomainRenewFlowTest.java | 8 +- .../domain/DomainRestoreRequestFlowTest.java | 4 +- .../domain/DomainTransferApproveFlowTest.java | 25 +++--- .../domain/DomainTransferCancelFlowTest.java | 2 +- .../domain/DomainTransferQueryFlowTest.java | 5 +- .../domain/DomainTransferRejectFlowTest.java | 2 +- .../domain/DomainTransferRequestFlowTest.java | 27 +++--- .../flows/host/HostUpdateFlowTest.java | 2 +- .../registry/model/domain/DomainTest.java | 81 +++++++++-------- .../model/domain/GracePeriodTest.java | 6 +- .../testing/AbstractEppResourceSubject.java | 6 +- .../registry/testing/DomainSubject.java | 2 +- .../tools/UnrenewDomainCommandTest.java | 8 +- .../domains/ConsoleBulkDomainActionTest.java | 5 +- .../registry/util/DateTimeUtilsTest.java | 50 ++++++++++- 66 files changed, 530 insertions(+), 213 deletions(-) diff --git a/common/src/main/java/google/registry/util/Clock.java b/common/src/main/java/google/registry/util/Clock.java index 78372cba4..9943aaa7c 100644 --- a/common/src/main/java/google/registry/util/Clock.java +++ b/common/src/main/java/google/registry/util/Clock.java @@ -15,6 +15,7 @@ package google.registry.util; import java.io.Serializable; +import java.time.Instant; import javax.annotation.concurrent.ThreadSafe; import org.joda.time.DateTime; @@ -30,5 +31,9 @@ import org.joda.time.DateTime; public interface Clock extends Serializable { /** Returns current time in UTC timezone. */ + @Deprecated DateTime nowUtc(); + + /** Returns current Instant (which is always in UTC). */ + Instant now(); } diff --git a/common/src/main/java/google/registry/util/DateTimeUtils.java b/common/src/main/java/google/registry/util/DateTimeUtils.java index b085fbabd..1c7650eda 100644 --- a/common/src/main/java/google/registry/util/DateTimeUtils.java +++ b/common/src/main/java/google/registry/util/DateTimeUtils.java @@ -20,6 +20,9 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Ordering; import java.sql.Date; +import java.time.Instant; +import java.time.ZoneOffset; +import javax.annotation.Nullable; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.LocalDate; @@ -28,7 +31,10 @@ import org.joda.time.LocalDate; public abstract class DateTimeUtils { /** The start of the epoch, in a convenient constant. */ - public static final DateTime START_OF_TIME = new DateTime(0, DateTimeZone.UTC); + @Deprecated public static final DateTime START_OF_TIME = new DateTime(0, DateTimeZone.UTC); + + /** The start of the UNIX epoch (which is defined in UTC), in a convenient constant. */ + public static final Instant START_INSTANT = Instant.ofEpochMilli(0); /** * A date in the far future that we can treat as infinity. @@ -37,19 +43,40 @@ public abstract class DateTimeUtils { * but Java uses milliseconds, so this is the largest representable date that will survive a * round-trip through the database. */ + @Deprecated public static final DateTime END_OF_TIME = new DateTime(Long.MAX_VALUE / 1000, DateTimeZone.UTC); + /** + * An instant in the far future that we can treat as infinity. + * + *

This value is (2^63-1)/1000 rounded down. Postgres can store dates as 64 bit microseconds, + * but Java uses milliseconds, so this is the largest representable date that will survive a + * round-trip through the database. + */ + public static final Instant END_INSTANT = Instant.ofEpochMilli(Long.MAX_VALUE / 1000); + /** Returns the earliest of a number of given {@link DateTime} instances. */ public static DateTime earliestOf(DateTime first, DateTime... rest) { + return earliestDateTimeOf(Lists.asList(first, rest)); + } + + /** Returns the earliest of a number of given {@link Instant} instances. */ + public static Instant earliestOf(Instant first, Instant... rest) { return earliestOf(Lists.asList(first, rest)); } /** Returns the earliest element in a {@link DateTime} iterable. */ - public static DateTime earliestOf(Iterable dates) { + public static DateTime earliestDateTimeOf(Iterable dates) { checkArgument(!Iterables.isEmpty(dates)); return Ordering.natural().min(dates); } + /** Returns the earliest element in a {@link Instant} iterable. */ + public static Instant earliestOf(Iterable instants) { + checkArgument(!Iterables.isEmpty(instants)); + return Ordering.natural().min(instants); + } + /** Returns the latest of a number of given {@link DateTime} instances. */ public static DateTime latestOf(DateTime first, DateTime... rest) { return latestOf(Lists.asList(first, rest)); @@ -66,29 +93,63 @@ public abstract class DateTimeUtils { return !timeToCheck.isAfter(timeToCompareTo); } + /** Returns whether the first {@link Instant} is equal to or earlier than the second. */ + public static boolean isBeforeOrAt(Instant timeToCheck, Instant timeToCompareTo) { + return !timeToCheck.isAfter(timeToCompareTo); + } + /** Returns whether the first {@link DateTime} is equal to or later than the second. */ public static boolean isAtOrAfter(DateTime timeToCheck, DateTime timeToCompareTo) { return !timeToCheck.isBefore(timeToCompareTo); } + /** Returns whether the first {@link Instant} is equal to or later than the second. */ + public static boolean isAtOrAfter(Instant timeToCheck, Instant timeToCompareTo) { + return !timeToCheck.isBefore(timeToCompareTo); + } + /** * Adds years to a date, in the {@code Duration} sense of semantic years. Use this instead of * {@link DateTime#plusYears} to ensure that we never end up on February 29. */ + @Deprecated public static DateTime leapSafeAddYears(DateTime now, int years) { checkArgument(years >= 0); return years == 0 ? now : now.plusYears(1).plusYears(years - 1); } + /** + * Adds years to a date, in the {@code Duration} sense of semantic years. Use this instead of + * {@link java.time.ZonedDateTime#plusYears} to ensure that we never end up on February 29. + */ + public static Instant leapSafeAddYears(Instant now, long years) { + checkArgument(years >= 0); + return (years == 0) + ? now + : now.atZone(ZoneOffset.UTC).plusYears(1).plusYears(years - 1).toInstant(); + } + /** * Subtracts years from a date, in the {@code Duration} sense of semantic years. Use this instead * of {@link DateTime#minusYears} to ensure that we never end up on February 29. */ + @Deprecated public static DateTime leapSafeSubtractYears(DateTime now, int years) { checkArgument(years >= 0); return years == 0 ? now : now.minusYears(1).minusYears(years - 1); } + /** + * Subtracts years from a date, in the {@code Duration} sense of semantic years. Use this instead + * of {@link java.time.ZonedDateTime#minusYears} to ensure that we never end up on February 29. + */ + public static Instant leapSafeSubtractYears(Instant now, int years) { + checkArgument(years >= 0); + return (years == 0) + ? now + : now.atZone(ZoneOffset.UTC).minusYears(1).minusYears(years - 1).toInstant(); + } + public static Date toSqlDate(LocalDate localDate) { return new Date(localDate.toDateTimeAtStartOfDay().getMillis()); } @@ -96,4 +157,28 @@ public abstract class DateTimeUtils { public static LocalDate toLocalDate(Date date) { return new LocalDate(date.getTime(), DateTimeZone.UTC); } + + /** Convert a joda {@link DateTime} to a java.time {@link Instant}, null-safe. */ + @Nullable + public static Instant toInstant(@Nullable DateTime dateTime) { + return (dateTime == null) ? null : Instant.ofEpochMilli(dateTime.getMillis()); + } + + /** Convert a java.time {@link Instant} to a joda {@link DateTime}, null-safe. */ + @Nullable + public static DateTime toDateTime(@Nullable Instant instant) { + return (instant == null) ? null : new DateTime(instant.toEpochMilli(), DateTimeZone.UTC); + } + + public static Instant plusYears(Instant instant, int years) { + return instant.atZone(ZoneOffset.UTC).plusYears(years).toInstant(); + } + + public static Instant plusDays(Instant instant, int days) { + return instant.atZone(ZoneOffset.UTC).plusDays(days).toInstant(); + } + + public static Instant minusDays(Instant instant, int days) { + return instant.atZone(ZoneOffset.UTC).minusDays(days).toInstant(); + } } diff --git a/common/src/main/java/google/registry/util/SystemClock.java b/common/src/main/java/google/registry/util/SystemClock.java index eb553678d..52ac9893f 100644 --- a/common/src/main/java/google/registry/util/SystemClock.java +++ b/common/src/main/java/google/registry/util/SystemClock.java @@ -17,6 +17,7 @@ package google.registry.util; import static org.joda.time.DateTimeZone.UTC; import jakarta.inject.Inject; +import java.time.Instant; import javax.annotation.concurrent.ThreadSafe; import org.joda.time.DateTime; @@ -34,4 +35,9 @@ public class SystemClock implements Clock { public DateTime nowUtc() { return DateTime.now(UTC); } + + @Override + public Instant now() { + return Instant.now(); + } } diff --git a/common/src/testing/java/google/registry/testing/FakeClock.java b/common/src/testing/java/google/registry/testing/FakeClock.java index 526f943a2..656ec7109 100644 --- a/common/src/testing/java/google/registry/testing/FakeClock.java +++ b/common/src/testing/java/google/registry/testing/FakeClock.java @@ -19,6 +19,7 @@ import static org.joda.time.DateTimeZone.UTC; import static org.joda.time.Duration.millis; import google.registry.util.Clock; +import java.time.Instant; import java.util.concurrent.atomic.AtomicLong; import javax.annotation.concurrent.ThreadSafe; import org.joda.time.DateTime; @@ -54,6 +55,11 @@ public final class FakeClock implements Clock { return new DateTime(currentTimeMillis.addAndGet(autoIncrementStepMs), UTC); } + @Override + public Instant now() { + return Instant.ofEpochMilli(currentTimeMillis.addAndGet(autoIncrementStepMs)); + } + /** * Sets the increment applied to the clock whenever it is queried. The increment is zero by * default: the clock is left unchanged when queried. diff --git a/core/src/main/java/google/registry/batch/BulkDomainTransferAction.java b/core/src/main/java/google/registry/batch/BulkDomainTransferAction.java index 990428edd..b3bcc419d 100644 --- a/core/src/main/java/google/registry/batch/BulkDomainTransferAction.java +++ b/core/src/main/java/google/registry/batch/BulkDomainTransferAction.java @@ -17,6 +17,7 @@ package google.registry.batch; import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8; import static google.registry.flows.FlowUtils.marshalWithLenientRetry; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; +import static google.registry.util.DateTimeUtils.END_INSTANT; import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT; import static jakarta.servlet.http.HttpServletResponse.SC_OK; @@ -39,7 +40,6 @@ import google.registry.request.Parameter; import google.registry.request.Response; import google.registry.request.auth.Auth; import google.registry.request.lock.LockHandler; -import google.registry.util.DateTimeUtils; import jakarta.inject.Inject; import jakarta.inject.Named; import java.util.Optional; @@ -212,7 +212,7 @@ public class BulkDomainTransferAction implements Runnable { private boolean shouldSkipDomain(String domainName) { Optional maybeDomain = - ForeignKeyUtils.loadResource(Domain.class, domainName, tm().getTransactionTime()); + ForeignKeyUtils.loadResource(Domain.class, domainName, tm().getTxTime()); if (maybeDomain.isEmpty()) { logger.atWarning().log("Domain '%s' was already deleted", domainName); missingDomains++; @@ -232,7 +232,7 @@ public class BulkDomainTransferAction implements Runnable { return true; } if (domain.getStatusValues().contains(StatusValue.PENDING_DELETE) - || !domain.getDeletionTime().equals(DateTimeUtils.END_OF_TIME)) { + || !domain.getDeletionTime().equals(END_INSTANT)) { logger.atWarning().log("Domain '%s' is in PENDING_DELETE", domainName); pendingDelete++; return true; diff --git a/core/src/main/java/google/registry/batch/DeleteExpiredDomainsAction.java b/core/src/main/java/google/registry/batch/DeleteExpiredDomainsAction.java index 528136034..a23d5ce17 100644 --- a/core/src/main/java/google/registry/batch/DeleteExpiredDomainsAction.java +++ b/core/src/main/java/google/registry/batch/DeleteExpiredDomainsAction.java @@ -18,6 +18,7 @@ import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8; import static google.registry.flows.FlowUtils.marshalWithLenientRetry; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; +import static google.registry.util.DateTimeUtils.END_INSTANT; import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.ResourceUtils.readResourceUtf8; import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; @@ -177,7 +178,7 @@ public class DeleteExpiredDomainsAction implements Runnable { "Failed to delete domain %s because of its autorenew end time: %s.", transDomain.getDomainName(), transDomain.getAutorenewEndTime()); return Optional.empty(); - } else if (domain.getDeletionTime().isBefore(END_OF_TIME)) { + } else if (domain.getDeletionTime().isBefore(END_INSTANT)) { logger.atSevere().log( "Failed to delete domain %s because it was already deleted on %s.", transDomain.getDomainName(), transDomain.getDeletionTime()); diff --git a/core/src/main/java/google/registry/batch/RelockDomainAction.java b/core/src/main/java/google/registry/batch/RelockDomainAction.java index f9a5ab5be..010eef40f 100644 --- a/core/src/main/java/google/registry/batch/RelockDomainAction.java +++ b/core/src/main/java/google/registry/batch/RelockDomainAction.java @@ -188,7 +188,7 @@ public class RelockDomainAction implements Runnable { "Domain %s has a pending delete.", domainName); checkArgument( - !DateTimeUtils.isAtOrAfter(tm().getTransactionTime(), domain.getDeletionTime()), + !DateTimeUtils.isAtOrAfter(tm().getTxTime(), domain.getDeletionTime()), "Domain %s has been deleted.", domainName); checkArgument( diff --git a/core/src/main/java/google/registry/beam/billing/ExpandBillingRecurrencesPipeline.java b/core/src/main/java/google/registry/beam/billing/ExpandBillingRecurrencesPipeline.java index 193103c69..1bfcc1c48 100644 --- a/core/src/main/java/google/registry/beam/billing/ExpandBillingRecurrencesPipeline.java +++ b/core/src/main/java/google/registry/beam/billing/ExpandBillingRecurrencesPipeline.java @@ -24,6 +24,7 @@ import static google.registry.util.CollectionUtils.union; import static google.registry.util.DateTimeUtils.START_OF_TIME; import static google.registry.util.DateTimeUtils.earliestOf; import static google.registry.util.DateTimeUtils.latestOf; +import static google.registry.util.DateTimeUtils.toInstant; import static org.apache.beam.sdk.values.TypeDescriptors.voids; import com.google.common.collect.ImmutableMap; @@ -372,7 +373,7 @@ public class ExpandBillingRecurrencesPipeline implements Serializable { // during ARGP). // // See: DomainFlowUtils#createCancellingRecords - domain.getDeletionTime().isBefore(billingTime) + domain.getDeletionTime().isBefore(toInstant(billingTime)) ? ImmutableSet.of() : ImmutableSet.of( DomainTransactionRecord.create( diff --git a/core/src/main/java/google/registry/flows/ResourceFlowUtils.java b/core/src/main/java/google/registry/flows/ResourceFlowUtils.java index 122d5ded3..101bafa96 100644 --- a/core/src/main/java/google/registry/flows/ResourceFlowUtils.java +++ b/core/src/main/java/google/registry/flows/ResourceFlowUtils.java @@ -16,6 +16,7 @@ package google.registry.flows; import static com.google.common.collect.Sets.intersection; import static google.registry.model.EppResourceUtils.isLinked; +import static google.registry.util.DateTimeUtils.toInstant; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; @@ -44,6 +45,7 @@ import google.registry.model.eppcommon.StatusValue; import google.registry.model.host.Host; import google.registry.model.transfer.TransferStatus; import google.registry.persistence.VKey; +import java.time.Instant; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -89,6 +91,11 @@ public final class ResourceFlowUtils { public static R loadAndVerifyExistence( Class clazz, String targetId, DateTime now) throws ResourceDoesNotExistException { + return loadAndVerifyExistence(clazz, targetId, toInstant(now)); + } + + public static R loadAndVerifyExistence( + Class clazz, String targetId, Instant now) throws ResourceDoesNotExistException { return verifyExistence(clazz, targetId, ForeignKeyUtils.loadResource(clazz, targetId, now)); } @@ -197,8 +204,8 @@ public final class ResourceFlowUtils { * * @param domain is the domain already projected at approvalTime */ - public static DateTime computeExDateForApprovalTime( - DomainBase domain, DateTime approvalTime, Period period) { + public static Instant computeExDateForApprovalTime( + DomainBase domain, Instant approvalTime, Period period) { boolean inAutoRenew = domain.getGracePeriodStatuses().contains(GracePeriodStatus.AUTO_RENEW); // inAutoRenew is set to false if the period is zero because a zero-period transfer should not // subsume an autorenew. diff --git a/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java b/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java index 6414aa93b..9cb5a7c4b 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java @@ -236,7 +236,7 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging } // Cancel any grace periods that were still active, and set the expiration time accordingly. - DateTime newExpirationTime = existingDomain.getRegistrationExpirationTime(); + DateTime newExpirationTime = existingDomain.getRegistrationExpirationDateTime(); for (GracePeriod gracePeriod : existingDomain.getGracePeriods()) { // No cancellation is written if the grace period was not for a billable event. if (gracePeriod.hasBillingEvent()) { @@ -289,7 +289,7 @@ public final class DomainDeleteFlow implements MutatingFlow, SqlStatementLogging flowCustomLogic.beforeResponse( BeforeResponseParameters.newBuilder() .setResultCode( - newDomain.getDeletionTime().isAfter(now) + newDomain.getDeletionDateTime().isAfter(now) ? SUCCESS_WITH_ACTION_PENDING : SUCCESS) .setResponseExtensions( diff --git a/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java b/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java index fb6b358dc..3a2fdd196 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java +++ b/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java @@ -503,7 +503,7 @@ public class DomainFlowUtils { .setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) .setTargetId(domain.getDomainName()) .setRegistrarId(domain.getCurrentSponsorRegistrarId()) - .setEventTime(domain.getRegistrationExpirationTime()); + .setEventTime(domain.getRegistrationExpirationDateTime()); } /** @@ -514,7 +514,7 @@ public class DomainFlowUtils { return new Autorenew.Builder() .setTargetId(domain.getDomainName()) .setRegistrarId(domain.getCurrentSponsorRegistrarId()) - .setEventTime(domain.getRegistrationExpirationTime()) + .setEventTime(domain.getRegistrationExpirationDateTime()) .setMsg("Domain was auto-renewed."); } @@ -658,7 +658,7 @@ public class DomainFlowUtils { // process, don't count as expired for the purposes of requiring an added year of renewal on // restore because they can't be restored in the first place. boolean isExpired = - domain.isPresent() && domain.get().getRegistrationExpirationTime().isBefore(now); + domain.isPresent() && domain.get().getRegistrationExpirationDateTime().isBefore(now); fees = pricingLogic.getRestorePrice(tld, domainNameString, now, isExpired).getFees(); } case TRANSFER -> { diff --git a/core/src/main/java/google/registry/flows/domain/DomainInfoFlow.java b/core/src/main/java/google/registry/flows/domain/DomainInfoFlow.java index 15a9b1b48..8815d2ca7 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainInfoFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainInfoFlow.java @@ -122,8 +122,8 @@ public final class DomainInfoFlow implements MutatingFlow { .setNameservers( hostsRequest.requestDelegated() ? domain.loadNameserverHostNames() : null) .setCreationTime(domain.getCreationTime()) - .setLastEppUpdateTime(domain.getLastEppUpdateTime()) - .setRegistrationExpirationTime(domain.getRegistrationExpirationTime()) + .setLastEppUpdateTime(domain.getLastEppUpdateDateTime()) + .setRegistrationExpirationTime(domain.getRegistrationExpirationDateTime()) .setLastTransferTime(domain.getLastTransferTime()); // If authInfo is non-null, then the caller is authorized to see the full information since we diff --git a/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java b/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java index ec7d982ca..32278bf53 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java @@ -191,7 +191,7 @@ public final class DomainRenewFlow implements MutatingFlow { existingDomain = maybeApplyBulkPricingRemovalToken(existingDomain, allocationToken); DateTime newExpirationTime = - leapSafeAddYears(existingDomain.getRegistrationExpirationTime(), years); // Uncapped + leapSafeAddYears(existingDomain.getRegistrationExpirationDateTime(), years); // Uncapped validateRegistrationPeriod(now, newExpirationTime); Optional feeRenew = eppInput.getSingleExtension(FeeRenewCommandExtension.class); @@ -328,8 +328,9 @@ public final class DomainRenewFlow implements MutatingFlow { // We only allow __REMOVE_BULK_PRICING__ token on bulk pricing domains for now verifyBulkTokenAllowedOnDomain(existingDomain, allocationToken); // If the date they specify doesn't match the expiration, fail. (This is an idempotence check). - if (!command.getCurrentExpirationDate().equals( - existingDomain.getRegistrationExpirationTime().toLocalDate())) { + if (!command + .getCurrentExpirationDate() + .equals(existingDomain.getRegistrationExpirationDateTime().toLocalDate())) { throw new IncorrectCurrentExpirationDateException(); } } diff --git a/core/src/main/java/google/registry/flows/domain/DomainRestoreRequestFlow.java b/core/src/main/java/google/registry/flows/domain/DomainRestoreRequestFlow.java index 29fc413d3..3ec154e7f 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainRestoreRequestFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainRestoreRequestFlow.java @@ -138,7 +138,7 @@ public final class DomainRestoreRequestFlow implements MutatingFlow { Update command = (Update) resourceCommand; DateTime now = tm().getTransactionTime(); Domain existingDomain = loadAndVerifyExistence(Domain.class, targetId, now); - boolean isExpired = existingDomain.getRegistrationExpirationTime().isBefore(now); + boolean isExpired = existingDomain.getRegistrationExpirationDateTime().isBefore(now); FeesAndCredits feesAndCredits = pricingLogic.getRestorePrice(Tld.get(existingDomain.getTld()), targetId, now, isExpired); Optional feeUpdate = @@ -149,7 +149,7 @@ public final class DomainRestoreRequestFlow implements MutatingFlow { ImmutableSet.Builder entitiesToInsert = new ImmutableSet.Builder<>(); DateTime newExpirationTime = - existingDomain.getRegistrationExpirationTime().plusYears(isExpired ? 1 : 0); + existingDomain.getRegistrationExpirationDateTime().plusYears(isExpired ? 1 : 0); // Restore the expiration time on the deleted domain, except if that's already passed, then add // a year and bill for it immediately, with no grace period. if (isExpired) { diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java index cea6f6568..7b7eb47b3 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java @@ -33,6 +33,8 @@ import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_ import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.util.CollectionUtils.union; import static google.registry.util.DateTimeUtils.END_OF_TIME; +import static google.registry.util.DateTimeUtils.toDateTime; +import static google.registry.util.DateTimeUtils.toInstant; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -193,7 +195,9 @@ public final class DomainTransferApproveFlow implements MutatingFlow { updateAutorenewRecurrenceEndTime( existingDomain, existingBillingRecurrence, now, domainHistoryId); DateTime newExpirationTime = - computeExDateForApprovalTime(existingDomain, now, transferData.getTransferPeriod()); + toDateTime( + computeExDateForApprovalTime( + existingDomain, toInstant(now), transferData.getTransferPeriod())); // Create a new autorenew event starting at the expiration time. BillingRecurrence autorenewEvent = new BillingRecurrence.Builder() @@ -268,8 +272,11 @@ public final class DomainTransferApproveFlow implements MutatingFlow { // been implicitly server approved. tm().delete(existingDomain.getTransferData().getServerApproveEntities()); return responseBuilder - .setResData(createTransferResponse( - targetId, newDomain.getTransferData(), newDomain.getRegistrationExpirationTime())) + .setResData( + createTransferResponse( + targetId, + newDomain.getTransferData(), + newDomain.getRegistrationExpirationDateTime())) .build(); } diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferQueryFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferQueryFlow.java index b562422b6..3e002f60c 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferQueryFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferQueryFlow.java @@ -15,15 +15,17 @@ package google.registry.flows.domain; import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn; +import static google.registry.flows.ResourceFlowUtils.computeExDateForApprovalTime; import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence; import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo; import static google.registry.flows.domain.DomainTransferUtils.createTransferResponse; +import static google.registry.util.DateTimeUtils.toDateTime; +import static google.registry.util.DateTimeUtils.toInstant; import google.registry.flows.EppException; import google.registry.flows.ExtensionManager; import google.registry.flows.FlowModule.RegistrarId; import google.registry.flows.FlowModule.TargetId; -import google.registry.flows.ResourceFlowUtils; import google.registry.flows.TransactionalFlow; import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.exceptions.NoTransferHistoryToQueryException; @@ -88,11 +90,12 @@ public final class DomainTransferQueryFlow implements TransactionalFlow { } DateTime newExpirationTime = null; if (transferData.getTransferStatus().isApproved()) { - newExpirationTime = transferData.getTransferredRegistrationExpirationTime(); + newExpirationTime = transferData.getTransferredRegistrationExpirationDateTime(); } else if (transferData.getTransferStatus().equals(TransferStatus.PENDING)) { newExpirationTime = - ResourceFlowUtils.computeExDateForApprovalTime( - domain, now, domain.getTransferData().getTransferPeriod()); + toDateTime( + computeExDateForApprovalTime( + domain, toInstant(now), domain.getTransferData().getTransferPeriod())); } return responseBuilder .setResData(createTransferResponse(targetId, transferData, newExpirationTime)) diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferRejectFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferRejectFlow.java index 351ee5e18..39b25d8d5 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferRejectFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferRejectFlow.java @@ -32,6 +32,7 @@ import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_ import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.util.CollectionUtils.union; import static google.registry.util.DateTimeUtils.END_OF_TIME; +import static google.registry.util.DateTimeUtils.toDateTime; import com.google.common.collect.ImmutableSet; import google.registry.flows.EppException; @@ -53,6 +54,7 @@ import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.tld.Tld; import google.registry.model.transfer.TransferStatus; import jakarta.inject.Inject; +import java.time.Instant; import java.util.Optional; import org.joda.time.DateTime; @@ -92,7 +94,7 @@ public final class DomainTransferRejectFlow implements MutatingFlow { extensionManager.register(MetadataExtension.class); validateRegistrarIsLoggedIn(registrarId); extensionManager.validate(); - DateTime now = tm().getTransactionTime(); + Instant now = tm().getTxTime(); Domain existingDomain = loadAndVerifyExistence(Domain.class, targetId, now); Tld tld = Tld.get(existingDomain.getTld()); HistoryEntryId domainHistoryId = createHistoryEntryId(existingDomain); @@ -107,13 +109,14 @@ public final class DomainTransferRejectFlow implements MutatingFlow { checkAllowedAccessToTld(registrarId, existingDomain.getTld()); } Domain newDomain = - denyPendingTransfer(existingDomain, TransferStatus.CLIENT_REJECTED, now, registrarId); - DomainHistory domainHistory = buildDomainHistory(newDomain, tld, now); + denyPendingTransfer( + existingDomain, TransferStatus.CLIENT_REJECTED, toDateTime(now), registrarId); + DomainHistory domainHistory = buildDomainHistory(newDomain, tld, toDateTime(now)); tm().update(newDomain); tm().insertAll( domainHistory, createGainingTransferPollMessage( - targetId, newDomain.getTransferData(), null, now, domainHistoryId)); + targetId, newDomain.getTransferData(), null, toDateTime(now), domainHistoryId)); // Reopen the autorenew event and poll message that we closed for the implicit transfer. This // may end up recreating the poll message if it was deleted upon the transfer request. BillingRecurrence existingBillingRecurrence = diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java index db7ce17bf..ad711a9b7 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java @@ -35,6 +35,8 @@ import static google.registry.flows.domain.DomainTransferUtils.createTransferSer import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING; import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; +import static google.registry.util.DateTimeUtils.toDateTime; +import static google.registry.util.DateTimeUtils.toInstant; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -80,6 +82,7 @@ import google.registry.model.transfer.DomainTransferData.TransferServerApproveEn import google.registry.model.transfer.TransferResponse.DomainTransferResponse; import google.registry.model.transfer.TransferStatus; import jakarta.inject.Inject; +import java.time.Instant; import java.util.Optional; import org.joda.time.DateTime; @@ -230,7 +233,9 @@ public final class DomainTransferRequestFlow implements MutatingFlow { Domain domainAtTransferTime = existingDomain.cloneProjectedAtTime(automaticTransferTime); // The new expiration time if there is a server approval. DateTime serverApproveNewExpirationTime = - computeExDateForApprovalTime(domainAtTransferTime, automaticTransferTime, period); + toDateTime( + computeExDateForApprovalTime( + domainAtTransferTime, toInstant(automaticTransferTime), period)); // Create speculative entities in anticipation of an automatic server approval. ImmutableSet serverApproveEntities = createTransferServerApproveEntities( @@ -287,7 +292,7 @@ public final class DomainTransferRequestFlow implements MutatingFlow { tm().insertAll(domainHistory, requestPollMessage); return responseBuilder .setResultFromCode(SUCCESS_WITH_ACTION_PENDING) - .setResData(createResponse(period, existingDomain, newDomain, now)) + .setResData(createResponse(period, existingDomain, newDomain, toInstant(now))) .setExtensions(createResponseExtensions(feesAndCredits, feeTransfer)) .build(); } @@ -375,14 +380,14 @@ public final class DomainTransferRequestFlow implements MutatingFlow { } private DomainTransferResponse createResponse( - Period period, Domain existingDomain, Domain newDomain, DateTime now) { + Period period, Domain existingDomain, Domain newDomain, Instant now) { // If the registration were approved this instant, this is what the new expiration would be, // because we cap at 10 years from the moment of approval. This is different from the server // approval new expiration time, which is capped at 10 years from the server approve time. - DateTime approveNowExtendedRegistrationTime = + Instant approveNowExtendedRegistrationTime = computeExDateForApprovalTime(existingDomain, now, period); return createTransferResponse( - targetId, newDomain.getTransferData(), approveNowExtendedRegistrationTime); + targetId, newDomain.getTransferData(), toDateTime(approveNowExtendedRegistrationTime)); } private static ImmutableList createResponseExtensions( diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferUtils.java b/core/src/main/java/google/registry/flows/domain/DomainTransferUtils.java index 60000b224..f9c0ab163 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferUtils.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferUtils.java @@ -184,7 +184,7 @@ public final class DomainTransferUtils { HistoryEntryId domainHistoryId) { return new PollMessage.OneTime.Builder() .setRegistrarId(transferData.getGainingRegistrarId()) - .setEventTime(transferData.getPendingTransferExpirationTime()) + .setEventTime(transferData.getPendingTransferExpirationDateTime()) .setMsg(transferData.getTransferStatus().getMessage()) .setResponseData( ImmutableList.of( @@ -206,7 +206,7 @@ public final class DomainTransferUtils { HistoryEntryId domainHistoryId) { return new PollMessage.OneTime.Builder() .setRegistrarId(transferData.getLosingRegistrarId()) - .setEventTime(transferData.getPendingTransferExpirationTime()) + .setEventTime(transferData.getPendingTransferExpirationDateTime()) .setMsg(transferData.getTransferStatus().getMessage()) .setResponseData( ImmutableList.of( @@ -224,7 +224,7 @@ public final class DomainTransferUtils { .setDomainName(targetId) .setGainingRegistrarId(transferData.getGainingRegistrarId()) .setLosingRegistrarId(transferData.getLosingRegistrarId()) - .setPendingTransferExpirationTime(transferData.getPendingTransferExpirationTime()) + .setPendingTransferExpirationTime(transferData.getPendingTransferExpirationDateTime()) .setTransferRequestTime(transferData.getTransferRequestTime()) .setTransferStatus(transferData.getTransferStatus()) .setExtendedRegistrationExpirationTime(extendedRegistrationExpirationTime) diff --git a/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java b/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java index 16f89e57b..752c194eb 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java @@ -281,7 +281,7 @@ public final class DomainUpdateFlow implements MutatingFlow { if (superuserExt.get().getAutorenews().isPresent()) { boolean autorenews = superuserExt.get().getAutorenews().get(); domainBuilder.setAutorenewEndTime( - Optional.ofNullable(autorenews ? null : domain.getRegistrationExpirationTime())); + Optional.ofNullable(autorenews ? null : domain.getRegistrationExpirationDateTime())); } } return domainBuilder.build(); diff --git a/core/src/main/java/google/registry/flows/host/HostInfoFlow.java b/core/src/main/java/google/registry/flows/host/HostInfoFlow.java index af5a5b258..4647ade89 100644 --- a/core/src/main/java/google/registry/flows/host/HostInfoFlow.java +++ b/core/src/main/java/google/registry/flows/host/HostInfoFlow.java @@ -99,7 +99,7 @@ public final class HostInfoFlow implements TransactionalFlow { .setCreationRegistrarId(host.getCreationRegistrarId()) .setCreationTime(host.getCreationTime()) .setLastEppUpdateRegistrarId(host.getLastEppUpdateRegistrarId()) - .setLastEppUpdateTime(host.getLastEppUpdateTime()) + .setLastEppUpdateTime(host.getLastEppUpdateDateTime()) .build()) .build(); } diff --git a/core/src/main/java/google/registry/model/EppResource.java b/core/src/main/java/google/registry/model/EppResource.java index ee5c376ef..f8007038f 100644 --- a/core/src/main/java/google/registry/model/EppResource.java +++ b/core/src/main/java/google/registry/model/EppResource.java @@ -25,6 +25,7 @@ import static google.registry.persistence.transaction.TransactionManagerFactory. import static google.registry.util.CollectionUtils.nullToEmpty; import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy; import static google.registry.util.DateTimeUtils.END_OF_TIME; +import static google.registry.util.DateTimeUtils.toInstant; import com.github.benmanes.caffeine.cache.CacheLoader; import com.github.benmanes.caffeine.cache.LoadingCache; @@ -45,6 +46,7 @@ import jakarta.persistence.Enumerated; import jakarta.persistence.MappedSuperclass; import jakarta.persistence.Transient; import java.time.Duration; +import java.time.Instant; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -163,10 +165,15 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B return creationRegistrarId; } - public DateTime getLastEppUpdateTime() { + @Deprecated + public DateTime getLastEppUpdateDateTime() { return lastEppUpdateTime; } + public Instant getLastEppUpdateTime() { + return toInstant(lastEppUpdateTime); + } + public String getLastEppUpdateRegistrarId() { return lastEppUpdateRegistrarId; } @@ -185,13 +192,22 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B return nullToEmptyImmutableCopy(statuses); } - public DateTime getDeletionTime() { + @Deprecated + public DateTime getDeletionDateTime() { return deletionTime; } + public Instant getDeletionTime() { + return toInstant(deletionTime); + } + /** Return a clone of the resource with timed status values modified using the given time. */ + @Deprecated public abstract EppResource cloneProjectedAtTime(DateTime now); + /** Return a clone of the resource with timed status values modified using the given time. */ + public abstract EppResource cloneProjectedAtInstant(Instant now); + /** Get the foreign key string for this resource. */ public abstract String getForeignKey(); diff --git a/core/src/main/java/google/registry/model/EppResourceUtils.java b/core/src/main/java/google/registry/model/EppResourceUtils.java index 4af8c6ccf..c64591ce4 100644 --- a/core/src/main/java/google/registry/model/EppResourceUtils.java +++ b/core/src/main/java/google/registry/model/EppResourceUtils.java @@ -34,6 +34,7 @@ import google.registry.model.transfer.DomainTransferData; import google.registry.model.transfer.TransferStatus; import google.registry.persistence.VKey; import jakarta.persistence.Query; +import java.time.Instant; import java.util.Comparator; import java.util.function.Function; import javax.annotation.Nullable; @@ -83,7 +84,7 @@ public final class EppResourceUtils { * exclusive, which happily maps to the behavior of Interval. */ private static Interval getLifetime(EppResource resource) { - return new Interval(resource.getCreationTime(), resource.getDeletionTime()); + return new Interval(resource.getCreationTime(), resource.getDeletionDateTime()); } public static boolean isActive(EppResource resource, DateTime time) { @@ -108,7 +109,7 @@ public final class EppResourceUtils { builder .removeStatusValue(StatusValue.PENDING_TRANSFER) .setTransferData(transferDataBuilder.build()) - .setLastTransferTime(transferData.getPendingTransferExpirationTime()) + .setLastTransferTime(transferData.getPendingTransferExpirationDateTime()) .setPersistedCurrentSponsorRegistrarId(transferData.getGainingRegistrarId()); } @@ -120,10 +121,10 @@ public final class EppResourceUtils { * */ public static void projectResourceOntoBuilderAtTime( - DomainBase domain, DomainBase.Builder builder, DateTime now) { + DomainBase domain, DomainBase.Builder builder, Instant now) { DomainTransferData transferData = domain.getTransferData(); // If there's a pending transfer that has expired, process it. - DateTime expirationTime = transferData.getPendingTransferExpirationTime(); + Instant expirationTime = transferData.getPendingTransferExpirationTime(); if (TransferStatus.PENDING.equals(transferData.getTransferStatus()) && isBeforeOrAt(expirationTime, now)) { setAutomaticTransferSuccessProperties(builder, transferData); diff --git a/core/src/main/java/google/registry/model/ForeignKeyUtils.java b/core/src/main/java/google/registry/model/ForeignKeyUtils.java index 9a0b08006..ba1ab670b 100644 --- a/core/src/main/java/google/registry/model/ForeignKeyUtils.java +++ b/core/src/main/java/google/registry/model/ForeignKeyUtils.java @@ -35,6 +35,7 @@ import google.registry.persistence.VKey; import google.registry.persistence.transaction.JpaTransactionManager; import google.registry.util.NonFinalForTesting; import java.time.Duration; +import java.time.Instant; import java.util.Collection; import java.util.Map; import java.util.Map.Entry; @@ -81,6 +82,7 @@ public final class ForeignKeyUtils { *

Returns null if no resource with this foreign key was ever created or if the most recently * created resource was deleted before time "now". */ + @Deprecated public static Optional loadResource( Class clazz, String foreignKey, DateTime now) { // Note: no need to project to "now" because loadResources already does @@ -88,6 +90,19 @@ public final class ForeignKeyUtils { loadResources(clazz, ImmutableList.of(foreignKey), now).get(foreignKey)); } + /** + * Loads an {@link EppResource} from the database by foreign key. + * + *

Returns null if no resource with this foreign key was ever created or if the most recently + * created resource was deleted before time "now". + */ + public static Optional loadResource( + Class clazz, String foreignKey, Instant now) { + // Note: no need to project to "now" because loadResources already does + return Optional.ofNullable( + loadResources(clazz, ImmutableList.of(foreignKey), now).get(foreignKey)); + } + /** * Load a map of {@link String} foreign keys to {@link VKey}s to {@link EppResource} that are * active at or after the specified moment in time. @@ -110,13 +125,29 @@ public final class ForeignKeyUtils { * or has been soft-deleted. */ @SuppressWarnings("unchecked") + @Deprecated public static ImmutableMap loadResources( Class clazz, Collection foreignKeys, DateTime now) { return loadMostRecentResourceObjects(clazz, foreignKeys, false).entrySet().stream() - .filter(e -> now.isBefore(e.getValue().getDeletionTime())) + .filter(e -> now.isBefore(e.getValue().getDeletionDateTime())) .collect(toImmutableMap(Entry::getKey, e -> (E) e.getValue().cloneProjectedAtTime(now))); } + /** + * Load a map of {@link String} foreign keys to the {@link EppResource} that are active at or + * after the specified moment in time. + * + *

The returned map will omit any foreign keys for which the {@link EppResource} doesn't exist + * or has been soft-deleted. + */ + @SuppressWarnings("unchecked") + public static ImmutableMap loadResources( + Class clazz, Collection foreignKeys, Instant now) { + return loadMostRecentResourceObjects(clazz, foreignKeys, false).entrySet().stream() + .filter(e -> now.isBefore(e.getValue().getDeletionTime())) + .collect(toImmutableMap(Entry::getKey, e -> (E) e.getValue().cloneProjectedAtInstant(now))); + } + /** * Helper method to load {@link VKey}s to all the most recent {@link EppResource}s for the given * foreign keys, regardless of whether they have been soft-deleted. @@ -397,7 +428,7 @@ public final class ForeignKeyUtils { return (Optional) foreignKeyToResourceCache .get(VKey.create(clazz, foreignKey)) - .filter(e -> now.isBefore(e.getDeletionTime())) + .filter(e -> now.isBefore(e.getDeletionDateTime())) .map(e -> e.cloneProjectedAtTime(now)); } } diff --git a/core/src/main/java/google/registry/model/ResourceTransferUtils.java b/core/src/main/java/google/registry/model/ResourceTransferUtils.java index c6a700266..7d4bc12c6 100644 --- a/core/src/main/java/google/registry/model/ResourceTransferUtils.java +++ b/core/src/main/java/google/registry/model/ResourceTransferUtils.java @@ -50,11 +50,11 @@ public final class ResourceTransferUtils { .setDomainName(domain.getForeignKey()) .setExtendedRegistrationExpirationTime( ADD_EXDATE_STATUSES.contains(transferData.getTransferStatus()) - ? transferData.getTransferredRegistrationExpirationTime() + ? transferData.getTransferredRegistrationExpirationDateTime() : null) .setGainingRegistrarId(transferData.getGainingRegistrarId()) .setLosingRegistrarId(transferData.getLosingRegistrarId()) - .setPendingTransferExpirationTime(transferData.getPendingTransferExpirationTime()) + .setPendingTransferExpirationTime(transferData.getPendingTransferExpirationDateTime()) .setTransferRequestTime(transferData.getTransferRequestTime()) .setTransferStatus(transferData.getTransferStatus()) .build(); diff --git a/core/src/main/java/google/registry/model/billing/BillingCancellation.java b/core/src/main/java/google/registry/model/billing/BillingCancellation.java index 1adc3a8f1..045e87b95 100644 --- a/core/src/main/java/google/registry/model/billing/BillingCancellation.java +++ b/core/src/main/java/google/registry/model/billing/BillingCancellation.java @@ -104,7 +104,7 @@ public class BillingCancellation extends BillingBase { .setRegistrarId(gracePeriod.getRegistrarId()) .setEventTime(eventTime) // The charge being cancelled will take place at the grace period's expiration time. - .setBillingTime(gracePeriod.getExpirationTime()) + .setBillingTime(gracePeriod.getExpirationDateTime()) .setDomainHistoryId(domainHistoryId); // Set the grace period's billing event using the appropriate Cancellation builder method. if (gracePeriod.getBillingEvent() != null) { diff --git a/core/src/main/java/google/registry/model/domain/Domain.java b/core/src/main/java/google/registry/model/domain/Domain.java index 9a9715243..cff00f4db 100644 --- a/core/src/main/java/google/registry/model/domain/Domain.java +++ b/core/src/main/java/google/registry/model/domain/Domain.java @@ -14,6 +14,8 @@ package google.registry.model.domain; +import static google.registry.util.DateTimeUtils.toInstant; + import google.registry.model.EppResource; import google.registry.model.EppResource.ForeignKeyedEppResource; import google.registry.model.annotations.ExternalMessagingName; @@ -37,6 +39,7 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinTable; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; +import java.time.Instant; import java.util.Set; import org.hibernate.Hibernate; import org.joda.time.DateTime; @@ -153,6 +156,11 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource { @Override public Domain cloneProjectedAtTime(final DateTime now) { + return cloneDomainProjectedAtTime(this, toInstant(now)); + } + + @Override + public Domain cloneProjectedAtInstant(final Instant now) { return cloneDomainProjectedAtTime(this, now); } diff --git a/core/src/main/java/google/registry/model/domain/DomainBase.java b/core/src/main/java/google/registry/model/domain/DomainBase.java index 573f5d213..1f051b567 100644 --- a/core/src/main/java/google/registry/model/domain/DomainBase.java +++ b/core/src/main/java/google/registry/model/domain/DomainBase.java @@ -32,9 +32,14 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.earliestOf; import static google.registry.util.DateTimeUtils.isBeforeOrAt; import static google.registry.util.DateTimeUtils.leapSafeAddYears; +import static google.registry.util.DateTimeUtils.plusYears; +import static google.registry.util.DateTimeUtils.toDateTime; +import static google.registry.util.DateTimeUtils.toInstant; import static google.registry.util.DomainNameUtils.canonicalizeHostname; import static google.registry.util.DomainNameUtils.getTldFromDomainName; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; +import static java.time.ZoneOffset.UTC; +import static java.time.temporal.ChronoUnit.YEARS; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; @@ -79,13 +84,13 @@ import jakarta.persistence.Enumerated; import jakarta.persistence.Id; import jakarta.persistence.MappedSuperclass; import jakarta.persistence.Transient; +import java.time.Instant; import java.util.HashSet; import java.util.Optional; import java.util.Set; import javax.annotation.Nullable; import org.hibernate.collection.spi.PersistentSet; import org.joda.time.DateTime; -import org.joda.time.Interval; /** * A persistable domain resource including mutable and non-mutable fields. @@ -285,10 +290,15 @@ public class DomainBase extends EppResource { return nullToEmptyImmutableCopy(subordinateHosts); } - public DateTime getRegistrationExpirationTime() { + @Deprecated + public DateTime getRegistrationExpirationDateTime() { return registrationExpirationTime; } + public Instant getRegistrationExpirationTime() { + return toInstant(registrationExpirationTime); + } + public VKey getDeletePollMessage() { return deletePollMessage; } @@ -436,6 +446,11 @@ public class DomainBase extends EppResource { @Override public DomainBase cloneProjectedAtTime(final DateTime now) { + return cloneDomainProjectedAtTime(this, toInstant(now)); + } + + @Override + public DomainBase cloneProjectedAtInstant(final Instant now) { return cloneDomainProjectedAtTime(this, now); } @@ -444,9 +459,9 @@ public class DomainBase extends EppResource { * parallels the logic in {@code DomainTransferApproveFlow} which handles explicit client * approvals. */ - static T cloneDomainProjectedAtTime(T domain, DateTime now) { + static T cloneDomainProjectedAtTime(T domain, Instant now) { DomainTransferData transferData = domain.getTransferData(); - DateTime transferExpirationTime = transferData.getPendingTransferExpirationTime(); + Instant transferExpirationTime = transferData.getPendingTransferExpirationTime(); // If there's a pending transfer that has expired, handle it. if (TransferStatus.PENDING.equals(transferData.getTransferStatus()) @@ -459,7 +474,7 @@ public class DomainBase extends EppResource { T domainAtTransferTime = cloneDomainProjectedAtTime(domain, transferExpirationTime.minusMillis(1)); - DateTime expirationDate = transferData.getTransferredRegistrationExpirationTime(); + Instant expirationDate = transferData.getTransferredRegistrationExpirationTime(); if (expirationDate == null) { // Extend the registration by the correct number of years from the expiration time // that was current on the domain right before the transfer, capped at 10 years from @@ -478,7 +493,7 @@ public class DomainBase extends EppResource { Builder builder = domainAtTransferTime .asBuilder() - .setRegistrationExpirationTime(expirationDate) + .setRegistrationExpirationTime(toDateTime(expirationDate)) // Set the speculatively-written new autorenew events as the domain's autorenew // events. .setAutorenewBillingEvent(transferData.getServerApproveAutorenewEvent()) @@ -492,8 +507,8 @@ public class DomainBase extends EppResource { GracePeriod.create( GracePeriodStatus.TRANSFER, domain.getRepoId(), - transferExpirationTime.plus( - Tld.get(domain.getTld()).getTransferGracePeriodLength()), + toDateTime(transferExpirationTime) + .plus(Tld.get(domain.getTld()).getTransferGracePeriodLength()), transferData.getGainingRegistrarId(), transferData.getServerApproveBillingEvent()))); } else { @@ -503,32 +518,33 @@ public class DomainBase extends EppResource { // Set all remaining transfer properties. setAutomaticTransferSuccessProperties(builder, transferData); builder - .setLastEppUpdateTime(transferExpirationTime) + .setLastEppUpdateTime(toDateTime(transferExpirationTime)) .setLastEppUpdateRegistrarId(transferData.getGainingRegistrarId()); // Finish projecting to now. - return (T) builder.build().cloneProjectedAtTime(now); + return (T) builder.build().cloneProjectedAtInstant(now); } - Optional newLastEppUpdateTime = Optional.empty(); + Optional newLastEppUpdateTime = Optional.empty(); // There is no transfer. Do any necessary autorenews for active domains. Builder builder = domain.asBuilder(); if (isBeforeOrAt(domain.getRegistrationExpirationTime(), now) - && END_OF_TIME.equals(domain.getDeletionTime())) { + && END_OF_TIME.equals(domain.getDeletionDateTime())) { // Autorenew by the number of years between the old expiration time and now. - DateTime lastAutorenewTime = + Instant lastAutorenewTime = leapSafeAddYears( domain.getRegistrationExpirationTime(), - new Interval(domain.getRegistrationExpirationTime(), now).toPeriod().getYears()); - DateTime newExpirationTime = lastAutorenewTime.plusYears(1); + YEARS.between(domain.getRegistrationExpirationTime().atZone(UTC), now.atZone(UTC))); + Instant newExpirationTime = plusYears(lastAutorenewTime, 1); builder - .setRegistrationExpirationTime(newExpirationTime) + .setRegistrationExpirationTime(toDateTime(newExpirationTime)) .addGracePeriod( GracePeriod.createForRecurrence( GracePeriodStatus.AUTO_RENEW, domain.getRepoId(), - lastAutorenewTime.plus(Tld.get(domain.getTld()).getAutoRenewGracePeriodLength()), + toDateTime(lastAutorenewTime) + .plus(Tld.get(domain.getTld()).getAutoRenewGracePeriodLength()), domain.getCurrentSponsorRegistrarId(), domain.getAutorenewBillingEvent())); newLastEppUpdateTime = Optional.of(lastAutorenewTime); @@ -551,10 +567,10 @@ public class DomainBase extends EppResource { // id, so we have to do the comparison instead of having one variable just storing the most // recent time. if (newLastEppUpdateTime.isPresent()) { - if (domain.getLastEppUpdateTime() == null + if (domain.getLastEppUpdateDateTime() == null || newLastEppUpdateTime.get().isAfter(domain.getLastEppUpdateTime())) { builder - .setLastEppUpdateTime(newLastEppUpdateTime.get()) + .setLastEppUpdateTime(toDateTime(newLastEppUpdateTime.get())) .setLastEppUpdateRegistrarId(domain.getCurrentSponsorRegistrarId()); } } @@ -567,8 +583,8 @@ public class DomainBase extends EppResource { } /** Return what the expiration time would be if the given number of years were added to it. */ - public static DateTime extendRegistrationWithCap( - DateTime now, DateTime currentExpirationTime, @Nullable Integer extendedRegistrationYears) { + public static Instant extendRegistrationWithCap( + Instant now, Instant currentExpirationTime, @Nullable Integer extendedRegistrationYears) { // We must cap registration at the max years (aka 10), even if that truncates the last year. return earliestOf( leapSafeAddYears( @@ -826,16 +842,16 @@ public class DomainBase extends EppResource { .setDomainName(domainBase.getDomainName()) .setDeletePollMessage(domainBase.getDeletePollMessage()) .setDsData(domainBase.getDsData()) - .setDeletionTime(domainBase.getDeletionTime()) + .setDeletionTime(domainBase.getDeletionDateTime()) .setGracePeriods(domainBase.getGracePeriods()) .setIdnTableName(domainBase.getIdnTableName()) .setLastTransferTime(domainBase.getLastTransferTime()) .setLaunchNotice(domainBase.getLaunchNotice()) .setLastEppUpdateRegistrarId(domainBase.getLastEppUpdateRegistrarId()) - .setLastEppUpdateTime(domainBase.getLastEppUpdateTime()) + .setLastEppUpdateTime(domainBase.getLastEppUpdateDateTime()) .setNameservers(domainBase.getNameservers()) .setPersistedCurrentSponsorRegistrarId(domainBase.getPersistedCurrentSponsorRegistrarId()) - .setRegistrationExpirationTime(domainBase.getRegistrationExpirationTime()) + .setRegistrationExpirationTime(domainBase.getRegistrationExpirationDateTime()) .setRepoId(domainBase.getRepoId()) .setSmdId(domainBase.getSmdId()) .setSubordinateHosts(domainBase.getSubordinateHosts()) diff --git a/core/src/main/java/google/registry/model/domain/GracePeriodBase.java b/core/src/main/java/google/registry/model/domain/GracePeriodBase.java index a53abe457..cca7742ed 100644 --- a/core/src/main/java/google/registry/model/domain/GracePeriodBase.java +++ b/core/src/main/java/google/registry/model/domain/GracePeriodBase.java @@ -14,6 +14,8 @@ package google.registry.model.domain; +import static google.registry.util.DateTimeUtils.toInstant; + import google.registry.model.ImmutableObject; import google.registry.model.UnsafeSerializable; import google.registry.model.billing.BillingEvent; @@ -30,6 +32,7 @@ import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; import jakarta.persistence.MappedSuperclass; import jakarta.persistence.Transient; +import java.time.Instant; import org.joda.time.DateTime; /** Base class containing common fields and methods for {@link GracePeriod}. */ @@ -90,10 +93,15 @@ public class GracePeriodBase extends ImmutableObject implements UnsafeSerializab return domainRepoId; } - public DateTime getExpirationTime() { + @Deprecated + public DateTime getExpirationDateTime() { return expirationTime; } + public Instant getExpirationTime() { + return toInstant(expirationTime); + } + public String getRegistrarId() { return clientId; } diff --git a/core/src/main/java/google/registry/model/host/HostBase.java b/core/src/main/java/google/registry/model/host/HostBase.java index 8b70e49fc..66480452b 100644 --- a/core/src/main/java/google/registry/model/host/HostBase.java +++ b/core/src/main/java/google/registry/model/host/HostBase.java @@ -33,6 +33,7 @@ import jakarta.persistence.Column; import jakarta.persistence.Convert; import jakarta.persistence.MappedSuperclass; import java.net.InetAddress; +import java.time.Instant; import java.util.Optional; import java.util.Set; import javax.annotation.Nullable; @@ -132,6 +133,11 @@ public class HostBase extends EppResource { return this; } + @Override + public EppResource cloneProjectedAtInstant(Instant now) { + return this; + } + @Override public Builder asBuilder() { return new Builder<>(clone(this)); @@ -232,13 +238,13 @@ public class HostBase extends EppResource { public B copyFrom(HostBase hostBase) { return setCreationRegistrarId(hostBase.getCreationRegistrarId()) .setCreationTime(hostBase.getCreationTime()) - .setDeletionTime(hostBase.getDeletionTime()) + .setDeletionTime(hostBase.getDeletionDateTime()) .setHostName(hostBase.getHostName()) .setInetAddresses(hostBase.getInetAddresses()) .setLastTransferTime(hostBase.getLastTransferTime()) .setLastSuperordinateChange(hostBase.getLastSuperordinateChange()) .setLastEppUpdateRegistrarId(hostBase.getLastEppUpdateRegistrarId()) - .setLastEppUpdateTime(hostBase.getLastEppUpdateTime()) + .setLastEppUpdateTime(hostBase.getLastEppUpdateDateTime()) .setPersistedCurrentSponsorRegistrarId(hostBase.getPersistedCurrentSponsorRegistrarId()) .setRepoId(hostBase.getRepoId()) .setSuperordinateDomain(hostBase.getSuperordinateDomain()) diff --git a/core/src/main/java/google/registry/model/poll/PollMessage.java b/core/src/main/java/google/registry/model/poll/PollMessage.java index 2e73951e3..161722661 100644 --- a/core/src/main/java/google/registry/model/poll/PollMessage.java +++ b/core/src/main/java/google/registry/model/poll/PollMessage.java @@ -437,7 +437,7 @@ public abstract class PollMessage extends ImmutableObject .setTransferStatus(transferResponse.getTransferStatus()) .setTransferRequestTime(transferResponse.getTransferRequestTime()) .setPendingTransferExpirationTime( - transferResponse.getPendingTransferExpirationTime()) + transferResponse.getPendingTransferExpirationDateTime()) .setExtendedRegistrationExpirationTime(extendedRegistrationExpirationTime) .build(); } diff --git a/core/src/main/java/google/registry/model/transfer/BaseTransferObject.java b/core/src/main/java/google/registry/model/transfer/BaseTransferObject.java index 9c55b52a1..e1a0a04c1 100644 --- a/core/src/main/java/google/registry/model/transfer/BaseTransferObject.java +++ b/core/src/main/java/google/registry/model/transfer/BaseTransferObject.java @@ -14,6 +14,8 @@ package google.registry.model.transfer; +import static google.registry.util.DateTimeUtils.toInstant; + import google.registry.model.Buildable.GenericBuilder; import google.registry.model.ImmutableObject; import google.registry.model.UnsafeSerializable; @@ -23,6 +25,7 @@ import jakarta.persistence.Enumerated; import jakarta.persistence.MappedSuperclass; import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlTransient; +import java.time.Instant; import org.joda.time.DateTime; /** Fields common to {@link DomainTransferData} and {@link TransferResponse}. */ @@ -73,10 +76,15 @@ public abstract class BaseTransferObject extends ImmutableObject implements Unsa return losingClientId; } - public DateTime getPendingTransferExpirationTime() { + @Deprecated + public DateTime getPendingTransferExpirationDateTime() { return pendingTransferExpirationTime; } + public Instant getPendingTransferExpirationTime() { + return toInstant(pendingTransferExpirationTime); + } + /** Base class for builders of {@link BaseTransferObject} subclasses. */ public abstract static class Builder> extends GenericBuilder { diff --git a/core/src/main/java/google/registry/model/transfer/DomainTransferData.java b/core/src/main/java/google/registry/model/transfer/DomainTransferData.java index 7ecb17e26..a56c3889d 100644 --- a/core/src/main/java/google/registry/model/transfer/DomainTransferData.java +++ b/core/src/main/java/google/registry/model/transfer/DomainTransferData.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.ImmutableList.toImmutableList; import static google.registry.util.CollectionUtils.isNullOrEmpty; import static google.registry.util.CollectionUtils.nullToEmpty; +import static google.registry.util.DateTimeUtils.toInstant; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -41,6 +42,7 @@ import jakarta.persistence.Column; import jakarta.persistence.Convert; import jakarta.persistence.Embeddable; import jakarta.persistence.Embedded; +import java.time.Instant; import java.util.Set; import javax.annotation.Nullable; import org.joda.time.DateTime; @@ -168,10 +170,16 @@ public class DomainTransferData extends BaseTransferObject implements Buildable } @Nullable - public DateTime getTransferredRegistrationExpirationTime() { + @Deprecated + public DateTime getTransferredRegistrationExpirationDateTime() { return transferredRegistrationExpirationTime; } + @Nullable + public Instant getTransferredRegistrationExpirationTime() { + return toInstant(transferredRegistrationExpirationTime); + } + @Nullable public VKey getServerApproveBillingEvent() { return serverApproveBillingEvent; diff --git a/core/src/main/java/google/registry/persistence/transaction/JpaTransactionManagerImpl.java b/core/src/main/java/google/registry/persistence/transaction/JpaTransactionManagerImpl.java index f1633b7c1..4502a7d39 100644 --- a/core/src/main/java/google/registry/persistence/transaction/JpaTransactionManagerImpl.java +++ b/core/src/main/java/google/registry/persistence/transaction/JpaTransactionManagerImpl.java @@ -21,6 +21,7 @@ import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static google.registry.config.RegistryConfig.getHibernateAllowNestedTransactions; import static google.registry.persistence.transaction.DatabaseException.throwIfSqlException; +import static google.registry.util.DateTimeUtils.toDateTime; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import static java.util.AbstractMap.SimpleEntry; import static java.util.stream.Collectors.joining; @@ -61,6 +62,7 @@ import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.time.Instant; import java.util.Calendar; import java.util.Collections; import java.util.Date; @@ -340,6 +342,11 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager { @Override public DateTime getTransactionTime() { + return toDateTime(getTxTime()); + } + + @Override + public Instant getTxTime() { assertInTransaction(); TransactionInfo txnInfo = transactionInfo.get(); if (txnInfo.transactionTime == null) { @@ -746,7 +753,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager { private static class TransactionInfo { EntityManager entityManager; boolean inTransaction = false; - DateTime transactionTime; + Instant transactionTime; Supplier idProvider; // The set of entity objects that have been either persisted (via insert()) or merged (via @@ -759,7 +766,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager { private void start(Clock clock, Supplier idProvider) { checkArgumentNotNull(clock); inTransaction = true; - transactionTime = clock.nowUtc(); + transactionTime = clock.now(); this.idProvider = idProvider; } diff --git a/core/src/main/java/google/registry/persistence/transaction/TransactionManager.java b/core/src/main/java/google/registry/persistence/transaction/TransactionManager.java index 8cd63befe..aa49bb9b7 100644 --- a/core/src/main/java/google/registry/persistence/transaction/TransactionManager.java +++ b/core/src/main/java/google/registry/persistence/transaction/TransactionManager.java @@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableMap; import google.registry.model.ImmutableObject; import google.registry.persistence.PersistenceModule.TransactionIsolationLevel; import google.registry.persistence.VKey; +import java.time.Instant; import java.util.NoSuchElementException; import java.util.Optional; import java.util.concurrent.Callable; @@ -129,8 +130,12 @@ public interface TransactionManager { void reTransact(ThrowingRunnable work); /** Returns the time associated with the start of this particular transaction attempt. */ + @Deprecated DateTime getTransactionTime(); + /** Returns the Instant associated with the start of this particular transaction attempt. */ + Instant getTxTime(); + /** Persists a new entity in the database, throws exception if the entity already exists. */ void insert(Object entity); diff --git a/core/src/main/java/google/registry/rdap/RdapActionBase.java b/core/src/main/java/google/registry/rdap/RdapActionBase.java index 2b23be750..94804bf0a 100644 --- a/core/src/main/java/google/registry/rdap/RdapActionBase.java +++ b/core/src/main/java/google/registry/rdap/RdapActionBase.java @@ -17,6 +17,7 @@ package google.registry.rdap; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN; import static google.registry.request.Actions.getPathForAction; +import static google.registry.util.DateTimeUtils.toInstant; import static google.registry.util.DomainNameUtils.canonicalizeHostname; import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST; import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; @@ -241,7 +242,7 @@ public abstract class RdapActionBase implements Runnable { * is authorized to do so. */ boolean isAuthorized(EppResource eppResource) { - return getRequestTime().isBefore(eppResource.getDeletionTime()) + return toInstant(getRequestTime()).isBefore(eppResource.getDeletionTime()) || (shouldIncludeDeleted() && rdapAuthorization.isAuthorizedForRegistrar( eppResource.getPersistedCurrentSponsorRegistrarId())); diff --git a/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java b/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java index 9ba0d7c7b..44fcf0744 100644 --- a/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java +++ b/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java @@ -318,7 +318,7 @@ public class RdapJsonFormatter { .build(), Event.builder() .setEventAction(EventAction.EXPIRATION) - .setEventDate(domain.getRegistrationExpirationTime()) + .setEventDate(domain.getRegistrationExpirationDateTime()) .build(), // RDAP response profile section 1.5: // The topmost object in the RDAP response MUST contain an event of "eventAction" type @@ -361,7 +361,7 @@ public class RdapJsonFormatter { makeStatusValueList( allStatusValues, false, // isRedacted - domain.getDeletionTime().isBefore(getRequestTime())); + domain.getDeletionDateTime().isBefore(getRequestTime())); builder.statusBuilder().addAll(status); if (status.isEmpty()) { logger.atWarning().log( @@ -447,7 +447,7 @@ public class RdapJsonFormatter { makeStatusValueList( statuses.build(), false, // isRedacted - host.getDeletionTime().isBefore(getRequestTime()))); + host.getDeletionDateTime().isBefore(getRequestTime()))); } // For query responses - we MUST have all the ip addresses: RDAP Response Profile 4.2. @@ -761,7 +761,9 @@ public class RdapJsonFormatter { ImmutableList.Builder eventsBuilder = new ImmutableList.Builder<>(); DateTime creationTime = resource.getCreationTime(); DateTime lastChangeTime = - resource.getLastEppUpdateTime() == null ? creationTime : resource.getLastEppUpdateTime(); + resource.getLastEppUpdateDateTime() == null + ? creationTime + : resource.getLastEppUpdateDateTime(); // The order of the elements is stable - it's the order in which the enum elements are defined // in EventAction for (EventAction rdapEventAction : EventAction.values()) { diff --git a/core/src/main/java/google/registry/rde/DomainToXjcConverter.java b/core/src/main/java/google/registry/rde/DomainToXjcConverter.java index fe671a28d..89f4be1a0 100644 --- a/core/src/main/java/google/registry/rde/DomainToXjcConverter.java +++ b/core/src/main/java/google/registry/rde/DomainToXjcConverter.java @@ -94,13 +94,13 @@ final class DomainToXjcConverter { // identifying the end (expiration) of the domain name object's // registration period. This element MUST be present if the domain // name has been allocated. - bean.setExDate(model.getRegistrationExpirationTime()); + bean.setExDate(model.getRegistrationExpirationDateTime()); // o An OPTIONAL element that contains the date and time of // the most recent domain-name-object modification. This element // MUST NOT be present if the domain name object has never been // modified. - bean.setUpDate(model.getLastEppUpdateTime()); + bean.setUpDate(model.getLastEppUpdateDateTime()); // o An OPTIONAL element that contains the identifier of the // registrar that last updated the domain name object. This element @@ -228,8 +228,8 @@ final class DomainToXjcConverter { bean.setReRr(RdeUtils.makeXjcRdeRrType(model.getGainingRegistrarId())); bean.setAcRr(RdeUtils.makeXjcRdeRrType(model.getLosingRegistrarId())); bean.setReDate(model.getTransferRequestTime()); - bean.setAcDate(model.getPendingTransferExpirationTime()); - bean.setExDate(model.getTransferredRegistrationExpirationTime()); + bean.setAcDate(model.getPendingTransferExpirationDateTime()); + bean.setExDate(model.getTransferredRegistrationExpirationDateTime()); return bean; } diff --git a/core/src/main/java/google/registry/rde/HostToXjcConverter.java b/core/src/main/java/google/registry/rde/HostToXjcConverter.java index 3f75703ee..f822871aa 100644 --- a/core/src/main/java/google/registry/rde/HostToXjcConverter.java +++ b/core/src/main/java/google/registry/rde/HostToXjcConverter.java @@ -70,7 +70,7 @@ final class HostToXjcConverter { bean.setName(model.getHostName()); bean.setRoid(model.getRepoId()); bean.setCrDate(model.getCreationTime()); - bean.setUpDate(model.getLastEppUpdateTime()); + bean.setUpDate(model.getLastEppUpdateDateTime()); bean.setCrRr(RdeAdapter.convertRr(model.getCreationRegistrarId(), null)); bean.setUpRr(RdeAdapter.convertRr(model.getLastEppUpdateRegistrarId(), null)); bean.setCrRr(RdeAdapter.convertRr(model.getCreationRegistrarId(), null)); diff --git a/core/src/main/java/google/registry/tools/GenerateDnsReportCommand.java b/core/src/main/java/google/registry/tools/GenerateDnsReportCommand.java index f4aad1d54..88e0a3679 100644 --- a/core/src/main/java/google/registry/tools/GenerateDnsReportCommand.java +++ b/core/src/main/java/google/registry/tools/GenerateDnsReportCommand.java @@ -81,7 +81,7 @@ final class GenerateDnsReportCommand implements Command { .list()); for (Domain domain : domains) { // Skip deleted domains and domains that don't get published to DNS. - if (isBeforeOrAt(domain.getDeletionTime(), now) || !domain.shouldPublishToDns()) { + if (isBeforeOrAt(domain.getDeletionDateTime(), now) || !domain.shouldPublishToDns()) { continue; } write(domain); @@ -90,7 +90,7 @@ final class GenerateDnsReportCommand implements Command { Iterable nameservers = tm().transact(() -> tm().loadAllOf(Host.class)); for (Host nameserver : nameservers) { // Skip deleted hosts and external hosts. - if (isBeforeOrAt(nameserver.getDeletionTime(), now) + if (isBeforeOrAt(nameserver.getDeletionDateTime(), now) || nameserver.getInetAddresses().isEmpty()) { continue; } diff --git a/core/src/main/java/google/registry/tools/RenewDomainCommand.java b/core/src/main/java/google/registry/tools/RenewDomainCommand.java index 81f262634..838db13ce 100644 --- a/core/src/main/java/google/registry/tools/RenewDomainCommand.java +++ b/core/src/main/java/google/registry/tools/RenewDomainCommand.java @@ -81,7 +81,7 @@ final class RenewDomainCommand extends MutatingEppToolCommand { SoyMapData soyMapData = new SoyMapData( "domainName", domain.getDomainName(), - "expirationDate", domain.getRegistrationExpirationTime().toString(DATE_FORMATTER), + "expirationDate", domain.getRegistrationExpirationDateTime().toString(DATE_FORMATTER), "period", String.valueOf(period)); if (requestedByRegistrar != null) { diff --git a/core/src/main/java/google/registry/tools/UniformRapidSuspensionCommand.java b/core/src/main/java/google/registry/tools/UniformRapidSuspensionCommand.java index 1f3368ef2..77290a852 100644 --- a/core/src/main/java/google/registry/tools/UniformRapidSuspensionCommand.java +++ b/core/src/main/java/google/registry/tools/UniformRapidSuspensionCommand.java @@ -163,7 +163,7 @@ final class UniformRapidSuspensionCommand extends MutatingEppToolCommand { domain.getDomainName(), "expirationDate", domain - .getRegistrationExpirationTime() + .getRegistrationExpirationDateTime() .toString(DateTimeFormat.forPattern("YYYY-MM-dd")), // period is the number of years to renew the registration for "period", diff --git a/core/src/main/java/google/registry/tools/UnrenewDomainCommand.java b/core/src/main/java/google/registry/tools/UnrenewDomainCommand.java index 29613a8ec..06866ebca 100644 --- a/core/src/main/java/google/registry/tools/UnrenewDomainCommand.java +++ b/core/src/main/java/google/registry/tools/UnrenewDomainCommand.java @@ -99,8 +99,9 @@ class UnrenewDomainCommand extends ConfirmingCommand { domainsWithDisallowedStatusesBuilder.putAll( domainName, Sets.intersection(domain.get().getStatusValues(), DISALLOWED_STATUSES)); if (isBeforeOrAt( - leapSafeSubtractYears(domain.get().getRegistrationExpirationTime(), period), now)) { - domainsExpiringTooSoonBuilder.put(domainName, domain.get().getRegistrationExpirationTime()); + leapSafeSubtractYears(domain.get().getRegistrationExpirationDateTime(), period), now)) { + domainsExpiringTooSoonBuilder.put( + domainName, domain.get().getRegistrationExpirationDateTime()); } } @@ -143,7 +144,7 @@ class UnrenewDomainCommand extends ConfirmingCommand { DateTime now = clock.nowUtc(); for (String domainName : mainParameters) { Domain domain = ForeignKeyUtils.loadResource(Domain.class, domainName, now).get(); - DateTime previousTime = domain.getRegistrationExpirationTime(); + DateTime previousTime = domain.getRegistrationExpirationDateTime(); DateTime newTime = leapSafeSubtractYears(previousTime, period); resultBuilder.append( String.format( @@ -179,12 +180,12 @@ class UnrenewDomainCommand extends ConfirmingCommand { "Domain %s has prohibited status values", domainName); checkState( - leapSafeSubtractYears(domain.getRegistrationExpirationTime(), period).isAfter(now), + leapSafeSubtractYears(domain.getRegistrationExpirationDateTime(), period).isAfter(now), "Domain %s expires too soon", domainName); DateTime newExpirationTime = - leapSafeSubtractYears(domain.getRegistrationExpirationTime(), period); + leapSafeSubtractYears(domain.getRegistrationExpirationDateTime(), period); DomainHistory domainHistory = new DomainHistory.Builder() .setDomain(domain) diff --git a/core/src/main/java/google/registry/tools/UpdateRecurrenceCommand.java b/core/src/main/java/google/registry/tools/UpdateRecurrenceCommand.java index 871201482..73a300ae8 100644 --- a/core/src/main/java/google/registry/tools/UpdateRecurrenceCommand.java +++ b/core/src/main/java/google/registry/tools/UpdateRecurrenceCommand.java @@ -16,7 +16,9 @@ package google.registry.tools; import static com.google.common.base.Preconditions.checkArgument; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; +import static google.registry.util.DateTimeUtils.END_INSTANT; import static google.registry.util.DateTimeUtils.END_OF_TIME; +import static google.registry.util.DateTimeUtils.toDateTime; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; @@ -31,6 +33,7 @@ import google.registry.model.domain.DomainHistory; import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry.HistoryEntryId; import google.registry.model.transfer.TransferStatus; +import java.time.Instant; import java.util.List; import java.util.Optional; import javax.annotation.Nullable; @@ -161,7 +164,7 @@ public class UpdateRecurrenceCommand extends ConfirmingCommand { private ImmutableMap loadDomainsAndRecurrences() { ImmutableMap.Builder result = new ImmutableMap.Builder<>(); - DateTime now = tm().getTransactionTime(); + Instant now = tm().getTxTime(); for (String domainName : mainParameters) { Domain domain = ForeignKeyUtils.loadResource(Domain.class, domainName, now) @@ -171,7 +174,7 @@ public class UpdateRecurrenceCommand extends ConfirmingCommand { String.format( "Domain %s does not exist or has been deleted", domainName))); checkArgument( - domain.getDeletionTime().equals(END_OF_TIME), + domain.getDeletionTime().equals(END_INSTANT), "Domain %s has already had a deletion time set", domainName); checkArgument( @@ -184,7 +187,7 @@ public class UpdateRecurrenceCommand extends ConfirmingCommand { domainAutorenewEndTime.ifPresent( endTime -> checkArgument( - endTime.isAfter(now), + endTime.isAfter(toDateTime(now)), "Domain %s autorenew ended prior to now at %s", domainName, endTime)); diff --git a/core/src/test/java/google/registry/batch/DeleteExpiredDomainsActionTest.java b/core/src/test/java/google/registry/batch/DeleteExpiredDomainsActionTest.java index 6fe869496..0315dedd6 100644 --- a/core/src/test/java/google/registry/batch/DeleteExpiredDomainsActionTest.java +++ b/core/src/test/java/google/registry/batch/DeleteExpiredDomainsActionTest.java @@ -24,6 +24,7 @@ import static google.registry.testing.DatabaseHelper.loadByEntity; import static google.registry.testing.DatabaseHelper.persistActiveDomain; import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.util.DateTimeUtils.END_OF_TIME; +import static google.registry.util.DateTimeUtils.plusDays; import com.google.common.collect.ImmutableSet; import google.registry.flows.DaggerEppTestComponent; @@ -117,7 +118,7 @@ class DeleteExpiredDomainsActionTest { assertThat(loadByEntity(notYetExpiredDomain)).isEqualTo(notYetExpiredDomain); Domain reloadedExpiredDomain = loadByEntity(pendingExpirationDomain); assertThat(reloadedExpiredDomain.getStatusValues()).contains(PENDING_DELETE); - assertThat(reloadedExpiredDomain.getDeletionTime()).isEqualTo(clock.nowUtc().plusDays(35)); + assertThat(reloadedExpiredDomain.getDeletionTime()).isEqualTo(plusDays(clock.now(), 35)); } @Test diff --git a/core/src/test/java/google/registry/batch/DeleteProberDataActionTest.java b/core/src/test/java/google/registry/batch/DeleteProberDataActionTest.java index 9c11baa01..96c2d0c98 100644 --- a/core/src/test/java/google/registry/batch/DeleteProberDataActionTest.java +++ b/core/src/test/java/google/registry/batch/DeleteProberDataActionTest.java @@ -26,7 +26,7 @@ import static google.registry.testing.DatabaseHelper.persistActiveHost; import static google.registry.testing.DatabaseHelper.persistDeletedDomain; import static google.registry.testing.DatabaseHelper.persistDomainAsDeleted; import static google.registry.testing.DatabaseHelper.persistResource; -import static google.registry.util.DateTimeUtils.END_OF_TIME; +import static google.registry.util.DateTimeUtils.END_INSTANT; import static org.joda.time.DateTimeZone.UTC; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -47,6 +47,7 @@ import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationT import google.registry.testing.DatabaseHelper; import google.registry.testing.SystemPropertyExtension; import google.registry.util.RegistryEnvironment; +import java.time.Instant; import java.util.Optional; import java.util.Set; import org.joda.money.Money; @@ -201,7 +202,7 @@ class DeleteProberDataActionTest { .setCreationTimeForTest(DateTime.now(UTC).minusYears(1)) .build()); action.run(); - DateTime timeAfterDeletion = DateTime.now(UTC); + Instant timeAfterDeletion = Instant.now(); assertThat(ForeignKeyUtils.loadResource(Domain.class, "blah.ib-any.test", timeAfterDeletion)) .isEmpty(); assertThat(loadByEntity(domain).getDeletionTime()).isLessThan(timeAfterDeletion); @@ -217,7 +218,7 @@ class DeleteProberDataActionTest { .setCreationTimeForTest(DateTime.now(UTC).minusYears(1)) .build()); action.run(); - DateTime timeAfterDeletion = DateTime.now(UTC); + Instant timeAfterDeletion = Instant.now(); resetAction(); action.run(); assertThat(ForeignKeyUtils.loadResource(Domain.class, "blah.ib-any.test", timeAfterDeletion)) @@ -237,7 +238,7 @@ class DeleteProberDataActionTest { Optional domain = ForeignKeyUtils.loadResource(Domain.class, "blah.ib-any.test", DateTime.now(UTC)); assertThat(domain).isPresent(); - assertThat(domain.get().getDeletionTime()).isEqualTo(END_OF_TIME); + assertThat(domain.get().getDeletionTime()).isEqualTo(END_INSTANT); } @Test @@ -250,7 +251,7 @@ class DeleteProberDataActionTest { .build()); action.isDryRun = true; action.run(); - assertThat(loadByEntity(domain).getDeletionTime()).isEqualTo(END_OF_TIME); + assertThat(loadByEntity(domain).getDeletionTime()).isEqualTo(END_INSTANT); } @Test diff --git a/core/src/test/java/google/registry/beam/resave/ResaveAllEppResourcesPipelineTest.java b/core/src/test/java/google/registry/beam/resave/ResaveAllEppResourcesPipelineTest.java index c87216be0..b9d8f59a5 100644 --- a/core/src/test/java/google/registry/beam/resave/ResaveAllEppResourcesPipelineTest.java +++ b/core/src/test/java/google/registry/beam/resave/ResaveAllEppResourcesPipelineTest.java @@ -25,6 +25,8 @@ import static google.registry.testing.DatabaseHelper.persistActiveHost; import static google.registry.testing.DatabaseHelper.persistDomainWithDependentResources; import static google.registry.testing.DatabaseHelper.persistDomainWithPendingTransfer; import static google.registry.testing.DatabaseHelper.persistNewRegistrars; +import static google.registry.util.DateTimeUtils.plusYears; +import static google.registry.util.DateTimeUtils.toInstant; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -113,11 +115,12 @@ public class ResaveAllEppResourcesPipelineTest { DateTime now = fakeClock.nowUtc(); Domain domain = persistDomainWithDependentResources("domain", "tld", now, now, now.plusYears(1)); - assertThat(domain.getRegistrationExpirationTime()).isEqualTo(now.plusYears(1)); + assertThat(domain.getRegistrationExpirationTime()).isEqualTo(plusYears(toInstant(now), 1)); fakeClock.advanceBy(Duration.standardDays(500)); runPipeline(); Domain postPipeline = loadByEntity(domain); - assertThat(postPipeline.getRegistrationExpirationTime()).isEqualTo(now.plusYears(2)); + assertThat(postPipeline.getRegistrationExpirationTime()) + .isEqualTo(plusYears(toInstant(now), 2)); } @Test diff --git a/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java b/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java index fb45f3473..3d3540ab8 100644 --- a/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java +++ b/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java @@ -488,7 +488,7 @@ class EppLifecycleDomainTest extends EppTestCase { // Make sure that in the future, the domain expiration is unchanged after deletion Domain clonedDomain = domain.cloneProjectedAtTime(deleteTime.plusYears(5)); - assertThat(clonedDomain.getRegistrationExpirationTime()).isEqualTo(createTime.plusYears(2)); + assertThat(clonedDomain.getRegistrationExpirationDateTime()).isEqualTo(createTime.plusYears(2)); } @Test diff --git a/core/src/test/java/google/registry/flows/FlowTestCase.java b/core/src/test/java/google/registry/flows/FlowTestCase.java index ba2b31f61..4daf414b2 100644 --- a/core/src/test/java/google/registry/flows/FlowTestCase.java +++ b/core/src/test/java/google/registry/flows/FlowTestCase.java @@ -182,7 +182,7 @@ public abstract class FlowTestCase { GracePeriod.create( entry.getKey().getType(), entry.getKey().getDomainRepoId(), - entry.getKey().getExpirationTime(), + entry.getKey().getExpirationDateTime(), entry.getKey().getRegistrarId(), null, 1L), diff --git a/core/src/test/java/google/registry/flows/domain/DomainCreateFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainCreateFlowTest.java index f1ae4f485..6c402def6 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainCreateFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainCreateFlowTest.java @@ -361,7 +361,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase @Nullable Money renewalPrice) throws Exception { assertMutatingFlow(true); - DateTime currentExpiration = reloadResourceByForeignKey().getRegistrationExpirationTime(); + DateTime currentExpiration = reloadResourceByForeignKey().getRegistrationExpirationDateTime(); DateTime newExpiration = currentExpiration.plusYears(renewalYears); runFlowAssertResponse( CommitMode.LIVE, userPrivileges, loadFile(responseFilename, substitutions)); @@ -303,7 +303,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase .setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) .setTargetId(getUniqueIdFromCommand()) .setRegistrarId("TheRegistrar") - .setEventTime(domain.getRegistrationExpirationTime()) + .setEventTime(domain.getRegistrationExpirationDateTime()) .setRecurrenceEndTime(END_OF_TIME) .setDomainHistory(historyEntryDomainRenew) .build()); @@ -313,7 +313,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase new PollMessage.Autorenew.Builder() .setTargetId(getUniqueIdFromCommand()) .setRegistrarId("TheRegistrar") - .setEventTime(domain.getRegistrationExpirationTime()) + .setEventTime(domain.getRegistrationExpirationDateTime()) .setAutorenewEndTime(END_OF_TIME) .setMsg("Domain was auto-renewed.") .setHistoryEntry(historyEntryDomainRenew) @@ -817,7 +817,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase new PollMessage.Autorenew.Builder() .setTargetId(getUniqueIdFromCommand()) .setRegistrarId("TheRegistrar") - .setEventTime(reloadResourceByForeignKey().getRegistrationExpirationTime()) + .setEventTime(reloadResourceByForeignKey().getRegistrationExpirationDateTime()) .setAutorenewEndTime(END_OF_TIME) .setMsg("Domain was auto-renewed.") .setHistoryEntry(historyEntryDomainRenew) diff --git a/core/src/test/java/google/registry/flows/domain/DomainRestoreRequestFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainRestoreRequestFlowTest.java index 69c28ee89..35eeb1399 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainRestoreRequestFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainRestoreRequestFlowTest.java @@ -201,7 +201,7 @@ class DomainRestoreRequestFlowTest extends ResourceFlowTestCase originalGracePeriods = domain.getGracePeriods(); DomainTransferData originalTransferData = domain.getTransferData(); runFlowAssertResponse(loadFile("domain_transfer_cancel_response.xml")); diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferQueryFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferQueryFlowTest.java index 523120f4a..b96a4f412 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferQueryFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferQueryFlowTest.java @@ -143,7 +143,8 @@ class DomainTransferQueryFlowTest persistResource( domain .asBuilder() - .setRegistrationExpirationTime(domain.getRegistrationExpirationTime().plusYears(9)) + .setRegistrationExpirationTime( + domain.getRegistrationExpirationDateTime().plusYears(9)) .build()); doSuccessfulTest("domain_transfer_query.xml", "domain_transfer_query_response_10_years.xml", 1); } @@ -233,7 +234,7 @@ class DomainTransferQueryFlowTest // Set the clock to just past the extended registration time. We'd expect the domain to have // auto-renewed once, but the transfer query response should be the same. clock.setTo(EXTENDED_REGISTRATION_EXPIRATION_TIME.plusMillis(1)); - assertThat(domain.cloneProjectedAtTime(clock.nowUtc()).getRegistrationExpirationTime()) + assertThat(domain.cloneProjectedAtTime(clock.nowUtc()).getRegistrationExpirationDateTime()) .isEqualTo(EXTENDED_REGISTRATION_EXPIRATION_TIME.plusYears(1)); doSuccessfulTest( "domain_transfer_query.xml", "domain_transfer_query_response_server_approved.xml", 2); diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferRejectFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferRejectFlowTest.java index f26b460d4..e3bac6216 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferRejectFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferRejectFlowTest.java @@ -88,7 +88,7 @@ class DomainTransferRejectFlowTest assertThat(getPollMessages("TheRegistrar", clock.nowUtc().plusMonths(1))).hasSize(1); // Setup done; run the test. assertMutatingFlow(true); - DateTime originalExpirationTime = domain.getRegistrationExpirationTime(); + DateTime originalExpirationTime = domain.getRegistrationExpirationDateTime(); ImmutableSet originalGracePeriods = domain.getGracePeriods(); DomainTransferData originalTransferData = domain.getTransferData(); runFlowAssertResponse(loadFile(expectedXmlFilename)); diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java index 70ad4517e..7afa97cd6 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java @@ -244,7 +244,8 @@ class DomainTransferRequestFlowTest .setTransferPeriod(expectedPeriod) .setTransferStatus(TransferStatus.SERVER_APPROVED) .setPendingTransferExpirationTime(automaticTransferTime) - .setTransferredRegistrationExpirationTime(domain.getRegistrationExpirationTime()) + .setTransferredRegistrationExpirationTime( + domain.getRegistrationExpirationDateTime()) // Server-approve entity fields should all be nulled out. .build()); } @@ -542,7 +543,7 @@ class DomainTransferRequestFlowTest doSuccessfulTest( commandFilename, expectedXmlFilename, - domain.getRegistrationExpirationTime().plusYears(1), + domain.getRegistrationExpirationDateTime().plusYears(1), substitutions, Optional.empty()); } @@ -551,7 +552,9 @@ class DomainTransferRequestFlowTest throws Exception { clock.advanceOneMilli(); doSuccessfulTest( - commandFilename, expectedXmlFilename, domain.getRegistrationExpirationTime().plusYears(1)); + commandFilename, + expectedXmlFilename, + domain.getRegistrationExpirationDateTime().plusYears(1)); } private void doSuccessfulSuperuserExtensionTest( @@ -812,7 +815,7 @@ class DomainTransferRequestFlowTest doSuccessfulSuperuserExtensionTest( "domain_transfer_request_superuser_extension.xml", "domain_transfer_request_response_su_ext_zero_period_nonzero_transfer_length.xml", - domain.getRegistrationExpirationTime().plusYears(0), + domain.getRegistrationExpirationDateTime().plusYears(0), ImmutableMap.of("PERIOD", "0", "AUTOMATIC_TRANSFER_LENGTH", "5"), Optional.empty(), Period.create(0, Unit.YEARS), @@ -826,7 +829,7 @@ class DomainTransferRequestFlowTest doSuccessfulSuperuserExtensionTest( "domain_transfer_request_superuser_extension.xml", "domain_transfer_request_response_su_ext_zero_period_zero_transfer_length.xml", - domain.getRegistrationExpirationTime().plusYears(0), + domain.getRegistrationExpirationDateTime().plusYears(0), ImmutableMap.of("PERIOD", "0", "AUTOMATIC_TRANSFER_LENGTH", "0"), Optional.empty(), Period.create(0, Unit.YEARS), @@ -841,7 +844,7 @@ class DomainTransferRequestFlowTest doSuccessfulSuperuserExtensionTest( "domain_transfer_request_superuser_extension.xml", "domain_transfer_request_response_su_ext_one_year_period_nonzero_transfer_length.xml", - domain.getRegistrationExpirationTime().plusYears(1), + domain.getRegistrationExpirationDateTime().plusYears(1), ImmutableMap.of("PERIOD", "1", "AUTOMATIC_TRANSFER_LENGTH", "5"), Optional.empty(), Period.create(1, Unit.YEARS), @@ -873,7 +876,7 @@ class DomainTransferRequestFlowTest doSuccessfulSuperuserExtensionTest( "domain_transfer_request_superuser_extension.xml", "domain_transfer_request_response_su_ext_zero_period_autorenew_grace.xml", - domain.getRegistrationExpirationTime(), + domain.getRegistrationExpirationDateTime(), ImmutableMap.of("PERIOD", "0", "AUTOMATIC_TRANSFER_LENGTH", "0"), Optional.empty(), Period.create(0, Unit.YEARS), @@ -922,7 +925,7 @@ class DomainTransferRequestFlowTest doSuccessfulSuperuserExtensionTest( "domain_transfer_request_superuser_extension.xml", "domain_transfer_request_response_su_ext_zero_period_zero_transfer_length.xml", - domain.getRegistrationExpirationTime().plusYears(0), + domain.getRegistrationExpirationDateTime().plusYears(0), ImmutableMap.of("PERIOD", "0", "AUTOMATIC_TRANSFER_LENGTH", "0"), Optional.empty(), Period.create(0, Unit.YEARS), @@ -939,7 +942,7 @@ class DomainTransferRequestFlowTest doSuccessfulSuperuserExtensionTest( "domain_transfer_request_superuser_extension.xml", "domain_transfer_request_response_su_ext_zero_period_zero_transfer_length.xml", - domain.getRegistrationExpirationTime().plusYears(0), + domain.getRegistrationExpirationDateTime().plusYears(0), ImmutableMap.of("PERIOD", "0", "AUTOMATIC_TRANSFER_LENGTH", "0"), Optional.empty(), Period.create(0, Unit.YEARS), @@ -977,7 +980,7 @@ class DomainTransferRequestFlowTest doSuccessfulTest( "domain_transfer_request_separate_fees.xml", "domain_transfer_request_response_fees.xml", - domain.getRegistrationExpirationTime().plusYears(1), + domain.getRegistrationExpirationDateTime().plusYears(1), new ImmutableMap.Builder() .put("DOMAIN", "expensive-domain.foo") .put("YEARS", "1") @@ -1409,7 +1412,7 @@ class DomainTransferRequestFlowTest doSuccessfulSuperuserExtensionTest( "domain_transfer_request_superuser_extension.xml", "domain_transfer_request_response_su_ext_zero_period_zero_transfer_length.xml", - domain.getRegistrationExpirationTime().plusYears(0), + domain.getRegistrationExpirationDateTime().plusYears(0), ImmutableMap.of("PERIOD", "0", "AUTOMATIC_TRANSFER_LENGTH", "0"), Optional.empty(), Period.create(0, Unit.YEARS), @@ -2024,7 +2027,7 @@ class DomainTransferRequestFlowTest doSuccessfulTest( "domain_transfer_request_separate_fees.xml", "domain_transfer_request_response_fees.xml", - domain.getRegistrationExpirationTime().plusYears(1), + domain.getRegistrationExpirationDateTime().plusYears(1), new ImmutableMap.Builder() .put("DOMAIN", "expensive-domain.foo") .put("YEARS", "1") diff --git a/core/src/test/java/google/registry/flows/host/HostUpdateFlowTest.java b/core/src/test/java/google/registry/flows/host/HostUpdateFlowTest.java index 084cd4192..2103b06d4 100644 --- a/core/src/test/java/google/registry/flows/host/HostUpdateFlowTest.java +++ b/core/src/test/java/google/registry/flows/host/HostUpdateFlowTest.java @@ -256,7 +256,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase { .and() .hasPersistedCurrentSponsorRegistrarId("NewRegistrar") .and() - .hasLastTransferTime(domain.getTransferData().getPendingTransferExpirationTime()) + .hasLastTransferTime(domain.getTransferData().getPendingTransferExpirationDateTime()) .and() .hasOnlyOneHistoryEntryWhich() .hasType(HistoryEntry.Type.HOST_UPDATE); diff --git a/core/src/test/java/google/registry/model/domain/DomainTest.java b/core/src/test/java/google/registry/model/domain/DomainTest.java index e6e81d9a1..ad04eb1d0 100644 --- a/core/src/test/java/google/registry/model/domain/DomainTest.java +++ b/core/src/test/java/google/registry/model/domain/DomainTest.java @@ -31,6 +31,10 @@ import static google.registry.testing.DomainSubject.assertAboutDomains; import static google.registry.testing.SqlHelper.saveRegistrar; import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.START_OF_TIME; +import static google.registry.util.DateTimeUtils.minusDays; +import static google.registry.util.DateTimeUtils.plusDays; +import static google.registry.util.DateTimeUtils.plusYears; +import static google.registry.util.DateTimeUtils.toDateTime; import static org.joda.money.CurrencyUnit.USD; import static org.joda.time.DateTimeZone.UTC; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -67,6 +71,8 @@ import google.registry.persistence.transaction.JpaTestExtensions; import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationWithCoverageExtension; import google.registry.testing.DatabaseHelper; import google.registry.testing.FakeClock; +import java.time.Instant; +import java.time.ZoneOffset; import java.util.Optional; import org.joda.money.Money; import org.joda.time.DateTime; @@ -386,7 +392,7 @@ public class DomainTest { .isEqualTo(TransferStatus.SERVER_APPROVED); assertThat(domain.getCurrentSponsorRegistrarId()).isEqualTo("TheRegistrar"); assertThat(domain.getLastTransferTime()).isEqualTo(fakeClock.nowUtc().plusDays(1)); - assertThat(domain.getRegistrationExpirationTime()).isEqualTo(newExpirationTime); + assertThat(domain.getRegistrationExpirationDateTime()).isEqualTo(newExpirationTime); assertThat(domain.getAutorenewBillingEvent()).isEqualTo(newAutorenewEvent); } @@ -479,56 +485,57 @@ public class DomainTest { } private void setupPendingTransferDomain( - DateTime oldExpirationTime, DateTime transferRequestTime, DateTime transferSuccessTime) { + Instant oldExpirationTime, Instant transferRequestTime, Instant transferSuccessTime) { domain = domain .asBuilder() - .setRegistrationExpirationTime(oldExpirationTime) + .setRegistrationExpirationTime(toDateTime(oldExpirationTime)) .setTransferData( domain .getTransferData() .asBuilder() .setTransferStatus(TransferStatus.PENDING) - .setTransferRequestTime(transferRequestTime) - .setPendingTransferExpirationTime(transferSuccessTime) + .setTransferRequestTime(toDateTime(transferRequestTime)) + .setPendingTransferExpirationTime(toDateTime(transferSuccessTime)) .build()) - .setLastEppUpdateTime(transferRequestTime) + .setLastEppUpdateTime(toDateTime(transferRequestTime)) .setLastEppUpdateRegistrarId(domain.getTransferData().getGainingRegistrarId()) .build(); } @Test void testEppLastUpdateTimeAndClientId_autoRenewBeforeTransferSuccess() { - DateTime now = fakeClock.nowUtc(); - DateTime transferRequestDateTime = now.plusDays(1); - DateTime autorenewDateTime = now.plusDays(3); - DateTime transferSuccessDateTime = now.plusDays(5); + Instant now = fakeClock.now(); + Instant transferRequestDateTime = plusDays(now, 1); + Instant autorenewDateTime = plusDays(now, 3); + Instant transferSuccessDateTime = plusDays(now, 5); setupPendingTransferDomain(autorenewDateTime, transferRequestDateTime, transferSuccessDateTime); - Domain beforeAutoRenew = domain.cloneProjectedAtTime(autorenewDateTime.minusDays(1)); + Domain beforeAutoRenew = domain.cloneProjectedAtInstant(minusDays(autorenewDateTime, 1)); assertThat(beforeAutoRenew.getLastEppUpdateTime()).isEqualTo(transferRequestDateTime); assertThat(beforeAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("TheRegistrar"); // If autorenew happens before transfer succeeds(before transfer grace period starts as well), // lastEppUpdateRegistrarId should still be the current sponsor client id - Domain afterAutoRenew = domain.cloneProjectedAtTime(autorenewDateTime.plusDays(1)); + Domain afterAutoRenew = domain.cloneProjectedAtInstant(plusDays(autorenewDateTime, 1)); assertThat(afterAutoRenew.getLastEppUpdateTime()).isEqualTo(autorenewDateTime); assertThat(afterAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("NewRegistrar"); } @Test void testEppLastUpdateTimeAndClientId_autoRenewAfterTransferSuccess() { - DateTime now = fakeClock.nowUtc(); - DateTime transferRequestDateTime = now.plusDays(1); - DateTime autorenewDateTime = now.plusDays(3); - DateTime transferSuccessDateTime = now.plusDays(5); + Instant now = fakeClock.now(); + Instant transferRequestDateTime = plusDays(now, 1); + Instant autorenewDateTime = plusDays(now, 3); + Instant transferSuccessDateTime = plusDays(now, 5); setupPendingTransferDomain(autorenewDateTime, transferRequestDateTime, transferSuccessDateTime); - Domain beforeAutoRenew = domain.cloneProjectedAtTime(autorenewDateTime.minusDays(1)); + Domain beforeAutoRenew = domain.cloneProjectedAtInstant(minusDays(autorenewDateTime, 1)); assertThat(beforeAutoRenew.getLastEppUpdateTime()).isEqualTo(transferRequestDateTime); assertThat(beforeAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("TheRegistrar"); - Domain afterTransferSuccess = domain.cloneProjectedAtTime(transferSuccessDateTime.plusDays(1)); + Domain afterTransferSuccess = + domain.cloneProjectedAtInstant(plusDays(transferSuccessDateTime, 1)); assertThat(afterTransferSuccess.getLastEppUpdateTime()).isEqualTo(transferSuccessDateTime); assertThat(afterTransferSuccess.getLastEppUpdateRegistrarId()).isEqualTo("TheRegistrar"); } @@ -552,11 +559,11 @@ public class DomainTest { setupUnmodifiedDomain(autorenewDateTime); Domain beforeAutoRenew = domain.cloneProjectedAtTime(autorenewDateTime.minusDays(1)); - assertThat(beforeAutoRenew.getLastEppUpdateTime()).isEqualTo(null); + assertThat(beforeAutoRenew.getLastEppUpdateDateTime()).isEqualTo(null); assertThat(beforeAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo(null); Domain afterAutoRenew = domain.cloneProjectedAtTime(autorenewDateTime.plusDays(1)); - assertThat(afterAutoRenew.getLastEppUpdateTime()).isEqualTo(autorenewDateTime); + assertThat(afterAutoRenew.getLastEppUpdateDateTime()).isEqualTo(autorenewDateTime); assertThat(afterAutoRenew.getLastEppUpdateRegistrarId()).isEqualTo("NewRegistrar"); } @@ -633,9 +640,9 @@ public class DomainTest { @Test void testRenewalsHappenAtExpiration() { - Domain renewed = domain.cloneProjectedAtTime(domain.getRegistrationExpirationTime()); + Domain renewed = domain.cloneProjectedAtInstant(domain.getRegistrationExpirationTime()); assertThat(renewed.getRegistrationExpirationTime()) - .isEqualTo(domain.getRegistrationExpirationTime().plusYears(1)); + .isEqualTo(plusYears(domain.getRegistrationExpirationTime(), 1)); assertThat(renewed.getLastEppUpdateTime()).isEqualTo(domain.getRegistrationExpirationTime()); assertThat(getOnlyElement(renewed.getGracePeriods()).getType()) .isEqualTo(GracePeriodStatus.AUTO_RENEW); @@ -656,15 +663,16 @@ public class DomainTest { .setRegistrationExpirationTime(DateTime.parse("2004-02-29T22:00:00.0Z")) .build(); Domain renewed = - domain.cloneProjectedAtTime(domain.getRegistrationExpirationTime().plusYears(4)); - assertThat(renewed.getRegistrationExpirationTime().getDayOfMonth()).isEqualTo(28); + domain.cloneProjectedAtInstant(plusYears(domain.getRegistrationExpirationTime(), 4)); + assertThat(renewed.getRegistrationExpirationTime().atZone(ZoneOffset.UTC).getDayOfMonth()) + .isEqualTo(28); } @Test void testMultipleAutoRenews() { // Change the registry so that renewal costs change every year to make sure we are using the // autorenew time as the lookup time for the cost. - DateTime oldExpirationTime = domain.getRegistrationExpirationTime(); + DateTime oldExpirationTime = domain.getRegistrationExpirationDateTime(); persistResource( Tld.get("com") .asBuilder() @@ -680,9 +688,10 @@ public class DomainTest { .build()) .build()); Domain renewedThreeTimes = domain.cloneProjectedAtTime(oldExpirationTime.plusYears(2)); - assertThat(renewedThreeTimes.getRegistrationExpirationTime()) + assertThat(renewedThreeTimes.getRegistrationExpirationDateTime()) .isEqualTo(oldExpirationTime.plusYears(3)); - assertThat(renewedThreeTimes.getLastEppUpdateTime()).isEqualTo(oldExpirationTime.plusYears(2)); + assertThat(renewedThreeTimes.getLastEppUpdateDateTime()) + .isEqualTo(oldExpirationTime.plusYears(2)); assertThat(renewedThreeTimes.getGracePeriods()) .containsExactly( GracePeriod.createForRecurrence( @@ -730,7 +739,7 @@ public class DomainTest { .setDeletionTime(now.minusDays(10)) .setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE, StatusValue.INACTIVE)) .build()); - assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime()) + assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationDateTime()) .isEqualTo(now.minusDays(1)); } @@ -746,7 +755,7 @@ public class DomainTest { .setDeletionTime(now.plusDays(20)) .setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE, StatusValue.INACTIVE)) .build()); - assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime()) + assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationDateTime()) .isEqualTo(now.plusDays(1)); } @@ -773,7 +782,7 @@ public class DomainTest { .setTransferData(transferData) .build()); - assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime()) + assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationDateTime()) .isEqualTo(newExpiration); } @@ -801,7 +810,7 @@ public class DomainTest { .setTransferData(transferData) .build()); - assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime()) + assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationDateTime()) .isEqualTo(newExpiration); } @@ -843,7 +852,7 @@ public class DomainTest { assertThat(domain.getCurrentBulkToken()).isPresent(); Domain clonedDomain = domain.cloneProjectedAtTime(now); - assertThat(clonedDomain.getRegistrationExpirationTime()).isEqualTo(newExpiration); + assertThat(clonedDomain.getRegistrationExpirationDateTime()).isEqualTo(newExpiration); assertThat(clonedDomain.getCurrentBulkToken()).isEmpty(); } @@ -868,7 +877,7 @@ public class DomainTest { .setTransferData(transferData) .build()); - assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime()) + assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationDateTime()) .isEqualTo(previousExpiration); } @@ -906,7 +915,7 @@ public class DomainTest { .build()); Domain clonedDomain = domain.cloneProjectedAtTime(now); - assertThat(clonedDomain.getRegistrationExpirationTime()).isEqualTo(previousExpiration); + assertThat(clonedDomain.getRegistrationExpirationDateTime()).isEqualTo(previousExpiration); assertThat(clonedDomain.getCurrentBulkToken().get()).isEqualTo(allocationToken.createVKey()); } @@ -943,8 +952,8 @@ public class DomainTest { .setAutorenewBillingEvent(recurrenceBillKey) .build()); Domain clone = domain.cloneProjectedAtTime(now); - assertThat(clone.getRegistrationExpirationTime()) - .isEqualTo(domain.getRegistrationExpirationTime().plusYears(1)); + assertThat(clone.getRegistrationExpirationDateTime()) + .isEqualTo(domain.getRegistrationExpirationDateTime().plusYears(1)); // Transferring removes the AUTORENEW grace period and adds a TRANSFER grace period assertThat(getOnlyElement(clone.getGracePeriods()).getType()) .isEqualTo(GracePeriodStatus.TRANSFER); diff --git a/core/src/test/java/google/registry/model/domain/GracePeriodTest.java b/core/src/test/java/google/registry/model/domain/GracePeriodTest.java index bc79c043a..8453d28dd 100644 --- a/core/src/test/java/google/registry/model/domain/GracePeriodTest.java +++ b/core/src/test/java/google/registry/model/domain/GracePeriodTest.java @@ -68,7 +68,7 @@ public class GracePeriodTest { assertThat(gracePeriod.getBillingEvent()).isEqualTo(onetime.createVKey()); assertThat(gracePeriod.getBillingRecurrence()).isNull(); assertThat(gracePeriod.getRegistrarId()).isEqualTo("TheRegistrar"); - assertThat(gracePeriod.getExpirationTime()).isEqualTo(now.plusDays(1)); + assertThat(gracePeriod.getExpirationDateTime()).isEqualTo(now.plusDays(1)); assertThat(gracePeriod.hasBillingEvent()).isTrue(); } @@ -82,7 +82,7 @@ public class GracePeriodTest { assertThat(gracePeriod.getBillingEvent()).isNull(); assertThat(gracePeriod.getBillingRecurrence()).isEqualTo(recurrenceKey); assertThat(gracePeriod.getRegistrarId()).isEqualTo("TheRegistrar"); - assertThat(gracePeriod.getExpirationTime()).isEqualTo(now.plusDays(1)); + assertThat(gracePeriod.getExpirationDateTime()).isEqualTo(now.plusDays(1)); assertThat(gracePeriod.hasBillingEvent()).isTrue(); } @@ -96,7 +96,7 @@ public class GracePeriodTest { assertThat(gracePeriod.getBillingEvent()).isNull(); assertThat(gracePeriod.getBillingRecurrence()).isNull(); assertThat(gracePeriod.getRegistrarId()).isEqualTo("TheRegistrar"); - assertThat(gracePeriod.getExpirationTime()).isEqualTo(now); + assertThat(gracePeriod.getExpirationDateTime()).isEqualTo(now); assertThat(gracePeriod.hasBillingEvent()).isFalse(); } diff --git a/core/src/test/java/google/registry/testing/AbstractEppResourceSubject.java b/core/src/test/java/google/registry/testing/AbstractEppResourceSubject.java index baebec91b..a8a039c4d 100644 --- a/core/src/test/java/google/registry/testing/AbstractEppResourceSubject.java +++ b/core/src/test/java/google/registry/testing/AbstractEppResourceSubject.java @@ -148,15 +148,15 @@ abstract class AbstractEppResourceSubject< } public And hasDeletionTime(DateTime deletionTime) { - return hasValue(deletionTime, actual.getDeletionTime(), "getDeletionTime()"); + return hasValue(deletionTime, actual.getDeletionDateTime(), "getDeletionTime()"); } public And hasLastEppUpdateTime(DateTime lastUpdateTime) { - return hasValue(lastUpdateTime, actual.getLastEppUpdateTime(), "has lastEppUpdateTime"); + return hasValue(lastUpdateTime, actual.getLastEppUpdateDateTime(), "has lastEppUpdateTime"); } public And hasLastEppUpdateTimeAtLeast(DateTime before) { - DateTime lastEppUpdateTime = actual.getLastEppUpdateTime(); + DateTime lastEppUpdateTime = actual.getLastEppUpdateDateTime(); check("getLastEppUpdateTime()").that(lastEppUpdateTime).isAtLeast(before); return andChainer(); } diff --git a/core/src/test/java/google/registry/testing/DomainSubject.java b/core/src/test/java/google/registry/testing/DomainSubject.java index 0036528ba..507a548c9 100644 --- a/core/src/test/java/google/registry/testing/DomainSubject.java +++ b/core/src/test/java/google/registry/testing/DomainSubject.java @@ -78,7 +78,7 @@ public final class DomainSubject extends AbstractEppResourceSubject hasRegistrationExpirationTime(DateTime expiration) { return hasValue( - expiration, actual.getRegistrationExpirationTime(), "getRegistrationExpirationTime()"); + expiration, actual.getRegistrationExpirationDateTime(), "getRegistrationExpirationTime()"); } public And hasLastTransferTime(DateTime lastTransferTime) { diff --git a/core/src/test/java/google/registry/tools/UnrenewDomainCommandTest.java b/core/src/test/java/google/registry/tools/UnrenewDomainCommandTest.java index 9f4d161c8..378231a46 100644 --- a/core/src/test/java/google/registry/tools/UnrenewDomainCommandTest.java +++ b/core/src/test/java/google/registry/tools/UnrenewDomainCommandTest.java @@ -78,12 +78,12 @@ public class UnrenewDomainCommandTest extends CommandTestCase earliestOf(ImmutableList.of())); + assertThrows(IllegalArgumentException.class, () -> latestOf(ImmutableList.of())); } @Test @@ -107,4 +125,32 @@ class DateTimeUtilsTest { Date date = Date.valueOf("2020-02-29"); assertThat(toLocalDate(date)).isEqualTo(LocalDate.parse("2020-02-29")); } + + @Test + void test_startOfTimeConstants_areTheSame() { + assertThat(toInstant(START_OF_TIME)).isEqualTo(START_INSTANT); + assertThat(toDateTime(START_INSTANT)).isEqualTo(START_OF_TIME); + assertThat(toInstant(toDateTime(START_INSTANT))).isEqualTo(START_INSTANT); + assertThat(toDateTime(toInstant(START_OF_TIME))).isEqualTo(START_OF_TIME); + } + + @Test + void test_endOfTimeConstants_areTheSame() { + assertThat(toInstant(END_OF_TIME)).isEqualTo(END_INSTANT); + assertThat(toDateTime(END_INSTANT)).isEqualTo(END_OF_TIME); + assertThat(toInstant(toDateTime(END_INSTANT))).isEqualTo(END_INSTANT); + assertThat(toDateTime(toInstant(END_OF_TIME))).isEqualTo(END_OF_TIME); + } + + @Test + void test_instantConversionMethods_workCorrectly() { + assertThat(toInstant(DateTime.parse("2024-03-27T10:15:30.105Z"))) + .isEqualTo(Instant.parse("2024-03-27T10:15:30.105Z")); + assertThat(toDateTime(Instant.parse("2024-03-27T10:15:30.105Z"))) + .isEqualTo(DateTime.parse("2024-03-27T10:15:30.105Z")); + assertThat(toInstant(toDateTime(Instant.parse("2024-03-27T10:15:30.105Z")))) + .isEqualTo(Instant.parse("2024-03-27T10:15:30.105Z")); + assertThat(toDateTime(toInstant(DateTime.parse("2024-03-27T10:15:30.105Z")))) + .isEqualTo(DateTime.parse("2024-03-27T10:15:30.105Z")); + } }