From 652a622954461c1264e8cf8efca262c35c40a327 Mon Sep 17 00:00:00 2001 From: C <0xicl33n@gmail.com> Date: Sat, 4 Jul 2026 11:28:35 -0700 Subject: [PATCH] feat: Implement market hours and intelligent sleep duration calculation --- m5paper-stockticker.ino | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/m5paper-stockticker.ino b/m5paper-stockticker.ino index e9e55ca..5b62653 100644 --- a/m5paper-stockticker.ino +++ b/m5paper-stockticker.ino @@ -231,6 +231,68 @@ void fmtMoney(char* buf, size_t len, float val) { snprintf(buf, len, "%d.%02d", dollars, cents); } +// ------------------------------------------------------- +// US market hours (Eastern time) helpers +// ------------------------------------------------------- +// Approximate US Eastern DST window: 2nd Sunday of March .. 1st Sunday of Nov. +// (The exact 2 AM changeover happens on a Sunday when markets are closed, so +// day-level precision is sufficient here.) +bool usEasternDST(const struct tm& u) { + int m = u.tm_mon + 1, d = u.tm_mday, wday = u.tm_wday; + if (m < 3 || m > 11) return false; + if (m > 3 && m < 11) return true; + int prevSunday = d - wday; + if (m == 3) return prevSunday >= 8; // on/after 2nd Sunday -> DST + return prevSunday <= 0; // Nov: before 1st Sunday -> DST +} + +// Break current UTC time down into US Eastern local time. +void getEasternTime(struct tm& etTm) { + time_t utc = time(nullptr); + struct tm u; + gmtime_r(&utc, &u); + int off = usEasternDST(u) ? -4 * 3600 : -5 * 3600; + time_t et = utc + off; + gmtime_r(&et, &etTm); +} + +// Daily market events, as seconds-of-day in US Eastern time. +const long EVT_OPEN = 9 * 3600 + 30 * 60; // 09:30 -> 34200 s +const long EVT_MID = 12 * 3600 + 45 * 60; // 12:45 -> 45900 s (session midpoint) +const long EVT_CLOSE = 16 * 3600; // 16:00 -> 57600 s + +// Which event this update corresponds to: nearest of open / mid / close. +const char* marketPhase(const struct tm& et) { + long s = et.tm_hour * 3600 + et.tm_min * 60 + et.tm_sec; + long dOpen = labs(s - EVT_OPEN); + long dMid = labs(s - EVT_MID); + long dClose = labs(s - EVT_CLOSE); + if (dOpen <= dMid && dOpen <= dClose) return "open"; + if (dClose <= dMid && dClose <= dOpen) return "close"; + return "mid"; +} + +// Microseconds until the next market event: the opening bell (9:30 AM ET), +// midday (12:45 PM ET), or the closing bell (4:00 PM ET), whichever comes +// first, Mon-Fri only. We wake for these three events, so the ticker refreshes +// three times per session. +uint64_t usUntilNextEvent(const struct tm& et) { + const long events[3] = { EVT_OPEN, EVT_MID, EVT_CLOSE }; + long secsToday = et.tm_hour * 3600 + et.tm_min * 60 + et.tm_sec; + for (int d = 0; d <= 7; d++) { + int wd = (et.tm_wday + d) % 7; + if (wd < 1 || wd > 5) continue; // skip Sat/Sun + long base = (long)d * 86400 - secsToday; + long best = -1; + for (int e = 0; e < 3; e++) { + long cand = base + events[e]; + if (cand > 0 && (best < 0 || cand < best)) best = cand; + } + if (best > 0) return (uint64_t)best * 1000000ULL; + } + return 24ULL * 3600ULL * 1000000ULL; // fallback: 24h +} + // ------------------------------------------------------- // Setup // -------------------------------------------------------