Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions common/src/main/java/google/registry/util/Clock.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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();
}
89 changes: 87 additions & 2 deletions common/src/main/java/google/registry/util/DateTimeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -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.
*
* <p>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<DateTime> dates) {
public static DateTime earliestDateTimeOf(Iterable<DateTime> dates) {
checkArgument(!Iterables.isEmpty(dates));
return Ordering.<DateTime>natural().min(dates);
}

/** Returns the earliest element in a {@link Instant} iterable. */
public static Instant earliestOf(Iterable<Instant> instants) {
checkArgument(!Iterables.isEmpty(instants));
return Ordering.<Instant>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));
Expand All @@ -66,34 +93,92 @@ 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());
}

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();
}
}
6 changes: 6 additions & 0 deletions common/src/main/java/google/registry/util/SystemClock.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -34,4 +35,9 @@ public SystemClock() {}
public DateTime nowUtc() {
return DateTime.now(UTC);
}

@Override
public Instant now() {
return Instant.now();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -212,7 +212,7 @@ private void runTransferFlowInTransaction(String domainName) {

private boolean shouldSkipDomain(String domainName) {
Optional<Domain> 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++;
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand Down
11 changes: 9 additions & 2 deletions core/src/main/java/google/registry/flows/ResourceFlowUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -89,6 +91,11 @@ public static void verifyTransferInitiator(String registrarId, Domain domain)

public static <R extends EppResource & ForeignKeyedEppResource> R loadAndVerifyExistence(
Class<R> clazz, String targetId, DateTime now) throws ResourceDoesNotExistException {
return loadAndVerifyExistence(clazz, targetId, toInstant(now));
}

public static <R extends EppResource & ForeignKeyedEppResource> R loadAndVerifyExistence(
Class<R> clazz, String targetId, Instant now) throws ResourceDoesNotExistException {
return verifyExistence(clazz, targetId, ForeignKeyUtils.loadResource(clazz, targetId, now));
}

Expand Down Expand Up @@ -197,8 +204,8 @@ public static void verifyAllStatusesAreClientSettable(Set<StatusValue> 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@
}

// Cancel any grace periods that were still active, and set the expiration time accordingly.
DateTime newExpirationTime = existingDomain.getRegistrationExpirationTime();
DateTime newExpirationTime = existingDomain.getRegistrationExpirationDateTime();

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation Note

Invoking
DomainBase.getRegistrationExpirationDateTime
should be avoided because it has been deprecated.
for (GracePeriod gracePeriod : existingDomain.getGracePeriods()) {
// No cancellation is written if the grace period was not for a billable event.
if (gracePeriod.hasBillingEvent()) {
Expand Down Expand Up @@ -289,7 +289,7 @@
flowCustomLogic.beforeResponse(
BeforeResponseParameters.newBuilder()
.setResultCode(
newDomain.getDeletionTime().isAfter(now)
newDomain.getDeletionDateTime().isAfter(now)

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation Note

Invoking
EppResource.getDeletionDateTime
should be avoided because it has been deprecated.
? SUCCESS_WITH_ACTION_PENDING
: SUCCESS)
.setResponseExtensions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
.setTargetId(domain.getDomainName())
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
.setEventTime(domain.getRegistrationExpirationTime());
.setEventTime(domain.getRegistrationExpirationDateTime());

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation Note

Invoking
DomainBase.getRegistrationExpirationDateTime
should be avoided because it has been deprecated.
}

/**
Expand All @@ -514,7 +514,7 @@
return new Autorenew.Builder()
.setTargetId(domain.getDomainName())
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
.setEventTime(domain.getRegistrationExpirationTime())
.setEventTime(domain.getRegistrationExpirationDateTime())

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation Note

Invoking
DomainBase.getRegistrationExpirationDateTime
should be avoided because it has been deprecated.
.setMsg("Domain was auto-renewed.");
}

Expand Down Expand Up @@ -658,7 +658,7 @@
// 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);

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation Note

Invoking
DomainBase.getRegistrationExpirationDateTime
should be avoided because it has been deprecated.
fees = pricingLogic.getRestorePrice(tld, domainNameString, now, isExpired).getFees();
}
case TRANSFER -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@
.setNameservers(
hostsRequest.requestDelegated() ? domain.loadNameserverHostNames() : null)
.setCreationTime(domain.getCreationTime())
.setLastEppUpdateTime(domain.getLastEppUpdateTime())
.setRegistrationExpirationTime(domain.getRegistrationExpirationTime())
.setLastEppUpdateTime(domain.getLastEppUpdateDateTime())

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation Note

Invoking
EppResource.getLastEppUpdateDateTime
should be avoided because it has been deprecated.
.setRegistrationExpirationTime(domain.getRegistrationExpirationDateTime())

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation Note

Invoking
DomainBase.getRegistrationExpirationDateTime
should be avoided because it has been deprecated.
.setLastTransferTime(domain.getLastTransferTime());

// If authInfo is non-null, then the caller is authorized to see the full information since we
Expand Down
Loading
Loading