blob: 90ffdbcf9f93c47d284c38b039f629c6ff156b86 [file]
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Chapter 13.  Time</title><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><meta name="keywords" content="ISO C++, library" /><meta name="keywords" content="ISO C++, runtime, library" /><link rel="home" href="../index.html" title="The GNU C++ Library" /><link rel="up" href="std_contents.html" title="Part II.  Standard Contents" /><link rel="prev" href="numerics_and_c.html" title="Interacting with C" /><link rel="next" href="io.html" title="Chapter 14.  Input and Output" /></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 13. 
Time
</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="numerics_and_c.html">Prev</a> </td><th width="60%" align="center">Part II. 
Standard Contents
</th><td width="20%" align="right"> <a accesskey="n" href="io.html">Next</a></td></tr></table><hr /></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a id="std.time"></a>Chapter 13. 
Time
<a id="id-1.3.4.11.1.1.1" class="indexterm"></a>
</h2></div></div></div><div class="toc"><p><strong>Table of Contents</strong></p><dl class="toc"><dt><span class="section"><a href="time.html#std.time.zone.db">Time zone database</a></span></dt><dd><dl><dt><span class="section"><a href="time.html#zone.db.zic">tzdb uses zic format</a></span></dt><dt><span class="section"><a href="time.html#zone.current">current zone</a></span></dt><dt><span class="section"><a href="time.html#zone.db.sources">data sources</a></span></dt><dt><span class="section"><a href="time.html#zone.db.iterator">tzdb_list::const_iterator extends lifetime</a></span></dt></dl></dd></dl></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="std.time.zone.db"></a>Time zone database</h2></div></div></div><p>
Since C++20 the <code class="code">&lt;chrono&gt;</code> header provides time zone
support via <code class="code">std::chrono::tzdb</code>, a complete interface to the
<a class="link" href="https://www.iana.org/time-zones" target="_top">IANA Time Zone Database</a>.
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 class="code">std::chrono::get_tzdb()</code> to access
the database, <code class="code">std::chrono::locate_zone()</code> to look up
a zone by name, and <code class="code">std::chrono::current_zone()</code> to obtain
the system's local time zone. The <code class="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 class="code">std::chrono::reload_tzdb()</code> to pick up updated zone
data without restarting the program.
</p><p>
The <a class="link" href="https://howardhinnant.github.io/date/tz.html" target="_top">Time Zone Database
Parser</a> by Howard E. Hinnant is a valuable source of information and
examples of usage for the <code class="code">date</code> library, on which the standard
API is based.
</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="zone.db.zic"></a>tzdb uses zic format</h3></div></div></div><p>
When support is enabled (which is default) the time zone database class,
<code class="code">tzdb</code>, uses the <a class="link" href="https://man7.org/linux/man-pages/man8/zic.8.html#FILES" target="_top">
<code class="code">zic</code> file format</a>, 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.
</p><p>
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 class="code">time_zone</code> object is slower.
To mitigate this, a <code class="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 class="code">sys_info</code> dequence, as in the example below.
</p><pre class="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-&gt;get_info(time);
time = info.end + std::chrono::seconds(1);
}
}
</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="zone.current"></a>current zone</h3></div></div></div><p>
The <code class="code">time_zone</code> pointer returned from
<code class="code">std::chrono::current_zone</code>, is determined by looking up
(by <code class="code">std::chrono::locate_zone</code>) IANA zone name
determined as follows (for platforms other than AIX and Windows):
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
On system supporting <code class="code">readlink</code>, suffix components of the
path of the file linked by <code class="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 class="code">//</code>) are eliminated.
</li><li class="listitem">
Names stored in the files <code class="code">/etc/timezone</code> (Debian
derivatives) or <code class="code">/var/db/zoneinfo</code> (FreeBSD) in that order.
</li><li class="listitem">
Values for <code class="code">TIMEZONE</code> and <code class="code">ZONE</code> keys in
<code class="code">/etc/sysconfig/clock</code>.
</li><li class="listitem"><code class="code">UTC</code>.
</li></ul></div><p>
For AIX, the value of <code class="code">TZ</code> environment value is used, with
fallback to <code class="code">UTC</code>.
</p><p>
On Windows <code class="code">TimeZoneKeyName</code> is mapped to the IANA zone, using
internal mapping hard-coded in library, with fallback to <code class="code">UTC</code>:
</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
If the returned <code class="code">TimeZoneKeyName</code> is empty or DST is disabled,
then a value based on <code class="code">Bias</code> is returned: <code class="code">Etc/UTC</code>
for zero, <code class="code">Etc/GMT+/-N</code> for value that is multiply of 60,
and empty string otherwise.
</li><li class="listitem">
If the mapping contains a single entry for <code class="code">TimeZoneKeyName</code>,
that name is used.
</li><li class="listitem">
If <code class="code">TimeZoneKeyName</code> corresponds to multiple IANA zones,
a 2-letter country code is used, retrieved by applying <code class="code">GetGeoInfoW</code>
on the result of <code class="code">GetUserGeoID(GEOCLASS_NATION)</code>.
If determining the country code fails, or no entry exits for a given code,
the first mapping entry (<code class="code">001</code>) is returned.
</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="zone.db.sources"></a>data sources</h3></div></div></div><p>
Depending on the build configuration (see
<code class="code">--with-libstdcxx-zoneinfo=</code> documentation in
<a class="xref" href="configure.html" title="Configure">Configuring</a>).
the content of the time zone database is sourced from
<code class="filename">tzdata.zi</code> and <code class="filename">leapseconds</code> files
located in <span class="emphasis"><em>zoneinfo_dir</em></span>, or from static information
embedded in the library.
</p><p>
By default, <span class="emphasis"><em>zoneinfo_dir</em></span> is set to the
system-specific default directory (if a suitable dir is known for target),
usually <code class="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.
</p><p>
In addition to <code class="code">--with-libstdcxx-zoneinfo=</code> configure option
(used during GCC build), the path of <span class="emphasis"><em>zoneinfo_dir</em></span>
can be overridden by the application by providing a definition of the
<code class="code">__gnu_cxx::zoneinfo_dir_overrride()</code> function. The
returned path should be directory that contains <code class="code">tzdata.zi</code>
and <code class="code">leapseconds</code> files in the
<a class="link" href="https://man7.org/linux/man-pages/man8/zic.8.html#FILES" target="_top">
<code class="code">zic</code> format</a>.
</p><p>
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 class="code">std::chrono::get_tzdb().version</code>.
</p><p>
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 class="code">chrono::get_tzdb().version</code>
being set to <code class="code">"ersatz"</code>. This database contains leapseconds
data, <code class="code">Etc/UTC</code>, <code class="code">Etc/GMT</code> zones, and their aliases
(<code class="code">Etc/Zulu</code>, <code class="code">Etc/UCT</code>, <code class="code">Etc/Universal</code>,
<code class="code">Etc/Greenwich</code>, <code class="code">Etc/GMT0</code>, <code class="code">Etc/GMT+0</code>,
<code class="code">Etc/GMT-0</code>). This information is sufficient to support
conversion between <code class="code">utc_clock</code> and <code class="code">sys_clock</code>,
as well as a <code class="code">UTC</code> fallback for <code class="code">current_zone</code>
(<a class="xref" href="time.html#zone.current" title="current zone">current zone</a>).
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="zone.db.iterator"></a>tzdb_list::const_iterator extends lifetime</h3></div></div></div><p>
The <code class="code">std::chrono::reload_tzdb()</code> function may be used to load
updated content of the <code class="code">tzdata.zi</code> and <code class="code">leapseconds</code>
files from <span class="emphasis"><em>zoneinfo_dir</em></span> (if
<a class="xref" href="time.html#zone.db.sources" title="data sources">data sources</a>). If the version is different
(<code class="code">std::chrono::remote_version() != std::chrono::get_tzdb().version</code>),
a new element is added at the front of the <code class="code">tzdb_list</code>.
This new database is used for subsequent calls to <code class="code">current_zone</code>
and <code class="code">locate_zone</code>.
</p><p>
The above process is thread-safe, and does not invalidate nor change any
pre-existing pointers to <code class="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
<a class="xref" href="time.html#zone.db.zic" title="tzdb uses zic format">tzdb uses zic format</a>).
</p><p>
If accumulating old <code class="code">tzdb</code> databases is not acceptable
(e.g. due to memory constraints), entries
may be removed from <code class="code">tzdb_list</code> using <code class="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 class="code">time_zone*</code> to a removed database.
If you erase a <code class="code">tzdb</code> while some part of the application is still
using it (or one of its <code class="code">time_zone</code> objects) you will create
a dangling pointer, leading to undefined behaviour.
To make <code class="code">tzdb_list::erase_after</code> safer, libstdc++ provides an
<span class="emphasis"><em>extension</em></span> that avoids creating dangling pointers.
The <code class="code">tzdb_list</code> uses <code class="code">shared_ptr&lt;tzdb&gt;</code> to
refer to each entry in the list, and <code class="code">tzdb_list::const_iterator</code>
also uses a <code class="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 class="code">tzdb</code> and <code class="code">time_zone</code>
objects are not destroyed while they're still being used. The lifetime
of a <code class="code">tzdb</code> that is still in use can be extended by holding
onto a <code class="code">tzdb_list::const_iterator</code> that refers to it.
</p></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="numerics_and_c.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="std_contents.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="io.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Interacting with C </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 14. 
Input and Output
</td></tr></table></div></body></html>