time.mktime() returns incorrect Unix timestamp on ESP32
Port, board and/or hardware
sysname='esp32', nodename='esp32', release='1.24.1', version='v1.24.1 on 2024-11-29', machine='Generic ESP32 module with ESP32. Unique ID b'\x94\xe6\x86\x13o$' (not sure what this is
MicroPython version
release='1.24.1', version='v1.24.1 on 2024-11-29',
When using this board and setting time using the ntp library thus ntptime.settime() this synchronizes the RTC to UTC using an NTP server, and it seems to be working correctly since time.localtime() returns (2024, 12, 28, 18, 11, 1, 5, 363) (UTC time). As I understand it, this should reset the real time clock to the current time. If I then set time.mktime(time.localtime()) which should provide the Unix time, it does not, instead is spits out 788726670 which is 1994-12-29 18:44:30 UTC. Can someone please explain this ? Is it a a bug? Bottom line, how can the realtime clock be set to a specific time?
Reproduction
from machine import RTC
import time
Manually set the RTC to a known time (e.g., 2024-01-28 15:30:00 UTC)
rtc = RTC()
rtc.datetime((2024, 1, 28, 0, 15, 30, 0, 0)) # (year, month, day, weekday, hour, minute, second, subseconds)
Get the Unix timestamp
unix_time = time.mktime(time.localtime())
print("Unix time:", unix_time)
Result: Unix time: 759771000 it should be closer to 1735413856.203176
Expected behaviour
Expected the unix time to be determined correctly. That is it should look something like this 1735413022.697727
Observed behaviour
The output is incorrect - see Expected behaviour result above
Additional Information
No, I've provided everything above.
Code of Conduct
Yes, I agree
Add time.mktime and enhance time.localtime (for stmhal)
Now you can use time.localtime on the timestamps presented by os.stat
I tested the implementation using the following script on my stmhal board:
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()