AceTime  1.8.0
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> // 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 
250  uint32_t getZoneId() const {
251  switch (mType) {
252  case kTypeError:
253  case kTypeReserved:
254  case kTypeManual:
255  return 0;
256 
257  default:
258  return getBoundZoneProcessor()->getZoneId();
259  }
260  }
261 
263  bool isError() const { return mType == kTypeError; }
264 
268  TimeOffset getUtcOffset(acetime_t epochSeconds) const {
269  switch (mType) {
270  case kTypeError:
271  case kTypeReserved:
272  return TimeOffset::forError();
273 
274  case kTypeManual:
275  return TimeOffset::forMinutes(mStdOffsetMinutes + mDstOffsetMinutes);
276 
277  default:
278  return getBoundZoneProcessor()->getUtcOffset(epochSeconds);
279  }
280  }
281 
287  TimeOffset getDeltaOffset(acetime_t epochSeconds) const {
288  switch (mType) {
289  case kTypeError:
290  case kTypeReserved:
291  return TimeOffset::forError();
292 
293  case kTypeManual:
294  return TimeOffset::forMinutes(mDstOffsetMinutes);
295 
296  default:
297  return getBoundZoneProcessor()->getDeltaOffset(epochSeconds);
298  }
299  }
300 
320  const char* getAbbrev(acetime_t epochSeconds) const {
321  switch (mType) {
322  case kTypeError:
323  case kTypeReserved:
324  return "";
325 
326  case kTypeManual:
327  if (isUtc()) {
328  return "UTC";
329  } else {
330  return (mDstOffsetMinutes != 0) ? "DST" : "STD";
331  }
332 
333  default:
334  return getBoundZoneProcessor()->getAbbrev(epochSeconds);
335  }
336  }
337 
346  switch (mType) {
347  case kTypeError:
348  case kTypeReserved:
349  break;
350 
351  case kTypeManual:
353  TimeOffset::forMinutes(mStdOffsetMinutes + mDstOffsetMinutes));
354  break;
355 
356  default:
357  odt = getBoundZoneProcessor()->getOffsetDateTime(ldt);
358  break;
359  }
360  return odt;
361  }
362 
364  bool isUtc() const {
365  if (mType != kTypeManual) return false;
366  return mStdOffsetMinutes == 0 && mDstOffsetMinutes == 0;
367  }
368 
376  bool isDst() const {
377  if (mType != kTypeManual) return false;
378  return mDstOffsetMinutes != 0;
379  }
380 
385  void setStdOffset(TimeOffset stdOffset) {
386  if (mType != kTypeManual) return;
387  mStdOffsetMinutes = stdOffset.toMinutes();
388  }
389 
394  void setDstOffset(TimeOffset dstOffset) {
395  if (mType != kTypeManual) return;
396  mDstOffsetMinutes = dstOffset.toMinutes();
397  }
398 
406  TimeZoneData d;
407  switch (mType) {
408  case kTypeError:
409  case kTypeReserved:
410  d.type = TimeZoneData::kTypeError;
411  break;
412 
414  d.stdOffsetMinutes = mStdOffsetMinutes;
415  d.dstOffsetMinutes = mDstOffsetMinutes;
416  d.type = TimeZoneData::kTypeManual;
417  break;
418 
419  default:
420  d.zoneId = getZoneId();
421  d.type = TimeZoneData::kTypeZoneId;
422  break;
423  }
424  return d;
425  }
426 
436  void printTo(Print& printer) const;
437 
456  void printShortTo(Print& printer) const;
457 
458  // Use default copy constructor and assignment operator.
459  TimeZone(const TimeZone&) = default;
460  TimeZone& operator=(const TimeZone&) = default;
461 
462  private:
463  friend bool operator==(const TimeZone& a, const TimeZone& b);
464 
471  explicit TimeZone(TimeOffset stdOffset, TimeOffset dstOffset):
472  mType(kTypeManual),
473  mStdOffsetMinutes(stdOffset.toMinutes()),
474  mDstOffsetMinutes(dstOffset.toMinutes()) {}
475 
477  explicit TimeZone(uint8_t type):
478  mType(type) {}
479 
481  explicit TimeZone(
482  uint8_t type,
483  uintptr_t zoneKey,
484  ZoneProcessor* zoneProcessor
485  ):
486  mType(type),
487  mZoneKey(zoneKey),
488  mZoneProcessor(zoneProcessor)
489  {}
490 
498  ZoneProcessor* getBoundZoneProcessor() const {
500  return mZoneProcessor;
501  }
502 
503  uint8_t mType;
504 
505  // 3 combinations:
506  // (kTypeError)
507  // (kTypeManual, mStdOffsetMinutes, mDstOffsetMinutes)
508  // (type, mZoneKey, mZoneProcessor)
509  union {
511  struct {
512  int16_t mStdOffsetMinutes;
513  int16_t mDstOffsetMinutes;
514  };
515 
516  /* Used by kTypeBasic and kTypeExtended. */
517  struct {
528  uintptr_t mZoneKey;
529 
535  };
536  };
537 };
538 
539 inline bool operator==(const TimeZone& a, const TimeZone& b) {
540  if (a.mType != b.mType) return false;
541  switch (a.mType) {
544  return true;
545 
547  return a.mStdOffsetMinutes == b.mStdOffsetMinutes
548  && a.mDstOffsetMinutes == b.mDstOffsetMinutes;
549 
550  default:
551  return (a.mZoneKey == b.mZoneKey);
552  }
553 }
554 
555 inline bool operator!=(const TimeZone& a, const TimeZone& b) {
556  return ! (a == b);
557 }
558 
559 }
560 
561 #endif
ace_time::TimeZone::mZoneKey
uintptr_t mZoneKey
An opaque zone key.
Definition: TimeZone.h:528
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::printTo
void printTo(Print &printer) 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::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:534
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::ZoneProcessor::getZoneId
virtual uint32_t getZoneId() const =0
Return the unique stable zoneId.
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:364
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:394
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:268
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:33
ace_time::TimeZone::setStdOffset
void setStdOffset(TimeOffset stdOffset)
Sets the stdOffset of the TimeZone.
Definition: TimeZone.h:385
ace_time::ExtendedZoneProcessor
A specific implementation of ExtendedZoneProcessorTemplate that uses ZoneXxxBrokers which read from z...
Definition: ExtendedZoneProcessor.h:1964
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:344
ace_time::TimeZone::isError
bool isError() const
Return true if TimeZone is an error.
Definition: TimeZone.h:263
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:320
ace_time::ZoneProcessor
Base interface for ZoneProcessor classes.
Definition: ZoneProcessor.h:41
ace_time::TimeZone::toTimeZoneData
TimeZoneData toTimeZoneData() const
Convert to a TimeZoneData object, which can be fed back into ZoneManager::createForTimeZoneData() to ...
Definition: TimeZone.h:405
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:376
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::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::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::getZoneId
uint32_t getZoneId() const
Return the zoneId for kTypeBasic, kTypeExtended.
Definition: TimeZone.h:250
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::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:993
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:287
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