AceTime 3.0.0 Date and time classes for Arduino that support timezones from the TZ Database.

Transition.h
1 /*
2 * MIT License
3 * Copyright (c) 2019 Brian T. Park
4 */
5
6 #ifndef ACE_TIME_EXTENDED_TRANSITION_H
7 #define ACE_TIME_EXTENDED_TRANSITION_H
8
9 #include <stdint.h> // uint8_t
10 #include "common/logging.h"
11 #include "local_date_mutation.h"
12 #include "DateTuple.h"
13
14 class TransitionStorageTest_getFreeAgent;
15 class TransitionStorageTest_getFreeAgent2;
16 class TransitionStorageTest_addFreeAgentToActivePool;
17 class TransitionStorageTest_reservePrior;
18 class TransitionStorageTest_addPriorToCandidatePool;
19 class TransitionStorageTest_addFreeAgentToCandidatePool;
20 class TransitionStorageTest_setFreeAgentAsPriorIfValid;
21 class TransitionStorageTest_addActiveCandidatesToActivePool;
22 class TransitionStorageTest_findTransitionForDateTime;
23 class TransitionStorageTest_resetCandidatePool;
24
25 class Print;
26
27 #ifndef ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG
28 #define ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG 0
29 #endif
30
31 namespace ace_time {
32 namespace extended {
33
34 inline bool isCompareStatusActive(CompareStatus status) {
35 return status == CompareStatus::kExactMatch
36 || status == CompareStatus::kWithinMatch
37 || status == CompareStatus::kPrior;
38 }
39
46 template<typename D>
47 struct MatchingEraTemplate {
52 DateTuple startDateTime;
53
55 DateTuple untilDateTime;
56
58 typename D::ZoneEraBroker era;
59
61 MatchingEraTemplate* prevMatch;
62
64 int32_t lastOffsetSeconds;
65
67 int32_t lastDeltaSeconds;
68
69 void log() const {
70 logging::printf("MatchingEra(");
71 logging::printf("start="); startDateTime.log();
72 logging::printf("; until="); untilDateTime.log();
73 logging::printf("; era=%c", (era.isNull()) ? '-' : '*');
74 logging::printf("; prevMatch=%c", (prevMatch) ? '*' : '-');
75 logging::printf(")");
76 }
77 };
78
79 //---------------------------------------------------------------------------
80
111 template <typename D>
112 struct TransitionTemplate {
113
115 const MatchingEraTemplate<D>* match;
116
117 #if ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG
124 typename D::ZoneRuleBroker rule;
125 #endif
126
133 DateTuple transitionTime;
134
135 union {
141 DateTuple transitionTimeS;
142
147 DateTuple startDateTime;
148 };
149
150 union {
156 DateTuple transitionTimeU;
157
162 DateTuple untilDateTime;
163 };
164
165 #if ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG
170 DateTuple originalTransitionTime;
171 #endif
172
174 acetime_t startEpochSeconds;
175
177 int32_t offsetSeconds;
178
180 int32_t deltaSeconds;
181
188 char abbrev[kAbbrevSize];
189
190 union {
197 bool isValidPrior;
198
203 CompareStatus compareStatus;
204 };
205
206 const char* format() const {
207 return match->era.format();
208 }
209
211 void log() const {
212 logging::printf("Transition(");
213 if (sizeof(acetime_t) <= sizeof(int)) {
214 logging::printf("start=%d", startEpochSeconds);
215 } else {
216 logging::printf("start=%ld", startEpochSeconds);
217 }
218 logging::printf("; status=%d", compareStatus);
219 logging::printf("; UTC");
220 logHourMinuteSecond(offsetSeconds);
221 logHourMinuteSecond(deltaSeconds);
222 logging::printf("; tt="); transitionTime.log();
223 logging::printf("; tts="); transitionTimeS.log();
224 logging::printf("; ttu="); transitionTimeU.log();
225 #if ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG
226 if (rule.isNull()) {
227 logging::printf("; rule=-");
228 } else {
229 logging::printf("; rule=");
230 logging::printf("[%d,%d]", rule.fromYear(), rule.toYear());
231 }
232 #endif
233 }
234
236 static void logHourMinuteSecond(int32_t seconds) {
237 char sign;
238 if (seconds < 0) {
239 sign = '-';
240 seconds = -seconds;
241 } else {
242 sign = '+';
243 }
244 uint16_t minutes = seconds / 60;
245 uint8_t second = seconds - minutes * int32_t(60);
246 uint8_t hour = minutes / 60;
247 uint8_t minute = minutes - hour * 60;
248 if (second == 0) {
249 logging::printf("%c%02u:%02u", sign, (unsigned) hour, (unsigned) minute);
250 } else {
251 logging::printf("%c%02u:%02u:%02u",
252 sign, (unsigned) hour, (unsigned) minute, (unsigned) second);
253 }
254 }
255
256 #ifdef ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG
258 static void printTransitions(
259 const char* prefix,
260 const TransitionTemplate* const* begin,
261 const TransitionTemplate* const* end) {
262 for (const TransitionTemplate* const* iter = begin; iter != end; ++iter) {
263 logging::printf(prefix);
264 (*iter)->log();
265 logging::printf("\n");
266 }
267 }
268 #endif
269 };
270
278 template <typename D>
279 struct TransitionForSecondsTemplate {
281 const TransitionTemplate<D>* curr;
282
284 uint8_t fold;
285
292 uint8_t num;
293 };
294
308 template <typename D>
309 struct TransitionForDateTimeTemplate {
312 const TransitionTemplate<D>* prev;
315 const TransitionTemplate<D>* curr;
316
318 uint8_t num;
319 };
320
350 template<uint8_t SIZE, typename D>
351 class TransitionStorageTemplate {
352 public:
357 typedef TransitionTemplate<D> Transition;
358
364 typedef TransitionForSecondsTemplate<D> TransitionForSeconds;
365
371 typedef TransitionForDateTimeTemplate<D> TransitionForDateTime;
372
374 TransitionStorageTemplate() {}
375
382 void init() {
383 for (uint8_t i = 0; i < SIZE; i++) {
384 mTransitions[i] = &mPool[i];
385 }
386 mIndexPrior = 0;
387 mIndexCandidates = 0;
388 mIndexFree = 0;
389 }
390
392 Transition* getPrior() {
393 return mTransitions[mIndexPrior];
394 }
395
404 void resetCandidatePool() {
405 mIndexCandidates = mIndexPrior;
406 mIndexFree = mIndexPrior;
407 }
408
409 Transition** getCandidatePoolBegin() {
410 return &mTransitions[mIndexCandidates];
411 }
412 Transition** getCandidatePoolEnd() {
413 return &mTransitions[mIndexFree];
414 }
415
416 Transition** getActivePoolBegin() {
417 return &mTransitions[0];
418 }
419 Transition** getActivePoolEnd() {
420 return &mTransitions[mIndexFree];
421 }
422
428 Transition* getFreeAgent() {
429 if (mIndexFree < SIZE) {
430 // Allocate a free transition.
431 if (mIndexFree >= mAllocSize) {
432 mAllocSize = mIndexFree + 1;
433 }
434 return mTransitions[mIndexFree];
435 } else {
436 // No more transition available in the buffer, so just return the last
437 // one. This will probably cause a bug in the timezone calculations, but
438 // I think this is better than triggering undefined behavior by running
439 // off the end of the mTransitions buffer.
440 return mTransitions[SIZE - 1];
441 }
442 }
443
451 void addFreeAgentToActivePool() {
452 if (mIndexFree >= SIZE) return;
453 mIndexFree++;
454 mIndexPrior = mIndexFree;
455 mIndexCandidates = mIndexFree;
456 }
457
466 Transition** reservePrior() {
467 getFreeAgent(); // allocate a new Transition
468
469 mIndexCandidates++;
470 mIndexFree++;
471 return &mTransitions[mIndexPrior];
472 }
473
475 void setFreeAgentAsPriorIfValid() {
476 Transition* ft = mTransitions[mIndexFree];
477 Transition* prior = mTransitions[mIndexPrior];
478 if ((prior->isValidPrior && prior->transitionTime < ft->transitionTime)
479 || !prior->isValidPrior) {
480 ft->isValidPrior = true;
481 prior->isValidPrior = false;
482 swap(mTransitions[mIndexPrior], mTransitions[mIndexFree]);
483 }
484 }
485
491 void addPriorToCandidatePool() {
492 mIndexCandidates--;
493 }
494
501 void addFreeAgentToCandidatePool() {
502 if (mIndexFree >= SIZE) return;
503
504 // This implementation makes pair-wise swaps to shift the current
505 // Transition leftwards into its correctly sorted position. At first
506 // glance, this seem inefficient compared to the alternative
507 // implementation where we save the current Transition, then slide all the
508 // elements to the left by one position rightwards. However,
509 // MemoryBenchmark shows that this implementation is 46 bytes smaller on
510 // an AVR processor.
511 for (uint8_t i = mIndexFree; i > mIndexCandidates; i--) {
512 Transition* curr = mTransitions[i];
513 Transition* prev = mTransitions[i - 1];
514 if (curr->transitionTime >= prev->transitionTime) break;
515 mTransitions[i] = prev;
516 mTransitions[i - 1] = curr;
517 }
518 mIndexFree++;
519 }
520
527 Transition* addActiveCandidatesToActivePool() {
528 if (ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG) {
529 logging::printf("addActiveCandidatesToActivePool()\n");
530 }
531
532 // Shift active candidates to the left into the Active pool.
533 uint8_t iActive = mIndexPrior;
534 uint8_t iCandidate = mIndexCandidates;
535 for (; iCandidate < mIndexFree; iCandidate++) {
536 if (isCompareStatusActive(mTransitions[iCandidate]->compareStatus)) {
537 if (iActive != iCandidate) {
538 // Must use swap(), because we are moving pointers instead of the
539 // actual Transition objects.
540 swap(mTransitions[iActive], mTransitions[iCandidate]);
541 }
542 ++iActive;
543 }
544 }
545
546 mIndexPrior = iActive;
547 mIndexCandidates = iActive;
548 mIndexFree = iActive;
549
550 return mTransitions[iActive - 1];
551 }
552
561 TransitionForSeconds findTransitionForSeconds(acetime_t epochSeconds)
562 const {
563 if (ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG) {
564 logging::printf(
565 "findTransitionForSeconds(): mIndexFree: %d\n", mIndexFree);
566 }
567
568 const Transition* prev = nullptr;
569 const Transition* curr = nullptr;
570 const Transition* next = nullptr;
571 for (uint8_t i = 0; i < mIndexFree; i++) {
572 next = mTransitions[i];
573 if (next->startEpochSeconds > epochSeconds) break;
574 prev = curr;
575 curr = next;
576 next = nullptr;
577 }
578
579 uint8_t fold;
580 uint8_t num;
581 calcFoldAndOverlap(&fold, &num, prev, curr, next, epochSeconds);
582 //fprintf(stderr, "prev=%p;curr=%p;next=%p;fold=%d;num=%d\n",
583 // prev, curr, next, fold, num);
584 return TransitionForSeconds{curr, fold, num};
585 }
586
606 static void calcFoldAndOverlap(
607 uint8_t* fold,
608 uint8_t* num,
609 const Transition* prev,
610 const Transition* curr,
611 const Transition* next,
612 acetime_t epochSeconds) {
613
614 if (curr == nullptr) {
615 *fold = 0;
616 *num = 0;
617 return;
618 }
619
620 // Check if within forward overlap shadow from prev
621 bool isOverlap;
622 if (prev == nullptr) {
623 isOverlap = false;
624 } else {
625 // Extract the shift from prev transition. Can be 0 in some cases where
626 // the zone changed from DST of one zone to the STD into another zone,
627 // causing the overall UTC offset to remain unchanged.
628 acetime_t shiftSeconds = subtractDateTuple(
629 curr->startDateTime, prev->untilDateTime);
630 if (shiftSeconds >= 0) {
631 // spring forward, or unchanged
632 isOverlap = false;
633 } else {
634 // Check if within the forward overlap shadow from prev
635 isOverlap = epochSeconds - curr->startEpochSeconds < -shiftSeconds;
636 }
637 }
638 if (isOverlap) {
639 *fold = 1; // epochSeconds selects the second match
640 *num = 2;
641 return;
642 }
643
644 // Check if within backward overlap shawdow from next
645 if (next == nullptr) {
646 isOverlap = false;
647 } else {
648 // Extract the shift to next transition. Can be 0 in some cases where
649 // the zone changed from DST of one zone to the STD into another zone,
650 // causing the overall UTC offset to remain unchanged.
651 acetime_t shiftSeconds = subtractDateTuple(
652 next->startDateTime, curr->untilDateTime);
653 if (shiftSeconds >= 0) {
654 // spring forward, or unchanged
655 isOverlap = false;
656 } else {
657 // Check if within the backward overlap shadow from next
658 isOverlap = next->startEpochSeconds - epochSeconds <= -shiftSeconds;
659 }
660 }
661 if (isOverlap) {
662 *fold = 0; // epochSeconds selects the first match
663 *num = 2;
664 return;
665 }
666
667 // Normal single match, no overlap.
668 *fold = 0;
669 *num = 1;
670 }
671
677 TransitionForDateTime findTransitionForDateTime(
678 const LocalDateTime& ldt) const {
679 // Convert LocalDateTime to DateTuple.
680 DateTuple localDate{
681 ldt.year(),
682 ldt.month(),
683 ldt.day(),
684 ((ldt.hour() * int32_t(60) + ldt.minute()) * 60 + ldt.second()),
685 extended::Info::ZoneContext::kSuffixW,
686 };
687
688 // Examine adjacent pairs of Transitions, looking for an exact match, gap,
689 // or overlap.
690 const Transition* prev = nullptr;
691 const Transition* curr = nullptr;
692 uint8_t num = 0;
693 for (uint8_t i = 0; i < mIndexFree; i++) {
694 curr = mTransitions[i];
695
696 const DateTuple& startDateTime = curr->startDateTime;
697 const DateTuple& untilDateTime = curr->untilDateTime;
698 bool isExactMatch = (startDateTime <= localDate)
699 && (localDate < untilDateTime);
700
701 if (isExactMatch) {
702 // Check for a previous exact match to detect an overlap.
703 if (num == 1) {
704 num++;
705 break;
706 }
707
708 // Loop again to detect an overlap.
709 num = 1;
710 } else if (startDateTime > localDate) {
711 // Exit loop since no more candidate transition.
712 break;
713 }
714
715 prev = curr;
716
717 // Set the curr to nullptr so that if the loop runs off the end of the
718 // list of Transitions, the curr is marked as nullptr.
719 curr = nullptr;
720 }
721
722 // Check if the prev was an exact match, and set the curr to be identical.
723 // avoid confusion.
724 if (num == 1) {
725 curr = prev;
726 }
727
728 // This should get optimized by RVO.
729 return TransitionForDateTime{prev, curr, num};
730 }
731
733 void log() const {
734 logging::printf("TransitionStorage: ");
735 logging::printf("SIZE=%d, mAllocSize=%d\n", SIZE, mAllocSize);
736 int nActives = mIndexPrior;
737 int nPrior = mIndexCandidates - mIndexPrior;
738 int nCandidates = mIndexFree - mIndexCandidates;
739 int nAllocFree = mAllocSize - mIndexFree;
740 int nVirginFree = SIZE - mAllocSize;
741
742 logging::printf(" Actives: %d\n", nActives);
743 Transition::printTransitions(
744 " ", &mTransitions[0], &mTransitions[mIndexPrior]);
745
746 logging::printf(" Prior: %d\n", nPrior);
747 Transition::printTransitions(
748 " ", &mTransitions[mIndexPrior], &mTransitions[mIndexCandidates]);
749
750 logging::printf(" Candidates: %d\n", nCandidates);
751 Transition::printTransitions(
752 " ", &mTransitions[mIndexCandidates], &mTransitions[mIndexFree]);
753
754 logging::printf(" Allocated Free: %d\n", nAllocFree);
755 logging::printf(" Virgin Free: %d\n", nVirginFree);
756 }
757
759 void resetAllocSize() { mAllocSize = 0; }
760
766 uint8_t getAllocSize() const { return mAllocSize; }
767
768 private:
769 friend class ::TransitionStorageTest_getFreeAgent;
770 friend class ::TransitionStorageTest_getFreeAgent2;
771 friend class ::TransitionStorageTest_addFreeAgentToActivePool;
772 friend class ::TransitionStorageTest_reservePrior;
773 friend class ::TransitionStorageTest_addPriorToCandidatePool;
774 friend class ::TransitionStorageTest_addFreeAgentToCandidatePool;
775 friend class ::TransitionStorageTest_setFreeAgentAsPriorIfValid;
776 friend class ::TransitionStorageTest_addActiveCandidatesToActivePool;
777 friend class ::TransitionStorageTest_findTransitionForDateTime;
778 friend class ::TransitionStorageTest_resetCandidatePool;
779
781 Transition* getTransition(uint8_t i) {
782 return mTransitions[i];
783 }
784
785 Transition mPool[SIZE];
786 Transition* mTransitions[SIZE];
787 uint8_t mIndexPrior;
788 uint8_t mIndexCandidates;
789 uint8_t mIndexFree;
790
792 uint8_t mAllocSize = 0;
793 };
794
795 } // namespace extended
796 } // namespace ace_time
797
798 #endif
ace_time::LocalDateTime
Class that holds the date-time as the components (year, month, day, hour, minute, second) without reg...
Definition: LocalDateTime.h:30
ace_time::LocalDateTime::day
uint8_t day() const
Return the day of the month.
Definition: LocalDateTime.h:168
ace_time::LocalDateTime::month
uint8_t month() const
Return the month with January=1, December=12.
Definition: LocalDateTime.h:162
ace_time::LocalDateTime::second
uint8_t second() const
Return the second.
Definition: LocalDateTime.h:186
ace_time::LocalDateTime::minute
uint8_t minute() const
Return the minute.
Definition: LocalDateTime.h:180
ace_time::LocalDateTime::hour
uint8_t hour() const
Return the hour.
Definition: LocalDateTime.h:174
ace_time::LocalDateTime::year
int16_t year() const
Return the year.
Definition: LocalDateTime.h:156
ace_time::extended::TransitionStorageTemplate
A heap manager which is specialized and tuned to manage a collection of Transitions,...
Definition: Transition.h:351
ace_time::extended::TransitionStorageTemplate::setFreeAgentAsPriorIfValid
void setFreeAgentAsPriorIfValid()
Set the free agent transition as the most recent prior.
Definition: Transition.h:475
ace_time::extended::TransitionStorageTemplate::getFreeAgent
Transition * getFreeAgent()
Return a pointer to the first Transition in the free pool.
Definition: Transition.h:428
ace_time::extended::TransitionStorageTemplate::Transition
TransitionTemplate< D > Transition
Template instantiation of TransitionTemplate used by this class.
Definition: Transition.h:357
ace_time::extended::TransitionStorageTemplate::addPriorToCandidatePool
void addPriorToCandidatePool()
Add the current prior into the Candidates pool.
Definition: Transition.h:491
ace_time::extended::TransitionStorageTemplate::getAllocSize
uint8_t getAllocSize() const
Return the maximum number of transitions which was allocated.
Definition: Transition.h:766
ace_time::extended::TransitionStorageTemplate::addActiveCandidatesToActivePool
Transition * addActiveCandidatesToActivePool()
Add active candidates into the Active pool, and collapse the Candidate pool.
Definition: Transition.h:527
ace_time::extended::TransitionStorageTemplate::resetCandidatePool
void resetCandidatePool()
Empty the Candidate pool by resetting the various indexes.
Definition: Transition.h:404
ace_time::extended::TransitionStorageTemplate::resetAllocSize
void resetAllocSize()
Reset the current allocation size.
Definition: Transition.h:759
ace_time::extended::TransitionStorageTemplate::addFreeAgentToActivePool
void addFreeAgentToActivePool()
Immediately add the free agent Transition at index mIndexFree to the Active pool.
Definition: Transition.h:451
ace_time::extended::TransitionStorageTemplate::TransitionForSeconds
TransitionForSecondsTemplate< D > TransitionForSeconds
Template instantiation of TransitionForSecondsTemplate used by this class.
Definition: Transition.h:364
ace_time::extended::TransitionStorageTemplate::TransitionForDateTime
TransitionForDateTimeTemplate< D > TransitionForDateTime
Template instantiation of TransitionForDateTimeTemplate used by this class.
Definition: Transition.h:371
ace_time::extended::TransitionStorageTemplate::calcFoldAndOverlap
static void calcFoldAndOverlap(uint8_t *fold, uint8_t *num, const Transition *prev, const Transition *curr, const Transition *next, acetime_t epochSeconds)
Calculate the fold and num parameters of TransitionForSecond.
Definition: Transition.h:606
ace_time::extended::TransitionStorageTemplate::getPrior
Transition * getPrior()
Return the current prior transition.
Definition: Transition.h:392
ace_time::extended::TransitionStorageTemplate::TransitionStorageTemplate
TransitionStorageTemplate()
Constructor.
Definition: Transition.h:374
ace_time::extended::TransitionStorageTemplate::findTransitionForDateTime
TransitionForDateTime findTransitionForDateTime(const LocalDateTime &ldt) const
Return the candidate Transitions matching the given dateTime.
Definition: Transition.h:677
ace_time::extended::TransitionStorageTemplate::addFreeAgentToCandidatePool
void addFreeAgentToCandidatePool()
Add the free agent Transition at index mIndexFree to the Candidate pool, sorted by transitionTime.
Definition: Transition.h:501
ace_time::extended::TransitionStorageTemplate::reservePrior
Transition ** reservePrior()
Allocate a free Transition then add it to the Prior pool.
Definition: Transition.h:466
ace_time::extended::TransitionStorageTemplate::findTransitionForSeconds
TransitionForSeconds findTransitionForSeconds(acetime_t epochSeconds) const
Return the Transition matching the given epochSeconds.
Definition: Transition.h:561
ace_time::extended::TransitionStorageTemplate::init
void init()
Initialize all pools to 0 size, usually when a new year is initialized.
Definition: Transition.h:382
ace_time::extended::TransitionStorageTemplate::log
void log() const
Verify that the indexes are valid.
Definition: Transition.h:733
ace_time::swap
void swap(T &a, T &b)
Swap 2 parameters.
Definition: common.h:48
ace_time::kAbbrevSize
const uint8_t kAbbrevSize
Size of the c-string buffer needed to hold a time zone abbreviation.
Definition: common.h:44
ace_time::acetime_t
int32_t acetime_t
Type for the number of seconds from epoch.
Definition: common.h:24
ace_time::ZoneInfoLow::ZoneContext::kSuffixW
static const uint8_t kSuffixW
Represents 'w' or wall time.
Definition: ZoneInfoLow.h:88
ace_time::extended::DateTuple
A tuple that represents a date and time.
Definition: DateTuple.h:36
ace_time::extended::DateTuple::log
void log() const
Used only for debugging.
Definition: DateTuple.h:50
ace_time::extended::MatchingEraTemplate
Data structure that captures the matching ZoneEra and its ZoneRule transitions for a given year.
Definition: Transition.h:47
ace_time::extended::MatchingEraTemplate::lastDeltaSeconds
int32_t lastDeltaSeconds
The DST offset of the last Transition in this MatchingEra.
Definition: Transition.h:67
ace_time::extended::MatchingEraTemplate::prevMatch
MatchingEraTemplate * prevMatch
The previous MatchingEra, needed to interpret startDateTime.
Definition: Transition.h:61
ace_time::extended::MatchingEraTemplate::startDateTime
DateTuple startDateTime
The effective start time of the matching ZoneEra, which uses the UTC offsets of the previous matching...
Definition: Transition.h:52
ace_time::extended::MatchingEraTemplate::lastOffsetSeconds
int32_t lastOffsetSeconds
The STD offset of the last Transition in this MatchingEra.
Definition: Transition.h:64
ace_time::extended::MatchingEraTemplate::untilDateTime
DateTuple untilDateTime
The effective until time of the matching ZoneEra.
Definition: Transition.h:55
ace_time::extended::MatchingEraTemplate::era
D::ZoneEraBroker era
The ZoneEra that matched the given year.
Definition: Transition.h:58
ace_time::extended::TransitionForDateTimeTemplate
The result of the findTransitionForDateTime(const LocalDatetime& ldt) method which can return 0,...
Definition: Transition.h:309
ace_time::extended::TransitionForDateTimeTemplate::curr
const TransitionTemplate< D > * curr
The matching transition, or null if not found or in gap.
Definition: Transition.h:315
ace_time::extended::TransitionForDateTimeTemplate::prev
const TransitionTemplate< D > * prev
The previous transition.
Definition: Transition.h:312
ace_time::extended::TransitionForDateTimeTemplate::num
uint8_t num
Number of matches: 0, 1, 2.
Definition: Transition.h:318
ace_time::extended::TransitionForSecondsTemplate
Tuple of a matching Transition and its 'fold'.
Definition: Transition.h:279
ace_time::extended::TransitionForSecondsTemplate::curr
const TransitionTemplate< D > * curr
The matching transition, or null if not found.
Definition: Transition.h:281
ace_time::extended::TransitionForSecondsTemplate::num
uint8_t num
Number of occurrences of the resulting LocalDateTime: 0, 1, or 2.
Definition: Transition.h:292
ace_time::extended::TransitionForSecondsTemplate::fold
uint8_t fold
1 if corresponding datetime occurred the second time
Definition: Transition.h:284
ace_time::extended::TransitionTemplate
Represents an interval of time where the time zone obeyed a certain UTC offset and DST delta.
Definition: Transition.h:112
ace_time::extended::TransitionTemplate::logHourMinuteSecond
static void logHourMinuteSecond(int32_t seconds)
Print seconds as [+/-]hh:mm[:ss].
Definition: Transition.h:236
ace_time::extended::TransitionTemplate::transitionTimeU
DateTuple transitionTimeU
Version of transitionTime in 'u' mode, using the UTC offset of the previous transition.
Definition: Transition.h:156
ace_time::extended::TransitionTemplate::log
void log() const
Used only for debugging.
Definition: Transition.h:211
ace_time::extended::TransitionTemplate::transitionTime
DateTuple transitionTime
The original transition time, usually 'w' but sometimes 's' or 'u'.
Definition: Transition.h:133
ace_time::extended::TransitionTemplate::match
const MatchingEraTemplate< D > * match
The match which generated this Transition.
Definition: Transition.h:115
ace_time::extended::TransitionTemplate::startDateTime
DateTuple startDateTime
Start time expressed using the UTC offset of the current Transition.
Definition: Transition.h:147
ace_time::extended::TransitionTemplate::compareStatus
CompareStatus compareStatus
During processTransitionCompareStatus(), this flag indicates how the transition falls within the time...
Definition: Transition.h:203
ace_time::extended::TransitionTemplate::deltaSeconds
int32_t deltaSeconds
The DST delta seconds.
Definition: Transition.h:180
ace_time::extended::TransitionTemplate::isValidPrior
bool isValidPrior
During findCandidateTransitions(), this flag indicates whether the current transition is a valid "pri...
Definition: Transition.h:197
ace_time::extended::TransitionTemplate::abbrev
char abbrev[kAbbrevSize]
The calculated effective time zone abbreviation, e.g.
Definition: Transition.h:188
ace_time::extended::TransitionTemplate::startEpochSeconds
acetime_t startEpochSeconds
The calculated transition time of the given rule.
Definition: Transition.h:174
ace_time::extended::TransitionTemplate::untilDateTime
DateTuple untilDateTime
Until time expressed using the UTC offset of the current Transition.
Definition: Transition.h:162
ace_time::extended::TransitionTemplate::printTransitions
static void printTransitions(const char *prefix, const TransitionTemplate *const *begin, const TransitionTemplate *const *end)
Print an iterable of Transitions from 'begin' to 'end'.
Definition: Transition.h:258
ace_time::extended::TransitionTemplate::transitionTimeS
DateTuple transitionTimeS
Version of transitionTime in 's' mode, using the UTC offset of the previous Transition.
Definition: Transition.h:141
ace_time::extended::TransitionTemplate::offsetSeconds
int32_t offsetSeconds
The standard time offset seconds, not the total offset.
Definition: Transition.h:177