diff --git a/Documentation/card10-cfg.rst b/Documentation/card10-cfg.rst index d60b4c552ebf3e43ffea33073f5981ba75b531fe..3b3fdf7ab2f25229a314f96734b4cfe613c3abbf 100644 --- a/Documentation/card10-cfg.rst +++ b/Documentation/card10-cfg.rst @@ -38,4 +38,6 @@ Supported options Option name Type Description =============== ========== =========== ``execute_elf`` Boolean Allow running of binary :ref:`l0dables`. These files can be nefarious, so this option is off by default. +--------------- ---------- ----------- +``timezone`` String Timezone for card10; must be of format ``[+-]HHMM``. Examples: ``+0800``, ``-0200`` =============== ========== =========== diff --git a/pycardium/modules/utime.c b/pycardium/modules/utime.c index d29708205e24a1b6f2c16e8b64b6d340feedb205..1ca16df77c3a66fb8f117d31988ed44b3faac77c 100644 --- a/pycardium/modules/utime.c +++ b/pycardium/modules/utime.c @@ -9,7 +9,9 @@ #include "py/runtime.h" #include "extmod/utime_mphal.h" +#include <string.h> #include <stdint.h> +#include <stdlib.h> // Needs to be after the stdint include ... #include "lib/timeutils/timeutils.h" @@ -17,13 +19,45 @@ /* MicroPython has its epoch at 2000-01-01. Our RTC is in UTC */ #define EPOCH_OFFSET 946684800UL -/* Fixed time zone: CET */ +/* Default time zone: CET */ #define TZONE_OFFSET 3600UL +static uint32_t time_get_timezone_offset(void) +{ + static uint32_t offset = INT32_MAX; + + /* Only read the timezone setting once after starting + * the interpeter to not impact performance */ + if (offset == INT32_MAX) { + offset = TZONE_OFFSET; + + char buf[128]; + int ret = epic_config_get_string("timezone", buf, sizeof(buf)); + + /* Understands formats like +0100, 0100, 100, -0800 */ + if (ret == 0 && strlen(buf) > 0) { + errno = 0; + long int timezone = strtol(buf, NULL, 10); + int sign = 1; + if (timezone < 0) { + sign = -1; + timezone = -timezone; + } + if (errno == 0) { + offset = (timezone / 100) * 3600; + offset += (timezone % 100) * 60; + offset *= sign; + } + } + } + return offset; +} + static mp_obj_t time_set_time(mp_obj_t secs) { uint64_t timestamp = mp_obj_get_int(secs) * 1000ULL + - EPOCH_OFFSET * 1000ULL - TZONE_OFFSET * 1000ULL; + EPOCH_OFFSET * 1000ULL - + time_get_timezone_offset() * 1000ULL; epic_rtc_set_milliseconds(timestamp); return mp_const_none; } @@ -33,8 +67,8 @@ static mp_obj_t time_set_time_ms(mp_obj_t msecs_obj) { uint64_t msecs = 0; mp_obj_int_to_bytes_impl(msecs_obj, false, 8, (byte *)&msecs); - uint64_t timestamp = - msecs + EPOCH_OFFSET * 1000ULL - TZONE_OFFSET * 1000ULL; + uint64_t timestamp = msecs + EPOCH_OFFSET * 1000ULL - + time_get_timezone_offset() * 1000ULL; epic_rtc_set_milliseconds(timestamp); return mp_const_none; } @@ -62,7 +96,8 @@ static MP_DEFINE_CONST_FUN_OBJ_1( static mp_obj_t time_time(void) { mp_int_t seconds; - seconds = epic_rtc_get_seconds() - EPOCH_OFFSET + TZONE_OFFSET; + seconds = epic_rtc_get_seconds() - EPOCH_OFFSET + + time_get_timezone_offset(); return mp_obj_new_int(seconds); } MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); @@ -71,7 +106,7 @@ static mp_obj_t time_time_ms(void) { uint64_t milliseconds; milliseconds = epic_rtc_get_milliseconds() - EPOCH_OFFSET * 1000ULL + - TZONE_OFFSET * 1000ULL; + time_get_timezone_offset() * 1000ULL; return mp_obj_new_int_from_ull(milliseconds); } MP_DEFINE_CONST_FUN_OBJ_0(time_time_ms_obj, time_time_ms); @@ -111,7 +146,8 @@ static mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) mp_int_t seconds; if (n_args == 0 || args[0] == mp_const_none) { - seconds = epic_rtc_get_seconds() - EPOCH_OFFSET + TZONE_OFFSET; + seconds = epic_rtc_get_seconds() - EPOCH_OFFSET + + time_get_timezone_offset(); } else { seconds = mp_obj_get_int(args[0]); } @@ -163,8 +199,8 @@ static MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); /* Schedule an alarm */ static mp_obj_t time_alarm(size_t n_args, const mp_obj_t *args) { - mp_int_t timestamp = - mp_obj_get_int(args[0]) + EPOCH_OFFSET - TZONE_OFFSET; + mp_int_t timestamp = mp_obj_get_int(args[0]) + EPOCH_OFFSET - + time_get_timezone_offset(); if (n_args == 2) { /* If a callback was given, register it for the RTC Alarm */ mp_obj_t callback = args[1];