[PATCH] libstdc++: Document std::chrono::tzdb database implementation.

Jonathan Wakely <[email protected]> Mon, 3 Aug 2026 17:31:00 +0100
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.libstdc++.devel
Message-ID <[email protected]>
From: Tomasz KamiƄski <[email protected]>

libstdc++-v3/ChangeLog:

	* doc/Makefile.am: Add time.xml.
	* doc/Makefile.in: Regenerate.
	* doc/html/*: Regenerate.
	* doc/xml/manual/spine.xml: Add time.xml.
	* doc/xml/manual/time.xml: New file.
---

Same patch again but without the huge changes to the generated HTML
files, because that made the patch too big for gcc-patches.

 libstdc++-v3/doc/Makefile.am                  |   1 +
 libstdc++-v3/doc/Makefile.in                  |   1 +
 libstdc++-v3/doc/html/index.html              |  15 +-
 libstdc++-v3/doc/html/manual/api.html         |   2 +-
 libstdc++-v3/doc/html/manual/atomics.html     |   8 +-
 .../doc/html/manual/bitmap_allocator.html     |   4 +-
 .../html/manual/bitmap_allocator_impl.html    |   6 +-
 libstdc++-v3/doc/html/manual/concurrency.html |   8 +-
 libstdc++-v3/doc/html/manual/debug.html       |   6 +-
 libstdc++-v3/doc/html/manual/debug_mode.html  |   6 +-
 .../doc/html/manual/debug_mode_design.html    |   4 +-
 .../doc/html/manual/debug_mode_semantics.html |   4 +-
 .../doc/html/manual/debug_mode_using.html     |   6 +-
 .../doc/html/manual/ext_algorithms.html       |   6 +-
 .../doc/html/manual/ext_compile_checks.html   |   6 +-
 .../doc/html/manual/ext_concurrency.html      |   6 +-
 .../doc/html/manual/ext_concurrency_impl.html |   4 +-
 .../doc/html/manual/ext_concurrency_use.html  |   2 +-
 .../doc/html/manual/ext_containers.html       |   4 +-
 .../doc/html/manual/ext_demangling.html       |   6 +-
 libstdc++-v3/doc/html/manual/ext_io.html      |   6 +-
 .../doc/html/manual/ext_iterators.html        |   6 +-
 .../doc/html/manual/ext_numerics.html         |   6 +-
 libstdc++-v3/doc/html/manual/ext_preface.html |   4 +-
 libstdc++-v3/doc/html/manual/ext_sgi.html     |   4 +-
 .../doc/html/manual/ext_utilities.html        |   6 +-
 libstdc++-v3/doc/html/manual/extensions.html  |   8 +-
 libstdc++-v3/doc/html/manual/fstreams.html    |   2 +-
 libstdc++-v3/doc/html/manual/index.html       |  31 ++-
 libstdc++-v3/doc/html/manual/io.html          |  13 +-
 libstdc++-v3/doc/html/manual/io_and_c.html    |   6 +-
 libstdc++-v3/doc/html/manual/memory.html      |   6 +-
 .../doc/html/manual/mt_allocator.html         |   4 +-
 .../doc/html/manual/mt_allocator_design.html  |   4 +-
 .../html/manual/mt_allocator_ex_multi.html    |   4 +-
 .../html/manual/mt_allocator_ex_single.html   |   2 +-
 .../doc/html/manual/mt_allocator_impl.html    |   2 +-
 .../doc/html/manual/numerics_and_c.html       |   8 +-
 .../doc/html/manual/parallel_mode.html        |   4 +-
 .../doc/html/manual/parallel_mode_design.html |   2 +-
 .../html/manual/parallel_mode_semantics.html  |   4 +-
 .../doc/html/manual/parallel_mode_test.html   |   4 +-
 .../doc/html/manual/parallel_mode_using.html  |   4 +-
 .../policy_based_data_structures_test.html    |   2 +-
 .../html/manual/policy_data_structures.html   |  16 +-
 .../manual/policy_data_structures_ack.html    |   4 +-
 .../manual/policy_data_structures_design.html |  70 ++---
 .../manual/policy_data_structures_using.html  |   6 +-
 libstdc++-v3/doc/html/manual/status.html      |   4 +-
 .../doc/html/manual/std_contents.html         |   9 +-
 libstdc++-v3/doc/html/manual/streambufs.html  |   4 +-
 .../doc/html/manual/stringstreams.html        |   2 +-
 libstdc++-v3/doc/html/manual/test.html        |   8 +-
 libstdc++-v3/doc/html/manual/time.html        | 176 +++++++++++++
 libstdc++-v3/doc/html/manual/using.html       |   2 +-
 .../doc/html/manual/using_macros.html         |  10 +-
 libstdc++-v3/doc/xml/manual/spine.xml         |  10 +-
 libstdc++-v3/doc/xml/manual/time.xml          | 242 ++++++++++++++++++
 58 files changed, 623 insertions(+), 187 deletions(-)
 create mode 100644 libstdc++-v3/doc/html/manual/time.html
 create mode 100644 libstdc++-v3/doc/xml/manual/time.xml

diff --git a/libstdc++-v3/doc/Makefile.am b/libstdc++-v3/doc/Makefile.am
index 330b07ccf8ce..69f5faafc266 100644
--- a/libstdc++-v3/doc/Makefile.am
+++ b/libstdc++-v3/doc/Makefile.am
@@ -357,6 +357,7 @@ xml_sources_manual = \
 	${xml_dir}/manual/support.xml \
 	${xml_dir}/manual/test.xml \
 	${xml_dir}/manual/test_policy_data_structures.xml \
+	${xml_dir}/manual/time.xml \
 	${xml_dir}/manual/using.xml \
 	${xml_dir}/manual/using_exceptions.xml \
 	${xml_dir}/manual/utilities.xml \
diff --git a/libstdc++-v3/doc/Makefile.in b/libstdc++-v3/doc/Makefile.in
index 6e7a5a0f9084..39a6988d4853 100644
--- a/libstdc++-v3/doc/Makefile.in
+++ b/libstdc++-v3/doc/Makefile.in
@@ -509,6 +509,7 @@ xml_sources_manual = \
 	${xml_dir}/manual/support.xml \
 	${xml_dir}/manual/test.xml \
 	${xml_dir}/manual/test_policy_data_structures.xml \
+	${xml_dir}/manual/time.xml \
 	${xml_dir}/manual/using.xml \
 	${xml_dir}/manual/using_exceptions.xml \
 	${xml_dir}/manual/utilities.xml \
diff --git a/libstdc++-v3/doc/xml/manual/spine.xml b/libstdc++-v3/doc/xml/manual/spine.xml
index eff72bc13d72..47536f000778 100644
--- a/libstdc++-v3/doc/xml/manual/spine.xml
+++ b/libstdc++-v3/doc/xml/manual/spine.xml
@@ -197,15 +197,19 @@
 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml" href="numerics.xml">
 </xi:include>
 
-<!-- Chapter 10 : Input Output -->
+<!-- Chapter 10 : Time -->
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml" href="time.xml">
+</xi:include>
+
+<!-- Chapter 11 : Input Output -->
 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml" href="io.xml">
 </xi:include>
 
-<!-- Chapter 11 : Atomics -->
+<!-- Chapter 12 : Atomics -->
 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml" href="atomics.xml">
 </xi:include>
 
-<!-- Chapter 12 : Concurrency -->
+<!-- Chapter 13 : Concurrency -->
 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml" href="concurrency.xml">
 </xi:include>
 
diff --git a/libstdc++-v3/doc/xml/manual/time.xml b/libstdc++-v3/doc/xml/manual/time.xml
new file mode 100644
index 000000000000..b61be5852ef2
--- /dev/null
+++ b/libstdc++-v3/doc/xml/manual/time.xml
@@ -0,0 +1,242 @@
+<chapter xmlns="http://docbook.org/ns/docbook" version="5.0"
+	 xml:id="std.time" xreflabel="Time">
+<?dbhtml filename="time.html"?>
+
+<info><title>
+  Time
+  <indexterm><primary>Time</primary></indexterm>
+</title>
+  <keywordset>
+    <keyword>ISO C++</keyword>
+    <keyword>library</keyword>
+  </keywordset>
+</info>
+
+<!-- Sect1 01 : Time zone database -->
+<section xml:id="std.time.zone.db" xreflabel=""><info><title>Time zone database</title></info>
+<?dbhtml filename="tzdb.html"?>
+
+   <para>
+     Since C++20 the <code>&lt;chrono&gt;</code> header provides time zone
+     support via <code>std::chrono::tzdb</code>, a complete interface to the
+     <link xmlns:xlink="http://www.w3.org/1999/xlink"
+     xlink:href="https://www.iana.org/time-zones">IANA Time Zone Database</link>.
+     The library supports converting times between UTC and the local time
+     in a specific time zone, querying UTC offsets and DST information for a
+     given time zone on a given date, and finding the system's current time zone.
+     Key entry points are <code>std::chrono::get_tzdb()</code> to access
+     the database, <code>std::chrono::locate_zone()</code> to look up
+     a zone by name, and <code>std::chrono::current_zone()</code> to obtain
+     the system's local time zone. The <code>std::chrono::zoned_time</code>
+     class template represents a time point in a given time zone.
+     The database can be reloaded at runtime
+     via <code>std::chrono::reload_tzdb()</code> to pick up updated zone
+     data without restarting the program.
+   </para>
+
+   <para>
+     The <link xmlns:xlink="http://www.w3.org/1999/xlink"
+     xlink:href="https://howardhinnant.github.io/date/tz.html">Time Zone Database
+     Parser</link> by Howard E. Hinnant is a valuable source of information and
+     examples of usage for the <code>date</code> library, on which the standard
+     API is based.
+   </para>
+
+   <section xml:id="zone.db.zic" xreflabel="tzdb uses zic format"><info><title>tzdb uses zic format</title></info>
+
+   <para>
+     When support is enabled (which is default) the time zone database class,
+     <code>tzdb</code>, uses the <link xmlns:xlink="http://www.w3.org/1999/xlink"
+     xlink:href="https://man7.org/linux/man-pages/man8/zic.8.html#FILES">
+     <code>zic</code> file format</link>, both as the format of the input
+     files, and for in-memory representation. This results in a reduced
+     memory footprint for many programs, as time zone data is stored in
+     a compact form until needed by the application.
+   </para>
+   <para>
+     The transitions to/from DST (Daylight Savings Time) are generated and
+     cached on the fly, when information
+     for a given zone is requested. Consequently, the initial request for
+     UTC conversion for a given <code>time_zone</code> object is slower.
+     To mitigate this, a <code>time_zone</code> can be expanded for a
+     particular time range at the start
+     of the program (and after each reload), by iterating over the
+     <code>sys_info</code> dequence, as in the example below.
+   </para>
+   <programlisting>
+     void
+     expand_zone(const std::chrono::time_zone* tz,
+                 const std::chrono::sys_seconds start,
+                 const std::chrono::sys_seconds end)
+     {
+       std::chrono::sys_seconds time = start;
+       while (time &lt; end) {
+         const std::chrono::sys_info&amp; info = tz->get_info(time);
+         time = info.end + std::chrono::seconds(1);
+       }
+     }
+   </programlisting>
+  </section>
+
+  <section xml:id="zone.current" xreflabel="current zone"><info><title>current zone</title></info>
+
+   <para>
+     The <code>time_zone</code> pointer returned from
+     <code>std::chrono::current_zone</code>, is determined by looking up
+     (by <code>std::chrono::locate_zone</code>) IANA zone name
+     determined as follows (for platforms other than AIX and Windows):
+   </para>
+   <itemizedlist>
+     <listitem>
+       On system supporting <code>readlink</code>, suffix components of the
+       path of the file linked by <code>/etc/localtime</code>. The suffixes
+       are matched in the other of increasing length, starting from the final
+       component, until the match is found in the time zone database.
+       Any repeated slashes (<code>//</code>) are eliminated.
+     </listitem>
+     <listitem>
+       Names stored in the files <code>/etc/timezone</code> (Debian
+       derivatives) or <code>/var/db/zoneinfo</code> (FreeBSD) in that order.
+     </listitem>
+     <listitem>
+       Values for <code>TIMEZONE</code> and <code>ZONE</code> keys in
+       <code>/etc/sysconfig/clock</code>.
+     </listitem>
+     <listitem>
+       <code>UTC</code>.
+     </listitem>
+   </itemizedlist>
+
+   <para>
+     For AIX, the value of <code>TZ</code> environment value is used, with
+     fallback to <code>UTC</code>.
+   </para>
+
+   <para>
+     On Windows <code>TimeZoneKeyName</code> is mapped to the IANA zone, using
+     internal mapping hard-coded in library, with fallback to <code>UTC</code>:
+   </para>
+   <itemizedlist>
+     <listitem>
+       If the returned <code>TimeZoneKeyName</code> is empty or DST is disabled,
+       then a value based on <code>Bias</code> is returned: <code>Etc/UTC</code>
+       for zero, <code>Etc/GMT+/-N</code> for value that is multiply of 60,
+       and empty string otherwise.
+     </listitem>
+     <listitem>
+       If the mapping contains a single entry for <code>TimeZoneKeyName</code>,
+       that name is used.
+     </listitem>
+     <listitem>
+       If <code>TimeZoneKeyName</code> corresponds to multiple IANA zones,
+       a 2-letter country code is used, retrieved by applying <code>GetGeoInfoW</code>
+       on the result of <code>GetUserGeoID(GEOCLASS_NATION)</code>.
+       If determining the country code fails, or no entry exits for a given code,
+       the first mapping entry (<code>001</code>) is returned.
+     </listitem>
+   </itemizedlist>
+  </section>
+
+  <section xml:id="zone.db.sources" xreflabel="data sources"><info><title>data sources</title></info>
+    <para>
+      Depending on the build configuration (see
+      <code>--with-libstdcxx-zoneinfo=</code> documentation in
+      <xref linkend="manual.intro.setup.configure">Configure section</xref>).
+      the content of the time zone database is sourced from
+      <filename>tzdata.zi</filename> and <filename>leapseconds</filename> files
+      located in <emphasis>zoneinfo_dir</emphasis>, or from static information
+      embedded in the library.
+    </para>
+
+    <para>
+      By default, <emphasis>zoneinfo_dir</emphasis> is set to the
+      system-specific default directory (if a suitable dir is known for target),
+      usually <code>/usr/share/zoneinfo</code>. If no such directory
+      exits, or it does not contain the required files in the correct format,
+      embedded static data is used as fallback.
+    </para>
+
+    <para>
+      In addition to <code>--with-libstdcxx-zoneinfo=</code> configure option
+      (used during GCC build), the path of <emphasis>zoneinfo_dir</emphasis>
+      can be overridden by the application by providing a definition of the
+      <code>__gnu_cxx::zoneinfo_dir_overrride()</code> function. The
+      returned path should be directory that contains <code>tzdata.zi</code>
+      and <code>leapseconds</code> files in the
+      <link xmlns:xlink="http://www.w3.org/1999/xlink"
+      xlink:href="https://man7.org/linux/man-pages/man8/zic.8.html#FILES">
+      <code>zic</code> format</link>.
+    </para>
+
+    <para>
+      The embedded timezone information corresponds to the copy of the
+      IANA database at the time of the release, and its version can be queried
+      using <code>std::chrono::get_tzdb().version</code>.
+    </para>
+
+    <para>
+      The full time zone database can be disabled when GCC is configured,
+      in which case a minimal time zone database is provided. This minimal
+      database can be identified by <code>chrono::get_tzdb().version</code>
+      being set to <code>"ersatz"</code>. This database contains leapseconds
+      data, <code>Etc/UTC</code>, <code>Etc/GMT</code> zones, and their aliases
+      (<code>Etc/Zulu</code>, <code>Etc/UCT</code>, <code>Etc/Universal</code>,
+      <code>Etc/Greenwich</code>, <code>Etc/GMT0</code>, <code>Etc/GMT+0</code>,
+      <code>Etc/GMT-0</code>). This information is sufficient to support
+      conversion between <code>utc_clock</code> and <code>sys_clock</code>,
+      as well as a <code>UTC</code> fallback for <code>current_zone</code>
+      (<xref linkend="zone.current">link</xref>).
+    </para>
+  </section>
+
+  <section xml:id="zone.db.iterator" xreflabel="tzdb_list::const_iterator extends lifetime">
+    <info><title>tzdb_list::const_iterator extends lifetime</title></info>
+
+    <para>
+      The <code>std::chrono::reload_tzdb()</code> function may be used to load
+      updated content of the <code>tzdata.zi</code> and <code>leapseconds</code>
+      files from <emphasis>zoneinfo_dir</emphasis> (if
+      <xref linkend="zone.db.sources">enabled</xref>). If the version is different
+      (<code>std::chrono::remote_version() != std::chrono::get_tzdb().version</code>),
+      a new element is added at the front of the <code>tzdb_list</code>.
+      This new database is used for subsequent calls to <code>current_zone</code>
+      and <code>locate_zone</code>.
+    </para>
+
+    <para>
+      The above process is thread-safe, and does not invalidate nor change any
+      pre-existing pointers to <code>time_zone</code> objects. However, for a
+      long-running application it may lead to accumulation of time zone data,
+      and thus increased memory usage. In most cases, this is acceptable even
+      for long-running applications, due to infrequent updates to the IANA database,
+      and the reduced footprint of the libstdc++ implementation (see
+      <xref linkend="zone.db.zic">link</xref>).
+    </para>
+
+    <para>
+      If accumulating old <code>tzdb</code> databases is not acceptable
+      (e.g. due to memory constraints), entries
+      may be removed from <code>tzdb_list</code> using <code>tzdb_list::erase_after</code>.
+      When using this function, you are responsible for ensuring that the application
+      no longer is no longer using any <code>time_zone*</code> to a removed database.
+      If you erase a <code>tzdb</code> while some part of the application is still
+      using it (or one of its <code>time_zone</code> objects) you will create
+      a dangling pointer, leading to undefined behaviour.
+      To make <code>tzdb_list::erase_after</code> safer, libstdc++ provides an
+      <emphasis>extension</emphasis> that avoids creating dangling pointers.
+      The <code>tzdb_list</code> uses <code>shared_ptr&lt;tzdb&gt;</code> to
+      refer to each entry in the list, and <code>tzdb_list::const_iterator</code>
+      also uses a <code>shared_ptr&lt;tzdb&gt;</code> to refer to its target.
+      This means that iterators into the list share ownership of the list elements,
+      so that erasing an element from the list does not destroy it if there are
+      any iterators which share ownership of the element. The application can
+      use this to ensure that <code>tzdb</code> and <code>time_zone</code>
+      objects are not destroyed while they're still being used. The lifetime
+      of a <code>tzdb</code> that is still in use can be extended by holding
+      onto a <code>tzdb_list::const_iterator</code> that refers to it.
+    </para>
+  </section>
+
+</section>
+
+</chapter>
-- 
2.55.0