Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: remove old date time parser APIs (WPB-9934) #3171

Merged
merged 37 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
da71d72
feat: write tests for benchmark, and create new parser without sdf
yamilmedina Jul 5, 2024
506a191
feat: cleanup deprecated serverdate with sdf
yamilmedina Jul 5, 2024
aad9fb9
feat: extract to a new class/file the new parsers
yamilmedina Jul 8, 2024
a5ed0d3
feat: extract to a new class/file the new parsers
yamilmedina Jul 8, 2024
231e900
feat: migrate mediumdateformatter
yamilmedina Jul 8, 2024
994c4e5
feat: migrate formatFullDateShortTime
yamilmedina Jul 8, 2024
1d94ec1
feat: test cleanup
yamilmedina Jul 8, 2024
ed2fd17
feat: test cleanup
yamilmedina Jul 8, 2024
cf61e6e
feat: migrate filedatetime
yamilmedina Jul 8, 2024
8099bcf
feat: migrate readreceip
yamilmedina Jul 8, 2024
a55ccfb
feat: espresso tests for validation in device
yamilmedina Jul 8, 2024
1474f5a
feat: espresso tests for validation in device
yamilmedina Jul 8, 2024
4f501f7
feat: espresso tests for validation in device
yamilmedina Jul 8, 2024
a9f6541
feat: migrage medium only date
yamilmedina Jul 8, 2024
77e550a
feat: test format
yamilmedina Jul 8, 2024
64f3be4
fix: tests locally, force locales
yamilmedina Jul 8, 2024
10424aa
fix: detekt
yamilmedina Jul 8, 2024
73ae392
Merge branch 'develop' into feat/remove-oldapi-simpledateformat
yamilmedina Jul 8, 2024
8569b18
fix: detekt
yamilmedina Jul 8, 2024
f772a75
fix: detekt
yamilmedina Jul 8, 2024
1ec6e0e
fix: detekt
yamilmedina Jul 9, 2024
273c36d
chore: fix detekt
yamilmedina Jul 9, 2024
52910d0
refactor: extract uimessage time
yamilmedina Jul 9, 2024
bedb199
refactor: extract uimessage time
yamilmedina Jul 9, 2024
c0c7bb5
refactor: extract uimessage time, cleanup
yamilmedina Jul 9, 2024
af431bf
Merge branch 'develop' into feat/remove-oldapi-simpledateformat
yamilmedina Jul 9, 2024
78d80a0
fix: tests locally, force locales
yamilmedina Jul 9, 2024
022d605
Merge branch 'develop' into feat/remove-oldapi-simpledateformat
yamilmedina Jul 9, 2024
ea000d9
fix: pr comments stable funcs
yamilmedina Jul 9, 2024
5d3eca3
Merge branch 'develop' into feat/remove-oldapi-simpledateformat
yamilmedina Jul 9, 2024
54741a3
fix: pr comments stable funcs
yamilmedina Jul 9, 2024
3afc7d3
fix: pr deprecation notice
yamilmedina Jul 9, 2024
79e5bda
fix: pr deprecation notice
yamilmedina Jul 9, 2024
cc21fec
Merge branch 'develop' into feat/remove-oldapi-simpledateformat
mchenani Jul 12, 2024
37bce40
feat: cleanup code mapper
yamilmedina Jul 12, 2024
1a9414f
feat: cleanup code mapper
yamilmedina Jul 12, 2024
efd3770
feat: cleanup code mapper
yamilmedina Jul 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: extract to a new class/file the new parsers
  • Loading branch information
