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
2 changes: 1 addition & 1 deletion GEMINI.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ This document captures high-level architectural patterns, lessons learned from l
## Self-Review Guidelines
Before finalizing any PR or declaring a task complete, you MUST perform a thorough, rigorous self-review of your entire diff. Run `git diff HEAD^` (or review the staged changes) and actively verify the following against every modified line:

1. **Imports & FQNs:** Did I leave any fully-qualified class names or static variables inline? Did I add the necessary imports for them? *Crucial Exception:* If the file already imports a class with the identical name (e.g., it uses both `java.time.Duration` and `org.joda.time.Duration`), one MUST remain fully qualified to avoid a compilation conflict.
1. **Imports & FQNs:** Did I leave any fully-qualified class names or static variables inline? Did I add the necessary imports for them? *Crucial Exception:* If the file already imports a class with the identical name (e.g., it uses both `java.util.Date` and `java.sql.Date`), one MUST remain fully qualified to avoid a compilation conflict.
2. **Redundant Conversions:** Did I use `toDateTime(clock.now())` where `clock.nowUtc()` would suffice? Did I use `toDateTime(END_INSTANT)` instead of `END_OF_TIME`? Did I use `.toInstant()` or `.toDateTime()` on something that could be avoided by using a different method overload (e.g., `tm().getTxTime()`)?
3. **Verbose Math:** Did I write any verbose time conversions inline? Are there `DateTimeUtils` methods I should be using instead? If not, should I abstract this math into `DateTimeUtils`?
4. **Assertion Cleanliness:** Am I polluting test assertions with `toDateTime(...)` wraps? If so, I need to add overloaded assertions to the Truth Subjects instead.
Expand Down
13 changes: 12 additions & 1 deletion common/src/main/java/google/registry/util/Clock.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import java.io.Serializable;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import javax.annotation.concurrent.ThreadSafe;
Expand All @@ -24,7 +25,7 @@
* A clock that tells the current time in milliseconds or nanoseconds.
*
* <p>Clocks are technically serializable because they are either a stateless wrapper around the
* system clock, or for testing, are just a wrapper around a DateTime. This means that if you
* system clock, or for testing, are just a wrapper around a Instant. This means that if you
* serialize a clock and deserialize it elsewhere, you won't necessarily get the same time or time
* zone -- what you will get is a functioning clock.
*/
Expand All @@ -38,4 +39,14 @@ public interface Clock extends Serializable {
default ZonedDateTime nowDate() {
return ZonedDateTime.ofInstant(now(), ZoneOffset.UTC);
}

/** Returns the current time as a {@link LocalDate} in UTC. */
default LocalDate todayUtc() {
return LocalDate.ofInstant(now(), ZoneOffset.UTC);
}

/** Returns the current time in milliseconds since the epoch. */
default long nowMillis() {
return now().toEpochMilli();
}
}
32 changes: 0 additions & 32 deletions common/src/main/java/google/registry/util/DateTimeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package google.registry.util;

import static com.google.common.base.Preconditions.checkArgument;
import static org.joda.time.DateTimeZone.UTC;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
Expand All @@ -29,9 +28,6 @@
import java.time.format.SignStyle;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.joda.time.ReadableDuration;

