Localtime support in low-memory IoT devices
During the last several years, personal computers and smartphones became capable of displaying the local time, correctly adjusted for daylight saving time (DST) - and without requiring human intervention beyond selecting the correct timezone.
Nowadays, there are also some IoT devices, which need to support local time management - displaying it, or otherwise making it available.
Timekeeping is performed using the Internet protocol NTP, which provides the correct UTC. When using a PC or a smartphone, the timezone is usually selected by manual user action.
However, some IoT devices may not have the UI needed for convenient timezone selection. Then it is desirable to support automatic timezone selection as a default.
How to implement automatic timezone selection?
There are some websites, which discover your IP address and provide you with the best guess of your timezone.
The following tables lists some of those websites.
|Name||Account or API key?||Finds your IP?||Response format|
|Timezone API||Yes||Yes||JSON (including tz_string)|
Since those websites usually provide the timezone name rather than the
string describing the DST transition dates (the so-called
the next step is to figure out the DST transition dates from
the timezone name.
In devices with plenty of memory this is carried out by means of a timezone database.
For example, in Debian/Ubuntu based systems, this
database is stored in the
/usr/share/zoneinfo directory and occupies 3.5MB
(the relevant package in Ubuntu 18.04 is
tzdata and its version,
as of Nov. 2019, is
Memory constrained IoT devices
However, IoT devices are typically based upon memory-constrained controllers and cannot afford to store locally the whole timezone database - just to correctly determine the local time for a single timezone.
Therefore, IoT devices need to access an Internet based service to get the correct timezone information, just as they get UTC time updates using NTP. In other words, those IoT devices effectively outsource the timezone database management.
Internet service for providing the timezone information
An Internet service, for providing the correct
to a timezone name, needs to keep the timezone database up to date at
I implemented the internet service as follows.
- A machine, running an Ubuntu 18.04 installation with a webserver, is used.
- The Internet service is implmented as a small WSGI-based website.
- A script scans the
/usr/share/zoneinfocontents and creates a small database for translating timezone names into the corresponding
- There is a mechanism for invoking the above script and restarting the web server
each time the
tzdatapackage is updated/installed/re-installed.
The actual implementation is described in the following section.
Parts of the project
- WSGI-based website (the "tzstring website") for mapping from timezone into tz_string.
- Database builder
- Trigger scripts
- Sample client code
wsgi.py- creates the WSGI application
tzstring.py- stores the
tz_stringtranslation database in memory and provides the
tz_stringas a response to queries with the
timezoneparameter. When a
timezoneis not recognized,
A redacted Apache2 configuration file is provided as well
build_tz_string_db.py- scans the
/usr/share/zoneinfocontents and builds from them the database used by
Those trigger scripts cause the database builder script to be executed
and the webserver to be restarted whenever the
tzdata package is
99zz-tzdata-trigger-postupgradeconfigures apt to execute, before actual upgrade,
tzdata-trigger-postupgrade.shand provide it with a list of packages to be updated. In addition to the above, apt is configured to execute
tzdata-update-tzstring-db.shonce all packages have been updated.
tzdatais one of the packages to be updated. If yes, it gets
tzdata-update-tzstring-db.shto actually do its job.
tzdata-update-tzstring-db.shperforms the actual tzstring database and webserver restart.
Sample client code
The provided sample client code is an ESP8266 sketch. See usage instructions below.
What does it do?
During the setup phase:
- The client code performs the usual initializations.
- Then it tries to connect to WiFi using already-configured SSID and password.
- If unsuccessful, it opens an access point whose SSID and password are the
- An user can configure SSID and password by connecting to the above
access point and browsing to
- If unsuccessful, it opens an access point whose SSID and password are the values of
- Once the client code connects to the user's WiFi access point and has access to the Internet, it configures the UTC using NTP.
- Finally, the client code retrieves the
tz_stringfor the timezone in which the system is connected to the Internet.
During the loop phase:
- If more than 24 hours passed since the last NTP update, NTP is queried and the UTC is updated.
- If the UTC has changed (it changes once per second), new localtime is computed from it and written to the Serial port.
The loop phase is repeated 10 times per second.
The client code modules
ESP8266_auto_timezone_demo.ino - is the main module and it operates as described above.
get_tz_string.ino - is in charge of fetching the
tz_stringfor the current timezone.
Example: for the timezone
Asia/Jerusalem, the tz_string value is
urlencode.ino - is in charge of URLencoding the timezone before sending it to the tzstring website.
The sample client code (before redacting) was compiled on Arduino IDE v1.8.10 with some ESP8266 libraries installed. The board used was NodeMCU v3, and the IDE was configured to work with board "NodeMCU 1.0 (ESP-12E Module)".
The sample client code does not include code for manual overrides of the timezone determination, entry of custom tz_string, or manual setting of the local time vs. UTC offset.
The code, as it is, is not ready for running. You need to edit files as follows.
- Insert into
get_tz_string.inothe domain names of the websites you'll actually use for discovering your timezone (a list of suitable services can be found in
get_tz_string.h) and for converting it into tz_string (you need to register a domain name and set up this website).
- You need also to choose an username instead of
userand edit all usages of this username in the files.
- You may want also to change some filenames and the locations of some scripts and data files.
- I did not invest time in polishing the project's files.
- When the project is properly polished, it should include also a cookiecutter type configuration file.
- After redacting the files, they were not tested. However, they are based upon a working project.