Use PrettyTime's new formatUnrounded(OffsetDateTime) method.

Also change the types of the relevant variables from Calendar to OffsetDateTime.
This commit is contained in:
Isira Seneviratne 2020-12-20 09:53:05 +05:30
parent 8cf4ba25f5
commit 74e20a8c52
7 changed files with 16 additions and 98 deletions

View file

@ -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
}

View file

@ -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)
} }
// ///////////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////////

View file

@ -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()

View file

@ -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)
} }
) )

View file

@ -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) {

View file

@ -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()
}
}

View file

@ -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)