From 0ae28548c553463478b4e31bcea4550f48656beb Mon Sep 17 00:00:00 2001 From: Ben McIlwain Date: Fri, 27 Mar 2026 15:41:17 -0400 Subject: [PATCH] Begin migration of joda DateTime to java.time.Instant 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 | 48 +++++++++- 66 files changed, 529 insertions(+), 212 deletions(-) diff --git a/common/src/main/java/google/registry/util/Clock.java b/common/src/main/java/google/registry/util/Clock.java index 78372cba4bc..9943aaa7cec 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 @@ 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 b085fbabdc8..f4d05378c81 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.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 @@ 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 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 static boolean isBeforeOrAt(DateTime timeToCheck, DateTime timeToCompareT 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 DateTime} 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 DateTime#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 DateTime#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 static Date toSqlDate(LocalDate localDate) { 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 eb553678d45..52ac9893f67 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 @@ 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 SystemClock() {} 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 526f943a2ea..656ec7109b9 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.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 DateTime nowUtc() { 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 990428edde9..b3bcc419d3b 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 @@ 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.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 @@ private void runTransferFlowInTransaction(String domainName) { 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 @@ private boolean shouldSkipDomain(String domainName) { 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 5281360342c..a23d5ce17eb 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.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 @@ private boolean runDomainDeleteFlow(Domain domain) { "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 f9a5ab5bec9..010eef40f93 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 @@ private void verifyDomainAndLockState(RegistryLock oldLock, Domain domain) { "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 193103c69a9..1bfcc1c487c 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.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 @@ private void expandOneRecurrence( // 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 122d5ded3b0..101bafa96f0 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 @@ 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.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 static void verifyTransferInitiator(String registrarId, Domain domain) 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 static void verifyAllStatusesAreClientSettable(Set statusVal * * @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 6414aa93b80..9cb5a7c4b66 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 EppResponse run() throws EppException { } // 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 EppResponse run() throws EppException { 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 fb6b358dca1..3a2fdd196fc 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 static BillingRecurrence.Builder newAutorenewBillingEvent(Domain domain) .setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) .setTargetId(domain.getDomainName()) .setRegistrarId(domain.getCurrentSponsorRegistrarId()) - .setEventTime(domain.getRegistrationExpirationTime()); + .setEventTime(domain.getRegistrationExpirationDateTime()); } /** @@ -514,7 +514,7 @@ public static Autorenew.Builder newAutorenewPollMessage(Domain domain) { 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 @@ static void handleFeeRequest( // 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 15a9b1b48c9..8815d2ca7bd 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 EppResponse run() throws EppException { .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 120316c004f..f2361659ad4 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java @@ -188,7 +188,7 @@ public EppResponse run() throws EppException { int years = command.getPeriod().getValue(); DateTime newExpirationTime = - leapSafeAddYears(existingDomain.getRegistrationExpirationTime(), years); // Uncapped + leapSafeAddYears(existingDomain.getRegistrationExpirationDateTime(), years); // Uncapped validateRegistrationPeriod(now, newExpirationTime); Optional feeRenew = eppInput.getSingleExtension(FeeRenewCommandExtension.class); @@ -325,8 +325,9 @@ private void verifyRenewAllowed( // 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 29fc413d351..3ec154e7f8b 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 EppResponse run() throws EppException { 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 EppResponse run() throws EppException { 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 cea6f656825..7b7eb47b328 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.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 EppResponse run() throws EppException { 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 EppResponse run() throws EppException { // 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 b562422b6b5..3e002f60c13 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 EppResponse run() throws EppException { } 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 351ee5e18fd..39b25d8d551 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.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.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 EppResponse run() throws EppException { 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 EppResponse run() throws EppException { 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 db7ce17bfe5..ad711a9b722 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.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.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 EppResponse run() throws EppException { 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 EppResponse run() throws EppException { 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 @@ private DomainHistory buildDomainHistory(Domain newDomain, Tld tld, DateTime now } 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 60000b224d5..f9c0ab16372 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 static PollMessage createGainingTransferPollMessage( 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 static PollMessage createLosingTransferPollMessage( 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 @@ static DomainTransferResponse createTransferResponse( .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 16f89e57b82..752c194ebbf 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 @@ private Domain performUpdate(Update command, Domain domain, DateTime now) throws 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 af5a5b25851..4647ade8963 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 EppResponse run() throws EppException { .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 ee5c376ef63..f8007038f2d 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.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.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 String getCreationRegistrarId() { 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 final ImmutableSet getStatusValues() { 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 4af8c6ccf5c..c64591ce426 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.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 static Function transformAtTime(final DateT * 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 static void setAutomaticTransferSuccessProperties( builder .removeStatusValue(StatusValue.PENDING_TRANSFER) .setTransferData(transferDataBuilder.build()) - .setLastTransferTime(transferData.getPendingTransferExpirationTime()) + .setLastTransferTime(transferData.getPendingTransferExpirationDateTime()) .setPersistedCurrentSponsorRegistrarId(transferData.getGainingRegistrarId()); } @@ -120,10 +121,10 @@ public static void setAutomaticTransferSuccessProperties( * */ 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 9a0b08006e0..ba1ab670b79 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.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 static Optional> loadKey( *

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 static Optional loadResource( 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 static ImmutableMap> loadKeys( * 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 static Optional loadResourceByCache( 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 c6a70026622..7d4bc12c628 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 static TransferResponse createTransferResponse( .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 1adc3a8f163..045e87b956a 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 static google.registry.model.billing.BillingCancellation forGracePeriod( .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 9a9715243a7..cff00f4db31 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.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 VKey createVKey() { @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 573f5d213ce..1f051b567ee 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.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.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 ImmutableSet getSubordinateHosts() { 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 ImmutableSet getGracePeriodsOfType(GracePeriodStatus gracePe @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 DomainBase cloneProjectedAtTime(final DateTime now) { * 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 @@ && isBeforeOrAt(transferExpirationTime, now)) { 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 @@ && isBeforeOrAt(transferExpirationTime, now)) { 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 @@ && isBeforeOrAt(transferExpirationTime, now)) { 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 @@ && isBeforeOrAt(transferExpirationTime, now)) { // 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 @@ && isBeforeOrAt(transferExpirationTime, now)) { // 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 @@ && isBeforeOrAt(transferExpirationTime, now)) { } /** 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 B copyFrom(DomainBase domainBase) { .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 a53abe45790..cca7742ed57 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.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 String getDomainRepoId() { 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 8b70e49fc41..66480452b89 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.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 HostBase cloneProjectedAtTime(DateTime now) { return this; } + @Override + public EppResource cloneProjectedAtInstant(Instant now) { + return this; + } + @Override public Builder asBuilder() { return new Builder<>(clone(this)); @@ -232,13 +238,13 @@ public B setLastTransferTime(DateTime lastTransferTime) { 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 2e73951e3f3..16172266164 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 @@ void postLoad() { .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 9c55b52a1a9..e1a0a04c1bf 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.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 String getLosingRegistrarId() { 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 7ecb17e2698..a56c3889d54 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.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.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 Trid getTransferRequestTrid() { } @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 f1633b7c189..4502a7d39e7 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.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.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 TransactionIsolationLevel getCurrentTransactionIsolationLevel() { @Override public DateTime getTransactionTime() { + return toDateTime(getTxTime()); + } + + @Override + public Instant getTxTime() { assertInTransaction(); TransactionInfo txnInfo = transactionInfo.get(); if (txnInfo.transactionTime == null) { @@ -746,7 +753,7 @@ private T detach(@Nullable T entity) { 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 @@ private static class TransactionInfo { 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 8cd63befe80..aa49bb9b784 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 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 2b23be75044..94804bf0a17 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 @@ 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 @@ DeletedItemHandling getDeletedItemHandling() { * 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 baec62dc01d..cba2b5467a0 100644 --- a/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java +++ b/core/src/main/java/google/registry/rdap/RdapJsonFormatter.java @@ -317,7 +317,7 @@ RdapDomain createRdapDomain(Domain domain, OutputDataType outputDataType) { .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 @@ -358,7 +358,7 @@ RdapDomain createRdapDomain(Domain domain, OutputDataType outputDataType) { makeStatusValueList( allStatusValues, false, // isRedacted - domain.getDeletionTime().isBefore(getRequestTime())); + domain.getDeletionDateTime().isBefore(getRequestTime())); builder.statusBuilder().addAll(status); if (status.isEmpty()) { logger.atWarning().log( @@ -438,7 +438,7 @@ && replicaTm() 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. @@ -753,7 +753,9 @@ private ImmutableList makeOptionalEvents(EppResource resource) { 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 fe671a28def..89f4be1a01d 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 @@ static XjcRdeDomain convertDomain(Domain model, RdeMode mode) { // 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 @@ private static XjcRdeDomainTransferDataType convertTransferData(DomainTransferDa 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 3f75703ee55..f822871aa2c 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 @@ private static XjcRdeHost convertHostCommon( 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 f4aad1d544a..88e0a367901 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 @@ String generate() { .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 @@ String generate() { 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 81f26263454..838db13ce5d 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 @@ protected void initMutatingEppToolCommand() 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 1f3368ef2c4..77290a85292 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 @@ protected void initMutatingEppToolCommand() 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 29613a8ecaa..06866ebca3e 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 @@ protected void init() throws UnsupportedEncodingException { 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 @@ protected String prompt() { 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 @@ private void unrenewDomain(String domainName) { "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 87120148275..73a300ae885 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 @@ 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.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 @@ private ImmutableList internalExecute() { 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 @@ private ImmutableMap loadDomainsAndRecurrences() { 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 @@ private ImmutableMap loadDomainsAndRecurrences() { 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 6fe8694964c..0315dedd67f 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.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 @@ void test_deletesOnlyExpiredDomain() { 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 9c11baa01d4..96c2d0c98e0 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.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.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 @@ void testSuccess_activeDomain_isSoftDeleted() throws Exception { .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 @@ void testSuccess_activeDomain_doubleMapSoftDeletes() throws Exception { .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 @@ void test_recentlyCreatedDomain_isntDeletedYet() throws Exception { 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 @@ void testDryRun_doesntSoftDeleteData() throws Exception { .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 c87216be024..b9d8f59a547 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.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 @@ void testPipeline_autorenewedDomain() { 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 fb45f347354..3d3540ab885 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 @@ void testDomainDeletion_outsideAddGracePeriod_showsRedemptionPeriod() throws Exc // 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 ba2b31f61af..4daf414b2d1 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 @@ private static ImmutableMap canonicalizeGracePeriods( 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 238eb6e17f0..2659c01dbcd 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 @@ private void assertSuccessfulCreate( .setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) .setTargetId(getUniqueIdFromCommand()) .setRegistrarId("TheRegistrar") - .setEventTime(domain.getRegistrationExpirationTime()) + .setEventTime(domain.getRegistrationExpirationDateTime()) .setRecurrenceEndTime(END_OF_TIME) .setDomainHistory(historyEntry) .setRenewalPriceBehavior(expectedRenewalPriceBehavior) @@ -397,7 +397,7 @@ private void assertSuccessfulCreate( new PollMessage.Autorenew.Builder() .setTargetId(domain.getDomainName()) .setRegistrarId("TheRegistrar") - .setEventTime(domain.getRegistrationExpirationTime()) + .setEventTime(domain.getRegistrationExpirationDateTime()) .setMsg("Domain was auto-renewed.") .setHistoryEntry(historyEntry) .build()); @@ -1720,7 +1720,7 @@ private void assertPollMessagesWithCollisionOneTime(Domain domain) { new PollMessage.Autorenew.Builder() .setTargetId(domain.getDomainName()) .setRegistrarId("TheRegistrar") - .setEventTime(domain.getRegistrationExpirationTime()) + .setEventTime(domain.getRegistrationExpirationDateTime()) .setMsg("Domain was auto-renewed.") .setHistoryEntry(historyEntry) .build(), @@ -1853,7 +1853,7 @@ void testSuccess_customLogicIsCalled_andSavesExtraEntity() throws Exception { new PollMessage.Autorenew.Builder() .setTargetId(domain.getDomainName()) .setRegistrarId("TheRegistrar") - .setEventTime(domain.getRegistrationExpirationTime()) + .setEventTime(domain.getRegistrationExpirationDateTime()) .setMsg("Domain was auto-renewed.") .setHistoryEntry(historyEntry) .build(), diff --git a/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java index 223293b1f5f..9b3b2060b58 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java @@ -376,7 +376,7 @@ void testSuccess_updatedEppUpdateTimeAfterPendingRedemption() throws Exception { runFlowAssertResponse(loadFile("domain_delete_response_pending.xml")); Domain domain = reloadResourceByForeignKey(); - DateTime redemptionEndTime = domain.getLastEppUpdateTime().plusDays(3); + DateTime redemptionEndTime = domain.getLastEppUpdateDateTime().plusDays(3); Domain domainAtRedemptionTime = domain.cloneProjectedAtTime(redemptionEndTime); assertAboutDomains() .that(domainAtRedemptionTime) @@ -418,7 +418,7 @@ private void doSuccessfulTest_noAddGracePeriod( null)); // We should see exactly one poll message, which is for the autorenew 1 month in the future. assertPollMessages(createAutorenewPollMessage("TheRegistrar").build()); - DateTime expectedExpirationTime = domain.getRegistrationExpirationTime().minusYears(2); + DateTime expectedExpirationTime = domain.getRegistrationExpirationDateTime().minusYears(2); clock.advanceOneMilli(); runFlowAssertResponse(loadFile(responseFilename, substitutions)); Domain resource = reloadResourceByForeignKey(); @@ -462,7 +462,7 @@ private void assertDeletionPollMessageFor(Domain domain, String expectedMessage) // There should be a future poll message at the deletion time. The previous autorenew poll // message should now be deleted. assertAboutDomains().that(domain).hasDeletePollMessage(); - DateTime deletionTime = domain.getDeletionTime(); + DateTime deletionTime = domain.getDeletionDateTime(); assertThat(getPollMessages("TheRegistrar", deletionTime.minusMinutes(1))).isEmpty(); assertThat(getPollMessages("TheRegistrar", deletionTime)).hasSize(1); assertThat(domain.getDeletePollMessage()) @@ -496,7 +496,7 @@ void testSuccess_autorenewPollMessageIsNotDeleted() throws Exception { runFlowAssertResponse(loadFile("domain_delete_response_pending.xml")); // There should now be two poll messages; one for the delete of the domain (in the future), and // another for the unacked autorenew messages. - DateTime deletionTime = reloadResourceByForeignKey().getDeletionTime(); + DateTime deletionTime = reloadResourceByForeignKey().getDeletionDateTime(); assertThat(getPollMessages("TheRegistrar", deletionTime.minusMinutes(1))).hasSize(1); assertThat(getPollMessages("TheRegistrar", deletionTime)).hasSize(2); } @@ -613,7 +613,7 @@ void testSuccess_pendingTransfer() throws Exception { .isEqualTo(Trid.create("transferClient-trid", "transferServer-trid")); assertThat(panData.getActionResult()).isFalse(); // There should be a future poll message to the losing registrar at the deletion time. - DateTime deletionTime = domain.getDeletionTime(); + DateTime deletionTime = domain.getDeletionDateTime(); assertThat(getPollMessages("TheRegistrar", deletionTime.minusMinutes(1))).isEmpty(); assertThat(getPollMessages("TheRegistrar", deletionTime)).hasSize(1); assertOnlyBillingEventIsClosedAutorenew("TheRegistrar"); diff --git a/core/src/test/java/google/registry/flows/domain/DomainRenewFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainRenewFlowTest.java index 8b2f3a4e325..2743d6ac4f9 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainRenewFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainRenewFlowTest.java @@ -247,7 +247,7 @@ private void doSuccessfulTest( @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 @@ private void doSuccessfulTest( .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 @@ private void doSuccessfulTest( 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 @@ void testSuccess_autorenewPollMessageIsNotDeleted() throws Exception { 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 69c28ee896a..35eeb139945 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 @@ void testSuccess_expiryStillInFuture_notExtended() throws Exception { new PollMessage.Autorenew.Builder() .setTargetId("example.tld") .setRegistrarId("TheRegistrar") - .setEventTime(domain.getRegistrationExpirationTime()) + .setEventTime(domain.getRegistrationExpirationDateTime()) .setAutorenewEndTime(END_OF_TIME) .setMsg("Domain was auto-renewed.") .setHistoryEntry(historyEntryDomainRestore) @@ -269,7 +269,7 @@ void testSuccess_expiryInPast_extendedByOneYear() throws Exception { new PollMessage.Autorenew.Builder() .setTargetId("example.tld") .setRegistrarId("TheRegistrar") - .setEventTime(domain.getRegistrationExpirationTime()) + .setEventTime(domain.getRegistrationExpirationDateTime()) .setAutorenewEndTime(END_OF_TIME) .setMsg("Domain was auto-renewed.") .setHistoryEntry(historyEntryDomainRestore) diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java index aafa9387236..30a9339e3a2 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java @@ -148,7 +148,8 @@ private void assertTransferApproved(Domain domain, DomainTransferData oldTransfe .copyConstantFieldsToBuilder() .setTransferStatus(TransferStatus.CLIENT_APPROVED) .setPendingTransferExpirationTime(clock.nowUtc()) - .setTransferredRegistrationExpirationTime(domain.getRegistrationExpirationTime()) + .setTransferredRegistrationExpirationTime( + domain.getRegistrationExpirationDateTime()) .build()); } @@ -216,7 +217,7 @@ private void runSuccessfulFlowWithAssertions( // should be one at the current time to the gaining registrar, as well as one at the domain's // autorenew time. assertThat(getPollMessages(domain, "NewRegistrar", clock.nowUtc().plusMonths(1))).hasSize(1); - assertThat(getPollMessages(domain, "NewRegistrar", domain.getRegistrationExpirationTime())) + assertThat(getPollMessages(domain, "NewRegistrar", domain.getRegistrationExpirationDateTime())) .hasSize(2); PollMessage gainingTransferPollMessage = @@ -225,11 +226,11 @@ private void runSuccessfulFlowWithAssertions( getOnlyPollMessage( domain, "NewRegistrar", - domain.getRegistrationExpirationTime(), + domain.getRegistrationExpirationDateTime(), PollMessage.Autorenew.class); assertThat(gainingTransferPollMessage.getEventTime()).isEqualTo(clock.nowUtc()); assertThat(gainingAutorenewPollMessage.getEventTime()) - .isEqualTo(domain.getRegistrationExpirationTime()); + .isEqualTo(domain.getRegistrationExpirationDateTime()); DomainTransferResponse transferResponse = gainingTransferPollMessage .getResponseData() @@ -239,7 +240,7 @@ private void runSuccessfulFlowWithAssertions( .collect(onlyElement()); assertThat(transferResponse.getTransferStatus()).isEqualTo(TransferStatus.CLIENT_APPROVED); assertThat(transferResponse.getExtendedRegistrationExpirationTime()) - .isEqualTo(domain.getRegistrationExpirationTime()); + .isEqualTo(domain.getRegistrationExpirationDateTime()); PendingActionNotificationResponse panData = gainingTransferPollMessage .getResponseData() @@ -294,9 +295,9 @@ private void assertHistoryEntriesContainBillingEventsAndGracePeriods( .build(), getGainingClientAutorenewEvent() .asBuilder() - .setEventTime(domain.getRegistrationExpirationTime()) + .setEventTime(domain.getRegistrationExpirationDateTime()) .setRecurrenceLastExpansion( - domain.getRegistrationExpirationTime().minusYears(1)) + domain.getRegistrationExpirationDateTime().minusYears(1)) .setDomainHistory(historyEntryTransferApproved) .build())) .toArray(BillingBase[]::new)); @@ -332,9 +333,9 @@ private void assertHistoryEntriesDoNotContainTransferBillingEventsOrGracePeriods .build(), getGainingClientAutorenewEvent() .asBuilder() - .setEventTime(domain.getRegistrationExpirationTime()) + .setEventTime(domain.getRegistrationExpirationDateTime()) .setRecurrenceLastExpansion( - domain.getRegistrationExpirationTime().minusYears(1)) + domain.getRegistrationExpirationDateTime().minusYears(1)) .setDomainHistory(historyEntryTransferApproved) .build())) .toArray(BillingBase[]::new)); @@ -349,7 +350,7 @@ private void doSuccessfulTest(String tld, String commandFilename, String expecte tld, commandFilename, expectedXmlFilename, - domain.getRegistrationExpirationTime().plusYears(1), + domain.getRegistrationExpirationDateTime().plusYears(1), 1); } @@ -821,7 +822,7 @@ void testSuccess_superuserExtension_transferPeriodZero() throws Exception { "tld", "domain_transfer_approve.xml", "domain_transfer_approve_response_zero_period.xml", - domain.getRegistrationExpirationTime()); + domain.getRegistrationExpirationDateTime()); assertHistoryEntriesDoNotContainTransferBillingEventsOrGracePeriods(); } @@ -854,7 +855,7 @@ void testSuccess_superuserExtension_transferPeriodZero_autorenewGraceActive() th "tld", "domain_transfer_approve.xml", "domain_transfer_approve_response_zero_period_autorenew_grace.xml", - domain.getRegistrationExpirationTime()); + domain.getRegistrationExpirationDateTime()); assertHistoryEntriesDoNotContainTransferBillingEventsOrGracePeriods(); } diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferCancelFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferCancelFlowTest.java index c7b62116bb8..ea5ff9e16c3 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferCancelFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferCancelFlowTest.java @@ -114,7 +114,7 @@ private void doSuccessfulTest(String commandFilename) throws Exception { // 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("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 523120f4ade..b96a4f41223 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 @@ void testSuccess_tenYears() throws Exception { 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 @@ void testSuccess_serverApproved_afterAutorenews() throws Exception { // 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 f26b460d497..e3bac621677 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 @@ private void doSuccessfulTest(String commandFilename, String expectedXmlFilename 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 70ad4517e37..7afa97cd697 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 @@ private void assertTransferApproved( .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 @@ private void doSuccessfulTest( doSuccessfulTest( commandFilename, expectedXmlFilename, - domain.getRegistrationExpirationTime().plusYears(1), + domain.getRegistrationExpirationDateTime().plusYears(1), substitutions, Optional.empty()); } @@ -551,7 +552,9 @@ private void doSuccessfulTest(String commandFilename, String expectedXmlFilename throws Exception { clock.advanceOneMilli(); doSuccessfulTest( - commandFilename, expectedXmlFilename, domain.getRegistrationExpirationTime().plusYears(1)); + commandFilename, + expectedXmlFilename, + domain.getRegistrationExpirationDateTime().plusYears(1)); } private void doSuccessfulSuperuserExtensionTest( @@ -812,7 +815,7 @@ void testSuccess_superuserExtension_zeroPeriod_nonZeroAutomaticTransferLength() 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 @@ void testSuccess_superuserExtension_zeroPeriod_zeroAutomaticTransferLength() thr 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 @@ void testSuccess_superuserExtension_nonZeroPeriod_nonZeroAutomaticTransferLength 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 @@ void testSuccess_superuserExtension_zeroPeriod_autorenewGraceActive() throws Exc 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 @@ void testSuccess_superuserExtension_clientTransferProhibited() throws Exception 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 @@ void testSuccess_superuserExtension_serverTransferProhibited() throws Exception 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 @@ void testSuccess_customLogicFee_std_v1() throws Exception { 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 @@ void testSuccess_bulkPricingName_zeroPeriod() throws Exception { 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 @@ void testSuccess_customLogicFee_v06() throws Exception { 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 084cd41924b..2103b06d441 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 @@ void testSuccess_nameUnchanged_superordinateDomainWasTransferred() throws Except .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 e6e81d9a1df..ad04eb1d088 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.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.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 @@ private void assertTransferred( .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 @@ void testExpiredTransfer_autoRenewBeforeTransfer() { } 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 @@ void testEppLastUpdateTimeAndClientId_isSetCorrectlyWithNullPreviousValue() { 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 @@ void testGracePeriodsByType() { @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 @@ void testRenewalsDontHappenOnFebruary29() { .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 @@ void testMultipleAutoRenews() { .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 @@ void testClone_doNotExtendExpirationOnDeletedDomain() { .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 @@ void testClone_doNotExtendExpirationOnFutureDeletedDomain() { .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 @@ void testClone_extendsExpirationForExpiredTransferredDomain() { .setTransferData(transferData) .build()); - assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime()) + assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationDateTime()) .isEqualTo(newExpiration); } @@ -801,7 +810,7 @@ void testClone_extendsExpirationForNonExpiredTransferredDomain() { .setTransferData(transferData) .build()); - assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime()) + assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationDateTime()) .isEqualTo(newExpiration); } @@ -843,7 +852,7 @@ void testClone_removesBulkTokenFromTransferredDomain() { 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 @@ void testClone_doesNotExtendExpirationForPendingTransfer() { .setTransferData(transferData) .build()); - assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationTime()) + assertThat(domain.cloneProjectedAtTime(now).getRegistrationExpirationDateTime()) .isEqualTo(previousExpiration); } @@ -906,7 +915,7 @@ void testClone_doesNotRemoveBulkTokenForPendingTransfer() { .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 @@ void testClone_transferDuringAutorenew() { .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 bc79c043adc..8453d28ddc2 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 @@ void testSuccess_forBillingEvent() { 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 @@ void testSuccess_forRecurrence() { 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 @@ void testSuccess_createWithoutBillingEvent() { 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 baebec91be9..a8a039c4df3 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 @@ public And hasExactlyStatusValues(StatusValue... statusValues) { } 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 0036528baee..507a548c9c1 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 And hasCurrentSponsorRegistrarId(String registrarId) { public And 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 9f4d161c882..378231a46af 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 @@ void test_unrenewTwoDomains_worksSuccessfully() throws Exception { assertThat( ForeignKeyUtils.loadResource(Domain.class, "foo.tld", fakeClock.nowUtc()) .get() - .getRegistrationExpirationTime()) + .getRegistrationExpirationDateTime()) .isEqualTo(DateTime.parse("2019-12-06T13:55:01.001Z")); assertThat( ForeignKeyUtils.loadResource(Domain.class, "bar.tld", fakeClock.nowUtc()) .get() - .getRegistrationExpirationTime()) + .getRegistrationExpirationDateTime()) .isEqualTo(DateTime.parse("2018-12-06T13:55:01.002Z")); assertInStdout("Successfully unrenewed all domains."); } @@ -149,8 +149,8 @@ void test_unrenewDomain_savesDependentEntitiesCorrectly() throws Exception { .build())); // Check that fields on domain were updated correctly. - assertThat(domain.getRegistrationExpirationTime()).isEqualTo(newExpirationTime); - assertThat(domain.getLastEppUpdateTime()).isEqualTo(unrenewTime); + assertThat(domain.getRegistrationExpirationDateTime()).isEqualTo(newExpirationTime); + assertThat(domain.getLastEppUpdateDateTime()).isEqualTo(unrenewTime); assertThat(domain.getLastEppUpdateRegistrarId()).isEqualTo("TheRegistrar"); } diff --git a/core/src/test/java/google/registry/ui/server/console/domains/ConsoleBulkDomainActionTest.java b/core/src/test/java/google/registry/ui/server/console/domains/ConsoleBulkDomainActionTest.java index 7f5338f5e45..da0162a688e 100644 --- a/core/src/test/java/google/registry/ui/server/console/domains/ConsoleBulkDomainActionTest.java +++ b/core/src/test/java/google/registry/ui/server/console/domains/ConsoleBulkDomainActionTest.java @@ -19,6 +19,7 @@ import static google.registry.testing.DatabaseHelper.loadSingleton; import static google.registry.testing.DatabaseHelper.persistDomainWithDependentResources; import static google.registry.testing.DatabaseHelper.persistResource; +import static google.registry.util.DateTimeUtils.plusDays; import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST; import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN; import static jakarta.servlet.http.HttpServletResponse.SC_OK; @@ -92,7 +93,7 @@ void testSuccess_delete() { {"example.tld":{"message":"Command completed successfully; action pending",\ "responseCode":1001}}\ """); - assertThat(loadByEntity(domain).getDeletionTime()).isEqualTo(clock.nowUtc().plusDays(35)); + assertThat(loadByEntity(domain).getDeletionTime()).isEqualTo(plusDays(clock.now(), 35)); ConsoleUpdateHistory history = loadSingleton(ConsoleUpdateHistory.class).get(); assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.DOMAIN_DELETE); assertThat(history.getDescription()).hasValue("example.tld"); @@ -162,7 +163,7 @@ void testHalfSuccess_halfNonexistent() throws Exception { "nonexistent.tld":{"message":"The domain with given ID (nonexistent.tld) doesn\\u0027t exist.",\ "responseCode":2303}}\ """); - assertThat(loadByEntity(domain).getDeletionTime()).isEqualTo(clock.nowUtc().plusDays(35)); + assertThat(loadByEntity(domain).getDeletionTime()).isEqualTo(plusDays(clock.now(), 35)); ConsoleUpdateHistory history = loadSingleton(ConsoleUpdateHistory.class).get(); assertThat(history.getType()).isEqualTo(ConsoleUpdateHistory.Type.DOMAIN_DELETE); assertThat(history.getDescription()).hasValue("example.tld"); diff --git a/util/src/test/java/google/registry/util/DateTimeUtilsTest.java b/util/src/test/java/google/registry/util/DateTimeUtilsTest.java index 4dc92aa1f14..80eb7ec4193 100644 --- a/util/src/test/java/google/registry/util/DateTimeUtilsTest.java +++ b/util/src/test/java/google/registry/util/DateTimeUtilsTest.java @@ -15,7 +15,9 @@ package google.registry.util; import static com.google.common.truth.Truth.assertThat; +import static google.registry.util.DateTimeUtils.END_INSTANT; import static google.registry.util.DateTimeUtils.END_OF_TIME; +import static google.registry.util.DateTimeUtils.START_INSTANT; import static google.registry.util.DateTimeUtils.START_OF_TIME; import static google.registry.util.DateTimeUtils.earliestOf; import static google.registry.util.DateTimeUtils.isAtOrAfter; @@ -23,12 +25,15 @@ import static google.registry.util.DateTimeUtils.latestOf; import static google.registry.util.DateTimeUtils.leapSafeAddYears; import static google.registry.util.DateTimeUtils.leapSafeSubtractYears; +import static google.registry.util.DateTimeUtils.toDateTime; +import static google.registry.util.DateTimeUtils.toInstant; import static google.registry.util.DateTimeUtils.toLocalDate; import static google.registry.util.DateTimeUtils.toSqlDate; import static org.junit.jupiter.api.Assertions.assertThrows; import com.google.common.collect.ImmutableList; import java.sql.Date; +import java.time.Instant; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.junit.jupiter.api.Test; @@ -42,7 +47,7 @@ class DateTimeUtilsTest { @Test void testSuccess_earliestOf() { assertThat(earliestOf(START_OF_TIME, END_OF_TIME)).isEqualTo(START_OF_TIME); - assertThat(earliestOf(sampleDates)).isEqualTo(START_OF_TIME); + assertThat(DateTimeUtils.earliestDateTimeOf(sampleDates)).isEqualTo(START_OF_TIME); } @Test @@ -72,6 +77,12 @@ void testSuccess_leapSafeAddYears() { assertThat(leapSafeAddYears(startDate, 4)).isEqualTo(DateTime.parse("2016-02-28T00:00:00Z")); } + @Test + void test_leapSafeAddYears_worksWithInstants() { + Instant startDate = Instant.parse("2012-02-29T00:00:00Z"); + assertThat(leapSafeAddYears(startDate, 4)).isEqualTo(Instant.parse("2016-02-28T00:00:00Z")); + } + @Test void testSuccess_leapSafeSubtractYears() { DateTime startDate = DateTime.parse("2012-02-29T00:00:00Z"); @@ -80,6 +91,13 @@ void testSuccess_leapSafeSubtractYears() { .isEqualTo(DateTime.parse("2008-02-28T00:00:00Z")); } + @Test + void test_leapSafeSubtractYears_worksWithInstants() { + Instant startDate = Instant.parse("2012-02-29T00:00:00Z"); + assertThat(leapSafeSubtractYears(startDate, 4)) + .isEqualTo(Instant.parse("2008-02-28T00:00:00Z")); + } + @Test void testSuccess_leapSafeSubtractYears_zeroYears() { DateTime leapDay = DateTime.parse("2012-02-29T00:00:00Z"); @@ -107,4 +125,32 @@ void testSuccess_toLocalDate() { 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")); + } }