Merge "Fix JdkObsolete: Use new methods from PersonIdent to avoid Date/TimeZone"
diff --git a/java/com/google/gerrit/acceptance/testsuite/change/ChangeOperationsImpl.java b/java/com/google/gerrit/acceptance/testsuite/change/ChangeOperationsImpl.java
index b91a56a..c1029be 100644
--- a/java/com/google/gerrit/acceptance/testsuite/change/ChangeOperationsImpl.java
+++ b/java/com/google/gerrit/acceptance/testsuite/change/ChangeOperationsImpl.java
@@ -47,7 +47,6 @@
 import com.google.gerrit.server.util.time.TimeUtil;
 import com.google.inject.Inject;
 import java.io.IOException;
-import java.sql.Timestamp;
 import java.time.Instant;
 import java.util.Arrays;
 import java.util.Objects;
@@ -140,8 +139,7 @@
         RevWalk revWalk = new RevWalk(objectInserter.newReader())) {
       Instant now = TimeUtil.now();
       IdentifiedUser changeOwner = getChangeOwner(changeCreation);
-      PersonIdent authorAndCommitter =
-          changeOwner.newCommitterIdent(now, serverIdent.getTimeZone());
+      PersonIdent authorAndCommitter = changeOwner.newCommitterIdent(now, serverIdent.getZoneId());
       ObjectId commitId =
           createCommit(repository, revWalk, objectInserter, changeCreation, authorAndCommitter);
 
@@ -496,13 +494,10 @@
       return Optional.ofNullable(oldPatchsetCommit.getAuthorIdent()).orElse(serverIdent);
     }
 
-    // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-    // Instants
-    @SuppressWarnings("JdkObsolete")
     private PersonIdent getCommitter(RevCommit oldPatchsetCommit, Instant now) {
       PersonIdent oldPatchsetCommitter =
           Optional.ofNullable(oldPatchsetCommit.getCommitterIdent()).orElse(serverIdent);
-      if (asSeconds(now) == asSeconds(oldPatchsetCommitter.getWhen().toInstant())) {
+      if (asSeconds(now) == asSeconds(oldPatchsetCommitter.getWhenAsInstant())) {
         /* We need to ensure that the resulting commit SHA-1 is different from the old patchset.
          * In real situations, this automatically happens as two patchsets won't have exactly the
          * same commit timestamp even when the tree and commit message are the same. In tests,
@@ -512,7 +507,7 @@
          * here and simply add a second. */
         now = now.plusSeconds(1);
       }
-      return new PersonIdent(oldPatchsetCommitter, Timestamp.from(now));
+      return new PersonIdent(oldPatchsetCommitter, now);
     }
 
     private long asSeconds(Instant date) {
diff --git a/java/com/google/gerrit/extensions/common/testing/GitPersonSubject.java b/java/com/google/gerrit/extensions/common/testing/GitPersonSubject.java
index cb9d855..f75ec66 100644
--- a/java/com/google/gerrit/extensions/common/testing/GitPersonSubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/GitPersonSubject.java
@@ -72,14 +72,14 @@
 
   // TODO(issue-15508): Migrate timestamp fields in *Info/*Input classes from type Timestamp to
   // Instant
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
   @SuppressWarnings("JdkObsolete")
   public void matches(PersonIdent ident) {
     isNotNull();
     name().isEqualTo(ident.getName());
     email().isEqualTo(ident.getEmailAddress());
-    check("roundedDate()").that(gitPerson.date.getTime()).isEqualTo(ident.getWhen().getTime());
+    check("roundedDate()")
+        .that(gitPerson.date.getTime())
+        .isEqualTo(ident.getWhenAsInstant().toEpochMilli());
     tz().isEqualTo(ident.getTimeZoneOffset());
   }
 }
diff --git a/java/com/google/gerrit/pgm/init/AccountsOnInit.java b/java/com/google/gerrit/pgm/init/AccountsOnInit.java
index c56a8d9..be5fe1a 100644
--- a/java/com/google/gerrit/pgm/init/AccountsOnInit.java
+++ b/java/com/google/gerrit/pgm/init/AccountsOnInit.java
@@ -30,7 +30,6 @@
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Path;
-import java.util.Date;
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.dircache.DirCacheEditor;
 import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
@@ -61,16 +60,12 @@
     this.allUsers = allUsers.get();
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   public Account insert(Account.Builder account) throws IOException {
     File path = getPath();
     try (Repository repo = new FileRepository(path);
         ObjectInserter oi = repo.newObjectInserter()) {
       PersonIdent ident =
-          new PersonIdent(
-              new GerritPersonIdentProvider(flags.cfg).get(), Date.from(account.registeredOn()));
+          new PersonIdent(new GerritPersonIdentProvider(flags.cfg).get(), account.registeredOn());
 
       Config accountConfig = new Config();
       AccountProperties.writeToAccountConfig(
diff --git a/java/com/google/gerrit/pgm/init/GroupsOnInit.java b/java/com/google/gerrit/pgm/init/GroupsOnInit.java
index 020705e..f8fcadd 100644
--- a/java/com/google/gerrit/pgm/init/GroupsOnInit.java
+++ b/java/com/google/gerrit/pgm/init/GroupsOnInit.java
@@ -40,7 +40,6 @@
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Path;
-import java.sql.Timestamp;
 import java.time.Instant;
 import java.util.stream.Stream;
 import org.eclipse.jgit.errors.ConfigInvalidException;
@@ -166,14 +165,10 @@
     return AuditLogFormatter.createBackedBy(ImmutableSet.of(account), ImmutableSet.of(), serverId);
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private void commit(Repository repository, GroupConfig groupConfig, Instant groupCreatedOn)
       throws IOException {
     PersonIdent personIdent =
-        new PersonIdent(
-            new GerritPersonIdentProvider(flags.cfg).get(), Timestamp.from(groupCreatedOn));
+        new PersonIdent(new GerritPersonIdentProvider(flags.cfg).get(), groupCreatedOn);
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate(repository, personIdent)) {
       groupConfig.commit(metaDataUpdate);
     }
diff --git a/java/com/google/gerrit/server/CommonConverters.java b/java/com/google/gerrit/server/CommonConverters.java
index e7fd1c5..4ad143b 100644
--- a/java/com/google/gerrit/server/CommonConverters.java
+++ b/java/com/google/gerrit/server/CommonConverters.java
@@ -25,14 +25,11 @@
  * static utility methods.
  */
 public class CommonConverters {
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   public static GitPerson toGitPerson(PersonIdent ident) {
     GitPerson result = new GitPerson();
     result.name = ident.getName();
     result.email = ident.getEmailAddress();
-    result.setDate(ident.getWhen().toInstant());
+    result.setDate(ident.getWhenAsInstant());
     result.tz = ident.getTimeZoneOffset();
     return result;
   }
diff --git a/java/com/google/gerrit/server/IdentifiedUser.java b/java/com/google/gerrit/server/IdentifiedUser.java
index 122e18d..65a81f7 100644
--- a/java/com/google/gerrit/server/IdentifiedUser.java
+++ b/java/com/google/gerrit/server/IdentifiedUser.java
@@ -50,9 +50,9 @@
 import java.net.SocketAddress;
 import java.net.URL;
 import java.time.Instant;
+import java.time.ZoneId;
 import java.util.Optional;
 import java.util.Set;
-import java.util.TimeZone;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.util.SystemReader;
 
@@ -427,10 +427,10 @@
   }
 
   public PersonIdent newRefLogIdent() {
-    return newRefLogIdent(Instant.now(), TimeZone.getDefault());
+    return newRefLogIdent(Instant.now(), ZoneId.systemDefault());
   }
 
-  public PersonIdent newRefLogIdent(Instant when, TimeZone tz) {
+  public PersonIdent newRefLogIdent(Instant when, ZoneId zoneId) {
     final Account ua = getAccount();
 
     String name = ua.fullName();
@@ -451,21 +451,18 @@
               : ua.preferredEmail();
     }
 
-    return newPersonIdent(name, user, when, tz);
+    return new PersonIdent(name, user, when, zoneId);
   }
 
   private String constructMailAddress(Account ua, String host) {
     return getUserName().orElse("") + "|account-" + ua.id().toString() + "@" + host;
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   public PersonIdent newCommitterIdent(PersonIdent ident) {
-    return newCommitterIdent(ident.getWhen().toInstant(), ident.getTimeZone());
+    return newCommitterIdent(ident.getWhenAsInstant(), ident.getZoneId());
   }
 
-  public PersonIdent newCommitterIdent(Instant when, TimeZone tz) {
+  public PersonIdent newCommitterIdent(Instant when, ZoneId zoneId) {
     final Account ua = getAccount();
     String name = ua.fullName();
     String email = ua.preferredEmail();
@@ -500,7 +497,7 @@
       }
     }
 
-    return newPersonIdent(name, email, when, tz);
+    return new PersonIdent(name, email, when, zoneId);
   }
 
   @Override
@@ -568,19 +565,4 @@
     }
     return host;
   }
-
-  /**
-   * Create a {@link PersonIdent} from an {@code Instant} and a {@link TimeZone}.
-   *
-   * <p>We use the {@link PersonIdent#PersonIdent(String, String, long, int)} constructor to avoid
-   * doing a conversion to {@code java.util.Date} here. For the {@code int aTZ} argument, which is
-   * the time zone, we do the same computation as in {@link PersonIdent#PersonIdent(String, String,
-   * java.util.Date, TimeZone)} (just instead of getting the epoch millis from {@code
-   * java.util.Date} we get them from {@link Instant}).
-   */
-  // TODO(issue-15517): Drop this method once JGit's PersonIdent class supports Instants
-  private static PersonIdent newPersonIdent(String name, String email, Instant when, TimeZone tz) {
-    return new PersonIdent(
-        name, email, when.toEpochMilli(), tz.getOffset(when.toEpochMilli()) / (60 * 1000));
-  }
 }
diff --git a/java/com/google/gerrit/server/account/AccountConfig.java b/java/com/google/gerrit/server/account/AccountConfig.java
index 28e881e..4143f77 100644
--- a/java/com/google/gerrit/server/account/AccountConfig.java
+++ b/java/com/google/gerrit/server/account/AccountConfig.java
@@ -36,7 +36,6 @@
 import java.io.IOException;
 import java.time.Instant;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -258,9 +257,6 @@
     return c;
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Override
   protected boolean onSave(CommitBuilder commit) throws IOException, ConfigInvalidException {
     checkLoaded();
@@ -279,8 +275,8 @@
       }
 
       Instant registeredOn = loadedAccountProperties.get().getRegisteredOn();
-      commit.setAuthor(new PersonIdent(commit.getAuthor(), Date.from(registeredOn)));
-      commit.setCommitter(new PersonIdent(commit.getCommitter(), Date.from(registeredOn)));
+      commit.setAuthor(new PersonIdent(commit.getAuthor(), registeredOn));
+      commit.setCommitter(new PersonIdent(commit.getCommitter(), registeredOn));
     }
 
     saveAccount();
