Skip to content

Commit 8ba8324

Browse files
committed
stmhal, modtime: Small changes, reduced code size by around 80 bytes.
Also added test for modtime.
1 parent 6678595 commit 8ba8324

4 files changed

Lines changed: 117 additions & 44 deletions

File tree

stmhal/modtime.c

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,6 @@
3636
#include "portmodules.h"
3737
#include "rtc.h"
3838

39-
#define DAYS_PER_400Y (365*400 + 97)
40-
#define DAYS_PER_100Y (365*100 + 24)
41-
#define DAYS_PER_4Y (365*4 + 1)
42-
43-
typedef struct {
44-
uint16_t tm_year; // i.e. 2014
45-
uint8_t tm_mon; // 1..12
46-
uint8_t tm_mday; // 1..31
47-
uint8_t tm_hour; // 0..23
48-
uint8_t tm_min; // 0..59
49-
uint8_t tm_sec; // 0..59
50-
uint8_t tm_wday; // 0..6 0 = Monday
51-
uint16_t tm_yday; // 1..366
52-
} mod_struct_time;
53-
5439
/// \module time - time related functions
5540
///
5641
/// 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) {
6348
}
6449

6550
// Month is one based
66-
STATIC mp_uint_t days_in_month(mp_uint_t year, mp_uint_t month) {
51+
STATIC mp_uint_t mod_time_days_in_month(mp_uint_t year, mp_uint_t month) {
6752
mp_uint_t mdays = days_since_jan1[month] - days_since_jan1[month - 1];
6853
if (month == 2 && is_leap_year(year)) {
6954
mdays++;
@@ -73,7 +58,7 @@ STATIC mp_uint_t days_in_month(mp_uint_t year, mp_uint_t month) {
7358

7459
// compute the day of the year, between 1 and 366
7560
// month should be between 1 and 12, date should start at 1
76-
mp_uint_t mod_time_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date) {
61+
STATIC mp_uint_t mod_time_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date) {
7762
mp_uint_t yday = days_since_jan1[month - 1] + date;
7863
if (month >= 3 && is_leap_year(year)) {
7964
yday += 1;
@@ -102,11 +87,24 @@ mp_uint_t mod_time_seconds_since_2000(mp_uint_t year, mp_uint_t month, mp_uint_t
10287

10388
#define LEAPOCH ((31 + 29) * 86400)
10489

105-
void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm) {
106-
memset(tm, 0, sizeof(*tm));
90+
#define DAYS_PER_400Y (365*400 + 97)
91+
#define DAYS_PER_100Y (365*100 + 24)
92+
#define DAYS_PER_4Y (365*4 + 1)
93+
94+
typedef struct {
95+
uint16_t tm_year; // i.e. 2014
96+
uint8_t tm_mon; // 1..12
97+
uint8_t tm_mday; // 1..31
98+
uint8_t tm_hour; // 0..23
99+
uint8_t tm_min; // 0..59
100+
uint8_t tm_sec; // 0..59
101+
uint8_t tm_wday; // 0..6 0 = Monday
102+
uint16_t tm_yday; // 1..366
103+
} mod_struct_time;
107104

105+
STATIC void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm) {
108106
// The following algorithm was adapted from musl's __secs_to_tm and adapted
109-
// for differences in MicroPython's timebase.
107+
// for differences in Micro Python's timebase.
110108

111109
mp_int_t seconds = t - LEAPOCH;
112110

@@ -146,17 +144,21 @@ void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm
146144
}
147145
days -= (years * 365);
148146

147+
/* We will compute tm_yday at the very end
149148
mp_int_t leap = !years && (q_cycles || !c_cycles);
150149
151150
tm->tm_yday = days + 31 + 28 + leap;
152151
if (tm->tm_yday >= 365 + leap) {
153152
tm->tm_yday -= 365 + leap;
154153
}
155154
155+
tm->tm_yday++; // Make one based
156+
*/
157+
156158
tm->tm_year = 2000 + years + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles;
157159

158160
// Note: days_in_month[0] corresponds to March
159-
static const int8_t days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29};
161+
STATIC const int8_t days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29};
160162

161163
mp_int_t month;
162164
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
170172
}
171173
tm->tm_mday = days + 1; // Make one based
172174
tm->tm_mon++; // Make one based
173-
tm->tm_yday++; // Make one based
174-
}
175175

176+
tm->tm_yday = mod_time_year_day(tm->tm_year, tm->tm_mon, tm->tm_mday);
177+
}
176178

