ESP DateTime  0.2.0
Date Time Functions and Classes for ESP8266 and ESP32
DateTime.h
Go to the documentation of this file.
1 #ifndef ESP_DATE_TIME_CLASS_H
2 #define ESP_DATE_TIME_CLASS_H
3 
4 /**
5  * @file DateTime.h
6  * @author Zhang Xiaoke (github@mcxiaoke.com)
7  * @brief ESPDateTime header
8  *
9  */
10 
11 #if !defined(ESP8266) && !defined(ESP32)
12 #error "ESPDateTime only support ESP32 or ESP8266 platform!"
13 #endif
14 
15 #include <Arduino.h>
16 #include <time.h>
17 #include <sys/time.h>
18 
19 class DateTimeClass;
20 
21 /**
22  * @brief DateTime Parts struct, similar to struct tm in <time.h>, containing a
23  * calendar date and time broken down into its components, but more readable,
24  * include some useful getter methods.
25  *
26  */
27 struct DateTimeParts {
28  // http://www.cplusplus.com/reference/ctime/tm/
29  const time_t _ts; /**< timestamp variable, internal */
30  const int _tz; /**< timezone variable, internal */
31  const struct tm* _tm; /**< struct tm variable, internal */
32  /**
33  * @brief Get internal timestamp, in seconds
34  *
35  * @return time_t timestamp, in seconds
36  */
37  time_t getTime() const { return _ts; }
38  /**
39  * @brief Get internal timezone offset
40  *
41  * @return int timezone offset
42  */
43  int getTimeZone() const { return _tz; }
44  /**
45  * @brief Get the year (format: 19xx, 20xx)
46  *
47  * @return int year value
48  */
49  int getYear() const { return _tm->tm_year + 1900; }
50  /**
51  * @brief Get months since January (0-11)
52  *
53  * @return int month value
54  */
55  int getMonth() const { return _tm->tm_mon; }
56  /**
57  * @brief Get days since January 1 (0-365)
58  *
59  * @return int day of year
60  */
61  int getYearDay() const { return _tm->tm_yday; }
62  /**
63  * @brief Get day of the month (1-31)
64  *
65  * @return int month day
66  */
67  int getMonthDay() const { return _tm->tm_mday; }
68  /**
69  * @brief Get days since Sunday (0-6)
70  *
71  * @return int day of week
72  */
73  int getWeekDay() const { return _tm->tm_wday; }
74  /**
75  * @brief Get hours since midnight (0-23)
76  *
77  * @return int hours
78  */
79  int getHours() const { return _tm->tm_hour; }
80  /**
81  * @brief Get minutes after the hour (0-59)
82  *
83  * @return int minutes
84  */
85  int getMinutes() const { return _tm->tm_min; }
86  /**
87  * @brief Get seconds after the minute (0-60)
88  *
89  * @return int seconds
90  */
91  int getSeconds() const { return _tm->tm_sec; }
92 
93  /**
94  * @brief Foramt current time to string representation
95  *
96  * @param fmt format string for strftime
97  * @return String string representation of current time
98  */
99  String format(const char* fmt) const;
100  /**
101  * @brief Get string representation of current time
102  *
103  * @return String string representation of current time
104  */
105  String toString() const;
106 
107  /**
108  * @brief factory method for constructing DateTimeParts from timestamp and
109  * timezone.
110  *
111  * @param timeSecs timestamp in seconds since 1970
112  * @param timeZone timezone offset (-11,+13)
113  * @return DateTimeParts DateTimeParts object
114  */
115  static DateTimeParts from(const time_t timeSecs, const int timeZone = 0);
116  /**
117  * @brief factory method for constructing DateTimeParts from DateTimeClass
118  * object.
119  *
120  * @param dateTime DateTimeClass object
121  * @return DateTimeParts DateTimeParts object
122  */
123  static DateTimeParts from(DateTimeClass* dateTime);
124 };
125 
126 /**
127  * @brief DateTime Formatter constants and static format methods.
128  *
129  * Details in http://www.cplusplus.com/reference/ctime/strftime/
130  *
131  */
133  /**
134  * @brief ISO8601 date time string format (2019-11-29T23:29:55+0800).
135  *
136  */
137  constexpr static const char* ISO8601 = "%FT%T%z";
138  /**
139  * @brief RFC1123 date time string format (Fri, 29 Nov 2019 15:29:55 GMT)
140  *
141  */
142  constexpr static const char* HTTP = "%a, %d %b %Y %H:%M:%S GMT";
143  /**
144  * @brief Simple date time string format (2019-11-29 23:29:55).
145  *
146  */
147  constexpr static const char* SIMPLE = "%F %T";
148  /**
149  * @brief Compat date time string format (20191129_232955).
150  *
151  */
152  constexpr static const char* COMPAT = "%Y%m%d_%H%M%S";
153  /**
154  * @brief Date Only date time string format (2019-11-29).
155  *
156  */
157  constexpr static const char* DATE_ONLY = "%F";
158  /**
159  * @brief Time Only date time string format (23:29:55).
160  *
161  */
162  constexpr static const char* TIME_ONLY = "%T";
163  /**
164  * @brief utility method for formatting time using fmt.
165  *
166  * @param fmt date time format string
167  * @param timeSecs timestamp value
168  * @param timeZone timezone offset (-11,13)
169  * @return String string representation of timeSecs
170  */
171  inline static String format(const char* fmt,
172  const time_t timeSecs,
173  const int timeZone = 0) {
174  return DateTimeParts::from(timeSecs, timeZone).format(fmt);
175  }
176 };
177 
178 /**
179  * @brief DateTime Library Main Class, include time get/set/format methods.
180  *
181  */
183  public:
184  /**
185  * @brief Valid min timestamp value 1574870400 (2019/11/28 00:00:00).
186  *
187  * return value from time(null) < 1574870400 means system time invalid
188  *
189  */
190  constexpr static time_t SECS_START_POINT = 1574870400; // 20191128
191  /**
192  * @brief Unix Time Zero constant (1970-01-01 00:00:00)
193  *
194  */
195  constexpr static time_t TIME_ZERO = 0;
196  /**
197  * @brief UTC TimeZone Offset GMT+0
198  *
199  */
200  constexpr static int TIMEZONE_UTC = 0;
201  /**
202  * @brief TimeZone Offset GMT+8
203  *
204  */
205  constexpr static int TIMEZONE_CHINA = 8;
206  /**
207  * @brief Default TimeZone Offset GMT+0
208  *
209  */
210  constexpr static int DEFAULT_TIMEZONE = TIMEZONE_UTC; // time zone offset
211  /**
212  * @brief NTP Request default timeout: 10 seconds
213  *
214  */
215  constexpr static unsigned int DEFAULT_TIMEOUT = 10 * 1000; // milliseconds
216  /**
217  * @brief NTP Server 1
218  *
219  */
220  constexpr static const char* NTP_SERVER_1 = "ntp.ntsc.ac.cn";
221  /**
222  * @brief NTP Server 2
223  *
224  */
225  constexpr static const char* NTP_SERVER_2 = "pool.ntp.org";
226  /**
227  * @brief NTP Server 3
228  *
229  */
230  constexpr static const char* NTP_SERVER_3 = "time.windows.com";
231  /**
232  * @brief Construct a new DateTimeClass object.
233  *
234  * @param _timeSecs set initialize timestamp
235  * @param _timeZone set initialize timezone offset
236  * @param _ntpServer set initialize ntp server
237  */
238  DateTimeClass(const time_t _timeSecs = TIME_ZERO,
239  const int _timeZone = DEFAULT_TIMEZONE,
240  const char* _ntpServer = NTP_SERVER_1);
241  /**
242  * @brief Set the TimeZone offset
243  *
244  * @param _timeZone time zone offset value
245  * @return true if time zone valid and changed
246  * @return false if time zone not valid or not changed
247  */
248  bool setTimeZone(int _timeZone);
249  /**
250  * @brief Set the NTP Server
251  *
252  * @param _server ntp server domain name or ip address
253  */
254  void setServer(const char* _server);
255  /**
256  * @brief Force NTP Sync to update system timestamp for internal use, please *
257  * using begin() instead.
258  *
259  * @param timeOutMs ntp request timeout
260  * @return true if timestamp updated and valid
261  * @return false if timestamp not valid
262  */
263  bool forceUpdate(const unsigned int timeOutMs = DEFAULT_TIMEOUT);
264  /**
265  * @brief Set the timestamp from outside, for test only
266  *
267  * @param timeSecs timestamp in seconds
268  * @param forceSet ignore valid check, force set
269  * @return true if timestamp valid
270  * @return false if timestamp not valid
271  */
272  bool setTime(const time_t timeSecs, bool forceSet = false);
273  /**
274  * @brief Format current local time to string
275  *
276  * Attention: ESP8266 does not support real timezone, it just add timeZone
277  * 3600 seconds to original timestamp, so %z format is always +0000
278  *
279  * @param fmt date time format
280  * @return String string representation of local time
281  */
282  String format(const char* fmt);
283  /**
284  * @brief Format current utc time to string
285  *
286  * @param fmt date time format
287  * @return String String string representation of utc time
288  */
289  String formatUTC(const char* fmt);
290  // inline functions
291  // void formatTo(const char* fmt, char* dst);
292  /**
293  * @brief Begin ntp sync to update system time
294  *
295  * @param timeOutMs ntp request timeout
296  * @return true if timestamp updated and valid
297  * @return false if timestamp not valid
298  */
299  inline bool begin(const unsigned int timeOutMs = DEFAULT_TIMEOUT) {
300  return isTimeValid() || forceUpdate(timeOutMs);
301  }
302  /**
303  * @brief Check current timestamp is or not valid time
304  *
305  * @return true if time valid
306  * @return false if time not valid
307  */
308  inline bool isTimeValid() const { return bootTimeSecs > SECS_START_POINT; }
309  /**
310  * @brief Get system boot timestamp in seconds
311  *
312  * @return time_t boot timestamp
313  */
314  inline time_t getBootTime() const {
315  return bootTimeSecs > SECS_START_POINT
316  ? bootTimeSecs
317  : TIME_ZERO - (time_t)(millis() / 1000);
318  }
319  /**
320  * @brief Get current local timestamp, alias of getTime()
321  *
322  * @return time_t timestamp
323  */
324  inline time_t now() const { return getTime(); }
325  /**
326  * @brief Get current local timestamp
327  *
328  * @return time_t timestamp
329  */
330  inline time_t getTime() const {
331  return bootTimeSecs > SECS_START_POINT
332  ? (bootTimeSecs + (time_t)(millis() / 1000))
333  : TIME_ZERO;
334  }
335  /**
336  * @brief Get current utc timestamp
337  *
338  * @return time_t utc timestamp
339  */
340  inline time_t utcTime() const {
341  return bootTimeSecs > SECS_START_POINT ? (getTime() - timeZone * 3600)
342  : TIME_ZERO;
343  }
344  /**
345  * @brief Get system timestamp using time(nullptr), please use now() instead.
346  *
347  * @return time_t timestamp
348  */
349  inline time_t osTime() const {
350  auto t = time(nullptr);
351  return t > SECS_START_POINT ? t : TIME_ZERO;
352  }
353  /**
354  * @brief Get current timezone offset
355  *
356  * @return int time zone offset
357  */
358  inline int getTimeZone() const { return timeZone; }
359  /**
360  * @brief Get current ntp server address
361  *
362  * @return const char* ntp server
363  */
364  inline const char* getServer() { return ntpServer; }
365  /**
366  * @brief Get DateTimeParts object
367  *
368  * @return DateTimeParts DateTimeParts object
369  */
370  inline DateTimeParts getParts() { return DateTimeParts::from(this); }
371  /**
372  * @brief String simple string representation of local time
373  *
374  * @return String string representation
375  */
376  inline String toString() { return format(DateFormatter::SIMPLE); }
377  /**
378  * @brief String ISO8601 representation of local time
379  *
380  * @return String string representation
381  */
382  inline String toISOString() { return format(DateFormatter::ISO8601); }
383  /**
384  * @brief String RFC1123 representation of local time
385  *
386  * @return String string representation
387  */
388  inline String toUTCString() { return formatUTC(DateFormatter::HTTP); }
389  // operator overloads
390  DateTimeClass operator+(const time_t timeDeltaSecs) {
391  DateTimeClass dt(getTime() + timeDeltaSecs, timeZone, ntpServer);
392  return dt;
393  }
394  DateTimeClass operator-(const time_t timeDeltaSecs) {
395  DateTimeClass dt(getTime() - timeDeltaSecs, timeZone, ntpServer);
396  return dt;
397  }
398  DateTimeClass& operator-=(const time_t timeDeltaSecs) {
399  bootTimeSecs += timeDeltaSecs;
400  return *this;
401  }
402  DateTimeClass& operator+=(const time_t timeDeltaSecs) {
403  bootTimeSecs -= timeDeltaSecs;
404  return *this;
405  }
406  friend bool operator<(const DateTimeClass& lhs, const DateTimeClass& rhs) {
407  return lhs.bootTimeSecs + lhs.timeZone * 3600 <
408  rhs.bootTimeSecs + rhs.timeZone * 3600;
409  }
410  friend bool operator>(const DateTimeClass& lhs, const DateTimeClass& rhs) {
411  return rhs < lhs;
412  }
413  friend bool operator<=(const DateTimeClass& lhs, const DateTimeClass& rhs) {
414  return !(lhs > rhs);
415  }
416  friend bool operator>=(const DateTimeClass& lhs, const DateTimeClass& rhs) {
417  return !(lhs < rhs);
418  }
419 
420  friend bool operator==(const DateTimeClass& lhs, const DateTimeClass& rhs) {
421  return lhs.bootTimeSecs == rhs.bootTimeSecs && lhs.timeZone == rhs.timeZone;
422  }
423  friend bool operator!=(const DateTimeClass& lhs, const DateTimeClass& rhs) {
424  return !(lhs == rhs);
425  }
426 
427  private:
428  /**
429  * @brief Boot timestamp seconds.
430  *
431  */
432  unsigned long bootTimeSecs;
433  /**
434  * @brief Time zone offset
435  *
436  */
437  int timeZone;
438  /**
439  * @brief First ntp server address.
440  *
441  */
442  const char* ntpServer;
443  bool ntpMode;
444 };
445 
446 /**
447  * @brief Global DateTimeClass object.
448  *
449  */
450 extern DateTimeClass DateTime; // define in cpp
451 
452 #endif
DateTimeParts::toString
String toString() const
Get string representation of current time.
Definition: DateTime.cpp:22
DateTimeParts::from
static DateTimeParts from(const time_t timeSecs, const int timeZone=0)
factory method for constructing DateTimeParts from timestamp and timezone.
Definition: DateTime.cpp:26
DateFormatter
DateTime Formatter constants and static format methods.
Definition: DateTime.h:132
DateFormatter::COMPAT
constexpr static const char * COMPAT
Compat date time string format (20191129_232955).
Definition: DateTime.h:152
DateTimeClass::TIMEZONE_UTC
constexpr static int TIMEZONE_UTC
UTC TimeZone Offset GMT+0.
Definition: DateTime.h:200
DateTimeClass::TIME_ZERO
constexpr static time_t TIME_ZERO
Unix Time Zero constant (1970-01-01 00:00:00)
Definition: DateTime.h:195
DateTimeParts::getWeekDay
int getWeekDay() const
Get days since Sunday (0-6)
Definition: DateTime.h:73
DateFormatter::SIMPLE
constexpr static const char * SIMPLE
Simple date time string format (2019-11-29 23:29:55).
Definition: DateTime.h:147
DateTimeClass::toISOString
String toISOString()
String ISO8601 representation of local time.
Definition: DateTime.h:382
DateTimeClass::SECS_START_POINT
constexpr static time_t SECS_START_POINT
Valid min timestamp value 1574870400 (2019/11/28 00:00:00).
Definition: DateTime.h:190
DateTimeClass::DateTimeClass
DateTimeClass(const time_t _timeSecs=TIME_ZERO, const int _timeZone=DEFAULT_TIMEZONE, const char *_ntpServer=NTP_SERVER_1)
Construct a new DateTimeClass object.
Definition: DateTime.cpp:35
DateTimeClass::forceUpdate
bool forceUpdate(const unsigned int timeOutMs=DEFAULT_TIMEOUT)
Force NTP Sync to update system timestamp for internal use, please * using begin() instead.
Definition: DateTime.cpp:66
DateTimeParts::_tz
const int _tz
Definition: DateTime.h:30
DateTimeParts::getHours
int getHours() const
Get hours since midnight (0-23)
Definition: DateTime.h:79
DateTimeParts::getTimeZone
int getTimeZone() const
Get internal timezone offset.
Definition: DateTime.h:43
DateTimeParts::format
String format(const char *fmt) const
Foramt current time to string representation.
Definition: DateTime.cpp:16
DateTimeClass::DEFAULT_TIMEZONE
constexpr static int DEFAULT_TIMEZONE
Default TimeZone Offset GMT+0.
Definition: DateTime.h:210
DateTimeParts::getTime
time_t getTime() const
Get internal timestamp, in seconds.
Definition: DateTime.h:37
DateTime
DateTimeClass DateTime
Global DateTimeClass object.
Definition: DateTime.cpp:108
DateTimeClass::setTime
bool setTime(const time_t timeSecs, bool forceSet=false)
Set the timestamp from outside, for test only.
Definition: DateTime.cpp:89
DateTimeParts::getYear
int getYear() const
Get the year (format: 19xx, 20xx)
Definition: DateTime.h:49
DateTimeClass::osTime
time_t osTime() const
Get system timestamp using time(nullptr), please use now() instead.
Definition: DateTime.h:349
DateTimeClass::getTime
time_t getTime() const
Get current local timestamp.
Definition: DateTime.h:330
DateTimeParts::getSeconds
int getSeconds() const
Get seconds after the minute (0-60)
Definition: DateTime.h:91
DateTimeClass::now
time_t now() const
Get current local timestamp, alias of getTime()
Definition: DateTime.h:324
DateTimeClass::formatUTC
String formatUTC(const char *fmt)
Format current utc time to string.
Definition: DateTime.cpp:104
DateTimeClass::toString
String toString()
String simple string representation of local time.
Definition: DateTime.h:376
DateTimeClass::setServer
void setServer(const char *_server)
Set the NTP Server.
Definition: DateTime.cpp:56
DateTimeParts::getMinutes
int getMinutes() const
Get minutes after the hour (0-59)
Definition: DateTime.h:85
DateTimeClass
DateTime Library Main Class, include time get/set/format methods.
Definition: DateTime.h:182
DateTimeClass::setTimeZone
bool setTimeZone(int _timeZone)
Set the TimeZone offset.
Definition: DateTime.cpp:43
DateTimeParts
DateTime Parts struct, similar to struct tm in <time.h>, containing a calendar date and time broken d...
Definition: DateTime.h:27
DateTimeClass::getServer
const char * getServer()
Get current ntp server address.
Definition: DateTime.h:364
DateFormatter::HTTP
constexpr static const char * HTTP
RFC1123 date time string format (Fri, 29 Nov 2019 15:29:55 GMT)
Definition: DateTime.h:142
DateTimeClass::format
String format(const char *fmt)
Format current local time to string.
Definition: DateTime.cpp:100
DateTimeClass::DEFAULT_TIMEOUT
constexpr static unsigned int DEFAULT_TIMEOUT
NTP Request default timeout: 10 seconds.
Definition: DateTime.h:215
DateTimeParts::getMonthDay
int getMonthDay() const
Get day of the month (1-31)
Definition: DateTime.h:67
DateTimeParts::_tm
const struct tm * _tm
Definition: DateTime.h:31
DateTimeParts::getMonth
int getMonth() const
Get months since January (0-11)
Definition: DateTime.h:55
DateTimeClass::getTimeZone
int getTimeZone() const
Get current timezone offset.
Definition: DateTime.h:358
DateTimeClass::getParts
DateTimeParts getParts()
Get DateTimeParts object.
Definition: DateTime.h:370
DateTimeClass::getBootTime
time_t getBootTime() const
Get system boot timestamp in seconds.
Definition: DateTime.h:314
DateTimeClass::utcTime
time_t utcTime() const
Get current utc timestamp.
Definition: DateTime.h:340
DateTimeParts::getYearDay
int getYearDay() const
Get days since January 1 (0-365)
Definition: DateTime.h:61
DateTimeClass::NTP_SERVER_1
constexpr static const char * NTP_SERVER_1
NTP Server 1.
Definition: DateTime.h:220
DateFormatter::TIME_ONLY
constexpr static const char * TIME_ONLY
Time Only date time string format (23:29:55).
Definition: DateTime.h:162
DateTimeClass::begin
bool begin(const unsigned int timeOutMs=DEFAULT_TIMEOUT)
Begin ntp sync to update system time.
Definition: DateTime.h:299
DateTimeClass::toUTCString
String toUTCString()
String RFC1123 representation of local time.
Definition: DateTime.h:388
DateTimeClass::NTP_SERVER_3
constexpr static const char * NTP_SERVER_3
NTP Server 3.
Definition: DateTime.h:230
DateFormatter::ISO8601
constexpr static const char * ISO8601
ISO8601 date time string format (2019-11-29T23:29:55+0800).
Definition: DateTime.h:137
DateFormatter::DATE_ONLY
constexpr static const char * DATE_ONLY
Date Only date time string format (2019-11-29).
Definition: DateTime.h:157
DateTimeClass::NTP_SERVER_2
constexpr static const char * NTP_SERVER_2
NTP Server 2.
Definition: DateTime.h:225
DateFormatter::format
static String format(const char *fmt, const time_t timeSecs, const int timeZone=0)
utility method for formatting time using fmt.
Definition: DateTime.h:171
DateTimeParts::_ts
const time_t _ts
Definition: DateTime.h:29
DateTimeClass::TIMEZONE_CHINA
constexpr static int TIMEZONE_CHINA
TimeZone Offset GMT+8.
Definition: DateTime.h:205
DateTimeClass::isTimeValid
bool isTimeValid() const
Check current timestamp is or not valid time.
Definition: DateTime.h:308