From c0d6c8aeb37490d8a0274c33e5b1557842147342 Mon Sep 17 00:00:00 2001 From: Isira Seneviratne Date: Wed, 2 Dec 2020 09:39:40 +0530 Subject: [PATCH] Add a workaround for a possible null offset ID. --- .../org/schabi/newpipe/ktx/OffsetDateTime.kt | 25 +++++++++++++-- .../org/schabi/newpipe/util/Localization.java | 4 +-- .../ktx/OffsetDateTimeToCalendarTest.kt | 31 +++++++++++++++++++ 3 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 app/src/test/java/org/schabi/newpipe/ktx/OffsetDateTimeToCalendarTest.kt diff --git a/app/src/main/java/org/schabi/newpipe/ktx/OffsetDateTime.kt b/app/src/main/java/org/schabi/newpipe/ktx/OffsetDateTime.kt index b3df83c25..0d1a534b9 100644 --- a/app/src/main/java/org/schabi/newpipe/ktx/OffsetDateTime.kt +++ b/app/src/main/java/org/schabi/newpipe/ktx/OffsetDateTime.kt @@ -1,10 +1,29 @@ package org.schabi.newpipe.ktx import java.time.OffsetDateTime -import java.time.ZoneId +import java.time.ZoneOffset +import java.time.temporal.ChronoField import java.util.Calendar +import java.util.Date import java.util.GregorianCalendar +import java.util.TimeZone -fun OffsetDateTime.toCalendar(zoneId: ZoneId = ZoneId.systemDefault()): Calendar { - return GregorianCalendar.from(if (zoneId != offset) atZoneSameInstant(zoneId) else toZonedDateTime()) +// This method is a modified version of GregorianCalendar.from(ZonedDateTime). +// Math.addExact() and Math.multiplyExact() are desugared even though lint displays a warning. +@SuppressWarnings("NewApi") +fun OffsetDateTime.toCalendar(): Calendar { + val cal = GregorianCalendar(TimeZone.getTimeZone("UTC")) + val offsetDateTimeUTC = withOffsetSameInstant(ZoneOffset.UTC) + cal.gregorianChange = Date(Long.MIN_VALUE) + cal.firstDayOfWeek = Calendar.MONDAY + cal.minimalDaysInFirstWeek = 4 + try { + cal.timeInMillis = Math.addExact( + Math.multiplyExact(offsetDateTimeUTC.toEpochSecond(), 1000), + offsetDateTimeUTC[ChronoField.MILLI_OF_SECOND].toLong() + ) + } catch (ex: ArithmeticException) { + throw IllegalArgumentException(ex) + } + return cal } diff --git a/app/src/main/java/org/schabi/newpipe/util/Localization.java b/app/src/main/java/org/schabi/newpipe/util/Localization.java index afe2c0467..710827864 100644 --- a/app/src/main/java/org/schabi/newpipe/util/Localization.java +++ b/app/src/main/java/org/schabi/newpipe/util/Localization.java @@ -20,6 +20,7 @@ import org.ocpsoft.prettytime.units.Decade; import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.localization.ContentCountry; +import org.schabi.newpipe.ktx.OffsetDateTimeKt; import java.math.BigDecimal; import java.math.RoundingMode; @@ -30,7 +31,6 @@ import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.util.Arrays; import java.util.Calendar; -import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; @@ -314,7 +314,7 @@ public final class Localization { } public static String relativeTime(final OffsetDateTime offsetDateTime) { - return relativeTime(GregorianCalendar.from(offsetDateTime.toZonedDateTime())); + return relativeTime(OffsetDateTimeKt.toCalendar(offsetDateTime)); } public static String relativeTime(final Calendar calendarTime) { diff --git a/app/src/test/java/org/schabi/newpipe/ktx/OffsetDateTimeToCalendarTest.kt b/app/src/test/java/org/schabi/newpipe/ktx/OffsetDateTimeToCalendarTest.kt new file mode 100644 index 000000000..c93d36eb5 --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/ktx/OffsetDateTimeToCalendarTest.kt @@ -0,0 +1,31 @@ +package org.schabi.newpipe.ktx + +import org.junit.Assert.assertEquals +import org.junit.Test +import java.time.LocalDate +import java.time.OffsetDateTime +import java.time.ZoneId +import java.time.ZoneOffset +import java.util.Calendar +import java.util.TimeZone + +class OffsetDateTimeToCalendarTest { + @Test + fun testRelativeTimeWithCurrentOffsetDateTime() { + val calendar = LocalDate.of(2020, 1, 1).atStartOfDay().atOffset(ZoneOffset.UTC) + .toCalendar() + + assertEquals(2020, calendar[Calendar.YEAR]) + assertEquals(0, calendar[Calendar.MONTH]) + assertEquals(1, calendar[Calendar.DAY_OF_MONTH]) + assertEquals(0, calendar[Calendar.HOUR]) + assertEquals(0, calendar[Calendar.MINUTE]) + assertEquals(0, calendar[Calendar.SECOND]) + assertEquals(TimeZone.getTimeZone("UTC"), calendar.timeZone) + } + + @Test(expected = IllegalArgumentException::class) + fun testRelativeTimeWithFarOffOffsetDateTime() { + OffsetDateTime.MAX.minusYears(1).toCalendar() + } +}