all: Rename absolute time-based functions to include "epoch".

For time-based functions that work with absolute time there is the need for
an Epoch, to set the zero-point at which the absolute time starts counting.
Such functions include time.time() and filesystem stat return values.  And
different ports may use a different Epoch.

To make it clearer what functions use the Epoch (whatever it may be), and
make the ports more consistent with their use of the Epoch, this commit
renames all Epoch related functions to include the word "epoch" in their
name (and remove references to "2000").

Along with this rename, the following things have changed:

- mp_hal_time_ns() is now specified to return the number of nanoseconds
  since the Epoch, rather than since 1970 (but since this is an internal
  function it doesn't change anything for the user).

- littlefs timestamps on the esp8266 have been fixed (they were previously
  off by 30 years in nanoseconds).

Otherwise, there is no functional change made by this commit.

Signed-off-by: Damien George <damien@micropython.org>
This commit is contained in:
Damien George 2020-09-14 12:15:03 +10:00
parent bd7af6151d
commit 8f20cdc353
17 changed files with 67 additions and 50 deletions

View File

@ -311,7 +311,7 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
} else {
mode |= MP_S_IFREG;
}
mp_int_t seconds = timeutils_seconds_since_2000(
mp_int_t seconds = timeutils_seconds_since_epoch(
1980 + ((fno.fdate >> 9) & 0x7f),
(fno.fdate >> 5) & 0x0f,
fno.fdate & 0x1f,
@ -319,9 +319,6 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
(fno.ftime >> 5) & 0x3f,
2 * (fno.ftime & 0x1f)
);
#if MICROPY_EPOCH_IS_1970
seconds += TIMEUTILS_SECONDS_1970_TO_2000;
#endif
t->items[0] = MP_OBJ_NEW_SMALL_INT(mode); // st_mode
t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino
t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev

View File

@ -26,6 +26,7 @@
#include "py/runtime.h"
#include "py/mphal.h"
#include "lib/timeutils/timeutils.h"
#include "extmod/vfs.h"
#include "extmod/vfs_lfs.h"
@ -126,7 +127,8 @@ const char *mp_vfs_lfs2_make_path(mp_obj_vfs_lfs2_t *self, mp_obj_t path_in);
mp_obj_t mp_vfs_lfs2_file_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in);
STATIC void lfs_get_mtime(uint8_t buf[8]) {
uint64_t ns = mp_hal_time_ns();
// On-disk storage of timestamps uses 1970 as the Epoch, so convert from host's Epoch.
uint64_t ns = timeutils_nanoseconds_since_epoch_to_nanoseconds_since_1970(mp_hal_time_ns());
// Store "ns" to "buf" in little-endian format (essentially htole64).
for (size_t i = 0; i < 8; ++i) {
buf[i] = ns;

View File

@ -365,10 +365,8 @@ STATIC mp_obj_t MP_VFS_LFSx(stat)(mp_obj_t self_in, mp_obj_t path_in) {
for (size_t i = sizeof(mtime_buf); i > 0; --i) {
ns = ns << 8 | mtime_buf[i - 1];
}
mtime = timeutils_seconds_since_2000_from_nanoseconds_since_1970(ns);
#if MICROPY_EPOCH_IS_1970
mtime += TIMEUTILS_SECONDS_1970_TO_2000;
#endif
// On-disk storage of timestamps uses 1970 as the Epoch, so convert to host's Epoch.
mtime = timeutils_seconds_since_epoch_from_nanoseconds_since_1970(ns);
}
#endif

View File

@ -42,14 +42,6 @@ typedef struct _timeutils_struct_time_t {
uint16_t tm_yday; // 1..366
} timeutils_struct_time_t;
static inline uint64_t timeutils_seconds_since_2000_to_nanoseconds_since_1970(mp_uint_t s) {
return ((uint64_t)s + TIMEUTILS_SECONDS_1970_TO_2000) * 1000000000ULL;
}
static inline mp_uint_t timeutils_seconds_since_2000_from_nanoseconds_since_1970(uint64_t ns) {
return ns / 1000000000ULL - TIMEUTILS_SECONDS_1970_TO_2000;
}
bool timeutils_is_leap_year(mp_uint_t year);
mp_uint_t timeutils_days_in_month(mp_uint_t year, mp_uint_t month);
mp_uint_t timeutils_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date);
@ -63,10 +55,39 @@ mp_uint_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month,
mp_uint_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday,
mp_int_t hours, mp_int_t minutes, mp_int_t seconds);
static inline uint64_t timeutils_nanoseconds_since_1970(mp_uint_t year, mp_uint_t month,
// Select the Epoch used by the port.
#if MICROPY_EPOCH_IS_1970
static inline uint64_t timeutils_seconds_since_epoch(mp_uint_t year, mp_uint_t month,
mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second) {
return timeutils_seconds_since_2000_to_nanoseconds_since_1970(
timeutils_seconds_since_2000(year, month, date, hour, minute, second));
return timeutils_seconds_since_2000(year, month, date, hour, minute, second) + TIMEUTILS_SECONDS_1970_TO_2000;
}
static inline mp_uint_t timeutils_seconds_since_epoch_from_nanoseconds_since_1970(uint64_t ns) {
return ns / 1000000000ULL;
}
static inline uint64_t timeutils_nanoseconds_since_epoch_to_nanoseconds_since_1970(uint64_t ns) {
return ns;
}
#else // Epoch is 2000
#define timeutils_seconds_since_epoch_to_struct_time timeutils_seconds_since_2000_to_struct_time
#define timeutils_seconds_since_epoch timeutils_seconds_since_2000
static inline uint64_t timeutils_seconds_since_epoch_to_nanoseconds_since_1970(mp_uint_t s) {
return ((uint64_t)s + TIMEUTILS_SECONDS_1970_TO_2000) * 1000000000ULL;
}
static inline mp_uint_t timeutils_seconds_since_epoch_from_nanoseconds_since_1970(uint64_t ns) {
return ns / 1000000000ULL - TIMEUTILS_SECONDS_1970_TO_2000;
}
static inline int64_t timeutils_nanoseconds_since_epoch_to_nanoseconds_since_1970(int64_t ns) {
return ns + TIMEUTILS_SECONDS_1970_TO_2000 * 1000000000ULL;
}
#endif
#endif // MICROPY_INCLUDED_LIB_TIMEUTILS_TIMEUTILS_H

View File

@ -34,7 +34,7 @@ DWORD get_fattime(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(tv.tv_sec, &tm);
timeutils_seconds_since_epoch_to_struct_time(tv.tv_sec, &tm);
return ((DWORD)(tm.tm_year - 1980) << 25) | ((DWORD)tm.tm_mon << 21) | ((DWORD)tm.tm_mday << 16) |
((DWORD)tm.tm_hour << 11) | ((DWORD)tm.tm_min << 5) | ((DWORD)tm.tm_sec >> 1);

View File

@ -93,7 +93,7 @@ STATIC mp_obj_t machine_rtc_datetime_helper(mp_uint_t n_args, const mp_obj_t *ar
gettimeofday(&tv, NULL);
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(tv.tv_sec, &tm);
timeutils_seconds_since_epoch_to_struct_time(tv.tv_sec, &tm);
mp_obj_t tuple[8] = {
mp_obj_new_int(tm.tm_year),
@ -114,7 +114,7 @@ STATIC mp_obj_t machine_rtc_datetime_helper(mp_uint_t n_args, const mp_obj_t *ar
mp_obj_get_array_fixed_n(args[1], 8, &items);
struct timeval tv = {0};
tv.tv_sec = timeutils_seconds_since_2000(mp_obj_get_int(items[0]), mp_obj_get_int(items[1]), mp_obj_get_int(items[2]), mp_obj_get_int(items[4]), mp_obj_get_int(items[5]), mp_obj_get_int(items[6]));
tv.tv_sec = timeutils_seconds_since_epoch(mp_obj_get_int(items[0]), mp_obj_get_int(items[1]), mp_obj_get_int(items[2]), mp_obj_get_int(items[4]), mp_obj_get_int(items[5]), mp_obj_get_int(items[6]));
tv.tv_usec = mp_obj_get_int(items[7]);
settimeofday(&tv, NULL);

View File

@ -44,7 +44,7 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
} else {
seconds = mp_obj_get_int(args[0]);
}
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
timeutils_seconds_since_epoch_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),

View File

@ -200,8 +200,7 @@ void mp_hal_delay_us(uint32_t us) {
uint64_t mp_hal_time_ns(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
// gettimeofday returns seconds since 2000/1/1
uint64_t ns = timeutils_seconds_since_2000_to_nanoseconds_since_1970(tv.tv_sec);
uint64_t ns = tv.tv_sec * 1000000000ULL;
ns += (uint64_t)tv.tv_usec * 1000ULL;
return ns;
}

View File

@ -139,7 +139,7 @@ void MP_FASTCODE(mp_hal_delay_ms)(uint32_t delay) {
}
uint64_t mp_hal_time_ns(void) {
return pyb_rtc_get_us_since_2000() * 1000ULL;
return pyb_rtc_get_us_since_epoch() * 1000ULL;
}
void ets_event_poll(void) {

View File

@ -33,10 +33,10 @@ DWORD get_fattime(void) {
// TODO: Optimize division (there's no HW division support on ESP8266,
// so it's expensive).
uint32_t secs = (uint32_t)(pyb_rtc_get_us_since_2000() / 1000000);
uint32_t secs = (uint32_t)(pyb_rtc_get_us_since_epoch() / 1000000);
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(secs, &tm);
timeutils_seconds_since_epoch_to_struct_time(secs, &tm);
return ((DWORD)(tm.tm_year - 1980) << 25) | ((DWORD)tm.tm_mon << 21) | ((DWORD)tm.tm_mday << 16) |
((DWORD)tm.tm_hour << 11) | ((DWORD)tm.tm_min << 5) | ((DWORD)tm.tm_sec >> 1);

View File

@ -84,7 +84,7 @@ STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_
return (mp_obj_t)&pyb_rtc_obj;
}
void pyb_rtc_set_us_since_2000(uint64_t nowus) {
void pyb_rtc_set_us_since_epoch(uint64_t nowus) {
uint32_t cal = system_rtc_clock_cali_proc();
// Save RTC ticks for overflow detection.
rtc_last_ticks = system_get_rtc_time();
@ -96,7 +96,7 @@ void pyb_rtc_set_us_since_2000(uint64_t nowus) {
system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta));
};
uint64_t pyb_rtc_get_us_since_2000() {
uint64_t pyb_rtc_get_us_since_epoch() {
uint32_t cal;
int64_t delta;
uint32_t rtc_ticks;
@ -120,17 +120,17 @@ uint64_t pyb_rtc_get_us_since_2000() {
void rtc_prepare_deepsleep(uint64_t sleep_us) {
// RTC time will reset at wake up. Let's be preared for this.
int64_t delta = pyb_rtc_get_us_since_2000() + sleep_us;
int64_t delta = pyb_rtc_get_us_since_epoch() + sleep_us;
system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta));
}
STATIC mp_obj_t pyb_rtc_datetime(size_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
// Get time
uint64_t msecs = pyb_rtc_get_us_since_2000() / 1000;
uint64_t msecs = pyb_rtc_get_us_since_epoch() / 1000;
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(msecs / 1000, &tm);
timeutils_seconds_since_epoch_to_struct_time(msecs / 1000, &tm);
mp_obj_t tuple[8] = {
mp_obj_new_int(tm.tm_year),
@ -149,8 +149,8 @@ STATIC mp_obj_t pyb_rtc_datetime(size_t n_args, const mp_obj_t *args) {
mp_obj_t *items;
mp_obj_get_array_fixed_n(args[1], 8, &items);
pyb_rtc_set_us_since_2000(
((uint64_t)timeutils_seconds_since_2000(
pyb_rtc_set_us_since_epoch(
((uint64_t)timeutils_seconds_since_epoch(
mp_obj_get_int(items[0]),
mp_obj_get_int(items[1]),
mp_obj_get_int(items[2]),
@ -209,7 +209,7 @@ STATIC mp_obj_t pyb_rtc_alarm(mp_obj_t self_in, mp_obj_t alarm_id, mp_obj_t time
}
// set expiry time (in microseconds)
pyb_rtc_alarm0_expiry = pyb_rtc_get_us_since_2000() + (uint64_t)mp_obj_get_int(time_in) * 1000;
pyb_rtc_alarm0_expiry = pyb_rtc_get_us_since_epoch() + (uint64_t)mp_obj_get_int(time_in) * 1000;
return mp_const_none;
@ -222,7 +222,7 @@ STATIC mp_obj_t pyb_rtc_alarm_left(size_t n_args, const mp_obj_t *args) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid alarm"));
}
uint64_t now = pyb_rtc_get_us_since_2000();
uint64_t now = pyb_rtc_get_us_since_epoch();
if (pyb_rtc_alarm0_expiry <= now) {
return MP_OBJ_NEW_SMALL_INT(0);
} else {

View File

@ -132,7 +132,7 @@ STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *args) {
// see if RTC.ALARM0 should wake the device
if (pyb_rtc_alarm0_wake & MACHINE_WAKE_DEEPSLEEP) {
uint64_t t = pyb_rtc_get_us_since_2000();
uint64_t t = pyb_rtc_get_us_since_epoch();
if (pyb_rtc_alarm0_expiry <= t) {
sleep_us = 1; // alarm already expired so wake immediately
} else {

View File

@ -32,8 +32,8 @@ void pin_set(uint pin, int value);
extern uint32_t pyb_rtc_alarm0_wake;
extern uint64_t pyb_rtc_alarm0_expiry;
void pyb_rtc_set_us_since_2000(uint64_t nowus);
uint64_t pyb_rtc_get_us_since_2000();
void pyb_rtc_set_us_since_epoch(uint64_t nowus);
uint64_t pyb_rtc_get_us_since_epoch();
void rtc_prepare_deepsleep(uint64_t sleep_us);
#endif // MICROPY_INCLUDED_ESP8266_MODMACHINE_H

View File

@ -58,11 +58,11 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
timeutils_struct_time_t tm;
mp_int_t seconds;
if (n_args == 0 || args[0] == mp_const_none) {
seconds = pyb_rtc_get_us_since_2000() / 1000 / 1000;
seconds = pyb_rtc_get_us_since_epoch() / 1000 / 1000;
} else {
seconds = mp_obj_get_int(args[0]);
}
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
timeutils_seconds_since_epoch_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),
@ -98,10 +98,10 @@ STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);
/// \function time()
/// Returns the number of seconds, as an integer, since 1/1/2000.
/// Returns the number of seconds, as an integer, since the Epoch.
STATIC mp_obj_t time_time(void) {
// get date and time
return mp_obj_new_int(pyb_rtc_get_us_since_2000() / 1000 / 1000);
return mp_obj_new_int(pyb_rtc_get_us_since_epoch() / 1000 / 1000);
}
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);

View File

@ -76,7 +76,7 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
} else {
mp_int_t seconds = mp_obj_get_int(args[0]);
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
timeutils_seconds_since_epoch_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),
@ -125,7 +125,7 @@ STATIC mp_obj_t time_time(void) {
RTC_TimeTypeDef time;
HAL_RTC_GetTime(&RTCHandle, &time, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&RTCHandle, &date, RTC_FORMAT_BIN);
return mp_obj_new_int(timeutils_seconds_since_2000(2000 + date.Year, date.Month, date.Date, time.Hours, time.Minutes, time.Seconds));
return mp_obj_new_int(timeutils_seconds_since_epoch(2000 + date.Year, date.Month, date.Date, time.Hours, time.Minutes, time.Seconds));
}
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);

View File

@ -452,8 +452,8 @@ uint64_t mp_hal_time_ns(void) {
RTC_DateTypeDef date;
HAL_RTC_GetTime(&RTCHandle, &time, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&RTCHandle, &date, RTC_FORMAT_BIN);
ns = timeutils_nanoseconds_since_1970(
2000 + date.Year, date.Month, date.Date, time.Hours, time.Minutes, time.Seconds);
ns = timeutils_seconds_since_epoch(2000 + date.Year, date.Month, date.Date, time.Hours, time.Minutes, time.Seconds);
ns *= 1000000000ULL;
uint32_t usec = ((RTC_SYNCH_PREDIV - time.SubSeconds) * (1000000 / 64)) / ((RTC_SYNCH_PREDIV + 1) / 64);
ns += usec * 1000;
#endif

View File

@ -76,7 +76,7 @@ mp_uint_t mp_hal_ticks_cpu(void);
#endif
#ifndef mp_hal_time_ns
// Nanoseconds since 1970/1/1.
// Nanoseconds since the Epoch.
uint64_t mp_hal_time_ns(void);
#endif