Clean up usages for the DateTimeFormatter (#1113)

This commit is contained in:
David Perez 2024-03-08 13:35:45 -06:00 committed by Álison Fernandes
parent 9736aacd53
commit c986131afd
12 changed files with 67 additions and 63 deletions

View file

@ -322,7 +322,7 @@ private fun SendView.toDisplayItem(
SearchState.DisplayItem(
id = id.orEmpty(),
title = name,
subtitle = deletionDate.toFormattedPattern(DELETION_DATE_PATTERN, clock.zone),
subtitle = deletionDate.toFormattedPattern(DELETION_DATE_PATTERN, clock),
iconData = IconData.Local(
iconRes = when (type) {
SendType.TEXT -> R.drawable.ic_send_text

View file

@ -12,6 +12,7 @@ import com.x8bit.bitwarden.data.platform.manager.model.SpecialCircumstance
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
import com.x8bit.bitwarden.ui.platform.base.util.Text
import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.platform.util.toFormattedPattern
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
@ -20,7 +21,6 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import java.time.Clock
import java.time.format.DateTimeFormatter
import javax.inject.Inject
private const val KEY_STATE = "state"
@ -52,11 +52,6 @@ class LoginApprovalViewModel @Inject constructor(
)
},
) {
private val dateTimeFormatter
get() = DateTimeFormatter
.ofPattern("M/d/yy hh:mm a")
.withZone(clock.zone)
init {
state
.specialCircumstance
@ -171,7 +166,10 @@ class LoginApprovalViewModel @Inject constructor(
email = email,
fingerprint = result.authRequest.fingerprint,
ipAddress = result.authRequest.ipAddress,
time = dateTimeFormatter.format(result.authRequest.creationDate),
time = result.authRequest.creationDate.toFormattedPattern(
pattern = "M/d/yy hh:mm a",
clock = clock,
),
),
)
}

View file

@ -10,6 +10,7 @@ import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
import com.x8bit.bitwarden.ui.platform.base.util.Text
import com.x8bit.bitwarden.ui.platform.base.util.isOverFiveMinutesOld
import com.x8bit.bitwarden.ui.platform.util.toFormattedPattern
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
@ -19,7 +20,6 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import java.time.Clock
import java.time.format.DateTimeFormatter
import javax.inject.Inject
private const val KEY_STATE = "state"
@ -42,11 +42,6 @@ class PendingRequestsViewModel @Inject constructor(
) {
private var authJob: Job = Job().apply { complete() }
private val dateTimeFormatter
get() = DateTimeFormatter
.ofPattern("M/d/yy hh:mm a")
.withZone(clock.zone)
init {
updateAuthRequestList()
settingsRepository
@ -140,8 +135,9 @@ class PendingRequestsViewModel @Inject constructor(
PendingRequestsState.ViewState.Content.PendingLoginRequest(
fingerprintPhrase = request.fingerprint,
platform = request.platform,
timestamp = dateTimeFormatter.format(
request.creationDate,
timestamp = request.creationDate.toFormattedPattern(
pattern = "M/d/yy hh:mm a",
clock = clock,
),
)
}

View file

@ -217,6 +217,7 @@ class ExportVaultViewModel @Inject constructor(
is ExportVaultDataResult.Success -> {
val date = clock.instant().toFormattedPattern(
pattern = "yyyyMMddHHmmss",
clock = clock,
)
val extension = state.exportFormat.fileExtension
val fileName = "bitwarden_export_$date.$extension"

View file

@ -42,7 +42,7 @@ class OtherViewModel @Inject constructor(
clearClipboardFrequency = settingsRepo.clearClipboardFrequency,
lastSyncTime = settingsRepo
.vaultLastSync
?.toFormattedPattern(VAULT_LAST_SYNC_TIME_PATTERN, clock.zone)
?.toFormattedPattern(VAULT_LAST_SYNC_TIME_PATTERN, clock)
.orEmpty(),
dialogState = null,
),
@ -105,7 +105,7 @@ class OtherViewModel @Inject constructor(
it.copy(
lastSyncTime = action
.vaultLastSyncTime
?.toFormattedPattern(VAULT_LAST_SYNC_TIME_PATTERN, clock.zone)
?.toFormattedPattern(VAULT_LAST_SYNC_TIME_PATTERN, clock)
.orEmpty(),
dialogState = null,
)

View file

@ -1,17 +1,22 @@
package com.x8bit.bitwarden.ui.platform.util
import java.time.Clock
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.temporal.TemporalAccessor
import java.util.TimeZone
/**
* Converts the [TemporalAccessor] to a formatted string based on the provided pattern and timezone.
*/
fun TemporalAccessor.toFormattedPattern(
pattern: String,
zone: ZoneId = TimeZone.getDefault().toZoneId(),
): String {
val formatter = DateTimeFormatter.ofPattern(pattern).withZone(zone)
return formatter.format(this)
}
zone: ZoneId,
): String = DateTimeFormatter.ofPattern(pattern).withZone(zone).format(this)
/**
* Converts the [TemporalAccessor] to a formatted string based on the provided pattern and timezone.
*/
fun TemporalAccessor.toFormattedPattern(
pattern: String,
clock: Clock = Clock.systemDefaultZone(),
): String = toFormattedPattern(pattern = pattern, zone = clock.zone)

View file

@ -24,6 +24,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import java.time.Clock
import javax.inject.Inject
private const val KEY_STATE = "state"
@ -34,10 +35,11 @@ private const val KEY_STATE = "state"
@HiltViewModel
@Suppress("TooManyFunctions")
class PasswordHistoryViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val clock: Clock,
private val clipboardManager: BitwardenClipboardManager,
private val generatorRepository: GeneratorRepository,
private val vaultRepository: VaultRepository,
savedStateHandle: SavedStateHandle,
) : BaseViewModel<PasswordHistoryState, PasswordHistoryEvent, PasswordHistoryAction>(
initialState = savedStateHandle[KEY_STATE]
?: run {
@ -138,6 +140,7 @@ class PasswordHistoryViewModel @Inject constructor(
password = passwordHistoryView.password,
date = passwordHistoryView.lastUsedDate.toFormattedPattern(
pattern = "MM/dd/yy h:mm a",
clock = clock,
),
)
}

View file

@ -13,19 +13,16 @@ import com.x8bit.bitwarden.ui.platform.base.util.capitalize
import com.x8bit.bitwarden.ui.platform.base.util.nullIfAllEqual
import com.x8bit.bitwarden.ui.platform.base.util.orNullIfBlank
import com.x8bit.bitwarden.ui.platform.base.util.orZeroWidthSpace
import com.x8bit.bitwarden.ui.platform.util.toFormattedPattern
import com.x8bit.bitwarden.ui.vault.feature.item.VaultItemState
import com.x8bit.bitwarden.ui.vault.feature.item.model.TotpCodeItemData
import com.x8bit.bitwarden.ui.vault.feature.vault.VaultState
import com.x8bit.bitwarden.ui.vault.model.VaultCardBrand
import com.x8bit.bitwarden.ui.vault.model.VaultLinkedFieldType
import com.x8bit.bitwarden.ui.vault.model.findVaultCardBrandWithNameOrNull
import java.time.format.DateTimeFormatter
import java.util.TimeZone
private val dateTimeFormatter
get() = DateTimeFormatter
.ofPattern("M/d/yy hh:mm a")
.withZone(TimeZone.getDefault().toZoneId())
private const val DATE_TIME_PATTERN: String = "M/d/yy hh:mm a"
/**
* Transforms [VaultData] into [VaultState.ViewState].
@ -41,7 +38,10 @@ fun CipherView.toViewState(
name = name,
requiresReprompt = reprompt == CipherRepromptType.PASSWORD,
customFields = fields.orEmpty().map { it.toCustomField() },
lastUpdated = dateTimeFormatter.format(revisionDate),
lastUpdated = revisionDate.toFormattedPattern(
pattern = DATE_TIME_PATTERN,
zone = TimeZone.getDefault().toZoneId(),
),
notes = notes,
attachments = attachments
?.mapNotNull {
@ -83,9 +83,12 @@ fun CipherView.toViewState(
)
},
uris = loginValues.uris.orEmpty().map { it.toUriData() },
passwordRevisionDate = loginValues.passwordRevisionDate?.let {
dateTimeFormatter.format(it)
},
passwordRevisionDate = loginValues
.passwordRevisionDate
?.toFormattedPattern(
pattern = DATE_TIME_PATTERN,
zone = TimeZone.getDefault().toZoneId(),
),
passwordHistoryCount = passwordHistory?.count(),
isPremiumUser = isPremiumUser,
totpCodeItemData = totpCodeItemData,

View file

@ -283,7 +283,7 @@ private fun SendView.toDisplayItem(
VaultItemListingState.DisplayItem(
id = id.orEmpty(),
title = name,
subtitle = deletionDate.toFormattedPattern(DELETION_DATE_PATTERN, clock.zone),
subtitle = deletionDate.toFormattedPattern(DELETION_DATE_PATTERN, clock),
iconData = IconData.Local(
iconRes = when (type) {
SendType.TEXT -> R.drawable.ic_send_text

View file

@ -20,14 +20,11 @@ import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.time.Clock
import java.time.Instant
import java.time.ZoneOffset
import java.util.TimeZone
class ExportVaultViewModelTest : BaseViewModelTest() {
private val authRepository: AuthRepository = mockk()
@ -48,16 +45,6 @@ class ExportVaultViewModelTest : BaseViewModelTest() {
}
private val fileManager: FileManager = mockk()
@BeforeEach
fun setup() {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
}
@AfterEach
fun teardown() {
TimeZone.setDefault(null)
}
@Test
fun `initial state should be correct`() = runTest {
every {

View file

@ -2,13 +2,15 @@ package com.x8bit.bitwarden.ui.platform.util
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import java.time.Clock
import java.time.Instant
import java.time.ZoneId
import java.time.ZoneOffset
class TemporalAccessorExtensionsTest {
@Test
fun `toFormattedPattern should return correctly formatted string`() {
fun `toFormattedPattern should return correctly formatted string with timezone`() {
val instant = Instant.parse("2023-12-10T15:30:00Z")
val pattern = "MM/dd/yyyy hh:mm a"
val zone = ZoneId.of("UTC")
@ -17,4 +19,18 @@ class TemporalAccessorExtensionsTest {
assertEquals(expectedFormattedString, formattedString)
}
@Test
fun `toFormattedPattern should return correctly formatted string with clock`() {
val instant = Instant.parse("2023-12-10T15:30:00Z")
val pattern = "MM/dd/yyyy hh:mm a"
val clock: Clock = Clock.fixed(
Instant.parse("2023-10-27T12:00:00Z"),
ZoneOffset.UTC,
)
val expectedFormattedString = "12/10/2023 03:30 PM"
val formattedString = instant.toFormattedPattern(pattern, clock)
assertEquals(expectedFormattedString, formattedString)
}
}

View file

@ -22,18 +22,21 @@ import io.mockk.runs
import io.mockk.verify
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.time.Clock
import java.time.Instant
import java.util.TimeZone
import java.time.ZoneOffset
class PasswordHistoryViewModelTest : BaseViewModelTest() {
private val initialState = createPasswordHistoryState()
private val fixedClock: Clock = Clock.fixed(
Instant.parse("2023-10-27T12:00:00Z"),
ZoneOffset.UTC,
)
private val clipboardManager: BitwardenClipboardManager = mockk()
private val fakeGeneratorRepository = FakeGeneratorRepository()
private val mutableVaultItemFlow = MutableStateFlow<DataState<CipherView?>>(DataState.Loading)
@ -41,16 +44,6 @@ class PasswordHistoryViewModelTest : BaseViewModelTest() {
every { getVaultItemStateFlow("mockId-1") } returns mutableVaultItemFlow
}
@BeforeEach
fun setUp() {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
}
@AfterEach
fun tearDown() {
TimeZone.setDefault(null)
}
@Test
fun `initial state should be correct`() = runTest {
val viewModel = createViewModel()
@ -200,6 +193,7 @@ class PasswordHistoryViewModelTest : BaseViewModelTest() {
password = "password",
date = passwordHistoryView.lastUsedDate.toFormattedPattern(
pattern = "MM/dd/yy h:mm a",
clock = fixedClock,
),
),
),
@ -260,10 +254,11 @@ class PasswordHistoryViewModelTest : BaseViewModelTest() {
private fun createViewModel(
initialState: PasswordHistoryState = createPasswordHistoryState(),
): PasswordHistoryViewModel = PasswordHistoryViewModel(
savedStateHandle = createSavedStateHandleWithState(state = initialState),
clock = fixedClock,
clipboardManager = clipboardManager,
generatorRepository = fakeGeneratorRepository,
vaultRepository = fakeVaultRepository,
savedStateHandle = createSavedStateHandleWithState(state = initialState),
)
private fun createPasswordHistoryState(