mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 07:13:00 +00:00 
			
		
		
		
	Use PrettyTime's new formatUnrounded(OffsetDateTime) method.
Also change the types of the relevant variables from Calendar to OffsetDateTime.
This commit is contained in:
		| @@ -1,29 +0,0 @@ | |||||||
| package org.schabi.newpipe.ktx |  | ||||||
|  |  | ||||||
| import java.time.OffsetDateTime |  | ||||||
| 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 |  | ||||||
|  |  | ||||||
| // 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 |  | ||||||
| } |  | ||||||
| @@ -45,7 +45,7 @@ import org.schabi.newpipe.ktx.animate | |||||||
| import org.schabi.newpipe.ktx.animateHideRecyclerViewAllowingScrolling | import org.schabi.newpipe.ktx.animateHideRecyclerViewAllowingScrolling | ||||||
| import org.schabi.newpipe.local.feed.service.FeedLoadService | import org.schabi.newpipe.local.feed.service.FeedLoadService | ||||||
| import org.schabi.newpipe.util.Localization | import org.schabi.newpipe.util.Localization | ||||||
| import java.util.Calendar | import java.time.OffsetDateTime | ||||||
|  |  | ||||||
| class FeedFragment : BaseListFragment<FeedState, Unit>() { | class FeedFragment : BaseListFragment<FeedState, Unit>() { | ||||||
|     private var _feedBinding: FragmentFeedBinding? = null |     private var _feedBinding: FragmentFeedBinding? = null | ||||||
| @@ -58,7 +58,7 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() { | |||||||
|  |  | ||||||
|     private var groupId = FeedGroupEntity.GROUP_ALL_ID |     private var groupId = FeedGroupEntity.GROUP_ALL_ID | ||||||
|     private var groupName = "" |     private var groupName = "" | ||||||
|     private var oldestSubscriptionUpdate: Calendar? = null |     private var oldestSubscriptionUpdate: OffsetDateTime? = null | ||||||
|  |  | ||||||
|     init { |     init { | ||||||
|         setHasOptionsMenu(true) |         setHasOptionsMenu(true) | ||||||
| @@ -275,12 +275,10 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     private fun updateRefreshViewState() { |     private fun updateRefreshViewState() { | ||||||
|         val oldestSubscriptionUpdateText = when { |         feedBinding.refreshText.text = getString( | ||||||
|             oldestSubscriptionUpdate != null -> Localization.relativeTime(oldestSubscriptionUpdate!!) |             R.string.feed_oldest_subscription_update, | ||||||
|             else -> "—" |             oldestSubscriptionUpdate?.let { Localization.relativeTime(it) } ?: "—" | ||||||
|         } |         ) | ||||||
|  |  | ||||||
|         feedBinding.refreshText.text = getString(R.string.feed_oldest_subscription_update, oldestSubscriptionUpdateText) |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // ///////////////////////////////////////////////////////////////////////// |     // ///////////////////////////////////////////////////////////////////////// | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ package org.schabi.newpipe.local.feed | |||||||
|  |  | ||||||
| import androidx.annotation.StringRes | import androidx.annotation.StringRes | ||||||
| import org.schabi.newpipe.extractor.stream.StreamInfoItem | import org.schabi.newpipe.extractor.stream.StreamInfoItem | ||||||
| import java.util.Calendar | import java.time.OffsetDateTime | ||||||
|  |  | ||||||
| sealed class FeedState { | sealed class FeedState { | ||||||
|     data class ProgressState( |     data class ProgressState( | ||||||
| @@ -13,7 +13,7 @@ sealed class FeedState { | |||||||
|  |  | ||||||
|     data class LoadedState( |     data class LoadedState( | ||||||
|         val items: List<StreamInfoItem>, |         val items: List<StreamInfoItem>, | ||||||
|         val oldestUpdate: Calendar? = null, |         val oldestUpdate: OffsetDateTime? = null, | ||||||
|         val notLoadedCount: Long, |         val notLoadedCount: Long, | ||||||
|         val itemsErrors: List<Throwable> = emptyList() |         val itemsErrors: List<Throwable> = emptyList() | ||||||
|     ) : FeedState() |     ) : FeedState() | ||||||
|   | |||||||
| @@ -11,7 +11,6 @@ import io.reactivex.rxjava3.functions.Function4 | |||||||
| import io.reactivex.rxjava3.schedulers.Schedulers | import io.reactivex.rxjava3.schedulers.Schedulers | ||||||
| import org.schabi.newpipe.database.feed.model.FeedGroupEntity | import org.schabi.newpipe.database.feed.model.FeedGroupEntity | ||||||
| import org.schabi.newpipe.extractor.stream.StreamInfoItem | import org.schabi.newpipe.extractor.stream.StreamInfoItem | ||||||
| import org.schabi.newpipe.ktx.toCalendar |  | ||||||
| import org.schabi.newpipe.local.feed.service.FeedEventManager | import org.schabi.newpipe.local.feed.service.FeedEventManager | ||||||
| import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.ErrorResultEvent | import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.ErrorResultEvent | ||||||
| import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.IdleEvent | import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.IdleEvent | ||||||
| @@ -48,13 +47,11 @@ class FeedViewModel(applicationContext: Context, val groupId: Long = FeedGroupEn | |||||||
|         .subscribeOn(Schedulers.io()) |         .subscribeOn(Schedulers.io()) | ||||||
|         .observeOn(AndroidSchedulers.mainThread()) |         .observeOn(AndroidSchedulers.mainThread()) | ||||||
|         .subscribe { (event, listFromDB, notLoadedCount, oldestUpdate) -> |         .subscribe { (event, listFromDB, notLoadedCount, oldestUpdate) -> | ||||||
|             val oldestUpdateCalendar = oldestUpdate?.toCalendar() |  | ||||||
|  |  | ||||||
|             mutableStateLiveData.postValue( |             mutableStateLiveData.postValue( | ||||||
|                 when (event) { |                 when (event) { | ||||||
|                     is IdleEvent -> FeedState.LoadedState(listFromDB, oldestUpdateCalendar, notLoadedCount) |                     is IdleEvent -> FeedState.LoadedState(listFromDB, oldestUpdate, notLoadedCount) | ||||||
|                     is ProgressEvent -> FeedState.ProgressState(event.currentProgress, event.maxProgress, event.progressMessage) |                     is ProgressEvent -> FeedState.ProgressState(event.currentProgress, event.maxProgress, event.progressMessage) | ||||||
|                     is SuccessResultEvent -> FeedState.LoadedState(listFromDB, oldestUpdateCalendar, notLoadedCount, event.itemsErrors) |                     is SuccessResultEvent -> FeedState.LoadedState(listFromDB, oldestUpdate, notLoadedCount, event.itemsErrors) | ||||||
|                     is ErrorResultEvent -> FeedState.ErrorState(event.error) |                     is ErrorResultEvent -> FeedState.ErrorState(event.error) | ||||||
|                 } |                 } | ||||||
|             ) |             ) | ||||||
|   | |||||||
| @@ -20,7 +20,6 @@ import org.ocpsoft.prettytime.units.Decade; | |||||||
| import org.schabi.newpipe.R; | import org.schabi.newpipe.R; | ||||||
| import org.schabi.newpipe.extractor.ListExtractor; | import org.schabi.newpipe.extractor.ListExtractor; | ||||||
| import org.schabi.newpipe.extractor.localization.ContentCountry; | import org.schabi.newpipe.extractor.localization.ContentCountry; | ||||||
| import org.schabi.newpipe.ktx.OffsetDateTimeKt; |  | ||||||
|  |  | ||||||
| import java.math.BigDecimal; | import java.math.BigDecimal; | ||||||
| import java.math.RoundingMode; | import java.math.RoundingMode; | ||||||
| @@ -30,7 +29,6 @@ import java.time.ZoneId; | |||||||
| import java.time.format.DateTimeFormatter; | import java.time.format.DateTimeFormatter; | ||||||
| import java.time.format.FormatStyle; | import java.time.format.FormatStyle; | ||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.Calendar; |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Locale; | import java.util.Locale; | ||||||
|  |  | ||||||
| @@ -314,11 +312,7 @@ public final class Localization { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static String relativeTime(final OffsetDateTime offsetDateTime) { |     public static String relativeTime(final OffsetDateTime offsetDateTime) { | ||||||
|         return relativeTime(OffsetDateTimeKt.toCalendar(offsetDateTime)); |         return prettyTime.formatUnrounded(offsetDateTime); | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public static String relativeTime(final Calendar calendarTime) { |  | ||||||
|         return prettyTime.formatUnrounded(calendarTime); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static void changeAppLanguage(final Locale loc, final Resources res) { |     private static void changeAppLanguage(final Locale loc, final Resources res) { | ||||||
|   | |||||||
| @@ -1,30 +0,0 @@ | |||||||
| 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.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() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -3,34 +3,22 @@ package org.schabi.newpipe.util | |||||||
| import org.junit.Assert.assertEquals | import org.junit.Assert.assertEquals | ||||||
| import org.junit.Test | import org.junit.Test | ||||||
| import org.ocpsoft.prettytime.PrettyTime | import org.ocpsoft.prettytime.PrettyTime | ||||||
| import java.text.SimpleDateFormat | import java.time.LocalDate | ||||||
| import java.time.OffsetDateTime | import java.time.OffsetDateTime | ||||||
| import java.time.ZoneOffset | import java.time.ZoneOffset | ||||||
| import java.util.GregorianCalendar |  | ||||||
| import java.util.Locale | import java.util.Locale | ||||||
|  |  | ||||||
| class LocalizationTest { | class LocalizationTest { | ||||||
|  |  | ||||||
|     @Test |  | ||||||
|     fun `After initializing pretty time relativeTime() with a Calendar must work`() { |  | ||||||
|         val reference = SimpleDateFormat("yyyy/MM/dd").parse("2021/1/1") |  | ||||||
|         Localization.initPrettyTime(PrettyTime(reference, Locale.ENGLISH)) |  | ||||||
|  |  | ||||||
|         val actual = Localization.relativeTime(GregorianCalendar(2021, 1, 6)) |  | ||||||
|  |  | ||||||
|         // yes this assertion is true, even if it should be 5 days, it works as it is. Future research required. |  | ||||||
|         assertEquals("1 month from now", actual) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Test(expected = NullPointerException::class) |     @Test(expected = NullPointerException::class) | ||||||
|     fun `relativeTime() must fail without initializing pretty time`() { |     fun `relativeTime() must fail without initializing pretty time`() { | ||||||
|         Localization.relativeTime(GregorianCalendar(2021, 1, 6)) |         Localization.relativeTime(OffsetDateTime.of(2021, 1, 6, 0, 0, 0, 0, ZoneOffset.UTC)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Test |     @Test | ||||||
|     fun `relativeTime() with a OffsetDateTime must work`() { |     fun `relativeTime() with a OffsetDateTime must work`() { | ||||||
|         val reference = SimpleDateFormat("yyyy/MM/dd").parse("2021/1/1") |         val prettyTime = PrettyTime(LocalDate.of(2021, 1, 1), ZoneOffset.UTC) | ||||||
|         Localization.initPrettyTime(PrettyTime(reference, Locale.ENGLISH)) |         prettyTime.locale = Locale.ENGLISH | ||||||
|  |         Localization.initPrettyTime(prettyTime) | ||||||
|  |  | ||||||
|         val offset = OffsetDateTime.of(2021, 1, 6, 0, 0, 0, 0, ZoneOffset.UTC) |         val offset = OffsetDateTime.of(2021, 1, 6, 0, 0, 0, 0, ZoneOffset.UTC) | ||||||
|         val actual = Localization.relativeTime(offset) |         val actual = Localization.relativeTime(offset) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Isira Seneviratne
					Isira Seneviratne