A time interface class. This class replicates the normal time functions, but goes a couple of steps further. mbed library 82 and prior has a defective gmtime function. Also, this class enables access to setting the time, and adjusting the accuracy of the RTC.
Dependents: CI-data-logger-server WattEye X10Svr SSDP_Server
Revision 6:c79cfe750416, committed 2015-11-26
- Comitter:
- WiredHome
- Date:
- Thu Nov 26 16:32:36 2015 +0000
- Parent:
- 5:a5f50b5fb856
- Child:
- 7:1de342fa7840
- Commit message:
- Improving the selection of DST. Can be set on/off, or automatic when a start/stop date and time are made available.
Changed in this revision
TimeInterface.cpp | Show annotated file Show diff for this revision Revisions of this file |
TimeInterface.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/TimeInterface.cpp Thu Aug 06 11:13:47 2015 +0000 +++ b/TimeInterface.cpp Thu Nov 26 16:32:36 2015 +0000 @@ -3,7 +3,7 @@ #include "rtc_api.h" -//#define DEBUG "Time" +#define DEBUG "Time" #include <cstdio> #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) #define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); @@ -33,6 +33,8 @@ TimeInterface::TimeInterface() { + dst = false; + memset(&dst_pair, 0, sizeof(dst_pair)); // that's enough to keep it from running } TimeInterface::~TimeInterface() @@ -44,7 +46,7 @@ NTPClient ntp; NTPResult res; // int16_t tzomin = get_tzo_min(); - INFO("setTime(%s, %d, %d) %d\r\n", host, port, timeout, tzomin); + INFO("setTime(%s, %d, %d)\r\n", host, port, timeout); res = ntp.setTime(host, port, timeout); INFO(" ret: %d\r\n", res); if (res == NTP_OK) { @@ -57,14 +59,66 @@ return res; } -void set_dst(bool dst) +bool TimeInterface::parseDSTstring(TimeInterface::dst_event_t * result, const char * dstr) { - (void)dst; + int x; + dst_event_t test_dst; + + x = atoi(dstr); + if (x >= 1 && x <= 12) { + test_dst.MM = x; + dstr = strchr(dstr, '/'); + if (dstr++) { + x = atoi(dstr); + if (x >= 1 && x <= 31) { + test_dst.DD = x; + dstr = strchr(dstr, ','); + if (dstr++) { + x = atoi(dstr); + if (x >= 0 && x <= 23) { + test_dst.hh = x; + dstr = strchr(dstr, ':'); + if (dstr++) { + x = atoi(dstr); + if (x >= 0 && x <= 59) { + test_dst.mm = x; + memcpy(result, &test_dst, sizeof(dst_event_t)); + INFO("parsed: %d/%d %d:%02d", test_dst.MM, test_dst.DD, test_dst.hh, test_dst.mm); + return true; + } + } + } + } + } + } + } + return false; } -bool get_dst(void) +// parse MM/DD,hh:mm +bool TimeInterface::set_dst(const char * dstStart, const char * dstStop) { - return false; + dst_event_pair_t test_pair; + + if (parseDSTstring(&test_pair.dst_start, dstStart) + && parseDSTstring(&test_pair.dst_stop, dstStop)) { + memcpy(&dst_pair, &test_pair, sizeof(dst_event_pair_t)); + INFO("set_dst from (%s,%s)", dstStart, dstStop); + return true; + } + WARN("failed to set_dst from (%s,%s)", dstStart, dstStop); + return false; +} + +bool TimeInterface::set_dst(bool isdst) +{ + dst = isdst; + return true; +} + +bool TimeInterface::get_dst(void) +{ + return dst; } clock_t TimeInterface::clock(void) @@ -77,9 +131,31 @@ return std::time(timer); } +uint32_t TimeInterface::minutesSinceJan(int mon, int day, int hr, int min) +{ + return (mon * 60 * 24 * 31) + (day * 60 * 24) + (hr * 60) + min; +} + time_t TimeInterface::timelocal(time_t* timer) { - return std::time(timer) + 60 * get_tzo_min(); + time_t privTime; + struct tm * tminfo; + + if (dst_pair.dst_start.MM) { // may have to change the dst + std::time(&privTime); + tminfo = std::localtime(&privTime); + + uint32_t min_since_jan = minutesSinceJan(tminfo->tm_mon + 1, tminfo->tm_mday, tminfo->tm_hour, tminfo->tm_min); + uint32_t min_dst_start = minutesSinceJan(dst_pair.dst_start.MM, dst_pair.dst_start.DD, dst_pair.dst_start.hh, dst_pair.dst_start.mm); + uint32_t min_dst_stop = minutesSinceJan(dst_pair.dst_stop.MM, dst_pair.dst_stop.DD, dst_pair.dst_stop.hh, dst_pair.dst_stop.mm); + + if (min_since_jan >= min_dst_start && min_since_jan < min_dst_stop) { + dst = 1; + } else { + dst = 0; + } + } + return std::time(timer) + 60 * get_tzo_min() + 60 * dst; } char * TimeInterface::ctime(const time_t * timer) @@ -118,7 +194,7 @@ struct tm_ex * TimeInterface::gmtime(const time_t * timer) { - time_t priv = *timer + (get_tzo_min() * 60); + time_t priv = *timer + (get_tzo_min() * 60 + dst * 60); struct tm * tmp = std::localtime(&priv); tm_ext.tm_sec = tmp->tm_sec;
--- a/TimeInterface.h Thu Aug 06 11:13:47 2015 +0000 +++ b/TimeInterface.h Thu Nov 26 16:32:36 2015 +0000 @@ -4,7 +4,7 @@ #include "mbed.h" #include <ctime> -#include "NTPClient.h" // ver 4 Donatien Garnier +#include "NTPClient.h" // ver 7 Wiredhome from ver 5 Donatien Garnier // Special Registers and their usage: // GPREG0: 32 bits @@ -91,7 +91,7 @@ /// to a provided buffer. /// /// This reads the real time clock and returns the current time, adjusted - /// for the local timezone. + /// for the local timezone and daylight savings time. /// /// @code /// time_t t_ref2, t_ref3; @@ -149,7 +149,8 @@ /// Convert the referenced time_t value to a tm structure in local format. /// - /// This method leverages the time zone offset applied with @see set_tzo(). + /// This method leverages the time zone offset applied with @see set_tzo() + /// and the daylight savings time flag applied with @see set_dst(). /// /// @note Watch out for race conditions as this returns a pointer to a /// shared buffer. @@ -218,8 +219,24 @@ /// /// @param[in] dst is a boolean that should be set when dst is /// the active mode. + /// @returns true, always. /// - void set_dst(bool dst); + bool set_dst(bool dst); + + /// Set the clock for auto-adjust local time based on + /// changing to standard or daylight savings time. + /// + /// return values for localtime will then be adjusted not only + /// for the time zone offset, but for dst. + /// + /// @param[in] dstStart is a string of the form "mm/dd,hh:mm" + /// representing when DST starts. + /// @param[in] dstStop is a string of the form "mm/dd,hh:mm" + /// representing when DST stops. + /// @returns true if the start and stop pair could be successfully + /// parsed. + /// + bool set_dst(const char * dstStart, const char * dstStop); /// Get the current clock mode for daylight savings time. /// @@ -295,6 +312,31 @@ // ntp interface functions private: + typedef struct { + uint8_t MM; + uint8_t DD; + uint8_t hh; + uint8_t mm; + } dst_event_t; + typedef struct { + dst_event_t dst_start; + dst_event_t dst_stop; + } dst_event_pair_t; + + bool parseDSTstring(dst_event_t * result, const char * dstr); + + /// Performs a "simple" computation of two dates into minutes. + /// + /// Does not account for leap years or which month it is. Is + /// useful only for comparing which date/time came first, not for + /// computing the difference between them. + /// + /// @return "normalized" minutes since Jan 1 00:00. + /// + uint32_t minutesSinceJan(int mon, int day, int hr, int min); + + dst_event_pair_t dst_pair; + bool dst; // true in dst mode char result[30]; // holds the converted to text time string time_t tresult; // holds the converted time structure. struct tm_ex tm_ext;