From 9432f835fd83cbe46510f3d165d65b284f31c4b6 Mon Sep 17 00:00:00 2001 From: Brian Park Date: Fri, 5 May 2023 18:11:17 -0700 Subject: [PATCH 01/21] ZonedDateTimeExtendedTest: Fix typo --- tests/ZonedDateTimeExtendedTest/ZonedDateTimeExtendedTest.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ZonedDateTimeExtendedTest/ZonedDateTimeExtendedTest.ino b/tests/ZonedDateTimeExtendedTest/ZonedDateTimeExtendedTest.ino index 5fb0497d5..b92aea28a 100644 --- a/tests/ZonedDateTimeExtendedTest/ZonedDateTimeExtendedTest.ino +++ b/tests/ZonedDateTimeExtendedTest/ZonedDateTimeExtendedTest.ino @@ -391,7 +391,7 @@ test(ZonedDateTimeExtendedTest, normalize) { assertEqual(0, dt.minute()); assertEqual(0, dt.second()); - // Set the date/time to 2021-04-20T11:00:00, which happens to be in DST. + // Set the date/time to 2021-04-20T09:00:00, which happens to be in DST. dt.year(2021); dt.month(4); dt.day(20); From 477b53189998e92bd9cf18e87efa414e44fbda1b Mon Sep 17 00:00:00 2001 From: Brian Park Date: Fri, 5 May 2023 18:12:37 -0700 Subject: [PATCH 02/21] testing:*.h: Support splitting test_items into 'transitions' and 'samples' --- src/ace_time/testing/BasicTransitionTest.h | 20 ++++++- src/ace_time/testing/ExtendedTransitionTest.h | 52 ++++++++++++------- src/ace_time/testing/ValidationDataType.h | 6 ++- 3 files changed, 56 insertions(+), 22 deletions(-) diff --git a/src/ace_time/testing/BasicTransitionTest.h b/src/ace_time/testing/BasicTransitionTest.h index fcaf779ae..a9b7a416c 100644 --- a/src/ace_time/testing/BasicTransitionTest.h +++ b/src/ace_time/testing/BasicTransitionTest.h @@ -42,9 +42,25 @@ class BasicTransitionTest: public aunit::TestOnce { BasicZoneProcessor zoneProcessor; TimeZone tz = TimeZone::forZoneInfo(zoneInfo, &zoneProcessor); + assertNoFatalFailure(checkTestItems( + zoneProcessor, tz, testData->numTransitions, testData->transitions, + dstValidationScope, abbrevValidationScope)); + assertNoFatalFailure(checkTestItems( + zoneProcessor, tz, testData->numSamples, testData->samples, + dstValidationScope, abbrevValidationScope)); + } + + void checkTestItems( + BasicZoneProcessor& zoneProcessor, + TimeZone& tz, + uint16_t numItems, + const ValidationItem* const items, + ValidationScope dstValidationScope, + ValidationScope abbrevValidationScope) { + bool passed = true; - for (uint16_t i = 0; i < testData->numItems; i++) { - const ValidationItem& item = testData->items[i]; + for (uint16_t i = 0; i < numItems; i++) { + const ValidationItem& item = items[i]; acetime_t epochSeconds = item.epochSeconds; ZonedDateTime dt = ZonedDateTime::forEpochSeconds(epochSeconds, tz); diff --git a/src/ace_time/testing/ExtendedTransitionTest.h b/src/ace_time/testing/ExtendedTransitionTest.h index fa5880a62..e3c43f960 100644 --- a/src/ace_time/testing/ExtendedTransitionTest.h +++ b/src/ace_time/testing/ExtendedTransitionTest.h @@ -47,9 +47,41 @@ class ExtendedTransitionTest: public aunit::TestOnce { ExtendedZoneProcessor zoneProcessor; TimeZone tz = TimeZone::forZoneInfo(zoneInfo, &zoneProcessor); + assertNoFatalFailure(checkTestItems( + zoneProcessor, tz, testData->numTransitions, testData->transitions, + dstValidationScope, abbrevValidationScope)); + assertNoFatalFailure(checkTestItems( + zoneProcessor, tz, testData->numSamples, testData->samples, + dstValidationScope, abbrevValidationScope)); + + // Assert that the TransitionStorage buffer size is exactly the buffer + // size calculated from zone_processor.py. + if (expectedBufSize) { + zoneProcessor.resetTransitionAllocSize(); + // Include (startYear - 1) and (untilYear + 1) because the local year + // may shift slightly when converting from an epochSeconds. + for ( + int y = testData->startYear - 1; + y < testData->untilYear + 1; + y++) { + zoneProcessor.initForYear(y); + } + uint8_t observedBufSize = zoneProcessor.getTransitionAllocSize(); + assertLessOrEqual(observedBufSize, expectedBufSize); + } + } + + void checkTestItems( + ExtendedZoneProcessor& zoneProcessor, + TimeZone& tz, + uint16_t numItems, + const ValidationItem* const items, + ValidationScope dstValidationScope, + ValidationScope abbrevValidationScope) { + bool passed = true; - for (uint16_t i = 0; i < testData->numItems; i++) { - const ValidationItem& item = testData->items[i]; + for (uint16_t i = 0; i < numItems; i++) { + const ValidationItem& item = items[i]; acetime_t epochSeconds = item.epochSeconds; ZonedDateTime dt = ZonedDateTime::forEpochSeconds(epochSeconds, tz); @@ -91,22 +123,6 @@ class ExtendedTransitionTest: public aunit::TestOnce { } } assertTrue(passed); - - // Assert that the TransitionStorage buffer size is exactly the buffer - // size calculated from zone_processor.py. - if (expectedBufSize) { - zoneProcessor.resetTransitionAllocSize(); - // Include (startYear - 1) and (untilYear + 1) because the local year - // may shift slightly when converting from an epochSeconds. - for ( - int y = testData->startYear - 1; - y < testData->untilYear + 1; - y++) { - zoneProcessor.initForYear(y); - } - uint8_t observedBufSize = zoneProcessor.getTransitionAllocSize(); - assertLessOrEqual(observedBufSize, expectedBufSize); - } } void checkComponent(bool& passed, int i, const ValidationItem& item, diff --git a/src/ace_time/testing/ValidationDataType.h b/src/ace_time/testing/ValidationDataType.h index 92752be4b..77f202fa8 100644 --- a/src/ace_time/testing/ValidationDataType.h +++ b/src/ace_time/testing/ValidationDataType.h @@ -52,8 +52,10 @@ struct ValidationData { int const startYear; int const untilYear; int const epochYear; - uint16_t const numItems; - const ValidationItem* const items; + uint16_t const numTransitions; + const ValidationItem* const transitions; + uint16_t const numSamples; + const ValidationItem* const samples; }; } From be31ae92beac7bd34b98ddb5e098a6fc8e289a1a Mon Sep 17 00:00:00 2001 From: Brian Park Date: Sun, 7 May 2023 17:10:45 -0700 Subject: [PATCH 03/21] CHANGELOG.md: update --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a9baa96f..26a5b35dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog * Unreleased + * Update `ace_time/testing/*` classes to support splitting the test data + into 2 separate lists: `transitions` and `samples`. + * Required to support new `validation_data.json` from AceTimeValidation. * 2.2.2 (2023-04-01, TZDB version 2023c) * Upgrade TZDB from 2023b to 2023c. * https://mm.icann.org/pipermail/tz-announce/2023-March/000079.html From 7291d2970def5f59ba927474c92a1dc9b3281b20 Mon Sep 17 00:00:00 2001 From: Brian Park Date: Thu, 11 May 2023 16:24:57 -0700 Subject: [PATCH 04/21] USER_GUIDE.md: Add documentation for 'kAbbrevSize' --- USER_GUIDE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 052319d56..cf4bf9c5c 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -1591,7 +1591,9 @@ The `ZonedExtra::abbrev()` is the short abbreviation that is in effect at the given time instant. For example, for `America/Los_Angeles`, this returns "PST" or "PDT'. The abbreviation is copied into a small `char` buffer inside the `ZonedExtra` object, so the pointer returned by `abbrev()` is safe to use during -the life of the `ZonedExtra` object. +the life of the `ZonedExtra` object. The maximum `char` buffer size needed hold +any abbreviation is given by `ace_time::kAbbrevSize`. This is currently defined +as 7, which means the longest abbreviation is 6 characters long. The `ZonedExtra::reqStdOffset()` and `ZonedExtra::reqDstOffset()` are relevant and different from the corresponding `stdOffset()` and `dstOffset()` only if the From 73e1ed7c6525120434461846f9a7176a7e0c8acb Mon Sep 17 00:00:00 2001 From: Brian Park Date: Thu, 11 May 2023 16:39:27 -0700 Subject: [PATCH 05/21] github/workflow+various: Update names of AceTimeValidation/tests/*Test --- .github/workflows/validation.yml | 8 ++--- CHANGELOG.md | 13 ++++--- DEVELOPER.md | 36 +++++++++---------- README.md | 4 +-- .../CompareAceTimeToHinnantDate.ino | 2 +- src/ace_time/ExtendedZoneProcessor.h | 7 ++-- 6 files changed, 35 insertions(+), 35 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index b3c213770..77a66df9a 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -57,8 +57,8 @@ jobs: sudo apt update sudo apt install -y libcurl4-openssl-dev - # Run the validations from AceTimeValidations (BasicHinnantDateTest, - # ExtendedHinnantDateTest, BasicAcetzTest, ExtendedAcetzTest). We don't run + # Run the validations from AceTimeValidations (HinnantBasicTest, + # HinnantExtendedTest, AcetzBasicTest, AcetzExtendedTest). We don't run # the others because when a new TZDB version comes out, the Python # zoneinfo, Python pytz, Python dateutil, and Java validation tests will # fail because they depend on the obsolete TZ database on the host @@ -67,5 +67,5 @@ jobs: - name: AceTimeValidation run: | cd ../AceTimeValidation - make validations - make runvalidations + make -C tools validations + make -C tools runvalidations diff --git a/CHANGELOG.md b/CHANGELOG.md index 26a5b35dd..33185e0ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -546,12 +546,11 @@ * Run the Noda Time `TzdbCompiler` manually to generate custom `tzdata$(TZ_VERSION).nzd` for the specific TZDB version specified in the Makefile. - * Add `tests/validation/BasicNodaTest` which matches AceTime completely - from year 2000 until 2050. + * Add `tests/validation/tests/NodaBasicTest` which matches AceTime + completely from year 2000 until 2050. * Add `tests/validation/ExtendedNodaTest` which maches AceTime completely from year 1974 until 2050. - * Identical results to `BasicHinnantDateTest` and - `ExtendedHinnantDateTest`. + * Identical results to `HinnantBasicTest` and `HinnantExtendedTest`. * Add `ace_time::clock::Stm32F1Clock` and `ace_time::hw::Stm32F1Rtc` * Specialized classes for the STM32F1 chip, particularly the Blue Pill board, using the `LSE_CLOCK` (low speed external clock). @@ -578,7 +577,7 @@ but only 50-60 bytes on other 32-bit processors. * Finish a working implementation of `acetz.py`. * Includes support for `fold`. - * Create `BasicAcetzTest` and `ExtendedAcetzTest` and verify all zones + * Create `AcetzBasicTest` and `AcetzExtendedTest` and verify all zones validate. * Time zone short names are printed with spaces instead of underscore. * Various `printShortNameTo()` and `printShortTo()` methods now print @@ -915,8 +914,8 @@ * Upgrade to TZDB 2020c (https://mm.icann.org/pipermail/tz-announce/2020-October/000060.html) * "Fiji starts DST later than usual, on 2020-12-20." - * Restrict GitHub Actions workflow to run just BasicHinnantDateTest and - ExtendedHinnantDateTest, because the other Python and Java tests break + * Restrict GitHub Actions workflow to run just HinnantBasicTest and + HinnantExtendedTest, because the other Python and Java tests break every time a new TZDB version comes out. * Add `DEVELOPER.md` file containing notes mostly for myself. * 1.1 (2020-04-25, TZ DB version 2020a) diff --git a/DEVELOPER.md b/DEVELOPER.md index c34b071db..8b824bd03 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -585,8 +585,8 @@ available. should be a sibling to the `AceTime` repo: * `$ cd ../date` * `$ git pull` -* Update the zonedb files for AceTimePython (needed by BasicAcetzTest and - ExtendedAcetzTest): +* Update the zonedb files for AceTimePython (needed by AcetzBasicTest and + AcetzExtendedTest): * `$ cd AceTimePython/src/acetime/zonedb` * Update the `TZ_VERSION` variable in `Makefile`. * `$ make` @@ -594,10 +594,10 @@ available. AceTimePython and the Hinnant `date` library): * `$ cd ../AceTimeValidation` * Update the `TZ_VERSION` variable in the following files: - * `BasicAcetzTest/Makefile` - * `ExtendedAcetzTest/Makefile` - * `BasicHinnantDateTest/Makefile` - * `ExtendedHinnantDateTest/Makefile` + * `tests/AcetzBasicTest/Makefile` + * `tests/AcetExtendedzTest/Makefile` + * `tests/HinnantBasicTest/Makefile` + * `tests/HinnantExtendedTest/Makefile` * `$ make clean` * `$ make validations` * `$ make runvalidations` @@ -616,18 +616,18 @@ available. There are 12 other validation tests in the AceTimeValidation project that compare AceTime with various other third party libraries: -* `BasicDateUtilTest` -* `BasicGoTest` -* `BasicJavaTest` -* `BasicNodaTest` -* `BasicPytzTest` -* `BasicZoneInfoTest` -* `ExtendedDateUtilTest` -* `ExtendedGoTest` -* `ExtendedJavaTest` -* `ExtendedNodaTest` -* `ExtendedPytzTest` -* `ExtendedZoneInfoTest` +* `DateUtilBasicTest` +* `DateUtilExtendedTest` +* `GoBasicTest` +* `GoExtendedTest` +* `JavaBasicTest` +* `JavaExtendedTest` +* `NodaBasicTest` +* `NodaExtendedTest` +* `PytzBasicTest` +* `PytzExtendedTest` +* `ZoneInfoBasicTest` +* `ZoneInfoExtendedTest` Unfortunately, they all seem to use the underlying TZDB version provided by the Operating System, and I have not been able to figure out how to manually update diff --git a/README.md b/README.md index eb6a59884..fe1873f12 100644 --- a/README.md +++ b/README.md @@ -1140,9 +1140,9 @@ environment because: library. The Hinnant date libraries were invaluable for writing the -[BasicHinnantDateTest](https://github.com/bxparks/AceTimeValidation/tree/master/BasicHinnantDateTest) +[HinnantBasicTest](https://github.com/bxparks/AceTimeValidation/tree/master/tests/HinnantBasicTest) and -[ExtendedHinnantDateTest](https://github.com/bxparks/AceTimeValidation/tree/master/ExtendedHinnantDateTest) +[HinnantExtendedTest](https://github.com/bxparks/AceTimeValidation/tree/master/tests/HinnantExtendedTest) validation tests which compare the AceTime algorithms to the Hinnant Date algorithms. For all times zones between the years 2000 until 2100, the AceTime date-time components (`ZonedDateTime`) and abbreviations (`ZonedExtra`) diff --git a/examples/CompareAceTimeToHinnantDate/CompareAceTimeToHinnantDate.ino b/examples/CompareAceTimeToHinnantDate/CompareAceTimeToHinnantDate.ino index 919be4d21..b372efede 100644 --- a/examples/CompareAceTimeToHinnantDate/CompareAceTimeToHinnantDate.ino +++ b/examples/CompareAceTimeToHinnantDate/CompareAceTimeToHinnantDate.ino @@ -5,7 +5,7 @@ * hh:mm:ss) into epoch seconds. * * The zones.txt file comes from - * AceTimeValidation/ExtendedHinnantDate/zonedbxhd/zones.txt. + * AceTimeValidation/tests/HinnantExtendedTest/zonedbxhd/zones.txt. * * To compile the binary, type: * diff --git a/src/ace_time/ExtendedZoneProcessor.h b/src/ace_time/ExtendedZoneProcessor.h index 33f71f8ba..8b443c20f 100644 --- a/src/ace_time/ExtendedZoneProcessor.h +++ b/src/ace_time/ExtendedZoneProcessor.h @@ -99,9 +99,10 @@ class ExtendedZoneProcessorTemplate: public ZoneProcessor { * each Zone is given by the kZoneBufSize{zoneName} constant in the * generated `zonedb[x]/zone_infos.h` file. The maximum over all zones is * given in the 'MaxBufSize' comment in the `zone_infos.h` file. Currently - * that overall maximum is 7, which has been verified by the - * ExtendedDateUtilTest, ExtendedJavaTest, and ExtendedAcetzTest validation - * tests. We set this to one more than 7 for safety. + * that overall maximum is 7, which has been verified by various tests (e.g. + * HinnantExtendedTest, DateUtilExtendedTest, JavaExtendedTest, and + * AcetzExtendedTest) in the AceTimeValidation project. We set this to one + * more than 7 for safety. */ static const uint8_t kMaxTransitions = 8; From b6368b95775b7c7a9a0effb8977cdce61a31df9c Mon Sep 17 00:00:00 2001 From: Brian Park Date: Thu, 11 May 2023 16:42:30 -0700 Subject: [PATCH 06/21] github/workflows: Fix typo, tools -> tests --- .github/workflows/validation.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index 77a66df9a..c848665b3 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -67,5 +67,5 @@ jobs: - name: AceTimeValidation run: | cd ../AceTimeValidation - make -C tools validations - make -C tools runvalidations + make -C tests validations + make -C tests runvalidations From 5b0bc4311ca34e5e40b495c5049d6d2989554b53 Mon Sep 17 00:00:00 2001 From: Brian Park Date: Thu, 11 May 2023 16:59:22 -0700 Subject: [PATCH 07/21] ZonedExtra.h: Add ZonedExtra::kAbbrevSize --- CHANGELOG.md | 6 ++++++ USER_GUIDE.md | 10 +++++++--- src/ace_time/ZonedExtra.h | 5 ++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33185e0ba..fc5bc6a23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ * Update `ace_time/testing/*` classes to support splitting the test data into 2 separate lists: `transitions` and `samples`. * Required to support new `validation_data.json` from AceTimeValidation. + * Update `AceTimeValidation` test names to `tests/Xxx{Basic,Extended}Test`. + * Add `ZonedExtra::kAbbrevSize` to define the `char` buffer size needed to + hold an abbreviation. + * Change `ZonedExtra::kInvalidMinutes` from public to private. + * This is an implementation detail. + * Use `ZonedExtra::isError()` instead. * 2.2.2 (2023-04-01, TZDB version 2023c) * Upgrade TZDB from 2023b to 2023c. * https://mm.icann.org/pipermail/tz-announce/2023-March/000079.html diff --git a/USER_GUIDE.md b/USER_GUIDE.md index cf4bf9c5c..9c55ea15c 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -1508,6 +1508,8 @@ namespace ace_time { class ZonedExtra { public: + static const uint8_t kAbbrevSize = 6 + 1; + static const uint8_t kTypeNotFound = 0; static const uint8_t kTypeExact = 1; static const uint8_t kTypeGap = 2; @@ -1591,9 +1593,11 @@ The `ZonedExtra::abbrev()` is the short abbreviation that is in effect at the given time instant. For example, for `America/Los_Angeles`, this returns "PST" or "PDT'. The abbreviation is copied into a small `char` buffer inside the `ZonedExtra` object, so the pointer returned by `abbrev()` is safe to use during -the life of the `ZonedExtra` object. The maximum `char` buffer size needed hold -any abbreviation is given by `ace_time::kAbbrevSize`. This is currently defined -as 7, which means the longest abbreviation is 6 characters long. +the life of the `ZonedExtra` object. + +The `ZonedExtra::kAbbrevSize` defines the `char` buffer size needed to hold any +abbreviation. This is currently defined as 7, which means the longest +abbreviation is 6 characters long. The `ZonedExtra::reqStdOffset()` and `ZonedExtra::reqDstOffset()` are relevant and different from the corresponding `stdOffset()` and `dstOffset()` only if the diff --git a/src/ace_time/ZonedExtra.h b/src/ace_time/ZonedExtra.h index b84a78c71..63d4413cd 100644 --- a/src/ace_time/ZonedExtra.h +++ b/src/ace_time/ZonedExtra.h @@ -18,7 +18,8 @@ class LocalDateTime; class ZonedExtra { public: - static const int16_t kInvalidMinutes = INT16_MIN; + /** Size of char buffer needed to hold the largest abbreviation. */ + static const uint8_t kAbbrevSize = internal::kAbbrevSize; /** * The epochSeconds or LocalDateTime was not found because it was outside @@ -165,6 +166,8 @@ class ZonedExtra { const char* abbrev() const { return mAbbrev; } private: + static const int16_t kInvalidMinutes = INT16_MIN; + int16_t mStdOffsetMinutes = kInvalidMinutes; int16_t mDstOffsetMinutes = kInvalidMinutes; int16_t mReqStdOffsetMinutes = kInvalidMinutes; From 6d60ac1808397f6cad0114da5d3bcba502661274 Mon Sep 17 00:00:00 2001 From: Brian Park Date: Mon, 15 May 2023 12:17:35 -0700 Subject: [PATCH 08/21] *ZoneProcessor.h: replace out-of-band 'mIsFilled' flag Use mYear==kInvalidYear instead, which is an in-band indicator that the cache is invalid. This prevents a recurring bug in different libraries, where I fill the cache, but forget to mark it as filled, causing huge performance problems because the cache isn't being used. --- src/ace_time/BasicZoneProcessor.h | 3 --- src/ace_time/ExtendedZoneProcessor.h | 2 -- src/ace_time/ZoneProcessor.h | 15 ++++++++++++--- .../BasicZoneProcessorTest.ino | 9 +++++---- .../ExtendedZoneProcessorTest.ino | 9 +++++---- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/ace_time/BasicZoneProcessor.h b/src/ace_time/BasicZoneProcessor.h index 9c82a2c63..4fedd7377 100644 --- a/src/ace_time/BasicZoneProcessor.h +++ b/src/ace_time/BasicZoneProcessor.h @@ -325,7 +325,6 @@ class BasicZoneProcessorTemplate: public ZoneProcessor { mZoneInfoBroker = mBrokerFactory->createZoneInfoBroker(zoneKey); mYear = LocalDate::kInvalidYear; - mIsFilled = false; mNumTransitions = 0; } @@ -478,8 +477,6 @@ class BasicZoneProcessorTemplate: public ZoneProcessor { calcTransitions(); calcAbbreviations(); - mIsFilled = true; - if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) { log(); } diff --git a/src/ace_time/ExtendedZoneProcessor.h b/src/ace_time/ExtendedZoneProcessor.h index 8b443c20f..4a3918ba3 100644 --- a/src/ace_time/ExtendedZoneProcessor.h +++ b/src/ace_time/ExtendedZoneProcessor.h @@ -282,7 +282,6 @@ class ExtendedZoneProcessorTemplate: public ZoneProcessor { mZoneInfoBroker = mBrokerFactory->createZoneInfoBroker(zoneKey); mYear = LocalDate::kInvalidYear; - mIsFilled = false; mNumMatches = 0; resetTransitionAllocSize(); // clear the alloc size for new zone } @@ -381,7 +380,6 @@ class ExtendedZoneProcessorTemplate: public ZoneProcessor { calcAbbreviations(begin, end); if (ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG) { log(); } - mIsFilled = true; return true; } diff --git a/src/ace_time/ZoneProcessor.h b/src/ace_time/ZoneProcessor.h index 5143c72b0..b86b1bf8c 100644 --- a/src/ace_time/ZoneProcessor.h +++ b/src/ace_time/ZoneProcessor.h @@ -147,7 +147,7 @@ class ZoneProcessor { * Reset the internal transition cache. Useful when * Epoch::currentEpochYear() is changed at runtime. */ - void resetTransitionCache() { mIsFilled = false; } + void resetTransitionCache() { mYear = LocalDate::kInvalidYear; } /** Return true if timezone is a Link entry pointing to a Zone entry. */ virtual bool isLink() const = 0; @@ -230,7 +230,7 @@ class ZoneProcessor { /** Check if the Transition cache is filled for the given year. */ bool isFilled(int16_t year) const { - return mIsFilled && (year == mYear); + return year == mYear; } /** Return true if equal. */ @@ -238,8 +238,17 @@ class ZoneProcessor { protected: // The order of the fields is optimized to save space on 32-bit processors. + /** + * User-visible indicator of the subclass of ZoneProcessor, which implments + * a specific time-zone algorithm. Three common ones are + * BasicZoneProcessor::kTypeBasic and ExtendedZoneProcessor::kTypeExtended. + */ uint8_t const mType; - mutable bool mIsFilled = false; + + /** + * Year that was used to calculate the transitions in the current cache. Set + * to LocalDate::kInvalidYear to indicate invalid cache. + */ mutable int16_t mYear = LocalDate::kInvalidYear; }; diff --git a/tests/BasicZoneProcessorTest/BasicZoneProcessorTest.ino b/tests/BasicZoneProcessorTest/BasicZoneProcessorTest.ino index 35c7de0eb..06a2210c1 100644 --- a/tests/BasicZoneProcessorTest/BasicZoneProcessorTest.ino +++ b/tests/BasicZoneProcessorTest/BasicZoneProcessorTest.ino @@ -299,17 +299,18 @@ test(BasicZoneProcessorTest, createAbbreviation) { test(BasicZoneProcessorTest, setZoneKey) { BasicZoneProcessor zoneProcessor(&kZoneAmerica_Los_Angeles); + assertEqual(zoneProcessor.mYear, LocalDate::kInvalidYear); zoneProcessor.initForEpochSeconds(0); - assertTrue(zoneProcessor.mIsFilled); + assertNotEqual(zoneProcessor.mYear, LocalDate::kInvalidYear); zoneProcessor.setZoneKey((uintptr_t) &kZoneAustralia_Darwin); - assertFalse(zoneProcessor.mIsFilled); + assertEqual(zoneProcessor.mYear, LocalDate::kInvalidYear); zoneProcessor.initForEpochSeconds(0); - assertTrue(zoneProcessor.mIsFilled); + assertNotEqual(zoneProcessor.mYear, LocalDate::kInvalidYear); // Check that the cache remains valid if the zoneInfo does not change zoneProcessor.setZoneKey((uintptr_t) &kZoneAustralia_Darwin); - assertTrue(zoneProcessor.mIsFilled); + assertNotEqual(zoneProcessor.mYear, LocalDate::kInvalidYear); } // https://www.timeanddate.com/time/zone/usa/los-angeles diff --git a/tests/ExtendedZoneProcessorTest/ExtendedZoneProcessorTest.ino b/tests/ExtendedZoneProcessorTest/ExtendedZoneProcessorTest.ino index f6f1ac609..7c3a8b6f6 100644 --- a/tests/ExtendedZoneProcessorTest/ExtendedZoneProcessorTest.ino +++ b/tests/ExtendedZoneProcessorTest/ExtendedZoneProcessorTest.ino @@ -867,17 +867,18 @@ test(ExtendedZoneProcessorTest, createAbbreviation) { test(ExtendedZoneProcessorTest, setZoneKey) { ExtendedZoneProcessor zoneProcessor(&kZoneAmerica_Los_Angeles); + assertEqual(zoneProcessor.mYear, LocalDate::kInvalidYear); zoneProcessor.initForEpochSeconds(0); - assertTrue(zoneProcessor.mIsFilled); + assertNotEqual(zoneProcessor.mYear, LocalDate::kInvalidYear); zoneProcessor.setZoneKey((uintptr_t) &kZoneAustralia_Darwin); - assertFalse(zoneProcessor.mIsFilled); + assertEqual(zoneProcessor.mYear, LocalDate::kInvalidYear); zoneProcessor.initForEpochSeconds(0); - assertTrue(zoneProcessor.mIsFilled); + assertNotEqual(zoneProcessor.mYear, LocalDate::kInvalidYear); // Check that the cache remains valid if the zoneInfo does not change zoneProcessor.setZoneKey((uintptr_t) &kZoneAustralia_Darwin); - assertTrue(zoneProcessor.mIsFilled); + assertNotEqual(zoneProcessor.mYear, LocalDate::kInvalidYear); } test(ExtendedZoneProcessorTest, printNameTo) { From 6c6db57090f00de5e93668b897184614177162cd Mon Sep 17 00:00:00 2001 From: Brian Park Date: Wed, 17 May 2023 20:43:28 -0700 Subject: [PATCH 09/21] Rename AceTimePython to acetimepy --- .github/workflows/validation.yml | 6 ++-- CHANGELOG.md | 9 +++--- DEVELOPER.md | 48 ++++++++++++++-------------- README.md | 2 +- src/ace_time/ExtendedZoneProcessor.h | 3 +- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index c848665b3..cce12fa5b 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -31,7 +31,7 @@ jobs: git clone --depth 1 https://github.com/bxparks/AceCommon git clone --depth 1 https://github.com/bxparks/AceSorting git clone --depth 1 https://github.com/bxparks/AceTimeTools - git clone --depth 1 https://github.com/bxparks/AceTimePython + git clone --depth 1 https://github.com/bxparks/acetimepy git clone --depth 1 https://github.com/bxparks/AceTimeValidation git clone --depth 1 https://github.com/HowardHinnant/date git clone https://github.com/eggert/tz @@ -49,8 +49,8 @@ jobs: python -m pip install --upgrade pip pip install -r ../AceTimeTools/requirements.txt pip install -e ../AceTimeTools - pip install -r ../AceTimePython/requirements.txt - pip install -e ../AceTimePython + pip install -r ../acetimepy/requirements.txt + pip install -e ../acetimepy - name: Install libcurl4-openssl-dev run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index fc5bc6a23..8f5607fe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * Change `ZonedExtra::kInvalidMinutes` from public to private. * This is an implementation detail. * Use `ZonedExtra::isError()` instead. + * Rename AceTimePython to acetimepy. * 2.2.2 (2023-04-01, TZDB version 2023c) * Upgrade TZDB from 2023b to 2023c. * https://mm.icann.org/pipermail/tz-announce/2023-March/000079.html @@ -396,7 +397,7 @@ * All of these methods were intended for internal debugging so these changes are not considered to be an API change. * The semantics of these methods are now closer to the algorithm in - `AceTimePython/zone_processor.ZoneProcessor`. + `acetimepy/zone_processor.py`. * **Breaking Change**: Extract `BasicZoneProcessorCache` and `ExtendedZoneProcessorCache` out of `BasicZoneManager` and `ExtendedZoneManager`. Remove all pure `virtual` methods from @@ -457,19 +458,19 @@ * They are now considered to happen at the same time if any of the 'w' time, 's' time, or 'u' time are equal. * The behavior of `ExtendedZoneProcessor.h` should now be identical - to `zone_processor.py` in the `AceTimePython` library. + to `zone_processor.py` in the `acetimepy` library. * Seems to affect only `Europe/Lisbon` in 1992, which is not a part of the predefined `zonedb` or `zonedbx` database, which normally include only 2000 until 2050. * Testing - * Create [AceTimePython](https://github.com/bxparks/AceTimePython) + * Create [acetimepy](https://github.com/bxparks/acetimepy) library extracted from the previously split [AceTimeTools](https://github.com/bxparks/AceTimeTools) project. * Update `ace_time/testing/ExtendedTransitionTest.h` to validate the exact equality between the observed maximum buffer size of TransitionStorage as observed by `ExtendedZoneProcessor` and the buffer size calculated by AceTimeTools using `zone_processor.py` of - `AceTimePython` library. + `acetimepy` library. * Create `examples/DebugZoneProcessor` for debugging the internal logic of `ExtendedZoneProcessor`. * Tool Chain diff --git a/DEVELOPER.md b/DEVELOPER.md index 8b824bd03..60d98a824 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -28,7 +28,7 @@ integration tests under `./tests/validation` were moved into the [AceTimeValidations](https://github.com/bxparks/AceTimeValidation) project. Then on 2021-09-08, the Python timezone classes (`zone_processor.py`, `acetz.py`, etc) were moved into the -[AceTimePython](https://github.com/bxparks/AceTimePython) project. +[acetimepy](https://github.com/bxparks/acetimepy) project. Here is the dependency diagram among these projects. @@ -36,30 +36,30 @@ Here is the dependency diagram among these projects. AceTimeTools -------- ^ ^ ^ \ artransformer.py creating / | \ creating \ -> bufestimator.py - zonedb[x] / | \ zonedb \ -> zone_processor.py - / | \ v - AceTime | AceTimePython + zonedb[x] / | \ zonedb / -> zone_processor.py + / | \ v + AceTime | acetimepy ^ ^ | ^ / \ | / / \ | / AceTimeClock AceTimeValidation ``` -There is slight circular dependency between `AceTimeTools` and `AceTimePython`. +There is slight circular dependency between `AceTimeTools` and `acetimepy`. -AceTimeTools needs AceTimePython when generating the C++ zoneinfo files under +AceTimeTools needs acetimepy when generating the C++ zoneinfo files under `AceTime/src/zonedb[x]`. The `tzcompiler.py` calls `bufestimator.py` to generate the buffer sizes needed by the C++ `ExtendedZoneProcessor` class. The -`AceTimeTools/bufestimator.py` module needs `AceTimePython/zone_processor.py` +`AceTimeTools/bufestimator.py` module needs `acetimepy/zone_processor.py` module to calculate those buffer sizes. -On the other hand, AceTimePython needs AceTimeTools to generate the zoneinfo -files under `AceTimePython/zonedb`, which are consumed by the `acetz.py` -module. Fortunately, AceTimePython does *not* need AceTimeTools during runtime, -so 3rd party consumers can incorporate AceTimePython without pulling in -AceTimeTools. +On the other hand, acetimepy needs AceTimeTools to generate the zoneinfo +files under `acetimepy/zonedb/`, which are consumed by the `acetz` and +`ZoneManager` classes. Fortunately, acetimepy does *not* need AceTimeTools +during runtime, so 3rd party consumers can incorporate acetimepy without pulling +in AceTimeTools. -Both AceTime and AceTimePython can be used as runtime libraries **without** +Both AceTime and acetimepy can be used as runtime libraries **without** pulling in the dependency to AceTimeTools (which is required only to generated the zoneinfo database files). @@ -585,13 +585,13 @@ available. should be a sibling to the `AceTime` repo: * `$ cd ../date` * `$ git pull` -* Update the zonedb files for AceTimePython (needed by AcetzBasicTest and +* Update the zonedb files for acetimepy (needed by AcetzBasicTest and AcetzExtendedTest): - * `$ cd AceTimePython/src/acetime/zonedb` + * `$ cd acetimepy/src/acetime/zonedb` * Update the `TZ_VERSION` variable in `Makefile`. * `$ make` * Verify that `AceTimeValidation` passes (which compares AceTime with - AceTimePython and the Hinnant `date` library): + acetimepy and the Hinnant `date` library): * `$ cd ../AceTimeValidation` * Update the `TZ_VERSION` variable in the following files: * `tests/AcetzBasicTest/Makefile` @@ -607,7 +607,7 @@ available. * `$ make` * Update CHANGELOGs * AceTime/CHANGELOG.md - * AceTimePython/CHANGELOG.md + * acetimepy/CHANGELOG.md * AceTimeValidation/CHANGELOG.md * Commit the changes to git * `$ git add ...` @@ -657,9 +657,9 @@ fail until the underlying timezone database of the OS is updated. * `$ git add .` * `$ git commit -m "..."` * `$ git push` -* (Optional) Create a new Release of AceTimePython +* (Optional) Create a new Release of acetimepy * (This should be done first, before AceTime) - * Go to https://github.com/bxparks/AceTimePython + * Go to https://github.com/bxparks/acetimepy * Bump version number on `develop`. * Merge `develop` into `master`. * Click on "Releases" @@ -670,7 +670,7 @@ fail until the underlying timezone database of the OS is updated. from `CHANGELOG.md`. * Click Publish release. * (Optional) Create a new Release of AceTimeTools - * (Depends on AceTimePython) + * (Depends on acetimepy) * Go to https://github.com/bxparks/AceTimeTools * Click on "Releases" * Click on "Draft a new release" @@ -680,7 +680,7 @@ fail until the underlying timezone database of the OS is updated. from `CHANGELOG.md`. * Click Publish release. * (Optional) Create a new Release of AceTimeValidation. - * (Depends on AceTimePython) + * (Depends on acetimepy) * Go to https://github.com/bxparks/AceTimeTools * Click on "Releases" * Click on "Draft a new release" @@ -690,7 +690,7 @@ fail until the underlying timezone database of the OS is updated. from `CHANGELOG.md`. * Click Publish release. * Create a new Release of AceTime (third, depends on AceTimeValidation). - * (Depends on AceTimePython, AceTimeValidation) + * (Depends on acetimepy, AceTimeValidation) * Go to https://github.com/bxparks/AceTime * Merge the `develop` branch into `master` by creating a Pull Request. * Approve and merge the PR. @@ -701,9 +701,9 @@ fail until the underlying timezone database of the OS is updated. * Enter the release notes. I normally just copy and paste the latest changes from `CHANGELOG.md`. * Click Publish release. -* Add corresponding tags on AceTimePython, AceTimeTools and AceTimeValidation +* Add corresponding tags on acetimepy, AceTimeTools and AceTimeValidation for reference. - * AceTimePython + * acetimepy * `$ git tag -a 'atX.Y.Z' -m 'AceTime vX.Y.Z'` * `$ git push --tags` * AceTimeTools diff --git a/README.md b/README.md index fe1873f12..518bcb0c6 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ v2.2.0](MIGRATING.md#MigratingToVersion220) for details. * AceTimeClock (https://github.com/bxparks/AceTimeClock) * AceTimeValidation (https://github.com/bxparks/AceTimeValidation) * AceTimeTools (https://github.com/bxparks/AceTimeTools) -* AceTimePython (https://github.com/bxparks/AceTimePython) +* acetimepy (https://github.com/bxparks/acetimepy) ## Table of Contents diff --git a/src/ace_time/ExtendedZoneProcessor.h b/src/ace_time/ExtendedZoneProcessor.h index 4a3918ba3..dbd03541e 100644 --- a/src/ace_time/ExtendedZoneProcessor.h +++ b/src/ace_time/ExtendedZoneProcessor.h @@ -341,8 +341,7 @@ class ExtendedZoneProcessorTemplate: public ZoneProcessor { extended::YearMonthTuple untilYm = { (int16_t) (year + 1), 2 }; // Step 1. The equivalent steps for the Python version are in the - // AceTimePython project, under - // zone_processor.ZoneProcessor.init_for_year(). + // acetimepy project, under zone_processor.ZoneProcessor.init_for_year(). if (ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG) { logging::printf("==== Step 1: findMatches()\n"); } From 7c1be1d19637cc6520f1f81e6b192a26c5909fb8 Mon Sep 17 00:00:00 2001 From: Brian Park Date: Wed, 17 May 2023 20:48:37 -0700 Subject: [PATCH 10/21] github/workflows: use 'make tests' replacement for 'make validations' --- .github/workflows/validation.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index cce12fa5b..c2f7499e2 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -57,15 +57,15 @@ jobs: sudo apt update sudo apt install -y libcurl4-openssl-dev - # Run the validations from AceTimeValidations (HinnantBasicTest, - # HinnantExtendedTest, AcetzBasicTest, AcetzExtendedTest). We don't run - # the others because when a new TZDB version comes out, the Python - # zoneinfo, Python pytz, Python dateutil, and Java validation tests will - # fail because they depend on the obsolete TZ database on the host - # Operating System. The 'make validations' will also compile the binary in + # Run the tests in AceTimeValidations (HinnantBasicTest, + # HinnantExtendedTest, AcetzBasicTest, AcetzExtendedTest). We don't run the + # others because when a new TZDB version comes out, the Python zoneinfo, + # Python pytz, Python dateutil, and Java validation tests will fail because + # they depend on the obsolete TZ database on the host Operating System. The + # 'make validations' will also compile the binary in # AceTimeValidation/compare_cpp/ as necessary. - name: AceTimeValidation run: | cd ../AceTimeValidation - make -C tests validations - make -C tests runvalidations + make -C tests tests + make -C tests runtests From 9ce4d043afdcfbeb65e323c1887f19a676e8301f Mon Sep 17 00:00:00 2001 From: Brian Park Date: Mon, 22 May 2023 13:33:44 -0700 Subject: [PATCH 11/21] ZoneInfo.inc: Update comment on 'numEras' to describe actual implementation, hard links instead of symlinks --- src/zoneinfo/ZoneInfo.inc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/zoneinfo/ZoneInfo.inc b/src/zoneinfo/ZoneInfo.inc index 09c180648..efb741b9c 100644 --- a/src/zoneinfo/ZoneInfo.inc +++ b/src/zoneinfo/ZoneInfo.inc @@ -123,7 +123,21 @@ struct ZoneInfo { /** ZoneContext metadata. */ const internal::ZoneContext* const zoneContext; - /** Number of ZoneEra entries. Set to 0 if this Zone is a actually a Link. */ + /** + * Number of ZoneEra entries. + * + * If this Zone is a actually a Link to a target Zone, the ZoneEra and + * numEras of the target Zone is placed here, and the targetInfo pointer + * below is set to the target ZoneInfo. This allows a Link entry to be + * self-contained, acting like any other Zone entry, which simplifies some of + * the code the ZoneProcessor because it does not need to traverse the link + * to find the required information. In essence, a Link is a "hard link" to a + * Zone. + * + * An alternative implementation is to set numEras to 0 for a Link, and + * traverse the targetInfo to find the required numEras and eras. This led to + * more complicated code. + */ uint8_t const numEras; /** @@ -132,6 +146,6 @@ struct ZoneInfo { */ const ZoneEra* const eras; - /** If Link, points to the target zone info. If Zone, null. */ + /** If Link, points to the target zone info. If Zone, nullptr. */ const ZoneInfo* const targetInfo; }; From 098b1d92b1b0fa4acc712fabc227b5436a397cdb Mon Sep 17 00:00:00 2001 From: Brian Park Date: Mon, 22 May 2023 13:44:18 -0700 Subject: [PATCH 12/21] github/workflows: add acetimec; add setp to build binaries under ./tools --- .github/workflows/validation.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml index c2f7499e2..5bf1fb1af 100644 --- a/.github/workflows/validation.yml +++ b/.github/workflows/validation.yml @@ -26,14 +26,15 @@ jobs: - name: Checkout Additional Repos run: | cd .. - git clone --depth 1 https://github.com/bxparks/EpoxyDuino + git clone --depth 1 https://github.com/HowardHinnant/date git clone --depth 1 https://github.com/bxparks/AUnit git clone --depth 1 https://github.com/bxparks/AceCommon git clone --depth 1 https://github.com/bxparks/AceSorting git clone --depth 1 https://github.com/bxparks/AceTimeTools - git clone --depth 1 https://github.com/bxparks/acetimepy git clone --depth 1 https://github.com/bxparks/AceTimeValidation - git clone --depth 1 https://github.com/HowardHinnant/date + git clone --depth 1 https://github.com/bxparks/EpoxyDuino + git clone --depth 1 https://github.com/bxparks/acetimec + git clone --depth 1 https://github.com/bxparks/acetimepy git clone https://github.com/eggert/tz - name: Set up Python 3.7 @@ -57,6 +58,13 @@ jobs: sudo apt update sudo apt install -y libcurl4-openssl-dev + - name: Build Compare tools + run: | + make -C ../acetimec/src + make -C ../AceTimeValidation/tools/compare_acetimec + make -C ../AceTimeValidation/tools/compare_libc + make -C ../AceTimeValidation/tools/compare_hinnant + # Run the tests in AceTimeValidations (HinnantBasicTest, # HinnantExtendedTest, AcetzBasicTest, AcetzExtendedTest). We don't run the # others because when a new TZDB version comes out, the Python zoneinfo, From 64fdf2f58f8c09f566ee8deadd461237e4d99721 Mon Sep 17 00:00:00 2001 From: Brian Park Date: Sat, 27 May 2023 08:43:40 -0700 Subject: [PATCH 13/21] ZoneProcessor: automatically invalidate and regenerate cache when epoch year changes --- CHANGELOG.md | 7 +++ USER_GUIDE.md | 45 +++---------------- src/ace_time/BasicZoneProcessor.h | 2 + src/ace_time/ExtendedZoneProcessor.h | 2 + src/ace_time/TimeZone.h | 17 ------- src/ace_time/ZoneManager.h | 8 ---- src/ace_time/ZoneProcessor.h | 20 +++++---- src/ace_time/ZoneProcessorCache.h | 11 ----- .../ExtendedTransitionValidationTest.ino | 17 +------ .../ZonedDateTimeExtendedTest.ino | 8 ---- 10 files changed, 29 insertions(+), 108 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f5607fe4..6ca42c24d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,13 @@ * This is an implementation detail. * Use `ZonedExtra::isError()` instead. * Rename AceTimePython to acetimepy. + * ZoneProcessor transition cache + * Save the epoch year, and automatically invalidate and regenerate the + cache when the `Epoch::currentEpochYear()` is modified. + * Remove cache invalidation methods which are no longer needed: + * `ZoneProcessor::resetTransitionCache()` + * `ZoneProcessorCache::resetZoneProcessors()` + * `ZoneManager::resetZoneProcessors()` * 2.2.2 (2023-04-01, TZDB version 2023c) * Upgrade TZDB from 2023b to 2023c. * https://mm.icann.org/pipermail/tz-announce/2023-March/000079.html diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 9c55ea15c..2842c3009 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -70,7 +70,6 @@ TZ database. * [Resource Consumption with Fold](#ResourceConsumptionWithFold) * [Semantic Changes with Fold](#SemanticChangesWithFold) * [Examples with Fold](#ExamplesWithFold) - * [Zone Processor Cache Invalidation](#ZoneProcessorCacheInvalidation) * [ZoneInfo Database](#ZoneInfoDatabase) * [ZoneInfo Records](#ZoneInfoRecords) * [ZoneDB](#ZoneDB) @@ -382,10 +381,11 @@ class Epoch { Normally, the current epoch year is expected to be unchanged using the default 2050, or changed just once at the initialization phase of the application. -However in rare situations, it may be necessary for the client app to call -`Epoch::currentEpochYear()` during its runtime. When this occurs, it is -important to invalidate the zone processor cache, as explained in [Zone -Processor Cache Invalidation](#ZoneProcessorCacheInvalidation). +However in some situations, the client app may call `Epoch::currentEpochYear()` +during its runtime to extend the range of the years of interest. The +`BasicZoneProcessor` and `ExtendedZoneProcessor` objects will automatically +invalidate and regenerate its internal transition cache when the epoch year is +modified. ### LocalDate and LocalTime @@ -2247,41 +2247,6 @@ dt = ZonedDateTime::forComponents(2022, 3, 13, 2, 29, 0, tz, 1 /*fold*/); Serial.printTo(dt); Serial.println(); ``` - -### Zone Processor Cache Invalidation - -Normally, the current epoch year will be configured using -`Epoch::currentEpochYear(year)` only once during the lifetime of the -application. In rare situations, the application may choose to change the -current epoch year in the middle of its lifetime. When this happens, it is -important to invalidate the time zone transition cache maintained inside the -`BasicZoneProcessor` or `ExtendedZoneProcessor` classes. - -If the application is using the `TimeZone` class directly with an associated -`BasicZoneProcessor` or `ExtendedZoneProcessor`, then the following methods must -be called after calling `Epoch::currentEpochYear(year)`: - -```C++ -BasicZoneProcessor processor(...); -processor.resetTransitionCache(); - -ExtendedZoneProcessor processor(...); -processor.resetTransitionCache(); -``` - -If the application is using the `BasicZoneManager` or `ExtendedZoneManager` -class to create the `TimeZone` objects, then the -`ZoneManager::resetZoneProcessors()` must be called after calling -`Epoch::currentEpochYear(year)`: - -```C++ -BasicZoneManager manager(...); -manager.resetZoneProcessors(); - -ExtendedZoneManager manager(...); -manager.resetZoneProcessors(); -``` - ## ZoneInfo Database diff --git a/src/ace_time/BasicZoneProcessor.h b/src/ace_time/BasicZoneProcessor.h index 4fedd7377..5ee0d538b 100644 --- a/src/ace_time/BasicZoneProcessor.h +++ b/src/ace_time/BasicZoneProcessor.h @@ -336,6 +336,7 @@ class BasicZoneProcessorTemplate: public ZoneProcessor { void log() const { if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) { logging::printf("BasicZoneProcessor:\n"); + logging::printf(" mEpochYear: %d\n", mEpochYear); logging::printf(" mYear: %d\n", mYear); logging::printf(" mNumTransitions: %d\n", mNumTransitions); for (int i = 0; i < mNumTransitions; i++) { @@ -464,6 +465,7 @@ class BasicZoneProcessorTemplate: public ZoneProcessor { } mYear = year; + mEpochYear = Epoch::currentEpochYear(); mNumTransitions = 0; // clear cache if (year < mZoneInfoBroker.zoneContext()->startYear - 1 diff --git a/src/ace_time/ExtendedZoneProcessor.h b/src/ace_time/ExtendedZoneProcessor.h index dbd03541e..c3affb27f 100644 --- a/src/ace_time/ExtendedZoneProcessor.h +++ b/src/ace_time/ExtendedZoneProcessor.h @@ -255,6 +255,7 @@ class ExtendedZoneProcessorTemplate: public ZoneProcessor { void log() const { if (ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG) { logging::printf("ExtendedZoneProcessor:\n"); + logging::printf(" mEpochYear: %d\n", mEpochYear); logging::printf(" mYear: %d\n", mYear); logging::printf(" mNumMatches: %d\n", mNumMatches); for (int i = 0; i < mNumMatches; i++) { @@ -322,6 +323,7 @@ class ExtendedZoneProcessorTemplate: public ZoneProcessor { } mYear = year; + mEpochYear = Epoch::currentEpochYear(); mNumMatches = 0; // clear cache mTransitionStorage.init(); diff --git a/src/ace_time/TimeZone.h b/src/ace_time/TimeZone.h index c8f4caf9e..46ad9484b 100644 --- a/src/ace_time/TimeZone.h +++ b/src/ace_time/TimeZone.h @@ -237,23 +237,6 @@ class TimeZone { */ uint8_t getType() const { return mType; } - /** - * Reset the underlying ZoneProcessor if a ZoneProcessor is used. This is - * needed when the Epoch::currentEpochYear() changes and the current - * TimeZone object continues to be used. - */ - void resetZoneProcessor() { - switch (mType) { - case kTypeError: - case kTypeReserved: - case kTypeManual: - break; - - default: - return getBoundZoneProcessor()->resetTransitionCache(); - } - } - /** Return the Standard TimeOffset. Valid only for kTypeManual. */ TimeOffset getStdOffset() const { return TimeOffset::forMinutes(mStdOffsetMinutes); diff --git a/src/ace_time/ZoneManager.h b/src/ace_time/ZoneManager.h index 50426f9ef..741f93e80 100644 --- a/src/ace_time/ZoneManager.h +++ b/src/ace_time/ZoneManager.h @@ -184,14 +184,6 @@ class ZoneManagerTemplate : public ZoneManager { return Z(zoneInfo); } - /** - * Reset the transition cache of the zone processors in the cache. - * Useful when Epoch::currentEpochYear() is changed at runtime. - */ - void resetZoneProcessors() { - mZoneProcessorCache.resetZoneProcessors(); - } - protected: /** * Constructor. diff --git a/src/ace_time/ZoneProcessor.h b/src/ace_time/ZoneProcessor.h index b86b1bf8c..d6c530838 100644 --- a/src/ace_time/ZoneProcessor.h +++ b/src/ace_time/ZoneProcessor.h @@ -143,12 +143,6 @@ class ZoneProcessor { /** Return the kTypeXxx of the current instance. */ uint8_t getType() const { return mType; } - /** - * Reset the internal transition cache. Useful when - * Epoch::currentEpochYear() is changed at runtime. - */ - void resetTransitionCache() { mYear = LocalDate::kInvalidYear; } - /** Return true if timezone is a Link entry pointing to a Zone entry. */ virtual bool isLink() const = 0; @@ -228,9 +222,13 @@ class ZoneProcessor { ZoneProcessor(uint8_t type): mType(type) {} - /** Check if the Transition cache is filled for the given year. */ + /** + * Check if the Transition cache is filled for the given year and current + * epochYear. Checking the epoch year allows the cache to be automatically + * invalidated and regenerated if the epoch year is changed. + */ bool isFilled(int16_t year) const { - return year == mYear; + return year == mYear && mEpochYear == Epoch::currentEpochYear(); } /** Return true if equal. */ @@ -250,6 +248,12 @@ class ZoneProcessor { * to LocalDate::kInvalidYear to indicate invalid cache. */ mutable int16_t mYear = LocalDate::kInvalidYear; + + /** + * Epoch year that was used to calculate the transitions in the current + * cache. Set to LocalDate::kInvalidYear to indicate invalid cache. + */ + mutable int16_t mEpochYear = LocalDate::kInvalidYear; }; inline bool operator==(const ZoneProcessor& a, const ZoneProcessor& b) { diff --git a/src/ace_time/ZoneProcessorCache.h b/src/ace_time/ZoneProcessorCache.h index fc23ef587..5f11e5ff6 100644 --- a/src/ace_time/ZoneProcessorCache.h +++ b/src/ace_time/ZoneProcessorCache.h @@ -55,17 +55,6 @@ class ZoneProcessorCacheBaseTemplate { return zoneProcessor; } - /** - * Reset the transition cache of all zone processors in the cache. - * Useful when Epoch::currentEpochYear() is changed at runtime. - */ - void resetZoneProcessors() { - for (uint8_t i = 0; i < mSize; i++) { - ZP* zoneProcessor = &mZoneProcessors[i]; - zoneProcessor->resetTransitionCache(); - } - } - private: // disable copy constructor and assignment operator ZoneProcessorCacheBaseTemplate(const ZoneProcessorCacheBaseTemplate&) diff --git a/tests/ExtendedTransitionValidationTest/ExtendedTransitionValidationTest.ino b/tests/ExtendedTransitionValidationTest/ExtendedTransitionValidationTest.ino index 25d6e0a82..1c9be957d 100644 --- a/tests/ExtendedTransitionValidationTest/ExtendedTransitionValidationTest.ino +++ b/tests/ExtendedTransitionValidationTest/ExtendedTransitionValidationTest.ino @@ -1,4 +1,4 @@ -#line 2 "ExtendedZoneProcessorTransitionTest.ino" +#line 2 "ExtendedTransitionValidationTest.ino" #include #include @@ -51,23 +51,8 @@ class ExtendedTransitionValidation : public aunit::TestOnce { zonedbx::kZoneContext.untilYear); testing::EpochYearContext context(epochYear); - zoneProcessor.resetTransitionCache(); - - // FIXME: If a failure is detected, then this function returns early. - // The currentEpochYear() is guaranteed to be restored through the - // destructor of the 'context` object, but the cache invalidation clean - // up is skipped. Most likely this won't cause problems with the rest of - // the unit tests because the `zoneProcessor` will likely be set to a - // different year. However, there is a small chance of failure. The - // proper solution is to create a custom RAII context class to perform - // the resetTransitionCache() clean up, but I'm too lazy right now. assertNoFatalFailure(validateZone(startYear, untilYear)); } - - // Perform a final resetTransitionCache() in case a test case failed, - // which causes the epoch year to be reset to its original value, but - // the zoneProcessor cache is not automatically reset. - zoneProcessor.resetTransitionCache(); } // Validate the current zoneProcessor state using the [start, until) diff --git a/tests/ZonedDateTimeExtendedTest/ZonedDateTimeExtendedTest.ino b/tests/ZonedDateTimeExtendedTest/ZonedDateTimeExtendedTest.ino index b92aea28a..7495a841a 100644 --- a/tests/ZonedDateTimeExtendedTest/ZonedDateTimeExtendedTest.ino +++ b/tests/ZonedDateTimeExtendedTest/ZonedDateTimeExtendedTest.ino @@ -435,7 +435,6 @@ test(ZonedDateTimeExtendedTest, morocco_2090) { // Reconfigure the current epoch year to 2050 to allow calculations in the // year 2090. testing::EpochYearContext context(2050); - extendedZoneManager.resetZoneProcessors(); TimeZone tz = extendedZoneManager.createForZoneInfo( &kZoneAfrica_Casablanca); @@ -472,9 +471,6 @@ test(ZonedDateTimeExtendedTest, morocco_2090) { dt = ZonedDateTime::forComponents(2090, 1, 1, 1, 0, 0, tz); epochSeconds = dt.toEpochSeconds(); assertEqual(epochSeconds, (int32_t) 14610 * 86400); - - // Reset the transition caches of the zone processors. - extendedZoneManager.resetZoneProcessors(); } // -------------------------------------------------------------------------- @@ -490,7 +486,6 @@ test(ZonedDateTimeExtendedTest, Pacific_Apia) { // Reconfigure the current epoch year to 2050 to allow calculations in the // year 2090. testing::EpochYearContext context(2050); - extendedZoneManager.resetZoneProcessors(); TimeZone tz = extendedZoneManager.createForZoneInfo(&kZonePacific_Apia); @@ -579,9 +574,6 @@ test(ZonedDateTimeExtendedTest, Pacific_Apia) { assertEqual(0, dt.second()); assertEqual(14*60, dt.timeOffset().toMinutes()); assertEqual(0, dt.fold()); - - // Reset the transition caches of the zone processors. - extendedZoneManager.resetZoneProcessors(); } // -------------------------------------------------------------------------- From 0f1810e5b582a846ed304fa1f919520b16c7fb45 Mon Sep 17 00:00:00 2001 From: Brian Park Date: Wed, 31 May 2023 14:01:21 -0700 Subject: [PATCH 14/21] Epoch.h: fix typo --- src/ace_time/Epoch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ace_time/Epoch.h b/src/ace_time/Epoch.h index 15a803f45..37ab460a4 100644 --- a/src/ace_time/Epoch.h +++ b/src/ace_time/Epoch.h @@ -17,7 +17,7 @@ namespace ace_time { /** - * Utitliy functions for setting, retrieving, and converting the current epoch. + * Utility functions for setting, retrieving, and converting the current epoch. * Normally, the default epoch is 2050-01-01T00:00:00 UTC. It can be changed by * calling the `currentEpochYear(year)` function. */ From bad28ca6838250737177c14b749e81a2036568dd Mon Sep 17 00:00:00 2001 From: Brian Park Date: Wed, 31 May 2023 14:17:07 -0700 Subject: [PATCH 15/21] Epoch.{h,cpp}: rename 'converter epoch' to 'internal epoch' --- CHANGELOG.md | 5 ++++ USER_GUIDE.md | 4 ---- src/ace_time/Epoch.cpp | 2 +- src/ace_time/Epoch.h | 21 +++++++++-------- src/ace_time/EpochConverterHinnant.h | 19 ++++++++------- src/ace_time/EpochConverterJulian.h | 23 +++++++++---------- src/ace_time/LocalDate.h | 6 ++--- .../BasicZoneProcessorTest.ino | 8 +++---- tests/UnixTimeTest/UnixTimeTest.ino | 10 ++++---- 9 files changed, 50 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ca42c24d..952c1fe9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,11 @@ * `ZoneProcessor::resetTransitionCache()` * `ZoneProcessorCache::resetZoneProcessors()` * `ZoneManager::resetZoneProcessors()` + * Rename "Converter Epoch" to "Internal Epoch". + * Change `daysToCurrentEpochFromConverterEpoch()` to + `daysToCurrentEpochFromInternalEpoch()`. + * This is an internal implementation detail, exposed only for testing + purposes. * 2.2.2 (2023-04-01, TZDB version 2023c) * Upgrade TZDB from 2023b to 2023c. * https://mm.icann.org/pipermail/tz-announce/2023-March/000079.html diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 2842c3009..d90b19b64 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -355,10 +355,6 @@ class Epoch { // Set the current epoch year. static int16_t currentEpochYear(int16_t epochYear); - // The number of days from the converter epoch (2000-01-01T00:00:00) to - // the current epoch ({yyyy}-01-01T00:00:00). - static int32_t daysToCurrentEpochFromConverterEpoch(); - // The number of days from the Unix epoch (1970-01-01T00:00:00) // to the current epoch ({yyyy}-01-01T00:00:00). static int32_t daysToCurrentEpochFromUnixEpoch(); diff --git a/src/ace_time/Epoch.cpp b/src/ace_time/Epoch.cpp index ac824d090..d9777952c 100644 --- a/src/ace_time/Epoch.cpp +++ b/src/ace_time/Epoch.cpp @@ -5,6 +5,6 @@ namespace ace_time { int16_t Epoch::sCurrentEpochYear = 2050; // Number of days from 2000-01-01 to 2050-01-01: 50*365 + 13 leap days = 18263. -int32_t Epoch::sDaysToCurrentEpochFromConverterEpoch = 18263; +int32_t Epoch::sDaysToCurrentEpochFromInternalEpoch = 18263; } diff --git a/src/ace_time/Epoch.h b/src/ace_time/Epoch.h index 37ab460a4..d5bd1c5a4 100644 --- a/src/ace_time/Epoch.h +++ b/src/ace_time/Epoch.h @@ -31,23 +31,24 @@ class Epoch { /** Set the current epoch year. */ static void currentEpochYear(int16_t year) { sCurrentEpochYear = year; - sDaysToCurrentEpochFromConverterEpoch = daysFromConverterEpoch(year); + sDaysToCurrentEpochFromInternalEpoch = daysFromInternalEpoch(year); } /** * Return number of days to the given {year}-01-01 from the converter * epoch of 2000-01-01. */ - static int32_t daysFromConverterEpoch(int16_t year) { + static int32_t daysFromInternalEpoch(int16_t year) { return ACE_TIME_EPOCH_CONVERTER::toEpochDays(year, 1, 1); } /** - * Number of days from the converter epoch (2000-01-01) to the current - * epoch. + * Number of days from the internal epoch (2000-01-01) to the current + * epoch. This is an internal implementation that is public for testing + * purposes. */ - static int32_t daysToCurrentEpochFromConverterEpoch() { - return sDaysToCurrentEpochFromConverterEpoch; + static int32_t daysToCurrentEpochFromInternalEpoch() { + return sDaysToCurrentEpochFromInternalEpoch; } /** @@ -55,8 +56,8 @@ class Epoch { * the current epoch. */ static int32_t daysToCurrentEpochFromUnixEpoch() { - return ACE_TIME_EPOCH_CONVERTER::kDaysToConverterEpochFromUnixEpoch - + sDaysToCurrentEpochFromConverterEpoch; + return ACE_TIME_EPOCH_CONVERTER::kDaysToInternalEpochFromUnixEpoch + + sDaysToCurrentEpochFromInternalEpoch; } /** @@ -113,8 +114,8 @@ class Epoch { /** Base year `yyyy` of current epoch {yyyy}-01-01T00:00:00. */ static int16_t sCurrentEpochYear; - /** Number of days from kConverterEpochYear to sCurrentEpochYear. */ - static int32_t sDaysToCurrentEpochFromConverterEpoch; + /** Number of days from kInternalEpochYear to sCurrentEpochYear. */ + static int32_t sDaysToCurrentEpochFromInternalEpoch; }; } diff --git a/src/ace_time/EpochConverterHinnant.h b/src/ace_time/EpochConverterHinnant.h index 1da1bc1a9..501bf750f 100644 --- a/src/ace_time/EpochConverterHinnant.h +++ b/src/ace_time/EpochConverterHinnant.h @@ -22,20 +22,19 @@ class EpochConverterHinnant { * Epoch year used by this epoch converter. Must be a multiple of 400. Other * parts of the AceTime library will probably use a different epoch year. */ - static const int16_t kConverterEpochYear = 2000; + static const int16_t kInternalEpochYear = 2000; /** * Number of days from Unix epoch (1970-01-01 00:00:00 UTC) to - * the converter epoch (2000-01-01 00:00:00 UTC). + * the internal epoch (2000-01-01 00:00:00 UTC). */ - static const int32_t kDaysToConverterEpochFromUnixEpoch = 10957; + static const int32_t kDaysToInternalEpochFromUnixEpoch = 10957; /** * Convert (year, month, day) in the Gregorian calendar to days since the - * converter epoch (2000-01-01 instead of 2050-01-01). The `year` is - * restricted to be greater than or equal to 0001, which allows the internal - * 400-year era to start on 0000-03-01 with era=0, and we don't have to - * worry about negative eras. + * internal epoch (2000-01-01). The `year` is restricted to be greater than + * or equal to 0001, which allows the internal 400-year era to start on + * 0000-03-01 with era=0, and we don't have to worry about negative eras. * * No input validation is performed. The behavior is undefined if the * parameters are outside their expected range. The algorithm will likely @@ -59,7 +58,7 @@ class EpochConverterHinnant { int32_t dayOfEpochPrime = dayOfEra + 146097 * era; return dayOfEpochPrime - - (kConverterEpochYear / 400) * 146097 /*relative to 2000-03-01*/ + - (kInternalEpochYear / 400) * 146097 /*relative to 2000-03-01*/ + 60 /*relative to 2000-01-01, 2000 is a leap year*/; } @@ -69,7 +68,7 @@ class EpochConverterHinnant { * No input validation is performed. The behavior is undefined if the * parameters are outside their expected range. * - * @param epochDays number of days from the converter epoch of 2000-01-01 + * @param epochDays number of days from the internal epoch of 2000-01-01 * @param year year [1,9999] * @param month month integer [1, 12] * @param day day of month integer[1, 31] @@ -78,7 +77,7 @@ class EpochConverterHinnant { int16_t& year, uint8_t& month, uint8_t& day) { int32_t dayOfEpochPrime = epochDays - + (kConverterEpochYear / 400) * 146097 - 60; + + (kInternalEpochYear / 400) * 146097 - 60; uint16_t era = (uint32_t) dayOfEpochPrime / 146097; // [0,24] uint32_t dayOfEra = dayOfEpochPrime - 146097 * era; // [0,146096] uint16_t yearOfEra = (dayOfEra - dayOfEra / 1460 + dayOfEra / 36524 diff --git a/src/ace_time/EpochConverterJulian.h b/src/ace_time/EpochConverterJulian.h index dd6447451..12b72b753 100644 --- a/src/ace_time/EpochConverterJulian.h +++ b/src/ace_time/EpochConverterJulian.h @@ -23,28 +23,27 @@ class EpochConverterJulian { * Epoch year used by this epoch converter. Must be a multiple of 400. Other * parts of the AceTime library will probably use a different epoch year. */ - static const int16_t kConverterEpochYear = 2000; + static const int16_t kInternalEpochYear = 2000; /** * Number of days from Unix epoch (1970-01-01 00:00:00 UTC) to - * the converter epoch (2000-01-01 00:00:00 UTC). + * the internal epoch (2000-01-01 00:00:00 UTC). */ - static const int32_t kDaysToConverterEpochFromUnixEpoch = 10957; + static const int32_t kDaysToInternalEpochFromUnixEpoch = 10957; /** * Number of days from the modified proleptic Julian calendar epoch (4713 * BC 01-01, modified to start at 00:00:00 instead of 12:00:00) to the - * converter epoch (2000-01-01 instead of 2050-01-01). There are 1721060 - * days from the modified Julian epoch to 0000-01-01 of the proleptic - * Gregorian calendar. We then need to add 2000 years (5 x 400 years) to get - * to 2000-01-01. + * internal epoch (2000-01-01). There are 1721060 days from the modified + * Julian epoch to 0000-01-01 of the proleptic Gregorian calendar. We then + * need to add 2000 years (5 x 400 years) to get to 2000-01-01. */ - static const int32_t kDaysToConverterEpochFromJulianEpoch = 1721060 - + (kConverterEpochYear / 400) * 146097; // 2451545 + static const int32_t kDaysToInternalEpochFromJulianEpoch = 1721060 + + (kInternalEpochYear / 400) * 146097; // 2451545 /** * Convert (year, month, day) in the Gregorian calendar to days since the - * converter epoch (2000-01-01). The (year, month, day) is converted into + * internal epoch (2000-01-01). The (year, month, day) is converted into * Julian days, then converted to epoch days since AceTime Epoch. The Julian * day normally start at 12:00:00, but we use a modified Julian day number * starting at 00:00:00 to make it easier to convert to the Gregorian @@ -75,7 +74,7 @@ class EpochConverterJulian { + (367 * (month - 2 - 12 * mm))/12 - (3 * ((year + 4900 + mm)/100))/4 + day - 32075; - return jdn - kDaysToConverterEpochFromJulianEpoch; + return jdn - kDaysToInternalEpochFromJulianEpoch; } /** @@ -88,7 +87,7 @@ class EpochConverterJulian { static void fromEpochDays(int32_t epochDays, int16_t& year, uint8_t& month, uint8_t& day) { - uint32_t J = epochDays + kDaysToConverterEpochFromJulianEpoch; + uint32_t J = epochDays + kDaysToInternalEpochFromJulianEpoch; uint32_t f = J + 1401 + (((4 * J + 274277 ) / 146097) * 3) / 4 - 38; uint32_t e = 4 * f + 3; uint32_t g = e % 1461 / 4; diff --git a/src/ace_time/LocalDate.h b/src/ace_time/LocalDate.h index bbc3af9b9..57f19ed49 100644 --- a/src/ace_time/LocalDate.h +++ b/src/ace_time/LocalDate.h @@ -175,8 +175,8 @@ class LocalDate { month = 0; day = 0; } else { - // shift relative to Epoch::kConverterEpochYear - epochDays += Epoch::daysToCurrentEpochFromConverterEpoch(); + // shift relative to Epoch::kInternalEpochYear + epochDays += Epoch::daysToCurrentEpochFromInternalEpoch(); ACE_TIME_EPOCH_CONVERTER::fromEpochDays(epochDays, year, month, day); } return forComponents(year, month, day); @@ -355,7 +355,7 @@ class LocalDate { int32_t toEpochDays() const { if (isError()) return kInvalidEpochDays; int32_t days = ACE_TIME_EPOCH_CONVERTER::toEpochDays(mYear, mMonth, mDay) - - Epoch::daysToCurrentEpochFromConverterEpoch(); + - Epoch::daysToCurrentEpochFromInternalEpoch(); return days; } diff --git a/tests/BasicZoneProcessorTest/BasicZoneProcessorTest.ino b/tests/BasicZoneProcessorTest/BasicZoneProcessorTest.ino index 06a2210c1..6319d14fc 100644 --- a/tests/BasicZoneProcessorTest/BasicZoneProcessorTest.ino +++ b/tests/BasicZoneProcessorTest/BasicZoneProcessorTest.ino @@ -193,14 +193,14 @@ test(BasicZoneProcessorTest, init_primitives) { assertEqual(-7*60, zoneProcessor.mTransitions[1].offsetMinutes); assertEqual( (acetime_t) (39434400 /*relative to 2000*/ - - Epoch::daysToCurrentEpochFromConverterEpoch() * 86400), + - Epoch::daysToCurrentEpochFromInternalEpoch() * 86400), zoneProcessor.mTransitions[1].startEpochSeconds); // t >= 2001-10-28 02:00 UTC-07:00 Sunday goes to PST assertEqual(-8*60, zoneProcessor.mTransitions[2].offsetMinutes); assertEqual( (acetime_t) (57574800 /*relative to 2000*/ - - Epoch::daysToCurrentEpochFromConverterEpoch() * 86400), + - Epoch::daysToCurrentEpochFromInternalEpoch() * 86400), zoneProcessor.mTransitions[2].startEpochSeconds); } @@ -243,14 +243,14 @@ test(BasicZoneProcessorTest, initForLocalDate) { assertEqual(-7*60, zoneProcessor.mTransitions[1].offsetMinutes); assertEqual( (acetime_t) (574077600 /*relative to 2000*/ - - Epoch::daysToCurrentEpochFromConverterEpoch() * 86400), + - Epoch::daysToCurrentEpochFromInternalEpoch() * 86400), zoneProcessor.mTransitions[1].startEpochSeconds); // t >= 2018-11-04 02:00 UTC-07:00 Sunday goes to PST assertEqual(-8*60, zoneProcessor.mTransitions[2].offsetMinutes); assertEqual( (acetime_t) (594637200 /*relative to 2000*/ - - Epoch::daysToCurrentEpochFromConverterEpoch() * 86400), + - Epoch::daysToCurrentEpochFromInternalEpoch() * 86400), zoneProcessor.mTransitions[2].startEpochSeconds); } diff --git a/tests/UnixTimeTest/UnixTimeTest.ino b/tests/UnixTimeTest/UnixTimeTest.ino index 2daf0ab9d..2a31e3461 100644 --- a/tests/UnixTimeTest/UnixTimeTest.ino +++ b/tests/UnixTimeTest/UnixTimeTest.ino @@ -60,11 +60,12 @@ test(UnixTimeTest, toEpochSeconds) { t.tm_year = 2018 - 1900; // year since 1900 (!) #if defined(AVR) + // AVR libc epoch year is 2000, which happens to be the same as the AceTime + // internal epoch. //time_t avrSeconds = mk_gmtime(&t); time_t avrSeconds = mktime(&t); - // AVR libc epoch year is 2000 which is the same as the AceTime base epoch acetime_t expected = avrSeconds - - Epoch::daysToCurrentEpochFromConverterEpoch() * 86400; + - Epoch::daysToCurrentEpochFromInternalEpoch() * 86400; assertEqual(epochSeconds, expected); #elif defined(ESP8266) || defined(ESP32) time_t espSeconds = mktime(&t); @@ -85,9 +86,10 @@ test(UnixTimeTest, forEpochSeconds) { // 2029-12-31 23:59:59Z Monday acetime_t epochSeconds = 10958 * (acetime_t) 86400 - 1; #if defined(AVR) - // AVR libc epoch year is 2000, same as the converter epoch + // AVR libc epoch year is 2000, which happens to be the same as the AceTime + // internal epoch. time_t avrSeconds = (time_t) epochSeconds - + Epoch::daysToCurrentEpochFromConverterEpoch() * 86400; + + Epoch::daysToCurrentEpochFromInternalEpoch() * 86400; gmtime_r(&avrSeconds, &t); #elif defined(ESP8266) || defined(ESP32) time_t espSeconds = epochSeconds From b507db4d384c81ea56754e108002e37e033d334a Mon Sep 17 00:00:00 2001 From: Brian Park Date: Wed, 31 May 2023 15:19:35 -0700 Subject: [PATCH 16/21] MemoryBenchmark: add SAMD21, SAMD51; remove Teensy 3.2 --- examples/MemoryBenchmark/Makefile | 10 +- examples/MemoryBenchmark/MemoryBenchmark.ino | 12 +- examples/MemoryBenchmark/README.md | 276 ++++++++++--------- examples/MemoryBenchmark/esp32.txt | 34 +-- examples/MemoryBenchmark/esp8266.txt | 32 +-- examples/MemoryBenchmark/generate_readme.py | 48 ++-- examples/MemoryBenchmark/micro.txt | 28 +- examples/MemoryBenchmark/nano.txt | 28 +- examples/MemoryBenchmark/samd21.txt | 26 +- examples/MemoryBenchmark/samd51.txt | 18 ++ examples/MemoryBenchmark/stm32.txt | 36 +-- examples/MemoryBenchmark/teensy32.txt | 18 -- 12 files changed, 295 insertions(+), 271 deletions(-) create mode 100644 examples/MemoryBenchmark/samd51.txt delete mode 100644 examples/MemoryBenchmark/teensy32.txt diff --git a/examples/MemoryBenchmark/Makefile b/examples/MemoryBenchmark/Makefile index a577f65be..1bfdd0f4a 100644 --- a/examples/MemoryBenchmark/Makefile +++ b/examples/MemoryBenchmark/Makefile @@ -8,8 +8,8 @@ include ../../../EpoxyDuino/EpoxyDuino.mk .PHONY: benchmarks -TARGETS := nano.txt micro.txt samd21.txt stm32.txt esp8266.txt esp32.txt \ - teensy32.txt +TARGETS := nano.txt micro.txt samd21.txt stm32.txt samd51.txt \ + esp8266.txt esp32.txt README.md: $(TARGETS) generate_readme.py generate_table.awk ./generate_readme.py > $@ @@ -28,15 +28,15 @@ samd21.txt: stm32.txt: ./collect.sh --cli stm32 $@ +samd51.txt: + ./collect.sh --ide itsym4 $@ + esp8266.txt: ./collect.sh --cli nodemcu $@ esp32.txt: ./collect.sh --cli esp32 $@ -teensy32.txt: - ./collect.sh --ide teensy32 $@ - epoxy: ./validate_using_epoxy_duino.sh diff --git a/examples/MemoryBenchmark/MemoryBenchmark.ino b/examples/MemoryBenchmark/MemoryBenchmark.ino index 4b3b90969..a01e4e07e 100644 --- a/examples/MemoryBenchmark/MemoryBenchmark.ino +++ b/examples/MemoryBenchmark/MemoryBenchmark.ino @@ -14,14 +14,14 @@ #define FEATURE_BASIC_TIME_ZONE2 5 #define FEATURE_BASIC_ZONE_MANAGER_ONE 6 #define FEATURE_BASIC_ZONE_MANAGER_ZONES 7 -#define FEATURE_BASIC_ZONE_MANAGER_ZONES_AND_FAT_LINKS 8 +#define FEATURE_BASIC_ZONE_MANAGER_ZONES_AND_LINKS 8 #define FEATURE_BASIC_ZONE_SORTER_BY_NAME 9 #define FEATURE_BASIC_ZONE_SORTER_BY_OFFSET_AND_NAME 10 #define FEATURE_EXTENDED_TIME_ZONE 11 #define FEATURE_EXTENDED_TIME_ZONE2 12 #define FEATURE_EXTENDED_ZONE_MANAGER_ONE 13 #define FEATURE_EXTENDED_ZONE_MANAGER_ZONES 14 -#define FEATURE_EXTENDED_ZONE_MANAGER_ZONES_AND_FAT_LINKS 15 +#define FEATURE_EXTENDED_ZONE_MANAGER_ZONES_AND_LINKS 15 #define FEATURE_EXTENDED_ZONE_SORTER_BY_NAME 16 #define FEATURE_EXTENDED_ZONE_SORTER_BY_OFFSET_AND_NAME 17 @@ -79,7 +79,7 @@ volatile int16_t year = 2019; zonedb::kZoneRegistrySize, zonedb::kZoneRegistry, zoneProcessorCache); -#elif FEATURE == FEATURE_BASIC_ZONE_MANAGER_ZONES_AND_FAT_LINKS +#elif FEATURE == FEATURE_BASIC_ZONE_MANAGER_ZONES_AND_LINKS BasicZoneProcessorCache<1> zoneProcessorCache; BasicZoneManager manager( zonedb::kZoneAndLinkRegistrySize, @@ -145,7 +145,7 @@ volatile int16_t year = 2019; zonedbx::kZoneRegistrySize, zonedbx::kZoneRegistry, zoneProcessorCache); -#elif FEATURE == FEATURE_EXTENDED_ZONE_MANAGER_ZONES_AND_FAT_LINKS +#elif FEATURE == FEATURE_EXTENDED_ZONE_MANAGER_ZONES_AND_LINKS ExtendedZoneProcessorCache<1> zoneProcessorCache; ExtendedZoneManager manager( zonedbx::kZoneAndLinkRegistrySize, @@ -250,7 +250,7 @@ void setup() { auto dt = ZonedDateTime::forComponents(year, 6, 17, 9, 18, 0, tz); acetime_t epochSeconds = dt.toEpochSeconds(); guard ^= epochSeconds; -#elif FEATURE == FEATURE_BASIC_ZONE_MANAGER_ZONES_AND_FAT_LINKS +#elif FEATURE == FEATURE_BASIC_ZONE_MANAGER_ZONES_AND_LINKS auto tz = manager.createForZoneInfo(&zonedb::kZoneAmerica_Los_Angeles); auto dt = ZonedDateTime::forComponents(year, 6, 17, 9, 18, 0, tz); acetime_t epochSeconds = dt.toEpochSeconds(); @@ -290,7 +290,7 @@ void setup() { auto dt = ZonedDateTime::forComponents(year, 6, 17, 9, 18, 0, tz); acetime_t epochSeconds = dt.toEpochSeconds(); guard ^= epochSeconds; -#elif FEATURE == FEATURE_EXTENDED_ZONE_MANAGER_ZONES_AND_FAT_LINKS +#elif FEATURE == FEATURE_EXTENDED_ZONE_MANAGER_ZONES_AND_LINKS auto tz = manager.createForZoneInfo(&zonedbx::kZoneAmerica_Los_Angeles); auto dt = ZonedDateTime::forComponents(year, 6, 17, 9, 18, 0, tz); acetime_t epochSeconds = dt.toEpochSeconds(); diff --git a/examples/MemoryBenchmark/README.md b/examples/MemoryBenchmark/README.md index bef264312..007ceeef7 100644 --- a/examples/MemoryBenchmark/README.md +++ b/examples/MemoryBenchmark/README.md @@ -5,7 +5,7 @@ memory and static RAM sizes were recorded. The `FEATURE_BASELINE` selection is the baseline, and its memory usage numbers are subtracted from the subsequent `FEATURE_*` memory usage. -**Version**: AceTime v2.2.0 +**Version**: AceTime v2.2.3 **DO NOT EDIT**: This file was auto-generated using `make README.md`. @@ -214,6 +214,7 @@ ASCII table. * ExtendedZoneProcessor * No change for 1-2 zones. * Decreases flash consumption by ~300 bytes for full TZ database. + **v2.2.0** * Upgrade tool chain * Arduino AVR from 1.8.5 to 1.8.6 @@ -221,9 +222,22 @@ ASCII table. * ESP8266 from 3.0.2 to 3.1.2 failed, reverted back to 3.0.2 * ESP32 from 2.0.5 to 2.0.7 * Add support for Seeed XIAO SAMD21 - * Seeeduino 1.8.3 + * Using Seeeduino SAMD Core 1.8.3 * Upgrade to TZDB 2023b +**v2.2.2** +* Upgrade to TZDB 2023c + +**v2.2.3** +* Add support for Adafruit ItsyBitsy M4 + * Using Adafruit SAMD Core 1.7.11 +* Remove Teensy 3.2 + * Nearing end of life. Moved to Tier 2 (should work). +* Upgrade tool chain + * Seeeduino 1.8.4 + * STM32duino 2.5.0 + * ESP32 Boards 2.0.9 + # Legend * [1] Delta flash and ram consumption for `ZoneSorterByName` and @@ -251,23 +265,23 @@ ASCII table. | ZonedDateTime | 1440/ 28 | 966/ 17 | | Manual ZoneManager | 1398/ 13 | 924/ 2 | |----------------------------------------+--------------+-------------| -| Basic TimeZone (1 zone) | 6870/ 355 | 6396/ 344 | -| Basic TimeZone (2 zones) | 7336/ 503 | 6862/ 492 | -| BasicZoneManager (1 zone) | 7074/ 366 | 6600/ 355 | -| BasicZoneManager (all zones) | 19764/ 744 | 19290/ 733 | -| BasicZoneManager (all zones+links) | 25116/ 744 | 24642/ 733 | +| Basic TimeZone (1 zone) | 6892/ 356 | 6418/ 345 | +| Basic TimeZone (2 zones) | 7356/ 505 | 6882/ 494 | +| BasicZoneManager (1 zone) | 7096/ 367 | 6622/ 356 | +| BasicZoneManager (all zones) | 19746/ 745 | 19272/ 734 | +| BasicZoneManager (all zones+links) | 25126/ 745 | 24652/ 734 | |----------------------------------------+--------------+-------------| -| Basic ZoneSorterByName [1] | 7690/ 368 | 616/ 2 | -| Basic ZoneSorterByOffsetAndName [1] | 7862/ 368 | 788/ 2 | +| Basic ZoneSorterByName [1] | 7712/ 369 | 616/ 2 | +| Basic ZoneSorterByOffsetAndName [1] | 7884/ 369 | 788/ 2 | |----------------------------------------+--------------+-------------| -| Extended TimeZone (1 zone) | 9992/ 742 | 9518/ 731 | -| Extended TimeZone (2 zones) | 10508/ 1207 | 10034/ 1196 | -| ExtendedZoneManager (1 zone) | 10168/ 748 | 9694/ 737 | -| ExtendedZoneManager (all zones) | 34416/ 1208 | 33942/ 1197 | -| ExtendedZoneManager (all zones+links) | 40420/ 1208 | 39946/ 1197 | +| Extended TimeZone (1 zone) | 9980/ 743 | 9506/ 732 | +| Extended TimeZone (2 zones) | 10496/ 1209 | 10022/ 1198 | +| ExtendedZoneManager (1 zone) | 10156/ 749 | 9682/ 738 | +| ExtendedZoneManager (all zones) | 35246/ 1209 | 34772/ 1198 | +| ExtendedZoneManager (all zones+links) | 41278/ 1209 | 40804/ 1198 | |----------------------------------------+--------------+-------------| -| Extended ZoneSorterByName [2] | 10780/ 750 | 612/ 2 | -| Extended ZoneSorterByOffsetAndName [2] | 10958/ 750 | 790/ 2 | +| Extended ZoneSorterByName [2] | 10768/ 751 | 612/ 2 | +| Extended ZoneSorterByOffsetAndName [2] | 10946/ 751 | 790/ 2 | +---------------------------------------------------------------------+ ``` @@ -288,23 +302,23 @@ ASCII table. | ZonedDateTime | 4412/ 168 | 942/ 15 | | Manual ZoneManager | 4392/ 153 | 922/ 0 | |----------------------------------------+--------------+-------------| -| Basic TimeZone (1 zone) | 9842/ 495 | 6372/ 342 | -| Basic TimeZone (2 zones) | 10290/ 641 | 6820/ 488 | -| BasicZoneManager (1 zone) | 10046/ 506 | 6576/ 353 | -| BasicZoneManager (all zones) | 22734/ 882 | 19264/ 729 | -| BasicZoneManager (all zones+links) | 28086/ 882 | 24616/ 729 | +| Basic TimeZone (1 zone) | 9864/ 496 | 6394/ 343 | +| Basic TimeZone (2 zones) | 10310/ 643 | 6840/ 490 | +| BasicZoneManager (1 zone) | 10068/ 507 | 6598/ 354 | +| BasicZoneManager (all zones) | 22716/ 883 | 19246/ 730 | +| BasicZoneManager (all zones+links) | 28096/ 883 | 24626/ 730 | |----------------------------------------+--------------+-------------| -| Basic ZoneSorterByName [1] | 10662/ 508 | 616/ 2 | -| Basic ZoneSorterByOffsetAndName [1] | 10834/ 508 | 788/ 2 | +| Basic ZoneSorterByName [1] | 10684/ 509 | 616/ 2 | +| Basic ZoneSorterByOffsetAndName [1] | 10856/ 509 | 788/ 2 | |----------------------------------------+--------------+-------------| -| Extended TimeZone (1 zone) | 12946/ 880 | 9476/ 727 | -| Extended TimeZone (2 zones) | 13464/ 1347 | 9994/ 1194 | -| ExtendedZoneManager (1 zone) | 13122/ 886 | 9652/ 733 | -| ExtendedZoneManager (all zones) | 37388/ 1348 | 33918/ 1195 | -| ExtendedZoneManager (all zones+links) | 43392/ 1348 | 39922/ 1195 | +| Extended TimeZone (1 zone) | 12934/ 881 | 9464/ 728 | +| Extended TimeZone (2 zones) | 13452/ 1349 | 9982/ 1196 | +| ExtendedZoneManager (1 zone) | 13110/ 887 | 9640/ 734 | +| ExtendedZoneManager (all zones) | 38218/ 1349 | 34748/ 1196 | +| ExtendedZoneManager (all zones+links) | 44250/ 1349 | 40780/ 1196 | |----------------------------------------+--------------+-------------| -| Extended ZoneSorterByName [2] | 13734/ 888 | 612/ 2 | -| Extended ZoneSorterByOffsetAndName [2] | 13912/ 888 | 790/ 2 | +| Extended ZoneSorterByName [2] | 13722/ 889 | 612/ 2 | +| Extended ZoneSorterByOffsetAndName [2] | 13900/ 889 | 790/ 2 | +---------------------------------------------------------------------+ ``` @@ -313,7 +327,7 @@ ASCII table. * SAMD21, 48 MHz ARM Cortex-M0+ * Arduino IDE 1.8.19, Arduino CLI 0.31.1 -* Seeeduino SAMD Boards 1.8.3 +* Seeeduino SAMD Boards 1.8.4 ``` +---------------------------------------------------------------------+ @@ -325,23 +339,23 @@ ASCII table. | ZonedDateTime | 35140/ 0 | 1072/ 0 | | Manual ZoneManager | 35124/ 0 | 1056/ 0 | |----------------------------------------+--------------+-------------| -| Basic TimeZone (1 zone) | 38636/ 0 | 4568/ 0 | -| Basic TimeZone (2 zones) | 38972/ 0 | 4904/ 0 | -| BasicZoneManager (1 zone) | 38740/ 0 | 4672/ 0 | -| BasicZoneManager (all zones) | 55580/ 0 | 21512/ 0 | +| Basic TimeZone (1 zone) | 38652/ 0 | 4584/ 0 | +| Basic TimeZone (2 zones) | 38988/ 0 | 4920/ 0 | +| BasicZoneManager (1 zone) | 38756/ 0 | 4688/ 0 | +| BasicZoneManager (all zones) | 55540/ 0 | 21472/ 0 | | BasicZoneManager (all zones+links) | 63788/ 0 | 29720/ 0 | |----------------------------------------+--------------+-------------| -| Basic ZoneSorterByName [1] | 39212/ 0 | 472/ 0 | -| Basic ZoneSorterByOffsetAndName [1] | 39260/ 0 | 520/ 0 | +| Basic ZoneSorterByName [1] | 39220/ 0 | 464/ 0 | +| Basic ZoneSorterByOffsetAndName [1] | 39268/ 0 | 512/ 0 | |----------------------------------------+--------------+-------------| -| Extended TimeZone (1 zone) | 40684/ 0 | 6616/ 0 | -| Extended TimeZone (2 zones) | 41028/ 0 | 6960/ 0 | -| ExtendedZoneManager (1 zone) | 40788/ 0 | 6720/ 0 | -| ExtendedZoneManager (all zones) | 72740/ 0 | 38672/ 0 | -| ExtendedZoneManager (all zones+links) | 81924/ 0 | 47856/ 0 | +| Extended TimeZone (1 zone) | 40700/ 0 | 6632/ 0 | +| Extended TimeZone (2 zones) | 41044/ 0 | 6976/ 0 | +| ExtendedZoneManager (1 zone) | 40804/ 0 | 6736/ 0 | +| ExtendedZoneManager (all zones) | 73652/ 0 | 39584/ 0 | +| ExtendedZoneManager (all zones+links) | 82884/ 0 | 48816/ 0 | |----------------------------------------+--------------+-------------| -| Extended ZoneSorterByName [2] | 41260/ 0 | 472/ 0 | -| Extended ZoneSorterByOffsetAndName [2] | 41308/ 0 | 520/ 0 | +| Extended ZoneSorterByName [2] | 41276/ 0 | 472/ 0 | +| Extended ZoneSorterByOffsetAndName [2] | 41324/ 0 | 520/ 0 | +---------------------------------------------------------------------+ ``` @@ -350,35 +364,35 @@ ASCII table. * STM32F103C8, 72 MHz ARM Cortex-M3 * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* STM32duino 2.4.0 +* STM32duino 2.5.0 ``` +---------------------------------------------------------------------+ | Functionality | flash/ ram | delta | |----------------------------------------+--------------+-------------| -| baseline | 21392/ 3556 | 0/ 0 | +| baseline | 21492/ 3840 | 0/ 0 | |----------------------------------------+--------------+-------------| -| LocalDateTime | 21740/ 3572 | 348/ 16 | -| ZonedDateTime | 22480/ 3588 | 1088/ 32 | -| Manual ZoneManager | 22468/ 3564 | 1076/ 8 | +| LocalDateTime | 21848/ 3856 | 356/ 16 | +| ZonedDateTime | 21928/ 3872 | 436/ 32 | +| Manual ZoneManager | 22528/ 3848 | 1036/ 8 | |----------------------------------------+--------------+-------------| -| Basic TimeZone (1 zone) | 26032/ 3768 | 4640/ 212 | -| Basic TimeZone (2 zones) | 26384/ 3972 | 4992/ 416 | -| BasicZoneManager (1 zone) | 26152/ 3788 | 4760/ 232 | -| BasicZoneManager (all zones) | 42996/ 3788 | 21604/ 232 | -| BasicZoneManager (all zones+links) | 51204/ 3788 | 29812/ 232 | +| Basic TimeZone (1 zone) | 26060/ 4056 | 4568/ 216 | +| Basic TimeZone (2 zones) | 26404/ 4264 | 4912/ 424 | +| BasicZoneManager (1 zone) | 26180/ 4076 | 4688/ 236 | +| BasicZoneManager (all zones) | 43228/ 4076 | 21736/ 236 | +| BasicZoneManager (all zones+links) | 51760/ 4076 | 30268/ 236 | |----------------------------------------+--------------+-------------| -| Basic ZoneSorterByName [1] | 26612/ 3792 | 460/ 4 | -| Basic ZoneSorterByOffsetAndName [1] | 26660/ 3792 | 508/ 4 | +| Basic ZoneSorterByName [1] | 26624/ 4080 | 444/ 4 | +| Basic ZoneSorterByOffsetAndName [1] | 26696/ 4080 | 516/ 4 | |----------------------------------------+--------------+-------------| -| Extended TimeZone (1 zone) | 27844/ 4180 | 6452/ 624 | -| Extended TimeZone (2 zones) | 28200/ 4796 | 6808/ 1240 | -| ExtendedZoneManager (1 zone) | 27960/ 4188 | 6568/ 632 | -| ExtendedZoneManager (all zones) | 59908/ 4188 | 38516/ 632 | -| ExtendedZoneManager (all zones+links) | 69096/ 4188 | 47704/ 632 | +| Extended TimeZone (1 zone) | 27876/ 4468 | 6384/ 628 | +| Extended TimeZone (2 zones) | 28224/ 5088 | 6732/ 1248 | +| ExtendedZoneManager (1 zone) | 27992/ 4476 | 6500/ 636 | +| ExtendedZoneManager (all zones) | 61280/ 4476 | 39788/ 636 | +| ExtendedZoneManager (all zones+links) | 70852/ 4476 | 49360/ 636 | |----------------------------------------+--------------+-------------| -| Extended ZoneSorterByName [2] | 28428/ 4192 | 468/ 4 | -| Extended ZoneSorterByOffsetAndName [2] | 28476/ 4192 | 516/ 4 | +| Extended ZoneSorterByName [2] | 28436/ 4480 | 444/ 4 | +| Extended ZoneSorterByOffsetAndName [2] | 28508/ 4480 | 516/ 4 | +---------------------------------------------------------------------+ ``` @@ -386,119 +400,117 @@ ASCII table. An entry of `-1` indicates that the memory usage exceeded the maximum of the microcontroller and the compiler did not generate the desired information. -## ESP8266 +## SAMD51 (Adafruit ItsyBitsy M4) -* NodeMCU 1.0, 80MHz ESP8266 +* SAMD51, 120 MHz ARM Cortex-M4 * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* ESP8266 Boards 3.0.2 +* Adafruit SAMD 1.7.11 ``` +---------------------------------------------------------------------+ | Functionality | flash/ ram | delta | |----------------------------------------+--------------+-------------| -| baseline | 260089/27892 | 0/ 0 | +| baseline | 10580/ 0 | 0/ 0 | |----------------------------------------+--------------+-------------| -| LocalDateTime | 260613/27912 | 524/ 20 | -| ZonedDateTime | 261733/27928 | 1644/ 36 | -| Manual ZoneManager | 261713/27900 | 1624/ 8 | +| LocalDateTime | 10880/ 0 | 300/ 0 | +| ZonedDateTime | 11600/ 0 | 1020/ 0 | +| Manual ZoneManager | 11592/ 0 | 1012/ 0 | |----------------------------------------+--------------+-------------| -| Basic TimeZone (1 zone) | 266965/28704 | 6876/ 812 | -| Basic TimeZone (2 zones) | 267461/28904 | 7372/ 1012 | -| BasicZoneManager (1 zone) | 267125/28720 | 7036/ 828 | -| BasicZoneManager (all zones) | 284261/28720 | 24172/ 828 | -| BasicZoneManager (all zones+links) | 292741/28720 | 32652/ 828 | +| Basic TimeZone (1 zone) | 15164/ 0 | 4584/ 0 | +| Basic TimeZone (2 zones) | 15516/ 0 | 4936/ 0 | +| BasicZoneManager (1 zone) | 15284/ 0 | 4704/ 0 | +| BasicZoneManager (all zones) | 32072/ 0 | 21492/ 0 | +| BasicZoneManager (all zones+links) | 40320/ 0 | 29740/ 0 | |----------------------------------------+--------------+-------------| -| Basic ZoneSorterByName [1] | 267749/28728 | 624/ 8 | -| Basic ZoneSorterByOffsetAndName [1] | 267893/28728 | 768/ 8 | +| Basic ZoneSorterByName [1] | 15752/ 0 | 468/ 0 | +| Basic ZoneSorterByOffsetAndName [1] | 15796/ 0 | 512/ 0 | |----------------------------------------+--------------+-------------| -| Extended TimeZone (1 zone) | 269021/29288 | 8932/ 1396 | -| Extended TimeZone (2 zones) | 269581/29904 | 9492/ 2012 | -| ExtendedZoneManager (1 zone) | 269165/29296 | 9076/ 1404 | -| ExtendedZoneManager (all zones) | 301581/29296 | 41492/ 1404 | -| ExtendedZoneManager (all zones+links) | 311117/29296 | 51028/ 1404 | +| Extended TimeZone (1 zone) | 16984/ 0 | 6404/ 0 | +| Extended TimeZone (2 zones) | 17336/ 0 | 6756/ 0 | +| ExtendedZoneManager (1 zone) | 17100/ 0 | 6520/ 0 | +| ExtendedZoneManager (all zones) | 49952/ 0 | 39372/ 0 | +| ExtendedZoneManager (all zones+links) | 59180/ 0 | 48600/ 0 | |----------------------------------------+--------------+-------------| -| Extended ZoneSorterByName [2] | 269789/29304 | 624/ 8 | -| Extended ZoneSorterByOffsetAndName [2] | 269821/29304 | 656/ 8 | +| Extended ZoneSorterByName [2] | 17568/ 0 | 468/ 0 | +| Extended ZoneSorterByOffsetAndName [2] | 17612/ 0 | 512/ 0 | +---------------------------------------------------------------------+ ``` +## ESP8266 -## ESP32 - -* ESP32-01 Dev Board, 240 MHz Tensilica LX6 +* NodeMCU 1.0, 80MHz ESP8266 * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* ESP32 Boards 2.0.7 +* ESP8266 Boards 3.0.2 ``` +---------------------------------------------------------------------+ | Functionality | flash/ ram | delta | |----------------------------------------+--------------+-------------| -| baseline | 228345/21976 | 0/ 0 | +| baseline | 260089/27892 | 0/ 0 | |----------------------------------------+--------------+-------------| -| LocalDateTime | 230613/21984 | 2268/ 8 | -| ZonedDateTime | 231761/22000 | 3416/ 24 | -| Manual ZoneManager | 231769/21976 | 3424/ 0 | +| LocalDateTime | 292761/28732 | 32672/ 840 | +| ZonedDateTime | 267785/28732 | 7696/ 840 | +| Manual ZoneManager | 261713/27900 | 1624/ 8 | |----------------------------------------+--------------+-------------| -| Basic TimeZone (1 zone) | 235845/22184 | 7500/ 208 | -| Basic TimeZone (2 zones) | 236429/22384 | 8084/ 408 | -| BasicZoneManager (1 zone) | 236009/22200 | 7664/ 224 | -| BasicZoneManager (all zones) | 253113/22200 | 24768/ 224 | -| BasicZoneManager (all zones+links) | 261593/22200 | 33248/ 224 | +| Basic TimeZone (1 zone) | 266985/28708 | 6896/ 816 | +| Basic TimeZone (2 zones) | 267481/28916 | 7392/ 1024 | +| BasicZoneManager (1 zone) | 267145/28732 | 7056/ 840 | +| BasicZoneManager (all zones) | 284233/28732 | 24144/ 840 | +| BasicZoneManager (all zones+links) | 292761/28732 | 32672/ 840 | |----------------------------------------+--------------+-------------| -| Basic ZoneSorterByName [1] | 236557/22208 | 548/ 8 | -| Basic ZoneSorterByOffsetAndName [1] | 236601/22208 | 592/ 8 | +| Basic ZoneSorterByName [1] | 267785/28732 | 640/ 0 | +| Basic ZoneSorterByOffsetAndName [1] | 267913/28732 | 768/ 0 | |----------------------------------------+--------------+-------------| -| Extended TimeZone (1 zone) | 237761/22592 | 9416/ 616 | -| Extended TimeZone (2 zones) | 238329/23208 | 9984/ 1232 | -| ExtendedZoneManager (1 zone) | 237893/22600 | 9548/ 624 | -| ExtendedZoneManager (all zones) | 270277/22600 | 41932/ 624 | -| ExtendedZoneManager (all zones+links) | 279797/22600 | 51452/ 624 | +| Extended TimeZone (1 zone) | 269025/29300 | 8936/ 1408 | +| Extended TimeZone (2 zones) | 269601/29916 | 9512/ 2024 | +| ExtendedZoneManager (1 zone) | 269185/29308 | 9096/ 1416 | +| ExtendedZoneManager (all zones) | 302497/29308 | 42408/ 1416 | +| ExtendedZoneManager (all zones+links) | 312065/29308 | 51976/ 1416 | |----------------------------------------+--------------+-------------| -| Extended ZoneSorterByName [2] | 238437/22608 | 544/ 8 | -| Extended ZoneSorterByOffsetAndName [2] | 238485/22608 | 592/ 8 | +| Extended ZoneSorterByName [2] | 269809/29308 | 624/ 0 | +| Extended ZoneSorterByOffsetAndName [2] | 269841/29308 | 656/ 0 | +---------------------------------------------------------------------+ ``` -RAM usage remains constant as more objects are created, which indicates that an -initial pool of a certain minimum size is created regardless of the actual RAM -usage by objects. - -## Teensy 3.2 +## ESP32 -* 96 MHz ARM Cortex-M4 +* ESP32-01 Dev Board, 240 MHz Tensilica LX6 * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* Teensyduino 1.57 -* Compiler options: "Faster" +* ESP32 Boards 2.0.9 ``` +---------------------------------------------------------------------+ | Functionality | flash/ ram | delta | |----------------------------------------+--------------+-------------| -| baseline | 10060/ 4152 | 0/ 0 | +| baseline | 228345/21976 | 0/ 0 | |----------------------------------------+--------------+-------------| -| LocalDateTime | 10424/ 4168 | 364/ 16 | -| ZonedDateTime | 10468/ 4184 | 408/ 32 | -| Manual ZoneManager | 10196/ 4160 | 136/ 8 | +| LocalDateTime | 230565/21984 | 2220/ 8 | +| ZonedDateTime | 231713/22000 | 3368/ 24 | +| Manual ZoneManager | 231721/21976 | 3376/ 0 | |----------------------------------------+--------------+-------------| -| Basic TimeZone (1 zone) | 20792/ 4364 | 10732/ 212 | -| Basic TimeZone (2 zones) | 22344/ 4568 | 12284/ 416 | -| BasicZoneManager (1 zone) | 21052/ 4384 | 10992/ 232 | -| BasicZoneManager (all zones) | 38192/ 4384 | 28132/ 232 | -| BasicZoneManager (all zones+links) | 46676/ 4384 | 36616/ 232 | +| Basic TimeZone (1 zone) | 235813/22184 | 7468/ 208 | +| Basic TimeZone (2 zones) | 236397/22392 | 8052/ 416 | +| BasicZoneManager (1 zone) | 235985/22208 | 7640/ 232 | +| BasicZoneManager (all zones) | 253025/22208 | 24680/ 232 | +| BasicZoneManager (all zones+links) | 261553/22208 | 33208/ 232 | |----------------------------------------+--------------+-------------| -| Basic ZoneSorterByName [1] | 21564/ 4388 | 512/ 4 | -| Basic ZoneSorterByOffsetAndName [1] | 21628/ 4388 | 576/ 4 | +| Basic ZoneSorterByName [1] | 236529/22208 | 544/ 0 | +| Basic ZoneSorterByOffsetAndName [1] | 236573/22208 | 588/ 0 | |----------------------------------------+--------------+-------------| -| Extended TimeZone (1 zone) | 24640/ 4776 | 14580/ 624 | -| Extended TimeZone (2 zones) | 26128/ 5392 | 16068/ 1240 | -| ExtendedZoneManager (1 zone) | 24836/ 4784 | 14776/ 632 | -| ExtendedZoneManager (all zones) | 57252/ 4784 | 47192/ 632 | -| ExtendedZoneManager (all zones+links) | 66780/ 4784 | 56720/ 632 | +| Extended TimeZone (1 zone) | 237737/22600 | 9392/ 624 | +| Extended TimeZone (2 zones) | 238297/23216 | 9952/ 1240 | +| ExtendedZoneManager (1 zone) | 237889/22608 | 9544/ 632 | +| ExtendedZoneManager (all zones) | 271169/22608 | 42824/ 632 | +| ExtendedZoneManager (all zones+links) | 280737/22608 | 52392/ 632 | |----------------------------------------+--------------+-------------| -| Extended ZoneSorterByName [2] | 25412/ 4788 | 576/ 4 | -| Extended ZoneSorterByOffsetAndName [2] | 25412/ 4788 | 576/ 4 | +| Extended ZoneSorterByName [2] | 238429/22608 | 540/ 0 | +| Extended ZoneSorterByOffsetAndName [2] | 238477/22608 | 588/ 0 | +---------------------------------------------------------------------+ ``` +RAM usage remains constant as more objects are created, which indicates that an +initial pool of a certain minimum size is created regardless of the actual RAM +usage by objects. + diff --git a/examples/MemoryBenchmark/esp32.txt b/examples/MemoryBenchmark/esp32.txt index 3736c6bf8..bdcf95b28 100644 --- a/examples/MemoryBenchmark/esp32.txt +++ b/examples/MemoryBenchmark/esp32.txt @@ -1,18 +1,18 @@ 0 228345 1310720 21976 327680 -1 230613 1310720 21984 327680 -2 231761 1310720 22000 327680 -3 231769 1310720 21976 327680 -4 235845 1310720 22184 327680 -5 236429 1310720 22384 327680 -6 236009 1310720 22200 327680 -7 253113 1310720 22200 327680 -8 261593 1310720 22200 327680 -9 236557 1310720 22208 327680 -10 236601 1310720 22208 327680 -11 237761 1310720 22592 327680 -12 238329 1310720 23208 327680 -13 237893 1310720 22600 327680 -14 270277 1310720 22600 327680 -15 279797 1310720 22600 327680 -16 238437 1310720 22608 327680 -17 238485 1310720 22608 327680 +1 230565 1310720 21984 327680 +2 231713 1310720 22000 327680 +3 231721 1310720 21976 327680 +4 235813 1310720 22184 327680 +5 236397 1310720 22392 327680 +6 235985 1310720 22208 327680 +7 253025 1310720 22208 327680 +8 261553 1310720 22208 327680 +9 236529 1310720 22208 327680 +10 236573 1310720 22208 327680 +11 237737 1310720 22600 327680 +12 238297 1310720 23216 327680 +13 237889 1310720 22608 327680 +14 271169 1310720 22608 327680 +15 280737 1310720 22608 327680 +16 238429 1310720 22608 327680 +17 238477 1310720 22608 327680 diff --git a/examples/MemoryBenchmark/esp8266.txt b/examples/MemoryBenchmark/esp8266.txt index 0332b16f2..6d0158cdc 100644 --- a/examples/MemoryBenchmark/esp8266.txt +++ b/examples/MemoryBenchmark/esp8266.txt @@ -1,18 +1,18 @@ 0 260089 1044464 27892 81920 -1 260613 1044464 27912 81920 -2 261733 1044464 27928 81920 +1 292761 1044464 28732 81920 +2 267785 1044464 28732 81920 3 261713 1044464 27900 81920 -4 266965 1044464 28704 81920 -5 267461 1044464 28904 81920 -6 267125 1044464 28720 81920 -7 284261 1044464 28720 81920 -8 292741 1044464 28720 81920 -9 267749 1044464 28728 81920 -10 267893 1044464 28728 81920 -11 269021 1044464 29288 81920 -12 269581 1044464 29904 81920 -13 269165 1044464 29296 81920 -14 301581 1044464 29296 81920 -15 311117 1044464 29296 81920 -16 269789 1044464 29304 81920 -17 269821 1044464 29304 81920 +4 266985 1044464 28708 81920 +5 267481 1044464 28916 81920 +6 267145 1044464 28732 81920 +7 284233 1044464 28732 81920 +8 292761 1044464 28732 81920 +9 267785 1044464 28732 81920 +10 267913 1044464 28732 81920 +11 269025 1044464 29300 81920 +12 269601 1044464 29916 81920 +13 269185 1044464 29308 81920 +14 302497 1044464 29308 81920 +15 312065 1044464 29308 81920 +16 269809 1044464 29308 81920 +17 269841 1044464 29308 81920 diff --git a/examples/MemoryBenchmark/generate_readme.py b/examples/MemoryBenchmark/generate_readme.py index aea9c8a86..9ef866299 100755 --- a/examples/MemoryBenchmark/generate_readme.py +++ b/examples/MemoryBenchmark/generate_readme.py @@ -14,12 +14,12 @@ "./generate_table.awk < samd21.txt", shell=True, text=True) stm32_results = check_output( "./generate_table.awk < stm32.txt", shell=True, text=True) +samd51_results = check_output( + "./generate_table.awk < samd51.txt", shell=True, text=True) esp8266_results = check_output( "./generate_table.awk < esp8266.txt", shell=True, text=True) esp32_results = check_output( "./generate_table.awk < esp32.txt", shell=True, text=True) -teensy32_results = check_output( - "./generate_table.awk < teensy32.txt", shell=True, text=True) print(f"""\ # Memory Benchmark @@ -29,7 +29,7 @@ the baseline, and its memory usage numbers are subtracted from the subsequent `FEATURE_*` memory usage. -**Version**: AceTime v2.2.0 +**Version**: AceTime v2.2.3 **DO NOT EDIT**: This file was auto-generated using `make README.md`. @@ -238,6 +238,7 @@ * ExtendedZoneProcessor * No change for 1-2 zones. * Decreases flash consumption by ~300 bytes for full TZ database. + **v2.2.0** * Upgrade tool chain * Arduino AVR from 1.8.5 to 1.8.6 @@ -245,9 +246,22 @@ * ESP8266 from 3.0.2 to 3.1.2 failed, reverted back to 3.0.2 * ESP32 from 2.0.5 to 2.0.7 * Add support for Seeed XIAO SAMD21 - * Seeeduino 1.8.3 + * Using Seeeduino SAMD Core 1.8.3 * Upgrade to TZDB 2023b +**v2.2.2** +* Upgrade to TZDB 2023c + +**v2.2.3** +* Add support for Adafruit ItsyBitsy M4 + * Using Adafruit SAMD Core 1.7.11 +* Remove Teensy 3.2 + * Nearing end of life. Moved to Tier 2 (should work). +* Upgrade tool chain + * Seeeduino 1.8.4 + * STM32duino 2.5.0 + * ESP32 Boards 2.0.9 + # Legend * [1] Delta flash and ram consumption for `ZoneSorterByName` and @@ -283,7 +297,7 @@ * SAMD21, 48 MHz ARM Cortex-M0+ * Arduino IDE 1.8.19, Arduino CLI 0.31.1 -* Seeeduino SAMD Boards 1.8.3 +* Seeeduino SAMD Boards 1.8.4 ``` {samd21_results} @@ -293,7 +307,7 @@ * STM32F103C8, 72 MHz ARM Cortex-M3 * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* STM32duino 2.4.0 +* STM32duino 2.5.0 ``` {stm32_results} @@ -302,6 +316,15 @@ An entry of `-1` indicates that the memory usage exceeded the maximum of the microcontroller and the compiler did not generate the desired information. +## SAMD51 (Adafruit ItsyBitsy M4) + +* SAMD51, 120 MHz ARM Cortex-M4 +* Arduino IDE 1.8.19, Arduino CLI 0.31.0 +* Adafruit SAMD 1.7.11 + +``` +{samd51_results} +``` ## ESP8266 * NodeMCU 1.0, 80MHz ESP8266 @@ -316,7 +339,7 @@ * ESP32-01 Dev Board, 240 MHz Tensilica LX6 * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* ESP32 Boards 2.0.7 +* ESP32 Boards 2.0.9 ``` {esp32_results} @@ -325,15 +348,4 @@ RAM usage remains constant as more objects are created, which indicates that an initial pool of a certain minimum size is created regardless of the actual RAM usage by objects. - -## Teensy 3.2 - -* 96 MHz ARM Cortex-M4 -* Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* Teensyduino 1.57 -* Compiler options: "Faster" - -``` -{teensy32_results} -``` """) diff --git a/examples/MemoryBenchmark/micro.txt b/examples/MemoryBenchmark/micro.txt index a0b3424ce..58d43aa62 100644 --- a/examples/MemoryBenchmark/micro.txt +++ b/examples/MemoryBenchmark/micro.txt @@ -2,17 +2,17 @@ 1 4080 28672 161 2560 2 4412 28672 168 2560 3 4392 28672 153 2560 -4 9842 28672 495 2560 -5 10290 28672 641 2560 -6 10046 28672 506 2560 -7 22734 28672 882 2560 -8 28086 28672 882 2560 -9 10662 28672 508 2560 -10 10834 28672 508 2560 -11 12946 28672 880 2560 -12 13464 28672 1347 2560 -13 13122 28672 886 2560 -14 37388 28672 1348 2560 -15 43392 28672 1348 2560 -16 13734 28672 888 2560 -17 13912 28672 888 2560 +4 9864 28672 496 2560 +5 10310 28672 643 2560 +6 10068 28672 507 2560 +7 22716 28672 883 2560 +8 28096 28672 883 2560 +9 10684 28672 509 2560 +10 10856 28672 509 2560 +11 12934 28672 881 2560 +12 13452 28672 1349 2560 +13 13110 28672 887 2560 +14 38218 28672 1349 2560 +15 44250 28672 1349 2560 +16 13722 28672 889 2560 +17 13900 28672 889 2560 diff --git a/examples/MemoryBenchmark/nano.txt b/examples/MemoryBenchmark/nano.txt index ae3c80b49..a7e348539 100644 --- a/examples/MemoryBenchmark/nano.txt +++ b/examples/MemoryBenchmark/nano.txt @@ -2,17 +2,17 @@ 1 1108 30720 21 2048 2 1440 30720 28 2048 3 1398 30720 13 2048 -4 6870 30720 355 2048 -5 7336 30720 503 2048 -6 7074 30720 366 2048 -7 19764 30720 744 2048 -8 25116 30720 744 2048 -9 7690 30720 368 2048 -10 7862 30720 368 2048 -11 9992 30720 742 2048 -12 10508 30720 1207 2048 -13 10168 30720 748 2048 -14 34416 30720 1208 2048 -15 40420 30720 1208 2048 -16 10780 30720 750 2048 -17 10958 30720 750 2048 +4 6892 30720 356 2048 +5 7356 30720 505 2048 +6 7096 30720 367 2048 +7 19746 30720 745 2048 +8 25126 30720 745 2048 +9 7712 30720 369 2048 +10 7884 30720 369 2048 +11 9980 30720 743 2048 +12 10496 30720 1209 2048 +13 10156 30720 749 2048 +14 35246 30720 1209 2048 +15 41278 30720 1209 2048 +16 10768 30720 751 2048 +17 10946 30720 751 2048 diff --git a/examples/MemoryBenchmark/samd21.txt b/examples/MemoryBenchmark/samd21.txt index f358967ab..ff78ee478 100644 --- a/examples/MemoryBenchmark/samd21.txt +++ b/examples/MemoryBenchmark/samd21.txt @@ -2,17 +2,17 @@ 1 34372 262144 2 35140 262144 3 35124 262144 -4 38636 262144 -5 38972 262144 -6 38740 262144 -7 55580 262144 +4 38652 262144 +5 38988 262144 +6 38756 262144 +7 55540 262144 8 63788 262144 -9 39212 262144 -10 39260 262144 -11 40684 262144 -12 41028 262144 -13 40788 262144 -14 72740 262144 -15 81924 262144 -16 41260 262144 -17 41308 262144 +9 39220 262144 +10 39268 262144 +11 40700 262144 +12 41044 262144 +13 40804 262144 +14 73652 262144 +15 82884 262144 +16 41276 262144 +17 41324 262144 diff --git a/examples/MemoryBenchmark/samd51.txt b/examples/MemoryBenchmark/samd51.txt new file mode 100644 index 000000000..a8ebcc9be --- /dev/null +++ b/examples/MemoryBenchmark/samd51.txt @@ -0,0 +1,18 @@ +0 10580 507904 +1 10880 507904 +2 11600 507904 +3 11592 507904 +4 15164 507904 +5 15516 507904 +6 15284 507904 +7 32072 507904 +8 40320 507904 +9 15752 507904 +10 15796 507904 +11 16984 507904 +12 17336 507904 +13 17100 507904 +14 49952 507904 +15 59180 507904 +16 17568 507904 +17 17612 507904 diff --git a/examples/MemoryBenchmark/stm32.txt b/examples/MemoryBenchmark/stm32.txt index 92b82f791..df4514611 100644 --- a/examples/MemoryBenchmark/stm32.txt +++ b/examples/MemoryBenchmark/stm32.txt @@ -1,18 +1,18 @@ -0 21392 131072 3556 20480 -1 21740 131072 3572 20480 -2 22480 131072 3588 20480 -3 22468 131072 3564 20480 -4 26032 131072 3768 20480 -5 26384 131072 3972 20480 -6 26152 131072 3788 20480 -7 42996 131072 3788 20480 -8 51204 131072 3788 20480 -9 26612 131072 3792 20480 -10 26660 131072 3792 20480 -11 27844 131072 4180 20480 -12 28200 131072 4796 20480 -13 27960 131072 4188 20480 -14 59908 131072 4188 20480 -15 69096 131072 4188 20480 -16 28428 131072 4192 20480 -17 28476 131072 4192 20480 +0 21492 131072 3840 20480 +1 21848 131072 3856 20480 +2 21928 131072 3872 20480 +3 22528 131072 3848 20480 +4 26060 131072 4056 20480 +5 26404 131072 4264 20480 +6 26180 131072 4076 20480 +7 43228 131072 4076 20480 +8 51760 131072 4076 20480 +9 26624 131072 4080 20480 +10 26696 131072 4080 20480 +11 27876 131072 4468 20480 +12 28224 131072 5088 20480 +13 27992 131072 4476 20480 +14 61280 131072 4476 20480 +15 70852 131072 4476 20480 +16 28436 131072 4480 20480 +17 28508 131072 4480 20480 diff --git a/examples/MemoryBenchmark/teensy32.txt b/examples/MemoryBenchmark/teensy32.txt deleted file mode 100644 index 74631f86d..000000000 --- a/examples/MemoryBenchmark/teensy32.txt +++ /dev/null @@ -1,18 +0,0 @@ -0 10060 262144 4152 65536 -1 10424 262144 4168 65536 -2 10468 262144 4184 65536 -3 10196 262144 4160 65536 -4 20792 262144 4364 65536 -5 22344 262144 4568 65536 -6 21052 262144 4384 65536 -7 38192 262144 4384 65536 -8 46676 262144 4384 65536 -9 21564 262144 4388 65536 -10 21628 262144 4388 65536 -11 24640 262144 4776 65536 -12 26128 262144 5392 65536 -13 24836 262144 4784 65536 -14 57252 262144 4784 65536 -15 66780 262144 4784 65536 -16 25412 262144 4788 65536 -17 25412 262144 4788 65536 From a88b19d832906582372ee18047990855166dc9d0 Mon Sep 17 00:00:00 2001 From: Brian Park Date: Wed, 31 May 2023 16:10:37 -0700 Subject: [PATCH 17/21] AutoBenchmark: add SAMD21, SAMD51; remove Teensy 3.2 --- examples/AutoBenchmark/AutoBenchmark.ino | 2 +- examples/AutoBenchmark/Makefile | 20 +- examples/AutoBenchmark/README.md | 422 +++++++++++----------- examples/AutoBenchmark/esp32.txt | 52 +-- examples/AutoBenchmark/esp8266.txt | 62 ++-- examples/AutoBenchmark/generate_readme.py | 46 ++- examples/AutoBenchmark/micro.txt | 36 +- examples/AutoBenchmark/nano.txt | 24 +- examples/AutoBenchmark/samd21.txt | 54 +-- examples/AutoBenchmark/samd51.txt | 58 +++ examples/AutoBenchmark/stm32.txt | 54 +-- examples/AutoBenchmark/teensy32.txt | 58 --- 12 files changed, 452 insertions(+), 436 deletions(-) create mode 100644 examples/AutoBenchmark/samd51.txt delete mode 100644 examples/AutoBenchmark/teensy32.txt diff --git a/examples/AutoBenchmark/AutoBenchmark.ino b/examples/AutoBenchmark/AutoBenchmark.ino index 3cdb623fc..e0549cea6 100644 --- a/examples/AutoBenchmark/AutoBenchmark.ino +++ b/examples/AutoBenchmark/AutoBenchmark.ino @@ -13,7 +13,7 @@ using namespace ace_time; void setup() { #if ! defined(EPOXY_DUINO) - delay(1000); + delay(2000); // ESP8266, ESP32 now require 2000 instead of 1000 #endif SERIAL_PORT_MONITOR.begin(115200); diff --git a/examples/AutoBenchmark/Makefile b/examples/AutoBenchmark/Makefile index 5f8b5c616..2b745385b 100644 --- a/examples/AutoBenchmark/Makefile +++ b/examples/AutoBenchmark/Makefile @@ -10,8 +10,8 @@ include ../../../EpoxyDuino/EpoxyDuino.mk AUNITER_DIR := ../../../AUniter/tools -TARGETS := nano.txt micro.txt samd21.txt stm32.txt esp8266.txt esp32.txt \ - teensy32.txt +TARGETS := nano.txt micro.txt samd21.txt stm32.txt samd51.txt \ + esp8266.txt esp32.txt # It is not possible to auto-generate the $(TARGETS) because the USB ports are # dynamic. @@ -34,10 +34,11 @@ micro.txt: samd21.txt: $(AUNITER_DIR)/auniter.sh --cli upmon --delay 1 -o $@ --eof END xiao:ACM0 -# STM32 no longer works with CLI due to -# https://github.com/arduino/arduino-cli/issues/1444. Use IDE instead. stm32.txt: - $(AUNITER_DIR)/auniter.sh --ide upmon -o $@ --eof END stm32:ACM0 + $(AUNITER_DIR)/auniter.sh --cli upmon -o $@ --eof END stm32:ACM0 + +samd51.txt: + $(AUNITER_DIR)/auniter.sh --cli upmon --delay 2 -o $@ --eof END itsym4:ACM* esp8266.txt: $(AUNITER_DIR)/auniter.sh --cli upmon -o $@ --eof END nodemcu:USB0 @@ -45,15 +46,6 @@ esp8266.txt: esp32.txt: $(AUNITER_DIR)/auniter.sh --cli upmon -o $@ --eof END esp32:USB0 -# Teensy cannot upload a Arduino sketch and capture its Serial output -# programmatically using a script, at least, I don't know how. To generate -# teesy32.txt, I have to manually upload the program using the IDE, then fire -# up the Serial Monitor, then copy and paste the Serial output manually into -# teensy.txt. This Makefile rule is an aspirational hope that Teensy might -# allow automation some day in the future. -teensy32.txt: - $(AUNITER_DIR)/auniter.sh --cli upmon -o $@ --eof END teensy32:ACM0 - more_clean: echo "Use 'make clean_benchmarks' to remove *.txt files" diff --git a/examples/AutoBenchmark/README.md b/examples/AutoBenchmark/README.md index 4e8c8f486..37e7abacf 100644 --- a/examples/AutoBenchmark/README.md +++ b/examples/AutoBenchmark/README.md @@ -4,7 +4,7 @@ Here are the results from `AutoBenchmark.ino` for various boards. These results show that integer division and modulus operations are incredibly slow on 8-bit AVR processors. -**Version**: AceTime v2.2.0 +**Version**: AceTime v2.2.3 **NOTE**: This file was auto-generated using `make README.md`. DO NOT EDIT. @@ -186,6 +186,19 @@ The CPU times below are given in microseconds. * Seeeduino 1.8.3 * Upgrade to TZDB 2023b +**v2.2.2** +* Upgrade to TZDB 2023c + +**v2.2.3** +* Add support for Adafruit ItsyBitsy M4 + * Using Adafruit SAMD Core 1.7.11 +* Remove Teensy 3.2 + * Nearing end of life. Moved to Tier 2 (should work). +* Upgrade tool chain + * Seeeduino 1.8.4 + * STM32duino 2.5.0 + * ESP32 Boards 2.0.9 + ## Arduino Nano * 16MHz ATmega328P @@ -204,10 +217,10 @@ sizeof(TimeZoneData): 5 sizeof(ZonedDateTime): 15 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 142 -sizeof(ExtendedZoneProcessor): 456 -sizeof(BasicZoneProcessorCache<1>): 146 -sizeof(ExtendedZoneProcessorCache<1>): 460 +sizeof(BasicZoneProcessor): 143 +sizeof(ExtendedZoneProcessor): 457 +sizeof(BasicZoneProcessorCache<1>): 147 +sizeof(ExtendedZoneProcessorCache<1>): 461 sizeof(BasicZoneManager): 7 sizeof(ExtendedZoneManager): 7 sizeof(internal::ZoneContext): 14 @@ -243,24 +256,24 @@ CPU: | ZonedDateTime::forEpochSeconds(Extended_nocache) | -1.000 | | ZonedDateTime::forEpochSeconds(Extended_cached) | -1.000 | |--------------------------------------------------+----------| -| ZonedDateTime::forComponents(Basic_nocache) | 1815.000 | -| ZonedDateTime::forComponents(Basic_cached) | 1224.000 | +| ZonedDateTime::forComponents(Basic_nocache) | 1816.000 | +| ZonedDateTime::forComponents(Basic_cached) | 1225.000 | | ZonedDateTime::forComponents(Extended_nocache) | -1.000 | | ZonedDateTime::forComponents(Extended_cached) | -1.000 | |--------------------------------------------------+----------| -| ZonedExtra::forEpochSeconds(Basic_nocache) | 893.000 | -| ZonedExtra::forEpochSeconds(Basic_cached) | 323.000 | +| ZonedExtra::forEpochSeconds(Basic_nocache) | 895.000 | +| ZonedExtra::forEpochSeconds(Basic_cached) | 326.000 | | ZonedExtra::forEpochSeconds(Extended_nocache) | -1.000 | | ZonedExtra::forEpochSeconds(Extended_cached) | -1.000 | |--------------------------------------------------+----------| -| ZonedExtra::forComponents(Basic_nocache) | 1793.000 | -| ZonedExtra::forComponents(Basic_cached) | 1201.000 | +| ZonedExtra::forComponents(Basic_nocache) | 1796.000 | +| ZonedExtra::forComponents(Basic_cached) | 1206.000 | | ZonedExtra::forComponents(Extended_nocache) | -1.000 | | ZonedExtra::forComponents(Extended_cached) | -1.000 | |--------------------------------------------------+----------| -| BasicZoneManager::createForZoneName(binary) | 117.000 | +| BasicZoneManager::createForZoneName(binary) | 116.000 | | BasicZoneManager::createForZoneId(binary) | 49.000 | -| BasicZoneManager::createForZoneId(linear) | 299.000 | +| BasicZoneManager::createForZoneId(linear) | 300.000 | +--------------------------------------------------+----------+ Iterations_per_run: 1000 @@ -284,10 +297,10 @@ sizeof(TimeZoneData): 5 sizeof(ZonedDateTime): 15 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 142 -sizeof(ExtendedZoneProcessor): 456 -sizeof(BasicZoneProcessorCache<1>): 146 -sizeof(ExtendedZoneProcessorCache<1>): 460 +sizeof(BasicZoneProcessor): 143 +sizeof(ExtendedZoneProcessor): 457 +sizeof(BasicZoneProcessorCache<1>): 147 +sizeof(ExtendedZoneProcessorCache<1>): 461 sizeof(BasicZoneManager): 7 sizeof(ExtendedZoneManager): 7 sizeof(internal::ZoneContext): 14 @@ -307,40 +320,40 @@ CPU: |--------------------------------------------------+----------| | EmptyLoop | 3.000 | |--------------------------------------------------+----------| -| LocalDate::forEpochDays() | 244.000 | -| LocalDate::toEpochDays() | 49.000 | -| LocalDate::dayOfWeek() | 48.000 | +| LocalDate::forEpochDays() | 245.000 | +| LocalDate::toEpochDays() | 50.000 | +| LocalDate::dayOfWeek() | 47.000 | |--------------------------------------------------+----------| | OffsetDateTime::forEpochSeconds() | 367.000 | | OffsetDateTime::toEpochSeconds() | 78.000 | |--------------------------------------------------+----------| | ZonedDateTime::toEpochSeconds() | 77.000 | -| ZonedDateTime::toEpochDays() | 67.000 | -| ZonedDateTime::forEpochSeconds(UTC) | 393.000 | +| ZonedDateTime::toEpochDays() | 66.000 | +| ZonedDateTime::forEpochSeconds(UTC) | 392.000 | |--------------------------------------------------+----------| | ZonedDateTime::forEpochSeconds(Basic_nocache) | 1273.000 | | ZonedDateTime::forEpochSeconds(Basic_cached) | 702.000 | | ZonedDateTime::forEpochSeconds(Extended_nocache) | -1.000 | | ZonedDateTime::forEpochSeconds(Extended_cached) | -1.000 | |--------------------------------------------------+----------| -| ZonedDateTime::forComponents(Basic_nocache) | 1825.000 | -| ZonedDateTime::forComponents(Basic_cached) | 1231.000 | +| ZonedDateTime::forComponents(Basic_nocache) | 1826.000 | +| ZonedDateTime::forComponents(Basic_cached) | 1232.000 | | ZonedDateTime::forComponents(Extended_nocache) | -1.000 | | ZonedDateTime::forComponents(Extended_cached) | -1.000 | |--------------------------------------------------+----------| -| ZonedExtra::forEpochSeconds(Basic_nocache) | 898.000 | -| ZonedExtra::forEpochSeconds(Basic_cached) | 326.000 | +| ZonedExtra::forEpochSeconds(Basic_nocache) | 900.000 | +| ZonedExtra::forEpochSeconds(Basic_cached) | 327.000 | | ZonedExtra::forEpochSeconds(Extended_nocache) | -1.000 | | ZonedExtra::forEpochSeconds(Extended_cached) | -1.000 | |--------------------------------------------------+----------| -| ZonedExtra::forComponents(Basic_nocache) | 1802.000 | -| ZonedExtra::forComponents(Basic_cached) | 1210.000 | +| ZonedExtra::forComponents(Basic_nocache) | 1806.000 | +| ZonedExtra::forComponents(Basic_cached) | 1212.000 | | ZonedExtra::forComponents(Extended_nocache) | -1.000 | | ZonedExtra::forComponents(Extended_cached) | -1.000 | |--------------------------------------------------+----------| -| BasicZoneManager::createForZoneName(binary) | 115.000 | -| BasicZoneManager::createForZoneId(binary) | 49.000 | -| BasicZoneManager::createForZoneId(linear) | 300.000 | +| BasicZoneManager::createForZoneName(binary) | 117.000 | +| BasicZoneManager::createForZoneId(binary) | 50.000 | +| BasicZoneManager::createForZoneId(linear) | 299.000 | +--------------------------------------------------+----------+ Iterations_per_run: 1000 @@ -350,7 +363,7 @@ Iterations_per_run: 1000 * SAMD21, 48 MHz ARM Cortex-M0+ * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* Seeeduino 1.8.3 +* Seeeduino 1.8.4 ``` Sizes of Objects: @@ -364,10 +377,10 @@ sizeof(TimeZoneData): 8 sizeof(ZonedDateTime): 24 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 204 -sizeof(ExtendedZoneProcessor): 604 -sizeof(BasicZoneProcessorCache<1>): 212 -sizeof(ExtendedZoneProcessorCache<1>): 612 +sizeof(BasicZoneProcessor): 208 +sizeof(ExtendedZoneProcessor): 608 +sizeof(BasicZoneProcessorCache<1>): 216 +sizeof(ExtendedZoneProcessorCache<1>): 616 sizeof(BasicZoneManager): 12 sizeof(ExtendedZoneManager): 12 sizeof(internal::ZoneContext): 24 @@ -387,40 +400,40 @@ CPU: |--------------------------------------------------+----------| | EmptyLoop | 1.400 | |--------------------------------------------------+----------| -| LocalDate::forEpochDays() | 11.600 | -| LocalDate::toEpochDays() | 6.000 | +| LocalDate::forEpochDays() | 11.800 | +| LocalDate::toEpochDays() | 5.600 | | LocalDate::dayOfWeek() | 6.800 | |--------------------------------------------------+----------| | OffsetDateTime::forEpochSeconds() | 21.800 | -| OffsetDateTime::toEpochSeconds() | 12.000 | +| OffsetDateTime::toEpochSeconds() | 12.400 | |--------------------------------------------------+----------| -| ZonedDateTime::toEpochSeconds() | 12.200 | -| ZonedDateTime::toEpochDays() | 10.000 | -| ZonedDateTime::forEpochSeconds(UTC) | 24.200 | +| ZonedDateTime::toEpochSeconds() | 12.000 | +| ZonedDateTime::toEpochDays() | 9.800 | +| ZonedDateTime::forEpochSeconds(UTC) | 24.400 | |--------------------------------------------------+----------| | ZonedDateTime::forEpochSeconds(Basic_nocache) | 182.000 | -| ZonedDateTime::forEpochSeconds(Basic_cached) | 46.600 | -| ZonedDateTime::forEpochSeconds(Extended_nocache) | 493.400 | -| ZonedDateTime::forEpochSeconds(Extended_cached) | 57.800 | -|--------------------------------------------------+----------| -| ZonedDateTime::forComponents(Basic_nocache) | 246.400 | -| ZonedDateTime::forComponents(Basic_cached) | 96.600 | -| ZonedDateTime::forComponents(Extended_nocache) | 370.800 | -| ZonedDateTime::forComponents(Extended_cached) | 19.800 | -|--------------------------------------------------+----------| -| ZonedExtra::forEpochSeconds(Basic_nocache) | 157.400 | -| ZonedExtra::forEpochSeconds(Basic_cached) | 22.000 | -| ZonedExtra::forEpochSeconds(Extended_nocache) | 468.600 | -| ZonedExtra::forEpochSeconds(Extended_cached) | 33.400 | -|--------------------------------------------------+----------| -| ZonedExtra::forComponents(Basic_nocache) | 241.400 | -| ZonedExtra::forComponents(Basic_cached) | 91.400 | -| ZonedExtra::forComponents(Extended_nocache) | 365.600 | -| ZonedExtra::forComponents(Extended_cached) | 14.600 | -|--------------------------------------------------+----------| -| BasicZoneManager::createForZoneName(binary) | 16.000 | +| ZonedDateTime::forEpochSeconds(Basic_cached) | 47.000 | +| ZonedDateTime::forEpochSeconds(Extended_nocache) | 492.400 | +| ZonedDateTime::forEpochSeconds(Extended_cached) | 58.400 | +|--------------------------------------------------+----------| +| ZonedDateTime::forComponents(Basic_nocache) | 247.400 | +| ZonedDateTime::forComponents(Basic_cached) | 98.000 | +| ZonedDateTime::forComponents(Extended_nocache) | 368.800 | +| ZonedDateTime::forComponents(Extended_cached) | 20.000 | +|--------------------------------------------------+----------| +| ZonedExtra::forEpochSeconds(Basic_nocache) | 159.000 | +| ZonedExtra::forEpochSeconds(Basic_cached) | 24.000 | +| ZonedExtra::forEpochSeconds(Extended_nocache) | 469.000 | +| ZonedExtra::forEpochSeconds(Extended_cached) | 35.400 | +|--------------------------------------------------+----------| +| ZonedExtra::forComponents(Basic_nocache) | 244.000 | +| ZonedExtra::forComponents(Basic_cached) | 94.600 | +| ZonedExtra::forComponents(Extended_nocache) | 365.400 | +| ZonedExtra::forComponents(Extended_cached) | 16.600 | +|--------------------------------------------------+----------| +| BasicZoneManager::createForZoneName(binary) | 15.200 | | BasicZoneManager::createForZoneId(binary) | 4.200 | -| BasicZoneManager::createForZoneId(linear) | 14.400 | +| BasicZoneManager::createForZoneId(linear) | 14.200 | +--------------------------------------------------+----------+ Iterations_per_run: 5000 @@ -430,7 +443,7 @@ Iterations_per_run: 5000 * STM32F103C8, 72 MHz ARM Cortex-M3 * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* STM32duino 2.4.0 +* STM32duino 2.5.0 ``` Sizes of Objects: @@ -444,10 +457,10 @@ sizeof(TimeZoneData): 8 sizeof(ZonedDateTime): 24 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 204 -sizeof(ExtendedZoneProcessor): 604 -sizeof(BasicZoneProcessorCache<1>): 212 -sizeof(ExtendedZoneProcessorCache<1>): 612 +sizeof(BasicZoneProcessor): 208 +sizeof(ExtendedZoneProcessor): 608 +sizeof(BasicZoneProcessorCache<1>): 216 +sizeof(ExtendedZoneProcessorCache<1>): 616 sizeof(BasicZoneManager): 12 sizeof(ExtendedZoneManager): 12 sizeof(internal::ZoneContext): 24 @@ -468,49 +481,49 @@ CPU: | EmptyLoop | 1.200 | |--------------------------------------------------+----------| | LocalDate::forEpochDays() | 2.800 | -| LocalDate::toEpochDays() | 1.500 | -| LocalDate::dayOfWeek() | 1.400 | +| LocalDate::toEpochDays() | 1.300 | +| LocalDate::dayOfWeek() | 1.200 | |--------------------------------------------------+----------| -| OffsetDateTime::forEpochSeconds() | 4.400 | -| OffsetDateTime::toEpochSeconds() | 5.000 | +| OffsetDateTime::forEpochSeconds() | 4.200 | +| OffsetDateTime::toEpochSeconds() | 4.700 | |--------------------------------------------------+----------| -| ZonedDateTime::toEpochSeconds() | 5.000 | -| ZonedDateTime::toEpochDays() | 3.800 | -| ZonedDateTime::forEpochSeconds(UTC) | 6.400 | +| ZonedDateTime::toEpochSeconds() | 4.600 | +| ZonedDateTime::toEpochDays() | 3.300 | +| ZonedDateTime::forEpochSeconds(UTC) | 6.300 | |--------------------------------------------------+----------| -| ZonedDateTime::forEpochSeconds(Basic_nocache) | 81.700 | -| ZonedDateTime::forEpochSeconds(Basic_cached) | 12.500 | -| ZonedDateTime::forEpochSeconds(Extended_nocache) | 198.800 | -| ZonedDateTime::forEpochSeconds(Extended_cached) | 16.700 | +| ZonedDateTime::forEpochSeconds(Basic_nocache) | 76.300 | +| ZonedDateTime::forEpochSeconds(Basic_cached) | 12.300 | +| ZonedDateTime::forEpochSeconds(Extended_nocache) | 200.000 | +| ZonedDateTime::forEpochSeconds(Extended_cached) | 16.900 | |--------------------------------------------------+----------| -| ZonedDateTime::forComponents(Basic_nocache) | 106.300 | -| ZonedDateTime::forComponents(Basic_cached) | 36.200 | -| ZonedDateTime::forComponents(Extended_nocache) | 154.400 | +| ZonedDateTime::forComponents(Basic_nocache) | 100.800 | +| ZonedDateTime::forComponents(Basic_cached) | 36.300 | +| ZonedDateTime::forComponents(Extended_nocache) | 155.300 | | ZonedDateTime::forComponents(Extended_cached) | 7.400 | |--------------------------------------------------+----------| -| ZonedExtra::forEpochSeconds(Basic_nocache) | 77.300 | -| ZonedExtra::forEpochSeconds(Basic_cached) | 7.700 | -| ZonedExtra::forEpochSeconds(Extended_nocache) | 193.900 | -| ZonedExtra::forEpochSeconds(Extended_cached) | 11.900 | +| ZonedExtra::forEpochSeconds(Basic_nocache) | 72.000 | +| ZonedExtra::forEpochSeconds(Basic_cached) | 7.600 | +| ZonedExtra::forEpochSeconds(Extended_nocache) | 195.100 | +| ZonedExtra::forEpochSeconds(Extended_cached) | 12.000 | |--------------------------------------------------+----------| -| ZonedExtra::forComponents(Basic_nocache) | 105.600 | +| ZonedExtra::forComponents(Basic_nocache) | 100.200 | | ZonedExtra::forComponents(Basic_cached) | 35.600 | -| ZonedExtra::forComponents(Extended_nocache) | 153.600 | +| ZonedExtra::forComponents(Extended_nocache) | 154.500 | | ZonedExtra::forComponents(Extended_cached) | 6.800 | |--------------------------------------------------+----------| -| BasicZoneManager::createForZoneName(binary) | 11.200 | -| BasicZoneManager::createForZoneId(binary) | 2.400 | -| BasicZoneManager::createForZoneId(linear) | 17.700 | +| BasicZoneManager::createForZoneName(binary) | 12.900 | +| BasicZoneManager::createForZoneId(binary) | 2.700 | +| BasicZoneManager::createForZoneId(linear) | 17.100 | +--------------------------------------------------+----------+ Iterations_per_run: 10000 ``` -## ESP8266 +## Adafruit ItsyBitsy M4 SAMD51 -* NodeMCU 1.0 clone, 80MHz ESP8266 +* SAMD51, 120 MHz ARM Cortex-M4 * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* ESP8266 Boards 3.0.2 +* Adafruit SAMD 1.7.11 ``` Sizes of Objects: @@ -524,10 +537,10 @@ sizeof(TimeZoneData): 8 sizeof(ZonedDateTime): 24 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 204 -sizeof(ExtendedZoneProcessor): 604 -sizeof(BasicZoneProcessorCache<1>): 212 -sizeof(ExtendedZoneProcessorCache<1>): 612 +sizeof(BasicZoneProcessor): 208 +sizeof(ExtendedZoneProcessor): 608 +sizeof(BasicZoneProcessorCache<1>): 216 +sizeof(ExtendedZoneProcessorCache<1>): 616 sizeof(BasicZoneManager): 12 sizeof(ExtendedZoneManager): 12 sizeof(internal::ZoneContext): 24 @@ -545,52 +558,52 @@ CPU: +--------------------------------------------------+----------+ | Method | micros | |--------------------------------------------------+----------| -| EmptyLoop | 5.000 | +| EmptyLoop | 0.400 | +|--------------------------------------------------+----------| +| LocalDate::forEpochDays() | 1.200 | +| LocalDate::toEpochDays() | 0.400 | +| LocalDate::dayOfWeek() | 0.600 | |--------------------------------------------------+----------| -| LocalDate::forEpochDays() | 6.200 | -| LocalDate::toEpochDays() | 3.000 | -| LocalDate::dayOfWeek() | 3.800 | +| OffsetDateTime::forEpochSeconds() | 2.000 | +| OffsetDateTime::toEpochSeconds() | 2.400 | |--------------------------------------------------+----------| -| OffsetDateTime::forEpochSeconds() | 12.200 | -| OffsetDateTime::toEpochSeconds() | 6.800 | +| ZonedDateTime::toEpochSeconds() | 2.200 | +| ZonedDateTime::toEpochDays() | 1.600 | +| ZonedDateTime::forEpochSeconds(UTC) | 2.600 | |--------------------------------------------------+----------| -| ZonedDateTime::toEpochSeconds() | 7.000 | -| ZonedDateTime::toEpochDays() | 5.600 | -| ZonedDateTime::forEpochSeconds(UTC) | 14.800 | +| ZonedDateTime::forEpochSeconds(Basic_nocache) | 33.000 | +| ZonedDateTime::forEpochSeconds(Basic_cached) | 5.600 | +| ZonedDateTime::forEpochSeconds(Extended_nocache) | 91.800 | +| ZonedDateTime::forEpochSeconds(Extended_cached) | 7.600 | |--------------------------------------------------+----------| -| ZonedDateTime::forEpochSeconds(Basic_nocache) | 102.800 | -| ZonedDateTime::forEpochSeconds(Basic_cached) | 22.000 | -| ZonedDateTime::forEpochSeconds(Extended_nocache) | 238.800 | -| ZonedDateTime::forEpochSeconds(Extended_cached) | 29.000 | +| ZonedDateTime::forComponents(Basic_nocache) | 45.800 | +| ZonedDateTime::forComponents(Basic_cached) | 17.400 | +| ZonedDateTime::forComponents(Extended_nocache) | 71.000 | +| ZonedDateTime::forComponents(Extended_cached) | 3.400 | |--------------------------------------------------+----------| -| ZonedDateTime::forComponents(Basic_nocache) | 125.600 | -| ZonedDateTime::forComponents(Basic_cached) | 47.200 | -| ZonedDateTime::forComponents(Extended_nocache) | 172.200 | -| ZonedDateTime::forComponents(Extended_cached) | 3.200 | +| ZonedExtra::forEpochSeconds(Basic_nocache) | 30.600 | +| ZonedExtra::forEpochSeconds(Basic_cached) | 3.600 | +| ZonedExtra::forEpochSeconds(Extended_nocache) | 87.800 | +| ZonedExtra::forEpochSeconds(Extended_cached) | 5.400 | |--------------------------------------------------+----------| -| ZonedExtra::forEpochSeconds(Basic_nocache) | 92.800 | -| ZonedExtra::forEpochSeconds(Basic_cached) | 8.400 | -| ZonedExtra::forEpochSeconds(Extended_nocache) | 224.400 | -| ZonedExtra::forEpochSeconds(Extended_cached) | 14.800 | -|--------------------------------------------------+----------| -| ZonedExtra::forComponents(Basic_nocache) | 124.400 | -| ZonedExtra::forComponents(Basic_cached) | 46.000 | -| ZonedExtra::forComponents(Extended_nocache) | 171.000 | -| ZonedExtra::forComponents(Extended_cached) | 2.200 | -|--------------------------------------------------+----------| -| BasicZoneManager::createForZoneName(binary) | 14.800 | -| BasicZoneManager::createForZoneId(binary) | 6.200 | -| BasicZoneManager::createForZoneId(linear) | 43.200 | +| ZonedExtra::forComponents(Basic_nocache) | 46.200 | +| ZonedExtra::forComponents(Basic_cached) | 17.200 | +| ZonedExtra::forComponents(Extended_nocache) | 70.200 | +| ZonedExtra::forComponents(Extended_cached) | 3.000 | +|--------------------------------------------------+----------| +| BasicZoneManager::createForZoneName(binary) | 4.800 | +| BasicZoneManager::createForZoneId(binary) | 1.400 | +| BasicZoneManager::createForZoneId(linear) | 4.200 | +--------------------------------------------------+----------+ Iterations_per_run: 5000 ``` -## ESP32 +## ESP8266 -* ESP32-01 Dev Board, 240 MHz Tensilica LX6 +* NodeMCU 1.0 clone, 80MHz ESP8266 * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* ESP32 Boards 2.0.7 +* ESP8266 Boards 3.0.2 ``` Sizes of Objects: @@ -604,10 +617,10 @@ sizeof(TimeZoneData): 8 sizeof(ZonedDateTime): 24 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 204 -sizeof(ExtendedZoneProcessor): 604 -sizeof(BasicZoneProcessorCache<1>): 212 -sizeof(ExtendedZoneProcessorCache<1>): 612 +sizeof(BasicZoneProcessor): 208 +sizeof(ExtendedZoneProcessor): 608 +sizeof(BasicZoneProcessorCache<1>): 216 +sizeof(ExtendedZoneProcessorCache<1>): 616 sizeof(BasicZoneManager): 12 sizeof(ExtendedZoneManager): 12 sizeof(internal::ZoneContext): 24 @@ -625,56 +638,52 @@ CPU: +--------------------------------------------------+----------+ | Method | micros | |--------------------------------------------------+----------| -| EmptyLoop | 1.200 | -|--------------------------------------------------+----------| -| LocalDate::forEpochDays() | 0.850 | -| LocalDate::toEpochDays() | 0.300 | -| LocalDate::dayOfWeek() | 0.400 | +| EmptyLoop | 4.800 | |--------------------------------------------------+----------| -| OffsetDateTime::forEpochSeconds() | 1.650 | -| OffsetDateTime::toEpochSeconds() | 1.550 | +| LocalDate::forEpochDays() | 7.400 | +| LocalDate::toEpochDays() | 2.800 | +| LocalDate::dayOfWeek() | 3.600 | |--------------------------------------------------+----------| -| ZonedDateTime::toEpochSeconds() | 1.350 | -| ZonedDateTime::toEpochDays() | 1.150 | -| ZonedDateTime::forEpochSeconds(UTC) | 3.150 | +| OffsetDateTime::forEpochSeconds() | 12.600 | +| OffsetDateTime::toEpochSeconds() | 7.000 | |--------------------------------------------------+----------| -| ZonedDateTime::forEpochSeconds(Basic_nocache) | 17.450 | -| ZonedDateTime::forEpochSeconds(Basic_cached) | 3.500 | -| ZonedDateTime::forEpochSeconds(Extended_nocache) | 47.300 | -| ZonedDateTime::forEpochSeconds(Extended_cached) | 4.850 | +| ZonedDateTime::toEpochSeconds() | 6.800 | +| ZonedDateTime::toEpochDays() | 5.800 | +| ZonedDateTime::forEpochSeconds(UTC) | 15.000 | |--------------------------------------------------+----------| -| ZonedDateTime::forComponents(Basic_nocache) | 25.250 | -| ZonedDateTime::forComponents(Basic_cached) | 11.300 | -| ZonedDateTime::forComponents(Extended_nocache) | 36.000 | -| ZonedDateTime::forComponents(Extended_cached) | 2.100 | -|--------------------------------------------------+----------| -| ZonedExtra::forEpochSeconds(Basic_nocache) | 16.050 | -| ZonedExtra::forEpochSeconds(Basic_cached) | 1.300 | -| ZonedExtra::forEpochSeconds(Extended_nocache) | 45.000 | -| ZonedExtra::forEpochSeconds(Extended_cached) | 2.650 | +| ZonedDateTime::forEpochSeconds(Basic_nocache) | 103.000 | +| ZonedDateTime::forEpochSeconds(Basic_cached) | 22.800 | +| ZonedDateTime::forEpochSeconds(Extended_nocache) | 239.200 | +| ZonedDateTime::forEpochSeconds(Extended_cached) | 29.200 | |--------------------------------------------------+----------| -| ZonedExtra::forComponents(Basic_nocache) | 24.050 | -| ZonedExtra::forComponents(Basic_cached) | 10.100 | -| ZonedExtra::forComponents(Extended_nocache) | 34.800 | -| ZonedExtra::forComponents(Extended_cached) | 0.900 | +| ZonedDateTime::forComponents(Basic_nocache) | 126.000 | +| ZonedDateTime::forComponents(Basic_cached) | 47.800 | +| ZonedDateTime::forComponents(Extended_nocache) | 172.400 | +| ZonedDateTime::forComponents(Extended_cached) | 3.400 | |--------------------------------------------------+----------| -| BasicZoneManager::createForZoneName(binary) | 3.000 | -| BasicZoneManager::createForZoneId(binary) | 0.650 | -| BasicZoneManager::createForZoneId(linear) | 2.850 | +| ZonedExtra::forEpochSeconds(Basic_nocache) | 92.800 | +| ZonedExtra::forEpochSeconds(Basic_cached) | 8.600 | +| ZonedExtra::forEpochSeconds(Extended_nocache) | 224.800 | +| ZonedExtra::forEpochSeconds(Extended_cached) | 15.200 | +|--------------------------------------------------+----------| +| ZonedExtra::forComponents(Basic_nocache) | 124.800 | +| ZonedExtra::forComponents(Basic_cached) | 46.600 | +| ZonedExtra::forComponents(Extended_nocache) | 171.400 | +| ZonedExtra::forComponents(Extended_cached) | 2.400 | +|--------------------------------------------------+----------| +| BasicZoneManager::createForZoneName(binary) | 14.600 | +| BasicZoneManager::createForZoneId(binary) | 6.600 | +| BasicZoneManager::createForZoneId(linear) | 43.000 | +--------------------------------------------------+----------+ -Iterations_per_run: 20000 +Iterations_per_run: 5000 ``` -Note: Once the benchmark of the function under test becomes smaller than the -duration of an empty loop, the numbers become unreliable. - -## Teensy 3.2 +## ESP32 -* 96 MHz ARM Cortex-M4 +* ESP32-01 Dev Board, 240 MHz Tensilica LX6 * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* Teensyduino 1.57 -* Compiler options: "Faster" +* ESP32 Boards 2.0.9 ``` Sizes of Objects: @@ -688,10 +697,10 @@ sizeof(TimeZoneData): 8 sizeof(ZonedDateTime): 24 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 204 -sizeof(ExtendedZoneProcessor): 604 -sizeof(BasicZoneProcessorCache<1>): 212 -sizeof(ExtendedZoneProcessorCache<1>): 612 +sizeof(BasicZoneProcessor): 208 +sizeof(ExtendedZoneProcessor): 608 +sizeof(BasicZoneProcessorCache<1>): 216 +sizeof(ExtendedZoneProcessorCache<1>): 616 sizeof(BasicZoneManager): 12 sizeof(ExtendedZoneManager): 12 sizeof(internal::ZoneContext): 24 @@ -709,44 +718,47 @@ CPU: +--------------------------------------------------+----------+ | Method | micros | |--------------------------------------------------+----------| -| EmptyLoop | 0.400 | +| EmptyLoop | 1.200 | |--------------------------------------------------+----------| -| LocalDate::forEpochDays() | 2.300 | -| LocalDate::toEpochDays() | 0.450 | -| LocalDate::dayOfWeek() | 1.000 | +| LocalDate::forEpochDays() | 0.800 | +| LocalDate::toEpochDays() | 0.250 | +| LocalDate::dayOfWeek() | 0.400 | |--------------------------------------------------+----------| -| OffsetDateTime::forEpochSeconds() | 3.100 | -| OffsetDateTime::toEpochSeconds() | 0.700 | +| OffsetDateTime::forEpochSeconds() | 1.700 | +| OffsetDateTime::toEpochSeconds() | 1.450 | |--------------------------------------------------+----------| -| ZonedDateTime::toEpochSeconds() | 1.150 | -| ZonedDateTime::toEpochDays() | 1.050 | -| ZonedDateTime::forEpochSeconds(UTC) | 3.600 | +| ZonedDateTime::toEpochSeconds() | 1.350 | +| ZonedDateTime::toEpochDays() | 1.150 | +| ZonedDateTime::forEpochSeconds(UTC) | 3.200 | |--------------------------------------------------+----------| -| ZonedDateTime::forEpochSeconds(Basic_nocache) | 42.550 | -| ZonedDateTime::forEpochSeconds(Basic_cached) | 8.700 | -| ZonedDateTime::forEpochSeconds(Extended_nocache) | 112.150 | -| ZonedDateTime::forEpochSeconds(Extended_cached) | 10.400 | +| ZonedDateTime::forEpochSeconds(Basic_nocache) | 17.400 | +| ZonedDateTime::forEpochSeconds(Basic_cached) | 3.550 | +| ZonedDateTime::forEpochSeconds(Extended_nocache) | 47.250 | +| ZonedDateTime::forEpochSeconds(Extended_cached) | 4.900 | |--------------------------------------------------+----------| -| ZonedDateTime::forComponents(Basic_nocache) | 56.400 | -| ZonedDateTime::forComponents(Basic_cached) | 21.800 | -| ZonedDateTime::forComponents(Extended_nocache) | 87.450 | -| ZonedDateTime::forComponents(Extended_cached) | 4.450 | +| ZonedDateTime::forComponents(Basic_nocache) | 25.300 | +| ZonedDateTime::forComponents(Basic_cached) | 11.400 | +| ZonedDateTime::forComponents(Extended_nocache) | 35.950 | +| ZonedDateTime::forComponents(Extended_cached) | 2.100 | |--------------------------------------------------+----------| -| ZonedExtra::forEpochSeconds(Basic_nocache) | 40.200 | -| ZonedExtra::forEpochSeconds(Basic_cached) | 6.250 | -| ZonedExtra::forEpochSeconds(Extended_nocache) | 110.000 | -| ZonedExtra::forEpochSeconds(Extended_cached) | 8.050 | +| ZonedExtra::forEpochSeconds(Basic_nocache) | 16.150 | +| ZonedExtra::forEpochSeconds(Basic_cached) | 1.400 | +| ZonedExtra::forEpochSeconds(Extended_nocache) | 45.100 | +| ZonedExtra::forEpochSeconds(Extended_cached) | 2.800 | |--------------------------------------------------+----------| -| ZonedExtra::forComponents(Basic_nocache) | 56.650 | -| ZonedExtra::forComponents(Basic_cached) | 22.100 | -| ZonedExtra::forComponents(Extended_nocache) | 87.700 | -| ZonedExtra::forComponents(Extended_cached) | 4.800 | +| ZonedExtra::forComponents(Basic_nocache) | 24.150 | +| ZonedExtra::forComponents(Basic_cached) | 10.300 | +| ZonedExtra::forComponents(Extended_nocache) | 34.900 | +| ZonedExtra::forComponents(Extended_cached) | 1.050 | |--------------------------------------------------+----------| -| BasicZoneManager::createForZoneName(binary) | 6.050 | -| BasicZoneManager::createForZoneId(binary) | 2.050 | -| BasicZoneManager::createForZoneId(linear) | 10.250 | +| BasicZoneManager::createForZoneName(binary) | 3.050 | +| BasicZoneManager::createForZoneId(binary) | 0.700 | +| BasicZoneManager::createForZoneId(linear) | 2.850 | +--------------------------------------------------+----------+ Iterations_per_run: 20000 ``` +Note: Once the benchmark of the function under test becomes smaller than the +duration of an empty loop, the numbers become unreliable. + diff --git a/examples/AutoBenchmark/esp32.txt b/examples/AutoBenchmark/esp32.txt index 8bc473729..b464b6313 100644 --- a/examples/AutoBenchmark/esp32.txt +++ b/examples/AutoBenchmark/esp32.txt @@ -9,10 +9,10 @@ sizeof(TimeZoneData): 8 sizeof(ZonedDateTime): 24 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 204 -sizeof(ExtendedZoneProcessor): 604 -sizeof(BasicZoneProcessorCache<1>): 212 -sizeof(ExtendedZoneProcessorCache<1>): 612 +sizeof(BasicZoneProcessor): 208 +sizeof(ExtendedZoneProcessor): 608 +sizeof(BasicZoneProcessorCache<1>): 216 +sizeof(ExtendedZoneProcessorCache<1>): 616 sizeof(BasicZoneManager): 12 sizeof(ExtendedZoneManager): 12 sizeof(internal::ZoneContext): 24 @@ -27,32 +27,32 @@ sizeof(ExtendedZoneProcessor::TransitionStorage): 452 sizeof(ExtendedZoneProcessor::MatchingEra): 32 BENCHMARKS EmptyLoop 1.200 -LocalDate::forEpochDays() 0.850 -LocalDate::toEpochDays() 0.300 +LocalDate::forEpochDays() 0.800 +LocalDate::toEpochDays() 0.250 LocalDate::dayOfWeek() 0.400 -OffsetDateTime::forEpochSeconds() 1.650 -OffsetDateTime::toEpochSeconds() 1.550 +OffsetDateTime::forEpochSeconds() 1.700 +OffsetDateTime::toEpochSeconds() 1.450 ZonedDateTime::toEpochSeconds() 1.350 ZonedDateTime::toEpochDays() 1.150 -ZonedDateTime::forEpochSeconds(UTC) 3.150 -ZonedDateTime::forEpochSeconds(Basic_nocache) 17.450 -ZonedDateTime::forEpochSeconds(Basic_cached) 3.500 -ZonedDateTime::forEpochSeconds(Extended_nocache) 47.300 -ZonedDateTime::forEpochSeconds(Extended_cached) 4.850 -ZonedDateTime::forComponents(Basic_nocache) 25.250 -ZonedDateTime::forComponents(Basic_cached) 11.300 -ZonedDateTime::forComponents(Extended_nocache) 36.000 +ZonedDateTime::forEpochSeconds(UTC) 3.200 +ZonedDateTime::forEpochSeconds(Basic_nocache) 17.400 +ZonedDateTime::forEpochSeconds(Basic_cached) 3.550 +ZonedDateTime::forEpochSeconds(Extended_nocache) 47.250 +ZonedDateTime::forEpochSeconds(Extended_cached) 4.900 +ZonedDateTime::forComponents(Basic_nocache) 25.300 +ZonedDateTime::forComponents(Basic_cached) 11.400 +ZonedDateTime::forComponents(Extended_nocache) 35.950 ZonedDateTime::forComponents(Extended_cached) 2.100 -ZonedExtra::forEpochSeconds(Basic_nocache) 16.050 -ZonedExtra::forEpochSeconds(Basic_cached) 1.300 -ZonedExtra::forEpochSeconds(Extended_nocache) 45.000 -ZonedExtra::forEpochSeconds(Extended_cached) 2.650 -ZonedExtra::forComponents(Basic_nocache) 24.050 -ZonedExtra::forComponents(Basic_cached) 10.100 -ZonedExtra::forComponents(Extended_nocache) 34.800 -ZonedExtra::forComponents(Extended_cached) 0.900 -BasicZoneManager::createForZoneName(binary) 3.000 -BasicZoneManager::createForZoneId(binary) 0.650 +ZonedExtra::forEpochSeconds(Basic_nocache) 16.150 +ZonedExtra::forEpochSeconds(Basic_cached) 1.400 +ZonedExtra::forEpochSeconds(Extended_nocache) 45.100 +ZonedExtra::forEpochSeconds(Extended_cached) 2.800 +ZonedExtra::forComponents(Basic_nocache) 24.150 +ZonedExtra::forComponents(Basic_cached) 10.300 +ZonedExtra::forComponents(Extended_nocache) 34.900 +ZonedExtra::forComponents(Extended_cached) 1.050 +BasicZoneManager::createForZoneName(binary) 3.050 +BasicZoneManager::createForZoneId(binary) 0.700 BasicZoneManager::createForZoneId(linear) 2.850 Iterations_per_run 20000 END diff --git a/examples/AutoBenchmark/esp8266.txt b/examples/AutoBenchmark/esp8266.txt index aea96477a..7aa4052c0 100644 --- a/examples/AutoBenchmark/esp8266.txt +++ b/examples/AutoBenchmark/esp8266.txt @@ -9,10 +9,10 @@ sizeof(TimeZoneData): 8 sizeof(ZonedDateTime): 24 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 204 -sizeof(ExtendedZoneProcessor): 604 -sizeof(BasicZoneProcessorCache<1>): 212 -sizeof(ExtendedZoneProcessorCache<1>): 612 +sizeof(BasicZoneProcessor): 208 +sizeof(ExtendedZoneProcessor): 608 +sizeof(BasicZoneProcessorCache<1>): 216 +sizeof(ExtendedZoneProcessorCache<1>): 616 sizeof(BasicZoneManager): 12 sizeof(ExtendedZoneManager): 12 sizeof(internal::ZoneContext): 24 @@ -26,33 +26,33 @@ sizeof(ExtendedZoneProcessor::Transition): 52 sizeof(ExtendedZoneProcessor::TransitionStorage): 452 sizeof(ExtendedZoneProcessor::MatchingEra): 32 BENCHMARKS -EmptyLoop 5.000 -LocalDate::forEpochDays() 6.200 -LocalDate::toEpochDays() 3.000 -LocalDate::dayOfWeek() 3.800 -OffsetDateTime::forEpochSeconds() 12.200 -OffsetDateTime::toEpochSeconds() 6.800 -ZonedDateTime::toEpochSeconds() 7.000 -ZonedDateTime::toEpochDays() 5.600 -ZonedDateTime::forEpochSeconds(UTC) 14.800 -ZonedDateTime::forEpochSeconds(Basic_nocache) 102.800 -ZonedDateTime::forEpochSeconds(Basic_cached) 22.000 -ZonedDateTime::forEpochSeconds(Extended_nocache) 238.800 -ZonedDateTime::forEpochSeconds(Extended_cached) 29.000 -ZonedDateTime::forComponents(Basic_nocache) 125.600 -ZonedDateTime::forComponents(Basic_cached) 47.200 -ZonedDateTime::forComponents(Extended_nocache) 172.200 -ZonedDateTime::forComponents(Extended_cached) 3.200 +EmptyLoop 4.800 +LocalDate::forEpochDays() 7.400 +LocalDate::toEpochDays() 2.800 +LocalDate::dayOfWeek() 3.600 +OffsetDateTime::forEpochSeconds() 12.600 +OffsetDateTime::toEpochSeconds() 7.000 +ZonedDateTime::toEpochSeconds() 6.800 +ZonedDateTime::toEpochDays() 5.800 +ZonedDateTime::forEpochSeconds(UTC) 15.000 +ZonedDateTime::forEpochSeconds(Basic_nocache) 103.000 +ZonedDateTime::forEpochSeconds(Basic_cached) 22.800 +ZonedDateTime::forEpochSeconds(Extended_nocache) 239.200 +ZonedDateTime::forEpochSeconds(Extended_cached) 29.200 +ZonedDateTime::forComponents(Basic_nocache) 126.000 +ZonedDateTime::forComponents(Basic_cached) 47.800 +ZonedDateTime::forComponents(Extended_nocache) 172.400 +ZonedDateTime::forComponents(Extended_cached) 3.400 ZonedExtra::forEpochSeconds(Basic_nocache) 92.800 -ZonedExtra::forEpochSeconds(Basic_cached) 8.400 -ZonedExtra::forEpochSeconds(Extended_nocache) 224.400 -ZonedExtra::forEpochSeconds(Extended_cached) 14.800 -ZonedExtra::forComponents(Basic_nocache) 124.400 -ZonedExtra::forComponents(Basic_cached) 46.000 -ZonedExtra::forComponents(Extended_nocache) 171.000 -ZonedExtra::forComponents(Extended_cached) 2.200 -BasicZoneManager::createForZoneName(binary) 14.800 -BasicZoneManager::createForZoneId(binary) 6.200 -BasicZoneManager::createForZoneId(linear) 43.200 +ZonedExtra::forEpochSeconds(Basic_cached) 8.600 +ZonedExtra::forEpochSeconds(Extended_nocache) 224.800 +ZonedExtra::forEpochSeconds(Extended_cached) 15.200 +ZonedExtra::forComponents(Basic_nocache) 124.800 +ZonedExtra::forComponents(Basic_cached) 46.600 +ZonedExtra::forComponents(Extended_nocache) 171.400 +ZonedExtra::forComponents(Extended_cached) 2.400 +BasicZoneManager::createForZoneName(binary) 14.600 +BasicZoneManager::createForZoneId(binary) 6.600 +BasicZoneManager::createForZoneId(linear) 43.000 Iterations_per_run 5000 END diff --git a/examples/AutoBenchmark/generate_readme.py b/examples/AutoBenchmark/generate_readme.py index 9c5a567c9..1e0e68a19 100755 --- a/examples/AutoBenchmark/generate_readme.py +++ b/examples/AutoBenchmark/generate_readme.py @@ -14,12 +14,12 @@ "./generate_table.awk < samd21.txt", shell=True, text=True) stm32_results = check_output( "./generate_table.awk < stm32.txt", shell=True, text=True) +samd51_results = check_output( + "./generate_table.awk < samd51.txt", shell=True, text=True) esp8266_results = check_output( "./generate_table.awk < esp8266.txt", shell=True, text=True) esp32_results = check_output( "./generate_table.awk < esp32.txt", shell=True, text=True) -teensy32_results = check_output( - "./generate_table.awk < teensy32.txt", shell=True, text=True) print(f"""\ # Auto Benchmark @@ -28,7 +28,7 @@ These results show that integer division and modulus operations are incredibly slow on 8-bit AVR processors. -**Version**: AceTime v2.2.0 +**Version**: AceTime v2.2.3 **NOTE**: This file was auto-generated using `make README.md`. DO NOT EDIT. @@ -210,6 +210,19 @@ * Seeeduino 1.8.3 * Upgrade to TZDB 2023b +**v2.2.2** +* Upgrade to TZDB 2023c + +**v2.2.3** +* Add support for Adafruit ItsyBitsy M4 + * Using Adafruit SAMD Core 1.7.11 +* Remove Teensy 3.2 + * Nearing end of life. Moved to Tier 2 (should work). +* Upgrade tool chain + * Seeeduino 1.8.4 + * STM32duino 2.5.0 + * ESP32 Boards 2.0.9 + ## Arduino Nano * 16MHz ATmega328P @@ -234,7 +247,7 @@ * SAMD21, 48 MHz ARM Cortex-M0+ * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* Seeeduino 1.8.3 +* Seeeduino 1.8.4 ``` {samd21_results} @@ -244,12 +257,22 @@ * STM32F103C8, 72 MHz ARM Cortex-M3 * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* STM32duino 2.4.0 +* STM32duino 2.5.0 ``` {stm32_results} ``` +## Adafruit ItsyBitsy M4 SAMD51 + +* SAMD51, 120 MHz ARM Cortex-M4 +* Arduino IDE 1.8.19, Arduino CLI 0.31.0 +* Adafruit SAMD 1.7.11 + +``` +{samd51_results} +``` + ## ESP8266 * NodeMCU 1.0 clone, 80MHz ESP8266 @@ -264,7 +287,7 @@ * ESP32-01 Dev Board, 240 MHz Tensilica LX6 * Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* ESP32 Boards 2.0.7 +* ESP32 Boards 2.0.9 ``` {esp32_results} @@ -272,15 +295,4 @@ Note: Once the benchmark of the function under test becomes smaller than the duration of an empty loop, the numbers become unreliable. - -## Teensy 3.2 - -* 96 MHz ARM Cortex-M4 -* Arduino IDE 1.8.19, Arduino CLI 0.31.0 -* Teensyduino 1.57 -* Compiler options: "Faster" - -``` -{teensy32_results} -``` """) diff --git a/examples/AutoBenchmark/micro.txt b/examples/AutoBenchmark/micro.txt index f95759813..2e1b41be5 100644 --- a/examples/AutoBenchmark/micro.txt +++ b/examples/AutoBenchmark/micro.txt @@ -9,10 +9,10 @@ sizeof(TimeZoneData): 5 sizeof(ZonedDateTime): 15 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 142 -sizeof(ExtendedZoneProcessor): 456 -sizeof(BasicZoneProcessorCache<1>): 146 -sizeof(ExtendedZoneProcessorCache<1>): 460 +sizeof(BasicZoneProcessor): 143 +sizeof(ExtendedZoneProcessor): 457 +sizeof(BasicZoneProcessorCache<1>): 147 +sizeof(ExtendedZoneProcessorCache<1>): 461 sizeof(BasicZoneManager): 7 sizeof(ExtendedZoneManager): 7 sizeof(internal::ZoneContext): 14 @@ -27,32 +27,32 @@ sizeof(ExtendedZoneProcessor::TransitionStorage): 348 sizeof(ExtendedZoneProcessor::MatchingEra): 24 BENCHMARKS EmptyLoop 3.000 -LocalDate::forEpochDays() 244.000 -LocalDate::toEpochDays() 49.000 -LocalDate::dayOfWeek() 48.000 +LocalDate::forEpochDays() 245.000 +LocalDate::toEpochDays() 50.000 +LocalDate::dayOfWeek() 47.000 OffsetDateTime::forEpochSeconds() 367.000 OffsetDateTime::toEpochSeconds() 78.000 ZonedDateTime::toEpochSeconds() 77.000 -ZonedDateTime::toEpochDays() 67.000 -ZonedDateTime::forEpochSeconds(UTC) 393.000 +ZonedDateTime::toEpochDays() 66.000 +ZonedDateTime::forEpochSeconds(UTC) 392.000 ZonedDateTime::forEpochSeconds(Basic_nocache) 1273.000 ZonedDateTime::forEpochSeconds(Basic_cached) 702.000 ZonedDateTime::forEpochSeconds(Extended_nocache) -1 ZonedDateTime::forEpochSeconds(Extended_cached) -1 -ZonedDateTime::forComponents(Basic_nocache) 1825.000 -ZonedDateTime::forComponents(Basic_cached) 1231.000 +ZonedDateTime::forComponents(Basic_nocache) 1826.000 +ZonedDateTime::forComponents(Basic_cached) 1232.000 ZonedDateTime::forComponents(Extended_nocache) -1 ZonedDateTime::forComponents(Extended_cached) -1 -ZonedExtra::forEpochSeconds(Basic_nocache) 898.000 -ZonedExtra::forEpochSeconds(Basic_cached) 326.000 +ZonedExtra::forEpochSeconds(Basic_nocache) 900.000 +ZonedExtra::forEpochSeconds(Basic_cached) 327.000 ZonedExtra::forEpochSeconds(Extended_nocache) -1 ZonedExtra::forEpochSeconds(Extended_cached) -1 -ZonedExtra::forComponents(Basic_nocache) 1802.000 -ZonedExtra::forComponents(Basic_cached) 1210.000 +ZonedExtra::forComponents(Basic_nocache) 1806.000 +ZonedExtra::forComponents(Basic_cached) 1212.000 ZonedExtra::forComponents(Extended_nocache) -1 ZonedExtra::forComponents(Extended_cached) -1 -BasicZoneManager::createForZoneName(binary) 115.000 -BasicZoneManager::createForZoneId(binary) 49.000 -BasicZoneManager::createForZoneId(linear) 300.000 +BasicZoneManager::createForZoneName(binary) 117.000 +BasicZoneManager::createForZoneId(binary) 50.000 +BasicZoneManager::createForZoneId(linear) 299.000 Iterations_per_run 1000 END diff --git a/examples/AutoBenchmark/nano.txt b/examples/AutoBenchmark/nano.txt index 69640de72..038ce7441 100644 --- a/examples/AutoBenchmark/nano.txt +++ b/examples/AutoBenchmark/nano.txt @@ -9,10 +9,10 @@ sizeof(TimeZoneData): 5 sizeof(ZonedDateTime): 15 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 142 -sizeof(ExtendedZoneProcessor): 456 -sizeof(BasicZoneProcessorCache<1>): 146 -sizeof(ExtendedZoneProcessorCache<1>): 460 +sizeof(BasicZoneProcessor): 143 +sizeof(ExtendedZoneProcessor): 457 +sizeof(BasicZoneProcessorCache<1>): 147 +sizeof(ExtendedZoneProcessorCache<1>): 461 sizeof(BasicZoneManager): 7 sizeof(ExtendedZoneManager): 7 sizeof(internal::ZoneContext): 14 @@ -39,20 +39,20 @@ ZonedDateTime::forEpochSeconds(Basic_nocache) 1266.000 ZonedDateTime::forEpochSeconds(Basic_cached) 698.000 ZonedDateTime::forEpochSeconds(Extended_nocache) -1 ZonedDateTime::forEpochSeconds(Extended_cached) -1 -ZonedDateTime::forComponents(Basic_nocache) 1815.000 -ZonedDateTime::forComponents(Basic_cached) 1224.000 +ZonedDateTime::forComponents(Basic_nocache) 1816.000 +ZonedDateTime::forComponents(Basic_cached) 1225.000 ZonedDateTime::forComponents(Extended_nocache) -1 ZonedDateTime::forComponents(Extended_cached) -1 -ZonedExtra::forEpochSeconds(Basic_nocache) 893.000 -ZonedExtra::forEpochSeconds(Basic_cached) 323.000 +ZonedExtra::forEpochSeconds(Basic_nocache) 895.000 +ZonedExtra::forEpochSeconds(Basic_cached) 326.000 ZonedExtra::forEpochSeconds(Extended_nocache) -1 ZonedExtra::forEpochSeconds(Extended_cached) -1 -ZonedExtra::forComponents(Basic_nocache) 1793.000 -ZonedExtra::forComponents(Basic_cached) 1201.000 +ZonedExtra::forComponents(Basic_nocache) 1796.000 +ZonedExtra::forComponents(Basic_cached) 1206.000 ZonedExtra::forComponents(Extended_nocache) -1 ZonedExtra::forComponents(Extended_cached) -1 -BasicZoneManager::createForZoneName(binary) 117.000 +BasicZoneManager::createForZoneName(binary) 116.000 BasicZoneManager::createForZoneId(binary) 49.000 -BasicZoneManager::createForZoneId(linear) 299.000 +BasicZoneManager::createForZoneId(linear) 300.000 Iterations_per_run 1000 END diff --git a/examples/AutoBenchmark/samd21.txt b/examples/AutoBenchmark/samd21.txt index d2633317c..17a6e2596 100644 --- a/examples/AutoBenchmark/samd21.txt +++ b/examples/AutoBenchmark/samd21.txt @@ -9,10 +9,10 @@ sizeof(TimeZoneData): 8 sizeof(ZonedDateTime): 24 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 204 -sizeof(ExtendedZoneProcessor): 604 -sizeof(BasicZoneProcessorCache<1>): 212 -sizeof(ExtendedZoneProcessorCache<1>): 612 +sizeof(BasicZoneProcessor): 208 +sizeof(ExtendedZoneProcessor): 608 +sizeof(BasicZoneProcessorCache<1>): 216 +sizeof(ExtendedZoneProcessorCache<1>): 616 sizeof(BasicZoneManager): 12 sizeof(ExtendedZoneManager): 12 sizeof(internal::ZoneContext): 24 @@ -27,32 +27,32 @@ sizeof(ExtendedZoneProcessor::TransitionStorage): 452 sizeof(ExtendedZoneProcessor::MatchingEra): 32 BENCHMARKS EmptyLoop 1.400 -LocalDate::forEpochDays() 11.600 -LocalDate::toEpochDays() 6.000 +LocalDate::forEpochDays() 11.800 +LocalDate::toEpochDays() 5.600 LocalDate::dayOfWeek() 6.800 OffsetDateTime::forEpochSeconds() 21.800 -OffsetDateTime::toEpochSeconds() 12.000 -ZonedDateTime::toEpochSeconds() 12.200 -ZonedDateTime::toEpochDays() 10.000 -ZonedDateTime::forEpochSeconds(UTC) 24.200 +OffsetDateTime::toEpochSeconds() 12.400 +ZonedDateTime::toEpochSeconds() 12.000 +ZonedDateTime::toEpochDays() 9.800 +ZonedDateTime::forEpochSeconds(UTC) 24.400 ZonedDateTime::forEpochSeconds(Basic_nocache) 182.000 -ZonedDateTime::forEpochSeconds(Basic_cached) 46.600 -ZonedDateTime::forEpochSeconds(Extended_nocache) 493.400 -ZonedDateTime::forEpochSeconds(Extended_cached) 57.800 -ZonedDateTime::forComponents(Basic_nocache) 246.400 -ZonedDateTime::forComponents(Basic_cached) 96.600 -ZonedDateTime::forComponents(Extended_nocache) 370.800 -ZonedDateTime::forComponents(Extended_cached) 19.800 -ZonedExtra::forEpochSeconds(Basic_nocache) 157.400 -ZonedExtra::forEpochSeconds(Basic_cached) 22.000 -ZonedExtra::forEpochSeconds(Extended_nocache) 468.600 -ZonedExtra::forEpochSeconds(Extended_cached) 33.400 -ZonedExtra::forComponents(Basic_nocache) 241.400 -ZonedExtra::forComponents(Basic_cached) 91.400 -ZonedExtra::forComponents(Extended_nocache) 365.600 -ZonedExtra::forComponents(Extended_cached) 14.600 -BasicZoneManager::createForZoneName(binary) 16.000 +ZonedDateTime::forEpochSeconds(Basic_cached) 47.000 +ZonedDateTime::forEpochSeconds(Extended_nocache) 492.400 +ZonedDateTime::forEpochSeconds(Extended_cached) 58.400 +ZonedDateTime::forComponents(Basic_nocache) 247.400 +ZonedDateTime::forComponents(Basic_cached) 98.000 +ZonedDateTime::forComponents(Extended_nocache) 368.800 +ZonedDateTime::forComponents(Extended_cached) 20.000 +ZonedExtra::forEpochSeconds(Basic_nocache) 159.000 +ZonedExtra::forEpochSeconds(Basic_cached) 24.000 +ZonedExtra::forEpochSeconds(Extended_nocache) 469.000 +ZonedExtra::forEpochSeconds(Extended_cached) 35.400 +ZonedExtra::forComponents(Basic_nocache) 244.000 +ZonedExtra::forComponents(Basic_cached) 94.600 +ZonedExtra::forComponents(Extended_nocache) 365.400 +ZonedExtra::forComponents(Extended_cached) 16.600 +BasicZoneManager::createForZoneName(binary) 15.200 BasicZoneManager::createForZoneId(binary) 4.200 -BasicZoneManager::createForZoneId(linear) 14.400 +BasicZoneManager::createForZoneId(linear) 14.200 Iterations_per_run 5000 END diff --git a/examples/AutoBenchmark/samd51.txt b/examples/AutoBenchmark/samd51.txt new file mode 100644 index 000000000..7144f8fd4 --- /dev/null +++ b/examples/AutoBenchmark/samd51.txt @@ -0,0 +1,58 @@ +SIZEOF +sizeof(LocalDate): 4 +sizeof(LocalTime): 4 +sizeof(LocalDateTime): 8 +sizeof(TimeOffset): 2 +sizeof(OffsetDateTime): 10 +sizeof(TimeZone): 12 +sizeof(TimeZoneData): 8 +sizeof(ZonedDateTime): 24 +sizeof(ZonedExtra): 16 +sizeof(TimePeriod): 4 +sizeof(BasicZoneProcessor): 208 +sizeof(ExtendedZoneProcessor): 608 +sizeof(BasicZoneProcessorCache<1>): 216 +sizeof(ExtendedZoneProcessorCache<1>): 616 +sizeof(BasicZoneManager): 12 +sizeof(ExtendedZoneManager): 12 +sizeof(internal::ZoneContext): 24 +sizeof(basic::ZoneEra): 16 +sizeof(basic::ZoneInfo): 24 +sizeof(basic::ZoneRule): 12 +sizeof(basic::ZonePolicy): 8 +sizeof(basic::ZoneRegistrar): 8 +sizeof(BasicZoneProcessor::Transition): 36 +sizeof(ExtendedZoneProcessor::Transition): 52 +sizeof(ExtendedZoneProcessor::TransitionStorage): 452 +sizeof(ExtendedZoneProcessor::MatchingEra): 32 +BENCHMARKS +EmptyLoop 0.400 +LocalDate::forEpochDays() 1.200 +LocalDate::toEpochDays() 0.400 +LocalDate::dayOfWeek() 0.600 +OffsetDateTime::forEpochSeconds() 2.000 +OffsetDateTime::toEpochSeconds() 2.400 +ZonedDateTime::toEpochSeconds() 2.200 +ZonedDateTime::toEpochDays() 1.600 +ZonedDateTime::forEpochSeconds(UTC) 2.600 +ZonedDateTime::forEpochSeconds(Basic_nocache) 33.000 +ZonedDateTime::forEpochSeconds(Basic_cached) 5.600 +ZonedDateTime::forEpochSeconds(Extended_nocache) 91.800 +ZonedDateTime::forEpochSeconds(Extended_cached) 7.600 +ZonedDateTime::forComponents(Basic_nocache) 45.800 +ZonedDateTime::forComponents(Basic_cached) 17.400 +ZonedDateTime::forComponents(Extended_nocache) 71.000 +ZonedDateTime::forComponents(Extended_cached) 3.400 +ZonedExtra::forEpochSeconds(Basic_nocache) 30.600 +ZonedExtra::forEpochSeconds(Basic_cached) 3.600 +ZonedExtra::forEpochSeconds(Extended_nocache) 87.800 +ZonedExtra::forEpochSeconds(Extended_cached) 5.400 +ZonedExtra::forComponents(Basic_nocache) 46.200 +ZonedExtra::forComponents(Basic_cached) 17.200 +ZonedExtra::forComponents(Extended_nocache) 70.200 +ZonedExtra::forComponents(Extended_cached) 3.000 +BasicZoneManager::createForZoneName(binary) 4.800 +BasicZoneManager::createForZoneId(binary) 1.400 +BasicZoneManager::createForZoneId(linear) 4.200 +Iterations_per_run 5000 +END diff --git a/examples/AutoBenchmark/stm32.txt b/examples/AutoBenchmark/stm32.txt index fca053e7a..ca7c06f8a 100644 --- a/examples/AutoBenchmark/stm32.txt +++ b/examples/AutoBenchmark/stm32.txt @@ -9,10 +9,10 @@ sizeof(TimeZoneData): 8 sizeof(ZonedDateTime): 24 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 204 -sizeof(ExtendedZoneProcessor): 604 -sizeof(BasicZoneProcessorCache<1>): 212 -sizeof(ExtendedZoneProcessorCache<1>): 612 +sizeof(BasicZoneProcessor): 208 +sizeof(ExtendedZoneProcessor): 608 +sizeof(BasicZoneProcessorCache<1>): 216 +sizeof(ExtendedZoneProcessorCache<1>): 616 sizeof(BasicZoneManager): 12 sizeof(ExtendedZoneManager): 12 sizeof(internal::ZoneContext): 24 @@ -28,31 +28,31 @@ sizeof(ExtendedZoneProcessor::MatchingEra): 32 BENCHMARKS EmptyLoop 1.200 LocalDate::forEpochDays() 2.800 -LocalDate::toEpochDays() 1.500 -LocalDate::dayOfWeek() 1.400 -OffsetDateTime::forEpochSeconds() 4.400 -OffsetDateTime::toEpochSeconds() 5.000 -ZonedDateTime::toEpochSeconds() 5.000 -ZonedDateTime::toEpochDays() 3.800 -ZonedDateTime::forEpochSeconds(UTC) 6.400 -ZonedDateTime::forEpochSeconds(Basic_nocache) 81.700 -ZonedDateTime::forEpochSeconds(Basic_cached) 12.500 -ZonedDateTime::forEpochSeconds(Extended_nocache) 198.800 -ZonedDateTime::forEpochSeconds(Extended_cached) 16.700 -ZonedDateTime::forComponents(Basic_nocache) 106.300 -ZonedDateTime::forComponents(Basic_cached) 36.200 -ZonedDateTime::forComponents(Extended_nocache) 154.400 +LocalDate::toEpochDays() 1.300 +LocalDate::dayOfWeek() 1.200 +OffsetDateTime::forEpochSeconds() 4.200 +OffsetDateTime::toEpochSeconds() 4.700 +ZonedDateTime::toEpochSeconds() 4.600 +ZonedDateTime::toEpochDays() 3.300 +ZonedDateTime::forEpochSeconds(UTC) 6.300 +ZonedDateTime::forEpochSeconds(Basic_nocache) 76.300 +ZonedDateTime::forEpochSeconds(Basic_cached) 12.300 +ZonedDateTime::forEpochSeconds(Extended_nocache) 200.000 +ZonedDateTime::forEpochSeconds(Extended_cached) 16.900 +ZonedDateTime::forComponents(Basic_nocache) 100.800 +ZonedDateTime::forComponents(Basic_cached) 36.300 +ZonedDateTime::forComponents(Extended_nocache) 155.300 ZonedDateTime::forComponents(Extended_cached) 7.400 -ZonedExtra::forEpochSeconds(Basic_nocache) 77.300 -ZonedExtra::forEpochSeconds(Basic_cached) 7.700 -ZonedExtra::forEpochSeconds(Extended_nocache) 193.900 -ZonedExtra::forEpochSeconds(Extended_cached) 11.900 -ZonedExtra::forComponents(Basic_nocache) 105.600 +ZonedExtra::forEpochSeconds(Basic_nocache) 72.000 +ZonedExtra::forEpochSeconds(Basic_cached) 7.600 +ZonedExtra::forEpochSeconds(Extended_nocache) 195.100 +ZonedExtra::forEpochSeconds(Extended_cached) 12.000 +ZonedExtra::forComponents(Basic_nocache) 100.200 ZonedExtra::forComponents(Basic_cached) 35.600 -ZonedExtra::forComponents(Extended_nocache) 153.600 +ZonedExtra::forComponents(Extended_nocache) 154.500 ZonedExtra::forComponents(Extended_cached) 6.800 -BasicZoneManager::createForZoneName(binary) 11.200 -BasicZoneManager::createForZoneId(binary) 2.400 -BasicZoneManager::createForZoneId(linear) 17.700 +BasicZoneManager::createForZoneName(binary) 12.900 +BasicZoneManager::createForZoneId(binary) 2.700 +BasicZoneManager::createForZoneId(linear) 17.100 Iterations_per_run 10000 END diff --git a/examples/AutoBenchmark/teensy32.txt b/examples/AutoBenchmark/teensy32.txt deleted file mode 100644 index d07ea1e1c..000000000 --- a/examples/AutoBenchmark/teensy32.txt +++ /dev/null @@ -1,58 +0,0 @@ -SIZEOF -sizeof(LocalDate): 4 -sizeof(LocalTime): 4 -sizeof(LocalDateTime): 8 -sizeof(TimeOffset): 2 -sizeof(OffsetDateTime): 10 -sizeof(TimeZone): 12 -sizeof(TimeZoneData): 8 -sizeof(ZonedDateTime): 24 -sizeof(ZonedExtra): 16 -sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 204 -sizeof(ExtendedZoneProcessor): 604 -sizeof(BasicZoneProcessorCache<1>): 212 -sizeof(ExtendedZoneProcessorCache<1>): 612 -sizeof(BasicZoneManager): 12 -sizeof(ExtendedZoneManager): 12 -sizeof(internal::ZoneContext): 24 -sizeof(basic::ZoneEra): 16 -sizeof(basic::ZoneInfo): 24 -sizeof(basic::ZoneRule): 12 -sizeof(basic::ZonePolicy): 8 -sizeof(basic::ZoneRegistrar): 8 -sizeof(BasicZoneProcessor::Transition): 36 -sizeof(ExtendedZoneProcessor::Transition): 52 -sizeof(ExtendedZoneProcessor::TransitionStorage): 452 -sizeof(ExtendedZoneProcessor::MatchingEra): 32 -BENCHMARKS -EmptyLoop 0.400 -LocalDate::forEpochDays() 2.300 -LocalDate::toEpochDays() 0.450 -LocalDate::dayOfWeek() 1.000 -OffsetDateTime::forEpochSeconds() 3.100 -OffsetDateTime::toEpochSeconds() 0.700 -ZonedDateTime::toEpochSeconds() 1.150 -ZonedDateTime::toEpochDays() 1.050 -ZonedDateTime::forEpochSeconds(UTC) 3.600 -ZonedDateTime::forEpochSeconds(Basic_nocache) 42.550 -ZonedDateTime::forEpochSeconds(Basic_cached) 8.700 -ZonedDateTime::forEpochSeconds(Extended_nocache) 112.150 -ZonedDateTime::forEpochSeconds(Extended_cached) 10.400 -ZonedDateTime::forComponents(Basic_nocache) 56.400 -ZonedDateTime::forComponents(Basic_cached) 21.800 -ZonedDateTime::forComponents(Extended_nocache) 87.450 -ZonedDateTime::forComponents(Extended_cached) 4.450 -ZonedExtra::forEpochSeconds(Basic_nocache) 40.200 -ZonedExtra::forEpochSeconds(Basic_cached) 6.250 -ZonedExtra::forEpochSeconds(Extended_nocache) 110.000 -ZonedExtra::forEpochSeconds(Extended_cached) 8.050 -ZonedExtra::forComponents(Basic_nocache) 56.650 -ZonedExtra::forComponents(Basic_cached) 22.100 -ZonedExtra::forComponents(Extended_nocache) 87.700 -ZonedExtra::forComponents(Extended_cached) 4.800 -BasicZoneManager::createForZoneName(binary) 6.050 -BasicZoneManager::createForZoneId(binary) 2.050 -BasicZoneManager::createForZoneId(linear) 10.250 -Iterations_per_run 20000 -END From 19dc323e82b4986b88707ea15af6fa2191559222 Mon Sep 17 00:00:00 2001 From: Brian Park Date: Wed, 31 May 2023 16:28:00 -0700 Subject: [PATCH 18/21] Bump version to 2.2.3 --- CHANGELOG.md | 18 ++++ README.md | 156 +++++++++++++++--------------- USER_GUIDE.md | 2 +- docs/doxygen.cfg | 2 +- examples/AutoBenchmark/Makefile | 8 +- examples/MemoryBenchmark/Makefile | 2 +- library.properties | 2 +- src/AceTime.h | 4 +- 8 files changed, 109 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 952c1fe9b..a00e95537 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog * Unreleased +* 2.2.3 (2023-05-31, TZDB version 2023c) * Update `ace_time/testing/*` classes to support splitting the test data into 2 separate lists: `transitions` and `samples`. * Required to support new `validation_data.json` from AceTimeValidation. @@ -23,6 +24,23 @@ `daysToCurrentEpochFromInternalEpoch()`. * This is an internal implementation detail, exposed only for testing purposes. + * Update supported boards and tiers + * Add SAMD21 and SAMD51 boards to Tier 1 + * Add Adafruit ItsyBitsy M4 (SAMD51 120MHz ARM Cortex-M4) + * SAMD21 and SAMD51 boards are back in Tier 1, as long as they use + the traditional Arduino API instead of the new + [Arduino-Core](https://github.com/arduino/ArduinoCore-api). + * Fortunately most third party SAMD21 and SAMD51 boards continue to + use the traditional Arduino API. + * Move Teensy 3.2 to Tier 2 + * This board is entering end-of-life. + * As well, the Teensyduino environment integrates with the Arduino + IDE and CLI in a way that's different than all other third-party + Arduino boards. Some of my automation scripts do not work with + Teensyduino, so it becomes very time consuming to test the Teensy + boards. + * All Teensy boards are now in Tier 2 ("Should work but not tested + often"). * 2.2.2 (2023-04-01, TZDB version 2023c) * Upgrade TZDB from 2023b to 2023c. * https://mm.icann.org/pipermail/tz-announce/2023-March/000079.html diff --git a/README.md b/README.md index 518bcb0c6..5301df39d 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ This library can be an alternative to the Arduino Time offsets of type `kTypeManual`. See [Migrating to v2.2.0](MIGRATING.md#MigratingToVersion220) for details. -**Version**: 2.2.2 (2023-04-01, TZDB version 2023c) +**Version**: 2.2.3 (2023-05-31, TZDB version 2023c) **Changelog**: [CHANGELOG.md](CHANGELOG.md) @@ -499,6 +499,7 @@ different programming languages: **8-bit processors** ``` +Sizes of Objects: sizeof(LocalDate): 4 sizeof(LocalTime): 4 sizeof(LocalDateTime): 8 @@ -509,10 +510,10 @@ sizeof(TimeZoneData): 5 sizeof(ZonedDateTime): 15 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 142 -sizeof(ExtendedZoneProcessor): 456 -sizeof(BasicZoneProcessorCache<1>): 146 -sizeof(ExtendedZoneProcessorCache<1>): 460 +sizeof(BasicZoneProcessor): 143 +sizeof(ExtendedZoneProcessor): 457 +sizeof(BasicZoneProcessorCache<1>): 147 +sizeof(ExtendedZoneProcessorCache<1>): 461 sizeof(BasicZoneManager): 7 sizeof(ExtendedZoneManager): 7 sizeof(internal::ZoneContext): 14 @@ -529,6 +530,7 @@ sizeof(ExtendedZoneProcessor::MatchingEra): 24 **32-bit processors** ``` +Sizes of Objects: sizeof(LocalDate): 4 sizeof(LocalTime): 4 sizeof(LocalDateTime): 8 @@ -539,10 +541,10 @@ sizeof(TimeZoneData): 8 sizeof(ZonedDateTime): 24 sizeof(ZonedExtra): 16 sizeof(TimePeriod): 4 -sizeof(BasicZoneProcessor): 204 -sizeof(ExtendedZoneProcessor): 604 -sizeof(BasicZoneProcessorCache<1>): 212 -sizeof(ExtendedZoneProcessorCache<1>): 612 +sizeof(BasicZoneProcessor): 208 +sizeof(ExtendedZoneProcessor): 608 +sizeof(BasicZoneProcessorCache<1>): 216 +sizeof(ExtendedZoneProcessorCache<1>): 616 sizeof(BasicZoneManager): 12 sizeof(ExtendedZoneManager): 12 sizeof(internal::ZoneContext): 24 @@ -614,23 +616,23 @@ Arduino Nano: | ZonedDateTime | 1440/ 28 | 966/ 17 | | Manual ZoneManager | 1398/ 13 | 924/ 2 | |----------------------------------------+--------------+-------------| -| Basic TimeZone (1 zone) | 6870/ 355 | 6396/ 344 | -| Basic TimeZone (2 zones) | 7336/ 503 | 6862/ 492 | -| BasicZoneManager (1 zone) | 7074/ 366 | 6600/ 355 | -| BasicZoneManager (all zones) | 19764/ 744 | 19290/ 733 | -| BasicZoneManager (all zones+links) | 25116/ 744 | 24642/ 733 | +| Basic TimeZone (1 zone) | 6892/ 356 | 6418/ 345 | +| Basic TimeZone (2 zones) | 7356/ 505 | 6882/ 494 | +| BasicZoneManager (1 zone) | 7096/ 367 | 6622/ 356 | +| BasicZoneManager (all zones) | 19746/ 745 | 19272/ 734 | +| BasicZoneManager (all zones+links) | 25126/ 745 | 24652/ 734 | |----------------------------------------+--------------+-------------| -| Basic ZoneSorterByName [1] | 7690/ 368 | 616/ 2 | -| Basic ZoneSorterByOffsetAndName [1] | 7862/ 368 | 788/ 2 | +| Basic ZoneSorterByName [1] | 7712/ 369 | 616/ 2 | +| Basic ZoneSorterByOffsetAndName [1] | 7884/ 369 | 788/ 2 | |----------------------------------------+--------------+-------------| -| Extended TimeZone (1 zone) | 9992/ 742 | 9518/ 731 | -| Extended TimeZone (2 zones) | 10508/ 1207 | 10034/ 1196 | -| ExtendedZoneManager (1 zone) | 10168/ 748 | 9694/ 737 | -| ExtendedZoneManager (all zones) | 34416/ 1208 | 33942/ 1197 | -| ExtendedZoneManager (all zones+links) | 40420/ 1208 | 39946/ 1197 | +| Extended TimeZone (1 zone) | 9980/ 743 | 9506/ 732 | +| Extended TimeZone (2 zones) | 10496/ 1209 | 10022/ 1198 | +| ExtendedZoneManager (1 zone) | 10156/ 749 | 9682/ 738 | +| ExtendedZoneManager (all zones) | 35246/ 1209 | 34772/ 1198 | +| ExtendedZoneManager (all zones+links) | 41278/ 1209 | 40804/ 1198 | |----------------------------------------+--------------+-------------| -| Extended ZoneSorterByName [2] | 10780/ 750 | 612/ 2 | -| Extended ZoneSorterByOffsetAndName [2] | 10958/ 750 | 790/ 2 | +| Extended ZoneSorterByName [2] | 10768/ 751 | 612/ 2 | +| Extended ZoneSorterByOffsetAndName [2] | 10946/ 751 | 790/ 2 | +---------------------------------------------------------------------+ ``` @@ -642,27 +644,27 @@ ESP8266: |----------------------------------------+--------------+-------------| | baseline | 260089/27892 | 0/ 0 | |----------------------------------------+--------------+-------------| -| LocalDateTime | 260613/27912 | 524/ 20 | -| ZonedDateTime | 261733/27928 | 1644/ 36 | +| LocalDateTime | 292761/28732 | 32672/ 840 | +| ZonedDateTime | 267785/28732 | 7696/ 840 | | Manual ZoneManager | 261713/27900 | 1624/ 8 | |----------------------------------------+--------------+-------------| -| Basic TimeZone (1 zone) | 266965/28704 | 6876/ 812 | -| Basic TimeZone (2 zones) | 267461/28904 | 7372/ 1012 | -| BasicZoneManager (1 zone) | 267125/28720 | 7036/ 828 | -| BasicZoneManager (all zones) | 284261/28720 | 24172/ 828 | -| BasicZoneManager (all zones+links) | 292741/28720 | 32652/ 828 | +| Basic TimeZone (1 zone) | 266985/28708 | 6896/ 816 | +| Basic TimeZone (2 zones) | 267481/28916 | 7392/ 1024 | +| BasicZoneManager (1 zone) | 267145/28732 | 7056/ 840 | +| BasicZoneManager (all zones) | 284233/28732 | 24144/ 840 | +| BasicZoneManager (all zones+links) | 292761/28732 | 32672/ 840 | |----------------------------------------+--------------+-------------| -| Basic ZoneSorterByName [1] | 267749/28728 | 624/ 8 | -| Basic ZoneSorterByOffsetAndName [1] | 267893/28728 | 768/ 8 | +| Basic ZoneSorterByName [1] | 267785/28732 | 640/ 0 | +| Basic ZoneSorterByOffsetAndName [1] | 267913/28732 | 768/ 0 | |----------------------------------------+--------------+-------------| -| Extended TimeZone (1 zone) | 269021/29288 | 8932/ 1396 | -| Extended TimeZone (2 zones) | 269581/29904 | 9492/ 2012 | -| ExtendedZoneManager (1 zone) | 269165/29296 | 9076/ 1404 | -| ExtendedZoneManager (all zones) | 301581/29296 | 41492/ 1404 | -| ExtendedZoneManager (all zones+links) | 311117/29296 | 51028/ 1404 | +| Extended TimeZone (1 zone) | 269025/29300 | 8936/ 1408 | +| Extended TimeZone (2 zones) | 269601/29916 | 9512/ 2024 | +| ExtendedZoneManager (1 zone) | 269185/29308 | 9096/ 1416 | +| ExtendedZoneManager (all zones) | 302497/29308 | 42408/ 1416 | +| ExtendedZoneManager (all zones+links) | 312065/29308 | 51976/ 1416 | |----------------------------------------+--------------+-------------| -| Extended ZoneSorterByName [2] | 269789/29304 | 624/ 8 | -| Extended ZoneSorterByOffsetAndName [2] | 269821/29304 | 656/ 8 | +| Extended ZoneSorterByName [2] | 269809/29308 | 624/ 0 | +| Extended ZoneSorterByOffsetAndName [2] | 269841/29308 | 656/ 0 | +---------------------------------------------------------------------+ ``` @@ -697,24 +699,24 @@ Arduino Nano: | ZonedDateTime::forEpochSeconds(Extended_nocache) | -1.000 | | ZonedDateTime::forEpochSeconds(Extended_cached) | -1.000 | |--------------------------------------------------+----------| -| ZonedDateTime::forComponents(Basic_nocache) | 1815.000 | -| ZonedDateTime::forComponents(Basic_cached) | 1224.000 | +| ZonedDateTime::forComponents(Basic_nocache) | 1816.000 | +| ZonedDateTime::forComponents(Basic_cached) | 1225.000 | | ZonedDateTime::forComponents(Extended_nocache) | -1.000 | | ZonedDateTime::forComponents(Extended_cached) | -1.000 | |--------------------------------------------------+----------| -| ZonedExtra::forEpochSeconds(Basic_nocache) | 893.000 | -| ZonedExtra::forEpochSeconds(Basic_cached) | 323.000 | +| ZonedExtra::forEpochSeconds(Basic_nocache) | 895.000 | +| ZonedExtra::forEpochSeconds(Basic_cached) | 326.000 | | ZonedExtra::forEpochSeconds(Extended_nocache) | -1.000 | | ZonedExtra::forEpochSeconds(Extended_cached) | -1.000 | |--------------------------------------------------+----------| -| ZonedExtra::forComponents(Basic_nocache) | 1793.000 | -| ZonedExtra::forComponents(Basic_cached) | 1201.000 | +| ZonedExtra::forComponents(Basic_nocache) | 1796.000 | +| ZonedExtra::forComponents(Basic_cached) | 1206.000 | | ZonedExtra::forComponents(Extended_nocache) | -1.000 | | ZonedExtra::forComponents(Extended_cached) | -1.000 | |--------------------------------------------------+----------| -| BasicZoneManager::createForZoneName(binary) | 117.000 | +| BasicZoneManager::createForZoneName(binary) | 116.000 | | BasicZoneManager::createForZoneId(binary) | 49.000 | -| BasicZoneManager::createForZoneId(linear) | 299.000 | +| BasicZoneManager::createForZoneId(linear) | 300.000 | +--------------------------------------------------+----------+ Iterations_per_run: 1000 ``` @@ -725,42 +727,42 @@ ESP8266: +--------------------------------------------------+----------+ | Method | micros | |--------------------------------------------------+----------| -| EmptyLoop | 5.000 | +| EmptyLoop | 4.800 | |--------------------------------------------------+----------| -| LocalDate::forEpochDays() | 6.200 | -| LocalDate::toEpochDays() | 3.000 | -| LocalDate::dayOfWeek() | 3.800 | +| LocalDate::forEpochDays() | 7.400 | +| LocalDate::toEpochDays() | 2.800 | +| LocalDate::dayOfWeek() | 3.600 | |--------------------------------------------------+----------| -| OffsetDateTime::forEpochSeconds() | 12.200 | -| OffsetDateTime::toEpochSeconds() | 6.800 | +| OffsetDateTime::forEpochSeconds() | 12.600 | +| OffsetDateTime::toEpochSeconds() | 7.000 | |--------------------------------------------------+----------| -| ZonedDateTime::toEpochSeconds() | 7.000 | -| ZonedDateTime::toEpochDays() | 5.600 | -| ZonedDateTime::forEpochSeconds(UTC) | 14.800 | +| ZonedDateTime::toEpochSeconds() | 6.800 | +| ZonedDateTime::toEpochDays() | 5.800 | +| ZonedDateTime::forEpochSeconds(UTC) | 15.000 | |--------------------------------------------------+----------| -| ZonedDateTime::forEpochSeconds(Basic_nocache) | 102.800 | -| ZonedDateTime::forEpochSeconds(Basic_cached) | 22.000 | -| ZonedDateTime::forEpochSeconds(Extended_nocache) | 238.800 | -| ZonedDateTime::forEpochSeconds(Extended_cached) | 29.000 | +| ZonedDateTime::forEpochSeconds(Basic_nocache) | 103.000 | +| ZonedDateTime::forEpochSeconds(Basic_cached) | 22.800 | +| ZonedDateTime::forEpochSeconds(Extended_nocache) | 239.200 | +| ZonedDateTime::forEpochSeconds(Extended_cached) | 29.200 | |--------------------------------------------------+----------| -| ZonedDateTime::forComponents(Basic_nocache) | 125.600 | -| ZonedDateTime::forComponents(Basic_cached) | 47.200 | -| ZonedDateTime::forComponents(Extended_nocache) | 172.200 | -| ZonedDateTime::forComponents(Extended_cached) | 3.200 | +| ZonedDateTime::forComponents(Basic_nocache) | 126.000 | +| ZonedDateTime::forComponents(Basic_cached) | 47.800 | +| ZonedDateTime::forComponents(Extended_nocache) | 172.400 | +| ZonedDateTime::forComponents(Extended_cached) | 3.400 | |--------------------------------------------------+----------| | ZonedExtra::forEpochSeconds(Basic_nocache) | 92.800 | -| ZonedExtra::forEpochSeconds(Basic_cached) | 8.400 | -| ZonedExtra::forEpochSeconds(Extended_nocache) | 224.400 | -| ZonedExtra::forEpochSeconds(Extended_cached) | 14.800 | +| ZonedExtra::forEpochSeconds(Basic_cached) | 8.600 | +| ZonedExtra::forEpochSeconds(Extended_nocache) | 224.800 | +| ZonedExtra::forEpochSeconds(Extended_cached) | 15.200 | |--------------------------------------------------+----------| -| ZonedExtra::forComponents(Basic_nocache) | 124.400 | -| ZonedExtra::forComponents(Basic_cached) | 46.000 | -| ZonedExtra::forComponents(Extended_nocache) | 171.000 | -| ZonedExtra::forComponents(Extended_cached) | 2.200 | +| ZonedExtra::forComponents(Basic_nocache) | 124.800 | +| ZonedExtra::forComponents(Basic_cached) | 46.600 | +| ZonedExtra::forComponents(Extended_nocache) | 171.400 | +| ZonedExtra::forComponents(Extended_cached) | 2.400 | |--------------------------------------------------+----------| -| BasicZoneManager::createForZoneName(binary) | 14.800 | -| BasicZoneManager::createForZoneId(binary) | 6.200 | -| BasicZoneManager::createForZoneId(linear) | 43.200 | +| BasicZoneManager::createForZoneName(binary) | 14.600 | +| BasicZoneManager::createForZoneId(binary) | 6.600 | +| BasicZoneManager::createForZoneId(linear) | 43.000 | +--------------------------------------------------+----------+ Iterations_per_run: 5000 ``` @@ -779,10 +781,10 @@ These boards are tested on each release: * SparkFun Pro Micro (16 MHz ATmega32U4) * Seeed Studio XIAO M0 (SAMD21, 48 MHz ARM Cortex-M0+) * STM32 Blue Pill (STM32F103C8, 72 MHz ARM Cortex-M3) +* Adafruit ItsyBitsy M4 (SAMD51, 120 MHz ARM Cortex-M4) * NodeMCU 1.0 (ESP-12E module, 80 MHz ESP8266) * WeMos D1 Mini (ESP-12E module, 80 MHz ESP8266) * ESP32 dev board (ESP-WROOM-32 module, 240 MHz dual core Tensilica LX6) -* Teensy 3.2 (96 MHz ARM Cortex-M4) **Tier 2: Should work** @@ -792,6 +794,7 @@ These boards should work but I don't test them as often: * Arduino Pro Mini (16 MHz ATmega328P) * Mini Mega 2560 (Arduino Mega 2560 compatible, 16 MHz ATmega2560) * Teensy LC (48 MHz ARM Cortex-M0+) +* Teensy 3.2 (96 MHz ARM Cortex-M4) **Tier 3: May work, but not supported** @@ -801,7 +804,8 @@ These boards should work but I don't test them as often: boards. These are explicitly blacklisted. See below. * Other 3rd party SAMD21 boards using the previous Arduino API. * The ones using the previous Arduino API *may* work but I have not - explicitly tested any of them except for the Seeed Studio XIAO M0. + explicitly tested any of them except for the Seeed Studio XIAO M0 + and Adafruit ItsyBitsy M4. **Tier Blacklisted** diff --git a/USER_GUIDE.md b/USER_GUIDE.md index d90b19b64..d788c0bff 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -18,7 +18,7 @@ valid from the years `[2000,10000)`. By adjusting the `currentEpochYear()`, the library will work across any 100 year interval across the 8000 year range of the TZ database. -**Version**: 2.2.2 (2023-04-01, TZDB 2023c) +**Version**: 2.2.3 (2023-05-31, TZDB 2023c) **Related Documents**: diff --git a/docs/doxygen.cfg b/docs/doxygen.cfg index a210ec9db..c2dd7844e 100644 --- a/docs/doxygen.cfg +++ b/docs/doxygen.cfg @@ -38,7 +38,7 @@ PROJECT_NAME = AceTime # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2.2.0 +PROJECT_NUMBER = 2.2.3 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/examples/AutoBenchmark/Makefile b/examples/AutoBenchmark/Makefile index 2b745385b..1d0ab6048 100644 --- a/examples/AutoBenchmark/Makefile +++ b/examples/AutoBenchmark/Makefile @@ -13,9 +13,7 @@ AUNITER_DIR := ../../../AUniter/tools TARGETS := nano.txt micro.txt samd21.txt stm32.txt samd51.txt \ esp8266.txt esp32.txt -# It is not possible to auto-generate the $(TARGETS) because the USB ports are -# dynamic. -README.md: generate_readme.py generate_table.awk $(TARGETS) +README.md: $(TARGETS) generate_readme.py generate_table.awk ./generate_readme.py > $@ benchmarks: $(TARGETS) @@ -28,6 +26,7 @@ benchmarks: $(TARGETS) nano.txt: $(AUNITER_DIR)/auniter.sh --cli upmon -o $@ --eof END nano:USB0 +# Sparkfun Micro does not flash using the Arduino CLI. Use IDE instead. micro.txt: $(AUNITER_DIR)/auniter.sh --ide upmon -o $@ --eof END micro:ACM0 @@ -37,6 +36,9 @@ samd21.txt: stm32.txt: $(AUNITER_DIR)/auniter.sh --cli upmon -o $@ --eof END stm32:ACM0 +# ItsyBitsy M4 appears on ACM0 when powered on, then disappears after flashing, +# and reappears on ACM1s. Specifying the ports as "ACM*" tells auniter.sh to +# use any port satisfying the glob pattern. samd51.txt: $(AUNITER_DIR)/auniter.sh --cli upmon --delay 2 -o $@ --eof END itsym4:ACM* diff --git a/examples/MemoryBenchmark/Makefile b/examples/MemoryBenchmark/Makefile index 1bfdd0f4a..98caab98b 100644 --- a/examples/MemoryBenchmark/Makefile +++ b/examples/MemoryBenchmark/Makefile @@ -29,7 +29,7 @@ stm32.txt: ./collect.sh --cli stm32 $@ samd51.txt: - ./collect.sh --ide itsym4 $@ + ./collect.sh --cli itsym4 $@ esp8266.txt: ./collect.sh --cli nodemcu $@ diff --git a/library.properties b/library.properties index 11253ce40..3ef73e299 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=AceTime -version=2.2.2 +version=2.2.3 author=Brian T. Park maintainer=Brian T. Park sentence=Date, time, timezone classes for Arduino supporting the full IANA TZ Database to convert epoch seconds to date and time components in different time zones. diff --git a/src/AceTime.h b/src/AceTime.h index bd5f19552..805da9aed 100644 --- a/src/AceTime.h +++ b/src/AceTime.h @@ -66,7 +66,7 @@ #include "zonedbx/zone_registry.h" // Version format: xxyyzz == "xx.yy.zz" -#define ACE_TIME_VERSION 20202 -#define ACE_TIME_VERSION_STRING "2.2.2" +#define ACE_TIME_VERSION 20203 +#define ACE_TIME_VERSION_STRING "2.2.3" #endif From 67bb2a0a4e98521ff364008544f9d58fbbf42ebe Mon Sep 17 00:00:00 2001 From: Brian Park Date: Wed, 31 May 2023 16:28:29 -0700 Subject: [PATCH 19/21] docs: regenerate doxygen --- docs/html/AceTime_8h_source.html | 6 +- docs/html/BasicZoneProcessor_8h_source.html | 882 +- docs/html/BasicZone_8cpp_source.html | 2 +- docs/html/BasicZone_8h_source.html | 2 +- docs/html/BrokerCommon_8cpp_source.html | 2 +- docs/html/BrokerCommon_8h.html | 2 +- docs/html/BrokerCommon_8h_source.html | 2 +- docs/html/Brokers_8h.html | 2 +- docs/html/Brokers_8h_source.html | 2 +- docs/html/DateStrings_8cpp_source.html | 2 +- docs/html/DateStrings_8h_source.html | 2 +- docs/html/DateTuple_8h_source.html | 2 +- .../html/EpochConverterHinnant_8h_source.html | 106 +- docs/html/EpochConverterJulian_8h_source.html | 80 +- docs/html/Epoch_8cpp_source.html | 4 +- docs/html/Epoch_8h_source.html | 80 +- .../html/ExtendedZoneProcessor_8h_source.html | 540 +- docs/html/ExtendedZone_8cpp_source.html | 2 +- docs/html/ExtendedZone_8h_source.html | 2 +- docs/html/LocalDateTime_8cpp_source.html | 2 +- docs/html/LocalDateTime_8h_source.html | 6 +- docs/html/LocalDate_8cpp_source.html | 2 +- docs/html/LocalDate_8h_source.html | 14 +- docs/html/LocalTime_8cpp_source.html | 2 +- docs/html/LocalTime_8h_source.html | 2 +- docs/html/OffsetDateTime_8cpp_source.html | 2 +- docs/html/OffsetDateTime_8h_source.html | 4 +- docs/html/TimeOffset_8cpp_source.html | 2 +- docs/html/TimeOffset_8h_source.html | 2 +- docs/html/TimePeriod_8cpp_source.html | 2 +- docs/html/TimePeriod_8h_source.html | 2 +- docs/html/TimeZoneData_8h_source.html | 2 +- docs/html/TimeZone_8cpp_source.html | 6 +- docs/html/TimeZone_8h_source.html | 610 +- docs/html/Transition_8h_source.html | 2 +- docs/html/ZoneContext_8h_source.html | 2 +- docs/html/ZoneInfo_8h_source.html | 2 +- docs/html/ZoneInfo_8inc_source.html | 14 +- docs/html/ZoneManager_8h_source.html | 215 +- docs/html/ZonePolicy_8h_source.html | 2 +- docs/html/ZonePolicy_8inc_source.html | 2 +- docs/html/ZoneProcessorCache_8h_source.html | 174 +- docs/html/ZoneProcessor_8cpp_source.html | 2 +- docs/html/ZoneProcessor_8h_source.html | 147 +- docs/html/ZoneRegistrar_8h_source.html | 2 +- docs/html/ZoneSorterByName_8h_source.html | 2 +- .../ZoneSorterByOffsetAndName_8h_source.html | 2 +- docs/html/ZonedDateTime_8cpp_source.html | 2 +- docs/html/ZonedDateTime_8h_source.html | 6 +- docs/html/ZonedExtra_8cpp_source.html | 4 +- docs/html/ZonedExtra_8h_source.html | 217 +- docs/html/ace__time__utils_8h_source.html | 2 +- docs/html/annotated.html | 4 +- .../classace__time_1_1BasicZone-members.html | 2 +- docs/html/classace__time_1_1BasicZone.html | 2 +- ...ace__time_1_1BasicZoneManager-members.html | 9 +- .../classace__time_1_1BasicZoneManager.html | 7 +- ...e__time_1_1BasicZoneProcessor-members.html | 19 +- .../classace__time_1_1BasicZoneProcessor.html | 26 +- ...me_1_1BasicZoneProcessorCache-members.html | 7 +- ...sace__time_1_1BasicZoneProcessorCache.html | 7 +- ...1_1BasicZoneProcessorTemplate-members.html | 19 +- ...e__time_1_1BasicZoneProcessorTemplate.html | 26 +- ...classace__time_1_1DateStrings-members.html | 2 +- docs/html/classace__time_1_1DateStrings.html | 2 +- .../html/classace__time_1_1Epoch-members.html | 6 +- docs/html/classace__time_1_1Epoch.html | 57 +- ...lassace__time_1_1ExtendedZone-members.html | 2 +- docs/html/classace__time_1_1ExtendedZone.html | 2 +- ...__time_1_1ExtendedZoneManager-members.html | 9 +- ...classace__time_1_1ExtendedZoneManager.html | 7 +- ...time_1_1ExtendedZoneProcessor-members.html | 25 +- ...assace__time_1_1ExtendedZoneProcessor.html | 24 +- ...1_1ExtendedZoneProcessorCache-members.html | 7 +- ...e__time_1_1ExtendedZoneProcessorCache.html | 7 +- ...ExtendedZoneProcessorTemplate-members.html | 25 +- ...time_1_1ExtendedZoneProcessorTemplate.html | 50 +- .../classace__time_1_1FindResult-members.html | 2 +- docs/html/classace__time_1_1FindResult.html | 2 +- .../classace__time_1_1LocalDate-members.html | 2 +- docs/html/classace__time_1_1LocalDate.html | 6 +- ...assace__time_1_1LocalDateTime-members.html | 2 +- .../html/classace__time_1_1LocalDateTime.html | 6 +- .../classace__time_1_1LocalTime-members.html | 2 +- docs/html/classace__time_1_1LocalTime.html | 2 +- ...ce__time_1_1ManualZoneManager-members.html | 2 +- .../classace__time_1_1ManualZoneManager.html | 2 +- ...ssace__time_1_1OffsetDateTime-members.html | 2 +- .../classace__time_1_1OffsetDateTime.html | 6 +- .../classace__time_1_1TimeOffset-members.html | 2 +- docs/html/classace__time_1_1TimeOffset.html | 2 +- .../classace__time_1_1TimePeriod-members.html | 2 +- docs/html/classace__time_1_1TimePeriod.html | 2 +- .../classace__time_1_1TimeZone-members.html | 9 +- docs/html/classace__time_1_1TimeZone.html | 51 +- ...classace__time_1_1ZoneManager-members.html | 2 +- docs/html/classace__time_1_1ZoneManager.html | 2 +- ...__time_1_1ZoneManagerTemplate-members.html | 9 +- ...classace__time_1_1ZoneManagerTemplate.html | 39 +- ...assace__time_1_1ZoneProcessor-members.html | 15 +- .../html/classace__time_1_1ZoneProcessor.html | 161 +- ...oneProcessorCacheBaseTemplate-members.html | 7 +- ...ime_1_1ZoneProcessorCacheBaseTemplate.html | 37 +- ...ace__time_1_1ZoneSorterByName-members.html | 2 +- .../classace__time_1_1ZoneSorterByName.html | 2 +- ..._1_1ZoneSorterByOffsetAndName-members.html | 2 +- ...ce__time_1_1ZoneSorterByOffsetAndName.html | 2 +- ...assace__time_1_1ZonedDateTime-members.html | 2 +- .../html/classace__time_1_1ZonedDateTime.html | 2 +- .../classace__time_1_1ZonedExtra-members.html | 4 +- docs/html/classace__time_1_1ZonedExtra.html | 25 +- ...ime_1_1basic_1_1ZoneRegistrar-members.html | 2 +- ...ssace__time_1_1basic_1_1ZoneRegistrar.html | 2 +- ..._1_1TransitionStorageTemplate-members.html | 2 +- ...extended_1_1TransitionStorageTemplate.html | 2 +- ..._1_1extended_1_1ZoneRegistrar-members.html | 2 +- ...ce__time_1_1extended_1_1ZoneRegistrar.html | 2 +- ..._1_1internal_1_1BrokerFactory-members.html | 2 +- ...ce__time_1_1internal_1_1BrokerFactory.html | 2 +- ...rnal_1_1EpochConverterHinnant-members.html | 6 +- ..._1_1internal_1_1EpochConverterHinnant.html | 36 +- ...ernal_1_1EpochConverterJulian-members.html | 8 +- ...e_1_1internal_1_1EpochConverterJulian.html | 66 +- ..._1_1internal_1_1ZoneEraBroker-members.html | 2 +- ...ce__time_1_1internal_1_1ZoneEraBroker.html | 2 +- ...1_1internal_1_1ZoneInfoBroker-members.html | 2 +- ...e__time_1_1internal_1_1ZoneInfoBroker.html | 2 +- ...1internal_1_1ZonePolicyBroker-members.html | 2 +- ..._time_1_1internal_1_1ZonePolicyBroker.html | 2 +- ...rnal_1_1ZoneRegistrarTemplate-members.html | 2 +- ..._1_1internal_1_1ZoneRegistrarTemplate.html | 2 +- ...nternal_1_1ZoneRegistryBroker-members.html | 2 +- ...ime_1_1internal_1_1ZoneRegistryBroker.html | 2 +- ...1_1internal_1_1ZoneRuleBroker-members.html | 2 +- ...e__time_1_1internal_1_1ZoneRuleBroker.html | 2 +- docs/html/classes.html | 2 +- docs/html/common_8h.html | 2 +- docs/html/common_8h_source.html | 2 +- docs/html/compat_8cpp_source.html | 2 +- docs/html/compat_8h.html | 2 +- docs/html/compat_8h_source.html | 2 +- docs/html/dir_000001_000002.html | 2 +- docs/html/dir_000001_000007.html | 2 +- docs/html/dir_000002_000007.html | 2 +- docs/html/dir_000003_000007.html | 2 +- docs/html/dir_000004_000007.html | 2 +- docs/html/dir_000005_000007.html | 2 +- docs/html/dir_000006_000007.html | 2 +- .../dir_173dd563440c1e02d7e3957b90659cd7.html | 2 +- .../dir_4087a17cae141e7242c9415587ae2d90.html | 2 +- .../dir_68267d1309a1af8e8297ef4c3efbcdba.html | 2 +- .../dir_73858eb619507b1c2bdbcff2e4bdaf1e.html | 2 +- .../dir_8565b5e544addb4843ed500eff19b703.html | 2 +- .../dir_afb2025690de77b1a5b5001a410c869c.html | 2 +- .../dir_c458c1a7ede63e0a4ba7e7b60e917e99.html | 2 +- .../dir_df46910787f3e07390b8f19cc6a1d1b6.html | 2 +- docs/html/files.html | 2 +- docs/html/functions.html | 2 +- docs/html/functions_b.html | 2 +- docs/html/functions_c.html | 2 +- docs/html/functions_d.html | 10 +- docs/html/functions_e.html | 2 +- docs/html/functions_f.html | 2 +- docs/html/functions_func.html | 2 +- docs/html/functions_func_b.html | 2 +- docs/html/functions_func_c.html | 2 +- docs/html/functions_func_d.html | 10 +- docs/html/functions_func_e.html | 2 +- docs/html/functions_func_f.html | 2 +- docs/html/functions_func_g.html | 2 +- docs/html/functions_func_h.html | 2 +- docs/html/functions_func_i.html | 2 +- docs/html/functions_func_k.html | 2 +- docs/html/functions_func_l.html | 2 +- docs/html/functions_func_m.html | 2 +- docs/html/functions_func_n.html | 2 +- docs/html/functions_func_o.html | 2 +- docs/html/functions_func_p.html | 2 +- docs/html/functions_func_r.html | 12 +- docs/html/functions_func_s.html | 2 +- docs/html/functions_func_t.html | 4 +- docs/html/functions_func_y.html | 2 +- docs/html/functions_func_z.html | 2 +- docs/html/functions_g.html | 2 +- docs/html/functions_h.html | 2 +- docs/html/functions_i.html | 2 +- docs/html/functions_k.html | 23 +- docs/html/functions_l.html | 2 +- docs/html/functions_m.html | 11 +- docs/html/functions_n.html | 2 +- docs/html/functions_o.html | 2 +- docs/html/functions_p.html | 2 +- docs/html/functions_r.html | 12 +- docs/html/functions_rela.html | 2 +- docs/html/functions_s.html | 2 +- docs/html/functions_t.html | 4 +- docs/html/functions_type.html | 2 +- docs/html/functions_u.html | 2 +- docs/html/functions_vars.html | 32 +- docs/html/functions_y.html | 2 +- docs/html/functions_z.html | 2 +- docs/html/globals.html | 2 +- docs/html/globals_defs.html | 2 +- docs/html/graph_legend.html | 2 +- docs/html/hierarchy.html | 4 +- docs/html/index.html | 2 +- docs/html/inherit_graph_3.map | 2 +- docs/html/inherit_graph_3.md5 | 2 +- docs/html/inherits.html | 4 +- .../html/local__date__mutation_8h_source.html | 2 +- docs/html/logging_8h_source.html | 2 +- ...brian_src_AceTime_src_zoneinfo_README.html | 2 +- .../html/offset__date__time__mutation_8h.html | 2 +- ...ffset__date__time__mutation_8h_source.html | 2 +- docs/html/pages.html | 2 +- docs/html/search/all_10.js | 32 +- docs/html/search/all_11.js | 73 +- docs/html/search/all_12.js | 4 +- docs/html/search/all_13.js | 4 +- docs/html/search/all_14.js | 50 +- docs/html/search/all_3.js | 4 +- docs/html/search/all_9.js | 14 +- docs/html/search/all_a.js | 18 +- docs/html/search/all_b.js | 27 +- docs/html/search/all_c.js | 10 +- docs/html/search/all_d.js | 12 +- docs/html/search/all_e.js | 16 +- docs/html/search/all_f.js | 23 +- docs/html/search/classes_0.js | 16 +- docs/html/search/classes_1.js | 4 +- docs/html/search/classes_2.js | 18 +- docs/html/search/classes_3.js | 2 +- docs/html/search/classes_4.js | 6 +- docs/html/search/classes_5.js | 6 +- docs/html/search/classes_6.js | 2 +- docs/html/search/classes_7.js | 18 +- docs/html/search/classes_8.js | 2 +- docs/html/search/classes_9.js | 42 +- docs/html/search/defines_0.js | 2 +- docs/html/search/files_0.js | 4 +- docs/html/search/files_1.js | 4 +- docs/html/search/files_2.js | 2 +- docs/html/search/files_3.js | 4 +- docs/html/search/files_4.js | 2 +- docs/html/search/functions_0.js | 10 +- docs/html/search/functions_1.js | 6 +- docs/html/search/functions_10.js | 26 +- docs/html/search/functions_11.js | 42 +- docs/html/search/functions_12.js | 2 +- docs/html/search/functions_13.js | 18 +- docs/html/search/functions_2.js | 24 +- docs/html/search/functions_3.js | 18 +- docs/html/search/functions_4.js | 12 +- docs/html/search/functions_5.js | 66 +- docs/html/search/functions_6.js | 32 +- docs/html/search/functions_7.js | 2 +- docs/html/search/functions_8.js | 42 +- docs/html/search/functions_9.js | 2 +- docs/html/search/functions_a.js | 14 +- docs/html/search/functions_b.js | 8 +- docs/html/search/functions_c.js | 4 +- docs/html/search/functions_d.js | 4 +- docs/html/search/functions_e.js | 12 +- docs/html/search/functions_f.js | 17 +- docs/html/search/pages_0.js | 2 +- docs/html/search/pages_1.js | 2 +- docs/html/search/related_0.js | 2 +- docs/html/search/typedefs_0.js | 2 +- docs/html/search/typedefs_1.js | 2 +- docs/html/search/typedefs_2.js | 8 +- docs/html/search/typedefs_3.js | 10 +- docs/html/search/variables_0.js | 2 +- docs/html/search/variables_1.js | 4 +- docs/html/search/variables_10.js | 2 +- docs/html/search/variables_11.js | 2 +- docs/html/search/variables_2.js | 4 +- docs/html/search/variables_3.js | 2 +- docs/html/search/variables_4.js | 4 +- docs/html/search/variables_5.js | 2 +- docs/html/search/variables_6.js | 82 +- docs/html/search/variables_7.js | 8 +- docs/html/search/variables_8.js | 13 +- docs/html/search/variables_9.js | 6 +- docs/html/search/variables_a.js | 2 +- docs/html/search/variables_b.js | 4 +- docs/html/search/variables_c.js | 6 +- docs/html/search/variables_d.js | 8 +- docs/html/search/variables_e.js | 10 +- docs/html/search/variables_f.js | 4 +- ...ructace__time_1_1TimeZoneData-members.html | 2 +- .../html/structace__time_1_1TimeZoneData.html | 2 +- ..._1basic_1_1TransitionTemplate-members.html | 2 +- ...__time_1_1basic_1_1TransitionTemplate.html | 2 +- ...time_1_1extended_1_1DateTuple-members.html | 2 +- ...uctace__time_1_1extended_1_1DateTuple.html | 2 +- ...tended_1_1MatchingEraTemplate-members.html | 2 +- ...me_1_1extended_1_1MatchingEraTemplate.html | 2 +- ...TransitionForDateTimeTemplate-members.html | 2 +- ...nded_1_1TransitionForDateTimeTemplate.html | 2 +- ...1TransitionForSecondsTemplate-members.html | 2 +- ...ended_1_1TransitionForSecondsTemplate.html | 2 +- ...xtended_1_1TransitionTemplate-members.html | 2 +- ...ime_1_1extended_1_1TransitionTemplate.html | 2 +- ...1_1extended_1_1YearMonthTuple-members.html | 2 +- ...e__time_1_1extended_1_1YearMonthTuple.html | 2 +- ..._time_1_1internal_1_1MonthDay-members.html | 2 +- ...ructace__time_1_1internal_1_1MonthDay.html | 4 +- ...me_1_1internal_1_1ZoneContext-members.html | 2 +- ...tace__time_1_1internal_1_1ZoneContext.html | 2 +- docs/html/time__offset__mutation_8h.html | 2 +- .../time__offset__mutation_8h_source.html | 2 +- docs/html/time__period__mutation_8h.html | 2 +- .../time__period__mutation_8h_source.html | 2 +- .../tzonedb_2zone__infos_8cpp_source.html | 10 +- docs/html/tzonedb_2zone__infos_8h_source.html | 616 +- .../tzonedb_2zone__policies_8cpp_source.html | 8 +- .../tzonedb_2zone__policies_8h_source.html | 8 +- .../tzonedb_2zone__registry_8cpp_source.html | 8 +- .../tzonedb_2zone__registry_8h_source.html | 8 +- .../tzonedbx_2zone__infos_8cpp_source.html | 10 +- .../html/tzonedbx_2zone__infos_8h_source.html | 632 +- .../tzonedbx_2zone__policies_8cpp_source.html | 56 +- .../tzonedbx_2zone__policies_8h_source.html | 12 +- .../tzonedbx_2zone__registry_8cpp_source.html | 8 +- .../tzonedbx_2zone__registry_8h_source.html | 8 +- docs/html/zoned__date__time__mutation_8h.html | 2 +- ...zoned__date__time__mutation_8h_source.html | 2 +- .../html/zonedb_2zone__infos_8cpp_source.html | 9097 +++++---- docs/html/zonedb_2zone__infos_8h_source.html | 2053 +- .../zonedb_2zone__policies_8cpp_source.html | 26 +- .../zonedb_2zone__policies_8h_source.html | 55 +- .../zonedb_2zone__registry_8cpp_source.html | 1369 +- .../zonedb_2zone__registry_8h_source.html | 30 +- .../zonedbx_2zone__infos_8cpp_source.html | 16751 ++++++++-------- docs/html/zonedbx_2zone__infos_8h_source.html | 2421 ++- .../zonedbx_2zone__policies_8cpp_source.html | 9740 +++++---- .../zonedbx_2zone__policies_8h_source.html | 46 +- .../zonedbx_2zone__registry_8cpp_source.html | 1909 +- .../zonedbx_2zone__registry_8h_source.html | 36 +- 339 files changed, 25598 insertions(+), 24719 deletions(-) diff --git a/docs/html/AceTime_8h_source.html b/docs/html/AceTime_8h_source.html index 6de3ecbd0..aec64c872 100644 --- a/docs/html/AceTime_8h_source.html +++ b/docs/html/AceTime_8h_source.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
@@ -128,8 +128,8 @@
66 #include "zonedbx/zone_registry.h"
67 
68 // Version format: xxyyzz == "xx.yy.zz"
-
69 #define ACE_TIME_VERSION 20200
-
70 #define ACE_TIME_VERSION_STRING "2.2.0"
+
69 #define ACE_TIME_VERSION 20203
+
70 #define ACE_TIME_VERSION_STRING "2.2.3"
71 
72 #endif
Identifiers used by implementation code which need to be publically exported.
diff --git a/docs/html/BasicZoneProcessor_8h_source.html b/docs/html/BasicZoneProcessor_8h_source.html index 15c45fee1..525f2b694 100644 --- a/docs/html/BasicZoneProcessor_8h_source.html +++ b/docs/html/BasicZoneProcessor_8h_source.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
@@ -258,19 +258,19 @@
324  if (mZoneInfoBroker.equals(zoneKey)) return;
325 
326  mZoneInfoBroker = mBrokerFactory->createZoneInfoBroker(zoneKey);
-
327  mYear = LocalDate::kInvalidYear;
-
328  mIsFilled = false;
-
329  mNumTransitions = 0;
-
330  }
-
331 
-
332  bool equalsZoneKey(uintptr_t zoneKey) const override {
-
333  return mZoneInfoBroker.equals(zoneKey);
-
334  }
-
335 
-
337  void log() const {
-
338  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
-
339  logging::printf("BasicZoneProcessor:\n");
-
340  logging::printf(" mYear: %d\n", mYear);
+ +
328  mNumTransitions = 0;
+
329  }
+
330 
+
331  bool equalsZoneKey(uintptr_t zoneKey) const override {
+
332  return mZoneInfoBroker.equals(zoneKey);
+
333  }
+
334 
+
336  void log() const {
+
337  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
+
338  logging::printf("BasicZoneProcessor:\n");
+
339  logging::printf(" mEpochYear: %d\n", mEpochYear);
+
340  logging::printf(" mYear: %d\n", mYear);
341  logging::printf(" mNumTransitions: %d\n", mNumTransitions);
342  for (int i = 0; i < mNumTransitions; i++) {
343  logging::printf(" mT[%d]=", i);
@@ -337,431 +337,430 @@
464  ld.year(), year);
465  }
466 
-
467  mYear = year;
-
468  mNumTransitions = 0; // clear cache
-
469 
-
470  if (year < mZoneInfoBroker.zoneContext()->startYear - 1
-
471  || mZoneInfoBroker.zoneContext()->untilYear < year) {
-
472  return false;
-
473  }
-
474 
-
475  ZEB priorEra = addTransitionPriorToYear(year);
-
476  ZEB currentEra = addTransitionsForYear(year, priorEra);
-
477  addTransitionAfterYear(year, currentEra);
-
478  calcTransitions();
-
479  calcAbbreviations();
-
480 
-
481  mIsFilled = true;
-
482 
-
483  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
-
484  log();
-
485  }
-
486 
-
487  return true;
-
488  }
-
489 
-
495  bool initForEpochSeconds(acetime_t epochSeconds) const {
-
496  LocalDate ld = LocalDate::forEpochSeconds(epochSeconds);
-
497  return initForLocalDate(ld);
-
498  }
-
499 
-
506  ZEB addTransitionPriorToYear(int16_t year) const {
-
507  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
-
508  logging::printf("addTransitionPriorToYear(): %d\n", year);
-
509  }
-
510 
-
511  const ZEB era = findZoneEra(mZoneInfoBroker, year - 1);
-
512 
-
513  // If the prior ZoneEra has a ZonePolicy), then find the latest rule
-
514  // within the ZoneEra. Otherwise, add a Transition using a rule==nullptr.
-
515  ZRB latest = findLatestPriorRule(era.zonePolicy(), year);
-
516  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
-
517  logging::printf("addTransitionsPriorToYear(): adding latest prior ");
-
518  if (latest.isNull()) {
-
519  logging::printf("ZR(null)\n");
-
520  } else {
-
521  logging::printf("ZR[%d,%d]\n", latest.fromYear(), latest.toYear());
-
522  }
-
523  }
-
524  addTransition(year - 1, 0 /*month*/, era, latest);
-
525 
-
526  return era;
-
527  }
-
528 
-
534  static ZRB findLatestPriorRule(const ZPB& zonePolicy, int16_t year) {
-
535  ZRB latest;
-
536  if (zonePolicy.isNull()) return latest;
-
537 
-
538  uint8_t numRules = zonePolicy.numRules();
-
539  for (uint8_t i = 0; i < numRules; i++) {
-
540  const ZRB rule = zonePolicy.rule(i);
-
541  // Check if rule is effective prior to the given year
-
542  if (rule.fromYear() < year) {
-
543  if ((latest.isNull()) ||
-
544  compareRulesBeforeYear(year, rule, latest) > 0) {
-
545  latest = rule;
-
546  }
-
547  }
-
548  }
-
549 
-
550  return latest;
-
551  }
-
552 
-
554  static int8_t compareRulesBeforeYear(
-
555  int16_t year, const ZRB& a, const ZRB& b) {
-
556  return basic::compareYearMonth(
-
557  priorYearOfRule(year, a), a.inMonth(),
-
558  priorYearOfRule(year, b), b.inMonth());
-
559  }
-
560 
-
569  static int16_t priorYearOfRule(int16_t year, const ZRB& rule) {
-
570  if (rule.toYear() < year) {
-
571  return rule.toYear();
-
572  }
-
573  return year - 1;
-
574  }
-
575 
-
580  ZEB addTransitionsForYear(int16_t year, const ZEB& priorEra) const {
-
581  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
-
582  logging::printf("addTransitionsForYear(): %d\n", year);
-
583  }
-
584 
-
585  const ZEB era = findZoneEra(mZoneInfoBroker, year);
-
586 
-
587  // If the ZonePolicy has no rules, then add a Transition which takes
-
588  // effect at the start time of the current year.
-
589  const ZPB zonePolicy = era.zonePolicy();
-
590  if (zonePolicy.isNull()) {
-
591  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
-
592  logging::printf("addTransitionsForYear(): adding ZE.untilY=%d\n",
-
593  era.untilYear());
-
594  }
-
595  addTransition(year, 0 /*month*/, era, ZRB());
-
596  return era;
-
597  }
-
598 
-
599  if (! era.equals(priorEra)) {
-
600  // The ZoneEra has changed, so we need to find the Rule in effect at
-
601  // the start of the current year of the current ZoneEra. This may be a
-
602  // rule far in the past, but shift the rule forward to {year, 1, 1}.
-
603  ZRB latestPrior = findLatestPriorRule(era.zonePolicy(), year);
-
604  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
-
605  logging::printf(
-
606  "addTransitionsForYear(): adding latest prior ");
-
607  if (latestPrior.isNull()) {
-
608  logging::printf("ZR(null)\n");
-
609  } else {
-
610  logging::printf("ZR[%d,%d]\n",
-
611  latestPrior.fromYear(), latestPrior.toYear());
-
612  }
-
613  }
-
614  addTransition(year, 1 /*month*/, era, latestPrior);
-
615  }
-
616 
-
617  // Find all directly matching transitions (i.e. the [from, to] overlap
-
618  // with the current year) and add them to mTransitions, in sorted order
-
619  // according to the ZoneRule::inMonth field.
-
620  uint8_t numRules = zonePolicy.numRules();
-
621  for (uint8_t i = 0; i < numRules; i++) {
-
622  const ZRB rule = zonePolicy.rule(i);
-
623  if ((rule.fromYear() <= year) && (year <= rule.toYear())) {
-
624  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
-
625  logging::printf(
-
626  "addTransitionsForYear(): adding rule ");
-
627  if (rule.isNull()) {
-
628  logging::printf("ZR(null)\n");
-
629  } else {
-
630  logging::printf("ZR[%d,%d]\n", rule.fromYear(), rule.toYear());
-
631  }
-
632  }
-
633  addTransition(year, 0 /*month*/, era, rule);
-
634  }
-
635  }
-
636 
-
637  return era;
-
638  }
-
639 
-
641  void addTransitionAfterYear(int16_t year, const ZEB& currentEra) const {
-
642  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
-
643  logging::printf("addTransitionAfterYear(): %d\n", year);
-
644  }
-
645 
-
646  const ZEB eraAfter = findZoneEra(mZoneInfoBroker, year + 1);
-
647 
-
648  // If the current era is the same as the following year, then we'll just
-
649  // assume that the latest ZoneRule carries over to Jan 1st of the next
-
650  // year. tzcompiler.py guarantees no ZoneRule occurs on Jan 1st.
-
651  if (currentEra.equals(eraAfter)) {
-
652  return;
-
653  }
-
654 
-
655  // If the ZoneEra did change, find the latest transition prior to
-
656  // {year + 1, 1, 1}, then shift that Transition to Jan 1st of the
-
657  // following year.
-
658  ZRB latest = findLatestPriorRule(eraAfter.zonePolicy(), year + 1);
-
659  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
-
660  logging::printf(
-
661  "addTransitionsAfterYear(): adding latest prior ");
-
662  if (latest.isNull()) {
-
663  logging::printf("ZR(null)\n");
-
664  } else {
-
665  logging::printf("ZR[%d,%d]\n", latest.fromYear(), latest.toYear());
-
666  }
-
667  }
-
668  addTransition(year + 1, 1 /*month*/, eraAfter, latest);
-
669  }
-
670 
-
694  void addTransition(int16_t year, uint8_t month, const ZEB& era,
-
695  const ZRB& rule) const {
-
696 
-
697  // If a zone needs more transitions than kMaxCacheEntries, the check below
-
698  // will cause the DST transition information to be inaccurate, and it is
-
699  // highly likely that this situation would be caught in the
-
700  // AceTimeValidation tests. Since these integration tests pass, I feel
-
701  // confident that those zones which need more than kMaxCacheEntries are
-
702  // already filtered out by tzcompiler.py.
-
703  //
-
704  // Ideally, the tzcompiler.py script would explicitly remove those zones
-
705  // which need more than kMaxCacheEntries Transitions. But this would
-
706  // require a Python version of the BasicZoneProcessor, and unfortunately,
-
707  // zone_processor.py implements only the ExtendedZoneProcessor algorithm
-
708  // An early version of zone_processor.py may have implemented something
-
709  // close to BasicZoneProcessor, and it may be available in the git
-
710  // history. But it seems like too much work right now to try to dig that
-
711  // out, just to implement the explicit check for kMaxCacheEntries. It
-
712  // would mean maintaining another version of zone_processor.py.
-
713  if (mNumTransitions >= kMaxCacheEntries) return;
-
714 
-
715  // insert new element at the end of the list
-
716  mTransitions[mNumTransitions] = createTransition(year, month, era, rule);
-
717  mNumTransitions++;
-
718 
-
719  // perform an insertion sort based on ZoneRule.inMonth()
-
720  for (uint8_t i = mNumTransitions - 1; i > 0; i--) {
-
721  Transition& left = mTransitions[i - 1];
-
722  Transition& right = mTransitions[i];
-
723  // assume only 1 rule per month
-
724  if (basic::compareYearMonth(left.year, left.month,
-
725  right.year, right.month) > 0) {
-
726  Transition tmp = left;
-
727  left = right;
-
728  right = tmp;
-
729  }
-
730  }
-
731  }
-
732 
-
738  static Transition createTransition(int16_t year, uint8_t month,
-
739  const ZEB& era, const ZRB& rule) {
-
740 
-
741  int16_t deltaMinutes;
-
742  const char* letter;
-
743  uint8_t mon;
-
744  if (rule.isNull()) {
-
745  mon = 1; // RULES is either '-' or 'hh:mm' so takes effect in Jan
-
746  deltaMinutes = era.deltaMinutes();
-
747  letter = "";
-
748  } else {
-
749  mon = rule.inMonth();
-
750  deltaMinutes = rule.deltaMinutes();
-
751  letter = rule.letter();
-
752  }
-
753  // Clobber the month if specified.
-
754  if (month != 0) {
-
755  mon = month;
-
756  }
-
757  int16_t offsetMinutes = era.offsetMinutes() + deltaMinutes;
-
758 
-
759  return {
-
760  era,
-
761  rule,
-
762  0 /*epochSeconds*/,
-
763  offsetMinutes,
-
764  deltaMinutes,
-
765  year,
-
766  mon,
-
767  {letter[0]}, // only single letters are allowed in Basic
-
768  };
-
769  }
-
770 
-
776  static ZEB findZoneEra(const ZIB& info, int16_t year) {
-
777  for (uint8_t i = 0; i < info.numEras(); i++) {
-
778  const ZEB era = info.era(i);
-
779  if (year < era.untilYear()) return era;
-
780  }
-
781  // Return the last ZoneEra if we run off the end.
-
782  return info.era(info.numEras() - 1);
-
783  }
-
784 
-
792  void calcTransitions() const {
-
793  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
-
794  logging::printf("calcTransitions():\n");
-
795  }
-
796 
-
797  // Set the initial startEpochSeconds to be -Infinity
-
798  Transition* prevTransition = &mTransitions[0];
-
799  prevTransition->startEpochSeconds = kMinEpochSeconds;
-
800 
-
801  for (uint8_t i = 1; i < mNumTransitions; i++) {
-
802  Transition& transition = mTransitions[i];
-
803  const int16_t year = transition.year;
-
804 
-
805  if (transition.rule.isNull()) {
-
806  // If the transition is simple (has no named rule), then the
-
807  // ZoneEra applies for the entire year (since BasicZoneProcessor
-
808  // supports only whole year in the UNTIL field). The whole year UNTIL
-
809  // field has an implied 'w' suffix on 00:00, we don't need to call
-
810  // calcRuleOffsetMinutes() with a 'w', we can just use the previous
-
811  // transition's offset to calculate the startDateTime of this
-
812  // transition.
-
813  //
-
814  // Also, when transition.rule == nullptr, the mNumTransitions should
-
815  // be 1, since only a single transition is added by
-
816  // addTransitionsForYear().
-
817  const int16_t prevOffsetMinutes = prevTransition->offsetMinutes;
-
818  OffsetDateTime startDateTime = OffsetDateTime::forComponents(
-
819  year, 1, 1, 0, 0, 0,
-
820  TimeOffset::forMinutes(prevOffsetMinutes));
-
821  transition.startEpochSeconds = startDateTime.toEpochSeconds();
-
822  } else {
-
823  // In this case, the transition points to a named ZonePolicy, which
-
824  // means that there could be multiple ZoneRules associated with the
-
825  // given year. For each transition, determine the startEpochSeconds,
-
826  // and the effective offset code.
-
827 
-
828  // Determine the start date of the rule.
-
829  const internal::MonthDay monthDay = internal::calcStartDayOfMonth(
-
830  year, transition.month, transition.rule.onDayOfWeek(),
-
831  transition.rule.onDayOfMonth());
-
832 
-
833  // Determine the offset of the 'atTimeSuffix'. The 'w' suffix
-
834  // requires the offset of the previous transition.
-
835  const int16_t prevOffsetMinutes = calcRuleOffsetMinutes(
-
836  prevTransition->offsetMinutes,
-
837  transition.era.offsetMinutes(),
-
838  transition.rule.atTimeSuffix());
-
839 
-
840  // startDateTime
-
841  const uint16_t minutes = transition.rule.atTimeMinutes();
-
842  const uint8_t atHour = minutes / 60;
-
843  const uint8_t atMinute = minutes % 60;
-
844  OffsetDateTime startDateTime = OffsetDateTime::forComponents(
-
845  year, monthDay.month, monthDay.day,
-
846  atHour, atMinute, 0 /*second*/,
-
847  TimeOffset::forMinutes(prevOffsetMinutes));
-
848  transition.startEpochSeconds = startDateTime.toEpochSeconds();
-
849  }
-
850 
-
851  prevTransition = &transition;
-
852  }
-
853  }
-
854 
-
861  static int16_t calcRuleOffsetMinutes(int16_t prevEffectiveOffsetMinutes,
-
862  int16_t currentBaseOffsetMinutes, uint8_t atSuffix) {
-
863  if (atSuffix == internal::ZoneContext::kSuffixW) {
-
864  return prevEffectiveOffsetMinutes;
-
865  } else if (atSuffix == internal::ZoneContext::kSuffixS) {
-
866  return currentBaseOffsetMinutes;
-
867  } else { // 'u', 'g' or 'z'
-
868  return 0;
-
869  }
-
870  }
-
871 
-
873  void calcAbbreviations() const {
-
874  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
-
875  logging::printf("calcAbbreviations():\n");
-
876  }
-
877 
-
878  for (uint8_t i = 0; i < mNumTransitions; i++) {
-
879  calcAbbreviation(&mTransitions[i]);
-
880  }
-
881  }
-
882 
-
884  static void calcAbbreviation(Transition* transition) {
-
885  createAbbreviation(
-
886  transition->abbrev,
-
887  internal::kAbbrevSize,
-
888  transition->era.format(),
-
889  transition->deltaMinutes,
-
890  transition->abbrev[0]);
-
891  }
-
892 
-
935  static void createAbbreviation(char* dest, uint8_t destSize,
-
936  const char* format, int16_t deltaMinutes, char letter) {
-
937  // Check if FORMAT contains a '%'.
-
938  if (strchr(format, '%') != nullptr) {
-
939  ace_common::copyReplaceChar(dest, destSize, format, '%', letter);
-
940  } else {
-
941  // Check if FORMAT contains a '/'.
-
942  const char* slashPos = strchr(format, '/');
-
943  if (slashPos != nullptr) {
-
944  if (deltaMinutes == 0) {
-
945  uint8_t headLength = (slashPos - format);
-
946  if (headLength >= destSize) headLength = destSize - 1;
-
947  memcpy(dest, format, headLength);
-
948  dest[headLength] = '\0';
-
949  } else {
-
950  uint8_t tailLength = strlen(slashPos+1);
-
951  if (tailLength >= destSize) tailLength = destSize - 1;
-
952  memcpy(dest, slashPos+1, tailLength);
-
953  dest[tailLength] = '\0';
-
954  }
-
955  } else {
-
956  // Just copy the FORMAT disregarding the deltaMinutes and letter.
-
957  strncpy(dest, format, destSize - 1);
-
958  dest[destSize - 1] = '\0';
-
959  }
-
960  }
-
961  }
-
962 
-
964  const Transition* findMatch(acetime_t epochSeconds) const {
-
965  const Transition* closestMatch = nullptr;
-
966  for (uint8_t i = 0; i < mNumTransitions; i++) {
-
967  const Transition* m = &mTransitions[i];
-
968  if (closestMatch == nullptr || m->startEpochSeconds <= epochSeconds) {
-
969  closestMatch = m;
-
970  }
-
971  }
-
972  return closestMatch;
-
973  }
-
974 
-
975  const BF* mBrokerFactory; // nullable
-
976  ZIB mZoneInfoBroker;
-
977 
-
978  mutable uint8_t mNumTransitions = 0;
-
979  mutable Transition mTransitions[kMaxCacheEntries];
-
980 };
-
981 
- -
987  basic::BrokerFactory,
-
988  basic::ZoneInfoBroker,
-
989  basic::ZoneEraBroker,
-
990  basic::ZonePolicyBroker,
-
991  basic::ZoneRuleBroker> {
-
992 
-
993  public:
-
995  static const uint8_t kTypeBasic = 3;
-
996 
-
997  explicit BasicZoneProcessor(const basic::ZoneInfo* zoneInfo = nullptr)
- -
999  basic::BrokerFactory,
-
1000  basic::ZoneInfoBroker,
-
1001  basic::ZoneEraBroker,
-
1002  basic::ZonePolicyBroker,
-
1003  basic::ZoneRuleBroker>(
-
1004  kTypeBasic, &mBrokerFactory, (uintptr_t) zoneInfo)
-
1005  {}
-
1006 
-
1007  private:
-
1008  basic::BrokerFactory mBrokerFactory;
-
1009 };
-
1010 
-
1011 } // namespace ace_time
-
1012 
-
1013 #endif
+
467  mYear = year;
+ +
469  mNumTransitions = 0; // clear cache
+
470 
+
471  if (year < mZoneInfoBroker.zoneContext()->startYear - 1
+
472  || mZoneInfoBroker.zoneContext()->untilYear < year) {
+
473  return false;
+
474  }
+
475 
+
476  ZEB priorEra = addTransitionPriorToYear(year);
+
477  ZEB currentEra = addTransitionsForYear(year, priorEra);
+
478  addTransitionAfterYear(year, currentEra);
+
479  calcTransitions();
+
480  calcAbbreviations();
+
481 
+
482  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
+
483  log();
+
484  }
+
485 
+
486  return true;
+
487  }
+
488 
+
494  bool initForEpochSeconds(acetime_t epochSeconds) const {
+
495  LocalDate ld = LocalDate::forEpochSeconds(epochSeconds);
+
496  return initForLocalDate(ld);
+
497  }
+
498 
+
505  ZEB addTransitionPriorToYear(int16_t year) const {
+
506  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
+
507  logging::printf("addTransitionPriorToYear(): %d\n", year);
+
508  }
+
509 
+
510  const ZEB era = findZoneEra(mZoneInfoBroker, year - 1);
+
511 
+
512  // If the prior ZoneEra has a ZonePolicy), then find the latest rule
+
513  // within the ZoneEra. Otherwise, add a Transition using a rule==nullptr.
+
514  ZRB latest = findLatestPriorRule(era.zonePolicy(), year);
+
515  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
+
516  logging::printf("addTransitionsPriorToYear(): adding latest prior ");
+
517  if (latest.isNull()) {
+
518  logging::printf("ZR(null)\n");
+
519  } else {
+
520  logging::printf("ZR[%d,%d]\n", latest.fromYear(), latest.toYear());
+
521  }
+
522  }
+
523  addTransition(year - 1, 0 /*month*/, era, latest);
+
524 
+
525  return era;
+
526  }
+
527 
+
533  static ZRB findLatestPriorRule(const ZPB& zonePolicy, int16_t year) {
+
534  ZRB latest;
+
535  if (zonePolicy.isNull()) return latest;
+
536 
+
537  uint8_t numRules = zonePolicy.numRules();
+
538  for (uint8_t i = 0; i < numRules; i++) {
+
539  const ZRB rule = zonePolicy.rule(i);
+
540  // Check if rule is effective prior to the given year
+
541  if (rule.fromYear() < year) {
+
542  if ((latest.isNull()) ||
+
543  compareRulesBeforeYear(year, rule, latest) > 0) {
+
544  latest = rule;
+
545  }
+
546  }
+
547  }
+
548 
+
549  return latest;
+
550  }
+
551 
+
553  static int8_t compareRulesBeforeYear(
+
554  int16_t year, const ZRB& a, const ZRB& b) {
+
555  return basic::compareYearMonth(
+
556  priorYearOfRule(year, a), a.inMonth(),
+
557  priorYearOfRule(year, b), b.inMonth());
+
558  }
+
559 
+
568  static int16_t priorYearOfRule(int16_t year, const ZRB& rule) {
+
569  if (rule.toYear() < year) {
+
570  return rule.toYear();
+
571  }
+
572  return year - 1;
+
573  }
+
574 
+
579  ZEB addTransitionsForYear(int16_t year, const ZEB& priorEra) const {
+
580  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
+
581  logging::printf("addTransitionsForYear(): %d\n", year);
+
582  }
+
583 
+
584  const ZEB era = findZoneEra(mZoneInfoBroker, year);
+
585 
+
586  // If the ZonePolicy has no rules, then add a Transition which takes
+
587  // effect at the start time of the current year.
+
588  const ZPB zonePolicy = era.zonePolicy();
+
589  if (zonePolicy.isNull()) {
+
590  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
+
591  logging::printf("addTransitionsForYear(): adding ZE.untilY=%d\n",
+
592  era.untilYear());
+
593  }
+
594  addTransition(year, 0 /*month*/, era, ZRB());
+
595  return era;
+
596  }
+
597 
+
598  if (! era.equals(priorEra)) {
+
599  // The ZoneEra has changed, so we need to find the Rule in effect at
+
600  // the start of the current year of the current ZoneEra. This may be a
+
601  // rule far in the past, but shift the rule forward to {year, 1, 1}.
+
602  ZRB latestPrior = findLatestPriorRule(era.zonePolicy(), year);
+
603  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
+
604  logging::printf(
+
605  "addTransitionsForYear(): adding latest prior ");
+
606  if (latestPrior.isNull()) {
+
607  logging::printf("ZR(null)\n");
+
608  } else {
+
609  logging::printf("ZR[%d,%d]\n",
+
610  latestPrior.fromYear(), latestPrior.toYear());
+
611  }
+
612  }
+
613  addTransition(year, 1 /*month*/, era, latestPrior);
+
614  }
+
615 
+
616  // Find all directly matching transitions (i.e. the [from, to] overlap
+
617  // with the current year) and add them to mTransitions, in sorted order
+
618  // according to the ZoneRule::inMonth field.
+
619  uint8_t numRules = zonePolicy.numRules();
+
620  for (uint8_t i = 0; i < numRules; i++) {
+
621  const ZRB rule = zonePolicy.rule(i);
+
622  if ((rule.fromYear() <= year) && (year <= rule.toYear())) {
+
623  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
+
624  logging::printf(
+
625  "addTransitionsForYear(): adding rule ");
+
626  if (rule.isNull()) {
+
627  logging::printf("ZR(null)\n");
+
628  } else {
+
629  logging::printf("ZR[%d,%d]\n", rule.fromYear(), rule.toYear());
+
630  }
+
631  }
+
632  addTransition(year, 0 /*month*/, era, rule);
+
633  }
+
634  }
+
635 
+
636  return era;
+
637  }
+
638 
+
640  void addTransitionAfterYear(int16_t year, const ZEB& currentEra) const {
+
641  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
+
642  logging::printf("addTransitionAfterYear(): %d\n", year);
+
643  }
+
644 
+
645  const ZEB eraAfter = findZoneEra(mZoneInfoBroker, year + 1);
+
646 
+
647  // If the current era is the same as the following year, then we'll just
+
648  // assume that the latest ZoneRule carries over to Jan 1st of the next
+
649  // year. tzcompiler.py guarantees no ZoneRule occurs on Jan 1st.
+
650  if (currentEra.equals(eraAfter)) {
+
651  return;
+
652  }
+
653 
+
654  // If the ZoneEra did change, find the latest transition prior to
+
655  // {year + 1, 1, 1}, then shift that Transition to Jan 1st of the
+
656  // following year.
+
657  ZRB latest = findLatestPriorRule(eraAfter.zonePolicy(), year + 1);
+
658  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
+
659  logging::printf(
+
660  "addTransitionsAfterYear(): adding latest prior ");
+
661  if (latest.isNull()) {
+
662  logging::printf("ZR(null)\n");
+
663  } else {
+
664  logging::printf("ZR[%d,%d]\n", latest.fromYear(), latest.toYear());
+
665  }
+
666  }
+
667  addTransition(year + 1, 1 /*month*/, eraAfter, latest);
+
668  }
+
669 
+
693  void addTransition(int16_t year, uint8_t month, const ZEB& era,
+
694  const ZRB& rule) const {
+
695 
+
696  // If a zone needs more transitions than kMaxCacheEntries, the check below
+
697  // will cause the DST transition information to be inaccurate, and it is
+
698  // highly likely that this situation would be caught in the
+
699  // AceTimeValidation tests. Since these integration tests pass, I feel
+
700  // confident that those zones which need more than kMaxCacheEntries are
+
701  // already filtered out by tzcompiler.py.
+
702  //
+
703  // Ideally, the tzcompiler.py script would explicitly remove those zones
+
704  // which need more than kMaxCacheEntries Transitions. But this would
+
705  // require a Python version of the BasicZoneProcessor, and unfortunately,
+
706  // zone_processor.py implements only the ExtendedZoneProcessor algorithm
+
707  // An early version of zone_processor.py may have implemented something
+
708  // close to BasicZoneProcessor, and it may be available in the git
+
709  // history. But it seems like too much work right now to try to dig that
+
710  // out, just to implement the explicit check for kMaxCacheEntries. It
+
711  // would mean maintaining another version of zone_processor.py.
+
712  if (mNumTransitions >= kMaxCacheEntries) return;
+
713 
+
714  // insert new element at the end of the list
+
715  mTransitions[mNumTransitions] = createTransition(year, month, era, rule);
+
716  mNumTransitions++;
+
717 
+
718  // perform an insertion sort based on ZoneRule.inMonth()
+
719  for (uint8_t i = mNumTransitions - 1; i > 0; i--) {
+
720  Transition& left = mTransitions[i - 1];
+
721  Transition& right = mTransitions[i];
+
722  // assume only 1 rule per month
+
723  if (basic::compareYearMonth(left.year, left.month,
+
724  right.year, right.month) > 0) {
+
725  Transition tmp = left;
+
726  left = right;
+
727  right = tmp;
+
728  }
+
729  }
+
730  }
+
731 
+
737  static Transition createTransition(int16_t year, uint8_t month,
+
738  const ZEB& era, const ZRB& rule) {
+
739 
+
740  int16_t deltaMinutes;
+
741  const char* letter;
+
742  uint8_t mon;
+
743  if (rule.isNull()) {
+
744  mon = 1; // RULES is either '-' or 'hh:mm' so takes effect in Jan
+
745  deltaMinutes = era.deltaMinutes();
+
746  letter = "";
+
747  } else {
+
748  mon = rule.inMonth();
+
749  deltaMinutes = rule.deltaMinutes();
+
750  letter = rule.letter();
+
751  }
+
752  // Clobber the month if specified.
+
753  if (month != 0) {
+
754  mon = month;
+
755  }
+
756  int16_t offsetMinutes = era.offsetMinutes() + deltaMinutes;
+
757 
+
758  return {
+
759  era,
+
760  rule,
+
761  0 /*epochSeconds*/,
+
762  offsetMinutes,
+
763  deltaMinutes,
+
764  year,
+
765  mon,
+
766  {letter[0]}, // only single letters are allowed in Basic
+
767  };
+
768  }
+
769 
+
775  static ZEB findZoneEra(const ZIB& info, int16_t year) {
+
776  for (uint8_t i = 0; i < info.numEras(); i++) {
+
777  const ZEB era = info.era(i);
+
778  if (year < era.untilYear()) return era;
+
779  }
+
780  // Return the last ZoneEra if we run off the end.
+
781  return info.era(info.numEras() - 1);
+
782  }
+
783 
+
791  void calcTransitions() const {
+
792  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
+
793  logging::printf("calcTransitions():\n");
+
794  }
+
795 
+
796  // Set the initial startEpochSeconds to be -Infinity
+
797  Transition* prevTransition = &mTransitions[0];
+
798  prevTransition->startEpochSeconds = kMinEpochSeconds;
+
799 
+
800  for (uint8_t i = 1; i < mNumTransitions; i++) {
+
801  Transition& transition = mTransitions[i];
+
802  const int16_t year = transition.year;
+
803 
+
804  if (transition.rule.isNull()) {
+
805  // If the transition is simple (has no named rule), then the
+
806  // ZoneEra applies for the entire year (since BasicZoneProcessor
+
807  // supports only whole year in the UNTIL field). The whole year UNTIL
+
808  // field has an implied 'w' suffix on 00:00, we don't need to call
+
809  // calcRuleOffsetMinutes() with a 'w', we can just use the previous
+
810  // transition's offset to calculate the startDateTime of this
+
811  // transition.
+
812  //
+
813  // Also, when transition.rule == nullptr, the mNumTransitions should
+
814  // be 1, since only a single transition is added by
+
815  // addTransitionsForYear().
+
816  const int16_t prevOffsetMinutes = prevTransition->offsetMinutes;
+
817  OffsetDateTime startDateTime = OffsetDateTime::forComponents(
+
818  year, 1, 1, 0, 0, 0,
+
819  TimeOffset::forMinutes(prevOffsetMinutes));
+
820  transition.startEpochSeconds = startDateTime.toEpochSeconds();
+
821  } else {
+
822  // In this case, the transition points to a named ZonePolicy, which
+
823  // means that there could be multiple ZoneRules associated with the
+
824  // given year. For each transition, determine the startEpochSeconds,
+
825  // and the effective offset code.
+
826 
+
827  // Determine the start date of the rule.
+
828  const internal::MonthDay monthDay = internal::calcStartDayOfMonth(
+
829  year, transition.month, transition.rule.onDayOfWeek(),
+
830  transition.rule.onDayOfMonth());
+
831 
+
832  // Determine the offset of the 'atTimeSuffix'. The 'w' suffix
+
833  // requires the offset of the previous transition.
+
834  const int16_t prevOffsetMinutes = calcRuleOffsetMinutes(
+
835  prevTransition->offsetMinutes,
+
836  transition.era.offsetMinutes(),
+
837  transition.rule.atTimeSuffix());
+
838 
+
839  // startDateTime
+
840  const uint16_t minutes = transition.rule.atTimeMinutes();
+
841  const uint8_t atHour = minutes / 60;
+
842  const uint8_t atMinute = minutes % 60;
+
843  OffsetDateTime startDateTime = OffsetDateTime::forComponents(
+
844  year, monthDay.month, monthDay.day,
+
845  atHour, atMinute, 0 /*second*/,
+
846  TimeOffset::forMinutes(prevOffsetMinutes));
+
847  transition.startEpochSeconds = startDateTime.toEpochSeconds();
+
848  }
+
849 
+
850  prevTransition = &transition;
+
851  }
+
852  }
+
853 
+
860  static int16_t calcRuleOffsetMinutes(int16_t prevEffectiveOffsetMinutes,
+
861  int16_t currentBaseOffsetMinutes, uint8_t atSuffix) {
+
862  if (atSuffix == internal::ZoneContext::kSuffixW) {
+
863  return prevEffectiveOffsetMinutes;
+
864  } else if (atSuffix == internal::ZoneContext::kSuffixS) {
+
865  return currentBaseOffsetMinutes;
+
866  } else { // 'u', 'g' or 'z'
+
867  return 0;
+
868  }
+
869  }
+
870 
+
872  void calcAbbreviations() const {
+
873  if (ACE_TIME_BASIC_ZONE_PROCESSOR_DEBUG) {
+
874  logging::printf("calcAbbreviations():\n");
+
875  }
+
876 
+
877  for (uint8_t i = 0; i < mNumTransitions; i++) {
+
878  calcAbbreviation(&mTransitions[i]);
+
879  }
+
880  }
+
881 
+
883  static void calcAbbreviation(Transition* transition) {
+
884  createAbbreviation(
+
885  transition->abbrev,
+
886  internal::kAbbrevSize,
+
887  transition->era.format(),
+
888  transition->deltaMinutes,
+
889  transition->abbrev[0]);
+
890  }
+
891 
+
934  static void createAbbreviation(char* dest, uint8_t destSize,
+
935  const char* format, int16_t deltaMinutes, char letter) {
+
936  // Check if FORMAT contains a '%'.
+
937  if (strchr(format, '%') != nullptr) {
+
938  ace_common::copyReplaceChar(dest, destSize, format, '%', letter);
+
939  } else {
+
940  // Check if FORMAT contains a '/'.
+
941  const char* slashPos = strchr(format, '/');
+
942  if (slashPos != nullptr) {
+
943  if (deltaMinutes == 0) {
+
944  uint8_t headLength = (slashPos - format);
+
945  if (headLength >= destSize) headLength = destSize - 1;
+
946  memcpy(dest, format, headLength);
+
947  dest[headLength] = '\0';
+
948  } else {
+
949  uint8_t tailLength = strlen(slashPos+1);
+
950  if (tailLength >= destSize) tailLength = destSize - 1;
+
951  memcpy(dest, slashPos+1, tailLength);
+
952  dest[tailLength] = '\0';
+
953  }
+
954  } else {
+
955  // Just copy the FORMAT disregarding the deltaMinutes and letter.
+
956  strncpy(dest, format, destSize - 1);
+
957  dest[destSize - 1] = '\0';
+
958  }
+
959  }
+
960  }
+
961 
+
963  const Transition* findMatch(acetime_t epochSeconds) const {
+
964  const Transition* closestMatch = nullptr;
+
965  for (uint8_t i = 0; i < mNumTransitions; i++) {
+
966  const Transition* m = &mTransitions[i];
+
967  if (closestMatch == nullptr || m->startEpochSeconds <= epochSeconds) {
+
968  closestMatch = m;
+
969  }
+
970  }
+
971  return closestMatch;
+
972  }
+
973 
+
974  const BF* mBrokerFactory; // nullable
+
975  ZIB mZoneInfoBroker;
+
976 
+
977  mutable uint8_t mNumTransitions = 0;
+
978  mutable Transition mTransitions[kMaxCacheEntries];
+
979 };
+
980 
+ +
986  basic::BrokerFactory,
+
987  basic::ZoneInfoBroker,
+
988  basic::ZoneEraBroker,
+
989  basic::ZonePolicyBroker,
+
990  basic::ZoneRuleBroker> {
+
991 
+
992  public:
+
994  static const uint8_t kTypeBasic = 3;
+
995 
+
996  explicit BasicZoneProcessor(const basic::ZoneInfo* zoneInfo = nullptr)
+ +
998  basic::BrokerFactory,
+
999  basic::ZoneInfoBroker,
+
1000  basic::ZoneEraBroker,
+
1001  basic::ZonePolicyBroker,
+
1002  basic::ZoneRuleBroker>(
+
1003  kTypeBasic, &mBrokerFactory, (uintptr_t) zoneInfo)
+
1004  {}
+
1005 
+
1006  private:
+
1007  basic::BrokerFactory mBrokerFactory;
+
1008 };
+
1009 
+
1010 } // namespace ace_time
+
1011 
+
1012 #endif
An implementation of ZoneProcessor that supports a subset of the zones containing in the TZ Database.
void setBrokerFactory(const BF *brokerFactory)
Set the broker factory at runtime.
uint32_t getZoneId() const override
Return the unique stable zoneId.
-
bool equalsZoneKey(uintptr_t zoneKey) const override
Return true if ZoneProcessor is associated with the given opaque zoneKey.
+
bool equalsZoneKey(uintptr_t zoneKey) const override
Return true if ZoneProcessor is associated with the given opaque zoneKey.
bool isLink() const override
Return true if timezone is a Link entry pointing to a Zone entry.
void printTargetNameTo(Print &printer) const override
Print the full identifier (e.g.
FindResult findByEpochSeconds(acetime_t epochSeconds) const override
Return the search results at given epochSeconds.
@@ -771,9 +770,10 @@
BasicZoneProcessorTemplate(uint8_t type, const BF *brokerFactory, uintptr_t zoneKey)
Constructor.
FindResult findByLocalDateTime(const LocalDateTime &ldt) const override
Return the search results at given LocalDateTime.
basic::TransitionTemplate< ZIB, ZEB, ZPB, ZRB > Transition
Exposed only for testing purposes.
-
void log() const
Used only for debugging.
-
A specific implementation of BasicZoneProcessorTemplate that uses ZoneXxxBrokers which read from zone...
-
static const uint8_t kTypeBasic
Unique TimeZone type identifier for BasicZoneProcessor.
+
void log() const
Used only for debugging.
+
A specific implementation of BasicZoneProcessorTemplate that uses ZoneXxxBrokers which read from zone...
+
static const uint8_t kTypeBasic
Unique TimeZone type identifier for BasicZoneProcessor.
+
static int16_t currentEpochYear()
Get the current epoch year.
Definition: Epoch.h:27
Result of a search for transition at a specific epochSeconds or a specific LocalDateTime.
Definition: ZoneProcessor.h:24
int16_t dstOffsetMinutes
DST offset of the resulting OffsetDateTime.
Definition: ZoneProcessor.h:83
int16_t reqStdOffsetMinutes
STD offset of the Transition which matched the epochSeconds requested by findByEpochSeconds(),...
Definition: ZoneProcessor.h:96
@@ -790,7 +790,9 @@
static OffsetDateTime forComponents(int16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, TimeOffset timeOffset, uint8_t fold=0)
Factory method using separated date, time, and UTC offset fields.
static TimeOffset forMinutes(int16_t minutes)
Create TimeOffset from minutes from 00:00.
Definition: TimeOffset.h:83
Base interface for ZoneProcessor classes.
-
bool isFilled(int16_t year) const
Check if the Transition cache is filled for the given year.
+
int16_t mYear
Year that was used to calculate the transitions in the current cache.
+
bool isFilled(int16_t year) const
Check if the Transition cache is filled for the given year and current epochYear.
+
int16_t mEpochYear
Epoch year that was used to calculate the transitions in the current cache.
Identifiers used by implementation code which need to be publically exported.
int32_t acetime_t
Type for the number of seconds from epoch.
Definition: common.h:24
diff --git a/docs/html/BasicZone_8cpp_source.html b/docs/html/BasicZone_8cpp_source.html index cbfd6980d..2cddc3ab8 100644 --- a/docs/html/BasicZone_8cpp_source.html +++ b/docs/html/BasicZone_8cpp_source.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
diff --git a/docs/html/BasicZone_8h_source.html b/docs/html/BasicZone_8h_source.html index 9861ba730..0f4916256 100644 --- a/docs/html/BasicZone_8h_source.html +++ b/docs/html/BasicZone_8h_source.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
diff --git a/docs/html/BrokerCommon_8cpp_source.html b/docs/html/BrokerCommon_8cpp_source.html index 1140b0868..68481cc70 100644 --- a/docs/html/BrokerCommon_8cpp_source.html +++ b/docs/html/BrokerCommon_8cpp_source.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
diff --git a/docs/html/BrokerCommon_8h.html b/docs/html/BrokerCommon_8h.html index 34fc23872..3690c6994 100644 --- a/docs/html/BrokerCommon_8h.html +++ b/docs/html/BrokerCommon_8h.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
diff --git a/docs/html/BrokerCommon_8h_source.html b/docs/html/BrokerCommon_8h_source.html index 01a7519a3..e5b5537a3 100644 --- a/docs/html/BrokerCommon_8h_source.html +++ b/docs/html/BrokerCommon_8h_source.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
diff --git a/docs/html/Brokers_8h.html b/docs/html/Brokers_8h.html index a00af6d0d..af9549087 100644 --- a/docs/html/Brokers_8h.html +++ b/docs/html/Brokers_8h.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
diff --git a/docs/html/Brokers_8h_source.html b/docs/html/Brokers_8h_source.html index 4f0c17244..4e9eaf24f 100644 --- a/docs/html/Brokers_8h_source.html +++ b/docs/html/Brokers_8h_source.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
diff --git a/docs/html/DateStrings_8cpp_source.html b/docs/html/DateStrings_8cpp_source.html index 0d72e02e7..29b7962f1 100644 --- a/docs/html/DateStrings_8cpp_source.html +++ b/docs/html/DateStrings_8cpp_source.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
diff --git a/docs/html/DateStrings_8h_source.html b/docs/html/DateStrings_8h_source.html index 5df17afad..a36c1e064 100644 --- a/docs/html/DateStrings_8h_source.html +++ b/docs/html/DateStrings_8h_source.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
diff --git a/docs/html/DateTuple_8h_source.html b/docs/html/DateTuple_8h_source.html index b5a0760be..c0980ca1f 100644 --- a/docs/html/DateTuple_8h_source.html +++ b/docs/html/DateTuple_8h_source.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
diff --git a/docs/html/EpochConverterHinnant_8h_source.html b/docs/html/EpochConverterHinnant_8h_source.html index e9f6d8a6f..c7889f268 100644 --- a/docs/html/EpochConverterHinnant_8h_source.html +++ b/docs/html/EpochConverterHinnant_8h_source.html @@ -22,7 +22,7 @@
AceTime -  2.2.0 +  2.2.3
Date and time classes for Arduino that support timezones from the TZ Database.
@@ -86,62 +86,62 @@
13 
20  public:
-
25  static const int16_t kConverterEpochYear = 2000;
+
25  static const int16_t kInternalEpochYear = 2000;
26 
-
31  static const int32_t kDaysToConverterEpochFromUnixEpoch = 10957;
+
31  static const int32_t kDaysToInternalEpochFromUnixEpoch = 10957;
32 
-
49  static int32_t toEpochDays(int16_t year, uint8_t month, uint8_t day) {
-
50  uint16_t yearPrime = year - ((month <= 2) ? 1 : 0);
-
51  uint16_t era = yearPrime / 400; // [0,24]
-
52  uint16_t yearOfEra = yearPrime - 400 * era; // [0,399]
-
53 
-
54  uint8_t monthPrime = (month <= 2) ? month + 9 : month - 3; // [0,11]
-
55  uint16_t daysUntilMonthPrime = toDaysUntilMonthPrime(monthPrime);
-
56  uint16_t dayOfYearPrime = daysUntilMonthPrime + day - 1; // [0,365]
-
57  uint32_t dayOfEra = (uint32_t) 365 * yearOfEra + (yearOfEra / 4)
-
58  - (yearOfEra / 100) + dayOfYearPrime; // [0, 146096]
-
59 
-
60  int32_t dayOfEpochPrime = dayOfEra + 146097 * era;
-
61  return dayOfEpochPrime
-
62  - (kConverterEpochYear / 400) * 146097 /*relative to 2000-03-01*/
-
63  + 60 /*relative to 2000-01-01, 2000 is a leap year*/;
-
64  }
-
65 
-
77  static void fromEpochDays(int32_t epochDays,
-
78  int16_t& year, uint8_t& month, uint8_t& day) {
-
79 
-
80  int32_t dayOfEpochPrime = epochDays
-
81  + (kConverterEpochYear / 400) * 146097 - 60;
-
82  uint16_t era = (uint32_t) dayOfEpochPrime / 146097; // [0,24]
-
83  uint32_t dayOfEra = dayOfEpochPrime - 146097 * era; // [0,146096]
-
84  uint16_t yearOfEra = (dayOfEra - dayOfEra / 1460 + dayOfEra / 36524
-
85  - dayOfEra / 146096) / 365; // [0,399]
-
86  uint16_t yearPrime = yearOfEra + 400 * era; // [0,9999]
-
87  uint16_t dayOfYearPrime = dayOfEra - (365 * yearOfEra + yearOfEra/4
-
88  - yearOfEra/100);
-
89  uint8_t monthPrime = (5 * dayOfYearPrime + 2) / 153;
-
90  uint16_t daysUntilMonthPrime = toDaysUntilMonthPrime(monthPrime);
-
91 
-
92  day = dayOfYearPrime - daysUntilMonthPrime + 1; // [1,31]
-
93  month = (monthPrime < 10) ? monthPrime + 3 : monthPrime - 9; // [1,12]
-
94  year = yearPrime + ((month <= 2) ? 1 : 0); // [1,9999]
-
95  }
-
96 
-
101  static uint16_t toDaysUntilMonthPrime(uint8_t monthPrime) {
-
102  return (153 * monthPrime + 2) / 5;
-
103  }
-
104 };
-
105 
+
48  static int32_t toEpochDays(int16_t year, uint8_t month, uint8_t day) {
+
49  uint16_t yearPrime = year - ((month <= 2) ? 1 : 0);
+
50  uint16_t era = yearPrime / 400; // [0,24]
+
51  uint16_t yearOfEra = yearPrime - 400 * era; // [0,399]
+
52 
+
53  uint8_t monthPrime = (month <= 2) ? month + 9 : month - 3; // [0,11]
+
54  uint16_t daysUntilMonthPrime = toDaysUntilMonthPrime(monthPrime);
+
55  uint16_t dayOfYearPrime = daysUntilMonthPrime + day - 1; // [0,365]
+
56  uint32_t dayOfEra = (uint32_t) 365 * yearOfEra + (yearOfEra / 4)
+
57  - (yearOfEra / 100) + dayOfYearPrime; // [0, 146096]
+
58 
+
59  int32_t dayOfEpochPrime = dayOfEra + 146097 * era;
+
60  return dayOfEpochPrime
+
61  - (kInternalEpochYear / 400) * 146097 /*relative to 2000-03-01*/
+
62  + 60 /*relative to 2000-01-01, 2000 is a leap year*/;
+
63  }
+
64 
+
76  static void fromEpochDays(int32_t epochDays,
+
77  int16_t& year, uint8_t& month, uint8_t& day) {
+
78 
+
79  int32_t dayOfEpochPrime = epochDays
+
80  + (kInternalEpochYear / 400) * 146097 - 60;
+
81  uint16_t era = (uint32_t) dayOfEpochPrime / 146097; // [0,24]
+
82  uint32_t dayOfEra = dayOfEpochPrime - 146097 * era; // [0,146096]
+
83  uint16_t yearOfEra = (dayOfEra - dayOfEra / 1460 + dayOfEra / 36524
+
84  - dayOfEra / 146096) / 365; // [0,399]
+
85  uint16_t yearPrime = yearOfEra + 400 * era; // [0,9999]
+
86  uint16_t dayOfYearPrime = dayOfEra - (365 * yearOfEra + yearOfEra/4
+
87  - yearOfEra/100);
+
88  uint8_t monthPrime = (5 * dayOfYearPrime + 2) / 153;
+
89  uint16_t daysUntilMonthPrime = toDaysUntilMonthPrime(monthPrime);
+
90 
+
91  day = dayOfYearPrime - daysUntilMonthPrime + 1; // [1,31]
+
92  month = (monthPrime < 10) ? monthPrime + 3 : monthPrime - 9; // [1,12]
+
93  year = yearPrime + ((month <= 2) ? 1 : 0); // [1,9999]
+
94  }
+
95 
+
100  static uint16_t toDaysUntilMonthPrime(uint8_t monthPrime) {
+
101  return (153 * monthPrime + 2) / 5;
+
102  }
+
103 };
+
104 
+
105 }
106 }
-
107 }
-
108 
-
109 #endif
+
107 
+
108 #endif
Utility class that converts AceTime epoch days to (year, month, day) in the Gregorian calendar and vi...
-
static void fromEpochDays(int32_t epochDays, int16_t &year, uint8_t &month, uint8_t &day)
Extract the (year, month, day) fields from AceTime epochDays.
-
static const int16_t kConverterEpochYear
Epoch year used by this epoch converter.
-
static uint16_t toDaysUntilMonthPrime(uint8_t monthPrime)
Return the number days before the given monthPrime.
-
static const int32_t kDaysToConverterEpochFromUnixEpoch
Number of days from Unix epoch (1970-01-01 00:00:00 UTC) to the converter epoch (2000-01-01 00:00:00 ...
-
static int32_t toEpochDays(int16_t year, uint8_t month, uint8_t day)
Convert (year, month, day) in the Gregorian calendar to days since the converter epoch (2000-01-01 in...
+
static const int32_t kDaysToInternalEpochFromUnixEpoch
Number of days from Unix epoch (1970-01-01 00:00:00 UTC) to the internal epoch (2000-01-01 00:00:00 U...
+
static const int16_t kInternalEpochYear
Epoch year used by this epoch converter.
+
static void fromEpochDays(int32_t epochDays, int16_t &year, uint8_t &month, uint8_t &day)
Extract the (year, month, day) fields from AceTime epochDays.
+
static uint16_t toDaysUntilMonthPrime(uint8_t monthPrime)
Return the number days before the given monthPrime.
+
static int32_t toEpochDays(int16_t year, uint8_t month, uint8_t day)
Convert (year, month, day) in the Gregorian calendar to days since the internal epoch (2000-01-01).