stmhal, modtime: Small changes, reduced code size by around 80 bytes.
Also added test for modtime.
This commit is contained in:
parent
6678595e7e
commit
8ba832456e
@ -36,21 +36,6 @@
|
|||||||
#include "portmodules.h"
|
#include "portmodules.h"
|
||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
|
|
||||||
#define DAYS_PER_400Y (365*400 + 97)
|
|
||||||
#define DAYS_PER_100Y (365*100 + 24)
|
|
||||||
#define DAYS_PER_4Y (365*4 + 1)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t tm_year; // i.e. 2014
|
|
||||||
uint8_t tm_mon; // 1..12
|
|
||||||
uint8_t tm_mday; // 1..31
|
|
||||||
uint8_t tm_hour; // 0..23
|
|
||||||
uint8_t tm_min; // 0..59
|
|
||||||
uint8_t tm_sec; // 0..59
|
|
||||||
uint8_t tm_wday; // 0..6 0 = Monday
|
|
||||||
uint16_t tm_yday; // 1..366
|
|
||||||
} mod_struct_time;
|
|
||||||
|
|
||||||
/// \module time - time related functions
|
/// \module time - time related functions
|
||||||
///
|
///
|
||||||
/// The `time` module provides functions for getting the current time and date,
|
/// The `time` module provides functions for getting the current time and date,
|
||||||
@ -63,7 +48,7 @@ STATIC bool is_leap_year(mp_uint_t year) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Month is one based
|
// Month is one based
|
||||||
STATIC mp_uint_t days_in_month(mp_uint_t year, mp_uint_t month) {
|
STATIC mp_uint_t mod_time_days_in_month(mp_uint_t year, mp_uint_t month) {
|
||||||
mp_uint_t mdays = days_since_jan1[month] - days_since_jan1[month - 1];
|
mp_uint_t mdays = days_since_jan1[month] - days_since_jan1[month - 1];
|
||||||
if (month == 2 && is_leap_year(year)) {
|
if (month == 2 && is_leap_year(year)) {
|
||||||
mdays++;
|
mdays++;
|
||||||
@ -73,7 +58,7 @@ STATIC mp_uint_t days_in_month(mp_uint_t year, mp_uint_t month) {
|
|||||||
|
|
||||||
// compute the day of the year, between 1 and 366
|
// compute the day of the year, between 1 and 366
|
||||||
// month should be between 1 and 12, date should start at 1
|
// month should be between 1 and 12, date should start at 1
|
||||||
mp_uint_t mod_time_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date) {
|
STATIC mp_uint_t mod_time_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date) {
|
||||||
mp_uint_t yday = days_since_jan1[month - 1] + date;
|
mp_uint_t yday = days_since_jan1[month - 1] + date;
|
||||||
if (month >= 3 && is_leap_year(year)) {
|
if (month >= 3 && is_leap_year(year)) {
|
||||||
yday += 1;
|
yday += 1;
|
||||||
@ -102,9 +87,22 @@ mp_uint_t mod_time_seconds_since_2000(mp_uint_t year, mp_uint_t month, mp_uint_t
|
|||||||
|
|
||||||
#define LEAPOCH ((31 + 29) * 86400)
|
#define LEAPOCH ((31 + 29) * 86400)
|
||||||
|
|
||||||
void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm) {
|
#define DAYS_PER_400Y (365*400 + 97)
|
||||||
memset(tm, 0, sizeof(*tm));
|
#define DAYS_PER_100Y (365*100 + 24)
|
||||||
|
#define DAYS_PER_4Y (365*4 + 1)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t tm_year; // i.e. 2014
|
||||||
|
uint8_t tm_mon; // 1..12
|
||||||
|
uint8_t tm_mday; // 1..31
|
||||||
|
uint8_t tm_hour; // 0..23
|
||||||
|
uint8_t tm_min; // 0..59
|
||||||
|
uint8_t tm_sec; // 0..59
|
||||||
|
uint8_t tm_wday; // 0..6 0 = Monday
|
||||||
|
uint16_t tm_yday; // 1..366
|
||||||
|
} mod_struct_time;
|
||||||
|
|
||||||
|
STATIC void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm) {
|
||||||
// The following algorithm was adapted from musl's __secs_to_tm and adapted
|
// The following algorithm was adapted from musl's __secs_to_tm and adapted
|
||||||
// for differences in Micro Python's timebase.
|
// for differences in Micro Python's timebase.
|
||||||
|
|
||||||
@ -146,6 +144,7 @@ void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm
|
|||||||
}
|
}
|
||||||
days -= (years * 365);
|
days -= (years * 365);
|
||||||
|
|
||||||
|
/* We will compute tm_yday at the very end
|
||||||
mp_int_t leap = !years && (q_cycles || !c_cycles);
|
mp_int_t leap = !years && (q_cycles || !c_cycles);
|
||||||
|
|
||||||
tm->tm_yday = days + 31 + 28 + leap;
|
tm->tm_yday = days + 31 + 28 + leap;
|
||||||
@ -153,10 +152,13 @@ void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm
|
|||||||
tm->tm_yday -= 365 + leap;
|
tm->tm_yday -= 365 + leap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tm->tm_yday++; // Make one based
|
||||||
|
*/
|
||||||
|
|
||||||
tm->tm_year = 2000 + years + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles;
|
tm->tm_year = 2000 + years + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles;
|
||||||
|
|
||||||
// Note: days_in_month[0] corresponds to March
|
// Note: days_in_month[0] corresponds to March
|
||||||
static const int8_t days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29};
|
STATIC const int8_t days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29};
|
||||||
|
|
||||||
mp_int_t month;
|
mp_int_t month;
|
||||||
for (month = 0; days_in_month[month] <= days; month++) {
|
for (month = 0; days_in_month[month] <= days; month++) {
|
||||||
@ -170,9 +172,9 @@ void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm
|
|||||||
}
|
}
|
||||||
tm->tm_mday = days + 1; // Make one based
|
tm->tm_mday = days + 1; // Make one based
|
||||||
tm->tm_mon++; // Make one based
|
tm->tm_mon++; // Make one based
|
||||||
tm->tm_yday++; // Make one based
|
|
||||||
}
|
|
||||||
|
|
||||||
|
tm->tm_yday = mod_time_year_day(tm->tm_year, tm->tm_mon, tm->tm_mday);
|
||||||
|
}
|
||||||
|
|
||||||
/// \function localtime([secs])
|
/// \function localtime([secs])
|
||||||
/// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which
|
/// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which
|
||||||
@ -205,23 +207,23 @@ STATIC mp_obj_t time_localtime(uint n_args, const mp_obj_t *args) {
|
|||||||
mp_obj_new_int(mod_time_year_day(2000 + date.Year, date.Month, date.Date)),
|
mp_obj_new_int(mod_time_year_day(2000 + date.Year, date.Month, date.Date)),
|
||||||
};
|
};
|
||||||
return mp_obj_new_tuple(8, tuple);
|
return mp_obj_new_tuple(8, tuple);
|
||||||
}
|
} else {
|
||||||
|
|
||||||
mp_int_t seconds = mp_obj_get_int(args[0]);
|
mp_int_t seconds = mp_obj_get_int(args[0]);
|
||||||
mod_struct_time tm;
|
mod_struct_time tm;
|
||||||
mod_time_seconds_since_2000_to_struct_time(seconds, &tm);
|
mod_time_seconds_since_2000_to_struct_time(seconds, &tm);
|
||||||
mp_obj_t tuple[8] = {
|
mp_obj_t tuple[8] = {
|
||||||
mp_obj_new_int(tm.tm_year),
|
tuple[0] = mp_obj_new_int(tm.tm_year),
|
||||||
mp_obj_new_int(tm.tm_mon),
|
tuple[1] = mp_obj_new_int(tm.tm_mon),
|
||||||
mp_obj_new_int(tm.tm_mday),
|
tuple[2] = mp_obj_new_int(tm.tm_mday),
|
||||||
mp_obj_new_int(tm.tm_hour),
|
tuple[3] = mp_obj_new_int(tm.tm_hour),
|
||||||
mp_obj_new_int(tm.tm_min),
|
tuple[4] = mp_obj_new_int(tm.tm_min),
|
||||||
mp_obj_new_int(tm.tm_sec),
|
tuple[5] = mp_obj_new_int(tm.tm_sec),
|
||||||
mp_obj_new_int(tm.tm_wday),
|
tuple[6] = mp_obj_new_int(tm.tm_wday),
|
||||||
mp_obj_new_int(tm.tm_yday),
|
tuple[7] = mp_obj_new_int(tm.tm_yday),
|
||||||
};
|
};
|
||||||
return mp_obj_new_tuple(8, tuple);
|
return mp_obj_new_tuple(8, tuple);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
|
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
|
||||||
|
|
||||||
|
|
||||||
@ -248,7 +250,7 @@ STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
|
|||||||
mp_int_t minutes = mp_obj_get_int(elem[4]);
|
mp_int_t minutes = mp_obj_get_int(elem[4]);
|
||||||
mp_int_t seconds = mp_obj_get_int(elem[5]);
|
mp_int_t seconds = mp_obj_get_int(elem[5]);
|
||||||
|
|
||||||
// Normalize the tuple. This allows things like:
|
// Normalise the tuple. This allows things like:
|
||||||
//
|
//
|
||||||
// tm_tomorrow = list(time.localtime())
|
// tm_tomorrow = list(time.localtime())
|
||||||
// tm_tomorrow[2] += 1 # Adds 1 to mday
|
// tm_tomorrow[2] += 1 # Adds 1 to mday
|
||||||
@ -289,10 +291,10 @@ STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
|
|||||||
month = 12;
|
month = 12;
|
||||||
year--;
|
year--;
|
||||||
}
|
}
|
||||||
mday += days_in_month(year, month);
|
mday += mod_time_days_in_month(year, month);
|
||||||
}
|
}
|
||||||
while (mday > days_in_month(year, month)) {
|
while (mday > mod_time_days_in_month(year, month)) {
|
||||||
mday -= days_in_month(year, month);
|
mday -= mod_time_days_in_month(year, month);
|
||||||
if (++month == 13) {
|
if (++month == 13) {
|
||||||
month = 1;
|
month = 1;
|
||||||
year++;
|
year++;
|
||||||
|
@ -31,5 +31,4 @@ extern const mp_obj_module_t time_module;
|
|||||||
|
|
||||||
// additional helper functions exported by the modules
|
// additional helper functions exported by the modules
|
||||||
|
|
||||||
mp_uint_t mod_time_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date);
|
|
||||||
mp_uint_t mod_time_seconds_since_2000(mp_uint_t year, mp_uint_t month, mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second);
|
mp_uint_t mod_time_seconds_since_2000(mp_uint_t year, mp_uint_t month, mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second);
|
||||||
|
38
tests/pyb/modtime.py
Normal file
38
tests/pyb/modtime.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
DAYS_PER_MONTH = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
||||||
|
|
||||||
|
def is_leap(year):
|
||||||
|
return (year % 4) == 0
|
||||||
|
|
||||||
|
def test():
|
||||||
|
seconds = 0
|
||||||
|
wday = 5 # Jan 1, 2000 was a Saturday
|
||||||
|
for year in range(2000, 2034):
|
||||||
|
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))
|
||||||
|
if secs != seconds:
|
||||||
|
print("mktime failed for %d-%02d-%02d got %d expected %d" % (year, month, day, secs, seconds))
|
||||||
|
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()
|
34
tests/pyb/modtime.py.exp
Normal file
34
tests/pyb/modtime.py.exp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
Testing 2000
|
||||||
|
Testing 2001
|
||||||
|
Testing 2002
|
||||||
|
Testing 2003
|
||||||
|
Testing 2004
|
||||||
|
Testing 2005
|
||||||
|
Testing 2006
|
||||||
|
Testing 2007
|
||||||
|
Testing 2008
|
||||||
|
Testing 2009
|
||||||
|
Testing 2010
|
||||||
|
Testing 2011
|
||||||
|
Testing 2012
|
||||||
|
Testing 2013
|
||||||
|
Testing 2014
|
||||||
|
Testing 2015
|
||||||
|
Testing 2016
|
||||||
|
Testing 2017
|
||||||
|
Testing 2018
|
||||||
|
Testing 2019
|
||||||
|
Testing 2020
|
||||||
|
Testing 2021
|
||||||
|
Testing 2022
|
||||||
|
Testing 2023
|
||||||
|
Testing 2024
|
||||||
|
Testing 2025
|
||||||
|
Testing 2026
|
||||||
|
Testing 2027
|
||||||
|
Testing 2028
|
||||||
|
Testing 2029
|
||||||
|
Testing 2030
|
||||||
|
Testing 2031
|
||||||
|
Testing 2032
|
||||||
|
Testing 2033
|
Loading…
x
Reference in New Issue
Block a user