]> git.earman.xyz Git - sensor-watch.git/commitdiff
Time now auto-updates with DST
authorDavid Volovskiy <devolov@gmail.com>
Fri, 2 Aug 2024 05:23:21 +0000 (01:23 -0400)
committerDavid Volovskiy <devolov@gmail.com>
Fri, 2 Aug 2024 05:23:21 +0000 (01:23 -0400)
movement/movement.c
movement/movement.h
movement/watch_faces/clock/clock_face.c
movement/watch_faces/clock/simple_clock_face.c
movement/watch_faces/settings/set_time_face.c
watch-library/shared/watch/watch_utility.c
watch-library/shared/watch/watch_utility.h

index 8b45535fc52db70b737bf0cb963aa3d1739dd879..5c804fe6e3a821e27e876734134595ad14331d12 100644 (file)
@@ -34,6 +34,7 @@
 #include "filesystem.h"
 #include "movement.h"
 #include "shell.h"
+#include "watch_utility.h"
 
 #ifndef MOVEMENT_FIRMWARE
 #include "movement_config.h"
@@ -467,6 +468,21 @@ uint8_t movement_claim_backup_register(void) {
     return movement_state.next_available_backup_register++;
 }
 
+int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time) {
+    if (!movement_state.settings.bit.dst_active) return movement_timezone_offsets[timezone_idx];
+    uint8_t dst_result = is_dst(date_time);
+    switch (dst_result)
+    {
+    case DST_STARTED:
+    case DST_OCCURRING:
+        return movement_timezone_offsets[movement_dst_jump_table[timezone_idx]];
+    case DST_ENDING:
+    case DST_ENDED:
+    default:
+        return movement_timezone_offsets[timezone_idx];
+    }
+}
+
 void app_init(void) {
 #if defined(NO_FREQCORR)
     watch_rtc_freqcorr_write(0, 0);
index d19ab3fc52ec2f0268c4e4ba9205dbcbc834401a..a89e3778665405c323ecbb9618695f7b9e962baf 100644 (file)
@@ -314,5 +314,6 @@ void movement_play_alarm(void);
 void movement_play_alarm_beeps(uint8_t rounds, BuzzerNote alarm_note);
 
 uint8_t movement_claim_backup_register(void);
+int16_t get_timezone_offset(uint8_t timezone_idx, watch_date_time date_time);
 
 #endif // MOVEMENT_H_
index eab5cd8d3f9f9d9b160d40cb9c5e24f79fc18b35..68019d8582b3985a292ba6624faafe653231ceb1 100644 (file)
@@ -280,12 +280,28 @@ void clock_face_resign(movement_settings_t *settings, void *context) {
     (void) context;
 }
 
+static void check_and_act_on_daylight_savings(bool dst_active, watch_date_time date_time) {
+    if (!dst_active) return;
+    uint8_t dst_result = is_dst(date_time);
+    switch (dst_result)
+    {
+    case DST_STARTED:
+        date_time.unit.hour = (date_time.unit.hour + 1) % 24;
+        break;
+    case DST_ENDING:
+        date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24;
+        break;
+    default:
+        return;
+    }
+    watch_rtc_set_date_time(date_time);
+}
+
 bool clock_face_wants_background_task(movement_settings_t *settings, void *context) {
-    (void) settings;
     clock_state_t *state = (clock_state_t *) context;
-    if (!state->time_signal_enabled) return false;
-
     watch_date_time date_time = watch_rtc_get_date_time();
+    check_and_act_on_daylight_savings(settings->bit.dst_active, date_time);
+    if (!state->time_signal_enabled) return false;
 
     return date_time.unit.minute == 0;
 }
index fbc2c4b3ea71aefb8b32615b8c413e1cd2c8a0f5..c0f837238646ca0cb61ea9dd5863125ae4bcf76c 100644 (file)
@@ -150,12 +150,28 @@ void simple_clock_face_resign(movement_settings_t *settings, void *context) {
     (void) context;
 }
 
+static void check_and_act_on_daylight_savings(bool dst_active, watch_date_time date_time) {
+    if (!dst_active) return;
+    uint8_t dst_result = is_dst(date_time);
+    switch (dst_result)
+    {
+    case DST_STARTED:
+        date_time.unit.hour = (date_time.unit.hour + 1) % 24;
+        break;
+    case DST_ENDING:
+        date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24;
+        break;
+    default:
+        return;
+    }
+    watch_rtc_set_date_time(date_time);
+}
+
 bool simple_clock_face_wants_background_task(movement_settings_t *settings, void *context) {
-    (void) settings;
     simple_clock_state_t *state = (simple_clock_state_t *)context;
-    if (!state->signal_enabled) return false;
-
     watch_date_time date_time = watch_rtc_get_date_time();
+    check_and_act_on_daylight_savings(settings->bit.dst_active, date_time);
+    if (!state->signal_enabled) return false;
 
     return date_time.unit.minute == 0;
 }
index fb0c80640872167e8d695fdb1df867187d91af31..90edac250de6633b735a3ffb354a5dd29ec099f7 100644 (file)
@@ -67,13 +67,6 @@ static void _handle_alarm_button(movement_settings_t *settings, watch_date_time
             if (settings->bit.time_zone > 40) settings->bit.time_zone = 0;
             break;
         case 7: // daylight savings time
-            if (settings->bit.dst_active) {  // deactivate DST
-                date_time.unit.hour = (date_time.unit.hour + 24 - 1) % 24;
-                settings->bit.time_zone = movement_dst_inverse_jump_table[settings->bit.time_zone];
-            } else {  // activate DST
-                date_time.unit.hour = (date_time.unit.hour + 1) % 24;
-                settings->bit.time_zone = movement_dst_jump_table[settings->bit.time_zone];
-            }
             settings->bit.dst_active = !settings->bit.dst_active;
             break;
     }
@@ -161,8 +154,9 @@ bool set_time_face_loop(movement_event_t event, movement_settings_t *settings, v
             watch_clear_colon();
             sprintf(buf, "%s        ", set_time_face_titles[current_page]);
         } else {
+            int16_t tz = get_timezone_offset(settings->bit.time_zone, date_time);
             watch_set_colon();
-            sprintf(buf, "%s %3d%02d  ", set_time_face_titles[current_page], (int8_t) (movement_timezone_offsets[settings->bit.time_zone] / 60), (int8_t) (movement_timezone_offsets[settings->bit.time_zone] % 60) * (movement_timezone_offsets[settings->bit.time_zone] < 0 ? -1 : 1));
+            sprintf(buf, "%s %3d%02d  ", set_time_face_titles[current_page], (int8_t) (tz / 60), (int8_t) (tz % 60) * (tz < 0 ? -1 : 1));
         }
     } else { // daylight savings
         watch_clear_colon();
index 64b3bb791cfcd06ebe8f60542e326b7499b633df..1410e41413be219bcefda935324531412470eede 100644 (file)
@@ -83,6 +83,39 @@ uint8_t is_leap(uint16_t y)
        return !(y%4) && ((y%100) || !(y%400));
 }
 
