AceTime  1.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.
LocalDateTime.h
1 /*
2  * MIT License
3  * Copyright (c) 2018 Brian T. Park
4  */
5 
6 #ifndef ACE_TIME_LOCAL_DATE_TIME_H
7 #define ACE_TIME_LOCAL_DATE_TIME_H
8 
9 #include <stdint.h>
10 #include "LocalDate.h"
11 #include "LocalTime.h"
12 
13 class Print;
14 class __FlashStringHelper;
15 
16 namespace ace_time {
17 
28  public:
29 
40  static LocalDateTime forComponents(int16_t year, uint8_t month,
41  uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
42  int8_t yearTiny = LocalDate::isYearValid(year)
43  ? year - LocalDate::kEpochYear
45  return forTinyComponents(yearTiny, month, day, hour, minute, second);
46  }
47 
50  uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
51  return LocalDateTime(
52  LocalDate::forTinyComponents(yearTiny, month, day),
53  LocalTime::forComponents(hour, minute, second));
54  }
55 
67  static LocalDateTime forEpochSeconds(acetime_t epochSeconds) {
68  LocalDate ld;
69  LocalTime lt;
70  if (epochSeconds == LocalDate::kInvalidEpochSeconds) {
71  ld = LocalDate::forError();
72  lt = LocalTime::forError();
73  } else {
74  // Integer floor-division towards -infinity
75  acetime_t days = (epochSeconds < 0)
76  ? (epochSeconds + 1) / 86400 - 1
77  : epochSeconds / 86400;
78 
79  // Avoid % operator, because it's slow on an 8-bit process and because
80  // epochSeconds could be negative.
81  acetime_t seconds = epochSeconds - 86400 * days;
82  ld = LocalDate::forEpochDays(days);
83  lt = LocalTime::forSeconds(seconds);
84  }
85 
86  return LocalDateTime(ld, lt);
87  }
88 
97  static LocalDateTime forUnixSeconds(acetime_t unixSeconds) {
98  acetime_t epochSeconds = (unixSeconds == LocalDate::kInvalidEpochSeconds)
99  ? unixSeconds
100  : unixSeconds - LocalDate::kSecondsSinceUnixEpoch;
101  return forEpochSeconds(epochSeconds);
102  }
103 
120  static LocalDateTime forDateString(const char* dateString);
121 
129  static LocalDateTime forDateStringChainable(const char*& dateString);
130 
135  static LocalDateTime forDateString(const __FlashStringHelper* dateString) {
136  // Copy the F() string into a buffer. Use strncpy_P() because ESP32 and
137  // ESP8266 do not have strlcpy_P(). We need +1 for the '\0' character and
138  // another +1 to determine if the dateString is too long to fit.
139  char buffer[kDateTimeStringLength + 2];
140  strncpy_P(buffer, (const char*) dateString, sizeof(buffer));
141  buffer[kDateTimeStringLength + 1] = 0;
142 
143  // check if the original F() was too long
144  size_t len = strlen(buffer);
145  if (len > kDateTimeStringLength) {
146  return forError();
147  }
148 
149  return forDateString(buffer);
150  }
151 
155  }
156 
158  explicit LocalDateTime() {}
159 
161  bool isError() const {
162  return mLocalDate.isError() || mLocalTime.isError();
163  }
164 
166  int16_t year() const { return mLocalDate.year(); }
167 
169  void year(int16_t year) { mLocalDate.year(year); }
170 
176  int8_t yearTiny() const { return mLocalDate.yearTiny(); }
177 
183  void yearTiny(int8_t yearTiny) { mLocalDate.yearTiny(yearTiny); }
184 
186  uint8_t month() const { return mLocalDate.month(); }
187 
189  void month(uint8_t month) { mLocalDate.month(month); }
190 
192  uint8_t day() const { return mLocalDate.day(); }
193 
195  void day(uint8_t day) { mLocalDate.day(day); }
196 
198  uint8_t hour() const { return mLocalTime.hour(); }
199 
201  void hour(uint8_t hour) { mLocalTime.hour(hour); }
202 
204  uint8_t minute() const { return mLocalTime.minute(); }
205 
207  void minute(uint8_t minute) { mLocalTime.minute(minute); }
208 
210  uint8_t second() const { return mLocalTime.second(); }
211 
213  void second(uint8_t second) { mLocalTime.second(second); }
214 
216  uint8_t dayOfWeek() const { return mLocalDate.dayOfWeek(); }
217 
219  const LocalDate& localDate() const { return mLocalDate; }
220 
222  const LocalTime& localTime() const { return mLocalTime; }
223 
227  acetime_t toEpochDays() const {
229  return mLocalDate.toEpochDays();
230  }
231 
233  acetime_t toUnixDays() const {
236  }
237 
243  acetime_t toEpochSeconds() const {
245 
246  acetime_t days = mLocalDate.toEpochDays();
247  acetime_t seconds = mLocalTime.toSeconds();
248  return days * 86400 + seconds;
249  }
250 
259  acetime_t toUnixSeconds() const {
262  }
263 
268  int8_t compareTo(const LocalDateTime& that) const {
269  acetime_t thisSeconds = toEpochSeconds();
270  acetime_t thatSeconds = that.toEpochSeconds();
271  if (thisSeconds < thatSeconds) return -1;
272  if (thisSeconds > thatSeconds) return 1;
273  return 0;
274  }
275 
281  void printTo(Print& printer) const;
282 
283  // Use default copy constructor and assignment operator.
284  LocalDateTime(const LocalDateTime&) = default;
285  LocalDateTime& operator=(const LocalDateTime&) = default;
286 
287  private:
288  friend bool operator==(const LocalDateTime& a, const LocalDateTime& b);
289 
291  static const uint8_t kDateTimeStringLength = 19;
292 
294  explicit LocalDateTime(const LocalDate& ld, const LocalTime& lt):
295  mLocalDate(ld),
296  mLocalTime(lt) {}
297 
298  LocalDate mLocalDate;
299  LocalTime mLocalTime;
300 };
301 
307 inline bool operator==(const LocalDateTime& a, const LocalDateTime& b) {
308  return a.mLocalDate == b.mLocalDate
309  && a.mLocalTime == b.mLocalTime;
310 }
311 
313 inline bool operator!=(const LocalDateTime& a, const LocalDateTime& b) {
314  return ! (a == b);
315 }
316 
317 }
318 
319 #endif
acetime_t toSeconds() const
Return the number of seconds since midnight.
Definition: LocalTime.h:137
static const acetime_t kSecondsSinceUnixEpoch
Number of seconds from Unix epoch (1970-01-01 00:00:00Z) to the AceTime epoch (2000-01-01 00:00:00Z)...
Definition: LocalDate.h:69
static LocalDate forEpochDays(acetime_t epochDays)
Factory method using the number of days since AceTime epoch of 2000-01-01.
Definition: LocalDate.h:125
int16_t year() const
Return the year.
uint8_t minute() const
Return the minute.
static const acetime_t kDaysSinceUnixEpoch
Number of days from Unix epoch (1970-01-01 00:00:00Z) to the AceTime epoch (2000-01-01 00:00:00Z)...
Definition: LocalDate.h:75
static LocalDateTime forDateString(const __FlashStringHelper *dateString)
Factory method.
static LocalDate forError()
Factory method that returns a LocalDate which represents an error condition.
Definition: LocalDate.h:206
static const acetime_t kInvalidEpochDays
Sentinel epochDays which indicates an error.
Definition: LocalDate.h:60
int8_t yearTiny() const
Return the single-byte year offset from year 2000.
Definition: LocalDate.h:241
static const acetime_t kInvalidEpochSeconds
Sentinel epochSeconds which indicates an error.
Definition: LocalDate.h:63
The time (hour, minute, second) fields representing the time without regards to the day or the time z...
Definition: LocalTime.h:26
void printTo(Print &printer) const
Print LocalDateTime to &#39;printer&#39; in ISO 8601 format.
static LocalDateTime forTinyComponents(int8_t yearTiny, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second)
Factory method using components with an int8_t yearTiny.
Definition: LocalDateTime.h:49
acetime_t toEpochDays() const
Return number of days since AceTime epoch (2000-01-01 00:00:00Z).
Definition: LocalDate.h:300
uint8_t day() const
Return the day of the month.
int8_t yearTiny() const
Return the single-byte year offset from year 2000.
static LocalDateTime forEpochSeconds(acetime_t epochSeconds)
Factory method.
Definition: LocalDateTime.h:67
static LocalDateTime forDateStringChainable(const char *&dateString)
Variant of forDateString() that updates the pointer to the next unprocessed character.
static LocalDate forTinyComponents(int8_t yearTiny, uint8_t month, uint8_t day)
Factory method using components with an int8_t yearTiny.
Definition: LocalDate.h:113
void minute(uint8_t minute)
Set the minute.
acetime_t toUnixDays() const
Return the number of days since Unix epoch (1970-01-01 00:00:00).
void hour(uint8_t hour)
Set the hour.
bool isError() const
Return true if any component indicates an error condition.
Definition: LocalDate.h:278
acetime_t toUnixSeconds() const
Return seconds from Unix epoch 1970-01-01 00:00:00Z, after assuming that the date and time components...
uint8_t day() const
Return the day of the month.
Definition: LocalDate.h:257
static LocalDateTime forDateString(const char *dateString)
Factory method.
uint8_t month() const
Return the month with January=1, December=12.
void yearTiny(int8_t yearTiny)
Set the single-byte year offset from year 2000.
static LocalDateTime forComponents(int16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second)
Factory method using separated date and time components.
Definition: LocalDateTime.h:40
acetime_t toEpochSeconds() const
Return seconds since AceTime epoch 2000-01-01 00:00:00Z, after assuming that the date and time compon...
const LocalDate & localDate() const
Return the LocalDate.
const LocalTime & localTime() const
Return the LocalTime.
uint8_t hour() const
Return the hour.
uint8_t dayOfWeek() const
Return the day of the week, Monday=1, Sunday=7 (per ISO 8601).
void year(int16_t year)
Set the year.
bool isError() const
Return true if any component is outside the normal time range of 00:00:00 to 23:59:59.
Definition: LocalTime.h:106
static const int8_t kInvalidYearTiny
Sentinel yearTiny which indicates an error condition or sometimes a year that &#39;does not exist&#39;...
Definition: LocalDate.h:45
uint8_t second() const
Return the second.
static LocalDateTime forUnixSeconds(acetime_t unixSeconds)
Factory method that takes the number of seconds since Unix Epoch of 1970-01-01.
Definition: LocalDateTime.h:97
static LocalDateTime forError()
Factory method that returns an instance where isError() returns true.
static LocalTime forError()
Factory method that returns an instance which indicates an error condition.
Definition: LocalTime.h:93
static LocalTime forComponents(uint8_t hour, uint8_t minute, uint8_t second)
Factory method using separated date, time, and time zone fields.
Definition: LocalTime.h:41
uint8_t hour() const
Return the hour.
Definition: LocalTime.h:116
int8_t compareTo(const LocalDateTime &that) const
Compare this LocalDateTime with another LocalDateTime, and return (<0, 0, >0) according to whether th...
The date (year, month, day) representing the date without regards to time zone.
Definition: LocalDate.h:36
friend bool operator==(const LocalDateTime &a, const LocalDateTime &b)
Return true if two LocalDateTime objects are equal in all components.
acetime_t toEpochDays() const
Return number of whole days since AceTime epoch (2000-01-01 00:00:00Z).
static const int16_t kEpochYear
Base year of epoch.
Definition: LocalDate.h:39
void month(uint8_t month)
Set the month.
uint8_t minute() const
Return the minute.
Definition: LocalTime.h:122
uint8_t month() const
Return the month with January=1, December=12.
Definition: LocalDate.h:251
static bool isYearValid(int16_t year)
Return true if year is within valid range of [1873, 2127].
Definition: LocalDate.h:216
int16_t year() const
Return the full year instead of just the last 2 digits.
Definition: LocalDate.h:231
uint8_t second() const
Return the second.
Definition: LocalTime.h:128
LocalDateTime()
Constructor.
bool isError() const
Return true if any component indicates an error condition.
static LocalTime forSeconds(acetime_t seconds)
Factory method.
Definition: LocalTime.h:54
void second(uint8_t second)
Set the second.
void day(uint8_t day)
Set the day of the month.
Class that holds the date-time as the components (year, month, day, hour, minute, second) without reg...
Definition: LocalDateTime.h:27
uint8_t dayOfWeek() const
Calculate the day of week given the (year, month, day).
Definition: LocalDate.h:268