From a99972f6b8b13e21a54df418eea1b39e0d582342 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sat, 21 Sep 2024 19:36:09 +0200 Subject: [PATCH] fix: alarm rings at wrong time on summer/winter time change --- .../java/com/bnyro/clock/util/AlarmHelper.kt | 16 ++++++++ .../java/com/bnyro/clock/SummerTimeTest.kt | 37 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 app/src/test/java/com/bnyro/clock/SummerTimeTest.kt diff --git a/app/src/main/java/com/bnyro/clock/util/AlarmHelper.kt b/app/src/main/java/com/bnyro/clock/util/AlarmHelper.kt index f7b762a5..a8b980c7 100644 --- a/app/src/main/java/com/bnyro/clock/util/AlarmHelper.kt +++ b/app/src/main/java/com/bnyro/clock/util/AlarmHelper.kt @@ -17,6 +17,7 @@ import java.util.GregorianCalendar object AlarmHelper { const val EXTRA_ID = "alarm_id" + private const val HOUR_IN_MILLIS = 60 * 60 * 1000 @SuppressLint("ScheduleExactAlarm") fun enqueue(context: Context, alarm: Alarm) { @@ -79,9 +80,24 @@ object AlarmHelper { calendar.add(Calendar.MILLISECOND, alarm.time.toInt()) calendar.add(Calendar.DATE, getPostponeDays(alarm, calendar)) + + fixDaylightTime(calendar) + return calendar.timeInMillis } + fun fixDaylightTime(calendar: GregorianCalendar) { + val now = TimeHelper.currentTime + + if (calendar.timeZone.useDaylightTime()) { + if (calendar.timeZone.inDaylightTime(now) && !calendar.timeZone.inDaylightTime(calendar.time)) { + calendar.timeInMillis += HOUR_IN_MILLIS + } else if (!calendar.timeZone.inDaylightTime(now) && calendar.timeZone.inDaylightTime(calendar.time)) { + calendar.timeInMillis -= HOUR_IN_MILLIS + } + } + } + private fun getPostponeDays(alarm: Alarm, calendar: GregorianCalendar): Int { if (alarm.days.isEmpty() && alarm.repeat) return 0 diff --git a/app/src/test/java/com/bnyro/clock/SummerTimeTest.kt b/app/src/test/java/com/bnyro/clock/SummerTimeTest.kt new file mode 100644 index 00000000..9cadb4a2 --- /dev/null +++ b/app/src/test/java/com/bnyro/clock/SummerTimeTest.kt @@ -0,0 +1,37 @@ +package com.bnyro.clock + +import com.bnyro.clock.util.AlarmHelper +import org.junit.Test +import java.util.Date +import java.util.GregorianCalendar +import java.util.TimeZone + +class SummerTimeTest { + @Test + fun scheduleWithSummerTime() { + TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin")) + val date = Date(Date.UTC(2024, 10, 30, 15, 0, 0)) + val calendar = GregorianCalendar() + calendar.time = date + val millis = calendar.timeInMillis + AlarmHelper.fixDaylightTime(calendar) + + if (calendar.timeZone.inDaylightTime(calendar.time)) { + assert(millis == calendar.timeInMillis + 60 * 60 * 1000L) + } else { + assert(millis == calendar.timeInMillis - 60 * 60 * 1000L) + } + } + + @Test + fun scheduleWithoutDaylightDiff() { + TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin")) + val date = Date() + val calendar = GregorianCalendar() + calendar.time = date + val millis = calendar.timeInMillis + AlarmHelper.fixDaylightTime(calendar) + + assert(millis == calendar.timeInMillis) + } +} \ No newline at end of file