diff --git a/app/src/main/java/de/jeanlucmakiola/clockula/domain/worldclock/ZoneCatalog.kt b/app/src/main/java/de/jeanlucmakiola/clockula/domain/worldclock/ZoneCatalog.kt index cfdbac1..fd397dc 100644 --- a/app/src/main/java/de/jeanlucmakiola/clockula/domain/worldclock/ZoneCatalog.kt +++ b/app/src/main/java/de/jeanlucmakiola/clockula/domain/worldclock/ZoneCatalog.kt @@ -57,7 +57,8 @@ object ZoneCatalog { /** * The last `/`-segment with underscores replaced by spaces, trimmed; the - * input trimmed when that is blank. Never throws. + * input trimmed when that is blank. `Etc/GMT±n` is the exception: it is + * named by its real offset instead. Never throws. */ fun cityFallbackFor(zoneId: String): String { etcOffsetName(zoneId)?.let { return it } @@ -74,11 +75,12 @@ object ZoneCatalog { private fun etcOffsetName(zoneId: String): String? { val match = ETC_OFFSET.matchEntire(zoneId.trim()) ?: return null val hours = match.groupValues[2].toInt() - if (hours == 0) return "GMT" - val sign = if (match.groupValues[1] == "-") "+" else "-" - return "GMT$sign$hours" + val sign = if (match.groupValues[1] == "-") 1 else -1 + return ZoneOffsetFormat.gmtLabel(sign * hours * MINUTES_PER_HOUR) } + private const val MINUTES_PER_HOUR = 60 + private val ETC_OFFSET = Regex("""Etc/GMT([+-])(\d{1,2})""") /** By `ZoneSearch.fold(city)` ascending, then [ZoneEntry.zoneId] ascending. */ diff --git a/app/src/main/java/de/jeanlucmakiola/clockula/ui/worldclock/WorldClockRowState.kt b/app/src/main/java/de/jeanlucmakiola/clockula/ui/worldclock/WorldClockRowState.kt index d54e877..cbd1fda 100644 --- a/app/src/main/java/de/jeanlucmakiola/clockula/ui/worldclock/WorldClockRowState.kt +++ b/app/src/main/java/de/jeanlucmakiola/clockula/ui/worldclock/WorldClockRowState.kt @@ -18,7 +18,7 @@ import kotlin.time.toJavaInstant internal data class WorldClockRowState( val id: Long, val zoneId: String, - /** The user's label when set, else the ICU city, else the id's last segment. Never blank. */ + /** The user's label when set, else the ICU city, else `ZoneCatalog.cityFallbackFor`. Never blank. */ val name: String, /** Truncated to the minute. Non-null **exactly** when [known]. */ val time: LocalTime?, diff --git a/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/ClockPrefsTest.kt b/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/ClockPrefsTest.kt index 869cca3..de4bf47 100644 --- a/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/ClockPrefsTest.kt +++ b/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/ClockPrefsTest.kt @@ -53,6 +53,7 @@ class ClockPrefsTest { prefs.setTimerRingtoneUri("content://t") prefs.setDismissChallenge(DismissChallenge.HOLD) prefs.setHomeZoneId("Europe/Berlin") + prefs.setAutomaticLocalClock(false) assertThat(prefs.defaults.first()).isEqualTo( ClockDefaults( @@ -64,6 +65,7 @@ class ClockPrefsTest { timerRingtoneUri = "content://t", dismissChallenge = DismissChallenge.HOLD, homeZoneId = "Europe/Berlin", + automaticLocalClock = false, ), ) } diff --git a/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt b/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt index 71ead3e..82ddb9d 100644 --- a/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt +++ b/app/src/test/java/de/jeanlucmakiola/clockula/data/prefs/SettingsPrefsTest.kt @@ -74,7 +74,12 @@ class SettingsPrefsTest { BackupSettings( themeMode = ThemeMode.DARK, dynamicColor = false, - defaults = ClockDefaults(snoozeMinutes = 99, volumeRampSeconds = 99, alarmRingtoneUri = " "), + defaults = ClockDefaults( + snoozeMinutes = 99, + volumeRampSeconds = 99, + alarmRingtoneUri = " ", + automaticLocalClock = false, + ), timerPresets = listOf(5.minutes, 1.minutes, 5.minutes), ), ) @@ -84,6 +89,7 @@ class SettingsPrefsTest { assertThat(prefs.currentDefaults().snoozeMinutes).isEqualTo(60) assertThat(prefs.currentDefaults().volumeRampSeconds).isEqualTo(60) assertThat(prefs.currentDefaults().alarmRingtoneUri).isNull() + assertThat(prefs.currentDefaults().automaticLocalClock).isFalse() assertThat(prefs.timerPresets.first()).containsExactly(1.minutes, 5.minutes).inOrder() }