AceTime  1.1.2
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 template<typename ZI, typename ZR, typename ZSC> class ZoneManager;
22 
82 class TimeZone {
83  public:
84  static const uint8_t kTypeError = 0;
85  static const uint8_t kTypeManual = 1;
86  static const uint8_t kTypeBasic = ZoneProcessor::kTypeBasic;
87  static const uint8_t kTypeExtended = ZoneProcessor::kTypeExtended;
88  static const uint8_t kTypeBasicManaged =
89  ZoneProcessorCache::kTypeBasicManaged;
90  static const uint8_t kTypeExtendedManaged =
91  ZoneProcessorCache::kTypeExtendedManaged;
92 
94  static TimeZone forUtc() {
95  return TimeZone();
96  }
97 
105  TimeOffset dstOffset = TimeOffset()) {
106  return TimeZone(stdOffset, dstOffset);
107  }
108 
117  static TimeZone forZoneInfo(const basic::ZoneInfo* zoneInfo,
118  BasicZoneProcessor* zoneProcessor) {
119  return TimeZone(kTypeBasic, zoneInfo, zoneProcessor);
120  }
121 
130  static TimeZone forZoneInfo(const extended::ZoneInfo* zoneInfo,
131  ExtendedZoneProcessor* zoneProcessor) {
132  return TimeZone(kTypeExtended, zoneInfo, zoneProcessor);
133  }
134 
139  static TimeZone forError() {
140  return TimeZone(kTypeError);
141  }
142 
145  mType(kTypeManual),
146  mStdOffsetMinutes(0),
147  mDstOffsetMinutes(0) {}
148 
153  uint8_t getType() const { return mType; }
154 
157  return TimeOffset::forMinutes(mStdOffsetMinutes);
158  }
159 
162  return TimeOffset::forMinutes(mDstOffsetMinutes);
163  }
164 
171  uint32_t getZoneId() const {
172  switch (mType) {
173  case kTypeManual:
174  return 0;
175  case kTypeBasic:
176  case kTypeBasicManaged:
177  return BasicZone((const basic::ZoneInfo*) mZoneInfo).zoneId();
178  case kTypeExtended:
179  case kTypeExtendedManaged:
180  return ExtendedZone((const extended::ZoneInfo*) mZoneInfo).zoneId();
181  }
182  return 0;
183  }
184 
186  bool isError() const { return mType == kTypeError; }
187 
191  TimeOffset getUtcOffset(acetime_t epochSeconds) const {
192  switch (mType) {
193  case kTypeManual:
194  return TimeOffset::forMinutes(mStdOffsetMinutes + mDstOffsetMinutes);
195  case kTypeBasic:
196  case kTypeExtended:
198  return mZoneProcessor->getUtcOffset(epochSeconds);
199  case kTypeBasicManaged:
200  case kTypeExtendedManaged:
201  {
202  ZoneProcessor* processor =
204  if (! processor) break;
205  return processor->getUtcOffset(epochSeconds);
206  }
207  }
208  return TimeOffset::forError();
209  }
210 
216  TimeOffset getDeltaOffset(acetime_t epochSeconds) const {
217  switch (mType) {
218  case kTypeManual:
219  return TimeOffset::forMinutes(mDstOffsetMinutes);
220  case kTypeBasic:
221  case kTypeExtended:
223  return mZoneProcessor->getDeltaOffset(epochSeconds);
224  case kTypeBasicManaged:
225  case kTypeExtendedManaged:
226  {
227  ZoneProcessor* processor =
229  if (! processor) break;
230  return processor->getDeltaOffset(epochSeconds);
231  }
232  }
233  return TimeOffset::forError();
234  }
235 
256  const char* getAbbrev(acetime_t epochSeconds) const {
257  switch (mType) {
258  case kTypeManual:
259  if (isUtc()) {
260  return "UTC";
261  } else {
262  return (mDstOffsetMinutes != 0) ? "DST" : "STD";
263  }
264  case kTypeBasic:
265  case kTypeExtended:
266  return mZoneProcessor->getAbbrev(epochSeconds);
267  case kTypeBasicManaged:
268  case kTypeExtendedManaged:
269  {
270  ZoneProcessor* processor =
272  if (! processor) break;
273  return processor->getAbbrev(epochSeconds);
274  }
275  }
276  return "";
277  }
278 
287  switch (mType) {
288  case kTypeManual:
290  TimeOffset::forMinutes(mStdOffsetMinutes + mDstOffsetMinutes));
291  break;
292  case kTypeBasic:
293  case kTypeExtended:
295  odt = mZoneProcessor->getOffsetDateTime(ldt);
296  break;
297  case kTypeBasicManaged:
298  case kTypeExtendedManaged:
299  {
300  ZoneProcessor* processor =
302  if (! processor) break;
303  odt = processor->getOffsetDateTime(ldt);
304  break;
305  }
306  }
307  return odt;
308  }
309 
311  bool isUtc() const {
312  if (mType != kTypeManual) return false;
313  return mStdOffsetMinutes == 0 && mDstOffsetMinutes == 0;
314  }
315 
323  bool isDst() const {
324  if (mType != kTypeManual) return false;
325  return mDstOffsetMinutes != 0;
326  }
327 
332  void setStdOffset(TimeOffset stdOffset) {
333  if (mType != kTypeManual) return;
334  mStdOffsetMinutes = stdOffset.toMinutes();
335  }
336 
341  void setDstOffset(TimeOffset dstOffset) {
342  if (mType != kTypeManual) return;
343  mDstOffsetMinutes = dstOffset.toMinutes();
344  }
345 
353  TimeZoneData d;
354  switch (mType) {
355  case TimeZone::kTypeManual:
356  d.stdOffsetMinutes = mStdOffsetMinutes;
357  d.dstOffsetMinutes = mDstOffsetMinutes;
358  d.type = TimeZoneData::kTypeManual;
359  break;
360  case TimeZone::kTypeBasic:
361  case TimeZone::kTypeExtended:
362  case TimeZone::kTypeBasicManaged:
363  case TimeZone::kTypeExtendedManaged:
364  d.zoneId = getZoneId();
365  d.type = TimeZoneData::kTypeZoneId;
366  break;
367  default:
368  d.type = TimeZoneData::kTypeError;
369  break;
370  }
371  return d;
372  }
373 
381  void printTo(Print& printer) const;
382 
389  void printShortTo(Print& printer) const;
390 
391  // Use default copy constructor and assignment operator.
392  TimeZone(const TimeZone&) = default;
393  TimeZone& operator=(const TimeZone&) = default;
394 
395  private:
396  friend bool operator==(const TimeZone& a, const TimeZone& b);
397 
398  // Allow ZoneManager to access the TimeZone() constructor that accepts
399  // a ZoneProcessorCache.
400  template<typename ZI, typename ZR, typename ZSC> friend class ZoneManager;
401 
409  explicit TimeZone(const void* zoneInfo,
410  ZoneProcessorCache* zoneProcessorCache):
411  mType(zoneProcessorCache->getType()),
412  mZoneInfo(zoneInfo),
413  mZoneProcessorCache(zoneProcessorCache) {}
414 
421  explicit TimeZone(TimeOffset stdOffset, TimeOffset dstOffset):
422  mType(kTypeManual),
423  mStdOffsetMinutes(stdOffset.toMinutes()),
424  mDstOffsetMinutes(dstOffset.toMinutes()) {}
425 
427  explicit TimeZone(uint8_t type):
428  mType(type) {}
429 
431  explicit TimeZone(uint8_t type, const void* zoneInfo,
432  ZoneProcessor* mZoneProcessor):
433  mType(type),
434  mZoneInfo(zoneInfo),
436 
437  uint8_t mType;
438 
439  // 4 combinations:
440  // (type) (kTypeError)
441  // (type, mStdOffsetMinutes, mDstOffsetMinutes)
442  // (type, mZoneInfo, mZoneProcessor)
443  // (type, mZoneInfo, mZoneProcessorCache)
444  union {
446  struct {
447  int16_t mStdOffsetMinutes;
448  int16_t mDstOffsetMinutes;
449  };
450 
451  struct {
456  const void* mZoneInfo;
457 
458  union {
461 
464  };
465  };
466  };
467 };
468 
469 inline bool operator==(const TimeZone& a, const TimeZone& b) {
470  if (a.mType != b.mType) return false;
471  switch (a.mType) {
472  case TimeZone::kTypeError:
473  return true;
474  case TimeZone::kTypeManual:
475  return a.mStdOffsetMinutes == b.mStdOffsetMinutes
476  && a.mDstOffsetMinutes == b.mDstOffsetMinutes;
477  case TimeZone::kTypeBasic:
478  case TimeZone::kTypeExtended:
479  case TimeZone::kTypeBasicManaged:
480  case TimeZone::kTypeExtendedManaged:
481  return (a.mZoneInfo == b.mZoneInfo);
482  default:
483  return false;
484  }
485 }
486 
487 inline bool operator!=(const TimeZone& a, const TimeZone& b) {
488  return ! (a == b);
489 }
490 
491 }
492 
493 #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:117
ace_time::TimeZone::printTo
void printTo(Print &printer) const
Print the human readable representation of the time zone.
Definition: TimeZone.cpp:12
ace_time::TimeZone::forUtc
static TimeZone forUtc()
Factory method to create a UTC TimeZone.
Definition: TimeZone.h:94
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:460
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:27
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:311
ace_time::TimeZone::mZoneInfo
const void * mZoneInfo
Used by kTypeBasic, kTypeExtended, kTypeBasicManaged, kTypeExtendedManaged.
Definition: TimeZone.h:456
ace_time::TimeZone::getStdOffset
TimeOffset getStdOffset() const
Return the Standard TimeOffset.
Definition: TimeZone.h:156
ace_time::TimeZone::getType
uint8_t getType() const
Return the type of TimeZone.
Definition: TimeZone.h:153
ace_time::TimeZone::setDstOffset
void setDstOffset(TimeOffset dstOffset)
Sets the dstOffset of the TimeZone.
Definition: TimeZone.h:341
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:139
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:191
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:39
ace_time::TimeZone::setStdOffset
void setStdOffset(TimeOffset stdOffset)
Sets the stdOffset of the TimeZone.
Definition: TimeZone.h:332
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:285
ace_time::TimeZone::isError
bool isError() const
Return true if TimeZone is an error.
Definition: TimeZone.h:186
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:256
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:352
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:323
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:130
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:171
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:463
ace_time::ZoneManager
Returns the TimeZone given the zoneInfo, zoneName, or zoneId.
Definition: TimeZone.h:21
ace_time::TimeZoneData
Data structure that captures the internal state of a TimeZone object with enough information so that ...
Definition: TimeZoneData.h:27
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
Class that describes a time zone.
Definition: TimeZone.h:82
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:104
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:45
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:216
ace_time::TimeZone::getDstOffset
TimeOffset getDstOffset() const
Return the DST TimeOffset.
Definition: TimeZone.h:161
ace_time::TimeZone::TimeZone
TimeZone()
Default constructor creates a UTC TimeZone.
Definition: TimeZone.h:144