Less sugar

This commit is contained in:
Sad Ellie 2023-02-03 14:10:27 +04:00
parent 32fafb9a66
commit 52d7db579c
8 changed files with 178 additions and 49 deletions

View File

@ -79,6 +79,7 @@ android {
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8
isCoreLibraryDesugaringEnabled = true
} }
packagingOptions { packagingOptions {
@ -101,6 +102,7 @@ android {
dependencies { dependencies {
implementation(libs.androidx.core) implementation(libs.androidx.core)
coreLibraryDesugaring(libs.android.desugarJdkLibs)
implementation(libs.androidx.compose.material3) implementation(libs.androidx.compose.material3)
implementation(libs.androidx.lifecycle.runtime.compose) implementation(libs.androidx.lifecycle.runtime.compose)

View File

@ -21,7 +21,10 @@ package com.sadellie.unitto
import com.android.build.api.dsl.CommonExtension import com.android.build.api.dsl.CommonExtension
import org.gradle.api.JavaVersion import org.gradle.api.JavaVersion
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.artifacts.VersionCatalogsExtension
import org.gradle.api.plugins.ExtensionAware import org.gradle.api.plugins.ExtensionAware
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.getByType
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
internal fun Project.configureKotlinAndroid( internal fun Project.configureKotlinAndroid(
@ -47,6 +50,7 @@ internal fun Project.configureKotlinAndroid(
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8
isCoreLibraryDesugaringEnabled = true
} }
buildFeatures { buildFeatures {
@ -75,6 +79,12 @@ internal fun Project.configureKotlinAndroid(
jvmTarget = JavaVersion.VERSION_1_8.toString() jvmTarget = JavaVersion.VERSION_1_8.toString()
} }
} }
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependencies {
add("coreLibraryDesugaring", libs.findLibrary("android.desugarJdkLibs").get())
}
} }
fun CommonExtension<*, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { fun CommonExtension<*, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) {

View File

@ -24,3 +24,7 @@ plugins {
android { android {
namespace = "com.sadellie.unitto.data.epoch" namespace = "com.sadellie.unitto.data.epoch"
} }
dependencies {
testImplementation(libs.junit)
}

View File

@ -18,60 +18,33 @@
package com.sadellie.unitto.data.epoch package com.sadellie.unitto.data.epoch
import java.math.BigDecimal import java.time.LocalDateTime
import java.util.* import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeParseException
object EpochDateConverter { object EpochDateConverter {
private val pattern by lazy {
DateTimeFormatter.ofPattern("HHmmssddMMyyyy")
}
fun convertDateToUnix(date: String): String { fun convertDateToUnix(date: String): String {
// Here we add some zeros, so that input is 14 symbols long return try {
val inputWithPadding = date.padEnd(14, '0') // Here we add some zeros, so that input is 14 symbols long
LocalDateTime
// Now we break input that is 14 symbols into pieces .parse(date.padEnd(14, '0'), pattern)
val hour = inputWithPadding.substring(0, 2) .toEpochSecond(ZoneOffset.UTC)
val minute = inputWithPadding.substring(2, 4) } catch (e: DateTimeParseException) {
val second = inputWithPadding.substring(4, 6) 0
val day = inputWithPadding.substring(6, 8) }.toString()
val month = inputWithPadding.substring(8, 10)
val year = inputWithPadding.substring(10, 14)
val cal = Calendar.getInstance()
cal.set(
year.toIntOrNull() ?: 1970,
(month.toIntOrNull() ?: 1) - 1,
day.toIntOrNull() ?: 0,
hour.toIntOrNull() ?: 0,
minute.toIntOrNull() ?: 0,
second.toIntOrNull() ?: 0,
)
return (cal.timeInMillis / 1000).toString()
} }
fun convertUnixToDate(unix: String): String { fun convertUnixToDate(unix: String): String {
var date = "" val unixLong = unix.toLong().takeIf { it <= 253402300559L }
val cal2 = Calendar.getInstance() ?: throw IllegalArgumentException("Max unix is 253402300559")
cal2.clear()
cal2.isLenient = true
// This lets us bypass calendars limits (it uses Int, we want BigDecimal) return LocalDateTime
try { .ofEpochSecond(unixLong, 0, ZoneOffset.UTC)
val unixBg = BigDecimal(unix.ifEmpty { "0" }) .format(pattern)
val division = unixBg.divideAndRemainder(BigDecimal(Int.MAX_VALUE))
val intTimes = division.component1()
val rem = division.component2()
repeat(intTimes.intValueExact()) {
cal2.add(Calendar.SECOND, Int.MAX_VALUE)
}
cal2.add(Calendar.SECOND, rem.intValueExact())
} catch (e: NumberFormatException) {
return ""
}
date += cal2.get(Calendar.HOUR_OF_DAY).toString().padStart(2, '0')
date += cal2.get(Calendar.MINUTE).toString().padStart(2, '0')
date += cal2.get(Calendar.SECOND).toString().padStart(2, '0')
date += cal2.get(Calendar.DAY_OF_MONTH).toString().padStart(2, '0')
date += (cal2.get(Calendar.MONTH) + 1).toString().padStart(2, '0')
// Year is 4 symbols long
date += cal2.get(Calendar.YEAR).toString().padStart(4, '0')
return date
} }
} }

View File

@ -0,0 +1,60 @@
/*
* Unitto is a unit converter for Android
* Copyright (c) 2023 Elshan Agaev
*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.sadellie.unitto.data.epoch
import org.junit.Assert.assertEquals
import org.junit.Test
class DateToEpochTest {
@Test
fun `00h0m00s 00 00 0000`() {
convertDateToUnixTest("00:00:00 00.00.0000", "0")
}
@Test
fun `00h00m00s 01 01 0001`() {
convertDateToUnixTest("00:00:00 01.01.0001", "-62135596800")
}
@Test
fun `00h00m00s 01 01 1970`() {
convertDateToUnixTest("00:00:00 01.01.1970", "0")
}
@Test
fun `23h55m59s 31 12 9999`() {
convertDateToUnixTest("23:55:59 31.12.9999", "253402300559")
}
@Test
fun `99h99m99s 99 99 9999`() {
convertDateToUnixTest("99:99:99 99.99.9999", "0")
}
private fun convertDateToUnixTest(inputDate: String, expectedUnix: String) {
// Date input comes "fancy"
val cleanInputDate = inputDate.filter{ it.isDigit() }
assertEquals(
"Couldn't convert $inputDate ($cleanInputDate) into unix",
expectedUnix,
EpochDateConverter.convertDateToUnix(cleanInputDate)
)
}
}

View File

@ -0,0 +1,72 @@
/*
* Unitto is a unit converter for Android
* Copyright (c) 2023 Elshan Agaev
*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.sadellie.unitto.data.epoch
import org.junit.Assert.assertEquals
import org.junit.Assert.assertThrows
import org.junit.Test
class EpochToDateTest {
@Test
fun `0`() {
convertUnixToDate("0", "00:00:00 01.01.1970")
}
@Test
fun `00000000000000 max input length`() {
convertUnixToDate("00000000000000", "00:00:00 01.01.1970")
}
@Test
fun `253402300559 max possible date`() {
convertUnixToDate("253402300559", "23:55:59 31.12.9999")
}
@Test
fun `2534023005599999 input longe than allowed`() {
convertUnixToDate("2534023005599999", "23:55:59 31.12.9999", IllegalArgumentException())
}
@Test
fun `99999999999999 max possible unix with max length`() {
convertUnixToDate("99999999999999", "23:55:59 31.12.9999", IllegalArgumentException())
}
private fun convertUnixToDate(inputUnix: String, expectedDate: String, throwable: Throwable? = null) {
// Date input comes "fancy"
val cleanExpectedDate = expectedDate.filter{ it.isDigit() }
// Will throw
if (throwable != null) {
assertThrows(
"Failed to throw ${throwable.javaClass} when converting $inputUnix into $expectedDate ($cleanExpectedDate)",
throwable.javaClass
) { EpochDateConverter.convertUnixToDate(inputUnix) }
return
}
// Should actually convert
assertEquals(
"Couldn't convert $inputUnix into $expectedDate ($cleanExpectedDate)",
cleanExpectedDate,
EpochDateConverter.convertUnixToDate(inputUnix)
)
}
}

View File

@ -52,9 +52,15 @@ class EpochViewModel @Inject constructor() : ViewModel() {
dateToUnix = fromDateToUnix dateToUnix = fromDateToUnix
) )
} else { } else {
val date = try {
EpochDateConverter.convertUnixToDate(input)
} catch (e: IllegalArgumentException) {
""
}
EpochUIState( EpochUIState(
unixField = input, unixField = input,
dateField = EpochDateConverter.convertUnixToDate(input), dateField = date,
dateToUnix = fromDateToUnix dateToUnix = fromDateToUnix
) )
} }

View File

@ -4,6 +4,7 @@ appName = "Glaucous"
androidxCore = "1.9.0" androidxCore = "1.9.0"
androidxTest = "1.5.0" androidxTest = "1.5.0"
androidxTestExt = "1.1.4" androidxTestExt = "1.1.4"
androidDesugarJdkLibs = "2.0.0"
junit = "4.13.2" junit = "4.13.2"
androidxTestRunner = "1.5.1" androidxTestRunner = "1.5.1"
androidxTestRules = "1.5.0" androidxTestRules = "1.5.0"
@ -61,6 +62,7 @@ com-squareup-retrofit2 = { group = "com.squareup.retrofit2", name = "converter-m
com-github-sadellie-themmo = { group = "com.github.sadellie", name = "themmo", version.ref = "comGithubSadellieThemmo" } com-github-sadellie-themmo = { group = "com.github.sadellie", name = "themmo", version.ref = "comGithubSadellieThemmo" }
org-burnoutcrew-composereorderable = { group = "org.burnoutcrew.composereorderable", name = "reorderable", version.ref = "orgBurnoutcrewComposereorderable" } org-burnoutcrew-composereorderable = { group = "org.burnoutcrew.composereorderable", name = "reorderable", version.ref = "orgBurnoutcrewComposereorderable" }
com-github-sadellie-exprk = { group = "com.github.sadellie", name = "ExprK", version.ref = "comGithubSadellieExprk" } com-github-sadellie-exprk = { group = "com.github.sadellie", name = "ExprK", version.ref = "comGithubSadellieExprk" }
android-desugarJdkLibs = { group = "com.android.tools", name = "desugar_jdk_libs", version.ref = "androidDesugarJdkLibs" }
# classpath # classpath
android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" }