Enable Javascript


Last Arduino/ESP project (click to open)

User Rating: 5 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Active
 

sMsecTime.h
A very Simple, easy to use and small ESP32 Milliseconds Time library.
Time synchronization from NTP time servers.
Timestamp in milliseconds: 1586793080376
Date and time: Monday 13 April 2020 15:51:20.376


(click thumbnail)

       sMsecTime.ino - sMsecTimeCalc.ino

Why a time in milliseconds?:
A time in hours and minutes is sufficient for normal use. Sometimes it is also useful to know the number of seconds. However, when storing or transmitting data, such as sensor data, a timestamp in milliseconds is highly desirable.
With my simple and small time library you have all the usual date and time values, included milliseconds, through the sEpoch and sDateTime structures.

No third-party time libraries required:
miliseconds, seconds, minutes, hours, day, month, year, week, weekday, yearday, zone, DST, offset (zone+DST), month Long, month Short, day Long, day Short.
seconds - offset = UTC/GMT
Time (re-)synchronization from NTP time servers or user input.

My sMsecTime.h
Is a very simple, easy to use and small ESP32 Time library to set, get and manipulate date and time.
The sMsecTime.h structures and functions can be found on page 3.
Date and time manipulation is easily done by adding or subtracting a timestamp. You can calc a timestamp or use one of the functions sMakeTime() or use the function sNow() to get it from the system timer.
EXAMPLES (download my simpleLib):
  sMsecTimeM5StickC.ino (picture on top) (using NTP time server)
  sMsecTime.ino (thumbnail 1) (using NTP time server)
  sMsecTimeCalc.ino (thumbnail 2) (using timestamps)

ESP32 Time from the system timer:
The time can be easily set and used via the internal RTC system timer and the ESP32 timeval structure. We set the system timer time to a UNIX epoch timestamp, the number of seconds from January 1, 1970 00:00:00. We do this easily with the sGetNTP() function. Now we can use the timeval tructure to set the struct sEpoch sec and msec that we use in this library.

NTP Time Servers:
With one of these default servers time.google.com, pool.ntp.org and time.nist.gov and the sGetNTP() function we get a actual UNIX epoch timestamp. We use this at start and for synchronization, so we also use WiFi. The default SNTP synchronization interval (3600 sec) is used.

Timezone and DST/Summertime:
Use timezone data from: https://sites.google.com/a/usapiens.com/opnode/time-zones
char * timeZone = "<tz-string>";  // in your ino-code and call sSetTz(timeZone) in setup().
  "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"  EU Amsterdam/Barcelona with Summertime (DST)
  "EST5EDT,M3.2.0,M11.1.0"  USA Eastern Time with DST
  "CET-1"  EU Amsterdam/Barcelona NO Summertime (DST)
  "CET+0"  Coordinated Universal Time (UTC) / Greenwich Mean Time (GMT)
