././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1730684484.0257382
pyrfc3339-2.0.1/ 0000755 0001751 0000177 00000000000 14712023104 012556 5 ustar 00runner docker ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684479.0
pyrfc3339-2.0.1/LICENSE.txt 0000644 0001751 0000177 00000002040 14712023077 014406 0 ustar 00runner docker Copyright (c) 2024 Kurt Raschke
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684479.0
pyrfc3339-2.0.1/MANIFEST.in 0000644 0001751 0000177 00000000024 14712023077 014321 0 ustar 00runner docker include LICENSE.txt
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1730684484.0257382
pyrfc3339-2.0.1/PKG-INFO 0000644 0001751 0000177 00000004050 14712023104 013652 0 ustar 00runner docker Metadata-Version: 2.1
Name: pyRFC3339
Version: 2.0.1
Summary: Generate and parse RFC 3339 timestamps
Home-page: https://github.com/kurtraschke/pyRFC3339
Author: Kurt Raschke
Author-email: kurt@kurtraschke.com
License: MIT
Keywords: rfc 3339 timestamp
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Internet
License-File: LICENSE.txt
Description
===========
.. image:: https://github.com/kurtraschke/pyRFC3339/actions/workflows/test-python.yml/badge.svg
:target: https://github.com/kurtraschke/pyRFC3339/actions/workflows/test-python.yml
:alt: Build Status
.. image:: https://readthedocs.org/projects/pyrfc3339/badge/?version=latest
:target: https://pyrfc3339.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
pyRFC3339 parses and generates :RFC:`3339`-compliant timestamps using `Python `_ `datetime.datetime `_ objects.
>>> from pyrfc3339 import generate, parse
>>> from datetime import datetime, timezone
>>> generate(datetime.now(timezone.utc)) #doctest:+ELLIPSIS
'...T...Z'
>>> parse('2009-01-01T10:01:02Z')
datetime.datetime(2009, 1, 1, 10, 1, 2, tzinfo=datetime.timezone.utc)
>>> parse('2009-01-01T14:01:02-04:00')
datetime.datetime(2009, 1, 1, 14, 1, 2, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000), ''))
Installation
============
To install the latest version from `PyPI `_:
``$ pip install pyRFC3339``
To install the latest development version:
``$ pip install https://github.com/kurtraschke/pyRFC3339/tarball/master#egg=pyRFC3339-dev``
To build the documentation with Sphinx:
#. ``$ pip install -r docs/requirements.txt``
#. ``$ sphinx-build -M html docs/source/ docs/build``
The documentation is also available online at:
``https://pyrfc3339.readthedocs.io/``
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684479.0
pyrfc3339-2.0.1/README.rst 0000644 0001751 0000177 00000003002 14712023077 014251 0 ustar 00runner docker Description
===========
.. image:: https://github.com/kurtraschke/pyRFC3339/actions/workflows/test-python.yml/badge.svg
:target: https://github.com/kurtraschke/pyRFC3339/actions/workflows/test-python.yml
:alt: Build Status
.. image:: https://readthedocs.org/projects/pyrfc3339/badge/?version=latest
:target: https://pyrfc3339.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
pyRFC3339 parses and generates :RFC:`3339`-compliant timestamps using `Python `_ `datetime.datetime `_ objects.
>>> from pyrfc3339 import generate, parse
>>> from datetime import datetime, timezone
>>> generate(datetime.now(timezone.utc)) #doctest:+ELLIPSIS
'...T...Z'
>>> parse('2009-01-01T10:01:02Z')
datetime.datetime(2009, 1, 1, 10, 1, 2, tzinfo=datetime.timezone.utc)
>>> parse('2009-01-01T14:01:02-04:00')
datetime.datetime(2009, 1, 1, 14, 1, 2, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000), ''))
Installation
============
To install the latest version from `PyPI `_:
``$ pip install pyRFC3339``
To install the latest development version:
``$ pip install https://github.com/kurtraschke/pyRFC3339/tarball/master#egg=pyRFC3339-dev``
To build the documentation with Sphinx:
#. ``$ pip install -r docs/requirements.txt``
#. ``$ sphinx-build -M html docs/source/ docs/build``
The documentation is also available online at:
``https://pyrfc3339.readthedocs.io/``
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1730684484.0257382
pyrfc3339-2.0.1/pyRFC3339.egg-info/ 0000755 0001751 0000177 00000000000 14712023104 015555 5 ustar 00runner docker ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684484.0
pyrfc3339-2.0.1/pyRFC3339.egg-info/PKG-INFO 0000644 0001751 0000177 00000004050 14712023104 016651 0 ustar 00runner docker Metadata-Version: 2.1
Name: pyRFC3339
Version: 2.0.1
Summary: Generate and parse RFC 3339 timestamps
Home-page: https://github.com/kurtraschke/pyRFC3339
Author: Kurt Raschke
Author-email: kurt@kurtraschke.com
License: MIT
Keywords: rfc 3339 timestamp
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Internet
License-File: LICENSE.txt
Description
===========
.. image:: https://github.com/kurtraschke/pyRFC3339/actions/workflows/test-python.yml/badge.svg
:target: https://github.com/kurtraschke/pyRFC3339/actions/workflows/test-python.yml
:alt: Build Status
.. image:: https://readthedocs.org/projects/pyrfc3339/badge/?version=latest
:target: https://pyrfc3339.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
pyRFC3339 parses and generates :RFC:`3339`-compliant timestamps using `Python `_ `datetime.datetime `_ objects.
>>> from pyrfc3339 import generate, parse
>>> from datetime import datetime, timezone
>>> generate(datetime.now(timezone.utc)) #doctest:+ELLIPSIS
'...T...Z'
>>> parse('2009-01-01T10:01:02Z')
datetime.datetime(2009, 1, 1, 10, 1, 2, tzinfo=datetime.timezone.utc)
>>> parse('2009-01-01T14:01:02-04:00')
datetime.datetime(2009, 1, 1, 14, 1, 2, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000), ''))
Installation
============
To install the latest version from `PyPI `_:
``$ pip install pyRFC3339``
To install the latest development version:
``$ pip install https://github.com/kurtraschke/pyRFC3339/tarball/master#egg=pyRFC3339-dev``
To build the documentation with Sphinx:
#. ``$ pip install -r docs/requirements.txt``
#. ``$ sphinx-build -M html docs/source/ docs/build``
The documentation is also available online at:
``https://pyrfc3339.readthedocs.io/``
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684484.0
pyrfc3339-2.0.1/pyRFC3339.egg-info/SOURCES.txt 0000644 0001751 0000177 00000000422 14712023104 017437 0 ustar 00runner docker LICENSE.txt
MANIFEST.in
README.rst
pyproject.toml
setup.py
pyRFC3339.egg-info/PKG-INFO
pyRFC3339.egg-info/SOURCES.txt
pyRFC3339.egg-info/dependency_links.txt
pyRFC3339.egg-info/top_level.txt
pyrfc3339/__init__.py
pyrfc3339/generator.py
pyrfc3339/parser.py
pyrfc3339/utils.py ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684484.0
pyrfc3339-2.0.1/pyRFC3339.egg-info/dependency_links.txt 0000644 0001751 0000177 00000000001 14712023104 021623 0 ustar 00runner docker
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684484.0
pyrfc3339-2.0.1/pyRFC3339.egg-info/top_level.txt 0000644 0001751 0000177 00000000012 14712023104 020300 0 ustar 00runner docker pyrfc3339
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684479.0
pyrfc3339-2.0.1/pyproject.toml 0000644 0001751 0000177 00000000121 14712023077 015475 0 ustar 00runner docker [build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1730684484.0257382
pyrfc3339-2.0.1/pyrfc3339/ 0000755 0001751 0000177 00000000000 14712023104 014223 5 ustar 00runner docker ././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684479.0
pyrfc3339-2.0.1/pyrfc3339/__init__.py 0000644 0001751 0000177 00000001222 14712023077 016342 0 ustar 00runner docker """
pyRFC3339 parses and generates :RFC:`3339`-compliant timestamps using Python
:class:`datetime.datetime` objects.
>>> from pyrfc3339 import generate, parse
>>> from datetime import datetime, timezone
>>> generate(datetime.now(timezone.utc)) #doctest:+ELLIPSIS
'...T...Z'
>>> parse('2009-01-01T10:01:02Z')
datetime.datetime(2009, 1, 1, 10, 1, 2, tzinfo=datetime.timezone.utc)
>>> parse('2009-01-01T14:01:02-04:00')
datetime.datetime(2009, 1, 1, 14, 1, 2, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000), ''))
"""
from pyrfc3339.generator import generate
from pyrfc3339.parser import parse
__all__ = ["generate", "parse"]
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684479.0
pyrfc3339-2.0.1/pyrfc3339/generator.py 0000644 0001751 0000177 00000004351 14712023077 016577 0 ustar 00runner docker import datetime
from pyrfc3339.utils import format_timezone
def generate(dt, utc=True, accept_naive=False, microseconds=False):
"""
Generate an :RFC:`3339`-formatted timestamp from a
:class:`datetime.datetime`.
>>> from datetime import datetime, timezone
>>> from zoneinfo import ZoneInfo
>>> generate(datetime(2009, 1, 1, 12, 59, 59, 0, timezone.utc))
'2009-01-01T12:59:59Z'
The timestamp will use UTC unless `utc=False` is specified, in which case
it will use the timezone from the :class:`datetime.datetime`'s
:attr:`tzinfo` parameter.
>>> eastern = ZoneInfo('US/Eastern')
>>> dt = datetime(2009, 1, 1, 12, 59, 59, tzinfo=eastern)
>>> generate(dt)
'2009-01-01T17:59:59Z'
>>> generate(dt, utc=False)
'2009-01-01T12:59:59-05:00'
Unless `accept_naive=True` is specified, the `datetime` must not be naive.
>>> generate(datetime(2009, 1, 1, 12, 59, 59, 0))
Traceback (most recent call last):
...
ValueError: naive datetime and accept_naive is False
>>> generate(datetime(2009, 1, 1, 12, 59, 59, 0), accept_naive=True)
'2009-01-01T12:59:59Z'
If `accept_naive=True` is specified, the `datetime` is assumed to be UTC.
Attempting to generate a local timestamp from a naive datetime will result
in an error.
>>> generate(datetime(2009, 1, 1, 12, 59, 59, 0), accept_naive=True, utc=False)
Traceback (most recent call last):
...
ValueError: cannot generate a local timestamp from a naive datetime
"""
if dt.tzinfo is None:
if accept_naive is True:
if utc is True:
dt = dt.replace(tzinfo=datetime.timezone.utc)
else:
raise ValueError(
"cannot generate a local timestamp from a naive datetime"
)
else:
raise ValueError("naive datetime and accept_naive is False")
if utc is True:
dt = dt.astimezone(datetime.timezone.utc)
timestamp = dt.strftime("%Y-%m-%dT%H:%M:%S")
if microseconds is True:
timestamp += dt.strftime(".%f")
if dt.tzinfo is datetime.timezone.utc:
timestamp += "Z"
else:
timestamp += format_timezone(dt.tzinfo.utcoffset(dt).total_seconds())
return timestamp
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684479.0
pyrfc3339-2.0.1/pyrfc3339/parser.py 0000644 0001751 0000177 00000006755 14712023077 016117 0 ustar 00runner docker import re
from datetime import datetime, timedelta, timezone
from pyrfc3339.utils import format_timezone
def parse(timestamp, utc=False, produce_naive=False):
"""
Parse an :RFC:`3339`-formatted timestamp and return a
:class:`datetime.datetime`.
If the timestamp is presented in UTC, then the `tzinfo` parameter of the
returned `datetime` will be set to :attr:`datetime.timezone.utc`.
>>> parse('2009-01-01T10:01:02Z')
datetime.datetime(2009, 1, 1, 10, 1, 2, tzinfo=datetime.timezone.utc)
Otherwise, a :class:`datetime.timezone` instance is created with the appropriate offset, and
the `tzinfo` parameter of the returned `datetime` is set to that value.
>>> parse('2009-01-01T14:01:02-04:00')
datetime.datetime(2009, 1, 1, 14, 1, 2, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=72000), ''))
However, if `parse()` is called with `utc=True`, then the returned
`datetime` will be normalized to UTC (and its tzinfo parameter set to
`datetime.timezone.utc`), regardless of the input timezone.
>>> parse('2009-01-01T06:01:02-04:00', utc=True)
datetime.datetime(2009, 1, 1, 10, 1, 2, tzinfo=datetime.timezone.utc)
The input is strictly required to conform to :RFC:`3339`, and appropriate
exceptions are thrown for invalid input.
>>> parse('2009-01-01T06:01:02')
Traceback (most recent call last):
...
ValueError: timestamp does not conform to RFC 3339
>>> parse('2009-01-01T25:01:02Z')
Traceback (most recent call last):
...
ValueError: hour must be in 0..23
"""
parse_re = re.compile(
r"""^(?:(?:(?P[0-9]{4})\-(?P[0-9]{2})\-(?P[0-9]{2}))T(?:(?:(?P[0-9]{2})\:(?P[0-9]{2})\:(?P[0-9]{2})(?P(?:\.[0-9]{1,}))?)(?P(?:Z|(?P(?P(?:\+|\-)[0-9]{2})\:(?P[0-9]{2}))))))$""",
re.I | re.X,
)
match = parse_re.match(timestamp)
if match is not None:
if match.group("time_offset") in ["Z", "z", "+00:00", "-00:00"]:
if produce_naive is True:
tzinfo = None
else:
tzinfo = timezone.utc
else:
if produce_naive is True:
raise ValueError(
"cannot produce a naive datetime from a local timestamp"
)
else:
tz_hours = int(match.group("time_houroffset"))
tz_minutes = int(match.group("time_minuteoffset"))
if tz_hours < 0:
tz_minutes *= -1
td = timedelta(hours=tz_hours, minutes=tz_minutes)
tzinfo = timezone(td, f"")
secfrac = match.group("time_secfrac")
if secfrac is None:
microsecond = 0
else:
microsecond = int(round(float(secfrac) * 1000000))
dt_out = datetime(
year=int(match.group("date_fullyear")),
month=int(match.group("date_month")),
day=int(match.group("date_mday")),
hour=int(match.group("time_hour")),
minute=int(match.group("time_minute")),
second=int(match.group("time_second")),
microsecond=microsecond,
tzinfo=tzinfo,
)
if utc:
dt_out = dt_out.astimezone(timezone.utc)
return dt_out
else:
raise ValueError("timestamp does not conform to RFC 3339")
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684479.0
pyrfc3339-2.0.1/pyrfc3339/utils.py 0000644 0001751 0000177 00000001017 14712023077 015745 0 ustar 00runner docker def format_timezone(utcoffset):
"""
Return a string representing the timezone offset.
Remaining seconds are rounded to the nearest minute.
>>> format_timezone(3600)
'+01:00'
>>> format_timezone(5400)
'+01:30'
>>> format_timezone(-28800)
'-08:00'
"""
hours, seconds = divmod(abs(utcoffset), 3600)
minutes = round(float(seconds) / 60)
if utcoffset >= 0:
sign = "+"
else:
sign = "-"
return "{0}{1:02d}:{2:02d}".format(sign, int(hours), int(minutes))
././@PaxHeader 0000000 0000000 0000000 00000000034 00000000000 010212 x ustar 00 28 mtime=1730684484.0257382
pyrfc3339-2.0.1/setup.cfg 0000644 0001751 0000177 00000000046 14712023104 014377 0 ustar 00runner docker [egg_info]
tag_build =
tag_date = 0
././@PaxHeader 0000000 0000000 0000000 00000000026 00000000000 010213 x ustar 00 22 mtime=1730684479.0
pyrfc3339-2.0.1/setup.py 0000644 0001751 0000177 00000001407 14712023077 014303 0 ustar 00runner docker from setuptools import setup
with open("README.rst", "r") as readme:
long_description = readme.read()
setup(
name = "pyRFC3339",
version = "2.0.1",
author = "Kurt Raschke",
author_email = "kurt@kurtraschke.com",
url = "https://github.com/kurtraschke/pyRFC3339",
description = "Generate and parse RFC 3339 timestamps",
long_description = long_description,
keywords = "rfc 3339 timestamp",
license = "MIT",
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Topic :: Internet"
],
packages = ['pyrfc3339']
)