date icon indicating copy to clipboard operation
date copied to clipboard

Run time specification of tzdb location with environment variable

Open samuel-emrys opened this issue 2 years ago • 3 comments

Hi Howard/all,

Summary

To facilitate package management, I think it would be very useful to add an environment variable specifying the location of either a binary or a source database, which is read at runtime to discover the location of the database. This has the following benefits:

  • Allows a user to keep their timezone database up to date without considering re-compilation
  • Allows a user to be flexible about where the timezone database is stored
  • Allows date to be used portably without compilation of paths into the resulting library (when not used as header only)

Context

I'm currently in the process of uplifting the conan date package to use the newly added tz package, which packages the tzdb. Currently it only supports a binary package, but can be uplifted to also package the source distribution.

The challenge I'm facing is that conan stores it packages in the conan cache, ~/.conan/p. Conan provides the facilities to make these packages available at runtime to consumer libraries via environmental scripts, which would be a convenient way to manage the tzdb to ensure that it remains modern, and distribute it with software releases. The challenge is that there doesn't seem to be a flexible way to tell date that this is where the tzdb lives.

To illustrate this, I thought I'd enumerate the ways that currently exist to customise tzdb location and talk about why these are unsuitable from a packaging perspective.

USE_SYSTEM_TZ_DB=1

  • This will set AUTO_DOWNLOAD=0 and HAS_REMOTE_API=0 to ensure that what's available locally is used
  • Will also set INSTALL=. and USE_OS_TZDB=1, which will use the compiled variant of tzdb in the system installation location
  • From a package management perspective, this does most of the right things, except that it doesn't appear as though I can define the location of the database. It looks specifically at the following locations, as far as I can tell:
    • /usr/share/zoneinfo
    • /usr/share/zoneinfo/uclibc
    • /var/db/timezone/zoneinfo
    • /etc/localtime

The problem for package management

Because the location of the database can't be defined, it's not possible to use this to point at a portable version of a compiled database in a custom location.

I could look at attempting to install tzdb from conan into the system locations here, but I don't feel this would be wise - this is the domain of system package management and I'm not sure what effect this would have on system package managers.

MANUAL_TZ_DB=1

  • This will set AUTO_DOWNLOAD=0 and HAS_REMOTE_API=0 to ensure that what's available locally is used
  • Will also set USE_OS_TZDB=0 to ensure that the system database is not used, if present
  • This expects the user will either:
    • invoke set_install(const std::string& s) in their code to set the location of the database. My assumption is that this refers to a source database only, and this can't be configured for a binary database.
    • Pass a value to INSTALL= when compiling, which means that ${INSTALL}/tzdata is searched for the source database
    • Populate ~/Downloads/tzdata themselves

The problem for package management

  • Relies on the user to set something that can be reasonably captured as a property of the date recipe - adds additional boilerplate
  • Only allows setting for a source version of the database
  • If the user actually specifies a path here, this would create a non-portable binary because it contains a path unlikely to exist in the deployment environment

MANUAL_TZ_DB=0 and USE_SYSTEM_TZ_DB=0

  • Will set AUTO_DOWNLOAD=1, HAS_REMOTE_API=1, USE_OS_TZDB=0
  • Will add a dependency on curl and attempt to download the latest version of the database src to ~/Downloads/tzdata

The problem for package management

Offloads management of tzdata as a dependency to the date library, rather than managed by the dependency (package) manager. Not a problem in and of itself, but orthogonal to the philosophy of using a package manager to manage dependencies.

Related issues

Customisation/management of these locations seems like an oft-requested feature:

  • https://github.com/HowardHinnant/date/issues/541
  • https://github.com/HowardHinnant/date/pull/611
  • https://github.com/HowardHinnant/date/issues/305
  • https://github.com/HowardHinnant/date/issues/472
  • https://github.com/HowardHinnant/date/issues/397
  • https://github.com/HowardHinnant/date/issues/626
  • https://github.com/HowardHinnant/date/issues/564
  • https://github.com/HowardHinnant/date/pull/639

These seem to have been stagnant for a few years now - in particular #611 seems to be the closest to what would be required here. Is there any intention to add this kind of customisation to the date library or is this kind of thing not being considered now that there's been acceptance of this into stdlib?

samuel-emrys avatar Jun 18 '23 12:06 samuel-emrys

@HowardHinnant do you have any thoughts on whether this can be supported?

samuel-emrys avatar Dec 06 '23 16:12 samuel-emrys

I'm sure it could be. I don't have the time to do it, or even to review someone else's work. Plus I am encouraging migration off of this library to C++20 chrono. I know that implementations are lagging, but MSVC is up to date, and gcc will be with gcc-14. Adding this feature (which does not exist in C++20 chrono) would hamper such migration.

I would have no objection whatsoever to someone forking this repository and providing this functionality on their own fork. I'd even be willing to link to it on my readme.

HowardHinnant avatar Dec 06 '23 17:12 HowardHinnant

No problems, thanks for providing your position. I'll see if I can put some time into an implementation of this - I think the easiest way for me to handle this would be to submit a PR against this repo and use that as a patch for the conan recipe. Appreciate you may not have time to review and it sounds like acceptance might be counter to your aims of promoting chrono migration; if that position doesn't change then anybody who wants to use the patch they can use my fork (or, hopefully the conan package).

As for the migration - I'm fully on board with a desire to move to chrono and will as soon as it satisfies my requirements. The following are currently my blockers:

  • I can't use C++20 for all of the projects in which I require the date features
  • Many of the projects I work on require multi-compiler/compiler version/operating system compatibility, so if the functionality is present on Windows but not macOS or Linux, then I'm constrained to the lowest common denominator.

So, until the relevant chrono implementations reach sufficient maturity to unblock the above, there will still be a use case for using date for us.

samuel-emrys avatar Dec 07 '23 01:12 samuel-emrys