diff --git a/java/com/google/gerrit/server/account/AccountsUpdate.java b/java/com/google/gerrit/server/account/AccountsUpdate.java
index 3ee6365..137fd59 100644
--- a/java/com/google/gerrit/server/account/AccountsUpdate.java
+++ b/java/com/google/gerrit/server/account/AccountsUpdate.java
@@ -319,17 +319,13 @@
    * @throws IOException if creating the user branch fails due to an IO error
    * @throws ConfigInvalidException if any of the account fields has an invalid value
    */
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   public AccountState insert(String message, Account.Id accountId, ConfigureDeltaFromState init)
       throws IOException, ConfigInvalidException {
     return execute(
             ImmutableList.of(
                 repo -> {
                   AccountConfig accountConfig = read(repo, accountId);
-                  Account account =
-                      accountConfig.getNewAccount(committerIdent.getWhen().toInstant());
+                  Account account = accountConfig.getNewAccount(committerIdent.getWhenAsInstant());
                   AccountState accountState = AccountState.forAccount(account);
                   AccountDelta.Builder deltaBuilder = AccountDelta.builder();
                   init.configure(accountState, deltaBuilder);
diff --git a/java/com/google/gerrit/server/account/Emails.java b/java/com/google/gerrit/server/account/Emails.java
index 45f0844..8c3f033 100644
--- a/java/com/google/gerrit/server/account/Emails.java
+++ b/java/com/google/gerrit/server/account/Emails.java
@@ -113,14 +113,11 @@
     return externalIds.byEmail(email).stream().map(ExternalId::accountId).collect(toImmutableSet());
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   public UserIdentity toUserIdentity(PersonIdent who) throws IOException {
     UserIdentity u = new UserIdentity();
     u.setName(who.getName());
     u.setEmail(who.getEmailAddress());
-    u.setDate(who.getWhen().toInstant());
+    u.setDate(who.getWhenAsInstant());
     u.setTimeZone(who.getTimeZoneOffset());
 
     // If only one account has access to this email address, select it
diff --git a/java/com/google/gerrit/server/edit/ChangeEditModifier.java b/java/com/google/gerrit/server/edit/ChangeEditModifier.java
index 232aa6a..2957d6b 100644
--- a/java/com/google/gerrit/server/edit/ChangeEditModifier.java
+++ b/java/com/google/gerrit/server/edit/ChangeEditModifier.java
@@ -53,10 +53,10 @@
 import com.google.inject.Singleton;
 import java.io.IOException;
 import java.time.Instant;
+import java.time.ZoneId;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.TimeZone;
 import org.eclipse.jgit.diff.DiffAlgorithm;
 import org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm;
 import org.eclipse.jgit.diff.RawText;
@@ -91,7 +91,7 @@
 @Singleton
 public class ChangeEditModifier {
 
-  private final TimeZone tz;
+  private final ZoneId zoneId;
   private final Provider<CurrentUser> currentUser;
   private final PermissionBackend permissionBackend;
   private final ChangeEditUtil changeEditUtil;
@@ -110,12 +110,12 @@
       ProjectCache projectCache) {
     this.currentUser = currentUser;
     this.permissionBackend = permissionBackend;
-    this.tz = gerritIdent.getTimeZone();
+    this.zoneId = gerritIdent.getZoneId();
     this.changeEditUtil = changeEditUtil;
     this.patchSetUtil = patchSetUtil;
     this.projectCache = projectCache;
 
-    noteDbEdits = new NoteDbEdits(tz, indexer, currentUser);
+    noteDbEdits = new NoteDbEdits(zoneId, indexer, currentUser);
   }
 
   /**
@@ -519,7 +519,7 @@
 
   private PersonIdent getCommitterIdent(Instant commitTimestamp) {
     IdentifiedUser user = currentUser.get().asIdentifiedUser();
-    return user.newCommitterIdent(commitTimestamp, tz);
+    return user.newCommitterIdent(commitTimestamp, zoneId);
   }
 
   /**
@@ -709,12 +709,12 @@
   }
 
   private static class NoteDbEdits {
-    private final TimeZone tz;
+    private final ZoneId zoneId;
     private final ChangeIndexer indexer;
     private final Provider<CurrentUser> currentUser;
 
-    NoteDbEdits(TimeZone tz, ChangeIndexer indexer, Provider<CurrentUser> currentUser) {
-      this.tz = tz;
+    NoteDbEdits(ZoneId zoneId, ChangeIndexer indexer, Provider<CurrentUser> currentUser) {
+      this.zoneId = zoneId;
       this.indexer = indexer;
       this.currentUser = currentUser;
     }
@@ -841,7 +841,7 @@
 
     private PersonIdent getRefLogIdent(Instant timestamp) {
       IdentifiedUser user = currentUser.get().asIdentifiedUser();
-      return user.newRefLogIdent(timestamp, tz);
+      return user.newRefLogIdent(timestamp, zoneId);
     }
 
     private void reindex(Change change) {
diff --git a/java/com/google/gerrit/server/git/BanCommit.java b/java/com/google/gerrit/server/git/BanCommit.java
index 9cc754c..e27197c 100644
--- a/java/com/google/gerrit/server/git/BanCommit.java
+++ b/java/com/google/gerrit/server/git/BanCommit.java
@@ -31,8 +31,8 @@
 import com.google.inject.Singleton;
 import java.io.IOException;
 import java.time.Instant;
+import java.time.ZoneId;
 import java.util.List;
-import java.util.TimeZone;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.lib.Constants;
@@ -78,7 +78,7 @@
 
   private final Provider<IdentifiedUser> currentUser;
   private final GitRepositoryManager repoManager;
-  private final TimeZone tz;
+  private final ZoneId zoneId;
   private final PermissionBackend permissionBackend;
   private final NotesBranchUtil.Factory notesBranchUtilFactory;
 
@@ -93,7 +93,7 @@
     this.repoManager = repoManager;
     this.notesBranchUtilFactory = notesBranchUtilFactory;
     this.permissionBackend = permissionBackend;
-    this.tz = gerritIdent.getTimeZone();
+    this.zoneId = gerritIdent.getZoneId();
   }
 
   /**
@@ -155,7 +155,7 @@
   }
 
   private PersonIdent createPersonIdent() {
-    return currentUser.get().newCommitterIdent(Instant.now(), tz);
+    return currentUser.get().newCommitterIdent(Instant.now(), zoneId);
   }
 
   private static String buildCommitMessage(List<ObjectId> bannedCommits, String reason) {
diff --git a/java/com/google/gerrit/server/git/CommitUtil.java b/java/com/google/gerrit/server/git/CommitUtil.java
index b04fbf8..fa46bf4 100644
--- a/java/com/google/gerrit/server/git/CommitUtil.java
+++ b/java/com/google/gerrit/server/git/CommitUtil.java
@@ -222,7 +222,7 @@
 
     PersonIdent committerIdent = serverIdent.get();
     PersonIdent authorIdent =
-        user.asIdentifiedUser().newCommitterIdent(ts, committerIdent.getTimeZone());
+        user.asIdentifiedUser().newCommitterIdent(ts, committerIdent.getZoneId());
 
     RevCommit parentToCommitToRevert = commitToRevert.getParent(0);
     revWalk.parseHeaders(parentToCommitToRevert);
diff --git a/java/com/google/gerrit/server/group/db/AuditLogReader.java b/java/com/google/gerrit/server/group/db/AuditLogReader.java
index 3f7ef2c..4c1f69b 100644
--- a/java/com/google/gerrit/server/group/db/AuditLogReader.java
+++ b/java/com/google/gerrit/server/group/db/AuditLogReader.java
@@ -139,9 +139,6 @@
     return result.stream().map(AccountGroupByIdAudit.Builder::build).collect(toImmutableList());
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private Optional<ParsedCommit> parse(AccountGroup.UUID uuid, RevCommit c) {
     Optional<Account.Id> authorId = NoteDbUtil.parseIdent(c.getAuthorIdent());
     if (!authorId.isPresent()) {
@@ -169,7 +166,7 @@
     return Optional.of(
         new AutoValue_AuditLogReader_ParsedCommit(
             authorId.get(),
-            c.getAuthorIdent().getWhen().toInstant(),
+            c.getAuthorIdent().getWhenAsInstant(),
             ImmutableList.copyOf(addedMembers),
             ImmutableList.copyOf(removedMembers),
             ImmutableList.copyOf(addedSubgroups),
diff --git a/java/com/google/gerrit/server/group/db/GroupConfig.java b/java/com/google/gerrit/server/group/db/GroupConfig.java
index 71cc08c..4f2c049 100644
--- a/java/com/google/gerrit/server/group/db/GroupConfig.java
+++ b/java/com/google/gerrit/server/group/db/GroupConfig.java
@@ -37,7 +37,6 @@
 import java.io.IOException;
 import java.time.Instant;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.Optional;
 import java.util.function.Function;
 import java.util.regex.Pattern;
@@ -300,9 +299,6 @@
     return c;
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Override
   protected boolean onSave(CommitBuilder commit) throws IOException, ConfigInvalidException {
     checkLoaded();
@@ -321,8 +317,8 @@
     Instant commitTimestamp =
         TimeUtil.truncateToSecond(
             groupDelta.flatMap(GroupDelta::getUpdatedOn).orElseGet(TimeUtil::now));
-    commit.setAuthor(new PersonIdent(commit.getAuthor(), Date.from(commitTimestamp)));
-    commit.setCommitter(new PersonIdent(commit.getCommitter(), Date.from(commitTimestamp)));
+    commit.setAuthor(new PersonIdent(commit.getAuthor(), commitTimestamp));
+    commit.setCommitter(new PersonIdent(commit.getCommitter(), commitTimestamp));
 
     InternalGroup updatedGroup = updateGroup(commitTimestamp);
 
diff --git a/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java b/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java
index 7efda47..e6f1622 100644
--- a/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java
+++ b/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java
@@ -29,7 +29,6 @@
 import com.google.gerrit.server.InternalUser;
 import java.io.IOException;
 import java.time.Instant;
-import java.util.Date;
 import org.eclipse.jgit.lib.CommitBuilder;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
@@ -56,9 +55,6 @@
   private ObjectId result;
   boolean rootOnly;
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   AbstractChangeUpdate(
       ChangeNotes notes,
       CurrentUser user,
@@ -66,7 +62,7 @@
       ChangeNoteUtil noteUtil,
       Instant when) {
     this.noteUtil = noteUtil;
-    this.serverIdent = new PersonIdent(serverIdent, Date.from(when));
+    this.serverIdent = new PersonIdent(serverIdent, when);
     this.notes = notes;
     this.change = notes.getChange();
     this.accountId = accountId(user);
@@ -76,9 +72,6 @@
     this.when = when;
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   AbstractChangeUpdate(
       ChangeNoteUtil noteUtil,
       PersonIdent serverIdent,
@@ -92,7 +85,7 @@
         (notes != null && change == null) || (notes == null && change != null),
         "exactly one of notes or change required");
     this.noteUtil = noteUtil;
-    this.serverIdent = new PersonIdent(serverIdent, Date.from(when));
+    this.serverIdent = new PersonIdent(serverIdent, when);
     this.notes = notes;
     this.change = change != null ? change : notes.getChange();
     this.accountId = accountId;
@@ -213,9 +206,6 @@
    *     deleted.
    * @throws IOException if a lower-level error occurred.
    */
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   final ObjectId apply(RevWalk rw, ObjectInserter ins, ObjectId curr) throws IOException {
     if (isEmpty()) {
       return null;
@@ -236,7 +226,7 @@
       return null; // Impl is a no-op.
     }
     cb.setAuthor(authorIdent);
-    cb.setCommitter(new PersonIdent(serverIdent, Date.from(when)));
+    cb.setCommitter(new PersonIdent(serverIdent, when));
     setParentCommit(cb, curr);
     if (cb.getTreeId() == null) {
       if (curr.equals(z)) {
diff --git a/java/com/google/gerrit/server/notedb/ChangeNoteUtil.java b/java/com/google/gerrit/server/notedb/ChangeNoteUtil.java
index e9d2f4c..6f413f1 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNoteUtil.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNoteUtil.java
@@ -24,7 +24,6 @@
 import com.google.gson.Gson;
 import com.google.inject.Inject;
 import java.time.Instant;
-import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 import org.eclipse.jgit.errors.ConfigInvalidException;
@@ -100,16 +99,13 @@
    * Returns a {@link PersonIdent} that contains the account ID, but not the user's name or email
    * address.
    */
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   public PersonIdent newAccountIdIdent(
       Account.Id accountId, Instant when, PersonIdent serverIdent) {
     return new PersonIdent(
         getAccountIdAsUsername(accountId),
         getAccountIdAsEmailAddress(accountId),
-        Date.from(when),
-        serverIdent.getTimeZone());
+        when,
+        serverIdent.getZoneId());
   }
 
   /** Returns the string {@code "Gerrit User " + accountId}, to pseudonymize user names. */
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
index 1d8ec82..6700f25 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
@@ -1270,11 +1270,8 @@
    * @param commit the commit to return commit time.
    * @return the timestamp when the commit was applied.
    */
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private Instant getCommitTimestamp(ChangeNotesCommit commit) {
-    return commit.getCommitterIdent().getWhen().toInstant();
+    return commit.getCommitterIdent().getWhenAsInstant();
   }
 
   private void pruneReviewers() {
diff --git a/java/com/google/gerrit/server/notedb/CommitRewriter.java b/java/com/google/gerrit/server/notedb/CommitRewriter.java
index e7a8948..da20475 100644
--- a/java/com/google/gerrit/server/notedb/CommitRewriter.java
+++ b/java/com/google/gerrit/server/notedb/CommitRewriter.java
@@ -578,12 +578,9 @@
     }
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private boolean verifyPersonIdent(PersonIdent newIdent, PersonIdent originalIdent) {
     return newIdent.getTimeZoneOffset() == originalIdent.getTimeZoneOffset()
-        && newIdent.getWhen().getTime() == originalIdent.getWhen().getTime()
+        && newIdent.getWhenAsInstant().equals(originalIdent.getWhenAsInstant())
         && newIdent.getEmailAddress().equals(originalIdent.getEmailAddress());
   }
 
diff --git a/java/com/google/gerrit/server/restapi/change/CherryPickChange.java b/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
index 232cd77..00c48dc 100644
--- a/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
+++ b/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
@@ -70,11 +70,11 @@
 import com.google.inject.Singleton;
 import java.io.IOException;
 import java.time.Instant;
+import java.time.ZoneId;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.TimeZone;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.errors.InvalidObjectIdException;
 import org.eclipse.jgit.errors.MissingObjectException;
@@ -104,7 +104,7 @@
   private final Sequences seq;
   private final Provider<InternalChangeQuery> queryProvider;
   private final GitRepositoryManager gitManager;
-  private final TimeZone serverTimeZone;
+  private final ZoneId serverZoneId;
   private final Provider<IdentifiedUser> user;
   private final ChangeInserter.Factory changeInserterFactory;
   private final PatchSetInserter.Factory patchSetInserterFactory;
@@ -135,7 +135,7 @@
     this.seq = seq;
     this.queryProvider = queryProvider;
     this.gitManager = gitManager;
-    this.serverTimeZone = myIdent.getTimeZone();
+    this.serverZoneId = myIdent.getZoneId();
     this.user = user;
     this.changeInserterFactory = changeInserterFactory;
     this.patchSetInserterFactory = patchSetInserterFactory;
@@ -307,7 +307,7 @@
       CodeReviewCommit cherryPickCommit;
       ProjectState projectState =
           projectCache.get(dest.project()).orElseThrow(noSuchProject(dest.project()));
-      PersonIdent committerIdent = identifiedUser.newCommitterIdent(timestamp, serverTimeZone);
+      PersonIdent committerIdent = identifiedUser.newCommitterIdent(timestamp, serverZoneId);
 
       try {
         MergeUtil mergeUtil;
diff --git a/java/com/google/gerrit/server/restapi/change/CreateChange.java b/java/com/google/gerrit/server/restapi/change/CreateChange.java
index e668891..8c56967 100644
--- a/java/com/google/gerrit/server/restapi/change/CreateChange.java
+++ b/java/com/google/gerrit/server/restapi/change/CreateChange.java
@@ -86,11 +86,10 @@
 import com.google.inject.Singleton;
 import java.io.IOException;
 import java.time.Instant;
+import java.time.ZoneId;
 import java.util.Collections;
-import java.util.Date;
 import java.util.List;
 import java.util.Optional;
-import java.util.TimeZone;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.errors.InvalidObjectIdException;
 import org.eclipse.jgit.errors.MissingObjectException;
@@ -118,7 +117,7 @@
   private final String anonymousCowardName;
   private final GitRepositoryManager gitManager;
   private final Sequences seq;
-  private final TimeZone serverTimeZone;
+  private final ZoneId serverZoneId;
   private final PermissionBackend permissionBackend;
   private final Provider<CurrentUser> user;
   private final ProjectsCollection projectsCollection;
@@ -158,7 +157,7 @@
     this.anonymousCowardName = anonymousCowardName;
     this.gitManager = gitManager;
     this.seq = seq;
-    this.serverTimeZone = myIdent.getTimeZone();
+    this.serverZoneId = myIdent.getZoneId();
     this.permissionBackend = permissionBackend;
     this.user = user;
     this.projectsCollection = projectsCollection;
@@ -321,9 +320,6 @@
     }
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private ChangeInfo createNewChange(
       ChangeInput input,
       IdentifiedUser me,
@@ -360,12 +356,11 @@
 
       Instant now = TimeUtil.now();
 
-      PersonIdent committer = me.newCommitterIdent(now, serverTimeZone);
+      PersonIdent committer = me.newCommitterIdent(now, serverZoneId);
       PersonIdent author =
           input.author == null
               ? committer
-              : new PersonIdent(
-                  input.author.name, input.author.email, Date.from(now), serverTimeZone);
+              : new PersonIdent(input.author.name, input.author.email, now, serverZoneId);
 
       String commitMessage = getCommitMessage(input.subject, me);
 
diff --git a/java/com/google/gerrit/server/restapi/change/CreateMergePatchSet.java b/java/com/google/gerrit/server/restapi/change/CreateMergePatchSet.java
index 7259deb..4b66cdc 100644
--- a/java/com/google/gerrit/server/restapi/change/CreateMergePatchSet.java
+++ b/java/com/google/gerrit/server/restapi/change/CreateMergePatchSet.java
@@ -69,9 +69,8 @@
 import com.google.inject.Singleton;
 import java.io.IOException;
 import java.time.Instant;
-import java.util.Date;
+import java.time.ZoneId;
 import java.util.List;
-import java.util.TimeZone;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.ObjectReader;
@@ -86,7 +85,7 @@
   private final BatchUpdate.Factory updateFactory;
   private final GitRepositoryManager gitManager;
   private final CommitsCollection commits;
-  private final TimeZone serverTimeZone;
+  private final ZoneId serverZoneId;
   private final Provider<CurrentUser> user;
   private final ChangeJson.Factory jsonFactory;
   private final PatchSetUtil psUtil;
@@ -113,7 +112,7 @@
     this.updateFactory = updateFactory;
     this.gitManager = gitManager;
     this.commits = commits;
-    this.serverTimeZone = myIdent.getTimeZone();
+    this.serverZoneId = myIdent.getZoneId();
     this.user = user;
     this.jsonFactory = json;
     this.psUtil = psUtil;
@@ -124,9 +123,6 @@
     this.permissionBackend = permissionBackend;
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Override
   public Response<ChangeInfo> apply(ChangeResource rsrc, MergePatchSetInput in)
       throws IOException, RestApiException, UpdateException, PermissionBackendException {
@@ -185,8 +181,8 @@
       IdentifiedUser me = user.get().asIdentifiedUser();
       PersonIdent author =
           in.author == null
-              ? me.newCommitterIdent(now, serverTimeZone)
-              : new PersonIdent(in.author.name, in.author.email, Date.from(now), serverTimeZone);
+              ? me.newCommitterIdent(now, serverZoneId)
+              : new PersonIdent(in.author.name, in.author.email, now, serverZoneId);
       CodeReviewCommit newCommit =
           createMergeCommit(
               in,
diff --git a/java/com/google/gerrit/server/restapi/change/PutMessage.java b/java/com/google/gerrit/server/restapi/change/PutMessage.java
index c62200a..f898dca 100644
--- a/java/com/google/gerrit/server/restapi/change/PutMessage.java
+++ b/java/com/google/gerrit/server/restapi/change/PutMessage.java
@@ -48,7 +48,7 @@
 import com.google.inject.Singleton;
 import java.io.IOException;
 import java.time.Instant;
-import java.util.TimeZone;
+import java.time.ZoneId;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.CommitBuilder;
 import org.eclipse.jgit.lib.ObjectId;
@@ -64,7 +64,7 @@
   private final BatchUpdate.Factory updateFactory;
   private final GitRepositoryManager repositoryManager;
   private final Provider<CurrentUser> userProvider;
-  private final TimeZone tz;
+  private final ZoneId zoneId;
   private final PatchSetInserter.Factory psInserterFactory;
   private final PermissionBackend permissionBackend;
   private final PatchSetUtil psUtil;
@@ -86,7 +86,7 @@
     this.repositoryManager = repositoryManager;
     this.userProvider = userProvider;
     this.psInserterFactory = psInserterFactory;
-    this.tz = gerritIdent.getTimeZone();
+    this.zoneId = gerritIdent.getZoneId();
     this.permissionBackend = permissionBackend;
     this.psUtil = psUtil;
     this.notifyResolver = notifyResolver;
@@ -167,7 +167,8 @@
     builder.setTreeId(basePatchSetCommit.getTree());
     builder.setParentIds(basePatchSetCommit.getParents());
     builder.setAuthor(basePatchSetCommit.getAuthorIdent());
-    builder.setCommitter(userProvider.get().asIdentifiedUser().newCommitterIdent(timestamp, tz));
+    builder.setCommitter(
+        userProvider.get().asIdentifiedUser().newCommitterIdent(timestamp, zoneId));
     builder.setMessage(commitMessage);
     ObjectId newCommitId = objectInserter.insert(builder);
     objectInserter.flush();
diff --git a/java/com/google/gerrit/server/restapi/change/Revisions.java b/java/com/google/gerrit/server/restapi/change/Revisions.java
index 41fecaf..1d5064e 100644
--- a/java/com/google/gerrit/server/restapi/change/Revisions.java
+++ b/java/com/google/gerrit/server/restapi/change/Revisions.java
@@ -154,9 +154,6 @@
     return ImmutableList.of();
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private ImmutableList<RevisionResource> loadEdit(
       ChangeResource change, @Nullable ObjectId commitId) throws AuthException, IOException {
     Optional<ChangeEdit> edit = editUtil.byChange(change.getNotes(), change.getUser());
@@ -167,7 +164,7 @@
               .id(PatchSet.id(change.getId(), 0))
               .commitId(editCommit)
               .uploader(change.getUser().getAccountId())
-              .createdOn(editCommit.getCommitterIdent().getWhen().toInstant())
+              .createdOn(editCommit.getCommitterIdent().getWhenAsInstant())
               .build();
       if (commitId == null || editCommit.equals(commitId)) {
         return ImmutableList.of(new RevisionResource(change, ps, edit));
diff --git a/java/com/google/gerrit/server/restapi/group/CreateGroup.java b/java/com/google/gerrit/server/restapi/group/CreateGroup.java
index f257f86..e617931 100644
--- a/java/com/google/gerrit/server/restapi/group/CreateGroup.java
+++ b/java/com/google/gerrit/server/restapi/group/CreateGroup.java
@@ -61,13 +61,13 @@
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import java.io.IOException;
+import java.time.ZoneId;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 import java.util.Optional;
-import java.util.TimeZone;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.PersonIdent;
@@ -77,7 +77,7 @@
 public class CreateGroup
     implements RestCollectionCreateView<TopLevelResource, GroupResource, GroupInput> {
   private final Provider<IdentifiedUser> self;
-  private final TimeZone serverTimeZone;
+  private final ZoneId serverZoneId;
   private final Provider<GroupsUpdate> groupsUpdateProvider;
   private final GroupCache groupCache;
   private final GroupResolver groups;
@@ -102,7 +102,7 @@
       @GerritServerConfig Config cfg,
       Sequences sequences) {
     this.self = self;
-    this.serverTimeZone = serverIdent.get().getTimeZone();
+    this.serverZoneId = serverIdent.get().getZoneId();
     this.groupsUpdateProvider = groupsUpdateProvider;
     this.groupCache = groupCache;
     this.groups = groups;
@@ -212,7 +212,7 @@
             createGroupArgs.uuid,
             GroupUuid.make(
                 createGroupArgs.getGroupName(),
-                self.get().newCommitterIdent(TimeUtil.now(), serverTimeZone)));
+                self.get().newCommitterIdent(TimeUtil.now(), serverZoneId)));
     InternalGroupCreation groupCreation =
         InternalGroupCreation.builder()
             .setGroupUUID(uuid)
diff --git a/java/com/google/gerrit/server/restapi/project/CreateTag.java b/java/com/google/gerrit/server/restapi/project/CreateTag.java
index 6980006..c5013f7 100644
--- a/java/com/google/gerrit/server/restapi/project/CreateTag.java
+++ b/java/com/google/gerrit/server/restapi/project/CreateTag.java
@@ -44,7 +44,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import java.io.IOException;
-import java.util.TimeZone;
+import java.time.ZoneId;
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.TagCommand;
 import org.eclipse.jgit.api.errors.GitAPIException;
@@ -136,7 +136,7 @@
                   resource
                       .getUser()
                       .asIdentifiedUser()
-                      .newCommitterIdent(TimeUtil.now(), TimeZone.getDefault()));
+                      .newCommitterIdent(TimeUtil.now(), ZoneId.systemDefault()));
         }
 
         Ref result = tag.call();
diff --git a/java/com/google/gerrit/server/restapi/project/GetReflog.java b/java/com/google/gerrit/server/restapi/project/GetReflog.java
index e0131ee..967b3c5 100644
--- a/java/com/google/gerrit/server/restapi/project/GetReflog.java
+++ b/java/com/google/gerrit/server/restapi/project/GetReflog.java
@@ -89,9 +89,6 @@
     this.permissionBackend = permissionBackend;
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Override
   public Response<List<ReflogEntryInfo>> apply(BranchResource rsrc)
       throws RestApiException, IOException, PermissionBackendException {
@@ -118,7 +115,7 @@
       } else {
         entries = limit > 0 ? new ArrayList<>(limit) : new ArrayList<>();
         for (ReflogEntry e : r.getReverseEntries()) {
-          Instant timestamp = e.getWho().getWhen().toInstant();
+          Instant timestamp = e.getWho().getWhenAsInstant();
           if ((from == null || from.isBefore(timestamp)) && (to == null || to.isAfter(timestamp))) {
             entries.add(e);
           }
diff --git a/java/com/google/gerrit/server/restapi/project/ListTags.java b/java/com/google/gerrit/server/restapi/project/ListTags.java
index eccdcfc..ac0dff9 100644
--- a/java/com/google/gerrit/server/restapi/project/ListTags.java
+++ b/java/com/google/gerrit/server/restapi/project/ListTags.java
@@ -172,9 +172,6 @@
     throw new ResourceNotFoundException(id);
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   public static TagInfo createTagInfo(
       PermissionBackend.ForRef perm, Ref ref, RevWalk rw, ProjectState projectState, WebLinks links)
       throws IOException {
@@ -200,12 +197,12 @@
           tagger != null ? CommonConverters.toGitPerson(tagger) : null,
           canDelete,
           webLinks.isEmpty() ? null : webLinks,
-          tagger != null ? tagger.getWhen().toInstant() : null);
+          tagger != null ? tagger.getWhenAsInstant() : null);
     }
 
     Instant timestamp =
         object instanceof RevCommit
-            ? ((RevCommit) object).getCommitterIdent().getWhen().toInstant()
+            ? ((RevCommit) object).getCommitterIdent().getWhenAsInstant()
             : null;
 
     // Lightweight tag
diff --git a/java/com/google/gerrit/server/update/BatchUpdate.java b/java/com/google/gerrit/server/update/BatchUpdate.java
index b247552..3dfd9b4 100644
--- a/java/com/google/gerrit/server/update/BatchUpdate.java
+++ b/java/com/google/gerrit/server/update/BatchUpdate.java
@@ -69,6 +69,7 @@
 import com.google.inject.assistedinject.Assisted;
 import java.io.IOException;
 import java.time.Instant;
+import java.time.ZoneId;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -76,7 +77,6 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.TimeZone;
 import java.util.TreeMap;
 import java.util.function.Function;
 import org.eclipse.jgit.lib.BatchRefUpdate;
@@ -257,8 +257,8 @@
     }
 
     @Override
-    public TimeZone getTimeZone() {
-      return tz;
+    public ZoneId getZoneId() {
+      return zoneId;
     }
 
     @Override
@@ -383,7 +383,7 @@
   private final Project.NameKey project;
   private final CurrentUser user;
   private final Instant when;
-  private final TimeZone tz;
+  private final ZoneId zoneId;
 
   private final ListMultimap<Change.Id, BatchUpdateOp> ops =
       MultimapBuilder.linkedHashKeys().arrayListValues().build();
@@ -422,7 +422,7 @@
     this.project = project;
     this.user = user;
     this.when = when;
-    tz = serverIdent.getTimeZone();
+    zoneId = serverIdent.getZoneId();
   }
 
   @Override
@@ -666,7 +666,7 @@
                     repo, repoView.getRevWalk(), repoView.getInserter(), repoView.getCommands()),
             dryrun);
     if (user.isIdentifiedUser()) {
-      handle.manager.setRefLogIdent(user.asIdentifiedUser().newRefLogIdent(when, tz));
+      handle.manager.setRefLogIdent(user.asIdentifiedUser().newRefLogIdent(when, zoneId));
     }
     handle.manager.setRefLogMessage(refLogMessage);
     handle.manager.setPushCertificate(pushCert);
diff --git a/java/com/google/gerrit/server/update/Context.java b/java/com/google/gerrit/server/update/Context.java
index 57ebedd..aa41d90 100644
--- a/java/com/google/gerrit/server/update/Context.java
+++ b/java/com/google/gerrit/server/update/Context.java
@@ -25,7 +25,7 @@
 import com.google.gerrit.server.change.NotifyResolver;
 import java.io.IOException;
 import java.time.Instant;
-import java.util.TimeZone;
+import java.time.ZoneId;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.revwalk.RevWalk;
 
@@ -70,13 +70,13 @@
   Instant getWhen();
 
   /**
-   * Get the time zone in which this update takes place.
+   * Get the time zone ID in which this update takes place.
    *
-   * <p>In the current implementation, this is always the time zone of the server.
+   * <p>In the current implementation, this is always the time zone ID of the server.
    *
-   * @return time zone.
+   * @return zone ID.
    */
-  TimeZone getTimeZone();
+  ZoneId getZoneId();
 
   /**
    * Get the user performing the update.
@@ -162,6 +162,6 @@
    * @return the created committer {@link PersonIdent}
    */
   default PersonIdent newCommitterIdent(IdentifiedUser user) {
-    return user.newCommitterIdent(getWhen(), getTimeZone());
+    return user.newCommitterIdent(getWhen(), getZoneId());
   }
 }
diff --git a/java/com/google/gerrit/testing/TestChanges.java b/java/com/google/gerrit/testing/TestChanges.java
index 8bd02b8..4a97bc5 100644
--- a/java/com/google/gerrit/testing/TestChanges.java
+++ b/java/com/google/gerrit/testing/TestChanges.java
@@ -31,7 +31,7 @@
 import com.google.gerrit.server.notedb.ChangeUpdate;
 import com.google.gerrit.server.util.time.TimeUtil;
 import com.google.inject.Injector;
-import java.util.TimeZone;
+import java.time.ZoneId;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.ObjectId;
@@ -109,7 +109,7 @@
     try (Repository repo = repoManager.openRepository(c.getProject());
         TestRepository<Repository> tr = new TestRepository<>(repo)) {
       PersonIdent ident =
-          user.asIdentifiedUser().newCommitterIdent(update.getWhen(), TimeZone.getDefault());
+          user.asIdentifiedUser().newCommitterIdent(update.getWhen(), ZoneId.systemDefault());
       TestRepository<Repository>.CommitBuilder cb =
           tr.commit()
               .author(ident)
diff --git a/javatests/com/google/gerrit/acceptance/ProjectResetterTest.java b/javatests/com/google/gerrit/acceptance/ProjectResetterTest.java
index 877ccd5..b6e5b74 100644
--- a/javatests/com/google/gerrit/acceptance/ProjectResetterTest.java
+++ b/javatests/com/google/gerrit/acceptance/ProjectResetterTest.java
@@ -36,7 +36,6 @@
 import com.google.gerrit.testing.InMemoryRepositoryManager;
 import com.google.gerrit.testing.TestTimeUtil;
 import java.io.IOException;
-import java.util.Date;
 import java.util.concurrent.TimeUnit;
 import org.eclipse.jgit.lib.CommitBuilder;
 import org.eclipse.jgit.lib.Constants;
@@ -333,13 +332,10 @@
     assertThat(repo.exactRef(ref.getName())).isNull();
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private ObjectId createCommit(Repository repo) throws IOException {
     try (ObjectInserter oi = repo.newObjectInserter()) {
       PersonIdent ident =
-          new PersonIdent(new PersonIdent("Foo Bar", "foo.bar@baz.com"), Date.from(TimeUtil.now()));
+          new PersonIdent(new PersonIdent("Foo Bar", "foo.bar@baz.com"), TimeUtil.now());
       CommitBuilder cb = new CommitBuilder();
       cb.setTreeId(oi.insert(Constants.OBJ_TREE, new byte[] {}));
       cb.setCommitter(ident);
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 78a0eeb..9f47925 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -158,7 +158,6 @@
 import java.security.KeyPair;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -2466,9 +2465,6 @@
   }
 
   @Test
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   public void stalenessChecker() throws Exception {
     // Newly created account is not stale.
     AccountInfo accountInfo = gApi.accounts().create(name("foo")).get();
@@ -2482,7 +2478,7 @@
         RevWalk rw = new RevWalk(repo)) {
       RevCommit commit = rw.parseCommit(repo.exactRef(userRef).getObjectId());
 
-      PersonIdent ident = new PersonIdent(serverIdent.get(), Date.from(TimeUtil.now()));
+      PersonIdent ident = new PersonIdent(serverIdent.get(), TimeUtil.now());
       CommitBuilder cb = new CommitBuilder();
       cb.setTreeId(commit.getTree());
       cb.setCommitter(ident);
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
index 63b67f8..d630296 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -112,7 +112,6 @@
 import java.time.Instant;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Stream;
@@ -1608,9 +1607,6 @@
     return createCommit(repo, commitMessage, null);
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private ObjectId createCommit(Repository repo, String commitMessage, @Nullable ObjectId treeId)
       throws IOException {
     try (ObjectInserter oi = repo.newObjectInserter()) {
@@ -1618,7 +1614,7 @@
         treeId = oi.insert(Constants.OBJ_TREE, new byte[] {});
       }
 
-      PersonIdent ident = new PersonIdent(serverIdent.get(), Date.from(TimeUtil.now()));
+      PersonIdent ident = new PersonIdent(serverIdent.get(), TimeUtil.now());
       CommitBuilder cb = new CommitBuilder();
       cb.setTreeId(treeId);
       cb.setCommitter(ident);
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
index efd3cea..1919810 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
@@ -3005,9 +3005,6 @@
     return "An unchanged patchset\n\nChange-Id: " + changeId;
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private void assertDiffForNewFile(
       PushOneCommit.Result pushResult, String path, String expectedContentSideB) throws Exception {
     DiffInfo diff =
@@ -3030,14 +3027,14 @@
       DateTimeFormatter fmt =
           DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss Z")
               .withLocale(Locale.US)
-              .withZone(author.getTimeZone().toZoneId());
+              .withZone(author.getZoneId());
       headers.add("Author:     " + author.getName() + " <" + author.getEmailAddress() + ">");
-      headers.add("AuthorDate: " + fmt.format(author.getWhen().toInstant()));
+      headers.add("AuthorDate: " + fmt.format(author.getWhenAsInstant()));
 
       PersonIdent committer = c.getCommitterIdent();
-      fmt = fmt.withZone(committer.getTimeZone().toZoneId());
+      fmt = fmt.withZone(committer.getZoneId());
       headers.add("Commit:     " + committer.getName() + " <" + committer.getEmailAddress() + ">");
-      headers.add("CommitDate: " + fmt.format(committer.getWhen().toInstant()));
+      headers.add("CommitDate: " + fmt.format(committer.getWhenAsInstant()));
       headers.add("");
     }
 
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
index 4a7849f..2c80333 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
@@ -1706,15 +1706,13 @@
     }
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
   // TODO(issue-15508): Migrate timestamp fields in *Info/*Input classes from type Timestamp to
   // Instant
   @SuppressWarnings("JdkObsolete")
   private void assertPersonIdent(GitPerson gitPerson, PersonIdent expectedIdent) {
     assertThat(gitPerson.name).isEqualTo(expectedIdent.getName());
     assertThat(gitPerson.email).isEqualTo(expectedIdent.getEmailAddress());
-    assertThat(gitPerson.date.getTime()).isEqualTo(expectedIdent.getWhen().getTime());
+    assertThat(gitPerson.date.getTime()).isEqualTo(expectedIdent.getWhenAsInstant().toEpochMilli());
     assertThat(gitPerson.tz).isEqualTo(expectedIdent.getTimeZoneOffset());
   }
 
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
index 8eada79..0e4f212 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -1361,14 +1361,11 @@
     assertThat(actual.getTimeZone()).isEqualTo(expected.getTimeZone());
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   protected void assertAuthorAndCommitDateEquals(RevCommit commit) {
-    assertThat(commit.getAuthorIdent().getWhen().getTime())
-        .isEqualTo(commit.getCommitterIdent().getWhen().getTime());
-    assertThat(commit.getAuthorIdent().getTimeZone())
-        .isEqualTo(commit.getCommitterIdent().getTimeZone());
+    assertThat(commit.getAuthorIdent().getWhenAsInstant())
+        .isEqualTo(commit.getCommitterIdent().getWhenAsInstant());
+    assertThat(commit.getAuthorIdent().getZoneId())
+        .isEqualTo(commit.getCommitterIdent().getZoneId());
   }
 
   protected void assertSubmitter(String changeId, int psId) throws Throwable {
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/TagsIT.java b/javatests/com/google/gerrit/acceptance/rest/project/TagsIT.java
index 044da19..c8c00a1 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/TagsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/TagsIT.java
@@ -457,11 +457,8 @@
     return gApi.projects().name(project.get()).tag(tagname);
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private Instant instant(PushOneCommit.Result r) {
-    return r.getCommit().getCommitterIdent().getWhen().toInstant();
+    return r.getCommit().getCommitterIdent().getWhenAsInstant();
   }
 
   private void assertBadRequest(ListRefsRequest<TagInfo> req) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java b/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
index 5b6da36..bcde618 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
@@ -825,14 +825,11 @@
     assertThat(ru.delete()).isEqualTo(RefUpdate.Result.FORCED);
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private void addNoteDbCommit(Change.Id id, String commitMessage) throws Exception {
     PersonIdent committer = serverIdent.get();
     PersonIdent author =
         noteUtil.newAccountIdIdent(
-            getAccount(admin.id()).id(), committer.getWhen().toInstant(), committer);
+            getAccount(admin.id()).id(), committer.getWhenAsInstant(), committer);
     serverSideTestRepo
         .branch(RefNames.changeMetaRef(id))
         .commit()
diff --git a/javatests/com/google/gerrit/server/git/DeleteZombieCommentsRefsTest.java b/javatests/com/google/gerrit/server/git/DeleteZombieCommentsRefsTest.java
index 29dbe58..5810df7 100644
--- a/javatests/com/google/gerrit/server/git/DeleteZombieCommentsRefsTest.java
+++ b/javatests/com/google/gerrit/server/git/DeleteZombieCommentsRefsTest.java
@@ -29,7 +29,6 @@
 import com.google.gerrit.testing.InMemoryRepositoryManager;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.List;
 import org.eclipse.jgit.lib.BatchRefUpdate;
 import org.eclipse.jgit.lib.CommitBuilder;
@@ -204,14 +203,11 @@
     return repo.exactRef(refName);
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private static ObjectId createCommit(Repository repo, ObjectId treeId, ObjectId parentCommit)
       throws IOException {
     try (ObjectInserter oi = repo.newObjectInserter()) {
       PersonIdent committer =
-          new PersonIdent(new PersonIdent("Foo Bar", "foo.bar@baz.com"), Date.from(TimeUtil.now()));
+          new PersonIdent(new PersonIdent("Foo Bar", "foo.bar@baz.com"), TimeUtil.now());
       CommitBuilder cb = new CommitBuilder();
       cb.setTreeId(treeId);
       cb.setCommitter(committer);
diff --git a/javatests/com/google/gerrit/server/git/meta/VersionedMetaDataTest.java b/javatests/com/google/gerrit/server/git/meta/VersionedMetaDataTest.java
index 6792703..91d5596 100644
--- a/javatests/com/google/gerrit/server/git/meta/VersionedMetaDataTest.java
+++ b/javatests/com/google/gerrit/server/git/meta/VersionedMetaDataTest.java
@@ -29,10 +29,9 @@
 import com.google.gerrit.server.util.time.TimeUtil;
 import com.google.gerrit.testing.TestTimeUtil;
 import java.io.IOException;
+import java.time.ZoneId;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.Optional;
-import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
@@ -56,7 +55,7 @@
   // instead coming up with a replacement interface for
   // VersionedMetaData/BatchMetaDataUpdate/MetaDataUpdate that is easier to use correctly.
 
-  private static final TimeZone TZ = TimeZone.getTimeZone("America/Los_Angeles");
+  private static final ZoneId ZONE_ID = ZoneId.of("America/Los_Angeles");
   private static final String DEFAULT_REF = "refs/meta/config";
 
   private Project.NameKey project;
@@ -221,13 +220,10 @@
     return u;
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private CommitBuilder newCommitBuilder() {
     CommitBuilder cb = new CommitBuilder();
     PersonIdent author =
-        new PersonIdent("J. Author", "author@example.com", Date.from(TimeUtil.now()), TZ);
+        new PersonIdent("J. Author", "author@example.com", TimeUtil.now(), ZONE_ID);
     cb.setAuthor(author);
     cb.setCommitter(
         new PersonIdent(
diff --git a/javatests/com/google/gerrit/server/group/db/AbstractGroupTest.java b/javatests/com/google/gerrit/server/group/db/AbstractGroupTest.java
index 54407ca..11f3528 100644
--- a/javatests/com/google/gerrit/server/group/db/AbstractGroupTest.java
+++ b/javatests/com/google/gerrit/server/group/db/AbstractGroupTest.java
@@ -31,9 +31,8 @@
 import com.google.gerrit.testing.InMemoryRepositoryManager;
 import java.io.IOException;
 import java.time.Instant;
-import java.util.Date;
+import java.time.ZoneId;
 import java.util.Optional;
-import java.util.TimeZone;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Ref;
@@ -45,7 +44,7 @@
 
 @Ignore
 public class AbstractGroupTest {
-  protected static final TimeZone TZ = TimeZone.getTimeZone("America/Los_Angeles");
+  protected static final ZoneId ZONE_ID = ZoneId.of("America/Los_Angeles");
   protected static final String SERVER_ID = "server-id";
   protected static final String SERVER_NAME = "Gerrit Server";
   protected static final String SERVER_EMAIL = "noreply@gerritcodereview.com";
@@ -60,16 +59,13 @@
   protected Account.Id userId;
   protected PersonIdent userIdent;
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Before
   public void abstractGroupTestSetUp() throws Exception {
     allUsersName = new AllUsersName(AllUsersNameProvider.DEFAULT);
     repoManager = new InMemoryRepositoryManager();
     allUsersRepo = repoManager.createRepository(allUsersName);
     serverAccountId = Account.id(SERVER_ACCOUNT_NUMBER);
-    serverIdent = new PersonIdent(SERVER_NAME, SERVER_EMAIL, Date.from(TimeUtil.now()), TZ);
+    serverIdent = new PersonIdent(SERVER_NAME, SERVER_EMAIL, TimeUtil.now(), ZONE_ID);
     userId = Account.id(USER_ACCOUNT_NUMBER);
     userIdent = newPersonIdent(userId, serverIdent);
   }
@@ -79,15 +75,12 @@
     allUsersRepo.close();
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   protected Instant getTipTimestamp(AccountGroup.UUID uuid) throws Exception {
     try (RevWalk rw = new RevWalk(allUsersRepo)) {
       Ref ref = allUsersRepo.exactRef(RefNames.refsGroups(uuid));
       return ref == null
           ? null
-          : rw.parseCommit(ref.getObjectId()).getAuthorIdent().getWhen().toInstant();
+          : rw.parseCommit(ref.getObjectId()).getAuthorIdent().getWhenAsInstant();
     }
   }
 
@@ -116,11 +109,8 @@
     return md;
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   protected static PersonIdent newPersonIdent() {
-    return new PersonIdent(SERVER_NAME, SERVER_EMAIL, Date.from(TimeUtil.now()), TZ);
+    return new PersonIdent(SERVER_NAME, SERVER_EMAIL, TimeUtil.now(), ZONE_ID);
   }
 
   protected static PersonIdent newPersonIdent(Account.Id id, PersonIdent ident) {
diff --git a/javatests/com/google/gerrit/server/group/db/GroupConfigTest.java b/javatests/com/google/gerrit/server/group/db/GroupConfigTest.java
index a8f9ff5..8c19732 100644
--- a/javatests/com/google/gerrit/server/group/db/GroupConfigTest.java
+++ b/javatests/com/google/gerrit/server/group/db/GroupConfigTest.java
@@ -40,9 +40,7 @@
 import java.time.LocalDateTime;
 import java.time.Month;
 import java.time.ZoneId;
-import java.util.Date;
 import java.util.Optional;
-import java.util.TimeZone;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
@@ -64,7 +62,7 @@
   private final AccountGroup.Id groupId = AccountGroup.id(123);
   private final AuditLogFormatter auditLogFormatter =
       AuditLogFormatter.createBackedBy(ImmutableSet.of(), ImmutableSet.of(), "server-id");
-  private final TimeZone timeZone = TimeZone.getTimeZone("America/Los_Angeles");
+  private final ZoneId zoneId = ZoneId.of("America/Los_Angeles");
 
   @Before
   public void setUp() throws Exception {
@@ -1044,9 +1042,6 @@
     assertThat(revCommit.getCommitTime()).isEqualTo(createdOnAsSecondsSinceEpoch);
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void timestampOfCommitterMatchesSpecifiedCreatedOnOfNewGroup() throws Exception {
     Instant committerTimestamp =
@@ -1068,23 +1063,18 @@
     groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
 
     PersonIdent committerIdent =
-        new PersonIdent(
-            "Jane", "Jane@gerritcodereview.com", Date.from(committerTimestamp), timeZone);
+        new PersonIdent("Jane", "Jane@gerritcodereview.com", committerTimestamp, zoneId);
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
       metaDataUpdate.getCommitBuilder().setCommitter(committerIdent);
       groupConfig.commit(metaDataUpdate);
     }
 
     RevCommit revCommit = getLatestCommitForGroup(groupUuid);
-    assertThat(revCommit.getCommitterIdent().getWhen().getTime())
-        .isEqualTo(createdOn.toEpochMilli());
-    assertThat(revCommit.getCommitterIdent().getTimeZone().getRawOffset())
-        .isEqualTo(timeZone.getRawOffset());
+    assertThat(revCommit.getCommitterIdent().getWhenAsInstant()).isEqualTo(createdOn);
+    assertThat(revCommit.getCommitterIdent().getZoneId().getRules().getOffset(createdOn))
+        .isEqualTo(zoneId.getRules().getOffset(createdOn));
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void timestampOfAuthorMatchesSpecifiedCreatedOnOfNewGroup() throws Exception {
     Instant authorTimestamp = toInstant(LocalDate.of(2017, Month.DECEMBER, 13).atTime(15, 5, 27));
@@ -1105,16 +1095,16 @@
     groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
 
     PersonIdent authorIdent =
-        new PersonIdent("Jane", "Jane@gerritcodereview.com", Date.from(authorTimestamp), timeZone);
+        new PersonIdent("Jane", "Jane@gerritcodereview.com", authorTimestamp, zoneId);
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
       metaDataUpdate.getCommitBuilder().setAuthor(authorIdent);
       groupConfig.commit(metaDataUpdate);
     }
 
     RevCommit revCommit = getLatestCommitForGroup(groupUuid);
-    assertThat(revCommit.getAuthorIdent().getWhen().getTime()).isEqualTo(createdOn.toEpochMilli());
-    assertThat(revCommit.getAuthorIdent().getTimeZone().getRawOffset())
-        .isEqualTo(timeZone.getRawOffset());
+    assertThat(revCommit.getAuthorIdent().getWhenAsInstant()).isEqualTo(createdOn);
+    assertThat(revCommit.getAuthorIdent().getZoneId().getRules().getOffset(createdOn))
+        .isEqualTo(zoneId.getRules().getOffset(createdOn));
   }
 
   @Test
@@ -1149,9 +1139,6 @@
   }
 
   @Test
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   public void timestampOfCommitterMatchesSpecifiedUpdatedOnOfUpdatedGroup() throws Exception {
     Instant committerTimestamp =
         toInstant(LocalDate.of(2017, Month.DECEMBER, 13).atTime(15, 5, 27));
@@ -1167,24 +1154,19 @@
     groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
 
     PersonIdent committerIdent =
-        new PersonIdent(
-            "Jane", "Jane@gerritcodereview.com", Date.from(committerTimestamp), timeZone);
+        new PersonIdent("Jane", "Jane@gerritcodereview.com", committerTimestamp, zoneId);
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
       metaDataUpdate.getCommitBuilder().setCommitter(committerIdent);
       groupConfig.commit(metaDataUpdate);
     }
 
     RevCommit revCommit = getLatestCommitForGroup(groupUuid);
-    assertThat(revCommit.getCommitterIdent().getWhen().getTime())
-        .isEqualTo(updatedOn.toEpochMilli());
-    assertThat(revCommit.getCommitterIdent().getTimeZone().getRawOffset())
-        .isEqualTo(timeZone.getRawOffset());
+    assertThat(revCommit.getCommitterIdent().getWhenAsInstant()).isEqualTo(updatedOn);
+    assertThat(revCommit.getCommitterIdent().getZoneId().getRules().getOffset(updatedOn))
+        .isEqualTo(zoneId.getRules().getOffset(updatedOn));
   }
 
   @Test
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   public void timestampOfAuthorMatchesSpecifiedUpdatedOnOfUpdatedGroup() throws Exception {
     Instant authorTimestamp = toInstant(LocalDate.of(2017, Month.DECEMBER, 13).atTime(15, 5, 27));
     Instant updatedOn = toInstant(LocalDate.of(2016, Month.MARCH, 11).atTime(23, 49, 11));
@@ -1199,16 +1181,16 @@
     groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
 
     PersonIdent authorIdent =
-        new PersonIdent("Jane", "Jane@gerritcodereview.com", Date.from(authorTimestamp), timeZone);
+        new PersonIdent("Jane", "Jane@gerritcodereview.com", authorTimestamp, zoneId);
     try (MetaDataUpdate metaDataUpdate = createMetaDataUpdate()) {
       metaDataUpdate.getCommitBuilder().setAuthor(authorIdent);
       groupConfig.commit(metaDataUpdate);
     }
 
     RevCommit revCommit = getLatestCommitForGroup(groupUuid);
-    assertThat(revCommit.getAuthorIdent().getWhen().getTime()).isEqualTo(updatedOn.toEpochMilli());
-    assertThat(revCommit.getAuthorIdent().getTimeZone().getRawOffset())
-        .isEqualTo(timeZone.getRawOffset());
+    assertThat(revCommit.getAuthorIdent().getWhenAsInstant()).isEqualTo(updatedOn);
+    assertThat(revCommit.getAuthorIdent().getZoneId().getRules().getOffset(updatedOn))
+        .isEqualTo(zoneId.getRules().getOffset(updatedOn));
   }
 
   @Test
@@ -1557,13 +1539,9 @@
     }
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private MetaDataUpdate createMetaDataUpdate() {
     PersonIdent serverIdent =
-        new PersonIdent(
-            "Gerrit Server", "noreply@gerritcodereview.com", Date.from(TimeUtil.now()), timeZone);
+        new PersonIdent("Gerrit Server", "noreply@gerritcodereview.com", TimeUtil.now(), zoneId);
 
     MetaDataUpdate metaDataUpdate =
         new MetaDataUpdate(
diff --git a/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java b/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java
index afc56ff..9d8f260 100644
--- a/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java
+++ b/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java
@@ -44,11 +44,10 @@
 import com.google.gerrit.truth.ListSubject;
 import com.google.gerrit.truth.OptionalSubject;
 import java.io.IOException;
+import java.time.ZoneId;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.List;
 import java.util.Optional;
-import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.eclipse.jgit.errors.ConfigInvalidException;
@@ -72,7 +71,7 @@
 public class GroupNameNotesTest {
   private static final String SERVER_NAME = "Gerrit Server";
   private static final String SERVER_EMAIL = "noreply@gerritcodereview.com";
-  private static final TimeZone TZ = TimeZone.getTimeZone("America/Los_Angeles");
+  private static final ZoneId ZONE_ID = ZoneId.of("America/Los_Angeles");
 
   private final AccountGroup.UUID groupUuid = AccountGroup.uuid("users-XYZ");
   private final AccountGroup.NameKey groupName = AccountGroup.nameKey("users");
@@ -558,11 +557,8 @@
     return GroupReference.create(AccountGroup.uuid(name + "-" + id), name);
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private static PersonIdent newPersonIdent() {
-    return new PersonIdent(SERVER_NAME, SERVER_EMAIL, Date.from(TimeUtil.now()), TZ);
+    return new PersonIdent(SERVER_NAME, SERVER_EMAIL, TimeUtil.now(), ZONE_ID);
   }
 
   private static ObjectId getNoteKey(GroupReference g) {
diff --git a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
index 222be83..d7c779e 100644
--- a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
@@ -68,8 +68,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 import java.time.Instant;
-import java.util.Date;
-import java.util.TimeZone;
+import java.time.ZoneId;
 import java.util.concurrent.ExecutorService;
 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
 import org.eclipse.jgit.junit.TestRepository;
@@ -85,7 +84,7 @@
 @Ignore
 @RunWith(ConfigSuite.class)
 public abstract class AbstractChangeNotesTest {
-  private static final TimeZone TZ = TimeZone.getTimeZone("America/Los_Angeles");
+  private static final ZoneId ZONE_ID = ZoneId.of("America/Los_Angeles");
 
   @ConfigSuite.Parameter public Config testConfig;
 
@@ -115,15 +114,11 @@
   protected Injector injector;
   private String systemTimeZone;
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Before
   public void setUpTestEnvironment() throws Exception {
     setTimeForTesting();
 
-    serverIdent =
-        new PersonIdent("Gerrit Server", "noreply@gerrit.com", Date.from(TimeUtil.now()), TZ);
+    serverIdent = new PersonIdent("Gerrit Server", "noreply@gerrit.com", TimeUtil.now(), ZONE_ID);
     project = Project.nameKey("test-project");
     repoManager = new InMemoryRepositoryManager();
     repo = repoManager.createRepository(project);
diff --git a/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java b/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
index 5e2e1f2..9d02067 100644
--- a/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
+++ b/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
@@ -27,7 +27,7 @@
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.util.time.TimeUtil;
 import com.google.gerrit.testing.TestChanges;
-import java.util.TimeZone;
+import java.time.ZoneId;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.revwalk.RevCommit;
@@ -35,9 +35,6 @@
 import org.junit.Test;
 
 public class CommitMessageOutputTest extends AbstractChangeNotesTest {
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void approvalsCommitFormatSimple() throws Exception {
     Change c = TestChanges.newChange(project, changeOwner.getAccountId(), 1);
@@ -70,14 +67,15 @@
     PersonIdent author = commit.getAuthorIdent();
     assertThat(author.getName()).isEqualTo("Gerrit User 1");
     assertThat(author.getEmailAddress()).isEqualTo("1@gerrit");
-    assertThat(author.getWhen().getTime()).isEqualTo(c.getCreatedOn().toEpochMilli() + 1000);
-    assertThat(author.getTimeZone()).isEqualTo(TimeZone.getTimeZone("GMT-7:00"));
+    assertThat(author.getWhenAsInstant().toEpochMilli())
+        .isEqualTo(c.getCreatedOn().toEpochMilli() + 1000);
+    assertThat(author.getZoneId()).isEqualTo(ZoneId.of("GMT-7"));
 
     PersonIdent committer = commit.getCommitterIdent();
     assertThat(committer.getName()).isEqualTo("Gerrit Server");
     assertThat(committer.getEmailAddress()).isEqualTo("noreply@gerrit.com");
-    assertThat(committer.getWhen().getTime()).isEqualTo(author.getWhen().getTime());
-    assertThat(committer.getTimeZone()).isEqualTo(author.getTimeZone());
+    assertThat(committer.getWhenAsInstant()).isEqualTo(author.getWhenAsInstant());
+    assertThat(committer.getZoneId()).isEqualTo(author.getZoneId());
   }
 
   @Test
@@ -145,9 +143,6 @@
   }
 
   @Test
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   public void submitCommitFormat() throws Exception {
     Change c = newChange();
     ChangeUpdate update = newUpdate(c, changeOwner);
@@ -189,14 +184,15 @@
     PersonIdent author = commit.getAuthorIdent();
     assertThat(author.getName()).isEqualTo("Gerrit User 1");
     assertThat(author.getEmailAddress()).isEqualTo("1@gerrit");
-    assertThat(author.getWhen().getTime()).isEqualTo(c.getCreatedOn().toEpochMilli() + 2000);
-    assertThat(author.getTimeZone()).isEqualTo(TimeZone.getTimeZone("GMT-7:00"));
+    assertThat(author.getWhenAsInstant().toEpochMilli())
+        .isEqualTo(c.getCreatedOn().toEpochMilli() + 2000);
+    assertThat(author.getZoneId()).isEqualTo(ZoneId.of("GMT-7"));
 
     PersonIdent committer = commit.getCommitterIdent();
     assertThat(committer.getName()).isEqualTo("Gerrit Server");
     assertThat(committer.getEmailAddress()).isEqualTo("noreply@gerrit.com");
-    assertThat(committer.getWhen().getTime()).isEqualTo(author.getWhen().getTime());
-    assertThat(committer.getTimeZone()).isEqualTo(author.getTimeZone());
+    assertThat(committer.getWhenAsInstant()).isEqualTo(author.getWhenAsInstant());
+    assertThat(committer.getZoneId()).isEqualTo(author.getZoneId());
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/server/notedb/CommitRewriterTest.java b/javatests/com/google/gerrit/server/notedb/CommitRewriterTest.java
index 051ea2d..5e6803e 100644
--- a/javatests/com/google/gerrit/server/notedb/CommitRewriterTest.java
+++ b/javatests/com/google/gerrit/server/notedb/CommitRewriterTest.java
@@ -49,7 +49,6 @@
 import com.google.inject.Inject;
 import java.time.Instant;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -321,9 +320,6 @@
     assertThat(secondRunResult.fixedRefDiff.keySet().size()).isEqualTo(expectedSecondRunResult);
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void fixAuthorIdent() throws Exception {
     Change c = newChange();
@@ -332,8 +328,8 @@
         new PersonIdent(
             changeOwner.getName(),
             changeNoteUtil.getAccountIdAsEmailAddress(changeOwner.getAccountId()),
-            Date.from(when),
-            serverIdent.getTimeZone());
+            when,
+            serverIdent.getZoneId());
     RevCommit invalidUpdateCommit =
         writeUpdate(
             RefNames.changeMetaRef(c.getId()),
@@ -374,8 +370,8 @@
     assertThat(fixedUpdateCommit.getAuthorIdent().getName())
         .isEqualTo("Gerrit User " + changeOwner.getAccountId());
     assertThat(originalAuthorIdent.getEmailAddress()).isEqualTo(fixedAuthorIdent.getEmailAddress());
-    assertThat(originalAuthorIdent.getWhen().getTime())
-        .isEqualTo(fixedAuthorIdent.getWhen().getTime());
+    assertThat(originalAuthorIdent.getWhenAsInstant())
+        .isEqualTo(fixedAuthorIdent.getWhenAsInstant());
     assertThat(originalAuthorIdent.getTimeZone()).isEqualTo(fixedAuthorIdent.getTimeZone());
     assertThat(invalidUpdateCommit.getFullMessage()).isEqualTo(fixedUpdateCommit.getFullMessage());
     assertThat(invalidUpdateCommit.getCommitterIdent())
@@ -453,9 +449,6 @@
     assertThat(secondRunResult.refsFailedToFix).isEmpty();
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void fixReviewerFooterIdent() throws Exception {
     Change c = newChange();
@@ -502,7 +495,7 @@
     BackfillResult result = rewriter.backfillProject(project, repo, options);
     assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
 
-    Instant updateTimestamp = serverIdent.getWhen().toInstant();
+    Instant updateTimestamp = serverIdent.getWhenAsInstant();
     ImmutableList<ReviewerStatusUpdate> expectedReviewerUpdates =
         ImmutableList.of(
             ReviewerStatusUpdate.create(
@@ -539,9 +532,6 @@
     assertThat(secondRunResult.refsFailedToFix).isEmpty();
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void fixReviewerMessage() throws Exception {
     Change c = newChange();
@@ -589,7 +579,7 @@
     BackfillResult result = rewriter.backfillProject(project, repo, options);
     assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
 
-    Instant updateTimestamp = serverIdent.getWhen().toInstant();
+    Instant updateTimestamp = serverIdent.getWhenAsInstant();
     ImmutableList<ReviewerStatusUpdate> expectedReviewerUpdates =
         ImmutableList.of(
             ReviewerStatusUpdate.create(
@@ -669,9 +659,6 @@
     assertThat(secondRunResult.refsFailedToFix).isEmpty();
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void fixLabelFooterIdent() throws Exception {
     Change c = newChange();
@@ -722,7 +709,7 @@
     BackfillResult result = rewriter.backfillProject(project, repo, options);
     assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
 
-    Instant updateTimestamp = serverIdent.getWhen().toInstant();
+    Instant updateTimestamp = serverIdent.getWhenAsInstant();
     ImmutableList<PatchSetApproval> expectedApprovals =
         ImmutableList.of(
             PatchSetApproval.builder()
@@ -806,9 +793,6 @@
     assertThat(secondRunResult.refsFailedToFix).isEmpty();
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void fixRemoveVoteChangeMessage() throws Exception {
     Change c = newChange();
@@ -862,7 +846,7 @@
     BackfillResult result = rewriter.backfillProject(project, repo, options);
     assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
 
-    Instant updateTimestamp = serverIdent.getWhen().toInstant();
+    Instant updateTimestamp = serverIdent.getWhenAsInstant();
     ImmutableList<PatchSetApproval> expectedApprovals =
         ImmutableList.of(
             PatchSetApproval.builder()
@@ -932,18 +916,12 @@
     assertThat(secondRunResult.refsFailedToFix).isEmpty();
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void fixRemoveVoteChangeMessageWithUnparsableAuthorIdent() throws Exception {
     Change c = newChange();
     PersonIdent invalidAuthorIdent =
         new PersonIdent(
-            changeOwner.getName(),
-            "server@" + serverId,
-            Date.from(TimeUtil.now()),
-            serverIdent.getTimeZone());
+            changeOwner.getName(), "server@" + serverId, TimeUtil.now(), serverIdent.getZoneId());
     writeUpdate(
         RefNames.changeMetaRef(c.getId()),
         getChangeUpdateBody(
@@ -1188,9 +1166,6 @@
     assertThat(secondRunResult.refsFailedToFix).isEmpty();
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void fixAttentionFooter() throws Exception {
     Change c = newChange();
@@ -1271,7 +1246,7 @@
     BackfillResult result = rewriter.backfillProject(project, repo, options);
     assertThat(result.fixedRefDiff.keySet()).containsExactly(RefNames.changeMetaRef(c.getId()));
     notesBeforeRewrite.getAttentionSetUpdates();
-    Instant updateTimestamp = serverIdent.getWhen().toInstant();
+    Instant updateTimestamp = serverIdent.getWhenAsInstant();
     ImmutableList<AttentionSetUpdate> attentionSetUpdatesBeforeRewrite =
         ImmutableList.of(
             AttentionSetUpdate.createFromRead(
@@ -1569,9 +1544,6 @@
     assertThat(secondRunResult.refsFailedToFix).isEmpty();
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void fixSubmitChangeMessageAndFooters() throws Exception {
     Change c = newChange();
@@ -1579,8 +1551,8 @@
         new PersonIdent(
             changeOwner.getName(),
             changeNoteUtil.getAccountIdAsEmailAddress(changeOwner.getAccountId()),
-            Date.from(TimeUtil.now()),
-            serverIdent.getTimeZone());
+            TimeUtil.now(),
+            serverIdent.getZoneId());
     String changeOwnerIdentToFix = getAccountIdentToFix(changeOwner.getAccount());
     writeUpdate(
         RefNames.changeMetaRef(c.getId()),
@@ -2281,9 +2253,6 @@
     assertThat(secondRunResult.refsFailedToFix).isEmpty();
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void singleRunFixesAll() throws Exception {
     Change c = newChange();
@@ -2293,8 +2262,8 @@
         new PersonIdent(
             changeOwner.getName(),
             changeNoteUtil.getAccountIdAsEmailAddress(changeOwner.getAccountId()),
-            Date.from(when),
-            serverIdent.getTimeZone());
+            when,
+            serverIdent.getZoneId());
 
     RevCommit invalidUpdateCommit =
         writeUpdate(
diff --git a/javatests/com/google/gerrit/server/patch/DiffOperationsTest.java b/javatests/com/google/gerrit/server/patch/DiffOperationsTest.java
index 788703c..1c28690 100644
--- a/javatests/com/google/gerrit/server/patch/DiffOperationsTest.java
+++ b/javatests/com/google/gerrit/server/patch/DiffOperationsTest.java
@@ -32,7 +32,6 @@
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 import java.io.IOException;
-import java.util.Date;
 import java.util.Map;
 import java.util.Optional;
 import org.eclipse.jgit.lib.CommitBuilder;
@@ -256,14 +255,11 @@
         : createCommitInRepo(repo, treeId, parentCommit);
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   private static ObjectId createCommitInRepo(Repository repo, ObjectId treeId, ObjectId... parents)
       throws IOException {
     try (ObjectInserter oi = repo.newObjectInserter()) {
       PersonIdent committer =
-          new PersonIdent(new PersonIdent("Foo Bar", "foo.bar@baz.com"), Date.from(TimeUtil.now()));
+          new PersonIdent(new PersonIdent("Foo Bar", "foo.bar@baz.com"), TimeUtil.now());
       CommitBuilder cb = new CommitBuilder();
       cb.setTreeId(treeId);
       cb.setCommitter(committer);
diff --git a/javatests/com/google/gerrit/server/patch/MagicFileTest.java b/javatests/com/google/gerrit/server/patch/MagicFileTest.java
index 21ea641..b0050b0 100644
--- a/javatests/com/google/gerrit/server/patch/MagicFileTest.java
+++ b/javatests/com/google/gerrit/server/patch/MagicFileTest.java
@@ -22,9 +22,8 @@
 import java.time.Instant;
 import java.time.LocalDateTime;
 import java.time.Month;
+import java.time.ZoneId;
 import java.time.ZoneOffset;
-import java.util.Date;
-import java.util.TimeZone;
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectReader;
@@ -95,9 +94,6 @@
     assertThat(magicFile.getStartLineOfModifiableContent()).isEqualTo(1);
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void commitMessageFileOfRootCommitContainsCorrectContent() throws Exception {
     try (Repository repository = repositoryManager.createRepository(Project.nameKey("repo1"));
@@ -107,20 +103,12 @@
       Instant authorTime =
           LocalDateTime.of(2020, Month.APRIL, 23, 19, 30, 27).atZone(ZoneOffset.UTC).toInstant();
       PersonIdent author =
-          new PersonIdent(
-              "Alfred",
-              "alfred@example.com",
-              Date.from(authorTime),
-              TimeZone.getTimeZone(ZoneOffset.UTC));
+          new PersonIdent("Alfred", "alfred@example.com", authorTime, ZoneId.of("UTC"));
 
       Instant committerTime =
           LocalDateTime.of(2021, Month.JANUARY, 6, 5, 12, 55).atZone(ZoneOffset.UTC).toInstant();
       PersonIdent committer =
-          new PersonIdent(
-              "Luise",
-              "luise@example.com",
-              Date.from(committerTime),
-              TimeZone.getTimeZone(ZoneOffset.UTC));
+          new PersonIdent("Luise", "luise@example.com", committerTime, ZoneId.of("UTC"));
 
       ObjectId commit =
           testRepo
@@ -149,9 +137,6 @@
     }
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void commitMessageFileOfNonMergeCommitContainsCorrectContent() throws Exception {
     try (Repository repository = repositoryManager.createRepository(Project.nameKey("repo1"));
@@ -161,20 +146,12 @@
       Instant authorTime =
           LocalDateTime.of(2020, Month.APRIL, 23, 19, 30, 27).atZone(ZoneOffset.UTC).toInstant();
       PersonIdent author =
-          new PersonIdent(
-              "Alfred",
-              "alfred@example.com",
-              Date.from(authorTime),
-              TimeZone.getTimeZone(ZoneOffset.UTC));
+          new PersonIdent("Alfred", "alfred@example.com", authorTime, ZoneId.of("UTC"));
 
       Instant committerTime =
           LocalDateTime.of(2021, Month.JANUARY, 6, 5, 12, 55).atZone(ZoneOffset.UTC).toInstant();
       PersonIdent committer =
-          new PersonIdent(
-              "Luise",
-              "luise@example.com",
-              Date.from(committerTime),
-              TimeZone.getTimeZone(ZoneOffset.UTC));
+          new PersonIdent("Luise", "luise@example.com", committerTime, ZoneId.of("UTC"));
 
       RevCommit parent =
           testRepo.commit().message("Parent subject\n\nParent further details.").create();
@@ -208,9 +185,6 @@
     }
   }
 
-  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
-  // Instants
-  @SuppressWarnings("JdkObsolete")
   @Test
   public void commitMessageFileOfMergeCommitContainsCorrectContent() throws Exception {
     try (Repository repository = repositoryManager.createRepository(Project.nameKey("repo1"));
@@ -220,20 +194,12 @@
       Instant authorTime =
           LocalDateTime.of(2020, Month.APRIL, 23, 19, 30, 27).atZone(ZoneOffset.UTC).toInstant();
       PersonIdent author =
-          new PersonIdent(
-              "Alfred",
-              "alfred@example.com",
-              Date.from(authorTime),
-              TimeZone.getTimeZone(ZoneOffset.UTC));
+          new PersonIdent("Alfred", "alfred@example.com", authorTime, ZoneId.of("UTC"));
 
       Instant committerTime =
           LocalDateTime.of(2021, Month.JANUARY, 6, 5, 12, 55).atZone(ZoneOffset.UTC).toInstant();
       PersonIdent committer =
-          new PersonIdent(
-              "Luise",
-              "luise@example.com",
-              Date.from(committerTime),
-              TimeZone.getTimeZone(ZoneOffset.UTC));
+          new PersonIdent("Luise", "luise@example.com", committerTime, ZoneId.of("UTC"));
 
       RevCommit parent1 = testRepo.commit().message("Parent 1\n\nExplanation 1.").create();
       RevCommit parent2 = testRepo.commit().message("Parent 2\n\nExplanation 2.").create();