diff --git a/services/core/java/com/android/server/notification/NotificationBitmapJobService.java b/services/core/java/com/android/server/notification/NotificationBitmapJobService.java
index 4335a1dcfa75701c59c281261d8e03ddda37cafe..e1a07076cb2d8d16b96ba5a52a51dbcf77d14982 100644
--- a/services/core/java/com/android/server/notification/NotificationBitmapJobService.java
+++ b/services/core/java/com/android/server/notification/NotificationBitmapJobService.java
@@ -29,7 +29,12 @@ import android.util.Slog;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
 
-import java.util.Calendar;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.ZonedDateTime;
+import java.time.ZoneId;
 
 /**
  * This service runs everyday at 2am local time to remove expired bitmaps.
@@ -69,26 +74,25 @@ public class NotificationBitmapJobService extends JobService {
      * @return Milliseconds until the next time the job should run.
      */
     private static long getRunAfterMs() {
-        Calendar cal = Calendar.getInstance();  // Uses local time zone
-        final long now = cal.getTimeInMillis();
+        ZoneId zoneId = ZoneId.systemDefault();
+        ZonedDateTime now = Instant.now().atZone(zoneId);
 
-        cal.set(Calendar.HOUR_OF_DAY, 2);
-        cal.set(Calendar.MINUTE, 0);
-        cal.set(Calendar.MILLISECOND, 0);
-        final long today2AM = cal.getTimeInMillis();
+        LocalDate today = now.toLocalDate();
+        LocalTime twoAM = LocalTime.of(/* hour= */ 2, /* minute= */ 0);
 
-        cal.add(Calendar.DAY_OF_YEAR, 1);
-        final long tomorrow2AM = cal.getTimeInMillis();
+        ZonedDateTime today2AM = ZonedDateTime.of(today, twoAM, zoneId);
+        ZonedDateTime tomorrow2AM = today2AM.plusDays(1);
 
         return getTimeUntilRemoval(now, today2AM, tomorrow2AM);
     }
 
     @VisibleForTesting
-    static long getTimeUntilRemoval(long now, long today2AM, long tomorrow2AM) {
-        if (now < today2AM) {
-            return today2AM - now;
+    static long getTimeUntilRemoval(ZonedDateTime now, ZonedDateTime today2AM,
+                                    ZonedDateTime tomorrow2AM) {
+        if (Duration.between(now, today2AM).isNegative()) {
+            return Duration.between(now, tomorrow2AM).toMillis();
         }
-        return tomorrow2AM - now;
+        return Duration.between(now, today2AM).toMillis();
     }
 
     @Override
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationBitmapJobServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationBitmapJobServiceTest.java
index 312057ee922d607d83f5a6534151e95d5c65d295..348d1bfd44dfcca53addc641ebcd95d27349e40d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationBitmapJobServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationBitmapJobServiceTest.java
@@ -44,6 +44,12 @@ import org.mockito.Captor;
 import org.mockito.Mock;
 
 import java.lang.reflect.Field;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.ZonedDateTime;
+import java.time.ZoneId;
 
 @RunWith(AndroidTestingRunner.class)
 public class NotificationBitmapJobServiceTest extends UiServiceTestCase {
@@ -103,17 +109,39 @@ public class NotificationBitmapJobServiceTest extends UiServiceTestCase {
 
     @Test
     public void testGetTimeUntilRemoval_beforeToday2am_returnTimeUntilToday2am() {
-        final long timeUntilRemoval = mJobService.getTimeUntilRemoval(/* now= */ 1,
-                /* today2AM= */ 2, /* tomorrow2AM= */ 26);
+        ZoneId zoneId = ZoneId.systemDefault();
+        ZonedDateTime now = Instant.now().atZone(zoneId);
+        LocalDate today = now.toLocalDate();
 
-        assertThat(timeUntilRemoval).isEqualTo(1);
+        LocalTime oneAM = LocalTime.of(/* hour= */ 1, /* minute= */ 0);
+        LocalTime twoAM = LocalTime.of(/* hour= */ 2, /* minute= */ 0);
+
+        ZonedDateTime today1AM = ZonedDateTime.of(today, oneAM, zoneId);
+        ZonedDateTime today2AM = ZonedDateTime.of(today, twoAM, zoneId);
+        ZonedDateTime tomorrow2AM = today2AM.plusDays(1);
+
+        final long msUntilRemoval = mJobService.getTimeUntilRemoval(
+                /* now= */ today1AM, today2AM, tomorrow2AM);
+
+        assertThat(msUntilRemoval).isEqualTo(Duration.ofHours(1).toMillis());
     }
 
     @Test
     public void testGetTimeUntilRemoval_afterToday2am_returnTimeUntilTomorrow2am() {
-        final long timeUntilRemoval = mJobService.getTimeUntilRemoval(/* now= */ 3,
-                /* today2AM= */ 2, /* tomorrow2AM= */ 26);
+        ZoneId zoneId = ZoneId.systemDefault();
+        ZonedDateTime now = Instant.now().atZone(zoneId);
+        LocalDate today = now.toLocalDate();
+
+        LocalTime threeAM = LocalTime.of(/* hour= */ 3, /* minute= */ 0);
+        LocalTime twoAM = LocalTime.of(/* hour= */ 2, /* minute= */ 0);
+
+        ZonedDateTime today3AM = ZonedDateTime.of(today, threeAM, zoneId);
+        ZonedDateTime today2AM = ZonedDateTime.of(today, twoAM, zoneId);
+        ZonedDateTime tomorrow2AM = today2AM.plusDays(1);
+
+        final long msUntilRemoval = mJobService.getTimeUntilRemoval(/* now= */ today3AM,
+                today2AM, tomorrow2AM);
 
-        assertThat(timeUntilRemoval).isEqualTo(23);
+        assertThat(msUntilRemoval).isEqualTo(Duration.ofHours(23).toMillis());
     }
 }
\ No newline at end of file