Use kotlinx.datetime.Timezone instead of java ZoneId

Change-Id: I62c4d044b319a9b59e06bb42fd12971d992e8628
pull/1837/head
Tomáš Mlynarič 2 years ago
parent 6c7a136de2
commit e208bd0bfd

@ -39,9 +39,9 @@ import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import kotlinx.datetime.TimeZone
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import java.time.ZoneId
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFalse import kotlin.test.assertFalse
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -199,7 +199,7 @@ class NiaAppStateTest {
timeZoneMonitor = timeZoneMonitor, timeZoneMonitor = timeZoneMonitor,
) )
} }
val changedTz = ZoneId.of("Europe/Prague") val changedTz = TimeZone.of("Europe/Prague")
backgroundScope.launch { state.currentTimeZone.collect() } backgroundScope.launch { state.currentTimeZone.collect() }
timeZoneMonitor.setTimeZone(changedTz) timeZoneMonitor.setTimeZone(changedTz)
assertEquals( assertEquals(

@ -47,7 +47,7 @@ import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand
import com.google.samples.apps.nowinandroid.core.ui.LocalZoneId import com.google.samples.apps.nowinandroid.core.ui.LocalTimeZone
import com.google.samples.apps.nowinandroid.ui.NiaApp import com.google.samples.apps.nowinandroid.ui.NiaApp
import com.google.samples.apps.nowinandroid.ui.rememberNiaAppState import com.google.samples.apps.nowinandroid.ui.rememberNiaAppState
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -144,7 +144,7 @@ class MainActivity : ComponentActivity() {
CompositionLocalProvider( CompositionLocalProvider(
LocalAnalyticsHelper provides analyticsHelper, LocalAnalyticsHelper provides analyticsHelper,
LocalZoneId provides currentZoneId, LocalTimeZone provides currentZoneId,
) { ) {
NiaTheme( NiaTheme(
darkTheme = darkTheme, darkTheme = darkTheme,

@ -51,7 +51,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import java.time.ZoneId import kotlinx.datetime.TimeZone
@Composable @Composable
fun rememberNiaAppState( fun rememberNiaAppState(
@ -140,11 +140,11 @@ class NiaAppState(
initialValue = emptySet(), initialValue = emptySet(),
) )
val currentTimeZone = timeZoneMonitor.currentZoneId val currentTimeZone = timeZoneMonitor.currentTimeZone
.stateIn( .stateIn(
coroutineScope, coroutineScope,
SharingStarted.WhileSubscribed(5_000), SharingStarted.WhileSubscribed(5_000),
ZoneId.systemDefault(), TimeZone.currentSystemDefault(),
) )
/** /**

@ -19,9 +19,9 @@ package com.google.samples.apps.nowinandroid.core.data.test
import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import java.time.ZoneId import kotlinx.datetime.TimeZone
import javax.inject.Inject import javax.inject.Inject
class DefaultZoneIdTimeZoneMonitor @Inject constructor() : TimeZoneMonitor { class DefaultZoneIdTimeZoneMonitor @Inject constructor() : TimeZoneMonitor {
override val currentZoneId: Flow<ZoneId> = flowOf(ZoneId.of("Europe/Warsaw")) override val currentTimeZone: Flow<TimeZone> = flowOf(TimeZone.of("Europe/Warsaw"))
} }

@ -34,10 +34,11 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.shareIn
import kotlinx.datetime.TimeZone
import java.time.ZoneId import java.time.ZoneId
import java.util.TimeZone
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -46,7 +47,7 @@ import javax.inject.Singleton
* It always emits at least once with default setting and then for each TZ change. * It always emits at least once with default setting and then for each TZ change.
*/ */
interface TimeZoneMonitor { interface TimeZoneMonitor {
val currentZoneId: Flow<ZoneId> val currentTimeZone: Flow<TimeZone>
} }
@Singleton @Singleton
@ -56,10 +57,10 @@ internal class TimeZoneBroadcastMonitor @Inject constructor(
@Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher, @Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher,
) : TimeZoneMonitor { ) : TimeZoneMonitor {
override val currentZoneId: SharedFlow<ZoneId> = override val currentTimeZone: SharedFlow<TimeZone> =
callbackFlow<ZoneId> { callbackFlow<TimeZone> {
// Send the default time zone first. // Send the default time zone first.
trySend(ZoneId.systemDefault()) trySend(TimeZone.currentSystemDefault())
// Registers BroadcastReceiver for the TimeZone changes // Registers BroadcastReceiver for the TimeZone changes
val receiver = object : BroadcastReceiver() { val receiver = object : BroadcastReceiver() {
@ -70,15 +71,15 @@ internal class TimeZoneBroadcastMonitor @Inject constructor(
null null
} else { } else {
// Starting Android R we also get the new TimeZone. // Starting Android R we also get the new TimeZone.
intent.getStringExtra(Intent.EXTRA_TIMEZONE)?.let { zoneId -> intent.getStringExtra(Intent.EXTRA_TIMEZONE)?.let { timeZoneId ->
// We need to convert it from java.util.Timezone to java.time.ZoneId // We need to convert it from java.util.Timezone to java.time.ZoneId
ZoneId.of(zoneId, ZoneId.SHORT_IDS) val zoneId = ZoneId.of(timeZoneId, ZoneId.SHORT_IDS)
TimeZone.getTimeZone(zoneId).toZoneId() TimeZone.of(zoneId.id)
} }
} }
// If there isn't a zoneId in the intent, fallback to the systemDefault, which should also reflect the change // If there isn't a zoneId in the intent, fallback to the systemDefault, which should also reflect the change
trySend(zoneIdFromIntent ?: ZoneId.systemDefault()) trySend(zoneIdFromIntent ?: TimeZone.currentSystemDefault())
} }
} }

@ -19,22 +19,22 @@ package com.google.samples.apps.nowinandroid.core.testing.util
import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import java.time.ZoneId import kotlinx.datetime.TimeZone
class TestTimeZoneMonitor : TimeZoneMonitor { class TestTimeZoneMonitor : TimeZoneMonitor {
private val timeZoneFlow = MutableStateFlow(defaultTimeZone) private val timeZoneFlow = MutableStateFlow(defaultTimeZone)
override val currentZoneId: Flow<ZoneId> = timeZoneFlow override val currentTimeZone: Flow<TimeZone> = timeZoneFlow
/** /**
* A test-only API to set the from tests. * A test-only API to set the from tests.
*/ */
fun setTimeZone(zoneId: ZoneId) { fun setTimeZone(zoneId: TimeZone) {
timeZoneFlow.value = zoneId timeZoneFlow.value = zoneId
} }
companion object { companion object {
val defaultTimeZone: ZoneId = ZoneId.of("Europe/Warsaw") val defaultTimeZone: TimeZone = TimeZone.of("Europe/Warsaw")
} }
} }

@ -17,10 +17,10 @@
package com.google.samples.apps.nowinandroid.core.ui package com.google.samples.apps.nowinandroid.core.ui
import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.compositionLocalOf
import java.time.ZoneId import kotlinx.datetime.TimeZone
/** /**
* ZoneId that can be provided with the TimeZoneMonitor. * TimeZone that can be provided with the TimeZoneMonitor.
* This way, it's not needed to pass every single composable the time zone to show in UI. * This way, it's not needed to pass every single composable the time zone to show in UI.
*/ */
val LocalZoneId = compositionLocalOf { ZoneId.systemDefault() } val LocalTimeZone = compositionLocalOf { TimeZone.currentSystemDefault() }

@ -69,6 +69,7 @@ import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource
import kotlinx.datetime.Instant import kotlinx.datetime.Instant
import kotlinx.datetime.toJavaInstant import kotlinx.datetime.toJavaInstant
import kotlinx.datetime.toJavaZoneId
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle import java.time.format.FormatStyle
import java.util.Locale import java.util.Locale
@ -244,7 +245,7 @@ fun NotificationDot(
fun dateFormatted(publishDate: Instant): String = DateTimeFormatter fun dateFormatted(publishDate: Instant): String = DateTimeFormatter
.ofLocalizedDate(FormatStyle.MEDIUM) .ofLocalizedDate(FormatStyle.MEDIUM)
.withLocale(Locale.getDefault()) .withLocale(Locale.getDefault())
.withZone(LocalZoneId.current) .withZone(LocalTimeZone.current.toJavaZoneId())
.format(publishDate.toJavaInstant()) .format(publishDate.toJavaInstant())
@Composable @Composable

Loading…
Cancel
Save