1058 lines
100 KiB
HTML
1058 lines
100 KiB
HTML
|
|
|||
|
<!DOCTYPE html>
|
|||
|
<html lang="en">
|
|||
|
<head>
|
|||
|
<meta charset="utf-8">
|
|||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
<meta name="color-scheme" content="light dark">
|
|||
|
<title>PEP 615 – Support for the IANA Time Zone Database in the Standard Library | peps.python.org</title>
|
|||
|
<link rel="shortcut icon" href="../_static/py.png">
|
|||
|
<link rel="canonical" href="https://peps.python.org/pep-0615/">
|
|||
|
<link rel="stylesheet" href="../_static/style.css" type="text/css">
|
|||
|
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
|
|||
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
|
|||
|
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
|
|||
|
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
|
|||
|
<meta property="og:title" content='PEP 615 – Support for the IANA Time Zone Database in the Standard Library | peps.python.org'>
|
|||
|
<meta property="og:description" content="This proposes adding a module, zoneinfo, to provide a concrete time zone implementation supporting the IANA time zone database. By default, zoneinfo will use the system’s time zone data if available; if no system time zone data is available, the librar...">
|
|||
|
<meta property="og:type" content="website">
|
|||
|
<meta property="og:url" content="https://peps.python.org/pep-0615/">
|
|||
|
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
|
|||
|
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
|
|||
|
<meta property="og:image:alt" content="Python PEPs">
|
|||
|
<meta property="og:image:width" content="200">
|
|||
|
<meta property="og:image:height" content="200">
|
|||
|
<meta name="description" content="This proposes adding a module, zoneinfo, to provide a concrete time zone implementation supporting the IANA time zone database. By default, zoneinfo will use the system’s time zone data if available; if no system time zone data is available, the librar...">
|
|||
|
<meta name="theme-color" content="#3776ab">
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
|||
|
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
|
|||
|
<title>Following system colour scheme</title>
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
|||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|||
|
<circle cx="12" cy="12" r="9"></circle>
|
|||
|
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
|
|||
|
</svg>
|
|||
|
</symbol>
|
|||
|
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
|
|||
|
<title>Selected dark colour scheme</title>
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
|||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
|
|||
|
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
|
|||
|
</svg>
|
|||
|
</symbol>
|
|||
|
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
|
|||
|
<title>Selected light colour scheme</title>
|
|||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
|||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|||
|
<circle cx="12" cy="12" r="5"></circle>
|
|||
|
<line x1="12" y1="1" x2="12" y2="3"></line>
|
|||
|
<line x1="12" y1="21" x2="12" y2="23"></line>
|
|||
|
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
|||
|
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
|||
|
<line x1="1" y1="12" x2="3" y2="12"></line>
|
|||
|
<line x1="21" y1="12" x2="23" y2="12"></line>
|
|||
|
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
|||
|
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
|||
|
</svg>
|
|||
|
</symbol>
|
|||
|
</svg>
|
|||
|
<script>
|
|||
|
|
|||
|
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
|
|||
|
</script>
|
|||
|
<section id="pep-page-section">
|
|||
|
<header>
|
|||
|
<h1>Python Enhancement Proposals</h1>
|
|||
|
<ul class="breadcrumbs">
|
|||
|
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li>
|
|||
|
<li><a href="../pep-0000/">PEP Index</a> » </li>
|
|||
|
<li>PEP 615</li>
|
|||
|
</ul>
|
|||
|
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
|
|||
|
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
|
|||
|
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
|
|||
|
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
|
|||
|
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
|
|||
|
</button>
|
|||
|
</header>
|
|||
|
<article>
|
|||
|
<section id="pep-content">
|
|||
|
<h1 class="page-title">PEP 615 – Support for the IANA Time Zone Database in the Standard Library</h1>
|
|||
|
<dl class="rfc2822 field-list simple">
|
|||
|
<dt class="field-odd">Author<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd">Paul Ganssle <paul at ganssle.io></dd>
|
|||
|
<dt class="field-even">Discussions-To<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even"><a class="reference external" href="https://discuss.python.org/t/3468">Discourse thread</a></dd>
|
|||
|
<dt class="field-odd">Status<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
|
|||
|
<dt class="field-even">Type<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
|
|||
|
<dt class="field-odd">Created<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd">22-Feb-2020</dd>
|
|||
|
<dt class="field-even">Python-Version<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even">3.9</dd>
|
|||
|
<dt class="field-odd">Post-History<span class="colon">:</span></dt>
|
|||
|
<dd class="field-odd">25-Feb-2020, 29-Mar-2020</dd>
|
|||
|
<dt class="field-even">Replaces<span class="colon">:</span></dt>
|
|||
|
<dd class="field-even"><a class="reference external" href="../pep-0431/">431</a></dd>
|
|||
|
</dl>
|
|||
|
<hr class="docutils" />
|
|||
|
<section id="contents">
|
|||
|
<details><summary>Table of Contents</summary><ul class="simple">
|
|||
|
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
|||
|
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
|||
|
<li><a class="reference internal" href="#proposal">Proposal</a><ul>
|
|||
|
<li><a class="reference internal" href="#the-zoneinfo-zoneinfo-class">The <code class="docutils literal notranslate"><span class="pre">zoneinfo.ZoneInfo</span></code> class</a><ul>
|
|||
|
<li><a class="reference internal" href="#constructors">Constructors</a></li>
|
|||
|
<li><a class="reference internal" href="#behavior-during-data-updates">Behavior during data updates</a></li>
|
|||
|
<li><a class="reference internal" href="#deliberate-cache-invalidation">Deliberate cache invalidation</a></li>
|
|||
|
<li><a class="reference internal" href="#string-representation">String representation</a></li>
|
|||
|
<li><a class="reference internal" href="#pickle-serialization">Pickle serialization</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#sources-for-time-zone-data">Sources for time zone data</a><ul>
|
|||
|
<li><a class="reference internal" href="#system-time-zone-information">System time zone information</a></li>
|
|||
|
<li><a class="reference internal" href="#the-tzdata-python-package">The <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> Python package</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#search-path-configuration">Search path configuration</a><ul>
|
|||
|
<li><a class="reference internal" href="#compile-time-options">Compile-time options</a></li>
|
|||
|
<li><a class="reference internal" href="#environment-variables">Environment variables</a></li>
|
|||
|
<li><a class="reference internal" href="#reset-tzpath-function"><code class="docutils literal notranslate"><span class="pre">reset_tzpath</span></code> function</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
|
|||
|
<li><a class="reference internal" href="#security-implications">Security Implications</a></li>
|
|||
|
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
|
|||
|
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul>
|
|||
|
<li><a class="reference internal" href="#building-a-custom-tzdb-compiler">Building a custom tzdb compiler</a></li>
|
|||
|
<li><a class="reference internal" href="#including-tzdata-in-the-standard-library-by-default">Including <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> in the standard library by default</a></li>
|
|||
|
<li><a class="reference internal" href="#support-for-leap-seconds">Support for leap seconds</a></li>
|
|||
|
<li><a class="reference internal" href="#using-a-pytz-like-interface">Using a <code class="docutils literal notranslate"><span class="pre">pytz</span></code>-like interface</a></li>
|
|||
|
<li><a class="reference internal" href="#windows-support-via-microsoft-s-icu-api">Windows support via Microsoft’s ICU API</a></li>
|
|||
|
<li><a class="reference internal" href="#alternative-environment-variable-configurations">Alternative environment variable configurations</a></li>
|
|||
|
<li><a class="reference internal" href="#using-the-datetime-module">Using the <code class="docutils literal notranslate"><span class="pre">datetime</span></code> module</a><ul>
|
|||
|
<li><a class="reference internal" href="#arguments-against-putting-zoneinfo-directly-into-datetime">Arguments against putting <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> directly into <code class="docutils literal notranslate"><span class="pre">datetime</span></code></a></li>
|
|||
|
<li><a class="reference internal" href="#using-datetime-zoneinfo-instead-of-zoneinfo">Using <code class="docutils literal notranslate"><span class="pre">datetime.zoneinfo</span></code> instead of <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code></a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#footnotes">Footnotes</a></li>
|
|||
|
<li><a class="reference internal" href="#references">References</a><ul>
|
|||
|
<li><a class="reference internal" href="#other-time-zone-implementations">Other time zone implementations:</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
|||
|
</ul>
|
|||
|
</details></section>
|
|||
|
<div class="pep-banner canonical-doc sticky-banner admonition important">
|
|||
|
<p class="admonition-title">Important</p>
|
|||
|
<p>This PEP is a historical document. The up-to-date, canonical documentation can now be found at <a class="reference external" href="https://docs.python.org/3/library/zoneinfo.html#module-zoneinfo" title="(in Python v3.13)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">zoneinfo</span></code></a>.</p>
|
|||
|
<p class="close-button">×</p>
|
|||
|
<p>See <a class="pep reference internal" href="../pep-0001/" title="PEP 1 – PEP Purpose and Guidelines">PEP 1</a> for how to propose changes.</p>
|
|||
|
</div>
|
|||
|
<section id="abstract">
|
|||
|
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
|
|||
|
<p>This proposes adding a module, <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code>, to provide a concrete time zone
|
|||
|
implementation supporting the IANA time zone database. By default,
|
|||
|
<code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> will use the system’s time zone data if available; if no system
|
|||
|
time zone data is available, the library will fall back to using the
|
|||
|
first-party package <code class="docutils literal notranslate"><span class="pre">tzdata</span></code>, deployed on PyPI. <a class="reference internal" href="#d" id="id1"><span>[d]</span></a></p>
|
|||
|
</section>
|
|||
|
<section id="motivation">
|
|||
|
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">datetime</span></code> library uses a flexible mechanism to handle time zones: all
|
|||
|
conversions and time zone information queries are delegated to an instance of a
|
|||
|
subclass of the abstract <code class="docutils literal notranslate"><span class="pre">datetime.tzinfo</span></code> base class. <a class="footnote-reference brackets" href="#tzinfo" id="id2">[10]</a> This allows
|
|||
|
users to implement arbitrarily complex time zone rules, but in practice the
|
|||
|
majority of users want support for just three types of time zone: <a class="reference internal" href="#a" id="id3"><span>[a]</span></a></p>
|
|||
|
<ol class="arabic simple">
|
|||
|
<li>UTC and fixed offsets thereof</li>
|
|||
|
<li>The system local time zone</li>
|
|||
|
<li>IANA time zones</li>
|
|||
|
</ol>
|
|||
|
<p>In Python 3.2, the <code class="docutils literal notranslate"><span class="pre">datetime.timezone</span></code> class was introduced to support the
|
|||
|
first class of time zone (with a special <code class="docutils literal notranslate"><span class="pre">datetime.timezone.utc</span></code> singleton
|
|||
|
for UTC).</p>
|
|||
|
<p>While there is still no “local” time zone, in Python 3.0 the semantics of naïve
|
|||
|
time zones was changed to support many “local time” operations, and it is now
|
|||
|
possible to get a fixed time zone offset from a local time:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">datetime</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">astimezone</span><span class="p">())</span>
|
|||
|
<span class="go">2020-02-22 12:00:00-05:00</span>
|
|||
|
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">datetime</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">astimezone</span><span class="p">()</span>
|
|||
|
<span class="gp">... </span> <span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">"%Y-%m-</span><span class="si">%d</span><span class="s2"> %H:%M:%S %Z"</span><span class="p">))</span>
|
|||
|
<span class="go">2020-02-22 12:00:00 EST</span>
|
|||
|
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">datetime</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">astimezone</span><span class="p">(</span><span class="n">timezone</span><span class="o">.</span><span class="n">utc</span><span class="p">))</span>
|
|||
|
<span class="go">2020-02-22 17:00:00+00:00</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>However, there is still no support for the time zones described in the IANA
|
|||
|
time zone database (also called the “tz” database or the Olson database
|
|||
|
<a class="footnote-reference brackets" href="#tzdb-wiki" id="id4">[6]</a>). The time zone database is in the public domain and is widely
|
|||
|
distributed — it is present by default on many Unix-like operating systems.
|
|||
|
Great care goes into the stability of the database: there are IETF RFCs both
|
|||
|
for the maintenance procedures (<span class="target" id="index-0"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc6557.html"><strong>RFC 6557</strong></a>) and for the compiled
|
|||
|
binary (TZif) format (<span class="target" id="index-1"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc8536.html"><strong>RFC 8536</strong></a>). As such, it is likely that adding
|
|||
|
support for the compiled outputs of the IANA database will add great value to
|
|||
|
end users even with the relatively long cadence of standard library releases.</p>
|
|||
|
</section>
|
|||
|
<section id="proposal">
|
|||
|
<h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2>
|
|||
|
<p>This PEP has three main concerns:</p>
|
|||
|
<ol class="arabic simple">
|
|||
|
<li>The semantics of the <code class="docutils literal notranslate"><span class="pre">zoneinfo.ZoneInfo</span></code> class (<a class="reference internal" href="#zoneinfo-class">zoneinfo-class</a>)</li>
|
|||
|
<li>Time zone data sources used (<a class="reference internal" href="#data-sources">data-sources</a>)</li>
|
|||
|
<li>Options for configuration of the time zone search path (<a class="reference internal" href="#search-path-config">search-path-config</a>)</li>
|
|||
|
</ol>
|
|||
|
<p>Because of the complexity of the proposal, rather than having separate
|
|||
|
“specification” and “rationale” sections the design decisions and rationales
|
|||
|
are grouped together by subject.</p>
|
|||
|
<section id="the-zoneinfo-zoneinfo-class">
|
|||
|
<span id="zoneinfo-class"></span><h3><a class="toc-backref" href="#the-zoneinfo-zoneinfo-class" role="doc-backlink">The <code class="docutils literal notranslate"><span class="pre">zoneinfo.ZoneInfo</span></code> class</a></h3>
|
|||
|
<section id="constructors">
|
|||
|
<h4><a class="toc-backref" href="#constructors" role="doc-backlink">Constructors</a></h4>
|
|||
|
<p>The initial design of the <code class="docutils literal notranslate"><span class="pre">zoneinfo.ZoneInfo</span></code> class has several constructors.</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ZoneInfo</span><span class="p">(</span><span class="n">key</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The primary constructor takes a single argument, <code class="docutils literal notranslate"><span class="pre">key</span></code>, which is a string
|
|||
|
indicating the name of a zone file in the system time zone database (e.g.
|
|||
|
<code class="docutils literal notranslate"><span class="pre">"America/New_York"</span></code>, <code class="docutils literal notranslate"><span class="pre">"Europe/London"</span></code>), and returns a <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code>
|
|||
|
constructed from the first matching data source on search path (see the
|
|||
|
<a class="reference internal" href="#data-sources">data-sources</a> section for more details). All zone information must be eagerly
|
|||
|
read from the data source (usually a TZif file) upon construction, and may
|
|||
|
not change during the lifetime of the object (this restriction applies to all
|
|||
|
<code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> constructors).</p>
|
|||
|
<p>In the event that no matching file is found on the search path (either because
|
|||
|
the system does not supply time zone data or because the key is invalid), the
|
|||
|
constructor will raise a <code class="docutils literal notranslate"><span class="pre">zoneinfo.ZoneInfoNotFoundError</span></code>, which will be a
|
|||
|
subclass of <code class="docutils literal notranslate"><span class="pre">KeyError</span></code>.</p>
|
|||
|
<p>One somewhat unusual guarantee made by this constructor is that calls with
|
|||
|
identical arguments must return <em>identical</em> objects. Specifically, for all
|
|||
|
values of <code class="docutils literal notranslate"><span class="pre">key</span></code>, the following assertion must always be valid <a class="reference internal" href="#b" id="id5"><span>[b]</span></a>:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
|
|||
|
<span class="n">b</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
|
|||
|
<span class="k">assert</span> <span class="n">a</span> <span class="ow">is</span> <span class="n">b</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The reason for this comes from the fact that the semantics of datetime
|
|||
|
operations (e.g. comparison, arithmetic) depend on whether the datetimes
|
|||
|
involved represent the same or different zones; two datetimes are in the same
|
|||
|
zone only if <code class="docutils literal notranslate"><span class="pre">dt1.tzinfo</span> <span class="pre">is</span> <span class="pre">dt2.tzinfo</span></code>. <a class="footnote-reference brackets" href="#nontransitive-comp" id="id6">[1]</a> In addition
|
|||
|
to the modest performance benefit from avoiding unnecessary proliferation of
|
|||
|
<code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> objects, providing this guarantee should minimize surprising
|
|||
|
behavior for end users.</p>
|
|||
|
<p><code class="docutils literal notranslate"><span class="pre">dateutil.tz.gettz</span></code> has provided a similar guarantee since version 2.7.0
|
|||
|
(release March 2018). <a class="footnote-reference brackets" href="#dateutil-tz" id="id7">[16]</a></p>
|
|||
|
<div class="admonition note">
|
|||
|
<p class="admonition-title">Note</p>
|
|||
|
<p>The implementation may decide how to implement the cache behavior, but the
|
|||
|
guarantee made here only requires that as long as two references exist to
|
|||
|
the result of identical constructor calls, they must be references to the
|
|||
|
same object. This is consistent with a reference counted cache where
|
|||
|
<code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> objects are ejected when no references to them exist (for
|
|||
|
example, a cache implemented with a <code class="docutils literal notranslate"><span class="pre">weakref.WeakValueDictionary</span></code>) — it is
|
|||
|
allowed but not required or recommended to implement this with a “strong”
|
|||
|
cache, where all <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> objects are kept alive indefinitely.</p>
|
|||
|
</div>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ZoneInfo</span><span class="o">.</span><span class="n">no_cache</span><span class="p">(</span><span class="n">key</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This is an alternate constructor that bypasses the constructor’s cache. It is
|
|||
|
identical to the primary constructor, but returns a new object on each call.
|
|||
|
This is likely most useful for testing purposes, or to deliberately induce
|
|||
|
“different zone” semantics between datetimes with the same nominal time zone.</p>
|
|||
|
<p>Even if an object constructed by this method would have been a cache miss, it
|
|||
|
must not be entered into the cache; in other words, the following assertion
|
|||
|
should always be true:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">a</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="o">.</span><span class="n">no_cache</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">b</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">a</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">b</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ZoneInfo</span><span class="o">.</span><span class="n">from_file</span><span class="p">(</span><span class="n">fobj</span><span class="p">:</span> <span class="n">IO</span><span class="p">[</span><span class="nb">bytes</span><span class="p">],</span> <span class="o">/</span><span class="p">,</span> <span class="n">key</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This is an alternate constructor that allows the construction of a <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code>
|
|||
|
object from any TZif byte stream. This constructor takes an optional
|
|||
|
parameter, <code class="docutils literal notranslate"><span class="pre">key</span></code>, which sets the name of the zone, for the purposes of
|
|||
|
<code class="docutils literal notranslate"><span class="pre">__str__</span></code> and <code class="docutils literal notranslate"><span class="pre">__repr__</span></code> (see <a class="reference internal" href="#string-representation">Representations</a>).</p>
|
|||
|
<p>Unlike the primary constructor, this always constructs a new object. There are
|
|||
|
two reasons that this deviates from the primary constructor’s caching behavior:
|
|||
|
stream objects have mutable state and so determining whether two inputs are
|
|||
|
identical is difficult or impossible, and it is likely that users constructing
|
|||
|
from a file specifically want to load from that file and not a cache.</p>
|
|||
|
<p>As with <code class="docutils literal notranslate"><span class="pre">ZoneInfo.no_cache</span></code>, objects constructed by this method must not be
|
|||
|
added to the cache.</p>
|
|||
|
</section>
|
|||
|
<section id="behavior-during-data-updates">
|
|||
|
<h4><a class="toc-backref" href="#behavior-during-data-updates" role="doc-backlink">Behavior during data updates</a></h4>
|
|||
|
<p>It is important that a given <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> object’s behavior not change during
|
|||
|
its lifetime, because a <code class="docutils literal notranslate"><span class="pre">datetime</span></code>’s <code class="docutils literal notranslate"><span class="pre">utcoffset()</span></code> method is used in both
|
|||
|
its equality and hash calculations, and if the result were to change during the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">datetime</span></code>’s lifetime, it could break the invariant for all hashable objects
|
|||
|
<a class="footnote-reference brackets" href="#hashable-def" id="id8">[3]</a> <a class="footnote-reference brackets" href="#hashes-equality" id="id9">[4]</a> that if <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">==</span> <span class="pre">y</span></code>, it must also be true
|
|||
|
that <code class="docutils literal notranslate"><span class="pre">hash(x)</span> <span class="pre">==</span> <span class="pre">hash(y)</span></code> <a class="reference internal" href="#c" id="id10"><span>[c]</span></a> .</p>
|
|||
|
<p>Considering both the preservation of <code class="docutils literal notranslate"><span class="pre">datetime</span></code>’s invariants and the
|
|||
|
primary constructor’s contract to always return the same object when called
|
|||
|
with identical arguments, if a source of time zone data is updated during a run
|
|||
|
of the interpreter, it must not invalidate any caches or modify any
|
|||
|
existing <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> objects. Newly constructed <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> objects, however,
|
|||
|
should come from the updated data source.</p>
|
|||
|
<p>This means that the point at which the data source is updated for new
|
|||
|
invocations of the <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> constructor depends primarily on the semantics
|
|||
|
of the caching behavior. The only guaranteed way to get a <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> object
|
|||
|
from an updated data source is to induce a cache miss, either by bypassing the
|
|||
|
cache and using <code class="docutils literal notranslate"><span class="pre">ZoneInfo.no_cache</span></code> or by clearing the cache.</p>
|
|||
|
<div class="admonition note">
|
|||
|
<p class="admonition-title">Note</p>
|
|||
|
<p>The specified cache behavior does not require that the cache be lazily
|
|||
|
populated — it is consistent with the specification (though not
|
|||
|
recommended) to eagerly pre-populate the cache with time zones that have
|
|||
|
never been constructed.</p>
|
|||
|
</div>
|
|||
|
</section>
|
|||
|
<section id="deliberate-cache-invalidation">
|
|||
|
<h4><a class="toc-backref" href="#deliberate-cache-invalidation" role="doc-backlink">Deliberate cache invalidation</a></h4>
|
|||
|
<p>In addition to <code class="docutils literal notranslate"><span class="pre">ZoneInfo.no_cache</span></code>, which allows a user to <em>bypass</em> the
|
|||
|
cache, <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> also exposes a <code class="docutils literal notranslate"><span class="pre">clear_cache</span></code> method to deliberately
|
|||
|
invalidate either the entire cache or selective portions of the cache:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ZoneInfo</span><span class="o">.</span><span class="n">clear_cache</span><span class="p">(</span><span class="o">*</span><span class="p">,</span> <span class="n">only_keys</span><span class="p">:</span> <span class="n">Iterable</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>If no arguments are passed, all caches are invalidated and the first call for
|
|||
|
each key to the primary <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> constructor after the cache has been
|
|||
|
cleared will return a new instance.</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">NYC0</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"America/New_York"</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">NYC0</span> <span class="ow">is</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"America/New_York"</span><span class="p">)</span>
|
|||
|
<span class="go">True</span>
|
|||
|
<span class="gp">>>> </span><span class="n">ZoneInfo</span><span class="o">.</span><span class="n">clear_cache</span><span class="p">()</span>
|
|||
|
<span class="gp">>>> </span><span class="n">NYC1</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"America/New_York"</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">NYC0</span> <span class="ow">is</span> <span class="n">NYC1</span>
|
|||
|
<span class="go">False</span>
|
|||
|
<span class="gp">>>> </span><span class="n">NYC1</span> <span class="ow">is</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"America/New_York"</span><span class="p">)</span>
|
|||
|
<span class="go">True</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>An optional parameter, <code class="docutils literal notranslate"><span class="pre">only_keys</span></code>, takes an iterable of keys to clear from
|
|||
|
the cache, otherwise leaving the cache intact.</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">NYC0</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"America/New_York"</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">LA0</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"America/Los_Angeles"</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">ZoneInfo</span><span class="o">.</span><span class="n">clear_cache</span><span class="p">(</span><span class="n">only_keys</span><span class="o">=</span><span class="p">[</span><span class="s2">"America/New_York"</span><span class="p">])</span>
|
|||
|
<span class="gp">>>> </span><span class="n">NYC1</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"America/New_York"</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">LA0</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"America/Los_Angeles"</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">NYC0</span> <span class="ow">is</span> <span class="n">NYC1</span>
|
|||
|
<span class="go">False</span>
|
|||
|
<span class="gp">>>> </span><span class="n">LA0</span> <span class="ow">is</span> <span class="n">LA1</span>
|
|||
|
<span class="go">True</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>Manipulation of the cache behavior is expected to be a niche use case; this
|
|||
|
function is primarily provided to facilitate testing, and to allow users with
|
|||
|
unusual requirements to tune the cache invalidation behavior to their needs.</p>
|
|||
|
</section>
|
|||
|
<section id="string-representation">
|
|||
|
<h4><a class="toc-backref" href="#string-representation" role="doc-backlink">String representation</a></h4>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> class’s <code class="docutils literal notranslate"><span class="pre">__str__</span></code> representation will be drawn from the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">key</span></code> parameter. This is partially because the <code class="docutils literal notranslate"><span class="pre">key</span></code> represents a
|
|||
|
human-readable “name” of the string, but also because it is a useful parameter
|
|||
|
that users will want exposed. It is necessary to provide a mechanism to expose
|
|||
|
the key for serialization between languages and because it is also a primary
|
|||
|
key for localization projects like CLDR (the Unicode Common Locale Data
|
|||
|
Repository <a class="footnote-reference brackets" href="#cldr" id="id11">[5]</a>).</p>
|
|||
|
<p>An example:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">zone</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"Pacific/Kwajalein"</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">zone</span><span class="p">)</span>
|
|||
|
<span class="go">'Pacific/Kwajalein'</span>
|
|||
|
|
|||
|
<span class="gp">>>> </span><span class="n">dt</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="n">tzinfo</span><span class="o">=</span><span class="n">zone</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">dt</span><span class="o">.</span><span class="n">isoformat</span><span class="p">()</span><span class="si">}</span><span class="s2"> [</span><span class="si">{</span><span class="n">dt</span><span class="o">.</span><span class="n">tzinfo</span><span class="si">}</span><span class="s2">]"</span>
|
|||
|
<span class="go">'2020-04-01T03:15:00+12:00 [Pacific/Kwajalein]'</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>When a <code class="docutils literal notranslate"><span class="pre">key</span></code> is not specified, the <code class="docutils literal notranslate"><span class="pre">str</span></code> operation should not fail, but
|
|||
|
should return the objects’s <code class="docutils literal notranslate"><span class="pre">__repr__</span></code>:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">zone</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="o">.</span><span class="n">from_file</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">zone</span><span class="p">)</span>
|
|||
|
<span class="go">'ZoneInfo.from_file(<_io.BytesIO object at ...>)'</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">__repr__</span></code> for a <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> is implementation-defined and not
|
|||
|
necessarily stable between versions, but it must not be a valid <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code>
|
|||
|
key, to avoid confusion between a key-derived <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> with a valid
|
|||
|
<code class="docutils literal notranslate"><span class="pre">__str__</span></code> and a file-derived <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> which has fallen through to the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">__repr__</span></code>.</p>
|
|||
|
<p>Since the use of <code class="docutils literal notranslate"><span class="pre">str()</span></code> to access the key provides no easy way to check
|
|||
|
for the <em>presence</em> of a key (the only way is to try constructing a <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code>
|
|||
|
from it and detect whether it raises an exception), <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> objects will
|
|||
|
also expose a read-only <code class="docutils literal notranslate"><span class="pre">key</span></code> attribute, which will be <code class="docutils literal notranslate"><span class="pre">None</span></code> in the event
|
|||
|
that no key was supplied.</p>
|
|||
|
</section>
|
|||
|
<section id="pickle-serialization">
|
|||
|
<h4><a class="toc-backref" href="#pickle-serialization" role="doc-backlink">Pickle serialization</a></h4>
|
|||
|
<p>Rather than serializing all transition data, <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> objects will be
|
|||
|
serialized by key, and <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> objects constructed from raw files (even
|
|||
|
those with a value for <code class="docutils literal notranslate"><span class="pre">key</span></code> specified) cannot be pickled.</p>
|
|||
|
<p>The behavior of a <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> object depends on how it was constructed:</p>
|
|||
|
<ol class="arabic">
|
|||
|
<li><code class="docutils literal notranslate"><span class="pre">ZoneInfo(key)</span></code>: When constructed with the primary constructor, a
|
|||
|
<code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> object will be serialized by key, and when deserialized the
|
|||
|
will use the primary constructor in the deserializing process, and thus be
|
|||
|
expected to be the same object as other references to the same time zone.
|
|||
|
For example, if <code class="docutils literal notranslate"><span class="pre">europe_berlin_pkl</span></code> is a string containing a pickle
|
|||
|
constructed from <code class="docutils literal notranslate"><span class="pre">ZoneInfo("Europe/Berlin")</span></code>, one would expect the
|
|||
|
following behavior:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">a</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"Europe/Berlin"</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">b</span> <span class="o">=</span> <span class="n">pickle</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">europe_berlin_pkl</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">a</span> <span class="ow">is</span> <span class="n">b</span>
|
|||
|
<span class="go">True</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li><code class="docutils literal notranslate"><span class="pre">ZoneInfo.no_cache(key)</span></code>: When constructed from the cache-bypassing
|
|||
|
constructor, the <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> object will still be serialized by key, but
|
|||
|
when deserialized, it will use the cache bypassing constructor. If
|
|||
|
<code class="docutils literal notranslate"><span class="pre">europe_berlin_pkl_nc</span></code> is a string containing a pickle constructed from
|
|||
|
<code class="docutils literal notranslate"><span class="pre">ZoneInfo.no_cache("Europe/Berlin")</span></code>, one would expect the following
|
|||
|
behavior:<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">a</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"Europe/Berlin"</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">b</span> <span class="o">=</span> <span class="n">pickle</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">europe_berlin_pkl_nc</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">a</span> <span class="ow">is</span> <span class="n">b</span>
|
|||
|
<span class="go">False</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
<li><code class="docutils literal notranslate"><span class="pre">ZoneInfo.from_file(fobj,</span> <span class="pre">/,</span> <span class="pre">key=None)</span></code>: When constructed from a file, the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> object will raise an exception on pickling. If an end user
|
|||
|
wants to pickle a <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> constructed from a file, it is recommended
|
|||
|
that they use a wrapper type or a custom serialization function: either
|
|||
|
serializing by key or storing the contents of the file object and
|
|||
|
serializing that.</li>
|
|||
|
</ol>
|
|||
|
<p>This method of serialization requires that the time zone data for the required
|
|||
|
key be available on both the serializing and deserializing side, similar to the
|
|||
|
way that references to classes and functions are expected to exist in both the
|
|||
|
serializing and deserializing environments. It also means that no guarantees
|
|||
|
are made about the consistency of results when unpickling a <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code>
|
|||
|
pickled in an environment with a different version of the time zone data.</p>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<section id="sources-for-time-zone-data">
|
|||
|
<span id="data-sources"></span><h3><a class="toc-backref" href="#sources-for-time-zone-data" role="doc-backlink">Sources for time zone data</a></h3>
|
|||
|
<p>One of the hardest challenges for IANA time zone support is keeping the data up
|
|||
|
to date; between 1997 and 2020, there have been between 3 and 21 releases per
|
|||
|
year, often in response to changes in time zone rules with little to no notice
|
|||
|
(see <a class="footnote-reference brackets" href="#timing-of-tz-changes" id="id12">[7]</a> for more details). In order to keep up to date,
|
|||
|
and to give the system administrator control over the data source, we propose
|
|||
|
to use system-deployed time zone data wherever possible. However, not all
|
|||
|
systems ship a publicly accessible time zone database — notably Windows uses a
|
|||
|
different system for managing time zones — and so if available <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code>
|
|||
|
falls back to an installable first-party package, <code class="docutils literal notranslate"><span class="pre">tzdata</span></code>, available on
|
|||
|
PyPI. <a class="reference internal" href="#d" id="id13"><span>[d]</span></a> If no system zoneinfo files are found but <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> is installed, the
|
|||
|
primary <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> constructor will use <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> as the time zone source.</p>
|
|||
|
<section id="system-time-zone-information">
|
|||
|
<h4><a class="toc-backref" href="#system-time-zone-information" role="doc-backlink">System time zone information</a></h4>
|
|||
|
<p>Many Unix-like systems deploy time zone data by default, or provide a canonical
|
|||
|
time zone data package (often called <code class="docutils literal notranslate"><span class="pre">tzdata</span></code>, as it is on Arch Linux, Fedora,
|
|||
|
and Debian). Whenever possible, it would be preferable to defer to the system
|
|||
|
time zone information, because this allows time zone information for all
|
|||
|
language stacks to be updated and maintained in one place. Python distributors
|
|||
|
are encouraged to ensure that time zone data is installed alongside Python
|
|||
|
whenever possible (e.g. by declaring <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> as a dependency for the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">python</span></code> package).</p>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> module will use a “search path” strategy analogous to the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">PATH</span></code> environment variable or the <code class="docutils literal notranslate"><span class="pre">sys.path</span></code> variable in Python; the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">zoneinfo.TZPATH</span></code> variable will be read-only (see <a class="reference internal" href="#search-path-config">search-path-config</a> for
|
|||
|
more details), ordered list of time zone data locations to search. When
|
|||
|
creating a <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> instance from a key, the zone file will be constructed
|
|||
|
from the first data source on the path in which the key exists, so for example,
|
|||
|
if <code class="docutils literal notranslate"><span class="pre">TZPATH</span></code> were:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">TZPATH</span> <span class="o">=</span> <span class="p">(</span>
|
|||
|
<span class="s2">"/usr/share/zoneinfo"</span><span class="p">,</span>
|
|||
|
<span class="s2">"/etc/zoneinfo"</span>
|
|||
|
<span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>and (although this would be very unusual) <code class="docutils literal notranslate"><span class="pre">/usr/share/zoneinfo</span></code> contained
|
|||
|
only <code class="docutils literal notranslate"><span class="pre">America/New_York</span></code> and <code class="docutils literal notranslate"><span class="pre">/etc/zoneinfo</span></code> contained both
|
|||
|
<code class="docutils literal notranslate"><span class="pre">America/New_York</span></code> and <code class="docutils literal notranslate"><span class="pre">Europe/Moscow</span></code>, then
|
|||
|
<code class="docutils literal notranslate"><span class="pre">ZoneInfo("America/New_York")</span></code> would be satisfied by
|
|||
|
<code class="docutils literal notranslate"><span class="pre">/usr/share/zoneinfo/America/New_York</span></code>, while <code class="docutils literal notranslate"><span class="pre">ZoneInfo("Europe/Moscow")</span></code>
|
|||
|
would be satisfied by <code class="docutils literal notranslate"><span class="pre">/etc/zoneinfo/Europe/Moscow</span></code>.</p>
|
|||
|
<p>At the moment, on Windows systems, the search path will default to empty,
|
|||
|
because Windows does not officially ship a copy of the time zone database. On
|
|||
|
non-Windows systems, the search path will default to a list of the most
|
|||
|
commonly observed search paths. Although this is subject to change in future
|
|||
|
versions, at launch the default search path will be:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">TZPATH</span> <span class="o">=</span> <span class="p">(</span>
|
|||
|
<span class="s2">"/usr/share/zoneinfo"</span><span class="p">,</span>
|
|||
|
<span class="s2">"/usr/lib/zoneinfo"</span><span class="p">,</span>
|
|||
|
<span class="s2">"/usr/share/lib/zoneinfo"</span><span class="p">,</span>
|
|||
|
<span class="s2">"/etc/zoneinfo"</span><span class="p">,</span>
|
|||
|
<span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This may be configured both at compile time or at runtime; more information on
|
|||
|
configuration options at <a class="reference internal" href="#search-path-config">search-path-config</a>.</p>
|
|||
|
</section>
|
|||
|
<section id="the-tzdata-python-package">
|
|||
|
<h4><a class="toc-backref" href="#the-tzdata-python-package" role="doc-backlink">The <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> Python package</a></h4>
|
|||
|
<p>In order to ensure easy access to time zone data for all end users, this PEP
|
|||
|
proposes to create a data-only package <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> as a fallback for when system
|
|||
|
data is not available. The <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> package would be distributed on PyPI as
|
|||
|
a “first party” package <a class="reference internal" href="#d" id="id14"><span>[d]</span></a>, maintained by the CPython development team.</p>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> package contains only data and metadata, with no public-facing
|
|||
|
functions or classes. It will be designed to be compatible with both newer
|
|||
|
<code class="docutils literal notranslate"><span class="pre">importlib.resources</span></code> <a class="footnote-reference brackets" href="#importlib-resources" id="id15">[11]</a> access patterns and older
|
|||
|
access patterns like <code class="docutils literal notranslate"><span class="pre">pkgutil.get_data</span></code> <a class="footnote-reference brackets" href="#pkgutil-data" id="id16">[12]</a> .</p>
|
|||
|
<p>While it is designed explicitly for the use of CPython, the <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> package
|
|||
|
is intended as a public package in its own right, and it may be used as an
|
|||
|
“official” source of time zone data for third party Python packages.</p>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<section id="search-path-configuration">
|
|||
|
<span id="search-path-config"></span><h3><a class="toc-backref" href="#search-path-configuration" role="doc-backlink">Search path configuration</a></h3>
|
|||
|
<p>The time zone search path is very system-dependent, and sometimes even
|
|||
|
application-dependent, and as such it makes sense to provide options to
|
|||
|
customize it. This PEP provides for three such avenues for customization:</p>
|
|||
|
<ol class="arabic simple">
|
|||
|
<li>Global configuration via a compile-time option</li>
|
|||
|
<li>Per-run configuration via environment variables</li>
|
|||
|
<li>Runtime configuration change via a <code class="docutils literal notranslate"><span class="pre">reset_tzpath</span></code> function</li>
|
|||
|
</ol>
|
|||
|
<p>In all methods of configuration, the search path must consist of only absolute,
|
|||
|
rather than relative paths. Implementations may choose to ignore, warn or raise
|
|||
|
an exception if a string other than an absolute path is found (and may make
|
|||
|
different choices depending on the context — e.g. raising an exception when an
|
|||
|
invalid path is passed to <code class="docutils literal notranslate"><span class="pre">reset_tzpath</span></code> but warning when one is included in
|
|||
|
the environment variable). If an exception is not raised, any strings other
|
|||
|
than an absolute path must not be included in the time zone search path.</p>
|
|||
|
<section id="compile-time-options">
|
|||
|
<h4><a class="toc-backref" href="#compile-time-options" role="doc-backlink">Compile-time options</a></h4>
|
|||
|
<p>It is most likely that downstream distributors will know exactly where their
|
|||
|
system time zone data is deployed, and so a compile-time option
|
|||
|
<code class="docutils literal notranslate"><span class="pre">PYTHONTZPATH</span></code> will be provided to set the default search path.</p>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">PYTHONTZPATH</span></code> option should be a string delimited by <code class="docutils literal notranslate"><span class="pre">os.pathsep</span></code>,
|
|||
|
listing possible locations for the time zone data to be deployed (e.g.
|
|||
|
<code class="docutils literal notranslate"><span class="pre">/usr/share/zoneinfo</span></code>).</p>
|
|||
|
</section>
|
|||
|
<section id="environment-variables">
|
|||
|
<h4><a class="toc-backref" href="#environment-variables" role="doc-backlink">Environment variables</a></h4>
|
|||
|
<p>When initializing <code class="docutils literal notranslate"><span class="pre">TZPATH</span></code> (and whenever <code class="docutils literal notranslate"><span class="pre">reset_tzpath</span></code> is called with no
|
|||
|
arguments), the <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> module will use the environment variable
|
|||
|
<code class="docutils literal notranslate"><span class="pre">PYTHONTZPATH</span></code>, if it exists, to set the search path.</p>
|
|||
|
<p><code class="docutils literal notranslate"><span class="pre">PYTHONTZPATH</span></code> is an <code class="docutils literal notranslate"><span class="pre">os.pathsep</span></code>-delimited string which <em>replaces</em> (rather
|
|||
|
than augments) the default time zone path. Some examples of the proposed
|
|||
|
semantics:</p>
|
|||
|
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python<span class="w"> </span>print_tzpath.py
|
|||
|
<span class="go">("/usr/share/zoneinfo",</span>
|
|||
|
<span class="go"> "/usr/lib/zoneinfo",</span>
|
|||
|
<span class="go"> "/usr/share/lib/zoneinfo",</span>
|
|||
|
<span class="go"> "/etc/zoneinfo")</span>
|
|||
|
|
|||
|
<span class="gp">$ </span><span class="nv">PYTHONTZPATH</span><span class="o">=</span><span class="s2">"/etc/zoneinfo:/usr/share/zoneinfo"</span><span class="w"> </span>python<span class="w"> </span>print_tzpath.py
|
|||
|
<span class="go">("/etc/zoneinfo",</span>
|
|||
|
<span class="go"> "/usr/share/zoneinfo")</span>
|
|||
|
|
|||
|
<span class="gp">$ </span><span class="nv">PYTHONTZPATH</span><span class="o">=</span><span class="s2">""</span><span class="w"> </span>python<span class="w"> </span>print_tzpath.py
|
|||
|
<span class="gp gp-VirtualEnv">()</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>This provides no built-in mechanism for prepending or appending to the default
|
|||
|
search path, as these use cases are likely to be somewhat more niche. It should
|
|||
|
be possible to populate an environment variable with the default search path
|
|||
|
fairly easily:</p>
|
|||
|
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span><span class="nb">export</span><span class="w"> </span><span class="nv">DEFAULT_TZPATH</span><span class="o">=</span><span class="k">$(</span>python<span class="w"> </span>-c<span class="w"> </span><span class="se">\</span>
|
|||
|
<span class="w"> </span><span class="s2">"import os, zoneinfo; print(os.pathsep.join(zoneinfo.TZPATH))"</span><span class="k">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
</section>
|
|||
|
<section id="reset-tzpath-function">
|
|||
|
<h4><a class="toc-backref" href="#reset-tzpath-function" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">reset_tzpath</span></code> function</a></h4>
|
|||
|
<p><code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> provides a <code class="docutils literal notranslate"><span class="pre">reset_tzpath</span></code> function that allows for changing the
|
|||
|
search path at runtime.</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">reset_tzpath</span><span class="p">(</span>
|
|||
|
<span class="n">to</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Sequence</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">PathLike</span><span class="p">]]]</span> <span class="o">=</span> <span class="kc">None</span>
|
|||
|
<span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
|||
|
<span class="o">...</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>When called with a sequence of paths, this function sets <code class="docutils literal notranslate"><span class="pre">zoneinfo.TZPATH</span></code> to
|
|||
|
a tuple constructed from the desired value. When called with no arguments or
|
|||
|
<code class="docutils literal notranslate"><span class="pre">None</span></code>, this function resets <code class="docutils literal notranslate"><span class="pre">zoneinfo.TZPATH</span></code> to the default
|
|||
|
configuration.</p>
|
|||
|
<p>This is likely to be primarily useful for (permanently or temporarily)
|
|||
|
disabling the use of system time zone paths and forcing the module to use the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">tzdata</span></code> package. It is not likely that <code class="docutils literal notranslate"><span class="pre">reset_tzpath</span></code> will be a common
|
|||
|
operation, save perhaps in test functions sensitive to time zone configuration,
|
|||
|
but it seems preferable to provide an official mechanism for changing this
|
|||
|
rather than allowing a proliferation of hacks around the immutability of
|
|||
|
<code class="docutils literal notranslate"><span class="pre">TZPATH</span></code>.</p>
|
|||
|
<div class="admonition caution">
|
|||
|
<p class="admonition-title">Caution</p>
|
|||
|
<p>Although changing <code class="docutils literal notranslate"><span class="pre">TZPATH</span></code> during a run is a supported operation, users
|
|||
|
should be advised that doing so may occasionally lead to unusual semantics,
|
|||
|
and when making design trade-offs greater weight will be afforded to using
|
|||
|
a static <code class="docutils literal notranslate"><span class="pre">TZPATH</span></code>, which is the much more common use case.</p>
|
|||
|
</div>
|
|||
|
<p>As noted in <a class="reference internal" href="#constructors">Constructors</a>, the primary <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> constructor employs a cache
|
|||
|
to ensure that two identically-constructed <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> objects always compare
|
|||
|
as identical (i.e. <code class="docutils literal notranslate"><span class="pre">ZoneInfo(key)</span> <span class="pre">is</span> <span class="pre">ZoneInfo(key)</span></code>), and the nature of this
|
|||
|
cache is implementation-defined. This means that the behavior of the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> constructor may be unpredictably inconsistent in some situations
|
|||
|
when used with the same <code class="docutils literal notranslate"><span class="pre">key</span></code> under different values of <code class="docutils literal notranslate"><span class="pre">TZPATH</span></code>. For
|
|||
|
example:</p>
|
|||
|
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">reset_tzpath</span><span class="p">(</span><span class="n">to</span><span class="o">=</span><span class="p">[</span><span class="s2">"/my/custom/tzdb"</span><span class="p">])</span>
|
|||
|
<span class="gp">>>> </span><span class="n">a</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"My/Custom/Zone"</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="n">reset_tzpath</span><span class="p">()</span>
|
|||
|
<span class="gp">>>> </span><span class="n">b</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"My/Custom/Zone"</span><span class="p">)</span>
|
|||
|
<span class="gp">>>> </span><span class="k">del</span> <span class="n">a</span>
|
|||
|
<span class="gp">>>> </span><span class="k">del</span> <span class="n">b</span>
|
|||
|
<span class="gp">>>> </span><span class="n">c</span> <span class="o">=</span> <span class="n">ZoneInfo</span><span class="p">(</span><span class="s2">"My/Custom/Zone"</span><span class="p">)</span>
|
|||
|
</pre></div>
|
|||
|
</div>
|
|||
|
<p>In this example, <code class="docutils literal notranslate"><span class="pre">My/Custom/Zone</span></code> exists only in the <code class="docutils literal notranslate"><span class="pre">/my/custom/tzdb</span></code> and
|
|||
|
not on the default search path. In all implementations the constructor for
|
|||
|
<code class="docutils literal notranslate"><span class="pre">a</span></code> must succeed. It is implementation-defined whether the constructor for
|
|||
|
<code class="docutils literal notranslate"><span class="pre">b</span></code> succeeds, but if it does, it must be true that <code class="docutils literal notranslate"><span class="pre">a</span> <span class="pre">is</span> <span class="pre">b</span></code>, because both
|
|||
|
<code class="docutils literal notranslate"><span class="pre">a</span></code> and <code class="docutils literal notranslate"><span class="pre">b</span></code> are references to the same key. It is also
|
|||
|
implementation-defined whether the constructor for <code class="docutils literal notranslate"><span class="pre">c</span></code> succeeds.
|
|||
|
Implementations of <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> <em>may</em> return the object constructed in previous
|
|||
|
constructor calls, or they may fail with an exception.</p>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<section id="backwards-compatibility">
|
|||
|
<h2><a class="toc-backref" href="#backwards-compatibility" role="doc-backlink">Backwards Compatibility</a></h2>
|
|||
|
<p>This will have no backwards compatibility issues as it will create a new API.</p>
|
|||
|
<p>With only minor modification, a backport with support for Python 3.6+ of the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> module could be created.</p>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> package is designed to be “data only”, and should support any
|
|||
|
version of Python that it can be built for (including Python 2.7).</p>
|
|||
|
</section>
|
|||
|
<section id="security-implications">
|
|||
|
<h2><a class="toc-backref" href="#security-implications" role="doc-backlink">Security Implications</a></h2>
|
|||
|
<p>This will require parsing zoneinfo data from disk, mostly from system locations
|
|||
|
but potentially from user-supplied data. Errors in the implementation
|
|||
|
(particularly the C code) could cause potential security issues, but there is
|
|||
|
no special risk relative to parsing other file types.</p>
|
|||
|
<p>Because the time zone data keys are essentially paths relative to some time
|
|||
|
zone root, implementations should take care to avoid path traversal attacks.
|
|||
|
Requesting keys such as <code class="docutils literal notranslate"><span class="pre">../../../path/to/something</span></code> should not reveal
|
|||
|
anything about the state of the file system outside of the time zone path.</p>
|
|||
|
</section>
|
|||
|
<section id="reference-implementation">
|
|||
|
<h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2>
|
|||
|
<p>An initial reference implementation is available at
|
|||
|
<a class="reference external" href="https://github.com/pganssle/zoneinfo">https://github.com/pganssle/zoneinfo</a></p>
|
|||
|
<p>This may eventually be converted into a backport for 3.6+.</p>
|
|||
|
</section>
|
|||
|
<section id="rejected-ideas">
|
|||
|
<h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2>
|
|||
|
<section id="building-a-custom-tzdb-compiler">
|
|||
|
<h3><a class="toc-backref" href="#building-a-custom-tzdb-compiler" role="doc-backlink">Building a custom tzdb compiler</a></h3>
|
|||
|
<p>One major concern with the use of the TZif format is that it does not actually
|
|||
|
contain enough information to always correctly determine the value to return
|
|||
|
for <code class="docutils literal notranslate"><span class="pre">tzinfo.dst()</span></code>. This is because for any given time zone offset, TZif
|
|||
|
only marks the UTC offset and whether or not it represents a DST offset, but
|
|||
|
<code class="docutils literal notranslate"><span class="pre">tzinfo.dst()</span></code> returns the total amount of the DST shift, so that the
|
|||
|
“standard” offset can be reconstructed from <code class="docutils literal notranslate"><span class="pre">datetime.utcoffset()</span> <span class="pre">-</span>
|
|||
|
<span class="pre">datetime.dst()</span></code>. The value to use for <code class="docutils literal notranslate"><span class="pre">dst()</span></code> can be determined by finding
|
|||
|
the equivalent STD offset and calculating the difference, but the TZif format
|
|||
|
does not specify which offsets form STD/DST pairs, and so heuristics must be
|
|||
|
used to determine this.</p>
|
|||
|
<p>One common heuristic — looking at the most recent standard offset — notably
|
|||
|
fails in the case of the time zone changes in Portugal in 1992 and 1996, where
|
|||
|
the “standard” offset was shifted by 1 hour during a DST transition, leading to
|
|||
|
a transition from STD to DST status with no change in offset. In fact, it is
|
|||
|
possible (though it has never happened) for a time zone to be created that is
|
|||
|
permanently DST and has no standard offsets.</p>
|
|||
|
<p>Although this information is missing in the compiled TZif binaries, it is
|
|||
|
present in the raw tzdb files, and it would be possible to parse this
|
|||
|
information ourselves and create a more suitable binary format.</p>
|
|||
|
<p>This idea was rejected for several reasons:</p>
|
|||
|
<ol class="arabic simple">
|
|||
|
<li>It precludes the use of any system-deployed time zone information, which is
|
|||
|
usually present only in TZif format.</li>
|
|||
|
<li>The raw tzdb format, while stable, is <em>less</em> stable than the TZif format;
|
|||
|
some downstream tzdb parsers have already run into problems with old
|
|||
|
deployments of their custom parsers becoming incompatible with recent tzdb
|
|||
|
releases, leading to the creation of a “rearguard” format to ease the
|
|||
|
transition. <a class="footnote-reference brackets" href="#rearguard" id="id17">[8]</a></li>
|
|||
|
<li>Heuristics currently suffice in <code class="docutils literal notranslate"><span class="pre">dateutil</span></code> and <code class="docutils literal notranslate"><span class="pre">pytz</span></code> for all known time
|
|||
|
zones, historical and present, and it is not very likely that new time zones
|
|||
|
will appear that cannot be captured by heuristics — though it is somewhat
|
|||
|
more likely that new rules that are not captured by the <em>current</em> generation
|
|||
|
of heuristics will appear; in that case, bugfixes would be required to
|
|||
|
accommodate the changed situation.</li>
|
|||
|
<li>The <code class="docutils literal notranslate"><span class="pre">dst()</span></code> method’s utility (and in fact the <code class="docutils literal notranslate"><span class="pre">isdst</span></code> parameter in TZif)
|
|||
|
is somewhat questionable to start with, as almost all the useful information
|
|||
|
is contained in the <code class="docutils literal notranslate"><span class="pre">utcoffset()</span></code> and <code class="docutils literal notranslate"><span class="pre">tzname()</span></code> methods, which are not
|
|||
|
subject to the same problems.</li>
|
|||
|
</ol>
|
|||
|
<p>In short, maintaining a custom tzdb compiler or compiled package adds
|
|||
|
maintenance burdens to both the CPython dev team and system administrators, and
|
|||
|
its main benefit is to address a hypothetical failure that would likely have
|
|||
|
minimal real world effects were it to occur.</p>
|
|||
|
</section>
|
|||
|
<section id="including-tzdata-in-the-standard-library-by-default">
|
|||
|
<span id="why-no-default-tzdata"></span><h3><a class="toc-backref" href="#including-tzdata-in-the-standard-library-by-default" role="doc-backlink">Including <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> in the standard library by default</a></h3>
|
|||
|
<p>Although <a class="pep reference internal" href="../pep-0453/" title="PEP 453 – Explicit bootstrapping of pip in Python installations">PEP 453</a>, which introduced the <code class="docutils literal notranslate"><span class="pre">ensurepip</span></code>
|
|||
|
mechanism to CPython, provides a convenient template for a standard library
|
|||
|
module maintained on PyPI, a potentially similar <code class="docutils literal notranslate"><span class="pre">ensuretzdata</span></code> mechanism is
|
|||
|
somewhat less necessary, and would be complicated enough that it is considered
|
|||
|
out of scope for this PEP.</p>
|
|||
|
<p>Because the <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> module is designed to use the system time zone data
|
|||
|
wherever possible, the <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> package is unnecessary (and may be
|
|||
|
undesirable) on systems that deploy time zone data, and so it does not seem
|
|||
|
critical to ship <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> with CPython.</p>
|
|||
|
<p>It is also not yet clear how these hybrid standard library / PyPI modules
|
|||
|
should be updated, (other than <code class="docutils literal notranslate"><span class="pre">pip</span></code>, which has a natural mechanism for
|
|||
|
updates and notifications) and since it is not critical to the operation of the
|
|||
|
module, it seems prudent to defer any such proposal.</p>
|
|||
|
</section>
|
|||
|
<section id="support-for-leap-seconds">
|
|||
|
<h3><a class="toc-backref" href="#support-for-leap-seconds" role="doc-backlink">Support for leap seconds</a></h3>
|
|||
|
<p>In addition to time zone offset and name rules, the IANA time zone database
|
|||
|
also provides a source of leap second data. This is deemed out of scope because
|
|||
|
<code class="docutils literal notranslate"><span class="pre">datetime.datetime</span></code> currently has no support for leap seconds, and the
|
|||
|
question of leap second data can be deferred until leap second support is
|
|||
|
added.</p>
|
|||
|
<p>The first-party <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> package should ship the leap second data, even if it
|
|||
|
is not used by the <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> module.</p>
|
|||
|
</section>
|
|||
|
<section id="using-a-pytz-like-interface">
|
|||
|
<h3><a class="toc-backref" href="#using-a-pytz-like-interface" role="doc-backlink">Using a <code class="docutils literal notranslate"><span class="pre">pytz</span></code>-like interface</a></h3>
|
|||
|
<p>A <code class="docutils literal notranslate"><span class="pre">pytz</span></code>-like (<a class="footnote-reference brackets" href="#pytz" id="id18">[18]</a>) interface was proposed in <a class="pep reference internal" href="../pep-0431/" title="PEP 431 – Time zone support improvements">PEP 431</a>, but
|
|||
|
was ultimately withdrawn / rejected for lack of ambiguous datetime support.
|
|||
|
<a class="pep reference internal" href="../pep-0495/" title="PEP 495 – Local Time Disambiguation">PEP 495</a> added the <code class="docutils literal notranslate"><span class="pre">fold</span></code> attribute to address this problem, but
|
|||
|
<code class="docutils literal notranslate"><span class="pre">fold</span></code> obviates the need for <code class="docutils literal notranslate"><span class="pre">pytz</span></code>’s non-standard <code class="docutils literal notranslate"><span class="pre">tzinfo</span></code> classes, and
|
|||
|
so a <code class="docutils literal notranslate"><span class="pre">pytz</span></code>-like interface is no longer necessary. <a class="footnote-reference brackets" href="#fastest-footgun" id="id19">[2]</a></p>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> approach is more closely based on <code class="docutils literal notranslate"><span class="pre">dateutil.tz</span></code>, which
|
|||
|
implemented support for <code class="docutils literal notranslate"><span class="pre">fold</span></code> (including a backport to older versions) just
|
|||
|
before the release of Python 3.6.</p>
|
|||
|
</section>
|
|||
|
<section id="windows-support-via-microsoft-s-icu-api">
|
|||
|
<h3><a class="toc-backref" href="#windows-support-via-microsoft-s-icu-api" role="doc-backlink">Windows support via Microsoft’s ICU API</a></h3>
|
|||
|
<p>Windows does not ship the time zone database as TZif files, but as of Windows
|
|||
|
10’s 2017 Creators Update, Microsoft has provided an API for interacting with
|
|||
|
the International Components for Unicode (ICU) project <a class="footnote-reference brackets" href="#icu-project" id="id20">[13]</a>
|
|||
|
<a class="footnote-reference brackets" href="#ms-icu-documentation" id="id21">[14]</a> , which includes an API for accessing time zone data —
|
|||
|
sourced from the IANA time zone database. <a class="footnote-reference brackets" href="#icu-timezone-api" id="id22">[15]</a></p>
|
|||
|
<p>Providing bindings for this would allow us to support Windows “out of the box”
|
|||
|
without the need to install the <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> package, but unfortunately the C
|
|||
|
headers provided by Windows do not provide any access to the underlying time
|
|||
|
zone data — only an API to query the system for transition and offset
|
|||
|
information is available. This would constrain the semantics of any ICU-based
|
|||
|
implementation in ways that may not be compatible with a non-ICU-based
|
|||
|
implementation — particularly around the behavior of the cache.</p>
|
|||
|
<p>Since it seems like ICU cannot be used as simply an additional data source for
|
|||
|
<code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> objects, this PEP considers the ICU support to be out of scope, and
|
|||
|
probably better supported by a third-party library.</p>
|
|||
|
</section>
|
|||
|
<section id="alternative-environment-variable-configurations">
|
|||
|
<h3><a class="toc-backref" href="#alternative-environment-variable-configurations" role="doc-backlink">Alternative environment variable configurations</a></h3>
|
|||
|
<p>This PEP proposes to use a single environment variable: <code class="docutils literal notranslate"><span class="pre">PYTHONTZPATH</span></code>.
|
|||
|
This is based on the assumption that the majority of users who would want to
|
|||
|
manipulate the time zone path would want to fully replace it (e.g. “I know
|
|||
|
exactly where my time zone data is”), and other use cases like prepending to
|
|||
|
the existing search path would be less common.</p>
|
|||
|
<p>There are several other schemes that were considered and rejected:</p>
|
|||
|
<ol class="arabic">
|
|||
|
<li>Separate <code class="docutils literal notranslate"><span class="pre">PYTHON_TZPATH</span></code> into two environment variables:
|
|||
|
<code class="docutils literal notranslate"><span class="pre">DEFAULT_PYTHONTZPATH</span></code> and <code class="docutils literal notranslate"><span class="pre">PYTHONTZPATH</span></code>, where <code class="docutils literal notranslate"><span class="pre">PYTHONTZPATH</span></code> would
|
|||
|
contain values to append (or prepend) to the default time zone path, and
|
|||
|
<code class="docutils literal notranslate"><span class="pre">DEFAULT_PYTHONTZPATH</span></code> would <em>replace</em> the default time zone path. This
|
|||
|
was rejected because it would likely lead to user confusion if the primary
|
|||
|
use case is to replace rather than augment.</li>
|
|||
|
<li>Adding either <code class="docutils literal notranslate"><span class="pre">PYTHONTZPATH_PREPEND</span></code>, <code class="docutils literal notranslate"><span class="pre">PYTHONTZPATH_APPEND</span></code> or both, so
|
|||
|
that users can augment the search path on either end without attempting to
|
|||
|
determine what the default time zone path is. This was rejected as likely to
|
|||
|
be unnecessary, and because it could easily be added in a
|
|||
|
backwards-compatible manner in future updates if there is much demand for
|
|||
|
such a feature.</li>
|
|||
|
<li>Use only the <code class="docutils literal notranslate"><span class="pre">PYTHONTZPATH</span></code> variable, but provide a custom special value
|
|||
|
that represents the default time zone path, e.g. <code class="docutils literal notranslate"><span class="pre"><<DEFAULT_TZPATH>></span></code>, so
|
|||
|
users could append to the time zone path with, e.g.
|
|||
|
<code class="docutils literal notranslate"><span class="pre">PYTHONTZPATH=<<DEFAULT_TZPATH>>:/my/path</span></code> could be used to append
|
|||
|
<code class="docutils literal notranslate"><span class="pre">/my/path</span></code> to the end of the time zone path.<p>One advantage to this scheme would be that it would add a natural extension
|
|||
|
point for specifying non-file-based elements on the search path, such as
|
|||
|
changing the priority of <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> if it exists, or if native support for
|
|||
|
<span class="target" id="index-2"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc7808.html"><strong>TZDIST</strong></a> were to be added to the library in the future.</p>
|
|||
|
<p>This was rejected mainly because these sort of special values are not
|
|||
|
usually found in <code class="docutils literal notranslate"><span class="pre">PATH</span></code>-like variables and the only currently proposed use
|
|||
|
case is a stand-in for the default <code class="docutils literal notranslate"><span class="pre">TZPATH</span></code>, which can be acquired by
|
|||
|
executing a Python program to query for the default value. An additional
|
|||
|
factor in rejecting this is that because <code class="docutils literal notranslate"><span class="pre">PYTHONTZPATH</span></code> accepts only
|
|||
|
absolute paths, any string that does not represent a valid absolute path is
|
|||
|
implicitly reserved for future use, so it would be possible to introduce
|
|||
|
these special values as necessary in a backwards-compatible way in future
|
|||
|
versions of the library.</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
</section>
|
|||
|
<section id="using-the-datetime-module">
|
|||
|
<h3><a class="toc-backref" href="#using-the-datetime-module" role="doc-backlink">Using the <code class="docutils literal notranslate"><span class="pre">datetime</span></code> module</a></h3>
|
|||
|
<p>One possible idea would be to add <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> to the <code class="docutils literal notranslate"><span class="pre">datetime</span></code> module,
|
|||
|
rather than giving it its own separate module. This PEP favors the use of
|
|||
|
a separate <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> module,though a nested <code class="docutils literal notranslate"><span class="pre">datetime.zoneinfo</span></code> module
|
|||
|
was also under consideration.</p>
|
|||
|
<section id="arguments-against-putting-zoneinfo-directly-into-datetime">
|
|||
|
<h4><a class="toc-backref" href="#arguments-against-putting-zoneinfo-directly-into-datetime" role="doc-backlink">Arguments against putting <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> directly into <code class="docutils literal notranslate"><span class="pre">datetime</span></code></a></h4>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">datetime</span></code> module is already somewhat crowded, as it has many classes
|
|||
|
with somewhat complex behavior — <code class="docutils literal notranslate"><span class="pre">datetime.datetime</span></code>, <code class="docutils literal notranslate"><span class="pre">datetime.date</span></code>,
|
|||
|
<code class="docutils literal notranslate"><span class="pre">datetime.time</span></code>, <code class="docutils literal notranslate"><span class="pre">datetime.timedelta</span></code>, <code class="docutils literal notranslate"><span class="pre">datetime.timezone</span></code> and
|
|||
|
<code class="docutils literal notranslate"><span class="pre">datetime.tzinfo</span></code>. The module’s implementation and documentation are already
|
|||
|
quite complicated, and it is probably beneficial to try to not to compound the
|
|||
|
problem if it can be helped.</p>
|
|||
|
<p>The <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> class is also in some ways different from all the other
|
|||
|
classes provided by <code class="docutils literal notranslate"><span class="pre">datetime</span></code>; the other classes are all intended to be
|
|||
|
lean, simple data types, whereas the <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> class is more complex: it is
|
|||
|
a parser for a specific format (TZif), a representation for the information
|
|||
|
stored in that format and a mechanism to look up the information in well-known
|
|||
|
locations in the system.</p>
|
|||
|
<p>Finally, while it is true that someone who needs the <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> module also
|
|||
|
needs the <code class="docutils literal notranslate"><span class="pre">datetime</span></code> module, the reverse is not necessarily true: many people
|
|||
|
will want to use <code class="docutils literal notranslate"><span class="pre">datetime</span></code> without <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code>. Considering that
|
|||
|
<code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> will likely pull in additional, possibly more heavy-weight
|
|||
|
standard library modules, it would be preferable to allow the two to be
|
|||
|
imported separately — particularly if potential “tree shaking” distributions
|
|||
|
are in Python’s future. <a class="footnote-reference brackets" href="#tree-shaking" id="id23">[9]</a></p>
|
|||
|
<p>In the final analysis, it makes sense to keep <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> a separate module
|
|||
|
with a separate documentation page rather than to put its classes and functions
|
|||
|
directly into <code class="docutils literal notranslate"><span class="pre">datetime</span></code>.</p>
|
|||
|
</section>
|
|||
|
<section id="using-datetime-zoneinfo-instead-of-zoneinfo">
|
|||
|
<h4><a class="toc-backref" href="#using-datetime-zoneinfo-instead-of-zoneinfo" role="doc-backlink">Using <code class="docutils literal notranslate"><span class="pre">datetime.zoneinfo</span></code> instead of <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code></a></h4>
|
|||
|
<p>A more palatable configuration may be to nest <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> as a module under
|
|||
|
<code class="docutils literal notranslate"><span class="pre">datetime</span></code>, as <code class="docutils literal notranslate"><span class="pre">datetime.zoneinfo</span></code>.</p>
|
|||
|
<p>Arguments in favor of this:</p>
|
|||
|
<ol class="arabic simple">
|
|||
|
<li>It neatly namespaces <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> together with <code class="docutils literal notranslate"><span class="pre">datetime</span></code></li>
|
|||
|
<li>The <code class="docutils literal notranslate"><span class="pre">timezone</span></code> class is already in <code class="docutils literal notranslate"><span class="pre">datetime</span></code>, and it may seem strange
|
|||
|
that some time zones are in <code class="docutils literal notranslate"><span class="pre">datetime</span></code> and others are in a top-level
|
|||
|
module.</li>
|
|||
|
<li>As mentioned earlier, importing <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> necessarily requires importing
|
|||
|
<code class="docutils literal notranslate"><span class="pre">datetime</span></code>, so it is no imposition to require importing the parent module.</li>
|
|||
|
</ol>
|
|||
|
<p>Arguments against this:</p>
|
|||
|
<ol class="arabic">
|
|||
|
<li>In order to avoid forcing all <code class="docutils literal notranslate"><span class="pre">datetime</span></code> users to import <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code>, the
|
|||
|
<code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> module would need to be lazily imported, which means that
|
|||
|
end-users would need to explicitly import <code class="docutils literal notranslate"><span class="pre">datetime.zoneinfo</span></code> (as opposed
|
|||
|
to importing <code class="docutils literal notranslate"><span class="pre">datetime</span></code> and accessing the <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> attribute on the
|
|||
|
module). This is the way <code class="docutils literal notranslate"><span class="pre">dateutil</span></code> works (all submodules are lazily
|
|||
|
imported), and it is a perennial source of confusion for end users.<p>This confusing requirement from end-users can be avoided using a
|
|||
|
module-level <code class="docutils literal notranslate"><span class="pre">__getattr__</span></code> and <code class="docutils literal notranslate"><span class="pre">__dir__</span></code> per <a class="pep reference internal" href="../pep-0562/" title="PEP 562 – Module __getattr__ and __dir__">PEP 562</a>, but this would
|
|||
|
add some complexity to the implementation of the <code class="docutils literal notranslate"><span class="pre">datetime</span></code> module. This
|
|||
|
sort of behavior in modules or classes tends to confuse static analysis
|
|||
|
tools, which may not be desirable for a library as widely used and critical
|
|||
|
as <code class="docutils literal notranslate"><span class="pre">datetime</span></code>.</p>
|
|||
|
</li>
|
|||
|
<li>Nesting the implementation under <code class="docutils literal notranslate"><span class="pre">datetime</span></code> would likely require
|
|||
|
<code class="docutils literal notranslate"><span class="pre">datetime</span></code> to be reorganized from a single-file module (<code class="docutils literal notranslate"><span class="pre">datetime.py</span></code>)
|
|||
|
to a directory with an <code class="docutils literal notranslate"><span class="pre">__init__.py</span></code>. This is a minor concern, but the
|
|||
|
structure of the <code class="docutils literal notranslate"><span class="pre">datetime</span></code> module has been stable for many years, and it
|
|||
|
would be preferable to avoid churn if possible.<p>This concern <em>could</em> be alleviated by implementing <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> as
|
|||
|
<code class="docutils literal notranslate"><span class="pre">_zoneinfo.py</span></code> and importing it as <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> from within <code class="docutils literal notranslate"><span class="pre">datetime</span></code>,
|
|||
|
but this does not seem desirable from an aesthetic or code organization
|
|||
|
standpoint, and it would preclude the version of nesting where end users are
|
|||
|
required to explicitly import <code class="docutils literal notranslate"><span class="pre">datetime.zoneinfo</span></code>.</p>
|
|||
|
</li>
|
|||
|
</ol>
|
|||
|
<p>This PEP takes the position that on balance it would be best to use a separate
|
|||
|
top-level <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code> module because the benefits of nesting are not so great
|
|||
|
that it overwhelms the practical implementation concerns.</p>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<section id="footnotes">
|
|||
|
<h2><a class="toc-backref" href="#footnotes" role="doc-backlink">Footnotes</a></h2>
|
|||
|
<div role="list" class="citation-list">
|
|||
|
<div class="citation" id="a" role="doc-biblioentry">
|
|||
|
<dt class="label" id="a">[<a href="#id3">a</a>]</dt>
|
|||
|
<dd>The claim that the vast majority of users only want a few types of time
|
|||
|
zone is based on anecdotal impressions rather than anything remotely
|
|||
|
scientific. As one data point, <code class="docutils literal notranslate"><span class="pre">dateutil</span></code> provides many time zone types,
|
|||
|
but user support mostly focuses on these three types.</div>
|
|||
|
<div class="citation" id="b" role="doc-biblioentry">
|
|||
|
<dt class="label" id="b">[<a href="#id5">b</a>]</dt>
|
|||
|
<dd>The statement that identically constructed <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> objects should be
|
|||
|
identical objects may be violated if the user deliberately clears the time
|
|||
|
zone cache.</div>
|
|||
|
<div class="citation" id="c" role="doc-biblioentry">
|
|||
|
<dt class="label" id="c">[<a href="#id10">c</a>]</dt>
|
|||
|
<dd>The hash value for a given <code class="docutils literal notranslate"><span class="pre">datetime</span></code> is cached on first calculation, so
|
|||
|
we do not need to worry about the possibly more serious issue that a given
|
|||
|
<code class="docutils literal notranslate"><span class="pre">datetime</span></code> object’s hash would change during its lifetime.</div>
|
|||
|
<div class="citation" id="d" role="doc-biblioentry">
|
|||
|
<dt class="label" id="d">[d]<em> (<a href='#id1'>1</a>, <a href='#id13'>2</a>, <a href='#id14'>3</a>) </em></dt>
|
|||
|
<dd>The term “first party” here is distinguished from “third party” in that,
|
|||
|
although it is distributed via PyPI and is not currently included in
|
|||
|
Python by default, it is to be considered an official sub-project of
|
|||
|
CPython rather than a “blessed” third-party package.</div>
|
|||
|
</div>
|
|||
|
</section>
|
|||
|
<section id="references">
|
|||
|
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
|
|||
|
<aside class="footnote-list brackets">
|
|||
|
<aside class="footnote brackets" id="nontransitive-comp" role="doc-footnote">
|
|||
|
<dt class="label" id="nontransitive-comp">[<a href="#id6">1</a>]</dt>
|
|||
|
<dd>Paul Ganssle: “A curious case of non-transitive datetime comparison”
|
|||
|
(Published 15 February 2018)
|
|||
|
<a class="reference external" href="https://blog.ganssle.io/articles/2018/02/a-curious-case-datetimes.html">https://blog.ganssle.io/articles/2018/02/a-curious-case-datetimes.html</a></aside>
|
|||
|
<aside class="footnote brackets" id="fastest-footgun" role="doc-footnote">
|
|||
|
<dt class="label" id="fastest-footgun">[<a href="#id19">2</a>]</dt>
|
|||
|
<dd>Paul Ganssle: “pytz: The Fastest Footgun in the West” (Published 19 March
|
|||
|
2018) <a class="reference external" href="https://blog.ganssle.io/articles/2018/03/pytz-fastest-footgun.html">https://blog.ganssle.io/articles/2018/03/pytz-fastest-footgun.html</a></aside>
|
|||
|
<aside class="footnote brackets" id="hashable-def" role="doc-footnote">
|
|||
|
<dt class="label" id="hashable-def">[<a href="#id8">3</a>]</dt>
|
|||
|
<dd>Python documentation: “Glossary” (Version 3.8.2)
|
|||
|
<a class="reference external" href="https://docs.python.org/3/glossary.html#term-hashable">https://docs.python.org/3/glossary.html#term-hashable</a></aside>
|
|||
|
<aside class="footnote brackets" id="hashes-equality" role="doc-footnote">
|
|||
|
<dt class="label" id="hashes-equality">[<a href="#id9">4</a>]</dt>
|
|||
|
<dd>Hynek Schlawack: “Python Hashes and Equality” (Published 20 November 2017)
|
|||
|
<a class="reference external" href="https://hynek.me/articles/hashes-and-equality/">https://hynek.me/articles/hashes-and-equality/</a></aside>
|
|||
|
<aside class="footnote brackets" id="cldr" role="doc-footnote">
|
|||
|
<dt class="label" id="cldr">[<a href="#id11">5</a>]</dt>
|
|||
|
<dd>CLDR: Unicode Common Locale Data Repository
|
|||
|
<a class="reference external" href="http://cldr.unicode.org/#TOC-How-to-Use">http://cldr.unicode.org/#TOC-How-to-Use</a>-</aside>
|
|||
|
<aside class="footnote brackets" id="tzdb-wiki" role="doc-footnote">
|
|||
|
<dt class="label" id="tzdb-wiki">[<a href="#id4">6</a>]</dt>
|
|||
|
<dd>Wikipedia page for Tz database:
|
|||
|
<a class="reference external" href="https://en.wikipedia.org/wiki/Tz_database">https://en.wikipedia.org/wiki/Tz_database</a></aside>
|
|||
|
<aside class="footnote brackets" id="timing-of-tz-changes" role="doc-footnote">
|
|||
|
<dt class="label" id="timing-of-tz-changes">[<a href="#id12">7</a>]</dt>
|
|||
|
<dd>Code of Matt: “On the Timing of Time Zone Changes” (Matt Johnson-Pint, 23
|
|||
|
April 2016) <a class="reference external" href="https://codeofmatt.com/on-the-timing-of-time-zone-changes/">https://codeofmatt.com/on-the-timing-of-time-zone-changes/</a></aside>
|
|||
|
<aside class="footnote brackets" id="rearguard" role="doc-footnote">
|
|||
|
<dt class="label" id="rearguard">[<a href="#id17">8</a>]</dt>
|
|||
|
<dd>tz mailing list: [PROPOSED] Support zi parsers that mishandle negative DST
|
|||
|
offsets (Paul Eggert, 23 April 2018)
|
|||
|
<a class="reference external" href="https://mm.icann.org/pipermail/tz/2018-April/026421.html">https://mm.icann.org/pipermail/tz/2018-April/026421.html</a></aside>
|
|||
|
<aside class="footnote brackets" id="tree-shaking" role="doc-footnote">
|
|||
|
<dt class="label" id="tree-shaking">[<a href="#id23">9</a>]</dt>
|
|||
|
<dd>“Russell Keith-Magee: Python On Other Platforms” (15 May 2019, Jesse Jiryu
|
|||
|
Davis)
|
|||
|
<a class="reference external" href="https://pyfound.blogspot.com/2019/05/russell-keith-magee-python-on-other.html">https://pyfound.blogspot.com/2019/05/russell-keith-magee-python-on-other.html</a></aside>
|
|||
|
<aside class="footnote brackets" id="tzinfo" role="doc-footnote">
|
|||
|
<dt class="label" id="tzinfo">[<a href="#id2">10</a>]</dt>
|
|||
|
<dd><code class="docutils literal notranslate"><span class="pre">datetime.tzinfo</span></code> documentation
|
|||
|
<a class="reference external" href="https://docs.python.org/3/library/datetime.html#datetime.tzinfo">https://docs.python.org/3/library/datetime.html#datetime.tzinfo</a></aside>
|
|||
|
<aside class="footnote brackets" id="importlib-resources" role="doc-footnote">
|
|||
|
<dt class="label" id="importlib-resources">[<a href="#id15">11</a>]</dt>
|
|||
|
<dd><code class="docutils literal notranslate"><span class="pre">importlib.resources</span></code> documentation
|
|||
|
<a class="reference external" href="https://docs.python.org/3/library/importlib.html#module-importlib.resources">https://docs.python.org/3/library/importlib.html#module-importlib.resources</a></aside>
|
|||
|
<aside class="footnote brackets" id="pkgutil-data" role="doc-footnote">
|
|||
|
<dt class="label" id="pkgutil-data">[<a href="#id16">12</a>]</dt>
|
|||
|
<dd><code class="docutils literal notranslate"><span class="pre">pkgutil.get_data</span></code> documentation
|
|||
|
<a class="reference external" href="https://docs.python.org/3/library/pkgutil.html#pkgutil.get_data">https://docs.python.org/3/library/pkgutil.html#pkgutil.get_data</a></aside>
|
|||
|
<aside class="footnote brackets" id="icu-project" role="doc-footnote">
|
|||
|
<dt class="label" id="icu-project">[<a href="#id20">13</a>]</dt>
|
|||
|
<dd>ICU TimeZone classes
|
|||
|
<a class="reference external" href="http://userguide.icu-project.org/datetime/timezone">http://userguide.icu-project.org/datetime/timezone</a></aside>
|
|||
|
<aside class="footnote brackets" id="ms-icu-documentation" role="doc-footnote">
|
|||
|
<dt class="label" id="ms-icu-documentation">[<a href="#id21">14</a>]</dt>
|
|||
|
<dd>Microsoft documentation for International Components for Unicode (ICU)
|
|||
|
<a class="reference external" href="https://docs.microsoft.com/en-us/windows/win32/intl/international-components-for-unicode--icu-">https://docs.microsoft.com/en-us/windows/win32/intl/international-components-for-unicode–icu-</a></aside>
|
|||
|
<aside class="footnote brackets" id="icu-timezone-api" role="doc-footnote">
|
|||
|
<dt class="label" id="icu-timezone-api">[<a href="#id22">15</a>]</dt>
|
|||
|
<dd><code class="docutils literal notranslate"><span class="pre">icu::TimeZone</span></code> class documentation
|
|||
|
<a class="reference external" href="https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1TimeZone.html">https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/classicu_1_1TimeZone.html</a></aside>
|
|||
|
</aside>
|
|||
|
<section id="other-time-zone-implementations">
|
|||
|
<h3><a class="toc-backref" href="#other-time-zone-implementations" role="doc-backlink">Other time zone implementations:</a></h3>
|
|||
|
<aside class="footnote-list brackets">
|
|||
|
<aside class="footnote brackets" id="dateutil-tz" role="doc-footnote">
|
|||
|
<dt class="label" id="dateutil-tz">[<a href="#id7">16</a>]</dt>
|
|||
|
<dd><code class="docutils literal notranslate"><span class="pre">dateutil.tz</span></code>
|
|||
|
<a class="reference external" href="https://dateutil.readthedocs.io/en/stable/tz.html">https://dateutil.readthedocs.io/en/stable/tz.html</a></aside>
|
|||
|
<aside class="footnote brackets" id="dateutil-tzwin" role="doc-footnote">
|
|||
|
<dt class="label" id="dateutil-tzwin">[17]</dt>
|
|||
|
<dd><code class="docutils literal notranslate"><span class="pre">dateutil.tz.win</span></code>: Concrete time zone implementations wrapping Windows
|
|||
|
time zones
|
|||
|
<a class="reference external" href="https://dateutil.readthedocs.io/en/stable/tzwin.html">https://dateutil.readthedocs.io/en/stable/tzwin.html</a></aside>
|
|||
|
<aside class="footnote brackets" id="pytz" role="doc-footnote">
|
|||
|
<dt class="label" id="pytz">[<a href="#id18">18</a>]</dt>
|
|||
|
<dd><code class="docutils literal notranslate"><span class="pre">pytz</span></code>
|
|||
|
<a class="reference external" href="http://pytz.sourceforge.net/">http://pytz.sourceforge.net/</a></aside>
|
|||
|
</aside>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<section id="copyright">
|
|||
|
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
|
|||
|
<p>This document is placed in the public domain or under the
|
|||
|
CC0-1.0-Universal license, whichever is more permissive.</p>
|
|||
|
</section>
|
|||
|
</section>
|
|||
|
<hr class="docutils" />
|
|||
|
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0615.rst">https://github.com/python/peps/blob/main/peps/pep-0615.rst</a></p>
|
|||
|
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0615.rst">2024-06-01 20:10:03 GMT</a></p>
|
|||
|
|
|||
|
</article>
|
|||
|
<nav id="pep-sidebar">
|
|||
|
<h2>Contents</h2>
|
|||
|
<ul>
|
|||
|
<li><a class="reference internal" href="#abstract">Abstract</a></li>
|
|||
|
<li><a class="reference internal" href="#motivation">Motivation</a></li>
|
|||
|
<li><a class="reference internal" href="#proposal">Proposal</a><ul>
|
|||
|
<li><a class="reference internal" href="#the-zoneinfo-zoneinfo-class">The <code class="docutils literal notranslate"><span class="pre">zoneinfo.ZoneInfo</span></code> class</a><ul>
|
|||
|
<li><a class="reference internal" href="#constructors">Constructors</a></li>
|
|||
|
<li><a class="reference internal" href="#behavior-during-data-updates">Behavior during data updates</a></li>
|
|||
|
<li><a class="reference internal" href="#deliberate-cache-invalidation">Deliberate cache invalidation</a></li>
|
|||
|
<li><a class="reference internal" href="#string-representation">String representation</a></li>
|
|||
|
<li><a class="reference internal" href="#pickle-serialization">Pickle serialization</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#sources-for-time-zone-data">Sources for time zone data</a><ul>
|
|||
|
<li><a class="reference internal" href="#system-time-zone-information">System time zone information</a></li>
|
|||
|
<li><a class="reference internal" href="#the-tzdata-python-package">The <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> Python package</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#search-path-configuration">Search path configuration</a><ul>
|
|||
|
<li><a class="reference internal" href="#compile-time-options">Compile-time options</a></li>
|
|||
|
<li><a class="reference internal" href="#environment-variables">Environment variables</a></li>
|
|||
|
<li><a class="reference internal" href="#reset-tzpath-function"><code class="docutils literal notranslate"><span class="pre">reset_tzpath</span></code> function</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#backwards-compatibility">Backwards Compatibility</a></li>
|
|||
|
<li><a class="reference internal" href="#security-implications">Security Implications</a></li>
|
|||
|
<li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></li>
|
|||
|
<li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul>
|
|||
|
<li><a class="reference internal" href="#building-a-custom-tzdb-compiler">Building a custom tzdb compiler</a></li>
|
|||
|
<li><a class="reference internal" href="#including-tzdata-in-the-standard-library-by-default">Including <code class="docutils literal notranslate"><span class="pre">tzdata</span></code> in the standard library by default</a></li>
|
|||
|
<li><a class="reference internal" href="#support-for-leap-seconds">Support for leap seconds</a></li>
|
|||
|
<li><a class="reference internal" href="#using-a-pytz-like-interface">Using a <code class="docutils literal notranslate"><span class="pre">pytz</span></code>-like interface</a></li>
|
|||
|
<li><a class="reference internal" href="#windows-support-via-microsoft-s-icu-api">Windows support via Microsoft’s ICU API</a></li>
|
|||
|
<li><a class="reference internal" href="#alternative-environment-variable-configurations">Alternative environment variable configurations</a></li>
|
|||
|
<li><a class="reference internal" href="#using-the-datetime-module">Using the <code class="docutils literal notranslate"><span class="pre">datetime</span></code> module</a><ul>
|
|||
|
<li><a class="reference internal" href="#arguments-against-putting-zoneinfo-directly-into-datetime">Arguments against putting <code class="docutils literal notranslate"><span class="pre">ZoneInfo</span></code> directly into <code class="docutils literal notranslate"><span class="pre">datetime</span></code></a></li>
|
|||
|
<li><a class="reference internal" href="#using-datetime-zoneinfo-instead-of-zoneinfo">Using <code class="docutils literal notranslate"><span class="pre">datetime.zoneinfo</span></code> instead of <code class="docutils literal notranslate"><span class="pre">zoneinfo</span></code></a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#footnotes">Footnotes</a></li>
|
|||
|
<li><a class="reference internal" href="#references">References</a><ul>
|
|||
|
<li><a class="reference internal" href="#other-time-zone-implementations">Other time zone implementations:</a></li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
<li><a class="reference internal" href="#copyright">Copyright</a></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<br>
|
|||
|
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0615.rst">Page Source (GitHub)</a>
|
|||
|
</nav>
|
|||
|
</section>
|
|||
|
<script src="../_static/colour_scheme.js"></script>
|
|||
|
<script src="../_static/wrap_tables.js"></script>
|
|||
|
<script src="../_static/sticky_banner.js"></script>
|
|||
|
</body>
|
|||
|
</html>
|