AceTime  1.3
Date and time classes for Arduino that support timezones from the TZ Database, and a system clock that can synchronize from an NTP server or an RTC chip.
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>
10 #include "TimeOffset.h"
11 #include "ZoneProcessor.h"
12 #include "ZoneProcessorCache.h"
13 #include "BasicZone.h"
14 #include "ExtendedZone.h"
15 #include "TimeZoneData.h"
16 
17 class Print;
18 
19 namespace ace_time {
20 
21 // Allow ZoneManager to access the TimeZone() constructor that accepts
22 // a ZoneProcessorCache.
23 template<typename ZI, typename ZR, typename ZSC> class ZoneManagerImpl;
24 
84 class TimeZone {
85  public:
86  static const uint8_t kTypeError = 0;
87  static const uint8_t kTypeManual = 1;
88  static const uint8_t kTypeBasic = ZoneProcessor::kTypeBasic;
89  static const uint8_t kTypeExtended = ZoneProcessor::kTypeExtended;
90  static const uint8_t kTypeBasicManaged =
91  ZoneProcessorCache::kTypeBasicManaged;
92  static const uint8_t kTypeExtendedManaged =
93  ZoneProcessorCache::kTypeExtendedManaged;
94 
96  static TimeZone forUtc() {
97  return TimeZone();
98  }
99 
107  TimeOffset dstOffset = TimeOffset()) {
108  return TimeZone(stdOffset, dstOffset);
109  }
110 
119  static TimeZone forZoneInfo(const basic::ZoneInfo* zoneInfo,
120  BasicZoneProcessor* zoneProcessor) {
121  return TimeZone(kTypeBasic, zoneInfo, zoneProcessor);
122  }
123 
132  static TimeZone forZoneInfo(const extended::ZoneInfo* zoneInfo,
133  ExtendedZoneProcessor* zoneProcessor) {
134  return TimeZone(kTypeExtended, zoneInfo, zoneProcessor);
135  }
136 
141  static TimeZone forError() {
142  return TimeZone(kTypeError);
143  }
144 
147  mType(kTypeManual),
148  mStdOffsetMinutes(0),
149  mDstOffsetMinutes(0) {}
150 
155  uint8_t getType() const { return mType; }
156 
159  return TimeOffset::forMinutes(mStdOffsetMinutes);
160  }
161 
164  return TimeOffset::forMinutes(mDstOffsetMinutes);
165  }
166 
173  uint32_t getZoneId() const {
174  switch (mType) {
175  case kTypeManual:
176  return 0;
177  case kTypeBasic:
178  case kTypeBasicManaged:
179  return BasicZone((const basic::ZoneInfo*) mZoneInfo).zoneId();
180  case kTypeExtended:
181  case kTypeExtendedManaged:
182  return ExtendedZone((const extended::ZoneInfo*) mZoneInfo).zoneId();
183  }
184  return 0;
185  }
186 
188  bool isError() const { return mType == kTypeError; }
189 
193  TimeOffset getUtcOffset(acetime_t epochSeconds) const {
194  switch (mType) {
195  case kTypeManual:
196  return TimeOffset::forMinutes(mStdOffsetMinutes + mDstOffsetMinutes);
197  case kTypeBasic:
198  case kTypeExtended:
200  return mZoneProcessor->getUtcOffset(epochSeconds);
201  case kTypeBasicManaged:
202  case kTypeExtendedManaged:
203  {
204  ZoneProcessor* processor =
206  if (! processor) break;
207  return processor->getUtcOffset(epochSeconds);
208  }
209  }
210  return TimeOffset::forError();
211  }
212 
218  TimeOffset getDeltaOffset(acetime_t epochSeconds) const {
219  switch (mType) {
220  case kTypeManual:
221  return TimeOffset::forMinutes(mDstOffsetMinutes);
222  case kTypeBasic:
223  case kTypeExtended:
225  return mZoneProcessor->getDeltaOffset(epochSeconds);
226  case kTypeBasicManaged:
227  case kTypeExtendedManaged:
228  {
229  ZoneProcessor* processor =
231  if (! processor) break;
232  return processor->getDeltaOffset(epochSeconds);
233  }
234  }
235  return TimeOffset::forError();
236  }
237 
258  const char* getAbbrev(acetime_t epochSeconds) const {
259  switch (mType) {
260  case kTypeManual:
261  if (isUtc()) {
262  return "UTC";
263  } else {
264  return (mDstOffsetMinutes != 0) ? "DST" : "STD";
265  }
266  case kTypeBasic:
267  case kTypeExtended:
268  return mZoneProcessor->getAbbrev(epochSeconds);
269  case kTypeBasicManaged:
270  case kTypeExtendedManaged:
271  {
272  ZoneProcessor* processor =
274  if (! processor) break;
275  return processor->getAbbrev(epochSeconds);
276  }
277  }
278  return "";
279  }
280 
289  switch (mType) {
290  case kTypeManual:
292  TimeOffset::forMinutes(mStdOffsetMinutes + mDstOffsetMinutes));
293  break;
294  case kTypeBasic:
295  case kTypeExtended:
297  odt = mZoneProcessor->getOffsetDateTime(ldt);
298  break;
299  case kTypeBasicManaged:
300  case kTypeExtendedManaged:
301  {
302  ZoneProcessor* processor =
304  if (! processor) break;
305  odt = processor->getOffsetDateTime(ldt);
306  break;
307  }
308  }
309  return odt;
310  }
311 
313  bool isUtc() const {
314  if (mType != kTypeManual) return false;
315  return mStdOffsetMinutes == 0 && mDstOffsetMinutes == 0;
316  }
317 
325  bool isDst() const {
326  if (mType != kTypeManual) return false;
327  return mDstOffsetMinutes != 0;
328  }
329 
334  void setStdOffset(TimeOffset stdOffset) {
335  if (mType != kTypeManual) return;
336  mStdOffsetMinutes = stdOffset.toMinutes();
337  }
338 
343  void setDstOffset(TimeOffset dstOffset) {
344  if (mType != kTypeManual) return;
345  mDstOffsetMinutes = dstOffset.toMinutes();
346  }
347 
355  TimeZoneData d;
356  switch (mType) {
357  case TimeZone::kTypeManual:
358  d.stdOffsetMinutes = mStdOffsetMinutes;
359  d.dstOffsetMinutes = mDstOffsetMinutes;
360  d.type = TimeZoneData::kTypeManual;
361  break;
362  case TimeZone::kTypeBasic:
363  case TimeZone::kTypeExtended:
364  case TimeZone::kTypeBasicManaged:
365  case TimeZone::kTypeExtendedManaged:
366  d.zoneId = getZoneId();
367  d.type = TimeZoneData::kTypeZoneId;
368  break;
369  default:
370  d.type = TimeZoneData::kTypeError;
371  break;
372  }
373  return d;
374  }
375 
383  void printTo(Print& printer) const;
384 
391  void printShortTo(Print& printer) const;
392 
393  // Use default copy constructor and assignment operator.
394  TimeZone(const TimeZone&) = default;
395  TimeZone& operator=(const TimeZone&) = default;
396 
397  private:
398  friend bool operator==(const TimeZone& a, const TimeZone& b);
399 
400  // Allow ZoneManager to access the TimeZone() constructor that accepts
401  // a ZoneProcessorCache.
402  template<typename ZI, typename ZR, typename ZSC>
403  friend class ZoneManagerImpl;
404 
412  explicit TimeZone(const void* zoneInfo,
413  ZoneProcessorCache* zoneProcessorCache):
414  mType(zoneProcessorCache->getType()),
415  mZoneInfo(zoneInfo),
416  mZoneProcessorCache(zoneProcessorCache) {}
417 
424  explicit TimeZone(TimeOffset stdOffset, TimeOffset dstOffset):
425  mType(kTypeManual),
426  mStdOffsetMinutes(stdOffset.toMinutes()),
427  mDstOffsetMinutes(dstOffset.toMinutes()) {}
428 
430  explicit TimeZone(uint8_t type):
431  mType(type) {}
432 
434  explicit TimeZone(uint8_t type, const void* zoneInfo,
435  ZoneProcessor* mZoneProcessor):
436  mType(type),
437  mZoneInfo(zoneInfo),
439 
440  uint8_t mType;
441 
442  // 4 combinations:
443  // (type) (kTypeError)
444  // (type, mStdOffsetMinutes, mDstOffsetMinutes)
445  // (type, mZoneInfo, mZoneProcessor)
446  // (type, mZoneInfo, mZoneProcessorCache)
447  union {
449  struct {
450  int16_t mStdOffsetMinutes;
451  int16_t mDstOffsetMinutes;
452  };
453 
454  struct {
459  const void* mZoneInfo;
460 
461  union {
464 
467  };
468  };
469  };
470 };
471 
472 inline bool operator==(const TimeZone& a, const TimeZone& b) {
473  if (a.mType != b.mType) return false;
474  switch (a.mType) {
475  case TimeZone::kTypeError:
476  return true;
477  case TimeZone::kTypeManual:
478  return a.mStdOffsetMinutes == b.mStdOffsetMinutes
479  && a.mDstOffsetMinutes == b.mDstOffsetMinutes;
480  case TimeZone::kTypeBasic:
481  case TimeZone::kTypeExtended:
482  case TimeZone::kTypeBasicManaged:
483  case TimeZone::kTypeExtendedManaged:
484  return (a.mZoneInfo == b.mZoneInfo);
485  default:
486  return false;
487  }
488 }
489 
490 inline bool operator!=(const TimeZone& a, const TimeZone& b) {
491  return ! (a == b);
492 }
493 
494 }
495 
496 #endif
ace_time::ZoneProcessorCache::getZoneProcessor
virtual ZoneProcessor * getZoneProcessor(const void *zoneInfo)=0
Get ZoneProcessor from either a basic::ZoneInfo or an extended::ZoneInfo.
ace_time::TimeZone::forZoneInfo
static TimeZone forZoneInfo(const basic::ZoneInfo *zoneInfo, BasicZoneProcessor *zoneProcessor)
Factory method to create from a zoneInfo and an associated BasicZoneProcessor.
Definition: TimeZone.h:119
ace_time::TimeZone::printTo
void printTo(Print &printer) const
Print the human readable representation of the time zone.
Definition: TimeZone.cpp:11
ace_time::TimeZone::forUtc
static TimeZone forUtc()
Factory method to create a UTC TimeZone.
Definition: TimeZone.h:96
ace_time::ZoneProcessor::setZoneInfo
virtual void setZoneInfo(const void *zoneInfo)=0
Set the opaque zoneInfo.
ace_time::TimeZone::mZoneProcessor
ZoneProcessor * mZoneProcessor
Used by kTypeBasic, kTypeExtended.
Definition: TimeZone.h:463
ace_time::ZoneProcessor::kTypeBasic
static const uint8_t kTypeBasic
Indicate BasicZoneProcessor.
Definition: ZoneProcessor.h:51
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::TimeOffset::forError
static TimeOffset forError()
Return an error indicator.
Definition: TimeOffset.h:105
ace_time::ZoneProcessor::kTypeExtended
static const uint8_t kTypeExtended
Indicate ExtendedZoneProcessor.
Definition: ZoneProcessor.h:57
ace_time::TimeZone::isUtc
bool isUtc() const
Return true if UTC (+00:00+00:00).
Definition: TimeZone.h:313
ace_time::TimeZone::mZoneInfo
const void * mZoneInfo
Used by kTypeBasic, kTypeExtended, kTypeBasicManaged, kTypeExtendedManaged.
Definition: TimeZone.h:459
ace_time::TimeZone::getStdOffset
TimeOffset getStdOffset() const
Return the Standard TimeOffset.
Definition: TimeZone.h:158
ace_time::TimeZone::getType
uint8_t getType() const
Return the type of TimeZone.
Definition: TimeZone.h:155
ace_time::TimeZone::setDstOffset
void setDstOffset(TimeOffset dstOffset)
Sets the dstOffset of the TimeZone.
Definition: TimeZone.h:343
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::ExtendedZone
A thin wrapper around an extended::ZoneInfo data structure to provide a stable API access to some use...
Definition: ExtendedZone.h:23
ace_time::TimeZone::forError
static TimeZone forError()
Return a TimeZone representing an error condition.
Definition: TimeZone.h:141
ace_time::ZoneProcessor::getDeltaOffset
virtual TimeOffset getDeltaOffset(acetime_t epochSeconds) const =0
Return the DST delta offset at epochSeconds.
ace_time::BasicZone
A thin wrapper around a basic::ZoneInfo data structure to provide a stable API access to some useful ...
Definition: BasicZone.h:22
ace_time::TimeZone::getUtcOffset
TimeOffset getUtcOffset(acetime_t epochSeconds) const
Return the total UTC offset at epochSeconds, including DST offset.
Definition: TimeZone.h:193
ace_time::TimeOffset::toMinutes
int16_t toMinutes() const
Return the time offset as minutes.
Definition: TimeOffset.h:111
ace_time::TimeZone::printShortTo
void printShortTo(Print &printer) const
Print the short human readable representation of the time zone.
Definition: TimeZone.cpp:38
ace_time::TimeZone::setStdOffset
void setStdOffset(TimeOffset stdOffset)
Sets the stdOffset of the TimeZone.
Definition: TimeZone.h:334
ace_time::ExtendedZoneProcessor
An implementation of ZoneProcessor that supports for all zones defined by the TZ Database.
Definition: ExtendedZoneProcessor.h:658
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:287
ace_time::TimeZone::isError
bool isError() const
Return true if TimeZone is an error.
Definition: TimeZone.h:188
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:258
ace_time::ZoneProcessor
Base interface for ZoneProcessor classes.
Definition: ZoneProcessor.h:45
ace_time::TimeZone::toTimeZoneData
TimeZoneData toTimeZoneData() const
Convert to a TimeZoneData object, which can be fed back into ZoneManager::createForTimeZoneData() to ...
Definition: TimeZone.h:354
ace_time::OffsetDateTime::forError
static OffsetDateTime forError()
Factory method that returns an instance whose isError() is true.
Definition: OffsetDateTime.h:146
ace_time::TimeZone::isDst
bool isDst() const
Return if mDstOffsetMinutes is not zero.
Definition: TimeZone.h:325
ace_time::TimeZone::forZoneInfo
static TimeZone forZoneInfo(const extended::ZoneInfo *zoneInfo, ExtendedZoneProcessor *zoneProcessor)
Factory method to create from a zoneInfo and an associated ExtendedZoneProcessor.
Definition: TimeZone.h:132
ace_time::ZoneProcessor::getUtcOffset
virtual TimeOffset getUtcOffset(acetime_t epochSeconds) const =0
Return the total UTC offset at epochSeconds, including DST offset.
ace_time::TimeOffset::forMinutes
static TimeOffset forMinutes(int16_t minutes)
Create TimeOffset from minutes from 00:00.
Definition: TimeOffset.h:83
ace_time::TimeZone::getZoneId
uint32_t getZoneId() const
Return the zoneId for kTypeBasic, kTypeExtended, kTypeBasicManaged, kTypeExtendedManaged.
Definition: TimeZone.h:173
ace_time::ZoneProcessorCache
Common interface to BasicZoneProcessorCache and ExtendedZoneProcessorCache.
Definition: ZoneProcessorCache.h:24
ace_time::TimeZone::mZoneProcessorCache
ZoneProcessorCache * mZoneProcessorCache
Used by kTypeBasicManaged, kTypeExtendedManaged.
Definition: TimeZone.h:466
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::OffsetDateTime::forLocalDateTimeAndOffset
static OffsetDateTime forLocalDateTimeAndOffset(const LocalDateTime &localDateTime, TimeOffset timeOffset)
Factory method from LocalDateTime and TimeOffset.
Definition: OffsetDateTime.h:37
ace_time::ZoneManagerImpl
A templatized implementation of ZoneManager that binds the (Basic|Extended)ZoneRegistrar with the cor...
Definition: TimeZone.h:23
ace_time::TimeZone
Class that describes a time zone.
Definition: TimeZone.h:84
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:106
ace_time::BasicZoneProcessor
An implementation of ZoneProcessor that supports a subset of the zones containing in the TZ Database.
Definition: BasicZoneProcessor.h:204
ace_time::TimeZoneData::zoneId
uint32_t zoneId
All of kTypeBasic, kTypeExtended, kTypeBasicManaged, kTypeExtendedManaged collapse down to a kTypeZon...
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:218
ace_time::TimeZone::getDstOffset
TimeOffset getDstOffset() const
Return the DST TimeOffset.
Definition: TimeZone.h:163
ace_time::TimeZone::TimeZone
TimeZone()
Default constructor creates a UTC TimeZone.
Definition: TimeZone.h:146