diff --git a/Sming/Libraries/Timezone b/Sming/Libraries/Timezone index 9af032b5b5..7822de2ee4 160000 --- a/Sming/Libraries/Timezone +++ b/Sming/Libraries/Timezone @@ -1 +1 @@ -Subproject commit 9af032b5b5820434f94c715a39da787b7ab8301b +Subproject commit 7822de2ee445892c9935bd2b11a465a5060e468b diff --git a/Tools/ci/build.cmd b/Tools/ci/build.cmd index 8744dc8fbf..3f4d7185ae 100644 --- a/Tools/ci/build.cmd +++ b/Tools/ci/build.cmd @@ -36,6 +36,8 @@ REM HostTests must build for all architectures REM Building Bear SSL library causes memory issues with CI builds in Windows, so avoid for now %MAKE_PARALLEL% -C "%SMING_PROJECTS_DIR%/tests/HostTests" %TEST_FLAGS% || goto :error +%MAKE_PARALLEL% -C "%SMING_HOME%" SystemClock_NTP || goto :error + REM Start Arch-specific tests cd /d %SMING_HOME% call Arch\%SMING_ARCH%\Tools\ci\build.run.cmd || goto :error diff --git a/samples/SystemClock_NTP/app/NtpClientDemo.cpp b/samples/SystemClock_NTP/app/NtpClientDemo.cpp index 8fb026c185..aefa2bf30f 100644 --- a/samples/SystemClock_NTP/app/NtpClientDemo.cpp +++ b/samples/SystemClock_NTP/app/NtpClientDemo.cpp @@ -2,40 +2,71 @@ #include #include #include +#include +#include -namespace +namespace MyZone { +using namespace TZ; /* * For handling local/UTC time conversions * This is for the UK, amend as required */ -const TimeChangeRule dstStart{"BST", Last, Sun, Mar, 1, 60}; -const TimeChangeRule stdStart{"GMT", Last, Sun, Oct, 2, 0}; -Timezone tz(dstStart, stdStart); +const Rule dstStart{"BST", Last, Sun, Mar, 1, 60}; +const Rule stdStart{"GMT", Last, Sun, Oct, 2, 0}; + +// Posix rule string +DEFINE_FSTR_LOCAL(tzstr, "GMT0BST,M3.5.0/1,M10.5.0") + +// Sunrise/sunset requires co-ordinates +SolarRef solarRef = {51.4769, 0.0005}; // Greenwich, London + +} // namespace MyZone + +namespace +{ +// We can initialise timezone in various ways +// Timezone tz = Timezone::fromPosix(MyZone::tzstr); +// Timezone tz(MyZone::dstStart, MyZone::stdStart); +Timezone tz = TZ::Europe::London(); /* * We use the y/m/d from local time for sunrise/sunset calculations, and the solar calculator * returns the time from midnight in UTC for that day. We therefore need to adjust this * to account for timezone and daylight savings. */ -time_t getNextSunriseSet(bool isSunrise) +ZonedTime getNextSunriseSet(bool isSunrise) { - auto timeNow = SystemClock.now(eTZ_Local); - DateTime dt(timeNow); + auto utcNow = SystemClock.now(eTZ_UTC); + DateTime dt(tz.toLocal(utcNow)); dt.Hour = 0; dt.Minute = 0; dt.Second = 0; - SolarCalculator calc; + SolarCalculator calc(MyZone::solarRef); int offset_secs = SECS_PER_MIN * calc.sunRiseSet(isSunrise, dt.Year, dt.Month + 1, dt.Day); - time_t t = tz.toLocal(dt + offset_secs); + time_t utcNext = dt + offset_secs; // If time has already passed, then make it tomorrow - if(t < timeNow) { - t = tz.toLocal(dt + offset_secs + SECS_PER_DAY); + if(utcNext < utcNow) { + utcNext += SECS_PER_DAY; } - return t; + return tz.makeZoned(utcNext); +} + +void checkTimeZoneOffset(time_t systemTime) +{ + static ZonedTime nextChange{TZ::invalidTime}; + + if(nextChange == TZ::invalidTime) { + nextChange = tz.makeZoned(systemTime); + } else if(systemTime < nextChange) { + return; + } + + SystemClock.setTimeZone(nextChange.getZoneInfo()); + nextChange = tz.getNextChange(systemTime); } } // namespace @@ -46,9 +77,10 @@ void NtpClientDemo::ntpResult(NtpClient& client, time_t ntpTime) * Update the system clock and calculate the correct time offset, * accounting for time zone and daylight savings. */ - auto localTime = tz.toLocal(ntpTime); SystemClock.setTime(ntpTime, eTZ_UTC); - SystemClock.setTimeZoneOffset(localTime - ntpTime); + + // Now we've set the clock, we can determine the initial active timezone and maintain the offset + SystemClock.onCheckTimeZoneOffset([this](time_t systemTime) { checkTimeZoneOffset(systemTime); }); /* * Display the new time @@ -60,8 +92,29 @@ void NtpClientDemo::ntpResult(NtpClient& client, time_t ntpTime) /* * Display times of next sunrise and sunset */ - DateTime sunrise = getNextSunriseSet(true); - DateTime sunset = getNextSunriseSet(false); - Serial << _F("Next sunrise at ") << sunrise.toShortTimeString() << _F(", sunset at ") << sunset.toShortTimeString() - << endl; + ZonedTime sunrise = getNextSunriseSet(true); + ZonedTime sunset = getNextSunriseSet(false); + Serial << _F("Next sunrise ") << sunrise.toString() << _F(", sunset ") << sunset.toString() << endl; + + /* + * Display points at which daylight savings changes. + */ + if(!tz.hasDaylightSavings()) { + Serial << _F("Selected timezone has no daylight savings.") << endl; + return; + } + + DateTime dt(ntpTime); + + Serial << _F("In ") << dt.Year << _F(", daylight savings:") << endl; + ZonedTime dst = tz.getTransition(dt.Year, true); + ZonedTime transition = tz.makeZoned(dst, true); + Serial << _F(" Starts: ") << transition.toString() << " (" << dst.toUtc().toString() << ")" << endl; + + ZonedTime std = tz.getTransition(dt.Year, false); + transition = tz.makeZoned(std, true); + Serial << _F(" Ends: ") << transition.toString() << " (" << std.toUtc().toString() << ")" << endl; + + ZonedTime nextChange = tz.getNextChange(ntpTime); + Serial << _F("Next change to ") << nextChange.tag() << _F(" on ") << nextChange.toUtc().toString() << endl; } diff --git a/samples/SystemClock_NTP/include/NtpClientDemo.h b/samples/SystemClock_NTP/include/NtpClientDemo.h index 037bf76cb2..d12c502963 100644 --- a/samples/SystemClock_NTP/include/NtpClientDemo.h +++ b/samples/SystemClock_NTP/include/NtpClientDemo.h @@ -1,8 +1,6 @@ #pragma once #include -#include -#include class NtpClientDemo {