AceTime  0.7
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 
244  switch (mType) {
245  case kTypeManual:
247  TimeOffset::forMinutes(mStdOffsetMinutes + mDstOffsetMinutes));
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 mStdOffsetMinutes == 0 && mDstOffsetMinutes == 0;
271  }
272 
280  bool isDst() const {
281  if (mType != kTypeManual) return false;
282  return mDstOffsetMinutes != 0;
283  }
284 
289  void setStdOffset(TimeOffset stdOffset) {
290  if (mType != kTypeManual) return;
291  mStdOffsetMinutes = stdOffset.toMinutes();
292  }
293 
298  void setDstOffset(TimeOffset dstOffset) {
299  if (mType != kTypeManual) return;
300  mDstOffsetMinutes = dstOffset.toMinutes();
301  }
302 
310  TimeZoneData d;
311  switch (mType) {
312  case TimeZone::kTypeManual:
313  d.stdOffsetMinutes = mStdOffsetMinutes;
314  d.dstOffsetMinutes = mDstOffsetMinutes;
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  mStdOffsetMinutes(stdOffset.toMinutes()),
389  mDstOffsetMinutes(dstOffset.toMinutes()) {}
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, mStdOffsetMinutes, mDstOffsetMinutes)
407  // (type, mZoneInfo, mZoneProcessor)
408  // (type, mZoneInfo, mZoneProcessorCache)
409  union {
411  struct {
412  int16_t mStdOffsetMinutes;
413  int16_t mDstOffsetMinutes;
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.mStdOffsetMinutes == b.mStdOffsetMinutes
441  && a.mDstOffsetMinutes == b.mDstOffsetMinutes;
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:113
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:86
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 mDstOffsetMinutes is not zero.
Definition: TimeZone.h:280
Representation of a given time zone, implemented as an array of ZoneEra records.
Definition: ZoneInfo.h:86
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
int16_t toMinutes() const
Return the time offset as minutes.
Definition: TimeOffset.h:132
virtual uint8_t getType()=0
Return the type of this cache.
An implementation of ZoneProcessor that supports for all zones defined by the TZ Database.
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 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:61
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
static TimeOffset forMinutes(int16_t minutes)
Create TimeOffset from minutes from 00:00.
Definition: TimeOffset.h:91
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:27
uint8_t getType() const
Return the type of TimeZone.
Definition: TimeZone.h:153
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:45
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