AceTime  2.3.0
Date and time classes for Arduino that support timezones from the TZ Database.
BrokersHigh.h
Go to the documentation of this file.
1 /*
2  * MIT License
3  * Copyright (c) 2023 Brian T. Park
4  */
5 
6 #ifndef ACE_TIME_BROKERS_HIGH_H
7 #define ACE_TIME_BROKERS_HIGH_H
8 
24 #include <stdint.h> // uintptr_t, uint32_t, etc
25 #include <Arduino.h> // pgm_read_xxx()
26 #include <AceCommon.h> // KString
27 #include "compat.h" // ACE_TIME_USE_PROGMEM
28 #include "BrokerCommon.h"
29 #include "ZoneInfoHigh.h"
30 
31 class __FlashStringHelper;
32 class Print;
33 
34 namespace ace_time {
35 namespace zoneinfohigh {
36 
37 //-----------------------------------------------------------------------------
38 
43 inline int32_t toDeltaSeconds(uint8_t deltaMinutes) {
44  return int32_t(60) * (int8_t) deltaMinutes;
45 }
46 
50 inline int32_t toOffsetSeconds(uint16_t offsetCode, uint8_t offsetRemainder) {
51  return int32_t(15) * (int16_t) offsetCode + (int32_t) offsetRemainder;
52 }
53 
60 inline uint32_t timeCodeToSeconds(uint16_t code, uint8_t modifier) {
61  return code * (uint32_t) 15 + (modifier & 0x0f);
62 }
63 
69 inline uint8_t toSuffix(uint8_t modifier) {
70  return modifier & 0xf0;
71 }
72 
73 //-----------------------------------------------------------------------------
74 
80 template <typename ZC>
82  public:
83  explicit ZoneContextBroker(const ZC* zoneContext = nullptr)
84  : mZoneContext(zoneContext)
85  {}
86 
87  // use the default copy constructor
88  ZoneContextBroker(const ZoneContextBroker&) = default;
89 
90  // use the default assignment operator
91  ZoneContextBroker& operator=(const ZoneContextBroker&) = default;
92 
93  bool isNull() const { return mZoneContext == nullptr; }
94 
95  const ZC* raw() const { return mZoneContext; }
96 
97  int16_t startYear() const {
98  return (int16_t) pgm_read_word(&mZoneContext->startYear);
99  }
100 
101  int16_t untilYear() const {
102  return (int16_t) pgm_read_word(&mZoneContext->untilYear);
103  }
104 
105  int16_t startYearAccurate() const {
106  return (int16_t) pgm_read_word(&mZoneContext->startYearAccurate);
107  }
108 
109  int16_t untilYearAccurate() const {
110  return (int16_t) pgm_read_word(&mZoneContext->untilYearAccurate);
111  }
112 
113  int16_t baseYear() const {
114  return (int16_t) pgm_read_word(&mZoneContext->baseYear);
115  }
116 
117  int16_t maxTransitions() const {
118  return (int16_t) pgm_read_word(&mZoneContext->maxTransitions);
119  }
120 
121  const __FlashStringHelper* tzVersion() const {
122  return (const __FlashStringHelper*)
123  pgm_read_ptr(&mZoneContext->tzVersion);
124  }
125 
126  uint8_t numFragments() const {
127  return (uint8_t) pgm_read_byte(&mZoneContext->numFragments);
128  }
129 
130  uint8_t numLetters() const {
131  return (uint8_t) pgm_read_byte(&mZoneContext->numLetters);
132  }
133 
134  const __FlashStringHelper* const* fragments() const {
135  return (const __FlashStringHelper* const*)
136  pgm_read_ptr(&mZoneContext->fragments);
137  }
138 
139  const __FlashStringHelper* letter(uint8_t i) const {
140  const char * const* letters = (const char* const*)
141  pgm_read_ptr(&mZoneContext->letters);
142  const char* letter = (const char*) pgm_read_ptr(letters + i);
143  return (const __FlashStringHelper*) letter;
144  }
145 
146  private:
147  const ZC* mZoneContext;
148 };
149 
150 //-----------------------------------------------------------------------------
151 
158 template <typename ZC, typename ZR>
160  public:
161  explicit ZoneRuleBroker(
162  const ZC* zoneContext = nullptr,
163  const ZR* zoneRule = nullptr)
164  : mZoneContext(zoneContext)
165  , mZoneRule(zoneRule)
166  {}
167 
168  // use the default copy constructor
169  ZoneRuleBroker(const ZoneRuleBroker&) = default;
170 
171  // use the default assignment operator
172  ZoneRuleBroker& operator=(const ZoneRuleBroker&) = default;
173 
174  bool isNull() const { return mZoneRule == nullptr; }
175 
176  int16_t fromYear() const {
177  return pgm_read_word(&mZoneRule->fromYear);
178  }
179 
180  int16_t toYear() const {
181  return pgm_read_word(&mZoneRule->toYear);
182  }
183 
184  uint8_t inMonth() const {
185  return pgm_read_byte(&mZoneRule->inMonth);
186  }
187 
188  uint8_t onDayOfWeek() const {
189  return pgm_read_byte(&mZoneRule->onDayOfWeek);
190  }
191 
192  int8_t onDayOfMonth() const {
193  return pgm_read_byte(&mZoneRule->onDayOfMonth);
194  }
195 
196  uint32_t atTimeSeconds() const {
197  return timeCodeToSeconds(
198  pgm_read_word(&mZoneRule->atTimeCode),
199  pgm_read_byte(&mZoneRule->atTimeModifier));
200  }
201 
202  uint8_t atTimeSuffix() const {
203  return toSuffix(pgm_read_byte(&mZoneRule->atTimeModifier));
204  }
205 
206  int32_t deltaSeconds() const {
207  return toDeltaSeconds(pgm_read_byte(&mZoneRule->deltaMinutes));
208  }
209 
210  const __FlashStringHelper* letter() const {
211  uint8_t index = pgm_read_byte(&mZoneRule->letterIndex);
212  return ZoneContextBroker<ZC>(mZoneContext).letter(index);
213  }
214 
215  private:
216  const ZC* mZoneContext;
217  const ZR* mZoneRule;
218 };
219 
227 template <typename ZC, typename ZP, typename ZR>
229  public:
230  explicit ZonePolicyBroker(
231  const ZC* zoneContext,
232  const ZP* zonePolicy)
233  : mZoneContext(zoneContext)
234  , mZonePolicy(zonePolicy)
235  {}
236 
237  // use default copy constructor
238  ZonePolicyBroker(const ZonePolicyBroker&) = default;
239 
240  // use default assignment operator
241  ZonePolicyBroker& operator=(const ZonePolicyBroker&) = default;
242 
243  bool isNull() const { return mZonePolicy == nullptr; }
244 
245  uint8_t numRules() const {
246  return pgm_read_byte(&mZonePolicy->numRules);
247  }
248 
249  const ZoneRuleBroker<ZC, ZR> rule(uint8_t i) const {
250  const ZR* rules = (const ZR*) pgm_read_ptr(&mZonePolicy->rules);
251  return ZoneRuleBroker<ZC, ZR>(mZoneContext, &rules[i]);
252  }
253 
254  private:
255  const ZC* mZoneContext;
256  const ZP* mZonePolicy;
257 };
258 
259 //-----------------------------------------------------------------------------
260 
269 template <typename ZC, typename ZE, typename ZP, typename ZR>
271  public:
272  explicit ZoneEraBroker(
273  const ZC* zoneContext = nullptr,
274  const ZE* zoneEra = nullptr)
275  : mZoneContext(zoneContext)
276  , mZoneEra(zoneEra)
277  {}
278 
279  // use default copy constructor
280  ZoneEraBroker(const ZoneEraBroker&) = default;
281 
282  // use default assignment operator
283  ZoneEraBroker& operator=(const ZoneEraBroker&) = default;
284 
285  bool isNull() const { return mZoneEra == nullptr; }
286 
287  bool equals(const ZoneEraBroker& other) const {
288  return mZoneEra == other.mZoneEra;
289  }
290 
291  const ZonePolicyBroker<ZC, ZP, ZR> zonePolicy() const {
293  mZoneContext,
294  (const ZP*) pgm_read_ptr(&mZoneEra->zonePolicy));
295  }
296 
297  int32_t offsetSeconds() const {
298  return toOffsetSeconds(
299  pgm_read_word(&mZoneEra->offsetCode),
300  pgm_read_byte(&mZoneEra->offsetRemainder));
301  }
302 
303  int32_t deltaSeconds() const {
304  return toDeltaSeconds(pgm_read_byte(&mZoneEra->deltaMinutes));
305  }
306 
307  const char* format() const {
308  return (const char*) pgm_read_ptr(&mZoneEra->format);
309  }
310 
311  int16_t untilYear() const {
312  return pgm_read_word(&mZoneEra->untilYear);
313  }
314 
315  uint8_t untilMonth() const {
316  return pgm_read_byte(&mZoneEra->untilMonth);
317  }
318 
319  uint8_t untilDay() const {
320  return pgm_read_byte(&mZoneEra->untilDay);
321  }
322 
323  uint32_t untilTimeSeconds() const {
324  return timeCodeToSeconds(
325  pgm_read_word(&mZoneEra->untilTimeCode),
326  pgm_read_byte(&mZoneEra->untilTimeModifier));
327  }
328 
329  uint8_t untilTimeSuffix() const {
330  return toSuffix(pgm_read_byte(&mZoneEra->untilTimeModifier));
331  }
332 
333  private:
334  const ZC* mZoneContext;
335  const ZE* mZoneEra;
336 };
337 
347 template <typename ZC, typename ZI, typename ZE, typename ZP, typename ZR>
349  public:
350  explicit ZoneInfoBroker(const ZI* zoneInfo = nullptr):
351  mZoneInfo(zoneInfo) {}
352 
353  // use default copy constructor
354  ZoneInfoBroker(const ZoneInfoBroker&) = default;
355 
356  // use default assignment operator
357  ZoneInfoBroker& operator=(const ZoneInfoBroker&) = default;
358 
363  bool equals(uintptr_t zoneKey) const {
364  return mZoneInfo == (const ZI*) zoneKey;
365  }
366 
367  bool equals(const ZoneInfoBroker& zoneInfoBroker) const {
368  return mZoneInfo == zoneInfoBroker.mZoneInfo;
369  }
370 
371  bool isNull() const { return mZoneInfo == nullptr; }
372 
373  const ZoneContextBroker<ZC> zoneContext() const {
374  const ZC* context = (const ZC*) pgm_read_ptr(&mZoneInfo->zoneContext);
375  return ZoneContextBroker<ZC>(context);
376  }
377 
378  const __FlashStringHelper* name() const {
379  return FPSTR(pgm_read_ptr(&mZoneInfo->name));
380  }
381 
382  uint32_t zoneId() const {
383  return pgm_read_dword(&mZoneInfo->zoneId);
384  }
385 
386  uint8_t numEras() const {
387  return pgm_read_byte(&mZoneInfo->numEras);
388  }
389 
390  const ZoneEraBroker<ZC, ZE, ZP, ZR> era(uint8_t i) const {
391  auto eras = (const ZE*) pgm_read_ptr(&mZoneInfo->eras);
392  return ZoneEraBroker<ZC, ZE, ZP, ZR>(zoneContext().raw(), &eras[i]);
393  }
394 
395  bool isLink() const {
396  return mZoneInfo->targetInfo != nullptr;
397  }
398 
399  ZoneInfoBroker targetInfo() const {
400  return ZoneInfoBroker(
401  (const ZI*) pgm_read_ptr(&mZoneInfo->targetInfo));
402  }
403 
405  void printNameTo(Print& printer) const;
406 
411  void printShortNameTo(Print& printer) const;
412 
413  private:
414  const ZI* mZoneInfo;
415 };
416 
417 
418 template <typename ZC, typename ZI, typename ZE, typename ZP, typename ZR>
420  ZoneContextBroker<ZC> zc = zoneContext();
421  ace_common::KString kname(name(), zc.fragments(), zc.numFragments());
422  kname.printTo(printer);
423 }
424 
425 template <typename ZC, typename ZI, typename ZE, typename ZP, typename ZR>
427  const {
428  ace_common::printReplaceCharTo(
429  printer, zoneinfo::findShortName(name()), '_', ' ');
430 }
431 
432 //-----------------------------------------------------------------------------
433 
440 template <typename ZI>
442  public:
443  ZoneRegistryBroker(const ZI* const* zoneRegistry):
444  mZoneRegistry(zoneRegistry) {}
445 
446  // use default copy constructor
447  ZoneRegistryBroker(const ZoneRegistryBroker&) = default;
448 
449  // use default assignment operator
450  ZoneRegistryBroker& operator=(const ZoneRegistryBroker&) = default;
451 
452  const ZI* zoneInfo(uint16_t i) const {
453  return (const ZI*) pgm_read_ptr(&mZoneRegistry[i]);
454  }
455 
456  private:
457  const ZI* const* mZoneRegistry;
458 };
459 
460 //-----------------------------------------------------------------------------
461 
473 template <typename ZC, typename ZI, typename ZE, typename ZP, typename ZR>
475  public:
481  createZoneInfoBroker(uintptr_t zoneKey) const {
482  return ZoneInfoBroker<ZC, ZI, ZE, ZP, ZR>((const ZI*) zoneKey);
483  }
484 };
485 
486 } // zoneinfohigh
487 } // ace_time
488 
489 #endif
Helper functions are used in both Basic brokers and Extended brokers.
uint32_t timeCodeToSeconds(uint16_t code, uint8_t modifier)
Convert (code, modifier) holding the UNTIL time in ZoneInfo or AT time in ZoneRule into seconds.
Definition: BrokersHigh.h:60
uint8_t toSuffix(uint8_t modifier)
Extract the 'w', 's' 'u' suffix from the 'modifier' field, so that they can be compared against kSuff...
Definition: BrokersHigh.h:69
int32_t toDeltaSeconds(uint8_t deltaMinutes)
Convert the deltaMinutes holding the RULES/DSTOFF field in ZoneEra or the SAVE field in ZoneRule to d...
Definition: BrokersHigh.h:43
int32_t toOffsetSeconds(uint16_t offsetCode, uint8_t offsetRemainder)
Convert (code, remainder) holding the STDOFF field of ZoneEra into seconds.
Definition: BrokersHigh.h:50
Data broker for accessing a ZoneContext.
Definition: BrokersHigh.h:81
Data broker for accessing ZoneEra.
Definition: BrokersHigh.h:270
Data broker for accessing ZoneInfo.
Definition: BrokersHigh.h:348
bool equals(uintptr_t zoneKey) const
Definition: BrokersHigh.h:363
void printShortNameTo(Print &printer) const
Print a short human-readable identifier (e.g.
Definition: BrokersHigh.h:426
void printNameTo(Print &printer) const
Print a human-readable identifier (e.g.
Definition: BrokersHigh.h:419
A storage object that creates an ZoneInfoBroker from a key that identifies the ZoneInfo.
Definition: BrokersHigh.h:474
ZoneInfoBroker< ZC, ZI, ZE, ZP, ZR > createZoneInfoBroker(uintptr_t zoneKey) const
Definition: BrokersHigh.h:481
Data broker for accessing ZonePolicy.
Definition: BrokersHigh.h:228
Data broker for accessing the ZoneRegistry.
Definition: BrokersHigh.h:441
Data broker for accessing ZoneRule.
Definition: BrokersHigh.h:159
Macros and definitions that provide a consistency layer among the various Arduino boards for compatib...