summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Leech <andrew.leech@planetinnovation.com.au>2019-11-26 11:02:19 +1100
committerDamien George <damien.p.george@gmail.com>2019-12-28 11:11:54 +1100
commit1b844e908c3a867be1e54efdb86a04c6a62b2f26 (patch)
treebed11a7695c36120d49887a0076336c1c669a7c1
parentb23bd6433cd68830d32c0c68dbbf554942bb6ad0 (diff)
unix/modtime: Add utime.mktime function, to complement utime.localtime.
This also adds it to the windows port.
-rw-r--r--ports/unix/modtime.c32
-rw-r--r--tests/unix/time.py44
2 files changed, 76 insertions, 0 deletions
diff --git a/ports/unix/modtime.c b/ports/unix/modtime.c
index 0a463014d..479d2a79d 100644
--- a/ports/unix/modtime.c
+++ b/ports/unix/modtime.c
@@ -161,6 +161,37 @@ STATIC mp_obj_t mod_time_localtime(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_time_localtime_obj, 0, 1, mod_time_localtime);
+STATIC mp_obj_t mod_time_mktime(mp_obj_t tuple) {
+ size_t len;
+ mp_obj_t *elem;
+ mp_obj_get_array(tuple, &len, &elem);
+
+ // localtime generates a tuple of len 8. CPython uses 9, so we accept both.
+ if (len < 8 || len > 9) {
+ mp_raise_TypeError("mktime needs a tuple of length 8 or 9");
+ }
+
+ struct tm time = {
+ .tm_year = mp_obj_get_int(elem[0]) - 1900,
+ .tm_mon = mp_obj_get_int(elem[1]) - 1,
+ .tm_mday = mp_obj_get_int(elem[2]),
+ .tm_hour = mp_obj_get_int(elem[3]),
+ .tm_min = mp_obj_get_int(elem[4]),
+ .tm_sec = mp_obj_get_int(elem[5]),
+ };
+ if (len == 9) {
+ time.tm_isdst = mp_obj_get_int(elem[8]);
+ } else {
+ time.tm_isdst = -1; // auto-detect
+ }
+ time_t ret = mktime(&time);
+ if (ret == -1) {
+ mp_raise_msg(&mp_type_OverflowError, "invalid mktime usage");
+ }
+ return mp_obj_new_int(ret);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(mod_time_mktime_obj, mod_time_mktime);
+
STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) },
{ MP_ROM_QSTR(MP_QSTR_clock), MP_ROM_PTR(&mod_time_clock_obj) },
@@ -174,6 +205,7 @@ STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) },
{ MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) },
{ MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&mod_time_localtime_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&mod_time_mktime_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table);
diff --git a/tests/unix/time.py b/tests/unix/time.py
new file mode 100644
index 000000000..a96c3f5b6
--- /dev/null
+++ b/tests/unix/time.py
@@ -0,0 +1,44 @@
+try:
+ import utime as time
+except ImportError:
+ import time
+
+DAYS_PER_MONTH = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+
+tzseconds = -time.mktime((1970, 1, 1, 0, 0, 0, 0, 0, 0))
+
+def is_leap(year):
+ return (year % 4) == 0
+
+def test():
+ seconds = 0
+ wday = 3 # Jan 1, 1970 was a Thursday
+ for year in range(1970, 2038):
+ print("Testing %d" % year)
+ yday = 1
+ for month in range(1, 13):
+ if month == 2 and is_leap(year):
+ DAYS_PER_MONTH[2] = 29
+ else:
+ DAYS_PER_MONTH[2] = 28
+ for day in range(1, DAYS_PER_MONTH[month] + 1):
+ secs = time.mktime((year, month, day, 0, 0, 0, 0, 0, 0)) + tzseconds
+ if secs != seconds:
+ print("mktime failed for %d-%02d-%02d got %d expected %d" % (year, month, day, secs, seconds))
+ return
+ tuple = time.localtime(seconds)
+ secs = time.mktime(tuple)
+ if secs != seconds:
+ print("localtime failed for %d-%02d-%02d got %d expected %d" % (year, month, day, secs, seconds))
+ return
+ seconds += 86400
+ if yday != tuple[7]:
+ print("locatime for %d-%02d-%02d got yday %d, expecting %d" % (year, month, day, tuple[7], yday))
+ return
+ if wday != tuple[6]:
+ print("locatime for %d-%02d-%02d got wday %d, expecting %d" % (year, month, day, tuple[6], wday))
+ return
+ yday += 1
+ wday = (wday + 1) % 7
+
+test()