AceTime  2.2.0
Date and time classes for Arduino that support timezones from the TZ Database.
DateTuple.h
1 /*
2  * MIT License
3  * Copyright (c) 2019 Brian T. Park
4  */
5 
6 #ifndef ACE_TIME_DATE_TUPLE_H
7 #define ACE_TIME_DATE_TUPLE_H
8 
9 #include <stdint.h> // uint8_t
10 #include "common/logging.h"
11 #include "local_date_mutation.h"
12 
13 #ifndef ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG
14 #define ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG 0
15 #endif
16 
17 namespace ace_time {
18 namespace extended {
19 
24 enum class CompareStatus : uint8_t {
25  kFarPast, // 0
26  kPrior, // 1
27  kExactMatch, // 2
28  kWithinMatch, // 3
29  kFarFuture, // 4
30 };
31 
36 struct DateTuple {
37  DateTuple() = default;
38 
39  DateTuple(int16_t y, uint8_t mon, uint8_t d, int16_t min, uint8_t mod):
40  year(y), month(mon), day(d), suffix(mod), minutes(min) {}
41 
42  int16_t year; // [-1,10000]
43  uint8_t month; // [1,12]
44  uint8_t day; // [1,31]
45  uint8_t suffix; // kSuffixS, kSuffixW, kSuffixU
46  int16_t minutes; // negative values allowed
47 
49  void log() const {
50  if (ACE_TIME_EXTENDED_ZONE_PROCESSOR_DEBUG) {
51  int hour = minutes / 60;
52  int minute = minutes - hour * 60;
53  char c = "wsu"[(suffix>>4)];
54  logging::printf("%04d-%02u-%02uT%02d:%02d%c",
55  year, month, day, hour, minute, c);
56  }
57  }
58 };
59 
61 inline bool operator<(const DateTuple& a, const DateTuple& b) {
62  if (a.year < b.year) return true;
63  if (a.year > b.year) return false;
64  if (a.month < b.month) return true;
65  if (a.month > b.month) return false;
66  if (a.day < b.day) return true;
67  if (a.day > b.day) return false;
68  if (a.minutes < b.minutes) return true;
69  if (a.minutes > b.minutes) return false;
70  return false;
71 }
72 
73 inline bool operator>=(const DateTuple& a, const DateTuple& b) {
74  return ! (a < b);
75 }
76 
77 inline bool operator<=(const DateTuple& a, const DateTuple& b) {
78  return ! (b < a);
79 }
80 
81 inline bool operator>(const DateTuple& a, const DateTuple& b) {
82  return (b < a);
83 }
84 
86 inline bool operator==(const DateTuple& a, const DateTuple& b) {
87  return a.year == b.year
88  && a.month == b.month
89  && a.day == b.day
90  && a.minutes == b.minutes
91  && a.suffix == b.suffix;
92 }
93 
95 inline void normalizeDateTuple(DateTuple* dt) {
96  const int16_t kOneDayAsMinutes = 60 * 24;
97  if (dt->minutes <= -kOneDayAsMinutes) {
98  LocalDate ld = LocalDate::forComponents(dt->year, dt->month, dt->day);
99  local_date_mutation::decrementOneDay(ld);
100  dt->year = ld.year();
101  dt->month = ld.month();
102  dt->day = ld.day();
103  dt->minutes += kOneDayAsMinutes;
104  } else if (kOneDayAsMinutes <= dt->minutes) {
105  LocalDate ld = LocalDate::forComponents(dt->year, dt->month, dt->day);
106  local_date_mutation::incrementOneDay(ld);
107  dt->year = ld.year();
108  dt->month = ld.month();
109  dt->day = ld.day();
110  dt->minutes -= kOneDayAsMinutes;
111  } else {
112  // do nothing
113  }
114 }
115 
122 inline acetime_t subtractDateTuple(const DateTuple& a, const DateTuple& b) {
123  int32_t epochDaysA = LocalDate::forComponents(
124  a.year, a.month, a.day).toEpochDays();
125 
126  int32_t epochDaysB = LocalDate::forComponents(
127  b.year, b.month, b.day).toEpochDays();
128 
129  // Perform the subtraction of the days first, before converting to seconds, to
130  // prevent overflow if a.year or b.year is more than 68 years from the current
131  // epoch year.
132  return (epochDaysA - epochDaysB) * 86400 + (a.minutes - b.minutes) * 60;
133 }
134 
147 inline CompareStatus compareDateTupleFuzzy(
148  const DateTuple& t,
149  const DateTuple& start,
150  const DateTuple& until) {
151  // Use int32_t because a delta year of 2730 or greater will exceed
152  // the range of an int16_t.
153  int32_t tMonths = t.year * (int32_t) 12 + t.month;
154  int32_t startMonths = start.year * (int32_t) 12 + start.month;
155  if (tMonths < startMonths - 1) return CompareStatus::kPrior;
156  int32_t untilMonths = until.year * 12 + until.month;
157  if (untilMonths + 1 < tMonths) return CompareStatus::kFarFuture;
158  return CompareStatus::kWithinMatch;
159 }
160 
161 } // namespace extended
162 } // namespace ace_time
163 
164 #endif
static LocalDate forComponents(int16_t year, uint8_t month, uint8_t day)
Factory method using separated year, month and day fields.
Definition: LocalDate.h:156
int32_t toEpochDays() const
Return number of days since the current epoch year sCurrentEpochYear.
Definition: LocalDate.h:355
int32_t acetime_t
Type for the number of seconds from epoch.
Definition: common.h:24
A tuple that represents a date and time.
Definition: DateTuple.h:36
void log() const
Used only for debugging.
Definition: DateTuple.h:49