.. _library_dates_tz:

``dates_tz``
============

Bridge library linking the ``dates`` and ``tzif`` libraries for
zone-aware date-time conversions. Provides predicates that convert UTC
date-times to civil local date-times and vice-versa, handling DST
transitions including ambiguous (fold) and non-existent (gap) times.
Also provides cross-zone conversion that routes through UTC as an
intermediate representation.

This library requires unbounded integer arithmetic support from the
backend Prolog compiler (as does the ``tzif`` library it depends on). It
is not available on backends where the ``bounded`` Prolog flag is
``true``.

API documentation
-----------------

Open the
`../../apis/library_index.html#dates_tz <../../apis/library_index.html#dates_tz>`__
link in a web browser.

Loading
-------

To load all entities in this library, load the ``loader.lgt`` utility
file:

::

   | ?- logtalk_load(dates_tz(loader)).

Testing
-------

To test this library predicates, load the ``tester.lgt`` file:

::

   | ?- logtalk_load(dates_tz(tester)).

Usage
-----

Zone data must be loaded separately into the ``tzif`` cache before
calling any ``dates_tz`` predicates. For example:

::

   :- initialization((
       logtalk_load(dates_tz(loader)),
       tzif::load(file('/usr/share/zoneinfo/America/New_York', 'America/New_York')),
       tzif::load(directory('/usr/share/zoneinfo'))
   )).

Examples
--------

Convert a UTC ``date_time/6`` compound to the civil local date-time in
the named IANA zone. The UTC instant always has exactly one local
representation.

::

   |?- dates_tz::utc_to_local_tz(date_time(2024,1,15,12,0,0), 'America/New_York', Local).
   Local = date_time(2024,1,15,7,0,0).

Convert a civil local ``date_time/6`` compound in the named zone to UTC
using strict interpretation. Fails silently if the local time falls in a
DST gap (non-existent) or a DST fold (ambiguous). Throws an error if the
zone is not cached.

::

   | ?- dates_tz::local_to_utc_tz(date_time(2024,1,15,7,0,0), 'America/New_York', UTC).
   UTC = date_time(2024,1,15,12,0,0).

Convert a civil local date-time to UTC with an explicit resolution mode.
The mode can be:

- ``strict`` — fail unless exactly one interpretation exists
- ``first`` — prefer the earliest valid interpretation (earliest UTC
  instant)
- ``second`` — prefer the latest valid interpretation (latest UTC
  instant)
- ``all`` — enumerate all valid interpretations in chronological order
  (non-deterministic)

Fall-back fold in New York: 2024-11-03 01:30 occurs twice:

::

   | ?- dates_tz::local_to_utc_tz_with_resolution(
        date_time(2024,11,3,1,30,0), 'America/New_York', first, UTC).
   UTC = date_time(2024,11,3,5,30,0).  % EDT interpretation

   | ?- dates_tz::local_to_utc_tz_with_resolution(
        date_time(2024,11,3,1,30,0), 'America/New_York', second, UTC).
   UTC = date_time(2024,11,3,6,30,0).  % EST interpretation

Convert a civil local date-time from one IANA zone to another, routing
through UTC. Uses strict interpretation for the source zone: fails if
the source local time is ambiguous or non-existent. Requires both zones
to be cached.

::

   | ?- dates_tz::convert_zones(
        date_time(2024,1,15,7,0,0), 'America/New_York', 'Asia/Kathmandu', Result).
   Result = date_time(2024,1,15,17,45,0).

Convert a civil local date-time between zones with an explicit
resolution mode applied to the source zone. Useful when the source local
time may be ambiguous due to a DST transition.

::

   | ?- dates_tz::convert_zones_with_resolution(
        date_time(2024,11,3,1,30,0), 'America/New_York', first, 'Asia/Kathmandu', Result).
   Result = date_time(2024,11,3,11,15,0).

Notes
-----

- Date-time values are represented as
  ``date_time(Year, Month, Day, Hour, Minute, Second)`` compounds,
  consistent with the ``dates`` library.

- UTC offset arithmetic is performed via integer seconds using
  ``date::add_duration/3`` and ``date::subtract_duration/3``.

- This library does not provide a system clock or current-time
  predicate. Use the ``dates`` library's ``date::now/6`` or equivalent
  for the current time.

- For performance when converting many instants in the same zone, load
  all required zones once at startup and keep them in the ``tzif``
  cache.
