feat(core): implement conversion from timestamp to datetime

pull/1879/head
matejcik 3 years ago committed by matejcik
parent e972839ac7
commit 1d72085b5c

@ -0,0 +1 @@
Convert timestamps to human-readable dates and times.

@ -197,7 +197,7 @@ if NEW_UI:
# modutime
SOURCE_MOD += [
'embed/firmware/modutime.c',
'embed/extmod/modutime.c',
]
SOURCE_MICROPYTHON = [
@ -208,12 +208,12 @@ SOURCE_MICROPYTHON = [
'vendor/micropython/extmod/utime_mphal.c',
'vendor/micropython/shared/libc/abort_.c',
'vendor/micropython/shared/libc/printf.c',
#'vendor/micropython/shared/readline/readline.c',
'vendor/micropython/shared/runtime/gchelper_m3.s',
'vendor/micropython/shared/runtime/gchelper_native.c',
'vendor/micropython/shared/runtime/interrupt_char.c',
'vendor/micropython/shared/runtime/pyexec.c',
'vendor/micropython/shared/runtime/stdout_helpers.c',
'vendor/micropython/shared/timeutils/timeutils.c',
'vendor/micropython/ports/stm32/gccollect.c',
'vendor/micropython/ports/stm32/pendsv.c',
'vendor/micropython/ports/stm32/softtimer.c',

@ -194,7 +194,7 @@ if NEW_UI:
# modutime
SOURCE_MOD += [
'vendor/micropython/ports/unix/modtime.c',
'embed/extmod/modutime.c',
]
SOURCE_MICROPYTHON = [
@ -204,6 +204,7 @@ SOURCE_MICROPYTHON = [
'vendor/micropython/extmod/modutimeq.c',
'vendor/micropython/extmod/utime_mphal.c',
'vendor/micropython/shared/readline/readline.c',
'vendor/micropython/shared/timeutils/timeutils.c',
'vendor/micropython/ports/unix/modos.c',
'vendor/micropython/py/argcheck.c',
'vendor/micropython/py/asmarm.c',

@ -25,10 +25,33 @@
*/
#include "extmod/utime_mphal.h"
#include "shared/timeutils/timeutils.h"
// copy of ports/stm32/modutime.c:time_localtime, without support
// for getting current clock time (i.e., timestamp must always be provided)
STATIC mp_obj_t time_gmtime2000(mp_obj_t timestamp) {
mp_int_t seconds = mp_obj_get_int(timestamp);
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
mp_obj_t tuple[8] = {
tuple[0] = mp_obj_new_int(tm.tm_year),
tuple[1] = mp_obj_new_int(tm.tm_mon),
tuple[2] = mp_obj_new_int(tm.tm_mday),
tuple[3] = mp_obj_new_int(tm.tm_hour),
tuple[4] = mp_obj_new_int(tm.tm_min),
tuple[5] = mp_obj_new_int(tm.tm_sec),
tuple[6] = mp_obj_new_int(tm.tm_wday),
tuple[7] = mp_obj_new_int(tm.tm_yday),
};
return mp_obj_new_tuple(8, tuple);
}
MP_DEFINE_CONST_FUN_OBJ_1(time_gmtime2000_obj, time_gmtime2000);
STATIC const mp_rom_map_elem_t time_module_globals_table[] = {
{MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime)},
{MP_ROM_QSTR(MP_QSTR_gmtime2000), MP_ROM_PTR(&time_gmtime2000_obj)},
{MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj)},
{MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj)},
{MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj)},
@ -46,4 +69,4 @@ const mp_obj_module_t mp_module_utime = {
.globals = (mp_obj_dict_t*)&time_module_globals,
};
MP_REGISTER_MODULE(MP_QSTR_utime, mp_module_utime, MICROPY_PY_UTIME_MP_HAL);
MP_REGISTER_MODULE(MP_QSTR_utime, mp_module_utime, MICROPY_PY_UTIME);

@ -141,6 +141,7 @@
#define MICROPY_PY_URANDOM (0)
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (0)
#define MICROPY_PY_USELECT (0)
#define MICROPY_PY_UTIME (1)
#define MICROPY_PY_UTIMEQ (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
#define MICROPY_PY_OS_DUPTERM (0)

@ -205,13 +205,9 @@ extern const struct _mp_print_t mp_stderr_print;
// extra built in modules to add to the list of known ones
extern const struct _mp_obj_module_t mp_module_os;
// on unix, we use time, not utime
extern const struct _mp_obj_module_t mp_module_time;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, \
{ MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_time) },
{ MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) },
// For size_t and ssize_t

@ -6,3 +6,4 @@ def ticks_us() -> int: ...
def ticks_cpu() -> int: ...
def ticks_add(ticks_in: int, delta_in: int) -> int: ...
def ticks_diff(old: int, new: int) -> int: ...
def gmtime2000(timestamp: int) -> tuple: ...

