AceTime  1.11.2
Date and time classes for Arduino that support timezones from the TZ Database.
TimeZone.h
1 /*
2  * MIT License
3  * Copyright (c) 2018 Brian T. Park
4  */
5 
6 #ifndef ACE_TIME_TIME_ZONE_H
7 #define ACE_TIME_TIME_ZONE_H
8 
9 #include <stdint.h> // uintptr_t
10 #include "TimeOffset.h"
11 #include "ZoneProcessor.h"
12 #include "BasicZoneProcessor.h"
13 #include "ExtendedZoneProcessor.h"
14 #include "TimeZoneData.h"
15 
16 class Print;
17 
18 namespace ace_time {
19 
85 class TimeZone {
86  public:
88  static const uint8_t kTypeError = 0;
89 
91  static const uint8_t kTypeManual = 1;
92 
94  static const uint8_t kTypeReserved = 2;
95 
97  static TimeZone forUtc() {
98  return TimeZone();
99  }
100 
115  TimeOffset stdOffset,
116  TimeOffset dstOffset = TimeOffset()
117  ) {
118  return TimeZone(stdOffset, dstOffset);
119  }
120 
127  static TimeZone forHours(int8_t stdHours, int8_t dstHours = 0) {
129  TimeOffset::forHours(stdHours),
130  TimeOffset::forHours(dstHours)
131  );
132  }
133 
140  static TimeZone forMinutes(int8_t stdMinutes, int8_t dstMinutes = 0) {
142  TimeOffset::forMinutes(stdMinutes),
143  TimeOffset::forMinutes(dstMinutes)
144  );
145  }
146 
154  int8_t stdHour,
155  int8_t stdMinute,
156  int8_t dstHour = 0,
157  int8_t dstMinute = 0
158  ) {
160  TimeOffset::forHourMinute(stdHour, stdMinute),
161  TimeOffset::forHourMinute(dstHour, dstMinute)
162  );
163  }
164 
174  const basic::ZoneInfo* zoneInfo,
175  BasicZoneProcessor* zoneProcessor
176  ) {
177  return TimeZone(
178  zoneProcessor->getType(),
179  (uintptr_t) zoneInfo,
180  zoneProcessor
181  );
182  }
183 
193  const extended::ZoneInfo* zoneInfo,
194  ExtendedZoneProcessor* zoneProcessor
195  ) {
196  return TimeZone(
197  zoneProcessor->getType(),
198  (uintptr_t) zoneInfo,
199  zoneProcessor
200  );
201  }
202 
208  static TimeZone forZoneKey(uintptr_t zoneKey, ZoneProcessor* processor) {
209  return TimeZone(processor->getType(), zoneKey, processor);
210  }
211 
216  static TimeZone forError() {
217  return TimeZone(kTypeError);
218  }
219 
222  mType(kTypeManual),
223  mStdOffsetMinutes(0),
224  mDstOffsetMinutes(0) {}
225 
233  uint8_t getType() const { return mType; }
234 
237  return TimeOffset::forMinutes(mStdOffsetMinutes);
238  }
239 
242  return TimeOffset::forMinutes(mDstOffsetMinutes);
243  }
244 
246  bool isLink() const {
247  switch (mType) {
248  case kTypeError:
249  case kTypeReserved:
250  case kTypeManual:
251  return false;
252 
253  default:
254  return getBoundZoneProcessor()->isLink();
255  }
256  }
257 
267  uint32_t getZoneId(bool followLink = false) const {
268  switch (mType) {
269  case kTypeError:
270  case kTypeReserved:
271  case kTypeManual:
272  return 0;
273 
274  default:
275  return getBoundZoneProcessor()->getZoneId(followLink);
276  }
277  }
278 
280  bool isError() const { return mType == kTypeError; }
281 
285  TimeOffset getUtcOffset(acetime_t epochSeconds) const {
286  switch (mType) {
287  case kTypeError:
288  case kTypeReserved:
289  return TimeOffset::forError();
290 
291  case kTypeManual:
292  return TimeOffset::forMinutes(mStdOffsetMinutes + mDstOffsetMinutes);
293 
294  default:
295  return getBoundZoneProcessor()->getUtcOffset(epochSeconds);
296  }
297  }
298 
304  TimeOffset getDeltaOffset(acetime_t epochSeconds) const {
305  switch (mType) {
306  case kTypeError:
307  case kTypeReserved:
308  return TimeOffset::forError();
309 
310  case kTypeManual:
311  return TimeOffset::forMinutes(mDstOffsetMinutes);
312 
313  default:
314  return getBoundZoneProcessor()->getDeltaOffset(epochSeconds);
315  }
316  }
317 
337  const char* getAbbrev(acetime_t epochSeconds) const {
338  switch (mType) {
339  case kTypeError:
340  case kTypeReserved:
341  return "";
342 
343  case kTypeManual:
344  if (isUtc()) {
345  return "UTC";
346  } else {
347  return (mDstOffsetMinutes != 0) ? "DST" : "STD";
348  }
349 
350  default:
351  return getBoundZoneProcessor()->getAbbrev(epochSeconds);
352  }
353  }
354 
363  switch (mType) {
364  case kTypeError:
365  case kTypeReserved:
366  break;
367 
368  case kTypeManual:
370  ldt,
371  TimeOffset::forMinutes(mStdOffsetMinutes + mDstOffsetMinutes));
372  break;
373 
374  default:
375  odt = getBoundZoneProcessor()->getOffsetDateTime(ldt);
376  break;
377  }
378  return odt;
379  }
380 
386  OffsetDateTime getOffsetDateTime(acetime_t epochSeconds) const {
388  switch (mType) {
389  case kTypeError:
390  case kTypeReserved:
391  break;
392 
393  case kTypeManual:
395  epochSeconds,
396  TimeOffset::forMinutes(mStdOffsetMinutes + mDstOffsetMinutes));
397  break;
398 
399  default:
400  odt = getBoundZoneProcessor()->getOffsetDateTime(epochSeconds);
401  break;
402  }
403  return odt;
404  }
405 
407  bool isUtc() const {
408  if (mType != kTypeManual) return false;
409  return mStdOffsetMinutes == 0 && mDstOffsetMinutes == 0;
410  }
411 
419  bool isDst() const {
420  if (mType != kTypeManual) return false;
421  return mDstOffsetMinutes != 0;
422  }
423 
428  void setStdOffset(TimeOffset stdOffset) {
429  if (mType != kTypeManual) return;
430  mStdOffsetMinutes = stdOffset.toMinutes();
431  }
432 
437  void setDstOffset(TimeOffset dstOffset) {
438  if (mType != kTypeManual) return;
439  mDstOffsetMinutes = dstOffset.toMinutes();
440  }
441 
448  TimeZoneData toTimeZoneData(bool followLink = false) const {
449  TimeZoneData d;
450  switch (mType) {
451  case kTypeError:
452  case kTypeReserved:
453  d.type = TimeZoneData::kTypeError;
454  break;
455 
457  d.stdOffsetMinutes = mStdOffsetMinutes;
458  d.dstOffsetMinutes = mDstOffsetMinutes;
459  d.type = TimeZoneData::kTypeManual;
460  break;
461 
462  default:
463  d.zoneId = getZoneId(followLink);
464  d.type = TimeZoneData::kTypeZoneId;
465  break;
466  }
467  return d;
468  }
469 
479  void printTo(Print& printer, bool followLink = false) const;
480 
499  void printShortTo(Print& printer, bool followLink = false) const;
500 
501  // Use default copy constructor and assignment operator.
502  TimeZone(const TimeZone&) = default;
503  TimeZone& operator=(const TimeZone&) = default;
504 
505  private:
506  friend bool operator==(const TimeZone& a, const TimeZone& b);
507 
514  explicit TimeZone(TimeOffset stdOffset, TimeOffset dstOffset):
515  mType(kTypeManual),
516  mStdOffsetMinutes(stdOffset.toMinutes()),
517  mDstOffsetMinutes(dstOffset.toMinutes()) {}
518 
520  explicit TimeZone(uint8_t type):
521  mType(type) {}
522 
524  explicit TimeZone(
525  uint8_t type,
526  uintptr_t zoneKey,
527  ZoneProcessor* zoneProcessor
528  ):
529  mType(type),
530  mZoneKey(zoneKey),
531  mZoneProcessor(zoneProcessor)
532  {}
533 
541  ZoneProcessor* getBoundZoneProcessor() const {
543  return mZoneProcessor;
544  }
545 
546  uint8_t mType;
547 
548  // 3 combinations:
549  // (kTypeError)
550  // (kTypeManual, mStdOffsetMinutes, mDstOffsetMinutes)
551  // (type, mZoneKey, mZoneProcessor)
552  union {
554  struct {
555  int16_t mStdOffsetMinutes;
556  int16_t mDstOffsetMinutes;
557  };
558 
559  /* Used by kTypeBasic and kTypeExtended. */
560  struct {
571  uintptr_t mZoneKey;
572 
578  };
579  };
580 };
581 
582 inline bool operator==(const TimeZone& a, const TimeZone& b) {
583  if (a.mType != b.mType) return false;
584  switch (a.mType) {
587  return true;
588 
590  return a.mStdOffsetMinutes == b.mStdOffsetMinutes
591  && a.mDstOffsetMinutes == b.mDstOffsetMinutes;
592 
593  default:
594  return (a.mZoneKey == b.mZoneKey);
595  }
596 }
597 
598 inline bool operator!=(const TimeZone& a, const TimeZone& b) {
599  return ! (a == b);
600 }
601 
602 }
603 
604 #endif
ace_time::TimeZone::toTimeZoneData
TimeZoneData toTimeZoneData(bool followLink=false) const
Convert to a TimeZoneData object, which can be fed back into ZoneManager::createForTimeZoneData() to ...
Definition: TimeZone.h:448
ace_time::TimeZone::mZoneKey
uintptr_t mZoneKey
An opaque zone key.
Definition: TimeZone.h:571
ace_time::TimeZone::forZoneInfo
static TimeZone forZoneInfo(const basic::ZoneInfo *zoneInfo, BasicZoneProcessor *zoneProcessor)
Convenience factory method to create from a zoneInfo and an associated BasicZoneProcessor.
Definition: TimeZone.h:173
ace_time::TimeZone::forUtc
static TimeZone forUtc()
Factory method to create a UTC TimeZone.
Definition: TimeZone.h:97
ace_time::TimeZone::mZoneProcessor
ZoneProcessor * mZoneProcessor
An instance of a ZoneProcessor, for example, BasicZoneProcessor or ExtendedZoneProcessor.
Definition: TimeZone.h:577
ace_time::LocalDateTime
Class that holds the date-time as the components (year, month, day, hour, minute, second) without reg...
Definition: LocalDateTime.h:31
ace_time::TimeOffset::forError
static TimeOffset forError()
Return an error indicator.
Definition: TimeOffset.h:105
ace_time::ZoneProcessor::setZoneKey
virtual void setZoneKey(uintptr_t zoneKey)=0
Set the opaque zoneKey of this object to a new value, reseting any internally cached information.
ace_time::TimeZone::isUtc
bool isUtc() const
Return true if UTC (+00:00+00:00).
Definition: TimeZone.h:407
ace_time::TimeZone::getOffsetDateTime
OffsetDateTime getOffsetDateTime(acetime_t epochSeconds) const
Return the best estimate of the OffsetDateTime at the given epochSeconds.
Definition: TimeZone.h:386
ace_time::TimeZone::getStdOffset
TimeOffset getStdOffset() const
Return the Standard TimeOffset.
Definition: TimeZone.h:236
ace_time::TimeZone::getType
uint8_t getType() const
Return the type of TimeZone, used to determine the behavior of certain methods at runtime.
Definition: TimeZone.h:233
ace_time::TimeZone::setDstOffset
void setDstOffset(TimeOffset dstOffset)
Sets the dstOffset of the TimeZone.
Definition: TimeZone.h:437
ace_time::TimeZone::kTypeManual
static const uint8_t kTypeManual
Manual STD offset and DST offset.
Definition: TimeZone.h:91
ace_time::ZoneProcessor::getType
uint8_t getType() const
Return the kTypeXxx of the current instance.
Definition: ZoneProcessor.h:44
ace_time::TimeOffset
A thin wrapper that represents a time offset from a reference point, usually 00:00 at UTC,...
Definition: TimeOffset.h:56
ace_time::TimeZone::forHours
static TimeZone forHours(int8_t stdHours, int8_t dstHours=0)
Factory method to create from UTC hour offset and optional DST hour offset.
Definition: TimeZone.h:127
ace_time::TimeZone::forError
static TimeZone forError()
Return a TimeZone representing an error condition.
Definition: TimeZone.h:216
ace_time::ZoneProcessor::getDeltaOffset
virtual TimeOffset getDeltaOffset(acetime_t epochSeconds) const =0
Return the DST delta offset at epochSeconds.
ace_time::TimeZone::getUtcOffset
TimeOffset getUtcOffset(acetime_t epochSeconds) const
Return the total UTC offset at epochSeconds, including DST offset.
Definition: TimeZone.h:285
ace_time::TimeOffset::toMinutes
int16_t toMinutes() const
Return the time offset as minutes.
Definition: TimeOffset.h:111
ace_time::TimeZone::setStdOffset
void setStdOffset(TimeOffset stdOffset)
Sets the stdOffset of the TimeZone.
Definition: TimeZone.h:428
ace_time::ExtendedZoneProcessor
A specific implementation of ExtendedZoneProcessorTemplate that uses ZoneXxxBrokers which read from z...
Definition: ExtendedZoneProcessor.h:2156
ace_time::TimeZone::getOffsetDateTime
OffsetDateTime getOffsetDateTime(const LocalDateTime &ldt) const
Return the best estimate of the OffsetDateTime at the given LocalDateTime for the current TimeZone.
Definition: TimeZone.h:361
ace_time::ZoneProcessor::isLink
virtual bool isLink() const =0
Return true if timezone is a Link entry pointing to a Zone entry.
ace_time::TimeZone::isError
bool isError() const
Return true if TimeZone is an error.
Definition: TimeZone.h:280
ace_time::OffsetDateTime
The date (year, month, day), time (hour, minute, second) and offset from UTC (timeOffset).
Definition: OffsetDateTime.h:33
ace_time::ZoneProcessor::getAbbrev
virtual const char * getAbbrev(acetime_t epochSeconds) const =0
Return the time zone abbreviation at epochSeconds.
ace_time::TimeZone::getAbbrev
const char * getAbbrev(acetime_t epochSeconds) const
Return the time zone abbreviation at the given epochSeconds.
Definition: TimeZone.h:337
ace_time::ZoneProcessor
Base interface for ZoneProcessor classes.
Definition: ZoneProcessor.h:41
ace_time::OffsetDateTime::forError
static OffsetDateTime forError()
Factory method that returns an instance whose isError() is true.
Definition: OffsetDateTime.h:179
ace_time::TimeZone::isDst
bool isDst() const
Return if mDstOffsetMinutes is not zero.
Definition: TimeZone.h:419
ace_time::TimeZone::forZoneInfo
static TimeZone forZoneInfo(const extended::ZoneInfo *zoneInfo, ExtendedZoneProcessor *zoneProcessor)
Convenience factory method to create from a zoneInfo and an associated ExtendedZoneProcessor.
Definition: TimeZone.h:192
ace_time::TimeZone::getZoneId
uint32_t getZoneId(bool followLink=false) const
Return the zoneId for kTypeBasic, kTypeExtended.
Definition: TimeZone.h:267
ace_time::ZoneProcessor::getUtcOffset
virtual TimeOffset getUtcOffset(acetime_t epochSeconds) const =0
Return the total UTC offset at epochSeconds, including DST offset.
ace_time::TimeZone::kTypeReserved
static const uint8_t kTypeReserved
Reserved for future use.
Definition: TimeZone.h:94
ace_time::TimeOffset::forHourMinute
static TimeOffset forHourMinute(int8_t hour, int8_t minute)
Create TimeOffset from (hour, minute) offset.
Definition: TimeOffset.h:77
ace_time::TimeZone::kTypeError
static const uint8_t kTypeError
A TimeZone that represents an invalid condition.
Definition: TimeZone.h:88
ace_time::TimeOffset::forMinutes
static TimeOffset forMinutes(int16_t minutes)
Create TimeOffset from minutes from 00:00.
Definition: TimeOffset.h:83
ace_time::TimeZone::printTo
void printTo(Print &printer, bool followLink=false) const
Print the text representation of the time zone using the full canonical time zone name or UTC offset ...
Definition: TimeZone.cpp:11
ace_time::TimeZone::forHourMinute
static TimeZone forHourMinute(int8_t stdHour, int8_t stdMinute, int8_t dstHour=0, int8_t dstMinute=0)
Factory method to create from UTC (hour, minute) pair and optional DST (hour, minute) pair.
Definition: TimeZone.h:153
ace_time::TimeZone::printShortTo
void printShortTo(Print &printer, bool followLink=false) const
Print the short human readable representation of the time zone.
Definition: TimeZone.cpp:33
ace_time::TimeZoneData
Data structure that captures the internal state of a TimeZone object with enough information so that ...
Definition: TimeZoneData.h:38
ace_time::ZoneProcessor::getZoneId
virtual uint32_t getZoneId(bool followLink=false) const =0
Return the unique stable zoneId.
ace_time::OffsetDateTime::forLocalDateTimeAndOffset
static OffsetDateTime forLocalDateTimeAndOffset(const LocalDateTime &localDateTime, TimeOffset timeOffset)
Factory method from LocalDateTime and TimeOffset.
Definition: OffsetDateTime.h:37
ace_time::TimeZone::isLink
bool isLink() const
Return true if timezone is a Link entry pointing to a Zone entry.
Definition: TimeZone.h:246
ace_time::TimeOffset::forHours
static TimeOffset forHours(int8_t hours)
Create TimeOffset with the corresponding hour offset.
Definition: TimeOffset.h:65
ace_time::TimeZone::forMinutes
static TimeZone forMinutes(int8_t stdMinutes, int8_t dstMinutes=0)
Factory method to create from UTC minute offset and optional DST minute offset.
Definition: TimeZone.h:140
ace_time::TimeZone
Class that describes a time zone.
Definition: TimeZone.h:85
ace_time::TimeZone::forTimeOffset
static TimeZone forTimeOffset(TimeOffset stdOffset, TimeOffset dstOffset=TimeOffset())
Factory method to create from a UTC offset and an optional DST offset.
Definition: TimeZone.h:114
ace_time::BasicZoneProcessor
A specific implementation of BasicZoneProcessorTemplate that uses ZoneXxxBrokers which read from zone...
Definition: BasicZoneProcessor.h:1022
ace_time::TimeZoneData::zoneId
uint32_t zoneId
Both TimeZone::kTypeBasic and TimeZone::kTypeExtended are mapped to a TimeZoneData::kTypeZoneId.
Definition: TimeZoneData.h:78
ace_time::ZoneProcessor::getOffsetDateTime
virtual OffsetDateTime getOffsetDateTime(const LocalDateTime &ldt) const =0
Return the best estimate of the OffsetDateTime at the given LocalDateTime for the timezone of the cur...
ace_time::TimeZone::getDeltaOffset
TimeOffset getDeltaOffset(acetime_t epochSeconds) const
Return the DST offset from standard UTC offset at epochSeconds.
Definition: TimeZone.h:304
ace_time::TimeZone::getDstOffset
TimeOffset getDstOffset() const
Return the DST TimeOffset.
Definition: TimeZone.h:241
ace_time::TimeZone::TimeZone
TimeZone()
Default constructor creates a UTC TimeZone.
Definition: TimeZone.h:221
ace_time::TimeZone::forZoneKey
static TimeZone forZoneKey(uintptr_t zoneKey, ZoneProcessor *processor)
Factory method to create from a generic zoneKey and a generic zoneProcessor.
Definition: TimeZone.h:208
ace_time::OffsetDateTime::forEpochSeconds
static OffsetDateTime forEpochSeconds(acetime_t epochSeconds, TimeOffset timeOffset, uint8_t fold=0)
Factory method.
Definition: OffsetDateTime.h:75