+uint8_t is_dst(watch_date_time date_time) {
+    uint8_t weekday_first_of_month;
+    watch_date_time dst_start_time;
+    watch_date_time dst_end_time;
+    uint32_t unix_dst_start_time;
+    uint32_t unix_dst_end_time;
+    uint32_t unix_curr_time;
+
+    dst_start_time.unit.month = 3;
+    dst_start_time.unit.hour = 2;
+    dst_start_time.unit.minute = 0;
+    dst_start_time.unit.second = 0;
+    weekday_first_of_month = watch_utility_get_iso8601_weekday_number(date_time.unit.year, dst_start_time.unit.month, 1);
+    dst_start_time.unit.day = 15 - weekday_first_of_month;
+    unix_dst_start_time = watch_utility_date_time_to_unix_time(dst_start_time, 0);
+
+    dst_end_time.unit.month = 11;
+    dst_end_time.unit.hour = 2;
+    dst_end_time.unit.minute = 0;
+    dst_end_time.unit.second = 0;
+    weekday_first_of_month = watch_utility_get_iso8601_weekday_number(date_time.unit.year, dst_end_time.unit.month, 1);
+    dst_end_time.unit.day = 15 - weekday_first_of_month;
+    unix_dst_end_time = watch_utility_date_time_to_unix_time(dst_end_time, 0);
+
+    date_time.unit.second = 0;
+    unix_curr_time = watch_utility_date_time_to_unix_time(date_time, 0);
+
+    if (unix_curr_time == unix_dst_start_time) return DST_STARTED;
+    if (unix_curr_time == unix_dst_end_time) return DST_ENDING;
+    if (unix_curr_time > unix_dst_end_time || unix_curr_time < unix_dst_start_time) return DST_ENDED;
+    return DST_OCCURRING;
+} 
+
 uint16_t watch_utility_days_since_new_year(uint16_t year, uint8_t month, uint8_t day) {
     uint16_t DAYS_SO_FAR[] = {
         0,   // Jan
index e2326d1318865fa34c7c3bba517a1def054b06ef..d3f3981a466ac062fe5be7f3d04d7591a379a7d7 100644 (file)
@@ -45,6 +45,13 @@ typedef struct {
     uint32_t days;    // 0-4294967295
 } watch_duration_t;
 
+typedef enum {
+    DST_STARTED,
+    DST_OCCURRING,
+    DST_ENDING,
+    DST_ENDED
+} dst_t;
+
 /** @brief Returns a two-letter weekday for the given timestamp, suitable for display
   *        in positions 0-1 of the watch face
   * @param date_time The watch_date_time whose weekday you want.
@@ -78,6 +85,12 @@ uint16_t watch_utility_days_since_new_year(uint16_t year, uint8_t month, uint8_t
  */
 uint8_t is_leap(uint16_t year);
 
+/** @brief Returns off of dst_t based off if DST is occurring, srted, ended, or none of those.
+ * @param date_time The watch_date_time that you wish to convert.
+ * @return DST_OCCURRING, DST_HAPPENING, DST_ENDING, DST_ENDED
+ */
+uint8_t is_dst(watch_date_time date_time);
+
 /** @brief Returns the UNIX time (seconds since 1970) for a given date/time in UTC.
   * @param date_time The watch_date_time that you wish to convert.
   * @param year The year of the date you wish to convert.