cache DST offsets so we're not constantly converting time zones
This commit is contained in:
parent
925e98be2c
commit
e5c20acd78
76
movement.c
76
movement.c
@ -40,6 +40,7 @@
|
||||
#include "filesystem.h"
|
||||
#include "shell.h"
|
||||
#include "utz.h"
|
||||
#include "zones.h"
|
||||
|
||||
#include "movement_config.h"
|
||||
|
||||
@ -56,6 +57,9 @@ const int32_t movement_le_inactivity_deadlines[8] = {INT_MAX, 600, 3600, 7200, 2
|
||||
const int16_t movement_timeout_inactivity_deadlines[4] = {60, 120, 300, 1800};
|
||||
movement_event_t event;
|
||||
|
||||
int8_t _movement_dst_offset_cache[NUM_ZONE_NAMES] = {0};
|
||||
#define TIMEZONE_DOES_NOT_OBSERVE (-127)
|
||||
|
||||
const char movement_valid_position_0_chars[] = " AaBbCcDdEeFGgHhIiJKLMNnOoPQrSTtUuWXYZ-='+\\/0123456789";
|
||||
const char movement_valid_position_1_chars[] = " ABCDEFHlJLNORTtUX-='01378";
|
||||
|
||||
@ -84,6 +88,39 @@ static udatetime_t _movement_convert_date_time_to_udate(watch_date_time date_tim
|
||||
};
|
||||
}
|
||||
|
||||
static bool _movement_update_dst_offset_cache(void) {
|
||||
uzone_t local_zone;
|
||||
udatetime_t udate_time;
|
||||
bool dst_changed = false;
|
||||
watch_date_time system_date_time = watch_rtc_get_date_time();
|
||||
|
||||
printf("current zone: %d\n", movement_state.settings.bit.time_zone);
|
||||
|
||||
for (uint8_t i = 0; i < NUM_ZONE_NAMES; i++) {
|
||||
unpack_zone(&zone_defns[i], "", &local_zone);
|
||||
watch_date_time date_time = watch_utility_date_time_convert_zone(system_date_time, 0, local_zone.offset.hours * 3600 + local_zone.offset.minutes * 60);
|
||||
|
||||
if (!!local_zone.rules_len) {
|
||||
// if local zone has DST rules, we need to see if DST applies.
|
||||
udate_time = _movement_convert_date_time_to_udate(date_time);
|
||||
uoffset_t offset;
|
||||
get_current_offset(&local_zone, &udate_time, &offset);
|
||||
int8_t new_offset = (offset.hours * 60 + offset.minutes) / 15;
|
||||
if (_movement_dst_offset_cache[i] != new_offset) {
|
||||
_movement_dst_offset_cache[i] = new_offset;
|
||||
dst_changed = true;
|
||||
}
|
||||
printf("zone %d: %d\n", i, new_offset);
|
||||
} else {
|
||||
// otherwise set the cache to a constant value that indicates no DST check needs to be performed.
|
||||
_movement_dst_offset_cache[i] = TIMEZONE_DOES_NOT_OBSERVE;
|
||||
printf("zone %d: %d\n", i, TIMEZONE_DOES_NOT_OBSERVE);
|
||||
}
|
||||
}
|
||||
|
||||
return dst_changed;
|
||||
}
|
||||
|
||||
static inline void _movement_reset_inactivity_countdown(void) {
|
||||
movement_state.le_mode_ticks = movement_le_inactivity_deadlines[movement_state.settings.bit.le_interval];
|
||||
movement_state.timeout_ticks = movement_timeout_inactivity_deadlines[movement_state.settings.bit.to_interval];
|
||||
@ -107,6 +144,13 @@ static inline void _movement_disable_fast_tick_if_possible(void) {
|
||||
}
|
||||
|
||||
static void _movement_handle_top_of_minute(void) {
|
||||
watch_date_time date_time = watch_rtc_get_date_time();
|
||||
|
||||
// update the DST offset cache every 15 minutes, since someplace in the world could change.
|
||||
if (date_time.unit.minute % 15 == 0) {
|
||||
_movement_update_dst_offset_cache();
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) {
|
||||
// For each face that offers an advisory...
|
||||
if (watch_faces[i].advise != NULL) {
|
||||
@ -327,25 +371,15 @@ uint8_t movement_claim_backup_register(void) {
|
||||
}
|
||||
|
||||
int32_t movement_get_current_timezone_offset_for_zone(uint8_t zone_index) {
|
||||
watch_date_time date_time = watch_rtc_get_date_time();
|
||||
udatetime_t udate_time = _movement_convert_date_time_to_udate(watch_rtc_get_date_time());
|
||||
uzone_t local_zone;
|
||||
int8_t cached_dst_offset = _movement_dst_offset_cache[zone_index];
|
||||
|
||||
// first unpack the zone to get the baseline offset
|
||||
unpack_zone(&zone_defns[zone_index], "", &local_zone);
|
||||
|
||||
// offset the UTC time by that amount to get the local standard time
|
||||
date_time = watch_utility_date_time_convert_zone(date_time, 0, local_zone.offset.hours * 3600 + local_zone.offset.minutes * 60);
|
||||
|
||||
// if local zone has DST rules, we need to see if DST applies.
|
||||
if (local_zone.rules_len) {
|
||||
udate_time = _movement_convert_date_time_to_udate(date_time);
|
||||
uoffset_t offset;
|
||||
get_current_offset(&local_zone, &udate_time, &offset);
|
||||
return offset.hours * 3600 + offset.minutes * 60;
|
||||
if (cached_dst_offset == TIMEZONE_DOES_NOT_OBSERVE) {
|
||||
// if time zone doesn't observe DST, we can just return the standard time offset from the zone definition.
|
||||
return (int32_t)zone_defns[zone_index].offset_inc_minutes * OFFSET_INCREMENT * 60;
|
||||
} else {
|
||||
// otherwise, we've precalculated the offset for this zone and can return it.
|
||||
return (int32_t)cached_dst_offset * OFFSET_INCREMENT * 60;
|
||||
}
|
||||
|
||||
return local_zone.offset.hours * 3600 + local_zone.offset.minutes * 60;
|
||||
}
|
||||
|
||||
int32_t movement_get_current_timezone_offset(void) {
|
||||
@ -378,6 +412,11 @@ void movement_set_local_date_time(watch_date_time date_time) {
|
||||
int32_t current_offset = movement_get_current_timezone_offset();
|
||||
watch_date_time utc_date_time = watch_utility_date_time_convert_zone(date_time, current_offset, 0);
|
||||
watch_rtc_set_date_time(utc_date_time);
|
||||
|
||||
// this may seem wasteful, but if the user's local time is in a zone that observes DST,
|
||||
// they may have just crossed a DST boundary, which means the next call to this function
|
||||
// could require a different offset to force local time back to UTC. Quelle horreur!
|
||||
_movement_update_dst_offset_cache();
|
||||
}
|
||||
|
||||
bool movement_button_should_sound(void) {
|
||||
@ -550,6 +589,9 @@ void app_setup(void) {
|
||||
is_first_launch = false;
|
||||
}
|
||||
|
||||
// populate the DST offset cache
|
||||
_movement_update_dst_offset_cache();
|
||||
|
||||
// set up the 1 minute alarm (for background tasks and low power updates)
|
||||
watch_date_time alarm_time;
|
||||
alarm_time.reg = 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user