|
roo_time
API Documentation for roo_time
|
Microcontroller library for basic management of elapsed time, wall time, and date time with multi-timezone support. Provides type safety around durations and different time units, guarding against common programming errors like confusing time units, or confusing 'timestamps' with 'durations'.
Internally, uses microsecond precision, and stores the time as int64_t (in other words, it will not overflow on you as millis() does).
The library is designed to work seamlessly with various RTC device drivers. For example, if you have a DS3231 real-time clock, you can use this library to keep the raw, UTC time in DS3231, and deal with time zones and daylight savings conversions on top of that.
This library is extensively tested on the ESP32-family microcontrollers. It works both with Arduino and raw esp-idf. It also works on RP2040-based Raspberry Pi Pico.
The library is written in standard C++, and the only platform-dependent function is the one behind Uptime::Now().
Example usage:
The library works well with device-specific libraries, via the base abstraction of a 'WallTimeClock'. On ESP chips, you can use 'SystemClock' to read time from NTP servers via WiFi. For DS3231, you can use a companion library roo_time_ds3231. If you have another time source, you can use it by implementing a simple adapter:
If your device returns date/time components (year, month, day, etc.), you can convert them to 'WallTime' using the conversion functions described below. (Also, see the roo_time_ds3231 library for a concrete illustration).
Once you have an implementation of the 'WallTimeClock', you can use it like this:
You can specify datetimes, and convert them from and to wall time:
Timezone is just a type-safe duration wrapper:
Daylight saving rules are not explicitly supported, because they are very complicated and change often. It is, however, reasonably simple to implement the logic yourself. For example, in Poland, summer time begins at 2AM local time on the last Sunday of March, and it ends at 3AM local time on the last Sunday of October. The appropriate daylight-savings-aware clock looks like this:
The library will protect you from making common mistakes, such as mixing up time units, mixing up uptime (i.e. the time since the device is running) with wall time (i.e. duration since Epoch), and mixing up durations with time points:
Duration narrowing conversions expose three rounding modes:
inXxx() and inXxxRoundedDown() round toward zero.inXxxRoundedUp() rounds away from zero.inXxxRoundedNearest() rounds to nearest, with ties (exact half) away from zero.Examples for milliseconds:
Micros(1501).inMillisRoundedDown() is 1, Micros(-1501).inMillisRoundedDown() is -1.Micros(1501).inMillisRoundedUp() is 2, Micros(-1501).inMillisRoundedUp() is -2.Micros(500).inMillisRoundedNearest() is 1, Micros(-500).inMillisRoundedNearest() is -1.The Uptime and WallTime classes are trivial wrappers around int64. For such classes, construction/destruction has zero cost, as it is completely optimized away. The compiler will generate code that will look exactly as if you directly operated on the int64.
The compiler is good at omitting stuff you don't use. For example, if you never call any date conversion function, it will have zero effect on your binary size. And, because of aggressive optimization mentioned above, the cost of using basic functionality of WallTime and Uptime is essentially zero in comparison to the equivalent code using integer types directly.