177179
/// \function localtime([secs])
178180
/// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which
@@ -205,22 +207,22 @@ STATIC mp_obj_t time_localtime(uint n_args, const mp_obj_t *args) {
205207
mp_obj_new_int(mod_time_year_day(2000 + date.Year, date.Month, date.Date)),
206208
};
207209
return mp_obj_new_tuple(8, tuple);
210+
} else {
211+
mp_int_t seconds = mp_obj_get_int(args[0]);
212+
mod_struct_time tm;
213+
mod_time_seconds_since_2000_to_struct_time(seconds, &tm);
214+
mp_obj_t tuple[8] = {
215+
tuple[0] = mp_obj_new_int(tm.tm_year),
216+
tuple[1] = mp_obj_new_int(tm.tm_mon),
217+
tuple[2] = mp_obj_new_int(tm.tm_mday),
218+
tuple[3] = mp_obj_new_int(tm.tm_hour),
219+
tuple[4] = mp_obj_new_int(tm.tm_min),
220+
tuple[5] = mp_obj_new_int(tm.tm_sec),
221+
tuple[6] = mp_obj_new_int(tm.tm_wday),
222+
tuple[7] = mp_obj_new_int(tm.tm_yday),
223+
};
224+
return mp_obj_new_tuple(8, tuple);
208225
}
209-
210-
mp_int_t seconds = mp_obj_get_int(args[0]);
211-
mod_struct_time tm;
212-
mod_time_seconds_since_2000_to_struct_time(seconds, &tm);
213-
mp_obj_t tuple[8] = {
214-
mp_obj_new_int(tm.tm_year),
215-
mp_obj_new_int(tm.tm_mon),
216-
mp_obj_new_int(tm.tm_mday),
217-
mp_obj_new_int(tm.tm_hour),
218-
mp_obj_new_int(tm.tm_min),
219-
mp_obj_new_int(tm.tm_sec),
220-
mp_obj_new_int(tm.tm_wday),
221-
mp_obj_new_int(tm.tm_yday),
222-
};
223-
return mp_obj_new_tuple(8, tuple);
224226
}
225227
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
226228

@@ -248,12 +250,12 @@ STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
248250
mp_int_t minutes = mp_obj_get_int(elem[4]);
249251
mp_int_t seconds = mp_obj_get_int(elem[5]);
250252

251-
// Normalize the tuple. This allows things like:
253+
// Normalise the tuple. This allows things like:
252254
//
253255
// tm_tomorrow = list(time.localtime())
254256
// tm_tomorrow[2] += 1 # Adds 1 to mday
255257
// tomorrow = time.mktime(tm_tommorrow)
256-
//
258+
//
257259
// And not have to worry about all the weird overflows.
258260
//
259261
// You can subtract dates/times this way as well.
@@ -289,10 +291,10 @@ STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
289291
month = 12;
290292
year--;
291293
}
292-
mday += days_in_month(year, month);
294+
mday += mod_time_days_in_month(year, month);
293295
}
294-
while (mday > days_in_month(year, month)) {
295-
mday -= days_in_month(year, month);
296+
while (mday > mod_time_days_in_month(year, month)) {
297+
mday -= mod_time_days_in_month(year, month);
296298
if (++month == 13) {
297299
month = 1;
298300
year++;

stmhal/portmodules.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,4 @@ extern const mp_obj_module_t time_module;
3131

3232
// additional helper functions exported by the modules
3333

34-
mp_uint_t mod_time_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date);
3534
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);

tests/pyb/modtime.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import time
2+
3+
DAYS_PER_MONTH = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
4+
5+
def is_leap(year):
6+
return (year % 4) == 0
7+
8+
def test():
9+
seconds = 0
10+
wday = 5 # Jan 1, 2000 was a Saturday
11+
for year in range(2000, 2034):
12+
print("Testing %d" % year)
13+
yday = 1
14+
for month in range(1, 13):
15+
if month == 2 and is_leap(year):
16+
DAYS_PER_MONTH[2] = 29
17+
else:
18+
DAYS_PER_MONTH[2] = 28
19+
for day in range(1, DAYS_PER_MONTH[month] + 1):
20+
secs = time.mktime((year, month, day, 0, 0, 0, 0, 0))
21+
if secs != seconds:
22+
print("mktime failed for %d-%02d-%02d got %d expected %d" % (year, month, day, secs, seconds))
23+
tuple = time.localtime(seconds)
24+
secs = time.mktime(tuple)
25+
if secs != seconds:
26+
print("localtime failed for %d-%02d-%02d got %d expected %d" % (year, month, day, secs, seconds))
27+
return
28+
seconds += 86400
29+
if yday != tuple[7]:
30+
print("locatime for %d-%02d-%02d got yday %d, expecting %d" % (year, month, day, tuple[7], yday))
31+
return
32+
if wday != tuple[6]:
33+
print("locatime for %d-%02d-%02d got wday %d, expecting %d" % (year, month, day, tuple[6], wday))
34+
return
35+
yday += 1
36+
wday = (wday + 1) % 7
37+
38+
test()

tests/pyb/modtime.py.exp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
Testing 2000
2+
Testing 2001
3+
Testing 2002
4+
Testing 2003
5+
Testing 2004
6+
Testing 2005
7+
Testing 2006
8+
Testing 2007
9+
Testing 2008
10+
Testing 2009
11+
Testing 2010
12+
Testing 2011
13+
Testing 2012
14+
Testing 2013
15+
Testing 2014
16+
Testing 2015
17+
Testing 2016
18+
Testing 2017
19+
Testing 2018
20+
Testing 2019
21+
Testing 2020
22+
Testing 2021
23+
Testing 2022
24+
Testing 2023
25+
Testing 2024
26+
Testing 2025
27+
Testing 2026
28+
Testing 2027
29+
Testing 2028
30+
Testing 2029
31+
Testing 2030
32+
Testing 2031
33+
Testing 2032
34+
Testing 2033

0 commit comments

Comments
 (0)