pyRFC3339-1.1/ 0000755 0000765 0000024 00000000000 13307340132 012764 5 ustar kurt staff 0000000 0000000 pyRFC3339-1.1/PKG-INFO 0000644 0000765 0000024 00000004361 13307340132 014065 0 ustar kurt staff 0000000 0000000 Metadata-Version: 1.1
Name: pyRFC3339
Version: 1.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
Description: Description
===========
.. image:: https://travis-ci.org/kurtraschke/pyRFC3339.svg?branch=master
:target: https://travis-ci.org/kurtraschke/pyRFC3339
pyRFC3339 parses and generates :RFC:`3339`-compliant timestamps using `Python `_ `datetime.datetime `_ objects.
>>> from pyrfc3339 import generate, parse
>>> from datetime import datetime
>>> import pytz
>>> generate(datetime.utcnow().replace(tzinfo=pytz.utc)) #doctest:+ELLIPSIS
'...T...Z'
>>> parse('2009-01-01T10:01:02Z')
datetime.datetime(2009, 1, 1, 10, 1, 2, tzinfo=)
>>> parse('2009-01-01T14:01:02-04:00')
datetime.datetime(2009, 1, 1, 14, 1, 2, tzinfo=)
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 Sphinx``
#. ``$ python setup.py build_sphinx``
The documentation is also available online at:
``https://pythonhosted.org/pyRFC3339/``
Keywords: rfc 3339 timestamp
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Topic :: Internet
pyRFC3339-1.1/pyRFC3339.egg-info/ 0000755 0000765 0000024 00000000000 13307340132 015763 5 ustar kurt staff 0000000 0000000 pyRFC3339-1.1/pyRFC3339.egg-info/PKG-INFO 0000644 0000765 0000024 00000004361 13307340132 017064 0 ustar kurt staff 0000000 0000000 Metadata-Version: 1.1
Name: pyRFC3339
Version: 1.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
Description: Description
===========
.. image:: https://travis-ci.org/kurtraschke/pyRFC3339.svg?branch=master
:target: https://travis-ci.org/kurtraschke/pyRFC3339
pyRFC3339 parses and generates :RFC:`3339`-compliant timestamps using `Python `_ `datetime.datetime `_ objects.
>>> from pyrfc3339 import generate, parse
>>> from datetime import datetime
>>> import pytz
>>> generate(datetime.utcnow().replace(tzinfo=pytz.utc)) #doctest:+ELLIPSIS
'...T...Z'
>>> parse('2009-01-01T10:01:02Z')
datetime.datetime(2009, 1, 1, 10, 1, 2, tzinfo=)
>>> parse('2009-01-01T14:01:02-04:00')
datetime.datetime(2009, 1, 1, 14, 1, 2, tzinfo=)
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 Sphinx``
#. ``$ python setup.py build_sphinx``
The documentation is also available online at:
``https://pythonhosted.org/pyRFC3339/``
Keywords: rfc 3339 timestamp
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Topic :: Internet
pyRFC3339-1.1/pyRFC3339.egg-info/SOURCES.txt 0000644 0000765 0000024 00000000455 13307340132 017653 0 ustar kurt staff 0000000 0000000 LICENSE.txt
MANIFEST.in
README.rst
setup.cfg
setup.py
pyRFC3339.egg-info/PKG-INFO
pyRFC3339.egg-info/SOURCES.txt
pyRFC3339.egg-info/dependency_links.txt
pyRFC3339.egg-info/requires.txt
pyRFC3339.egg-info/top_level.txt
pyrfc3339/__init__.py
pyrfc3339/generator.py
pyrfc3339/parser.py
pyrfc3339/utils.py pyRFC3339-1.1/pyRFC3339.egg-info/requires.txt 0000644 0000765 0000024 00000000005 13307340132 020356 0 ustar kurt staff 0000000 0000000 pytz
pyRFC3339-1.1/pyRFC3339.egg-info/top_level.txt 0000644 0000765 0000024 00000000012 13307340132 020506 0 ustar kurt staff 0000000 0000000 pyrfc3339
pyRFC3339-1.1/pyRFC3339.egg-info/dependency_links.txt 0000644 0000765 0000024 00000000001 13307340132 022031 0 ustar kurt staff 0000000 0000000
pyRFC3339-1.1/MANIFEST.in 0000644 0000765 0000024 00000000024 13302303551 014515 0 ustar kurt staff 0000000 0000000 include LICENSE.txt
pyRFC3339-1.1/pyrfc3339/ 0000755 0000765 0000024 00000000000 13307340132 014431 5 ustar kurt staff 0000000 0000000 pyRFC3339-1.1/pyrfc3339/__init__.py 0000644 0000765 0000024 00000001127 13302303551 016542 0 ustar kurt staff 0000000 0000000 """
pyRFC3339 parses and generates :RFC:`3339`-compliant timestamps using Python
:class:`datetime.datetime` objects.
>>> from pyrfc3339 import generate, parse
>>> from datetime import datetime
>>> import pytz
>>> generate(datetime.utcnow().replace(tzinfo=pytz.utc)) #doctest:+ELLIPSIS
'...T...Z'
>>> parse('2009-01-01T10:01:02Z')
datetime.datetime(2009, 1, 1, 10, 1, 2, tzinfo=)
>>> parse('2009-01-01T14:01:02-04:00')
datetime.datetime(2009, 1, 1, 14, 1, 2, tzinfo=)
"""
from pyrfc3339.generator import generate
from pyrfc3339.parser import parse
__all__ = ['generate', 'parse']
pyRFC3339-1.1/pyrfc3339/parser.py 0000644 0000765 0000024 00000006303 13302303551 016300 0 ustar kurt staff 0000000 0000000 import re
from datetime import datetime
import pytz
from pyrfc3339.utils import FixedOffset
def parse(timestamp, utc=False, produce_naive=False):
'''
Parse an :RFC:`3339`-formatted timestamp and return a
`datetime.datetime`.
If the timestamp is presented in UTC, then the `tzinfo` parameter of the
returned `datetime` will be set to `pytz.utc`.
>>> parse('2009-01-01T10:01:02Z')
datetime.datetime(2009, 1, 1, 10, 1, 2, tzinfo=)
Otherwise, a `tzinfo` 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=)
However, if `parse()` is called with `utc=True`, then the returned
`datetime` will be normalized to UTC (and its tzinfo parameter set to
`pytz.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=)
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 = pytz.utc
else:
if produce_naive is True:
raise ValueError("cannot produce a naive datetime from " +
"a local timestamp")
else:
tzinfo = FixedOffset(int(match.group('time_houroffset')),
int(match.group('time_minuteoffset')))
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(pytz.utc)
return dt_out
else:
raise ValueError("timestamp does not conform to RFC 3339")
pyRFC3339-1.1/pyrfc3339/generator.py 0000644 0000765 0000024 00000004172 13302303551 016774 0 ustar kurt staff 0000000 0000000 import pytz
from pyrfc3339.utils import timezone, timedelta_seconds
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
>>> generate(datetime(2009,1,1,12,59,59,0,pytz.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 = pytz.timezone('US/Eastern')
>>> dt = eastern.localize(datetime(2009,1,1,12,59,59))
>>> 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=pytz.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(pytz.utc)
timestamp = dt.strftime('%Y-%m-%dT%H:%M:%S')
if microseconds is True:
timestamp += dt.strftime('.%f')
if dt.tzinfo is pytz.utc:
timestamp += 'Z'
else:
timestamp += timezone(timedelta_seconds(dt.tzinfo.utcoffset(dt)))
return timestamp
pyRFC3339-1.1/pyrfc3339/utils.py 0000644 0000765 0000024 00000006521 13307335306 016156 0 ustar kurt staff 0000000 0000000 from __future__ import division
from datetime import timedelta, tzinfo
from copy import deepcopy
class FixedOffset(tzinfo):
'''
Represent a timezone with a fixed offset from UTC and no adjustment for
DST.
>>> FixedOffset(4,0)
>>> FixedOffset(-4,0)
>>> FixedOffset(4,30)
>>> tz = FixedOffset(-5,0)
>>> tz.dst(None)
datetime.timedelta(0)
The class tries to do the right thing with the sign
of the time zone offset:
>>> FixedOffset(-9,30)
>>> FixedOffset(-9,-30)
Traceback (most recent call last):
...
ValueError: minutes must not be negative
Offsets must thus be normalized so that the minute value is positive:
>>> FixedOffset(-8,30)
'''
def __init__(self, hours, minutes):
'''
Create a new FixedOffset instance with the given offset.
'''
tzinfo.__init__(self)
if minutes < 0:
raise ValueError("minutes must not be negative")
if hours < 0:
minutes *= -1
self.__offset = timedelta(hours=hours,
minutes=minutes)
self.__name = "UTC" + timezone(timedelta_seconds(self.__offset))
def dst(self, dt):
'''
Return offset for DST. Always returns timedelta(0).
'''
return timedelta(0)
def utcoffset(self, dt):
'''
Return offset from UTC.
'''
return self.__offset
def tzname(self, dt):
'''
Return name of timezone.
'''
return self.__name
def __repr__(self):
return "<{0}>".format(self.tzname(None))
def __deepcopy__(self, memo):
cls = self.__class__
result = cls.__new__(cls)
memo[id(self)] = result
for k, v in self.__dict__.items():
setattr(result, k, deepcopy(v, memo))
return result
def timedelta_seconds(td):
'''
Return the offset stored by a :class:`datetime.timedelta` object as an
integer number of seconds. Microseconds, if present, are rounded to
the nearest second.
Delegates to
:meth:`timedelta.total_seconds() `
if available.
>>> timedelta_seconds(timedelta(hours=1))
3600
>>> timedelta_seconds(timedelta(hours=-1))
-3600
>>> timedelta_seconds(timedelta(hours=1, minutes=30))
5400
>>> timedelta_seconds(timedelta(hours=1, minutes=30,
... microseconds=300000))
5400
>>> timedelta_seconds(timedelta(hours=1, minutes=30,
... microseconds=900000))
5401
'''
try:
return int(round(td.total_seconds()))
except AttributeError:
days = td.days
seconds = td.seconds
microseconds = td.microseconds
return int(round((days * 86400) + seconds + (microseconds / 1000000)))
def timezone(utcoffset):
'''
Return a string representing the timezone offset.
Remaining seconds are rounded to the nearest minute.
>>> timezone(3600)
'+01:00'
>>> timezone(5400)
'+01:30'
>>> 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))
pyRFC3339-1.1/setup.py 0000644 0000765 0000024 00000002133 13307335306 014504 0 ustar kurt staff 0000000 0000000 from setuptools import setup
with open("README.rst", "r") as readme:
long_description = readme.read()
setup(
name = "pyRFC3339",
version = "1.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 :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Topic :: Internet"
],
packages = ['pyrfc3339'],
install_requires = ['pytz'],
test_suite = 'nose.collector',
tests_require = ['nose']
)
pyRFC3339-1.1/setup.cfg 0000644 0000765 0000024 00000000720 13307340132 014604 0 ustar kurt staff 0000000 0000000 [nosetests]
verbosity = 2
detailed-errors = 1
with-coverage = 1
cover-package = pyrfc3339
cover-erase = 1
cover-html = 1
cover-html-dir = docs/coverage
with-doctest = 1
attr = !slow
[build_sphinx]
source-dir = docs/source
build-dir = docs/build
all-files = 1
builder = html
[upload_sphinx]
upload-dir = docs/build/html
[egg_info]
tag_build =
tag_date = 0
[bdist_wheel]
universal = 1
[aliases]
release = egg_info -Db ''
make_dist = release sdist bdist_wheel
pyRFC3339-1.1/README.rst 0000644 0000765 0000024 00000002250 13302303551 014451 0 ustar kurt staff 0000000 0000000 Description
===========
.. image:: https://travis-ci.org/kurtraschke/pyRFC3339.svg?branch=master
:target: https://travis-ci.org/kurtraschke/pyRFC3339
pyRFC3339 parses and generates :RFC:`3339`-compliant timestamps using `Python `_ `datetime.datetime `_ objects.
>>> from pyrfc3339 import generate, parse
>>> from datetime import datetime
>>> import pytz
>>> generate(datetime.utcnow().replace(tzinfo=pytz.utc)) #doctest:+ELLIPSIS
'...T...Z'
>>> parse('2009-01-01T10:01:02Z')
datetime.datetime(2009, 1, 1, 10, 1, 2, tzinfo=)
>>> parse('2009-01-01T14:01:02-04:00')
datetime.datetime(2009, 1, 1, 14, 1, 2, tzinfo=)
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 Sphinx``
#. ``$ python setup.py build_sphinx``
The documentation is also available online at:
``https://pythonhosted.org/pyRFC3339/``
pyRFC3339-1.1/LICENSE.txt 0000644 0000765 0000024 00000002040 13302347042 014605 0 ustar kurt staff 0000000 0000000 Copyright (c) 2018 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.