yamilmedina committed Jul 8, 2024
commit aad9fb9274fd6034b09a6dd3df35c4210e20fe9f
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ import kotlin.time.measureTime
class DateTimeUtilTest {

@Test
fun givenDates_OutputPerformanceOfFormattersInDevice() {
fun givenDates_OutputPerformanceForServerDateFormattersInDevice() {
// warmup
val date = Clock.System.now().toIsoDateTimeString()
repeat(ITERATIONS / 2) {
ServerDateTimeFormatter.serverDateOld(date)
serverDateOld(date)
date.serverDate()
}

Expand All @@ -43,14 +43,41 @@ class DateTimeUtilTest {
// datetime format
val duration2 = measureTime {
repeat(ITERATIONS) {
ServerDateTimeFormatter.serverDateOld(date)
serverDateOld(date)
}
}

println("The duration of using ServerDate/LocalDateTimeFormat was: $duration1")
println("The duration of using ServerDateOld/SimpleDateFormat was: $duration2")
}

@Test
fun givenDates_OutputPerformanceForDeviceDateFormattersInDevice() {
// warmup
val date = Clock.System.now().toIsoDateTimeString()
repeat(ITERATIONS / 2) {
date.deviceDateTimeFormat()
date.deviceDateTimeFormatOld()
}

// Old DateFormat from text api
val duration1 = measureTime {
repeat(ITERATIONS) {
date.deviceDateTimeFormat()
}
}

// New DateTimeFormatter from time api
val duration2 = measureTime {
repeat(ITERATIONS) {
date.deviceDateTimeFormatOld()
}
}

println("The duration of using TextApi/DateFormat was: $duration1")
println("The duration of using TimeApi/DateTimeFormatter was: $duration2")
}

companion object {
const val ITERATIONS = 1_000_000
}
Expand Down
58 changes: 58 additions & 0 deletions app/src/main/kotlin/com/wire/android/util/DateAndTimeParsers.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Wire
* Copyright (C) 2024 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.android.util

import com.wire.android.appLogger
import java.text.ParseException
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import java.util.Date
import java.util.Locale

fun String.deviceDateTimeFormat(): String? = DateAndTimeParsers.deviceDateTimeFormat(this)
fun String.serverDate(): Date? = DateAndTimeParsers.serverDate(this)

class DateAndTimeParsers private constructor() {

companion object {
private val dateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneId.of("UTC"))
private val longDateShortTimeFormat = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT)
.withZone(ZoneId.systemDefault()).withLocale(Locale.getDefault())

fun serverDate(stringVal: String): Date? {
return try {
Date(LocalDateTime.parse(stringVal, dateTimeFormatter).toInstant(ZoneOffset.UTC).toEpochMilli())
} catch (e: Exception) {
appLogger.e("There was an error parsing the server date")
null
}
}

fun deviceDateTimeFormat(stringVal: String): String? {
return try {
stringVal.serverDate()?.let { longDateShortTimeFormat.format(it.toInstant()) }
} catch (e: ParseException) {
null
}
}
}

}
42 changes: 14 additions & 28 deletions app/src/main/kotlin/com/wire/android/util/DateTimeUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,15 @@ import java.text.DateFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit
import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.TimeZone

private val serverDateTimeFormat =
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()).apply { timeZone = TimeZone.getTimeZone("UTC") }
private val mediumDateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM)
private val longDateShortTimeFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT)
private val mediumOnlyDateTimeFormat = DateFormat.getDateInstance(DateFormat.MEDIUM)
Expand Down Expand Up @@ -65,7 +64,11 @@ fun String.formatMediumDateTime(): String? =
null
}

fun String.deviceDateTimeFormat(): String? =
@Deprecated(
message = "This implementation uses discouraged SimpleDateFormat and it will be removed",
replaceWith = ReplaceWith("DateAndTimeParsers.serverDate() or String.serverDate()"),
)
fun String.deviceDateTimeFormatOld(): String? =
try {
this.serverDate()?.let { longDateShortTimeFormat.format(it) }
} catch (e: ParseException) {
Expand All @@ -79,10 +82,13 @@ fun String.formatFullDateShortTime(): String? =
null
}

private val dateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneId.of("UTC"))
fun String.serverDate(): Date? = try {
Date(LocalDateTime.parse(this, dateTimeFormatter).toInstant(ZoneOffset.UTC).toEpochMilli())
} catch (e: Exception) {
@Deprecated(
message = "This implementation uses discouraged SimpleDateFormat and it will be removed",
replaceWith = ReplaceWith("DateAndTimeParsers.serverDate() or String.serverDate()"),
)
fun serverDateOld(stringDate: String): Date? = try {
serverDateTimeFormat.parse(stringDate)
} catch (e: ParseException) {
appLogger.e("There was an error parsing the server date")
null
}
Expand Down Expand Up @@ -240,23 +246,3 @@ fun String.groupedUIMessageDateTime(now: Long): MessageDateTimeGroup? = this
fun Date.toMediumOnlyDateTime(): String = mediumOnlyDateTimeFormat.format(this)
fun Instant.uiReadReceiptDateTime(): String = readReceiptDateTimeFormat.format(Date(this.toEpochMilliseconds()))
fun Instant.fileDateTime(): String = fileDateTimeFormat.format(Date(this.toEpochMilliseconds()))

/**
* Deprecated Wrapper class for old server date formatter.
* Just keeping it around to validate old behavior and benchmarks.
*/
sealed class ServerDateTimeFormatter {

companion object {
private val serverDateTimeFormat =
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()).apply { timeZone = TimeZone.getTimeZone("UTC") }

@Deprecated("Prefer using serverDate()")
fun serverDateOld(stringDate: String): Date? = try {
serverDateTimeFormat.parse(stringDate)
} catch (e: ParseException) {
appLogger.e("There was an error parsing the server date")
null
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,13 @@ class DateTimeUtilKtTest {

@Test
fun `given a new serverDate is called, the formatted result should be the same with LocalDateTime format`() {
assertEquals(ServerDateTimeFormatter.serverDateOld(baseDate), baseDate.serverDate())
assertEquals(serverDateOld(baseDate), baseDate.serverDate())
}

@Test
fun `given a valid date, when performing a transformation, then the formatted result should be the same with DateTimeFormatter`() {
val result = "2022-03-24T18:02:30.360Z"
assertEquals(result.deviceDateTimeFormat(), result.deviceDateTimeFormatOld())
}
}

Expand Down