3232#include MICROPY_HAL_H
3333#include "py/nlr.h"
3434#include "py/obj.h"
35- #include "modutime .h"
35+ #include "timeutils .h"
3636#include "inc/hw_types.h"
3737#include "inc/hw_ints.h"
3838#include "inc/hw_memmap.h"
4141#include "pybrtc.h"
4242#include "mpexception.h"
4343
44-
45- // LEAPOCH corresponds to 2000-03-01, which is a mod-400 year, immediately
46- // after Feb 29. We calculate seconds as a signed integer relative to that.
47- //
48- // Our timebase is relative to 2000-01-01.
49-
50- #define LEAPOCH ((31 + 29) * 86400)
51-
52- #define DAYS_PER_400Y (365*400 + 97)
53- #define DAYS_PER_100Y (365*100 + 24)
54- #define DAYS_PER_4Y (365*4 + 1)
55-
56-
5744/// \module time - time related functions
5845///
5946/// The `time` module provides functions for getting the current time and date,
6047/// and for sleeping.
6148
62- STATIC const uint16_t days_since_jan1 []= { 0 , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334 , 365 };
63-
64- STATIC bool is_leap_year (mp_uint_t year ) {
65- return (year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0 ;
66- }
67-
68- // Month is one based
69- STATIC mp_uint_t mod_time_days_in_month (mp_uint_t year , mp_uint_t month ) {
70- mp_uint_t mdays = days_since_jan1 [month ] - days_since_jan1 [month - 1 ];
71- if (month == 2 && is_leap_year (year )) {
72- mdays ++ ;
73- }
74- return mdays ;
75- }
76-
77- // compute the day of the year, between 1 and 366
78- // month should be between 1 and 12, date should start at 1
79- STATIC mp_uint_t mod_time_year_day (mp_uint_t year , mp_uint_t month , mp_uint_t date ) {
80- mp_uint_t yday = days_since_jan1 [month - 1 ] + date ;
81- if (month >= 3 && is_leap_year (year )) {
82- yday += 1 ;
83- }
84- return yday ;
85- }
86-
87- // returns the number of seconds, as an integer, since 2000-01-01
88- 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 ) {
89- return
90- second
91- + minute * 60
92- + hour * 3600
93- + (mod_time_year_day (year , month , date ) - 1
94- + ((year - 2000 + 3 ) / 4 ) // add a day each 4 years starting with 2001
95- - ((year - 2000 + 99 ) / 100 ) // subtract a day each 100 years starting with 2001
96- + ((year - 2000 + 399 ) / 400 ) // add a day each 400 years starting with 2001
97- ) * 86400
98- + (year - 2000 ) * 31536000 ;
99- }
100-
101- void mod_time_seconds_since_2000_to_struct_time (mp_uint_t t , mod_struct_time * tm ) {
102- // The following algorithm was adapted from musl's __secs_to_tm and adapted
103- // for differences in Micro Python's timebase.
104-
105- mp_int_t seconds = t - LEAPOCH ;
106-
107- mp_int_t days = seconds / 86400 ;
108- seconds %= 86400 ;
109- tm -> tm_hour = seconds / 3600 ;
110- tm -> tm_min = seconds / 60 % 60 ;
111- tm -> tm_sec = seconds % 60 ;
112-
113- mp_int_t wday = (days + 2 ) % 7 ; // Mar 1, 2000 was a Wednesday (2)
114- if (wday < 0 ) {
115- wday += 7 ;
116- }
117- tm -> tm_wday = wday ;
118-
119- mp_int_t qc_cycles = days / DAYS_PER_400Y ;
120- days %= DAYS_PER_400Y ;
121- if (days < 0 ) {
122- days += DAYS_PER_400Y ;
123- qc_cycles -- ;
124- }
125- mp_int_t c_cycles = days / DAYS_PER_100Y ;
126- if (c_cycles == 4 ) {
127- c_cycles -- ;
128- }
129- days -= (c_cycles * DAYS_PER_100Y );
130-
131- mp_int_t q_cycles = days / DAYS_PER_4Y ;
132- if (q_cycles == 25 ) {
133- q_cycles -- ;
134- }
135- days -= q_cycles * DAYS_PER_4Y ;
136-
137- mp_int_t years = days / 365 ;
138- if (years == 4 ) {
139- years -- ;
140- }
141- days -= (years * 365 );
142-
143- tm -> tm_year = 2000 + years + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles ;
144-
145- // Note: days_in_month[0] corresponds to March
146- STATIC const int8_t days_in_month [] = {31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 , 31 , 29 };
147-
148- mp_int_t month ;
149- for (month = 0 ; days_in_month [month ] <= days ; month ++ ) {
150- days -= days_in_month [month ];
151- }
152-
153- tm -> tm_mon = month + 2 ;
154- if (tm -> tm_mon >= 12 ) {
155- tm -> tm_mon -= 12 ;
156- tm -> tm_year ++ ;
157- }
158- tm -> tm_mday = days + 1 ; // Make one based
159- tm -> tm_mon ++ ; // Make one based
160-
161- tm -> tm_yday = mod_time_year_day (tm -> tm_year , tm -> tm_mon , tm -> tm_mday );
162- }
163-
16449/// \function localtime([secs])
16550/// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which
16651/// contains: (year, month, mday, hour, minute, second, weekday, yearday)
@@ -175,14 +60,14 @@ void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm
17560/// yearday is 1-366
17661STATIC mp_obj_t time_localtime (mp_uint_t n_args , const mp_obj_t * args ) {
17762 if (n_args == 0 || args [0 ] == mp_const_none ) {
178- mod_struct_time tm ;
63+ timeutils_struct_time_t tm ;
17964 uint32_t seconds ;
18065 uint16_t mseconds ;
18166
18267 // get the seconds and the milliseconds from the RTC
18368 MAP_PRCMRTCGet (& seconds , & mseconds );
18469 mseconds = RTC_CYCLES_U16MS (mseconds );
185- mod_time_seconds_since_2000_to_struct_time (seconds , & tm );
70+ timeutils_seconds_since_2000_to_struct_time (seconds , & tm );
18671
18772 mp_obj_t tuple [8 ] = {
18873 mp_obj_new_int (tm .tm_year ),
@@ -197,8 +82,8 @@ STATIC mp_obj_t time_localtime(mp_uint_t n_args, const mp_obj_t *args) {
19782 return mp_obj_new_tuple (8 , tuple );
19883 } else {
19984 mp_int_t seconds = mp_obj_get_int (args [0 ]);
200- mod_struct_time tm ;
201- mod_time_seconds_since_2000_to_struct_time (seconds , & tm );
85+ timeutils_struct_time_t tm ;
86+ timeutils_seconds_since_2000_to_struct_time (seconds , & tm );
20287 mp_obj_t tuple [8 ] = {
20388 tuple [0 ] = mp_obj_new_int (tm .tm_year ),
20489 tuple [1 ] = mp_obj_new_int (tm .tm_mon ),
@@ -231,64 +116,10 @@ STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
231116 nlr_raise (mp_obj_new_exception_msg (& mp_type_TypeError , mpexception_num_type_invalid_arguments ));
232117 }
233118
234- mp_int_t year = mp_obj_get_int (elem [0 ]);
235- mp_int_t month = mp_obj_get_int (elem [1 ]);
236- mp_int_t mday = mp_obj_get_int (elem [2 ]);
237- mp_int_t hours = mp_obj_get_int (elem [3 ]);
238- mp_int_t minutes = mp_obj_get_int (elem [4 ]);
239- mp_int_t seconds = mp_obj_get_int (elem [5 ]);
119+ return mp_obj_new_int_from_uint (timeutils_mktime (mp_obj_get_int (elem [0 ]),
120+ mp_obj_get_int (elem [1 ]), mp_obj_get_int (elem [2 ]), mp_obj_get_int (elem [3 ]),
121+ mp_obj_get_int (elem [4 ]), mp_obj_get_int (elem [5 ])));
240122
241- // Normalize the tuple. This allows things like:
242- //
243- // tm_tomorrow = list(time.localtime())
244- // tm_tomorrow[2] += 1 # Adds 1 to mday
245- // tomorrow = time.mktime(tm_tommorrow)
246- //
247- // And not have to worry about all the weird overflows.
248- //
249- // You can subtract dates/times this way as well.
250-
251- minutes += seconds / 60 ;
252- if ((seconds = seconds % 60 ) < 0 ) {
253- seconds += 60 ;
254- minutes -- ;
255- }
256-
257- hours += minutes / 60 ;
258- if ((minutes = minutes % 60 ) < 0 ) {
259- minutes += 60 ;
260- hours -- ;
261- }
262-
263- mday += hours / 24 ;
264- if ((hours = hours % 24 ) < 0 ) {
265- hours += 24 ;
266- mday -- ;
267- }
268-
269- month -- ; // make month zero based
270- year += month / 12 ;
271- if ((month = month % 12 ) < 0 ) {
272- month += 12 ;
273- year -- ;
274- }
275- month ++ ; // back to one based
276-
277- while (mday < 1 ) {
278- if (-- month == 0 ) {
279- month = 12 ;
280- year -- ;
281- }
282- mday += mod_time_days_in_month (year , month );
283- }
284- while (mday > mod_time_days_in_month (year , month )) {
285- mday -= mod_time_days_in_month (year , month );
286- if (++ month == 13 ) {
287- month = 1 ;
288- year ++ ;
289- }
290- }
291- return mp_obj_new_int_from_uint (mod_time_seconds_since_2000 (year , month , mday , hours , minutes , seconds ));
292123}
293124MP_DEFINE_CONST_FUN_OBJ_1 (time_mktime_obj , time_mktime );
294125
0 commit comments