public abstract class DateTimeUtils {

Expand Down Expand Up @@ -110,17 +106,6 @@ public static Instant latestOf(Iterable<Instant> instants) {
return Ordering.<Instant>natural().max(instants);
}

/** Converts a Joda-Time Duration to a java.time.Duration. */
@Nullable
public static java.time.Duration toJavaDuration(@Nullable ReadableDuration duration) {
return duration == null ? null : java.time.Duration.ofMillis(duration.getMillis());
}

/** Converts a java.time.Duration to a Joda-Time Duration. */
@Nullable
public static org.joda.time.Duration toJodaDuration(@Nullable java.time.Duration duration) {
return duration == null ? null : org.joda.time.Duration.millis(duration.toMillis());
}

/** Returns whether the first {@link Instant} is equal to or earlier than the second. */
public static boolean isBeforeOrAt(Instant timeToCheck, Instant timeToCompareTo) {
Expand Down Expand Up @@ -171,23 +156,6 @@ public static LocalDate toLocalDate(Instant instant) {
return instant.atZone(ZoneOffset.UTC).toLocalDate();
}

/** 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(), UTC);
}

/** Convert a java.time {@link java.time.Instant} to a joda {@link org.joda.time.Instant}. */
@Nullable
public static org.joda.time.Instant toJodaInstant(@Nullable java.time.Instant instant) {
return (instant == null) ? null : org.joda.time.Instant.ofEpochMilli(instant.toEpochMilli());
}

public static Instant plusHours(Instant instant, long hours) {
return instant.plus(hours, ChronoUnit.HOURS);
Expand Down
2 changes: 1 addition & 1 deletion common/src/main/java/google/registry/util/SystemClock.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public SystemClock() {}

@Override
public Instant now() {
// Truncate to milliseconds to match the precision of Joda DateTime and our database schema
// Truncate to milliseconds to match the precision of Joda Instant and our database schema
// (which uses millisecond precision via DateTimeConverter). This prevents subtle comparison
// bugs where a high-precision Instant would be considered "after" a truncated database
// timestamp.
Expand Down
26 changes: 0 additions & 26 deletions common/src/testing/java/google/registry/testing/FakeClock.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import java.time.Instant;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.concurrent.ThreadSafe;
import org.joda.time.ReadableDuration;
import org.joda.time.ReadableInstant;

/** A mock clock for testing purposes that supports telling, setting, and advancing the time. */
@ThreadSafe
Expand All @@ -41,12 +39,6 @@ public FakeClock() {
this(START_INSTANT);
}

/** Creates a FakeClock initialized to a specific time. */
@Deprecated
public FakeClock(ReadableInstant startTime) {
setTo(startTime);
}

/** Creates a FakeClock initialized to a specific time. */
public FakeClock(Instant startTime) {
setTo(startTime);
Expand All @@ -66,12 +58,6 @@ public Instant now() {
* @param autoIncrementStep the new auto increment duration
* @return this
*/
@Deprecated
public FakeClock setAutoIncrementStep(ReadableDuration autoIncrementStep) {
this.autoIncrementStepMs = autoIncrementStep.getMillis();
return this;
}

/**
* 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 All @@ -91,23 +77,11 @@ public void advanceOneMilli() {
advanceBy(Duration.ofMillis(1));
}

/** Advances clock by some duration. */
@Deprecated
public void advanceBy(ReadableDuration duration) {
currentTimeMillis.addAndGet(duration.getMillis());
}

/** Advances clock by some duration. */
public void advanceBy(Duration duration) {
currentTimeMillis.addAndGet(duration.toMillis());
}

/** Sets the time to the specified instant. */
@Deprecated
public void setTo(ReadableInstant time) {
currentTimeMillis.set(time.getMillis());
}

/** Sets the time to the specified instant. */
public void setTo(Instant time) {
currentTimeMillis.set(time.toEpochMilli());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public class DeleteProberDataAction implements Runnable {
// prevents accidental double-map with the same key from immediately deleting active domains)
//
// Note: creationTime must be compared to a Java object (CreateAutoTimestamp) but deletionTime can
// be compared directly to the SQL timestamp (it's a DateTime)
// be compared directly to the SQL timestamp (it's a Instant)
private static final String DOMAIN_QUERY_STRING =
"FROM Domain d WHERE d.tld IN :tlds AND d.domainName NOT LIKE 'nic.%%' AND"
+ " (d.subordinateHosts IS NULL OR array_length(d.subordinateHosts) = 0) AND"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
* A record representing a single billable event, parsed from a {@code SchemaAndRecord}.
*
* @param id The unique ID for the {@code BillingEvent} associated with this event.
* @param billingTime The DateTime (in UTC) this event becomes billable.
* @param eventTime The DateTime (in UTC) this event was generated.
* @param billingTime The Instant (in UTC) this event becomes billable.
* @param eventTime The Instant (in UTC) this event was generated.
* @param registrarId The billed registrar's name.
* @param billingId The billed registrar's billing account key.
* @param poNumber The Purchase Order number.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaQuery;
import java.io.Serializable;
import java.time.Instant;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.joda.time.DateTime;

/** Interface for query instances used by {@link RegistryJpaIO.Read}. */
public interface RegistryQuery<T> extends Serializable {
Expand Down Expand Up @@ -61,11 +59,7 @@ static <T> RegistryQuery<T> createQuery(
if (parameters != null) {
parameters.forEach(
(key, value) -> {
if (value instanceof DateTime dt) {
query.setParameter(key, Instant.ofEpochMilli(dt.getMillis()));
} else {
query.setParameter(key, value);
}
query.setParameter(key, value);
});
}
JpaTransactionManager.setQueryFetchSize(query, QUERY_FETCH_SIZE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

package google.registry.beam.spec11;

import static google.registry.util.DateTimeUtils.toJodaInstant;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.http.HttpStatus.SC_OK;

Expand Down Expand Up @@ -127,12 +126,17 @@ static class EvaluateSafeBrowsingFn
}

/** Evaluates any buffered {@link DomainNameInfo} objects upon completing the bundle. */
@SuppressWarnings("UnnecessarilyFullyQualified")
@FinishBundle
public void finishBundle(FinishBundleContext context) {
if (!domainNameInfoBuffer.isEmpty()) {
ImmutableSet<KV<DomainNameInfo, ThreatMatch>> results = evaluateAndFlush();
results.forEach(
(kv) -> context.output(kv, toJodaInstant(clock.now()), GlobalWindow.INSTANCE));
(kv) ->
context.output(
kv,
org.joda.time.Instant.ofEpochMilli(clock.nowMillis()),
GlobalWindow.INSTANCE));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ private DelegatedCredentials(
@Override
public AccessToken refreshAccessToken() throws IOException {
JsonFactory jsonFactory = JSON_FACTORY;
long currentTime = clock.now().toEpochMilli();
long currentTime = clock.nowMillis();
String assertion = createAssertion(jsonFactory, currentTime);

GenericData tokenRequest = new GenericData();
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/google/registry/config/RegistryConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@
import java.lang.annotation.Retention;
import java.net.URI;
import java.net.URL;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.joda.time.DateTimeConstants;

/**
* Central clearing-house for all configuration.
Expand Down Expand Up @@ -271,7 +271,7 @@ public static String provideBrdaBucket(@Config("projectId") String projectId) {
@Provides
@Config("brdaDayOfWeek")
public static int provideBrdaDayOfWeek() {
return DateTimeConstants.TUESDAY;
return DayOfWeek.TUESDAY.getValue();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import dagger.Provides;
import google.registry.request.Parameter;
import jakarta.servlet.http.HttpServletRequest;
import org.joda.time.Minutes;

/**
* Dagger module for loadtest package.
Expand All @@ -42,15 +41,13 @@ static String provideClientId(HttpServletRequest req) {
@Provides
@Parameter("delaySeconds")
static int provideDelaySeconds(HttpServletRequest req) {
return extractOptionalIntParameter(req, "delaySeconds")
.orElse(Minutes.ONE.toStandardSeconds().getSeconds());
return extractOptionalIntParameter(req, "delaySeconds").orElse(60);
}

@Provides
@Parameter("runSeconds")
static int provideRunSeconds(HttpServletRequest req) {
return extractOptionalIntParameter(req, "runSeconds")
.orElse(Minutes.ONE.toStandardSeconds().getSeconds());
return extractOptionalIntParameter(req, "runSeconds").orElse(60);
}

@Provides
Expand Down
6 changes: 3 additions & 3 deletions core/src/main/java/google/registry/model/common/Cursor.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ public enum CursorType {
RECURRING_BILLING(false),

/**
* Cursor for {@link google.registry.export.sheet.SyncRegistrarsSheetAction}. The DateTime
* stored is the last time that registrar changes were successfully synced to the sheet. If
* there were no changes since the last time the action run, the cursor is not updated.
* Cursor for {@link google.registry.export.sheet.SyncRegistrarsSheetAction}. The Instant stored
* is the last time that registrar changes were successfully synced to the sheet. If there were
* no changes since the last time the action run, the cursor is not updated.
*/
SYNC_REGISTRAR_SHEET(false),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@
xmlns = @XmlNs(prefix = "contact", namespaceURI = "urn:ietf:params:xml:ns:contact-1.0"),
elementFormDefault = XmlNsForm.QUALIFIED)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(UtcInstantAdapter.class)
})
@XmlJavaTypeAdapters({@XmlJavaTypeAdapter(UtcDateTimeAdapter.class)})
package google.registry.model.contact;

import google.registry.xml.UtcInstantAdapter;
import google.registry.xml.UtcDateTimeAdapter;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlNs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,8 @@ public class DomainBase extends EppResource {
*
* <p>When a domain is scheduled to not autorenew, this field is set to the current value of its
* {@link #registrationExpirationTime}, after which point the next invocation of a periodic
* cronjob will explicitly delete the domain. This field is a DateTime and not a boolean because
* of edge cases that occur during the autorenew grace period. We need to be able to tell the
* cronjob will explicitly delete the domain. This field is a Instant and not a boolean because of
* edge cases that occur during the autorenew grace period. We need to be able to tell the
* difference domains that have reached their life and must be deleted now, and domains that
* happen to be in the autorenew grace period now but should be deleted in roughly a year.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@


import google.registry.model.eppoutput.EppResponse.ResponseData;
import google.registry.xml.UtcInstantAdapter;
import google.registry.xml.UtcDateTimeAdapter;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlType;
Expand All @@ -31,7 +31,7 @@ public class DomainRenewData implements ResponseData {
String name;

@XmlElement(name = "exDate")
@XmlJavaTypeAdapter(UtcInstantAdapter.class)
@XmlJavaTypeAdapter(UtcDateTimeAdapter.class)
Instant expirationDate;

public static DomainRenewData create(String name, Instant expirationDate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.Period;
import java.util.stream.Stream;
import org.joda.time.Period;

/** Base class for the fee and credit types. */
@XmlTransient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(CurrencyUnitAdapter.class),
@XmlJavaTypeAdapter(UtcInstantAdapter.class)
@XmlJavaTypeAdapter(UtcDateTimeAdapter.class)
})
package google.registry.model.domain.fee12;

import google.registry.model.adapters.CurrencyUnitAdapter;
import google.registry.xml.UtcInstantAdapter;
import google.registry.xml.UtcDateTimeAdapter;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlNs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(CurrencyUnitAdapter.class),
@XmlJavaTypeAdapter(UtcInstantAdapter.class)
@XmlJavaTypeAdapter(UtcDateTimeAdapter.class)
})
package google.registry.model.domain.feestdv1;

import google.registry.model.adapters.CurrencyUnitAdapter;
import google.registry.xml.UtcInstantAdapter;
import google.registry.xml.UtcDateTimeAdapter;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlNs;
Expand Down
Loading
Loading