AceTime  0.6
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  mStdOffsetCode(0),
147  mDstOffsetCode(0) {}
148 
153  uint8_t getType() const { return mType; }
154 
157  return TimeOffset::forOffsetCode(mStdOffsetCode);
158  }
159 
162  return TimeOffset::forOffsetCode(mDstOffsetCode);
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::forOffsetCode(mStdOffsetCode + mDstOffsetCode);
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::forOffsetCode(mDstOffsetCode);
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 
244  switch (mType) {
245  case kTypeManual:
247  TimeOffset::forOffsetCode(mStdOffsetCode + mDstOffsetCode));
248  break;
249  case kTypeBasic:
250  case kTypeExtended:
252  odt = mZoneProcessor->getOffsetDateTime(ldt);
253  break;
254  case kTypeBasicManaged:
255  case kTypeExtendedManaged:
256  {
257  ZoneProcessor* processor =
259  if (! processor) break;
260  odt = processor->getOffsetDateTime(ldt);
261  break;
262  }
263  }
264  return odt;
265  }
266 
268  bool isUtc() const {
269  if (mType != kTypeManual) return false;
270  return mStdOffsetCode == 0 && mDstOffsetCode == 0;
271  }
272 
280  bool isDst() const {
281  if (mType != kTypeManual) return false;
282  return mDstOffsetCode != 0;
283  }
284 
289  void setStdOffset(TimeOffset stdOffset) {
290  if (mType != kTypeManual) return;
291  mStdOffsetCode = stdOffset.toOffsetCode();
292  }
293 
298  void setDstOffset(TimeOffset dstOffset) {
299  if (mType != kTypeManual) return;
300  mDstOffsetCode = dstOffset.toOffsetCode();
301  }
302 
310  TimeZoneData d;
311  switch (mType) {
312  case TimeZone::kTypeManual:
313  d.stdOffsetCode = mStdOffsetCode;
314  d.dstOffsetCode = mDstOffsetCode;
315  d.type = TimeZoneData::kTypeManual;
316  break;
317  case TimeZone::kTypeBasic:
318  case TimeZone::kTypeExtended:
319  case TimeZone::kTypeBasicManaged:
320  case TimeZone::kTypeExtendedManaged:
321  d.zoneId = getZoneId();
322  d.type = TimeZoneData::kTypeZoneId;
323  break;
324  default:
325  d.type = TimeZoneData::kTypeError;
326  break;
327  }
328  return d;
329  }
330 
338  void printTo(Print& printer) const;
339 
346  void printShortTo(Print& printer) const;
347 
354  void printAbbrevTo(Print& printer, acetime_t epochSeconds) const;
355 
356  // Use default copy constructor and assignment operator.
357  TimeZone(const TimeZone&) = default;
358  TimeZone& operator=(const TimeZone&) = default;
359 
360  private:
361  friend bool operator==(const TimeZone& a, const TimeZone& b);
362 
363  // Allow ZoneManager to access the TimeZone() constructor that accepts
364  // a ZoneProcessorCache.
365  template<typename ZI, typename ZR, typename ZSC> friend class ZoneManager;
366 
374  explicit TimeZone(const void* zoneInfo,
375  ZoneProcessorCache* zoneProcessorCache):
376  mType(zoneProcessorCache->getType()),
377  mZoneInfo(zoneInfo),
378  mZoneProcessorCache(zoneProcessorCache) {}
379 
386  explicit TimeZone(TimeOffset stdOffset, TimeOffset dstOffset):
387  mType(kTypeManual),
388  mStdOffsetCode(stdOffset.toOffsetCode()),
389  mDstOffsetCode(dstOffset.toOffsetCode()) {}
390 
392  explicit TimeZone(uint8_t type):
393  mType(type) {}
394 
396  explicit TimeZone(uint8_t type, const void* zoneInfo,
398  mType(type),
399  mZoneInfo(zoneInfo),
400  mZoneProcessor(mZoneProcessor) {}
401 
402  uint8_t mType;
403 
404  // 4 combinations:
405  // (type) (kTypeError)
406  // (type, mStdOffsetCode, mDstOffsetCode)
407  // (type, mZoneInfo, mZoneProcessor)
408  // (type, mZoneInfo, mZoneProcessorCache)
409  union {
411  struct {
412  int8_t mStdOffsetCode;
413  int8_t mDstOffsetCode;
414  };
415 
416  struct {
421  const void* mZoneInfo;
422 
423  union {
426 
429  };
430  };
431  };
432 };
433 
434 inline bool operator==(const TimeZone& a, const TimeZone& b) {
435  if (a.mType != b.mType) return false;
436  switch (a.mType) {
437  case TimeZone::kTypeError:
438  return true;
439  case TimeZone::kTypeManual:
440  return a.mStdOffsetCode == b.mStdOffsetCode
441  && a.mDstOffsetCode == b.mDstOffsetCode;
442  case TimeZone::kTypeBasic:
443  case TimeZone::kTypeExtended:
444  case TimeZone::kTypeBasicManaged:
445  case TimeZone::kTypeExtendedManaged:
446  return (a.mZoneInfo == b.mZoneInfo);
447  default:
448  return false;
449  }
450 }
451 
452 inline bool operator!=(const TimeZone& a, const TimeZone& b) {
453  return ! (a == b);
454 }
455 
456 }
457 
458 #endif
void setDstOffset(TimeOffset dstOffset)
Sets the dstOffset of the TimeZone.
Definition: TimeZone.h:298
static TimeOffset forError()
Return an error indicator.
Definition: TimeOffset.h:110
Base interface for ZoneProcessor classes.
Definition: ZoneProcessor.h:45
virtual TimeOffset getDeltaOffset(acetime_t epochSeconds) const =0
Return the DST delta offset at epochSeconds.
bool isUtc() const
Return true if UTC (+00:00+00:00).
Definition: TimeZone.h:268
static OffsetDateTime forLocalDateTimeAndOffset(const LocalDateTime &localDateTime, TimeOffset timeOffset)
Factory method from LocalDateTime and TimeOffset.
Representation of a given time zone, implemented as an array of ZoneEra records.
Definition: ZoneInfo.h:77
static TimeZone forError()
Return a TimeZone representing an error condition.
Definition: TimeZone.h:139
A thin wrapper around a basic::ZoneInfo data structure to provide a stable API access to some useful ...
Definition: BasicZone.h:22
static const uint8_t kTypeExtended
Indicate ExtendedZoneProcessor.
Definition: ZoneProcessor.h:57
virtual ZoneProcessor * getZoneProcessor(const void *zoneInfo)=0
Get ZoneProcessor from either a basic::ZoneInfo or an extended::ZoneInfo.
bool isDst() const
Return if mDstOffsetCode is not zero.
Definition: TimeZone.h:280
Representation of a given time zone, implemented as an array of ZoneEra records.
Definition: ZoneInfo.h:77
void printShortTo(Print &printer) const
Print the short human readable representation of the time zone.
Definition: TimeZone.cpp:39
OffsetDateTime getOffsetDateTime(const LocalDateTime &ldt) const
Return the best estimate of the OffsetDateTime at the given LocalDateTime for the current TimeZone...
Definition: TimeZone.h:242
static TimeZone forZoneInfo(const basic::ZoneInfo *zoneInfo, BasicZoneProcessor *zoneProcessor)
Factory method to create from a zoneInfo and an associated BasicZoneProcessor.
Definition: TimeZone.h:117
void setStdOffset(TimeOffset stdOffset)
Sets the stdOffset of the TimeZone.
Definition: TimeZone.h:289
const void * mZoneInfo
Used by kTypeBasic, kTypeExtended, kTypeBasicManaged, kTypeExtendedManaged.
Definition: TimeZone.h:421
TimeOffset getDstOffset() const
Return the DST TimeOffset.
Definition: TimeZone.h:161
void printTo(Print &printer) const
Print the human readable representation of the time zone.
Definition: TimeZone.cpp:12
uint32_t getZoneId() const
Return the zoneId for kTypeBasic, kTypeExtended, kTypeBasicManaged, kTypeExtendedManaged.
Definition: TimeZone.h:171
virtual TimeOffset getUtcOffset(acetime_t epochSeconds) const =0
Return the total UTC offset at epochSeconds, including DST offset.
virtual void setZoneInfo(const void *zoneInfo)=0
Set the opaque zoneInfo.
TimeZone()
Default constructor creates a UTC TimeZone.
Definition: TimeZone.h:144
virtual uint8_t getType()=0
Return the type of this cache.
An implementation of ZoneProcessor that works for all zones defined by the TZ Database (with some zon...
Returns the TimeZone given the zoneInfo, zoneName, or zoneId.
Definition: TimeZone.h:21
static TimeZone forUtc()
Factory method to create a UTC TimeZone.
Definition: TimeZone.h:94
A thin wrapper around an extended::ZoneInfo data structure to provide a stable API access to some use...
Definition: ExtendedZone.h:23
An implementation of ZoneProcessor that supports a subset of the zones containing in the TZ Database...
static TimeOffset forOffsetCode(int8_t offsetCode)
Create TimeOffset from the offset code.
Definition: TimeOffset.h:117
static TimeZone forZoneInfo(const extended::ZoneInfo *zoneInfo, ExtendedZoneProcessor *zoneProcessor)
Factory method to create from a zoneInfo and an associated ExtendedZoneProcessor. ...
Definition: TimeZone.h:130
The date (year, month, day), time (hour, minute, second) and offset from UTC (timeOffset).
A thin wrapper that represents a time offset from a reference point, usually 00:00 at UTC...
Definition: TimeOffset.h:58
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
Common interface to BasicZoneProcessorCache and ExtendedZoneProcessorCache.
Class that describes a time zone.
Definition: TimeZone.h:82
TimeZoneData toTimeZoneData() const
Convert to a TimeZoneData object, which can be fed back into ZoneManager::createForTimeZoneData() to ...
Definition: TimeZone.h:309
Data structure that captures the internal state of a TimeZone object with enough information so that ...
Definition: TimeZoneData.h:20
uint8_t getType() const
Return the type of TimeZone.
Definition: TimeZone.h:153
int8_t toOffsetCode() const
Return the time offset as the number of 15 minute increments.
Definition: TimeOffset.h:125
TimeOffset getStdOffset() const
Return the Standard TimeOffset.
Definition: TimeZone.h:156
void printAbbrevTo(Print &printer, acetime_t epochSeconds) const
Print the time zone abbreviation for the given epochSeconds.
Definition: TimeZone.cpp:70
ZoneProcessor * mZoneProcessor
Used by kTypeBasic, kTypeExtended.
Definition: TimeZone.h:425
static const uint8_t kTypeBasic
Indicate BasicZoneProcessor.
Definition: ZoneProcessor.h:51
bool isError() const
Return true if TimeZone is an error.
Definition: TimeZone.h:186
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...
ZoneProcessorCache * mZoneProcessorCache
Used by kTypeBasicManaged, kTypeExtendedManaged.
Definition: TimeZone.h:428
static OffsetDateTime forError()
Factory method that returns an instance whose isError() is true.
uint32_t zoneId
All of kTypeBasic, kTypeExtended, kTypeBasicManaged, kTypeExtendedManaged collapse down to a kTypeZon...
Definition: TimeZoneData.h:38
Class that holds the date-time as the components (year, month, day, hour, minute, second) without reg...
Definition: LocalDateTime.h:27
TimeOffset getUtcOffset(acetime_t epochSeconds) const
Return the total UTC offset at epochSeconds, including DST offset.
Definition: TimeZone.h:191
TimeOffset getDeltaOffset(acetime_t epochSeconds) const
Return the DST offset from standard UTC offset at epochSeconds.
Definition: TimeZone.h:216