fix(simu): use local time rather than UTC in the WASM simulator (#7658)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3e1e1859bc
commit
e9a6ab8691
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "wasmsimulatorinterface.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QElapsedTimer>
|
||||
@@ -559,8 +560,11 @@ void WasmSimulatorInterface::start(const char * filename, bool tests)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t argv[1] = {(uint32_t)tests};
|
||||
if (!wasm_runtime_call_wasm(m_execEnv, m_fnStart, 1, argv)) {
|
||||
// WASI has no timezone support, so the module needs our UTC offset.
|
||||
uint32_t argv[2] = {
|
||||
(uint32_t)tests,
|
||||
(uint32_t)(int32_t)QDateTime::currentDateTime().offsetFromUtc()};
|
||||
if (!wasm_runtime_call_wasm(m_execEnv, m_fnStart, 2, argv)) {
|
||||
qWarning() << "WASM simuStart failed:"
|
||||
<< wasm_runtime_get_exception(m_moduleInst);
|
||||
return;
|
||||
|
||||
@@ -208,14 +208,14 @@ FRESULT file_stat(const std::string& realPath, FILINFO* fno)
|
||||
if (!ec) {
|
||||
auto systime = ftime_to_systime(ftime);
|
||||
auto time_t_val = std::chrono::system_clock::to_time_t(systime);
|
||||
struct tm* ltime = localtime(&time_t_val);
|
||||
struct tm ltime;
|
||||
|
||||
if (ltime) {
|
||||
if (simuLocalTime(time_t_val, <ime)) {
|
||||
// Convert to FatFs format
|
||||
fno->fdate = ((ltime->tm_year - 80) << 9) | ((ltime->tm_mon + 1) << 5) |
|
||||
ltime->tm_mday;
|
||||
fno->fdate = ((ltime.tm_year - 80) << 9) | ((ltime.tm_mon + 1) << 5) |
|
||||
ltime.tm_mday;
|
||||
fno->ftime =
|
||||
(ltime->tm_hour << 11) | (ltime->tm_min << 5) | (ltime->tm_sec / 2);
|
||||
(ltime.tm_hour << 11) | (ltime.tm_min << 5) | (ltime.tm_sec / 2);
|
||||
} else {
|
||||
fno->fdate = 0;
|
||||
fno->ftime = 0;
|
||||
@@ -572,7 +572,7 @@ FRESULT f_utime(const TCHAR* path, const FILINFO* fno)
|
||||
ltime.tm_sec = (fno->ftime & 0x1F) * 2;
|
||||
ltime.tm_isdst = -1;
|
||||
|
||||
time_t timestamp = mktime(<ime);
|
||||
time_t timestamp = simuLocalTimeToEpoch(<ime);
|
||||
if (timestamp == -1) {
|
||||
return FR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
@@ -142,11 +142,46 @@ void simuCreateDefaults()
|
||||
simuCreateDefaultSettings = true;
|
||||
}
|
||||
|
||||
void simuStart(bool tests)
|
||||
#if defined(__wasm__)
|
||||
static int32_t simuUtcOffset = 0;
|
||||
#endif
|
||||
|
||||
bool simuLocalTime(time_t t, struct tm* result)
|
||||
{
|
||||
struct tm* tmp;
|
||||
#if defined(__wasm__)
|
||||
t += simuUtcOffset;
|
||||
tmp = gmtime(&t);
|
||||
#else
|
||||
tmp = localtime(&t);
|
||||
#endif
|
||||
if (tmp == nullptr) return false;
|
||||
*result = *tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
time_t simuLocalTimeToEpoch(struct tm* tm)
|
||||
{
|
||||
#if defined(__wasm__)
|
||||
// wasi-libc's mktime() is timezone-less, i.e. equivalent to timegm()
|
||||
time_t t = mktime(tm);
|
||||
return t == (time_t)-1 ? t : t - simuUtcOffset;
|
||||
#else
|
||||
return mktime(tm);
|
||||
#endif
|
||||
}
|
||||
|
||||
void simuStart(bool tests, int32_t utcOffset)
|
||||
{
|
||||
if (simu_running)
|
||||
return;
|
||||
|
||||
#if defined(__wasm__)
|
||||
simuUtcOffset = utcOffset;
|
||||
#else
|
||||
(void)utcOffset;
|
||||
#endif
|
||||
|
||||
#if !defined(COLORLCD)
|
||||
menuLevel = 0;
|
||||
#endif
|
||||
@@ -171,20 +206,19 @@ void simuStart(bool tests)
|
||||
|
||||
#if defined(RTCLOCK)
|
||||
time_t rawtime;
|
||||
struct tm * timeinfo;
|
||||
struct tm timeinfo;
|
||||
time (&rawtime);
|
||||
timeinfo = localtime (&rawtime);
|
||||
|
||||
if (timeinfo != nullptr) {
|
||||
if (simuLocalTime(rawtime, &timeinfo)) {
|
||||
struct gtm gti;
|
||||
gti.tm_sec = timeinfo->tm_sec;
|
||||
gti.tm_min = timeinfo->tm_min;
|
||||
gti.tm_hour = timeinfo->tm_hour;
|
||||
gti.tm_mday = timeinfo->tm_mday;
|
||||
gti.tm_mon = timeinfo->tm_mon;
|
||||
gti.tm_year = timeinfo->tm_year;
|
||||
gti.tm_wday = timeinfo->tm_wday;
|
||||
gti.tm_yday = timeinfo->tm_yday;
|
||||
gti.tm_sec = timeinfo.tm_sec;
|
||||
gti.tm_min = timeinfo.tm_min;
|
||||
gti.tm_hour = timeinfo.tm_hour;
|
||||
gti.tm_mday = timeinfo.tm_mday;
|
||||
gti.tm_mon = timeinfo.tm_mon;
|
||||
gti.tm_year = timeinfo.tm_year;
|
||||
gti.tm_wday = timeinfo.tm_wday;
|
||||
gti.tm_yday = timeinfo.tm_yday;
|
||||
g_rtcTime = gmktime(>i);
|
||||
} else {
|
||||
g_rtcTime = rawtime;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -43,8 +44,10 @@
|
||||
|
||||
// Lifecycle: call simuInit() once, then simuFatfsSetPaths() + simuStart().
|
||||
// Poll simuIsRunning() periodically. Call simuStop() to shut down.
|
||||
// utcOffset: seconds east of UTC, DST applied; wasi-libc's localtime() always
|
||||
// reports UTC. Ignored by native builds.
|
||||
void WASM_EXPORT(simuInit)();
|
||||
void WASM_EXPORT(simuStart)(bool tests = true);
|
||||
void WASM_EXPORT(simuStart)(bool tests = true, int32_t utcOffset = 0);
|
||||
void WASM_EXPORT(simuStop)();
|
||||
bool WASM_EXPORT(simuIsRunning)();
|
||||
|
||||
@@ -189,6 +192,11 @@ void WASM_IMPORT(simuAuxSerialSendBuffer)(uint8_t port_nr, const uint8_t* data,
|
||||
uint32_t len);
|
||||
|
||||
// -- Internal (not exported) --
|
||||
|
||||
// Use instead of localtime()/mktime(): applies simuStart()'s utcOffset on WASM.
|
||||
bool simuLocalTime(time_t t, struct tm* result);
|
||||
time_t simuLocalTimeToEpoch(struct tm* tm);
|
||||
|
||||
void simuMain();
|
||||
std::string simuFatfsGetCurrentPath();
|
||||
std::string simuFatfsGetRealPath(const std::string& p);
|
||||
|
||||
+2
-1
@@ -448,7 +448,8 @@
|
||||
ex.simuInit();
|
||||
runner.setFatfsPaths('/', '/');
|
||||
ex.simuCreateDefaults();
|
||||
ex.simuStart(1);
|
||||
// WASI has no timezone support, so the module needs our UTC offset.
|
||||
ex.simuStart(1, -new Date().getTimezoneOffset() * 60);
|
||||
|
||||
if (canvas) {
|
||||
lcdRenderer = new LcdRenderer(canvas);
|
||||
|
||||
@@ -45,7 +45,7 @@ export interface SimulatorExports {
|
||||
free: (ptr: number) => void;
|
||||
|
||||
simuInit: () => void;
|
||||
simuStart: (tests: number) => void;
|
||||
simuStart: (tests: number, utcOffset: number) => void;
|
||||
simuStop: () => void;
|
||||
simuIsRunning: () => number;
|
||||
simuFatfsSetPaths: (sdPath: number, settingsPath: number) => void;
|
||||
|
||||
Reference in New Issue
Block a user