1
0
mirror of https://github.com/google/nomulus synced 2026-05-20 06:41:51 +00:00

Refactor foundational temporal types to java.time (#3036)

* Migrates core classes (Clock, Sleeper, TransactionManager) and extensive domain models from Joda-Time to java.time.
* Restores original public API method names while substituting parameters/return values with `java.time.Instant`.
* Updates JAXB XJC `bindings.xjb` to natively generate `java.time.Instant` and `java.time.LocalDate`, eliminating `toDateTime` wrapper methods.
* Fixes XML serializers (`DateAdapter`) to robustly convert OffsetDateTime timezone strings to UTC.
* Cleans up redundant imports and Checkstyle failures across the codebase.

Remaining Joda-Time surface area to migrate in future tasks:
* Command-line parameters (e.g. `DateTimeParameter`, `DateParameter`, `IntervalParameter`) in `google.registry.tools.params`.
* EPP/RDAP flow testing infrastructure (`EppTestCase`, `RdapActionBaseTestCase`, `FlowTestCase`).
* Beam pipelines and Load Testing modules (`Spec11PipelineTest`, `RdePipelineTest`, `RegistryJpaReadTest`, `EppClient`).
* Utility bridges and converters (`DateTimeUtils.toDateTime/toInstant`, `DateTimeConverter`, `UtcDateTimeAdapter`).
* Remaining UI Console tests and Actions.
This commit is contained in:
Ben McIlwain
2026-05-08 17:04:00 -04:00
committed by GitHub
parent 60d3653b46
commit b69d51add1
320 changed files with 2450 additions and 3488 deletions

View File

@@ -20,8 +20,8 @@ import static org.joda.time.DateTimeZone.UTC;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import java.sql.Date;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
@@ -31,27 +31,13 @@ import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.ReadableDuration;
/** Utilities methods and constants related to Joda {@link DateTime} objects. */
public abstract class DateTimeUtils {
/** The start of the epoch, in a convenient constant. */
@Deprecated public static final DateTime START_OF_TIME = new DateTime(0, UTC);
/** The start of the UNIX epoch (which is defined in UTC), in a convenient constant. */
public static final Instant START_INSTANT = Instant.ofEpochMilli(0);
/**
* A date in the far future that we can treat as infinity.
*
* <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.
*/
@Deprecated public static final DateTime END_OF_TIME = new DateTime(Long.MAX_VALUE / 1000, UTC);
/**
* An instant in the far future that we can treat as infinity.
*
@@ -71,7 +57,7 @@ public abstract class DateTimeUtils {
*/
private static final DateTimeFormatter ISO_8601_FORMATTER =
new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4, 10, SignStyle.NORMAL)
.appendValue(ChronoField.YEAR, 4, 10, SignStyle.NOT_NEGATIVE)
.appendPattern("-MM-dd'T'HH:mm:ss.SSS'Z'")
.toFormatter()
.withZone(ZoneOffset.UTC);
@@ -102,55 +88,28 @@ public abstract class DateTimeUtils {
}
}
/** 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 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 latestDateTimeOf(Lists.asList(first, rest));
}
/** Returns the latest of a number of given {@link Instant} instances. */
public static Instant latestOf(Instant first, Instant... rest) {
return latestOf(Lists.asList(first, rest));
}
/** Returns the latest element in a {@link DateTime} iterable. */
public static DateTime latestDateTimeOf(Iterable<DateTime> dates) {
checkArgument(!Iterables.isEmpty(dates));
return Ordering.<DateTime>natural().max(dates);
}
/** Returns the latest element in a {@link Instant} iterable. */
public static Instant latestOf(Iterable<Instant> instants) {
checkArgument(!Iterables.isEmpty(instants));
return Ordering.<Instant>natural().max(instants);
}
/** Returns whether the first {@link DateTime} is equal to or earlier than the second. */
public static boolean isBeforeOrAt(DateTime timeToCheck, DateTime timeToCompareTo) {
return !timeToCheck.isAfter(timeToCompareTo);
}
/** Converts a Joda-Time Duration to a java.time.Duration. */
@Nullable
public static java.time.Duration toJavaDuration(@Nullable ReadableDuration duration) {
@@ -168,25 +127,11 @@ public abstract class DateTimeUtils {
return !timeToCheck.isAfter(timeToCompareTo);
}
/** Returns whether the first {@link DateTime} is equal to or later than the second. */
public static boolean isAtOrAfter(DateTime timeToCheck, DateTime timeToCompareTo) {
return !timeToCheck.isBefore(timeToCompareTo);
}
/** Returns whether the first {@link Instant} is equal to or later than the second. */
public static boolean isAtOrAfter(Instant timeToCheck, Instant timeToCompareTo) {
return !timeToCheck.isBefore(timeToCompareTo);
}
/**
* Adds years to a date, in the {@code Duration} sense of semantic years. Use this instead of
* {@link DateTime#plusYears} to ensure that we never end up on February 29.
*/
public static DateTime plusYears(DateTime now, int years) {
checkArgument(years >= 0);
return years == 0 ? now : now.plusYears(1).plusYears(years - 1);
}
/**
* Adds years to a date, in the {@code Duration} sense of semantic years. Use this instead of
* {@link java.time.ZonedDateTime#plusYears} to ensure that we never end up on February 29.
@@ -210,15 +155,6 @@ public abstract class DateTimeUtils {
return now.atZone(ZoneOffset.UTC).minusMonths(months).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.
*/
public static DateTime minusYears(DateTime now, int years) {
checkArgument(years >= 0);
return years == 0 ? now : now.minusYears(1).minusYears(years - 1);
}
/**
* Subtracts years from a date, in the {@code Duration} sense of semantic years. Use this instead
* of {@link java.time.ZonedDateTime#minusYears} to ensure that we never end up on February 29.
@@ -230,40 +166,9 @@ public abstract class DateTimeUtils {
: now.atZone(ZoneOffset.UTC).minusYears(1).minusYears(years - 1).toInstant();
}
/**
* @deprecated Use {@link #plusYears(DateTime, int)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static DateTime leapSafeAddYears(DateTime now, int years) {
return plusYears(now, years);
}
/**
* @deprecated Use {@link #minusYears(DateTime, int)}
*/
@Deprecated
@SuppressWarnings("InlineMeSuggester")
public static DateTime leapSafeSubtractYears(DateTime now, int years) {
return minusYears(now, years);
}
public static Date toSqlDate(LocalDate localDate) {
return new Date(localDate.toDateTimeAtStartOfDay().getMillis());
}
public static LocalDate toLocalDate(Date date) {
return new LocalDate(date.getTime(), UTC);
}
/** Converts a java.time.LocalDate to a Joda-Time LocalDate. */
public static LocalDate toJodaLocalDate(java.time.LocalDate localDate) {
return new LocalDate(localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth());
}
/** Converts an Instant to a Joda-Time LocalDate in UTC. */
public static LocalDate toJodaLocalDate(Instant instant) {
return new LocalDate(instant.toEpochMilli(), UTC);
/** Converts an Instant to a java.time.LocalDate in UTC. */
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. */
@@ -300,11 +205,19 @@ public abstract class DateTimeUtils {
return instant.minus(minutes, ChronoUnit.MINUTES);
}
public static Instant plusDays(Instant instant, int days) {
public static Instant plusWeeks(Instant instant, int weeks) {
return instant.atZone(ZoneOffset.UTC).plusWeeks(weeks).toInstant();
}
public static Instant minusWeeks(Instant instant, int weeks) {
return instant.atZone(ZoneOffset.UTC).minusWeeks(weeks).toInstant();
}
public static Instant plusDays(Instant instant, long days) {
return instant.atZone(ZoneOffset.UTC).plusDays(days).toInstant();
}
public static Instant minusDays(Instant instant, int days) {
public static Instant minusDays(Instant instant, long days) {
return instant.atZone(ZoneOffset.UTC).minusDays(days).toInstant();
}
}