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.

Dependencies:   CalendarPage

Dependents:   CI-data-logger-server WattEye X10Svr SSDP_Server

Files at this revision

API Documentation at this revision

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;