If we use time from an NTP server, then we need to have an internet connection:
This solution with my sWiFi.h library prevents us from starting the application without the correct time.
Use the value syncTime to auto re-sync the time. (what about: IP, OTA, TIME, WTHR and WS http://www.kendziorra.nl/arduino/120)
/** directives used in sWiFi.h **/
#define USE_IP   false // if using a static IP (is needed with: USE_WS)
#define USE_OTA  false // ArduinoOTA
#define USE_TIME true  // NTP, date, time, timezone, DST/Summertime (using my sMsecTime.h)
#define USE_WTHR false // Weather, Sunrise, Sunset - sOpenweathermap.h
#define USE_WS   false // WebSockets Server - library: https://github.com/Links2004/arduinoWebSockets
const char *ssid = "your own"@,
       *password = "your own"@;
// ***** List of timezones https://sites.google.com/a/usapiens.com/opnode/time-zones
char *timeZone = "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"; // EU Amsterdam/Barcelona /Summertime
const time_t syncTime = 12 * 3600; // NTP time sync interval in sec. if 0 then NOT used
#include <sWiFi.h> // always under the optional #define declarations 
void setup() {
  stdSetup(); // is necessary on this place - init all your defined choices  
  // and your code
}
void loop() {
  wifiOn(); // is necessary on this place - WiFi 'stays alive' and sync with NTP time
  // and your code
}
How simple to use?:
Basic just three lines of code to get eighteen current local time and date values! (see structure sDateTime).
Or use it as the Arduino "Time.h" or "TimeLib.h".
#define USE_TIME true
const char *ssid = "your own"@,  /** @: compile error, enter your own values **/
       *password = "your own"@;
char *timeZone = "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00"@; // EU Amsterdam/Barcelona/Summertime
const time_t syncTime = 12 * 3600;@ // NTP time sync interval in sec. if 0 then NOT used
#include <sWiFi.h> // always under the time declarations 

void setup() {
  Serial.begin(115200);
  while (!Serial); delay(1000);
  Serial.println("\n");
  stdSetup(); // is necessary on this place - init all your defined choices 
  char *_tz = getenv("TZ");
  Serial.printf("used timeZone: %s\n", _tz);
}
void loop() {
  wifiOn(); // is necessary on this place - connection 'stays alive' control - sync NTP time 
  static bool gmt = false; // GMT: N/Y false/true
  // use it as the Arduino "Time.h" or "timeLib.h"
  time_t t = now();
  Serial.printf("%02u-%02u-%04u %02u:%02u:%02u local time "
                "weekday: %02u, yweek: %u, yday: %03u\n",
                day(t), month(t), year(t),
                hour(t), minute(t), second(t),
                weekday(t), yweek(t), yday(t));
  // use it with my "sMsecTime.h" sDateTime and sEpoch stuctures 
  sDateTime td = sTimeDate(false);  // get time and date values from sNow()
  Serial.printf("%02d:%02d:%02d.%03d %s %02d %s (%02d) %02d "
                "wday:%2d,  week:%3d, yday:%4d, ",
                dt.hour, dt.minute, dt.second, dt.msec, // time with milliseconds
                dt.dayS, dt.day, dt.monthS, dt.month, dt.year, // month, day and year
                dt.wday, dt.week, dt.yday); // diverse
  if (!gmt) Serial.printf("dst: %s\n\n", (dt.dst > 0 ? "Y" : "N")); // DST
  else Serial.println("GMT/UTC\n");
  gmt = !gmt;
  delayMicroseconds(987654); // almost a second to show the millisecond change 
}
OUTPUT: localIP: 192.168.178.25
        used timeZone: CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00 
        27-07-2020 13:52:14 local time weekday: 01, yweek: 31, yday: 209
        13:52:14.246 Mon 27 July (07) 2020 wday: 1,  week: 31, yday: 209, dst: Y

        27-07-2020 13:52:15 local time weekday: 01, yweek: 31, yday: 209
        11:52:15.235 Mon 27 July (07) 2020 wday: 1,  week: 31, yday: 209, GMT/UTC 
How to calc and split a time?:
Two timestamps, ep1 and ep2, calculate the absolute difference, ep, and split it into units of time.
sEpoch ep1 = {.sec = 1589106630, .msec = 250}; // D:10 m:5 2020 10:30:30.250
sEpoch ep2 = sMakeTime(14, 40, 50, 500, 15, 5, 2020); // h, m, s, ms, D, M, Y
sEpoch ep  = sAbsDiff(ep1, ep2);  // absolute difference calculation |X-Y| 
sSMHD sp = sTimeSplit(ep.sec);    // split timestamp in days, hours, minutes, seconds
Serial.printf("The absolute difference is\nsAbsDiff-XY sec: %010d, msec: %03d\n"
              "sTimeSplit days: %d, hours: %02d, minutes: %02d, seconds: %02d\n",
              ep.sec, ep.msec, sp.days, sp.hours, sp.minutes, sp.seconds);
OUTPUT: The absolute difference is
        sAbsDiff-XY sec: 0000447020, msec: 250
        sTimeSplit days: 5, hours: 04, minutes: 10, seconds: 20
How to check the correctness of the sMsecTime.h times:
That is quite simple, select and copy a timestamp and go to: https://www.epochconverter.com/

How to print (u)int64_t values?:
Useful to print the result from sTimestampInt().
Use the (s)printf specifiers length  ll | long long int | unsigned long long int 
int64_t myInt64value = 9223372036854775807;
Serial.printf("This \"%%lld\" print a int64_t: %lld\n", myInt64value);
OUTPUT: This %lld print a int64_t: 9223372036854775807
sMsecTime.h SimpleTime Functions, Enum and Structures:
(the basic functions and structures are highlighted)
void sSetTz(tz);            // set Time Zone
bool sGetNTP(tz);           // get time from server
int64_t sTimestampInt();    // int timestamp in millis from sNow()
...  or              (ep);  // ... from sEpoch ep time
String sTimestampStr();     // str timestamp in millis from sNow()
...  or             (ep);   // ... from sEpoch ep time
sEpoch sMakeTime(int64_t);  // get time from 64 bits timestamp
sEpoch sMakeTime(h, m, s, ms, D, M, Y);  // time from values
sEpoch sNow();              // current time
...  or    (ep);            // current time +/- a sEpoch ep-offset in sec and msec
sDateTime sTimeDate(bool);  // get a set of time and date values from sNow()
...  or            (bool, ep); // ... from sEpoch ep time (bool: false=local, true=GMT)
sEpoch sAbsDiff(_X, _Y);    // absolute difference from sEpoch _X and sEpoch _Y
...  or        (_X);        // ... from sEpoch _X and sNow() 
sSMHD sTimeSplit(time_t);   // split seconds in days, hours, minutes and seconds
                            //
time_t now();               // get a local or user time
...  or   (t);              // ... current time +/- a offset in sec
uint16_t year();            // compatible with  Arduino "Time.h" or "TimeLib.h"
...  or      (t);           // ... timestamp in sec
uint8_t month();            // compatible with  Arduino "Time.h" or "TimeLib.h"
...  or      (t);           // ... timestamp in sec
uint8_t day();              // compatible with  Arduino "Time.h" or "TimeLib.h"
...  or    (t);             // ... timestamp in sec
uint8_t hour();             // compatible with  Arduino "Time.h" or "TimeLib.h"
...  or     (t);            // ... timestamp in sec
uint8_t minute();           // compatible with  Arduino "Time.h" or "TimeLib.h"
...  or       (t);          // ... timestamp in sec
uint8_t second();           // compatible with  Arduino "Time.h" or "TimeLib.h"
...  or       (t);          // ... timestamp in sec
uint8_t weekday();          // compatible with  Arduino "Time.h" or "TimeLib.h"
...  or      (t);           // ... timestamp in sec
uint8_t yweek();            // week of the year
...  or      (t);           // ... timestamp in sec
uint16_t yday();            // day of the year
...  or      (t);           // ... timestamp in sec

struct sEpoch {  // timestamp and milliseconds
  time_t sec;    // UNIX timestamp
  int16_t msec;  // miliseconds 000-999
};
struct sDateTime {  // local time and date
  // set by function: sDateTime sTimeDate()
  time_t sec;  // UNIX timestamp (it's a int32_t)
               // GMT < 0, MIN: 13 December 1901 20:45:52
               // GMT == 0, | :  1 January  1970 00:00:00
               // GMT > 0, MAX: 19 January  2038 03:14:07
  int16_t msec;     // miliseconds 000-999
  int8_t second;    // seconds 00-59
  int8_t minute;    // minutes 00-59
  int8_t hour;      // hours 00-23
  int8_t day;       // day 01-31
  int8_t month;     // month 01-12
  int16_t year;     // year 1901-2038
  int8_t week;      // week 01-53
  int8_t wday;      // weekday 1-7
  int16_t yday;     // yearday 001-366
  // timezone and DST
  time_t zone;      // seconds
  time_t dst;       // seconds
  time_t offset;    // zone + dst (sec - offset = UTC/GMT)
  // Long/Short month/day names
  char monthL[16];  // month Long name
  char monthS[10];  // month Short name
  char dayL[16];    // day Long name
  char dayS[10];    // day Short name
};
struct sSMHD {  // split timestamp to time and days
  // set by function: sSMHD sTimeSplit(time_t _t)
  int8_t seconds;  // seconds 00-59
  int8_t minutes;  // seconds 00-59
  int8_t hours;    // hours 00-23
  int16_t days;    // days 0-n
};
enum {sOneminute = 60, sOnehour = sOneminute * 60, sOneday = sOnehour * 24};
/*********************************************************************
** you can change these default values in setup(), see the examples **
**                --------------------                              **
**********************************************************************/
// ***** strftime: http://www.cplusplus.com/reference/ctime/strftime
// ***** we assume by default that Monday is the first day of the week (ISO 8601)
char _week = 'V';  // strftime week number ((ISO 8601))
char _wday = 'u';  // strftime day of the week ((ISO 8601))
char _monthsLstr[12][21] = {"January", "February", "March", "April", "May", "June","July",
                            "August", "September", "October", "November", "December"};
char _monthsSstr[12][11] = {"Jan",  "Feb", "Mar",  "Apr", "May", "June", 
                            "July", "Aug", "Sept", "Oct", "Nov", "Dec"};
char _daysLstr[7][21] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
                         "Saturday", "Sunday"};  // strftime _wday: 'u' (ISO 8601)
char _daysSstr[7][11] = {"Mon", "Tue", "Wed", "Thu", "Fri", 
                         "Sat", "Sun"};  // strftime _wday: 'u' (ISO 8601)
// the "change default values" functions are (see the examples): 
sSetWeek(myweek); // change strftime week code
sSetWday(mywday); // change strftime weekday code
// change long and short month and day names
sSetMonthDayStr(monthsLstr, monthsSstr, daysLstr, daysSstr);