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
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/UTCHow 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: 9223372036854775807sMsecTime.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 sRiseSet sSun(time_t t, double lat, double lon, bool gmt = false); // sunRise and sunSet times struct sEpoch { // timestamp and milliseconds time_t sec; // UNIX timestamp int16_t msec; // miliseconds 000-999 }; struct sRiseSet { time_t rise; time_t set; }; 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);