@ -1,3 +1,9 @@
import utime
from micropython import const
_SECONDS_1970_TO_2000 = const(946684800)
def format_amount(amount: int, decimals: int) -> str:
if amount < 0:
amount = -amount
@ -60,3 +66,20 @@ def format_duration_ms(milliseconds: int) -> str:
divisor = 1
return format_plural("{count} {plural}", milliseconds // divisor, unit)
def format_timestamp(timestamp: int) -> str:
"""
Returns human-friendly representation of a unix timestamp (in seconds format).
Minutes and seconds are always displayed as 2 digits.
Example:
>>> format_timestamp_to_human(0)
'1970-01-01 00:00:00'
>>> format_timestamp_to_human(1616051824)
'2021-03-18 07:17:04'
"""
# By doing the conversion to 2000-based epoch in Python, we take advantage of the
# bignum implementation, and get another 30 years out of the 32-bit mp_int_t
# that is used internally.
d = utime.gmtime2000(timestamp - _SECONDS_1970_TO_2000)
return f"{d[0]}-{d[1]:02d}-{d[2]:02d} {d[3]:02d}:{d[4]:02d}:{d[5]:02d}"

@ -53,6 +53,101 @@ class TestStrings(unittest.TestCase):
for v in VECTORS:
self.assertEqual(strings.format_duration_ms(v[0]), v[1])
def test_format_timestamp(self):
VECTORS = [
(0, "1970-01-01 00:00:00"),
(123456, "1970-01-02 10:17:36"),
(246912, "1970-01-03 20:35:12"),
(370368, "1970-01-05 06:52:48"),
(493824, "1970-01-06 17:10:24"),
(10000, "1970-01-01 02:46:40"),
(12355678, "1970-05-24 00:07:58"),
(24701356, "1970-10-13 21:29:16"),
(37047034, "1971-03-05 18:50:34"),
(49392712, "1971-07-26 16:11:52"),
(1610057224, "2021-01-07 22:07:04"),
(1610806549, "2021-01-16 14:15:49"),
(1611555874, "2021-01-25 06:24:34"),
(1612305199, "2021-02-02 22:33:19"),
(1613054524, "2021-02-11 14:42:04"),
(1613803849, "2021-02-20 06:50:49"),
(1614553174, "2021-02-28 22:59:34"),
(1615302499, "2021-03-09 15:08:19"),
(1616051824, "2021-03-18 07:17:04"),
(1616801149, "2021-03-26 23:25:49"),
(1617550474, "2021-04-04 15:34:34"),
(1618299799, "2021-04-13 07:43:19"),
(1619049124, "2021-04-21 23:52:04"),
(1619798449, "2021-04-30 16:00:49"),
(1620547774, "2021-05-09 08:09:34"),
(1621297099, "2021-05-18 00:18:19"),
(1622046424, "2021-05-26 16:27:04"),
(1622795749, "2021-06-04 08:35:49"),
(1623545074, "2021-06-13 00:44:34"),
(1624294399, "2021-06-21 16:53:19"),
(1625043724, "2021-06-30 09:02:04"),
(1625793049, "2021-07-09 01:10:49"),
(1626542374, "2021-07-17 17:19:34"),
(1627291699, "2021-07-26 09:28:19"),
(1628041024, "2021-08-04 01:37:04"),
(1628790349, "2021-08-12 17:45:49"),
(1629539674, "2021-08-21 09:54:34"),
(1630288999, "2021-08-30 02:03:19"),
(1631038324, "2021-09-07 18:12:04"),
(1631787649, "2021-09-16 10:20:49"),
(1632536974, "2021-09-25 02:29:34"),
(1633286299, "2021-10-03 18:38:19"),
(1634035624, "2021-10-12 10:47:04"),
(1634784949, "2021-10-21 02:55:49"),
(1635534274, "2021-10-29 19:04:34"),
(1636283599, "2021-11-07 11:13:19"),
(1637032924, "2021-11-16 03:22:04"),
(1637782249, "2021-11-24 19:30:49"),
(1638531574, "2021-12-03 11:39:34"),
(1639280899, "2021-12-12 03:48:19"),
(1640030224, "2021-12-20 19:57:04"),
(1640779549, "2021-12-29 12:05:49"),
(1641528874, "2022-01-07 04:14:34"),
(976838400, "2000-12-15 00:00:00"),
(976838399, "2000-12-14 23:59:59"),
(976838401, "2000-12-15 00:00:01"),
(1119398400, "2005-06-22 00:00:00"),
(1119398399, "2005-06-21 23:59:59"),
(1119398401, "2005-06-22 00:00:01"),
(1261958400, "2009-12-28 00:00:00"),
(1261958399, "2009-12-27 23:59:59"),
(1261958401, "2009-12-28 00:00:01"),
(1404518400, "2014-07-05 00:00:00"),
(1404518399, "2014-07-04 23:59:59"),
(1404518401, "2014-07-05 00:00:01"),
(1547078400, "2019-01-10 00:00:00"),
(1547078399, "2019-01-09 23:59:59"),
(1547078401, "2019-01-10 00:00:01"),
(1689638400, "2023-07-18 00:00:00"),
(1689638399, "2023-07-17 23:59:59"),
(1689638401, "2023-07-18 00:00:01"),
(1832198400, "2028-01-23 00:00:00"),
(1832198399, "2028-01-22 23:59:59"),
(1832198401, "2028-01-23 00:00:01"),
(1891987200, "2029-12-15 00:00:00"),
(1891987199, "2029-12-14 23:59:59"),
(1891987201, "2029-12-15 00:00:01"),
(2747347200, "2057-01-22 00:00:00"),
(2747347199, "2057-01-21 23:59:59"),
(2747347201, "2057-01-22 00:00:01"),
(3602707200, "2084-03-01 00:00:00"),
(3602707199, "2084-02-29 23:59:59"),
(3602707201, "2084-03-01 00:00:01"),
(7982409599, "2222-12-14 23:59:59"),
(7982409600, "2222-12-15 00:00:00"),
(7982409601, "2222-12-15 00:00:01"),
]
for v in VECTORS:
self.assertEqual(strings.format_timestamp(v[0]), v[1])
strings.format_timestamp(1616057224)
if __name__ == '__main__':
unittest.main()

Loading…
Cancel
Save