python-dateutil
Advanced tools
| # This workflow is triggered three ways: | ||
| # | ||
| # 1. Manually triggering the workflow via the GitHub UI (Actions > Upload | ||
| # package) will upload to test.pypi.org without the need to create a tag. | ||
| # 2. When a tag is created, the workflow will upload the package to | ||
| # test.pypi.org. | ||
| # 3. When a GitHub Release is made, the workflow will upload the package to pypi.org. | ||
| # | ||
| # It is done this way until PyPI has draft reviews, to allow for a two-stage | ||
| # upload with a chance for manual intervention before the final publication. | ||
| name: Upload package | ||
| on: | ||
| release: | ||
| types: [created] | ||
| push: | ||
| tags: | ||
| - '*' | ||
| workflow_dispatch: | ||
| jobs: | ||
| deploy: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v2 | ||
| - name: Set up Python | ||
| uses: actions/setup-python@v2 | ||
| with: | ||
| python-version: '3.9' | ||
| - name: Install dependencies | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install -U tox | ||
| - name: Create tox environments | ||
| run: | | ||
| tox -p -e py,build,release --notest | ||
| - name: Run tests | ||
| run: | | ||
| tox -e py | ||
| - name: Build package | ||
| run: | | ||
| tox -e build | ||
| - name: Publish package | ||
| env: | ||
| TWINE_USERNAME: "__token__" | ||
| run: | | ||
| if [[ "$GITHUB_EVENT_NAME" == "push" || \ | ||
| "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]]; then | ||
| export TWINE_REPOSITORY_URL="https://test.pypi.org/legacy/" | ||
| export TWINE_PASSWORD="${{ secrets.TEST_PYPI_UPLOAD_TOKEN }}" | ||
| elif [[ "$GITHUB_EVENT_NAME" == "release" ]]; then | ||
| export TWINE_REPOSITORY="pypi" | ||
| export TWINE_PASSWORD="${{ secrets.PYPI_UPLOAD_TOKEN }}" | ||
| else | ||
| echo "Unknown event name: ${GITHUB_EVENT_NAME}" | ||
| exit 1 | ||
| fi | ||
| tox -e release |
| name: Validate | ||
| on: | ||
| push: | ||
| branches: | ||
| - master | ||
| pull_request: | ||
| branches: | ||
| - master | ||
| jobs: | ||
| test: | ||
| strategy: | ||
| matrix: | ||
| python-version: [ | ||
| "2.7", | ||
| "3.5", | ||
| "3.6", | ||
| "3.7", | ||
| "3.8", | ||
| "3.9", | ||
| "pypy2", | ||
| "pypy3", | ||
| ] | ||
| os: [ubuntu-latest, windows-latest, macos-latest] | ||
| runs-on: ${{ matrix.os }} | ||
| env: | ||
| TOXENV: py | ||
| steps: | ||
| - uses: actions/checkout@v2 | ||
| - name: Set up Python ${{ matrix.python-version }} on ${{ matrix.os }} | ||
| uses: actions/setup-python@v1 | ||
| with: | ||
| python-version: ${{ matrix.python-version }} | ||
| - name: Install dependencies | ||
| run: python -m pip install -U tox | ||
| - name: Install zic (Windows) | ||
| run: | | ||
| curl https://get.enterprisedb.com/postgresql/postgresql-9.5.21-2-windows-x64-binaries.zip --output $env:GITHUB_WORKSPACE\postgresql9.5.21.zip | ||
| unzip -oq $env:GITHUB_WORKSPACE\postgresql9.5.21.zip -d .postgresql | ||
| if: runner.os == 'Windows' | ||
| - name: Run updatezinfo.py (Windows) | ||
| run: | | ||
| $env:Path += ";$env:GITHUB_WORKSPACE\.postgresql\pgsql\bin" | ||
| ci_tools/retry.bat python updatezinfo.py | ||
| if: runner.os == 'Windows' | ||
| - name: Run updatezinfo.py (Unix) | ||
| run: ./ci_tools/retry.sh python updatezinfo.py | ||
| if: runner.os != 'Windows' | ||
| - name: Run tox | ||
| run: python -m tox | ||
| - name: Generate coverage.xml | ||
| run: python -m tox -e coverage | ||
| - name: Report coverage to Codecov | ||
| uses: codecov/codecov-action@v1 | ||
| with: | ||
| file: ./.tox/coverage.xml | ||
| name: ${{ matrix.os }}:${{ matrix.python-version }} | ||
| fail_ci_if_error: true | ||
| docs: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v2 | ||
| - name: Set up Python | ||
| uses: actions/setup-python@v1 | ||
| with: | ||
| python-version: 3.6 | ||
| - name: Install tox | ||
| run: python -m pip install -U tox | ||
| - name: Run tox | ||
| run: python -m tox -e docs | ||
| latest-tz: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v2 | ||
| - name: Set up Python | ||
| uses: actions/setup-python@v1 | ||
| with: | ||
| python-version: 3.6 | ||
| - name: Install tox | ||
| run: python -m pip install -U "tox<3.8.0" | ||
| - name: Run updatezinfo.py | ||
| run: ./ci_tools/retry.sh python updatezinfo.py | ||
| - name: Run tox | ||
| run: python -m tox -e tz | ||
| build-dist: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v2 | ||
| - name: Set up Python | ||
| uses: actions/setup-python@v2 | ||
| with: | ||
| python-version: "3.9" | ||
| - name: Install tox | ||
| run: python -m pip install -U tox | ||
| - name: Run tox | ||
| run: python -m tox -e build | ||
| - name: Check generation | ||
| run: | | ||
| exactly_one() { | ||
| value=$(find dist -iname $1 | wc -l) | ||
| if [ $value -ne 1 ]; then | ||
| echo "Found $value instances of $1, not 1" | ||
| return 1 | ||
| else | ||
| echo "Found exactly 1 instance of $value" | ||
| fi | ||
| } | ||
| # Check that exactly one tarball and one wheel are created | ||
| exactly_one '*.tar.gz' | ||
| exactly_one '*.whl' |
| from datetime import datetime, timedelta | ||
| import pytest | ||
| import six | ||
| from hypothesis import assume, given | ||
| from hypothesis import strategies as st | ||
| from dateutil import tz as tz | ||
| EPOCHALYPSE = datetime.fromtimestamp(2147483647) | ||
| NEGATIVE_EPOCHALYPSE = datetime.fromtimestamp(0) - timedelta(seconds=2147483648) | ||
| @pytest.mark.gettz | ||
| @pytest.mark.parametrize("gettz_arg", [None, ""]) | ||
| # TODO: Remove bounds when GH #590 is resolved | ||
| @given( | ||
| dt=st.datetimes( | ||
| min_value=NEGATIVE_EPOCHALYPSE, max_value=EPOCHALYPSE, timezones=st.just(tz.UTC), | ||
| ) | ||
| ) | ||
| def test_gettz_returns_local(gettz_arg, dt): | ||
| act_tz = tz.gettz(gettz_arg) | ||
| if isinstance(act_tz, tz.tzlocal): | ||
| return | ||
| dt_act = dt.astimezone(tz.gettz(gettz_arg)) | ||
| if six.PY2: | ||
| dt_exp = dt.astimezone(tz.tzlocal()) | ||
| else: | ||
| dt_exp = dt.astimezone() | ||
| assert dt_act == dt_exp | ||
| assert dt_act.tzname() == dt_exp.tzname() | ||
| assert dt_act.utcoffset() == dt_exp.utcoffset() |
+6
-34
| language: python | ||
| cache: pip | ||
| python: | ||
| - "2.7" | ||
| - "3.4" | ||
| - "3.5" | ||
| - "3.6" | ||
| - "3.7" | ||
| - "3.8" | ||
| - "nightly" | ||
| - "pypy" | ||
| - "pypy3.5" | ||
| - "pypy3.6" | ||
| env: | ||
| TOXENV=py | ||
| env: TOXENV=py | ||
@@ -23,12 +14,5 @@ matrix: | ||
| dist: trusty | ||
| env: TOXENV=py33 # Needed because "py" won't invoke testenv:py33 | ||
| - python: 3.6 | ||
| env: TOXENV=docs | ||
| - python: 3.6 | ||
| env: TOXENV=tz | ||
| - python: 3.7 | ||
| env: TOXENV=build | ||
| env: TOXENV=py33 # Needed because "py" won't invoke testenv:py33 | ||
| allow_failures: | ||
| - python: "nightly" | ||
| - python: "pypy3.6" | ||
@@ -41,2 +25,6 @@ install: | ||
| fi | ||
| - | | ||
| if [[ $TRAVIS_PYTHON_VERSION == "3.4" ]]; then | ||
| pip install -U setuptools | ||
| fi | ||
| - pip install -U "tox<3.8.0" $PIP_ARGS | ||
@@ -47,20 +35,4 @@ - if [[ $TOXENV == "py" ]]; then ./ci_tools/retry.sh python updatezinfo.py; fi | ||
| - tox | ||
| - | | ||
| if [[ $TOXENV == "build" ]]; then | ||
| exactly_one() { | ||
| value=$(find dist -iname $1 | wc -l) | ||
| if [ $value -ne 1 ]; then | ||
| echo "Found $value instances of $1, not 1" | ||
| return 1 | ||
| else | ||
| echo "Found exactly 1 instance of $value" | ||
| fi | ||
| } | ||
| # Check that exactly one tarball and one wheel are created | ||
| exactly_one '*.tar.gz' | ||
| exactly_one '*.whl' | ||
| fi | ||
| after_success: | ||
| - if [[ $TOXENV == "py" ]]; then tox -e coverage,codecov; fi |
+3
-10
| build: false | ||
| environment: | ||
| matrix: | ||
| - PYTHON_VERSION: 27 | ||
| - PYTHON_VERSION: 33 | ||
| - PYTHON_VERSION: 34 | ||
| - PYTHON_VERSION: 35 | ||
| - PYTHON_VERSION: 36 | ||
| platform: | ||
@@ -17,8 +13,4 @@ - x64 | ||
| - platform: x86 | ||
| PYTHON_VERSION: 33 | ||
| - platform: x86 | ||
| PYTHON_VERSION: 34 | ||
| - platform: x86 | ||
| PYTHON_VERSION: 35 | ||
| install: | ||
@@ -46,2 +38,3 @@ # set env variables | ||
| after_test: | ||
| - C:\Python36\scripts\tox -e coverage,codecov | ||
| # Uploading coverage on Python 3.4 on Windows is not worth the effort. | ||
| - if NOT %PYTHON_VERSION% == 34 (C:\Python36\scripts\tox -e coverage,codecov) |
+7
-0
@@ -27,2 +27,3 @@ This is a (possibly incomplete) list of all the contributors to python-dateutil, | ||
| - Andrew Murray <radarhere@MASKED> | ||
| - Arclight <arclight@MASKED> (gh: @arclightslavik) | ||
| - Aritro Nandi <gurgenz221@gmail.com> (gh: @gurgenz221) **D** | ||
@@ -42,2 +43,3 @@ - Bernat Gabor <bgabor8@bloomberg.net> (gh: @gaborbernat) **D** | ||
| - Cosimo Lupo <cosimo@anthrotype.com> (gh: @anthrotype) **D** | ||
| - Daniel Lemm (gh: @ffe4) **D** | ||
| - Daniel Lepage <dplepage@MASKED> | ||
@@ -75,2 +77,3 @@ - David Lehrian <david@MASKED> | ||
| - Mario Corchero <mcorcherojim@MASKED> (gh: @mariocj89) **R** | ||
| - Mark Bailey <msb@MASKED> **D** | ||
| - Mateusz Dziedzic (gh: @m-dz) **D** | ||
@@ -83,2 +86,3 @@ - Matt Cooper <vtbassmatt@MASKED> (gh: @vtbassmatt) **D** | ||
| - Michael J. Schultz <mjschultz@MASKED> | ||
| - Michael Käufl (gh: @michael-k) | ||
| - Mike Gilbert <floppym@MASKED> | ||
@@ -89,2 +93,3 @@ - Nicholas Herrriot <Nicholas.Herriot@gmail.com> **D** | ||
| - Orson Adams <orson.network@MASKED> (gh: @parsethis) **D** | ||
| - Paul Brown (gh: @pawl) **D** | ||
| - Paul Dickson (gh @prdickson) **D** | ||
@@ -99,2 +104,3 @@ - Paul Ganssle <paul@ganssle.io> (gh: @pganssle) **R** | ||
| - Ridhi Mahajan <ridhikmahajan@MASKED> **D** | ||
| - Robin Henriksson Törnström <gh: @MrRawbin> **D** | ||
| - Roy Williams <rwilliams@MASKED> | ||
@@ -112,2 +118,3 @@ - Rustem Saiargaliev (gh: @amureki) **D** | ||
| - Thomas Kluyver <takowl@MASKED> (gh: @takluyver) | ||
| - Tim Gates <tim.gates@iress.com> (gh: timgates42) | ||
| - Tomasz Kluczkowski (gh: @Tomasz-Kluczkowski) **D** | ||
@@ -114,0 +121,0 @@ - Tomi Pieviläinen <tomi.pievilainen@iki.fi> |
@@ -19,5 +19,3 @@ #!/usr/bin/env python3 | ||
| "southamerica", | ||
| "pacificnew", | ||
| "etcetera", | ||
| "systemv", | ||
| "factory", | ||
@@ -24,0 +22,0 @@ "backzone", |
@@ -72,3 +72,3 @@ #!/usr/bin/env bash | ||
| # Install everything else | ||
| make TOPDIR=$TMP_DIR/tzdir install | ||
| make ZFLAGS='-b fat' TOPDIR="$TMP_DIR/tzdir" install | ||
@@ -75,0 +75,0 @@ # |
| # coding: utf-8 | ||
| # file generated by setuptools_scm | ||
| # don't change, don't track in version control | ||
| version = '2.8.1' | ||
| version = '2.8.2' | ||
| version_tuple = (2, 8, 2) |
| # -*- coding: utf-8 -*- | ||
| """ | ||
| This module offers a generic easter computing method for any given year, using | ||
| This module offers a generic Easter computing method for any given year, using | ||
| Western, Orthodox or Julian algorithms. | ||
@@ -24,11 +24,11 @@ """ | ||
| This algorithm implements three different easter | ||
| This algorithm implements three different Easter | ||
| calculation methods: | ||
| 1 - Original calculation in Julian calendar, valid in | ||
| dates after 326 AD | ||
| 2 - Original method, with date converted to Gregorian | ||
| calendar, valid in years 1583 to 4099 | ||
| 3 - Revised method, in Gregorian calendar, valid in | ||
| years 1583 to 4099 as well | ||
| 1. Original calculation in Julian calendar, valid in | ||
| dates after 326 AD | ||
| 2. Original method, with date converted to Gregorian | ||
| calendar, valid in years 1583 to 4099 | ||
| 3. Revised method, in Gregorian calendar, valid in | ||
| years 1583 to 4099 as well | ||
@@ -35,0 +35,0 @@ These methods are represented by the constants: |
@@ -23,7 +23,7 @@ # -*- coding: utf-8 -*- | ||
| - `A summary of the international standard date and time notation | ||
| <http://www.cl.cam.ac.uk/~mgk25/iso-time.html>`_ | ||
| - `W3C Date and Time Formats <http://www.w3.org/TR/NOTE-datetime>`_ | ||
| <https://www.cl.cam.ac.uk/~mgk25/iso-time.html>`_ | ||
| - `W3C Date and Time Formats <https://www.w3.org/TR/NOTE-datetime>`_ | ||
| - `Time Formats (Planetary Rings Node) <https://pds-rings.seti.org:443/tools/time_formats.html>`_ | ||
| - `CPAN ParseDate module | ||
| <http://search.cpan.org/~muir/Time-modules-2013.0912/lib/Time/ParseDate.pm>`_ | ||
| <https://metacpan.org/pod/release/MUIR/Time-modules-2013.0912/lib/Time/ParseDate.pm>`_ | ||
| - `Java SimpleDateFormat Class | ||
@@ -64,10 +64,4 @@ <https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html>`_ | ||
| def __init__(self, instream): | ||
| if six.PY2: | ||
| # In Python 2, we can't duck type properly because unicode has | ||
| # a 'decode' function, and we'd be double-decoding | ||
| if isinstance(instream, (bytes, bytearray)): | ||
| instream = instream.decode() | ||
| else: | ||
| if getattr(instream, 'decode', None) is not None: | ||
| instream = instream.decode() | ||
| if isinstance(instream, (bytes, bytearray)): | ||
| instream = instream.decode() | ||
@@ -659,3 +653,3 @@ if isinstance(instream, text_type): | ||
| except ValueError as e: | ||
| six.raise_from(ParserError(e.args[0] + ": %s", timestr), e) | ||
| six.raise_from(ParserError(str(e) + ": %s", timestr), e) | ||
@@ -1365,6 +1359,6 @@ if not ignoretz: | ||
| :raises ValueError: | ||
| Raised for invalid or unknown string format, if the provided | ||
| :class:`tzinfo` is not in a valid format, or if an invalid date | ||
| would be created. | ||
| :raises ParserError: | ||
| Raised for invalid or unknown string formats, if the provided | ||
| :class:`tzinfo` is not in a valid format, or if an invalid date would | ||
| be created. | ||
@@ -1600,3 +1594,9 @@ :raises OverflowError: | ||
| class ParserError(ValueError): | ||
| """Error class for representing failure to parse a datetime string.""" | ||
| """Exception subclass used for any failure to parse a datetime string. | ||
| This is a subclass of :py:exc:`ValueError`, and should be raised any time | ||
| earlier versions of ``dateutil`` would have raised ``ValueError``. | ||
| .. versionadded:: 2.8.1 | ||
| """ | ||
| def __str__(self): | ||
@@ -1608,8 +1608,12 @@ try: | ||
| def __repr__(self): | ||
| return "%s(%s)" % (self.__class__.__name__, str(self)) | ||
| def __repr__(self): | ||
| args = ", ".join("'%s'" % arg for arg in self.args) | ||
| return "%s(%s)" % (self.__class__.__name__, args) | ||
| class UnknownTimezoneWarning(RuntimeWarning): | ||
| """Raised when the parser finds a timezone it cannot parse into a tzinfo""" | ||
| """Raised when the parser finds a timezone it cannot parse into a tzinfo. | ||
| .. versionadded:: 2.7.0 | ||
| """ | ||
| # vim:ts=4:sw=4:et |
@@ -162,3 +162,3 @@ # -*- coding: utf-8 -*- | ||
| raise ValueError('String contains unknown ISO ' + | ||
| 'components: {}'.format(datestr)) | ||
| 'components: {!r}'.format(datestr.decode('ascii'))) | ||
| return date(*components) | ||
@@ -337,6 +337,6 @@ | ||
| if len(timestr) < 2: | ||
| if len_str < 2: | ||
| raise ValueError('ISO time too short') | ||
| has_sep = len_str >= 3 and timestr[2:3] == self._TIME_SEP | ||
| has_sep = False | ||
@@ -352,2 +352,10 @@ while pos < len_str and comp < 5: | ||
| if comp == 1 and timestr[pos:pos+1] == self._TIME_SEP: | ||
| has_sep = True | ||
| pos += 1 | ||
| elif comp == 2 and has_sep: | ||
| if timestr[pos:pos+1] != self._TIME_SEP: | ||
| raise ValueError('Inconsistent use of colon separator') | ||
| pos += 1 | ||
| if comp < 3: | ||
@@ -357,5 +365,2 @@ # Hour, minute, second | ||
| pos += 2 | ||
| if (has_sep and pos < len_str and | ||
| timestr[pos:pos + 1] == self._TIME_SEP): | ||
| pos += 1 | ||
@@ -362,0 +367,0 @@ if comp == 3: |
+128
-118
| import sys | ||
| import unittest | ||
| import pytest | ||
| class ImportVersionTest(unittest.TestCase): | ||
| HOST_IS_WINDOWS = sys.platform.startswith('win') | ||
| def test_import_version_str(): | ||
| """ Test that dateutil.__version__ can be imported""" | ||
| from dateutil import __version__ | ||
| def testImportVersionStr(self): | ||
| from dateutil import __version__ | ||
| def testImportRoot(self): | ||
| import dateutil | ||
| def test_import_version_root(): | ||
| import dateutil | ||
| assert hasattr(dateutil, '__version__') | ||
| self.assertTrue(hasattr(dateutil, '__version__')) | ||
| # Test that dateutil.easter-related imports work properly | ||
| def test_import_easter_direct(): | ||
| import dateutil.easter | ||
| class ImportEasterTest(unittest.TestCase): | ||
| """ Test that dateutil.easter-related imports work properly """ | ||
| def testEasterDirect(self): | ||
| import dateutil.easter | ||
| def test_import_easter_from(): | ||
| from dateutil import easter | ||
| def testEasterFrom(self): | ||
| from dateutil import easter | ||
| def testEasterStar(self): | ||
| from dateutil.easter import easter | ||
| def test_import_easter_start(): | ||
| from dateutil.easter import easter | ||
| class ImportParserTest(unittest.TestCase): | ||
| """ Test that dateutil.parser-related imports work properly """ | ||
| def testParserDirect(self): | ||
| import dateutil.parser | ||
| # Test that dateutil.parser-related imports work properly | ||
| def test_import_parser_direct(): | ||
| import dateutil.parser | ||
| def testParserFrom(self): | ||
| from dateutil import parser | ||
| def testParserAll(self): | ||
| # All interface | ||
| from dateutil.parser import parse | ||
| from dateutil.parser import parserinfo | ||
| def test_import_parser_from(): | ||
| from dateutil import parser | ||
| # Other public classes | ||
| from dateutil.parser import parser | ||
| for var in (parse, parserinfo, parser): | ||
| self.assertIsNot(var, None) | ||
| def test_import_parser_all(): | ||
| # All interface | ||
| from dateutil.parser import parse | ||
| from dateutil.parser import parserinfo | ||
| # Other public classes | ||
| from dateutil.parser import parser | ||
| class ImportRelativeDeltaTest(unittest.TestCase): | ||
| """ Test that dateutil.relativedelta-related imports work properly """ | ||
| def testRelativeDeltaDirect(self): | ||
| import dateutil.relativedelta | ||
| for var in (parse, parserinfo, parser): | ||
| assert var is not None | ||
| def testRelativeDeltaFrom(self): | ||
| from dateutil import relativedelta | ||
| def testRelativeDeltaAll(self): | ||
| from dateutil.relativedelta import relativedelta | ||
| from dateutil.relativedelta import MO, TU, WE, TH, FR, SA, SU | ||
| # Test that dateutil.relativedelta-related imports work properly | ||
| def test_import_relative_delta_direct(): | ||
| import dateutil.relativedelta | ||
| for var in (relativedelta, MO, TU, WE, TH, FR, SA, SU): | ||
| self.assertIsNot(var, None) | ||
| # In the public interface but not in all | ||
| from dateutil.relativedelta import weekday | ||
| self.assertIsNot(weekday, None) | ||
| def test_import_relative_delta_from(): | ||
| from dateutil import relativedelta | ||
| def test_import_relative_delta_all(): | ||
| from dateutil.relativedelta import relativedelta | ||
| from dateutil.relativedelta import MO, TU, WE, TH, FR, SA, SU | ||
| class ImportRRuleTest(unittest.TestCase): | ||
| """ Test that dateutil.rrule related imports work properly """ | ||
| def testRRuleDirect(self): | ||
| import dateutil.rrule | ||
| for var in (relativedelta, MO, TU, WE, TH, FR, SA, SU): | ||
| assert var is not None | ||
| def testRRuleFrom(self): | ||
| from dateutil import rrule | ||
| # In the public interface but not in all | ||
| from dateutil.relativedelta import weekday | ||
| assert weekday is not None | ||
| def testRRuleAll(self): | ||
| from dateutil.rrule import rrule | ||
| from dateutil.rrule import rruleset | ||
| from dateutil.rrule import rrulestr | ||
| from dateutil.rrule import YEARLY, MONTHLY, WEEKLY, DAILY | ||
| from dateutil.rrule import HOURLY, MINUTELY, SECONDLY | ||
| from dateutil.rrule import MO, TU, WE, TH, FR, SA, SU | ||
| rr_all = (rrule, rruleset, rrulestr, | ||
| YEARLY, MONTHLY, WEEKLY, DAILY, | ||
| HOURLY, MINUTELY, SECONDLY, | ||
| MO, TU, WE, TH, FR, SA, SU) | ||
| # Test that dateutil.rrule related imports work properly | ||
| def test_import_rrule_direct(): | ||
| import dateutil.rrule | ||
| for var in rr_all: | ||
| self.assertIsNot(var, None) | ||
| # In the public interface but not in all | ||
| from dateutil.rrule import weekday | ||
| self.assertIsNot(weekday, None) | ||
| def test_import_rrule_from(): | ||
| from dateutil import rrule | ||
| class ImportTZTest(unittest.TestCase): | ||
| """ Test that dateutil.tz related imports work properly """ | ||
| def testTzDirect(self): | ||
| import dateutil.tz | ||
| def test_import_rrule_all(): | ||
| from dateutil.rrule import rrule | ||
| from dateutil.rrule import rruleset | ||
| from dateutil.rrule import rrulestr | ||
| from dateutil.rrule import YEARLY, MONTHLY, WEEKLY, DAILY | ||
| from dateutil.rrule import HOURLY, MINUTELY, SECONDLY | ||
| from dateutil.rrule import MO, TU, WE, TH, FR, SA, SU | ||
| def testTzFrom(self): | ||
| from dateutil import tz | ||
| rr_all = (rrule, rruleset, rrulestr, | ||
| YEARLY, MONTHLY, WEEKLY, DAILY, | ||
| HOURLY, MINUTELY, SECONDLY, | ||
| MO, TU, WE, TH, FR, SA, SU) | ||
| def testTzAll(self): | ||
| from dateutil.tz import tzutc | ||
| from dateutil.tz import tzoffset | ||
| from dateutil.tz import tzlocal | ||
| from dateutil.tz import tzfile | ||
| from dateutil.tz import tzrange | ||
| from dateutil.tz import tzstr | ||
| from dateutil.tz import tzical | ||
| from dateutil.tz import gettz | ||
| from dateutil.tz import tzwin | ||
| from dateutil.tz import tzwinlocal | ||
| from dateutil.tz import UTC | ||
| from dateutil.tz import datetime_ambiguous | ||
| from dateutil.tz import datetime_exists | ||
| from dateutil.tz import resolve_imaginary | ||
| for var in rr_all: | ||
| assert var is not None | ||
| tz_all = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange", | ||
| "tzstr", "tzical", "gettz", "datetime_ambiguous", | ||
| "datetime_exists", "resolve_imaginary", "UTC"] | ||
| # In the public interface but not in all | ||
| from dateutil.rrule import weekday | ||
| assert weekday is not None | ||
| tz_all += ["tzwin", "tzwinlocal"] if sys.platform.startswith("win") else [] | ||
| lvars = locals() | ||
| for var in tz_all: | ||
| self.assertIsNot(lvars[var], None) | ||
| # Test that dateutil.tz related imports work properly | ||
| def test_import_tztest_direct(): | ||
| import dateutil.tz | ||
| @unittest.skipUnless(sys.platform.startswith('win'), "Requires Windows") | ||
| class ImportTZWinTest(unittest.TestCase): | ||
| """ Test that dateutil.tzwin related imports work properly """ | ||
| def testTzwinDirect(self): | ||
| import dateutil.tzwin | ||
| def testTzwinFrom(self): | ||
| from dateutil import tzwin | ||
| def test_import_tz_from(): | ||
| from dateutil import tz | ||
| def testTzwinStar(self): | ||
| from dateutil.tzwin import tzwin | ||
| from dateutil.tzwin import tzwinlocal | ||
| tzwin_all = [tzwin, tzwinlocal] | ||
| def test_import_tz_all(): | ||
| from dateutil.tz import tzutc | ||
| from dateutil.tz import tzoffset | ||
| from dateutil.tz import tzlocal | ||
| from dateutil.tz import tzfile | ||
| from dateutil.tz import tzrange | ||
| from dateutil.tz import tzstr | ||
| from dateutil.tz import tzical | ||
| from dateutil.tz import gettz | ||
| from dateutil.tz import tzwin | ||
| from dateutil.tz import tzwinlocal | ||
| from dateutil.tz import UTC | ||
| from dateutil.tz import datetime_ambiguous | ||
| from dateutil.tz import datetime_exists | ||
| from dateutil.tz import resolve_imaginary | ||
| for var in tzwin_all: | ||
| self.assertIsNot(var, None) | ||
| tz_all = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange", | ||
| "tzstr", "tzical", "gettz", "datetime_ambiguous", | ||
| "datetime_exists", "resolve_imaginary", "UTC"] | ||
| tz_all += ["tzwin", "tzwinlocal"] if sys.platform.startswith("win") else [] | ||
| lvars = locals() | ||
| class ImportZoneInfoTest(unittest.TestCase): | ||
| def testZoneinfoDirect(self): | ||
| import dateutil.zoneinfo | ||
| for var in tz_all: | ||
| assert lvars[var] is not None | ||
| def testZoneinfoFrom(self): | ||
| from dateutil import zoneinfo | ||
| # Test that dateutil.tzwin related imports work properly | ||
| @pytest.mark.skipif(not HOST_IS_WINDOWS, reason="Requires Windows") | ||
| def test_import_tz_windows_direct(): | ||
| import dateutil.tzwin | ||
| def testZoneinfoStar(self): | ||
| from dateutil.zoneinfo import gettz | ||
| from dateutil.zoneinfo import gettz_db_metadata | ||
| from dateutil.zoneinfo import rebuild | ||
| zi_all = (gettz, gettz_db_metadata, rebuild) | ||
| @pytest.mark.skipif(not HOST_IS_WINDOWS, reason="Requires Windows") | ||
| def test_import_tz_windows_from(): | ||
| from dateutil import tzwin | ||
| for var in zi_all: | ||
| self.assertIsNot(var, None) | ||
| @pytest.mark.skipif(not HOST_IS_WINDOWS, reason="Requires Windows") | ||
| def test_import_tz_windows_star(): | ||
| from dateutil.tzwin import tzwin | ||
| from dateutil.tzwin import tzwinlocal | ||
| tzwin_all = [tzwin, tzwinlocal] | ||
| for var in tzwin_all: | ||
| assert var is not None | ||
| # Test imports of Zone Info | ||
| def test_import_zone_info_direct(): | ||
| import dateutil.zoneinfo | ||
| def test_import_zone_info_from(): | ||
| from dateutil import zoneinfo | ||
| def test_import_zone_info_star(): | ||
| from dateutil.zoneinfo import gettz | ||
| from dateutil.zoneinfo import gettz_db_metadata | ||
| from dateutil.zoneinfo import rebuild | ||
| zi_all = (gettz, gettz_db_metadata, rebuild) | ||
| for var in zi_all: | ||
| assert var is not None |
@@ -10,5 +10,3 @@ # -*- coding: utf-8 -*- | ||
| import unittest | ||
| import sys | ||
| import pytest | ||
@@ -22,31 +20,29 @@ | ||
| class TestYMD(unittest.TestCase): | ||
| @pytest.mark.smoke | ||
| def test_YMD_could_be_day(): | ||
| ymd = _ymd('foo bar 124 baz') | ||
| # @pytest.mark.smoke | ||
| def test_could_be_day(self): | ||
| ymd = _ymd('foo bar 124 baz') | ||
| ymd.append(2, 'M') | ||
| assert ymd.has_month | ||
| assert not ymd.has_year | ||
| assert ymd.could_be_day(4) | ||
| assert not ymd.could_be_day(-6) | ||
| assert not ymd.could_be_day(32) | ||
| ymd.append(2, 'M') | ||
| assert ymd.has_month | ||
| assert not ymd.has_year | ||
| assert ymd.could_be_day(4) | ||
| assert not ymd.could_be_day(-6) | ||
| assert not ymd.could_be_day(32) | ||
| # Assumes leap year | ||
| assert ymd.could_be_day(29) | ||
| # Assumes leap year | ||
| assert ymd.could_be_day(29) | ||
| ymd.append(1999) | ||
| assert ymd.has_year | ||
| assert not ymd.could_be_day(29) | ||
| ymd.append(1999) | ||
| assert ymd.has_year | ||
| assert not ymd.could_be_day(29) | ||
| ymd.append(16, 'D') | ||
| assert ymd.has_day | ||
| assert not ymd.could_be_day(1) | ||
| ymd.append(16, 'D') | ||
| assert ymd.has_day | ||
| assert not ymd.could_be_day(1) | ||
| ymd = _ymd('foo bar 124 baz') | ||
| ymd.append(1999) | ||
| assert ymd.could_be_day(31) | ||
| ymd = _ymd('foo bar 124 baz') | ||
| ymd.append(1999) | ||
| assert ymd.could_be_day(31) | ||
| ### | ||
@@ -53,0 +49,0 @@ # Test that private interfaces in _parser are deprecated properly |
@@ -247,2 +247,4 @@ # -*- coding: utf-8 -*- | ||
| ('20120425T0120:00', ValueError), # Inconsistent time separators | ||
| ('20120425T01:2000', ValueError), # Inconsistent time separators | ||
| ('14:3015', ValueError), # Inconsistent time separator | ||
| ('20120425T012500-334', ValueError), # Wrong microsecond separator | ||
@@ -290,13 +292,2 @@ ('2001-1', ValueError), # YYYY-M not valid | ||
| @pytest.mark.xfail() | ||
| @pytest.mark.parametrize('isostr,exception', [ # pragma: nocover | ||
| ('20120425T01:2000', ValueError), # Inconsistent time separators | ||
| ]) | ||
| def test_iso_raises_failing(isostr, exception): | ||
| # These are test cases where the current implementation is too lenient | ||
| # and need to be fixed | ||
| with pytest.raises(exception): | ||
| isoparse(isostr) | ||
| ### | ||
@@ -402,2 +393,3 @@ # Test ISOParser constructor | ||
| ('2014-04-19T', ValueError), # Unknown components | ||
| ('201202', ValueError), # Invalid format | ||
| ]) | ||
@@ -409,2 +401,14 @@ def test_isodate_raises(isostr, exception): | ||
| def test_parse_isodate_error_text(): | ||
| with pytest.raises(ValueError) as excinfo: | ||
| isoparser().parse_isodate('2014-0423') | ||
| # ensure the error message does not contain b' prefixes | ||
| if six.PY2: | ||
| expected_error = "String contains unknown ISO components: u'2014-0423'" | ||
| else: | ||
| expected_error = "String contains unknown ISO components: '2014-0423'" | ||
| assert expected_error == str(excinfo.value) | ||
| ### | ||
@@ -510,12 +514,1 @@ # Test parse_isotime | ||
| iparser.parse_isotime(isostr) | ||
| @pytest.mark.xfail() | ||
| @pytest.mark.parametrize('isostr,exception', [ # pragma: nocover | ||
| ('14:3015', ValueError), # Inconsistent separator use | ||
| ('201202', ValueError) # Invalid ISO format | ||
| ]) | ||
| def test_isotime_raises_xfail(isostr, exception): | ||
| iparser = isoparser() | ||
| with pytest.raises(exception): | ||
| iparser.parse_isotime(isostr) |
@@ -25,7 +25,8 @@ # -*- coding: utf-8 -*- | ||
| PLATFORM_HAS_DASH_D = False | ||
| try: | ||
| datetime.now().strftime('%-d') | ||
| PLATFORM_HAS_DASH_D = True | ||
| if datetime.now().strftime('%-d'): | ||
| PLATFORM_HAS_DASH_D = True | ||
| except ValueError: | ||
| PLATFORM_HAS_DASH_D = False | ||
| pass | ||
@@ -747,2 +748,6 @@ | ||
| def test_illegal_month_error(self): | ||
| with pytest.raises(ParserError): | ||
| parse("0-100") | ||
| def test_day_sanity(self, fuzzy): | ||
@@ -876,3 +881,12 @@ dstr = "2014-15-25" | ||
| @pytest.mark.xfail | ||
| def test_extraneous_numerical_content(self): | ||
| # ref: https://github.com/dateutil/dateutil/issues/1029 | ||
| # parser interprets price and percentage as parts of the date | ||
| dstr = "£14.99 (25% off, until April 20)" | ||
| res = parse(dstr, fuzzy=True, default=datetime(2000, 1, 1)) | ||
| expected = datetime(2000, 4, 20) | ||
| assert res == expected | ||
| @pytest.mark.skipif(IS_WIN, reason="Windows does not use TZ var") | ||
@@ -945,1 +959,10 @@ class TestTZVar(object): | ||
| parse(value) | ||
| def test_parsererror_repr(): | ||
| # GH 991 — the __repr__ was not properly indented and so was never defined. | ||
| # This tests the current behavior of the ParserError __repr__, but the | ||
| # precise format is not guaranteed to be stable and may change even in | ||
| # minor versions. This test exists to avoid regressions. | ||
| s = repr(ParserError("Problem with string: %s", "2019-01-01")) | ||
| assert s == "ParserError('Problem with string: %s', '2019-01-01')" |
@@ -122,2 +122,10 @@ # -*- coding: utf-8 -*- | ||
| def testLastDayOfFebruary(self): | ||
| self.assertEqual(date(2021, 2, 1) + relativedelta(day=31), | ||
| date(2021, 2, 28)) | ||
| def testLastDayOfFebruaryLeapYear(self): | ||
| self.assertEqual(date(2020, 2, 1) + relativedelta(day=31), | ||
| date(2020, 2, 29)) | ||
| def testNextWednesdayIsToday(self): | ||
@@ -127,3 +135,3 @@ self.assertEqual(self.today+relativedelta(weekday=WE), | ||
| def testNextWenesdayNotToday(self): | ||
| def testNextWednesdayNotToday(self): | ||
| self.assertEqual(self.today+relativedelta(days=+1, weekday=WE), | ||
@@ -130,0 +138,0 @@ date(2003, 9, 24)) |
@@ -5,4 +5,2 @@ # -*- coding: utf-8 -*- | ||
| import unittest | ||
| from dateutil import tz | ||
@@ -18,38 +16,39 @@ from dateutil import utils | ||
| class UtilsTest(unittest.TestCase): | ||
| @freeze_time(datetime(2014, 12, 15, 1, 21, 33, 4003)) | ||
| def testToday(self): | ||
| self.assertEqual(utils.today(), datetime(2014, 12, 15, 0, 0, 0)) | ||
| @freeze_time(datetime(2014, 12, 15, 1, 21, 33, 4003)) | ||
| def test_utils_today(): | ||
| assert utils.today() == datetime(2014, 12, 15, 0, 0, 0) | ||
| @freeze_time(datetime(2014, 12, 15, 12), tz_offset=5) | ||
| def testTodayTzInfo(self): | ||
| self.assertEqual(utils.today(NYC), | ||
| datetime(2014, 12, 15, 0, 0, 0, tzinfo=NYC)) | ||
| @freeze_time(datetime(2014, 12, 15, 23), tz_offset=5) | ||
| def testTodayTzInfoDifferentDay(self): | ||
| self.assertEqual(utils.today(UTC), | ||
| datetime(2014, 12, 16, 0, 0, 0, tzinfo=UTC)) | ||
| @freeze_time(datetime(2014, 12, 15, 12), tz_offset=5) | ||
| def test_utils_today_tz_info(): | ||
| assert utils.today(NYC) == datetime(2014, 12, 15, 0, 0, 0, tzinfo=NYC) | ||
| def testDefaultTZInfoNaive(self): | ||
| dt = datetime(2014, 9, 14, 9, 30) | ||
| self.assertIs(utils.default_tzinfo(dt, NYC).tzinfo, | ||
| NYC) | ||
| def testDefaultTZInfoAware(self): | ||
| dt = datetime(2014, 9, 14, 9, 30, tzinfo=UTC) | ||
| self.assertIs(utils.default_tzinfo(dt, NYC).tzinfo, | ||
| UTC) | ||
| @freeze_time(datetime(2014, 12, 15, 23), tz_offset=5) | ||
| def test_utils_today_tz_info_different_day(): | ||
| assert utils.today(UTC) == datetime(2014, 12, 16, 0, 0, 0, tzinfo=UTC) | ||
| def testWithinDelta(self): | ||
| d1 = datetime(2016, 1, 1, 12, 14, 1, 9) | ||
| d2 = d1.replace(microsecond=15) | ||
| self.assertTrue(within_delta(d1, d2, timedelta(seconds=1))) | ||
| self.assertFalse(within_delta(d1, d2, timedelta(microseconds=1))) | ||
| def test_utils_default_tz_info_naive(): | ||
| dt = datetime(2014, 9, 14, 9, 30) | ||
| assert utils.default_tzinfo(dt, NYC).tzinfo is NYC | ||
| def testWithinDeltaWithNegativeDelta(self): | ||
| d1 = datetime(2016, 1, 1) | ||
| d2 = datetime(2015, 12, 31) | ||
| self.assertTrue(within_delta(d2, d1, timedelta(days=-1))) | ||
| def test_utils_default_tz_info_aware(): | ||
| dt = datetime(2014, 9, 14, 9, 30, tzinfo=UTC) | ||
| assert utils.default_tzinfo(dt, NYC).tzinfo is UTC | ||
| def test_utils_within_delta(): | ||
| d1 = datetime(2016, 1, 1, 12, 14, 1, 9) | ||
| d2 = d1.replace(microsecond=15) | ||
| assert within_delta(d1, d2, timedelta(seconds=1)) | ||
| assert not within_delta(d1, d2, timedelta(microseconds=1)) | ||
| def test_utils_within_delta_with_negative_delta(): | ||
| d1 = datetime(2016, 1, 1) | ||
| d2 = datetime(2015, 12, 31) | ||
| assert within_delta(d2, d1, timedelta(days=-1)) |
@@ -1599,3 +1599,3 @@ # -*- coding: utf-8 -*- | ||
| pass | ||
| if name is None or name == ":": | ||
| if name is None or name in ("", ":"): | ||
| for filepath in TZFILES: | ||
@@ -1602,0 +1602,0 @@ if not os.path.isabs(filepath): |
@@ -66,3 +66,3 @@ # -*- coding: utf-8 -*- | ||
| """ | ||
| Useful for comparing two datetimes that may a negilible difference | ||
| Useful for comparing two datetimes that may have a negligible difference | ||
| to be considered equal. | ||
@@ -69,0 +69,0 @@ """ |
@@ -6,3 +6,3 @@ import logging | ||
| import json | ||
| from subprocess import check_call | ||
| from subprocess import check_call, check_output | ||
| from tarfile import TarFile | ||
@@ -27,7 +27,5 @@ | ||
| filepaths = [os.path.join(tmpdir, n) for n in zonegroups] | ||
| try: | ||
| check_call(["zic", "-d", zonedir] + filepaths) | ||
| except OSError as e: | ||
| _print_on_nosuchfile(e) | ||
| raise | ||
| _run_zic(zonedir, filepaths) | ||
| # write metadata file | ||
@@ -45,2 +43,26 @@ with open(os.path.join(zonedir, METADATA_FN), 'w') as f: | ||
| def _run_zic(zonedir, filepaths): | ||
| """Calls the ``zic`` compiler in a compatible way to get a "fat" binary. | ||
| Recent versions of ``zic`` default to ``-b slim``, while older versions | ||
| don't even have the ``-b`` option (but default to "fat" binaries). The | ||
| current version of dateutil does not support Version 2+ TZif files, which | ||
| causes problems when used in conjunction with "slim" binaries, so this | ||
| function is used to ensure that we always get a "fat" binary. | ||
| """ | ||
| try: | ||
| help_text = check_output(["zic", "--help"]) | ||
| except OSError as e: | ||
| _print_on_nosuchfile(e) | ||
| raise | ||
| if b"-b " in help_text: | ||
| bloat_args = ["-b", "fat"] | ||
| else: | ||
| bloat_args = [] | ||
| check_call(["zic"] + bloat_args + ["-d", zonedir] + filepaths) | ||
| def _print_on_nosuchfile(e): | ||
@@ -47,0 +69,0 @@ """Print helpful troubleshooting message |
@@ -22,3 +22,3 @@ Exercises | ||
| How would you generate a `recurrence rule <../rrule.html>`_ that generates Martin Luther King Day, starting from its first observance in 1986? | ||
| How would you generate a :doc:`recurrence rule <../rrule>` that generates Martin Luther King Day, starting from its first observance in 1986? | ||
@@ -78,3 +78,3 @@ | ||
| A team has a meeting at 10 AM every Monday and wants a function that tells them, given a ``datetime.datetime`` object, what is the date and time of the *next* Monday meeting? This is probably best accomplished using a `relativedelta <../relativedelta.html>`_. | ||
| A team has a meeting at 10 AM every Monday and wants a function that tells them, given a ``datetime.datetime`` object, what is the date and time of the *next* Monday meeting? This is probably best accomplished using a :doc:`relativedelta <../relativedelta>`. | ||
@@ -130,3 +130,3 @@ **Test Script** | ||
| Three-character time zone abbreviations are *not* unique in that they do not explicitly map to a time zone. A list of time zone abbreviations in use can be found `here <https://www.timeanddate.com/time/zones/>`_. This means that parsing a datetime string such as ``'2018-01-01 12:30:30 CST'`` is ambiguous without context. Using `dateutil.parser <../parser.html>`_ and `dateutil.tz <../tz.html>`_, it is possible to provide a context such that these local names are converted to proper time zones. | ||
| Three-character time zone abbreviations are *not* unique in that they do not explicitly map to a time zone. A list of time zone abbreviations in use can be found `here <https://www.timeanddate.com/time/zones/>`_. This means that parsing a datetime string such as ``'2018-01-01 12:30:30 CST'`` is ambiguous without context. Using :mod:`dateutil.parser` and :mod:`dateutil.tz`, it is possible to provide a context such that these local names are converted to proper time zones. | ||
@@ -133,0 +133,0 @@ Problem 1 |
+22
-5
| ====== | ||
| parser | ||
| ====== | ||
| .. automodule:: dateutil.parser | ||
| .. automethod:: dateutil.parser.parse | ||
| Functions | ||
| --------- | ||
| .. autoclass:: dateutil.parser.parserinfo | ||
| :members: | ||
| :undoc-members: | ||
| .. automethod:: dateutil.parser.parse | ||
| .. automethod:: dateutil.parser.isoparse | ||
| .. automethod:: dateutil.parser.isoparse | ||
| Classes | ||
| ------- | ||
| .. autoclass:: dateutil.parser.parserinfo | ||
| :members: | ||
| :undoc-members: | ||
| Warnings and Exceptions | ||
| ----------------------- | ||
| .. autoclass:: dateutil.parser.ParserError | ||
| .. autoclass:: dateutil.parser.UnknownTimezoneWarning | ||
+6
-0
@@ -12,3 +12,9 @@ ===== | ||
| .. autoclass:: rrule | ||
| :members: | ||
| :undoc-members: | ||
| :inherited-members: | ||
| .. autoclass:: rruleset | ||
| :members: | ||
| :undoc-members: | ||
| :inherited-members: | ||
@@ -15,0 +21,0 @@ Functions |
+61
-3
@@ -0,1 +1,59 @@ | ||
| Version 2.8.2 (2021-07-08) | ||
| ========================== | ||
| Data updates | ||
| ------------ | ||
| - Updated tzdata version to 2021a. (gh pr #1128) | ||
| Bugfixes | ||
| -------- | ||
| - Fixed a bug in the parser where non-``ValueError`` exceptions would be raised | ||
| during exception handling; this would happen, for example, if an | ||
| ``IllegalMonthError`` was raised in ``dateutil`` code. Fixed by Mark Bailey. | ||
| (gh issue #981, pr #987). | ||
| - Fixed the custom ``repr`` for ``dateutil.parser.ParserError``, which was not | ||
| defined due to an indentation error. (gh issue #991, gh pr #993) | ||
| - Fixed a bug that caused ``b'`` prefixes to appear in parse_isodate exception | ||
| messages. Reported and fixed by Paul Brown (@pawl) (gh pr #1122) | ||
| - Make ``isoparse`` raise when trying to parse times with inconsistent use of | ||
| `:` separator. Reported and fixed by @mariocj89 (gh pr #1125). | ||
| - Fixed ``tz.gettz()`` not returning local time when passed an empty string. | ||
| Reported by @labrys (gh issues #925, #926). Fixed by @ffe4 (gh pr #1024) | ||
| Documentation changes | ||
| --------------------- | ||
| - Rearranged parser documentation into "Functions", "Classes" and "Warnings and | ||
| Exceptions" categories. (gh issue #992, pr #994). | ||
| - Updated ``parser.parse`` documentation to reflect the switch from | ||
| ``ValueError`` to ``ParserError``. (gh issue #992, pr #994). | ||
| - Fixed methods in the ``rrule`` module not being displayed in the docs. (gh pr | ||
| #1025) | ||
| - Changed some relative links in the exercise documentation to refer to the | ||
| document locations in the input tree, rather than the generated HTML files in | ||
| the HTML output tree (which presumably will not exist in non-HTML output | ||
| formats). (gh pr #1078). | ||
| Misc | ||
| ---- | ||
| - Moved ``test_imports.py``, ``test_internals.py`` and ``test_utils.py`` to | ||
| pytest. Reported and fixed by @jpurviance (gh pr #978) | ||
| - Added project_urls for documentation and source. Patch by @andriyor (gh pr | ||
| #975). | ||
| - Simplified handling of bytes and bytearray in ``_parser._timelex``. Reported | ||
| and fixed by @frenzymadness (gh issue #1060). | ||
| - Changed the tests against the upstream tz database to always generate fat | ||
| binaries, since until GH-590 and GH-1059 are resolved, "slim" zic binaries | ||
| will cause problems in many zones, causing the tests to fail. This also | ||
| updates ``zoneinfo.rebuild`` to always generate fat binaries. (gh pr #1076). | ||
| - Moved sdist and wheel generation to use `python-build`. Reported and fixed by | ||
| @mariocj89 (gh pr #1133). | ||
| Version 2.8.1 (2019-11-03) | ||
@@ -303,3 +361,3 @@ ========================== | ||
| Initial implementation by @pganssle in gh pr #489 and #622, with a | ||
| pre-release fix by @kirit93 (gh issue #546, gh pr #573). | ||
| pre-release fix by @kirit93 (gh issue #546, gh pr #573). | ||
| - Moved parser module into parser/_parser.py and officially deprecated the use | ||
@@ -338,3 +396,3 @@ of several private functions and classes from that module. (gh pr #501, #515) | ||
| - Implemented of __hash__ for relativedelta and weekday, reported and fixed | ||
| by @mrigor (gh pr #389) | ||
| by @mrigor (gh pr #389) | ||
| - Implemented __abs__ for relativedelta. Reported by @binnisb and @pferreir | ||
@@ -374,3 +432,3 @@ (gh issue #350, pr #472) | ||
| and fixed by @lapointexavier (gh pr #601) | ||
| - Added a lock to tz.tzical's cache. Reported and fixed by @Unrud (gh pr #430) | ||
| - Added a lock to tz.tzical's cache. Reported and fixed by @Unrud (gh pr #430) | ||
| - Fixed an issue with fold support on certain Python 3 implementations that | ||
@@ -377,0 +435,0 @@ used the pre-3.6 pure Python implementation of datetime.replace, most |
+177
-171
| Metadata-Version: 2.1 | ||
| Name: python-dateutil | ||
| Version: 2.8.1 | ||
| Version: 2.8.2 | ||
| Summary: Extensions to the standard Python datetime module | ||
| Home-page: https://dateutil.readthedocs.io | ||
| Home-page: https://github.com/dateutil/dateutil | ||
| Author: Gustavo Niemeyer | ||
@@ -11,171 +11,4 @@ Author-email: gustavo@niemeyer.net | ||
| License: Dual License | ||
| Description: dateutil - powerful extensions to datetime | ||
| ========================================== | ||
| |pypi| |support| |licence| | ||
| |gitter| |readthedocs| | ||
| |travis| |appveyor| |pipelines| |coverage| | ||
| .. |pypi| image:: https://img.shields.io/pypi/v/python-dateutil.svg?style=flat-square | ||
| :target: https://pypi.org/project/python-dateutil/ | ||
| :alt: pypi version | ||
| .. |support| image:: https://img.shields.io/pypi/pyversions/python-dateutil.svg?style=flat-square | ||
| :target: https://pypi.org/project/python-dateutil/ | ||
| :alt: supported Python version | ||
| .. |travis| image:: https://img.shields.io/travis/dateutil/dateutil/master.svg?style=flat-square&label=Travis%20Build | ||
| :target: https://travis-ci.org/dateutil/dateutil | ||
| :alt: travis build status | ||
| .. |appveyor| image:: https://img.shields.io/appveyor/ci/dateutil/dateutil/master.svg?style=flat-square&logo=appveyor | ||
| :target: https://ci.appveyor.com/project/dateutil/dateutil | ||
| :alt: appveyor build status | ||
| .. |pipelines| image:: https://dev.azure.com/pythondateutilazure/dateutil/_apis/build/status/dateutil.dateutil?branchName=master | ||
| :target: https://dev.azure.com/pythondateutilazure/dateutil/_build/latest?definitionId=1&branchName=master | ||
| :alt: azure pipelines build status | ||
| .. |coverage| image:: https://codecov.io/github/dateutil/dateutil/coverage.svg?branch=master | ||
| :target: https://codecov.io/github/dateutil/dateutil?branch=master | ||
| :alt: Code coverage | ||
| .. |gitter| image:: https://badges.gitter.im/dateutil/dateutil.svg | ||
| :alt: Join the chat at https://gitter.im/dateutil/dateutil | ||
| :target: https://gitter.im/dateutil/dateutil | ||
| .. |licence| image:: https://img.shields.io/pypi/l/python-dateutil.svg?style=flat-square | ||
| :target: https://pypi.org/project/python-dateutil/ | ||
| :alt: licence | ||
| .. |readthedocs| image:: https://img.shields.io/readthedocs/dateutil/latest.svg?style=flat-square&label=Read%20the%20Docs | ||
| :alt: Read the documentation at https://dateutil.readthedocs.io/en/latest/ | ||
| :target: https://dateutil.readthedocs.io/en/latest/ | ||
| The `dateutil` module provides powerful extensions to | ||
| the standard `datetime` module, available in Python. | ||
| Installation | ||
| ============ | ||
| `dateutil` can be installed from PyPI using `pip` (note that the package name is | ||
| different from the importable name):: | ||
| pip install python-dateutil | ||
| Download | ||
| ======== | ||
| dateutil is available on PyPI | ||
| https://pypi.org/project/python-dateutil/ | ||
| The documentation is hosted at: | ||
| https://dateutil.readthedocs.io/en/stable/ | ||
| Code | ||
| ==== | ||
| The code and issue tracker are hosted on GitHub: | ||
| https://github.com/dateutil/dateutil/ | ||
| Features | ||
| ======== | ||
| * Computing of relative deltas (next month, next year, | ||
| next Monday, last week of month, etc); | ||
| * Computing of relative deltas between two given | ||
| date and/or datetime objects; | ||
| * Computing of dates based on very flexible recurrence rules, | ||
| using a superset of the `iCalendar <https://www.ietf.org/rfc/rfc2445.txt>`_ | ||
| specification. Parsing of RFC strings is supported as well. | ||
| * Generic parsing of dates in almost any string format; | ||
| * Timezone (tzinfo) implementations for tzfile(5) format | ||
| files (/etc/localtime, /usr/share/zoneinfo, etc), TZ | ||
| environment string (in all known formats), iCalendar | ||
| format files, given ranges (with help from relative deltas), | ||
| local machine timezone, fixed offset timezone, UTC timezone, | ||
| and Windows registry-based time zones. | ||
| * Internal up-to-date world timezone information based on | ||
| Olson's database. | ||
| * Computing of Easter Sunday dates for any given year, | ||
| using Western, Orthodox or Julian algorithms; | ||
| * A comprehensive test suite. | ||
| Quick example | ||
| ============= | ||
| Here's a snapshot, just to give an idea about the power of the | ||
| package. For more examples, look at the documentation. | ||
| Suppose you want to know how much time is left, in | ||
| years/months/days/etc, before the next easter happening on a | ||
| year with a Friday 13th in August, and you want to get today's | ||
| date out of the "date" unix system command. Here is the code: | ||
| .. code-block:: python3 | ||
| >>> from dateutil.relativedelta import * | ||
| >>> from dateutil.easter import * | ||
| >>> from dateutil.rrule import * | ||
| >>> from dateutil.parser import * | ||
| >>> from datetime import * | ||
| >>> now = parse("Sat Oct 11 17:13:46 UTC 2003") | ||
| >>> today = now.date() | ||
| >>> year = rrule(YEARLY,dtstart=now,bymonth=8,bymonthday=13,byweekday=FR)[0].year | ||
| >>> rdelta = relativedelta(easter(year), today) | ||
| >>> print("Today is: %s" % today) | ||
| Today is: 2003-10-11 | ||
| >>> print("Year with next Aug 13th on a Friday is: %s" % year) | ||
| Year with next Aug 13th on a Friday is: 2004 | ||
| >>> print("How far is the Easter of that year: %s" % rdelta) | ||
| How far is the Easter of that year: relativedelta(months=+6) | ||
| >>> print("And the Easter of that year is: %s" % (today+rdelta)) | ||
| And the Easter of that year is: 2004-04-11 | ||
| Being exactly 6 months ahead was **really** a coincidence :) | ||
| Contributing | ||
| ============ | ||
| We welcome many types of contributions - bug reports, pull requests (code, infrastructure or documentation fixes). For more information about how to contribute to the project, see the ``CONTRIBUTING.md`` file in the repository. | ||
| Author | ||
| ====== | ||
| The dateutil module was written by Gustavo Niemeyer <gustavo@niemeyer.net> | ||
| in 2003. | ||
| It is maintained by: | ||
| * Gustavo Niemeyer <gustavo@niemeyer.net> 2003-2011 | ||
| * Tomi Pieviläinen <tomi.pievilainen@iki.fi> 2012-2014 | ||
| * Yaron de Leeuw <me@jarondl.net> 2014-2016 | ||
| * Paul Ganssle <paul@ganssle.io> 2015- | ||
| Starting with version 2.4.1, all source and binary distributions will be signed | ||
| by a PGP key that has, at the very least, been signed by the key which made the | ||
| previous release. A table of release signing keys can be found below: | ||
| =========== ============================ | ||
| Releases Signing key fingerprint | ||
| =========== ============================ | ||
| 2.4.1- `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ (|pgp_mirror|_) | ||
| =========== ============================ | ||
| Contact | ||
| ======= | ||
| Our mailing list is available at `dateutil@python.org <https://mail.python.org/mailman/listinfo/dateutil>`_. As it is hosted by the PSF, it is subject to the `PSF code of | ||
| conduct <https://www.python.org/psf/codeofconduct/>`_. | ||
| License | ||
| ======= | ||
| All contributions after December 1, 2017 released under dual license - either `Apache 2.0 License <https://www.apache.org/licenses/LICENSE-2.0>`_ or the `BSD 3-Clause License <https://opensource.org/licenses/BSD-3-Clause>`_. Contributions before December 1, 2017 - except those those explicitly relicensed - are released only under the BSD 3-Clause License. | ||
| .. _6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB: | ||
| https://pgp.mit.edu/pks/lookup?op=vindex&search=0xCD54FCE3D964BEFB | ||
| .. |pgp_mirror| replace:: mirror | ||
| .. _pgp_mirror: https://sks-keyservers.net/pks/lookup?op=vindex&search=0xCD54FCE3D964BEFB | ||
| Project-URL: Documentation, https://dateutil.readthedocs.io/en/stable/ | ||
| Project-URL: Source, https://github.com/dateutil/dateutil | ||
| Platform: UNKNOWN | ||
@@ -196,4 +29,177 @@ Classifier: Development Status :: 5 - Production/Stable | ||
| Classifier: Programming Language :: Python :: 3.8 | ||
| Classifier: Programming Language :: Python :: 3.9 | ||
| Classifier: Topic :: Software Development :: Libraries | ||
| Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,>=2.7 | ||
| Description-Content-Type: text/x-rst | ||
| License-File: LICENSE | ||
| dateutil - powerful extensions to datetime | ||
| ========================================== | ||
| |pypi| |support| |licence| | ||
| |gitter| |readthedocs| | ||
| |travis| |appveyor| |pipelines| |coverage| | ||
| .. |pypi| image:: https://img.shields.io/pypi/v/python-dateutil.svg?style=flat-square | ||
| :target: https://pypi.org/project/python-dateutil/ | ||
| :alt: pypi version | ||
| .. |support| image:: https://img.shields.io/pypi/pyversions/python-dateutil.svg?style=flat-square | ||
| :target: https://pypi.org/project/python-dateutil/ | ||
| :alt: supported Python version | ||
| .. |travis| image:: https://img.shields.io/travis/dateutil/dateutil/master.svg?style=flat-square&label=Travis%20Build | ||
| :target: https://travis-ci.org/dateutil/dateutil | ||
| :alt: travis build status | ||
| .. |appveyor| image:: https://img.shields.io/appveyor/ci/dateutil/dateutil/master.svg?style=flat-square&logo=appveyor | ||
| :target: https://ci.appveyor.com/project/dateutil/dateutil | ||
| :alt: appveyor build status | ||
| .. |pipelines| image:: https://dev.azure.com/pythondateutilazure/dateutil/_apis/build/status/dateutil.dateutil?branchName=master | ||
| :target: https://dev.azure.com/pythondateutilazure/dateutil/_build/latest?definitionId=1&branchName=master | ||
| :alt: azure pipelines build status | ||
| .. |coverage| image:: https://codecov.io/gh/dateutil/dateutil/branch/master/graphs/badge.svg?branch=master | ||
| :target: https://codecov.io/gh/dateutil/dateutil?branch=master | ||
| :alt: Code coverage | ||
| .. |gitter| image:: https://badges.gitter.im/dateutil/dateutil.svg | ||
| :alt: Join the chat at https://gitter.im/dateutil/dateutil | ||
| :target: https://gitter.im/dateutil/dateutil | ||
| .. |licence| image:: https://img.shields.io/pypi/l/python-dateutil.svg?style=flat-square | ||
| :target: https://pypi.org/project/python-dateutil/ | ||
| :alt: licence | ||
| .. |readthedocs| image:: https://img.shields.io/readthedocs/dateutil/latest.svg?style=flat-square&label=Read%20the%20Docs | ||
| :alt: Read the documentation at https://dateutil.readthedocs.io/en/latest/ | ||
| :target: https://dateutil.readthedocs.io/en/latest/ | ||
| The `dateutil` module provides powerful extensions to | ||
| the standard `datetime` module, available in Python. | ||
| Installation | ||
| ============ | ||
| `dateutil` can be installed from PyPI using `pip` (note that the package name is | ||
| different from the importable name):: | ||
| pip install python-dateutil | ||
| Download | ||
| ======== | ||
| dateutil is available on PyPI | ||
| https://pypi.org/project/python-dateutil/ | ||
| The documentation is hosted at: | ||
| https://dateutil.readthedocs.io/en/stable/ | ||
| Code | ||
| ==== | ||
| The code and issue tracker are hosted on GitHub: | ||
| https://github.com/dateutil/dateutil/ | ||
| Features | ||
| ======== | ||
| * Computing of relative deltas (next month, next year, | ||
| next Monday, last week of month, etc); | ||
| * Computing of relative deltas between two given | ||
| date and/or datetime objects; | ||
| * Computing of dates based on very flexible recurrence rules, | ||
| using a superset of the `iCalendar <https://www.ietf.org/rfc/rfc2445.txt>`_ | ||
| specification. Parsing of RFC strings is supported as well. | ||
| * Generic parsing of dates in almost any string format; | ||
| * Timezone (tzinfo) implementations for tzfile(5) format | ||
| files (/etc/localtime, /usr/share/zoneinfo, etc), TZ | ||
| environment string (in all known formats), iCalendar | ||
| format files, given ranges (with help from relative deltas), | ||
| local machine timezone, fixed offset timezone, UTC timezone, | ||
| and Windows registry-based time zones. | ||
| * Internal up-to-date world timezone information based on | ||
| Olson's database. | ||
| * Computing of Easter Sunday dates for any given year, | ||
| using Western, Orthodox or Julian algorithms; | ||
| * A comprehensive test suite. | ||
| Quick example | ||
| ============= | ||
| Here's a snapshot, just to give an idea about the power of the | ||
| package. For more examples, look at the documentation. | ||
| Suppose you want to know how much time is left, in | ||
| years/months/days/etc, before the next easter happening on a | ||
| year with a Friday 13th in August, and you want to get today's | ||
| date out of the "date" unix system command. Here is the code: | ||
| .. code-block:: python3 | ||
| >>> from dateutil.relativedelta import * | ||
| >>> from dateutil.easter import * | ||
| >>> from dateutil.rrule import * | ||
| >>> from dateutil.parser import * | ||
| >>> from datetime import * | ||
| >>> now = parse("Sat Oct 11 17:13:46 UTC 2003") | ||
| >>> today = now.date() | ||
| >>> year = rrule(YEARLY,dtstart=now,bymonth=8,bymonthday=13,byweekday=FR)[0].year | ||
| >>> rdelta = relativedelta(easter(year), today) | ||
| >>> print("Today is: %s" % today) | ||
| Today is: 2003-10-11 | ||
| >>> print("Year with next Aug 13th on a Friday is: %s" % year) | ||
| Year with next Aug 13th on a Friday is: 2004 | ||
| >>> print("How far is the Easter of that year: %s" % rdelta) | ||
| How far is the Easter of that year: relativedelta(months=+6) | ||
| >>> print("And the Easter of that year is: %s" % (today+rdelta)) | ||
| And the Easter of that year is: 2004-04-11 | ||
| Being exactly 6 months ahead was **really** a coincidence :) | ||
| Contributing | ||
| ============ | ||
| We welcome many types of contributions - bug reports, pull requests (code, infrastructure or documentation fixes). For more information about how to contribute to the project, see the ``CONTRIBUTING.md`` file in the repository. | ||
| Author | ||
| ====== | ||
| The dateutil module was written by Gustavo Niemeyer <gustavo@niemeyer.net> | ||
| in 2003. | ||
| It is maintained by: | ||
| * Gustavo Niemeyer <gustavo@niemeyer.net> 2003-2011 | ||
| * Tomi Pieviläinen <tomi.pievilainen@iki.fi> 2012-2014 | ||
| * Yaron de Leeuw <me@jarondl.net> 2014-2016 | ||
| * Paul Ganssle <paul@ganssle.io> 2015- | ||
| Starting with version 2.4.1 and running until 2.8.2, all source and binary | ||
| distributions will be signed by a PGP key that has, at the very least, been | ||
| signed by the key which made the previous release. A table of release signing | ||
| keys can be found below: | ||
| =========== ============================ | ||
| Releases Signing key fingerprint | ||
| =========== ============================ | ||
| 2.4.1-2.8.2 `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ | ||
| =========== ============================ | ||
| New releases *may* have signed tags, but binary and source distributions | ||
| uploaded to PyPI will no longer have GPG signatures attached. | ||
| Contact | ||
| ======= | ||
| Our mailing list is available at `dateutil@python.org <https://mail.python.org/mailman/listinfo/dateutil>`_. As it is hosted by the PSF, it is subject to the `PSF code of | ||
| conduct <https://www.python.org/psf/conduct/>`_. | ||
| License | ||
| ======= | ||
| All contributions after December 1, 2017 released under dual license - either `Apache 2.0 License <https://www.apache.org/licenses/LICENSE-2.0>`_ or the `BSD 3-Clause License <https://opensource.org/licenses/BSD-3-Clause>`_. Contributions before December 1, 2017 - except those those explicitly relicensed - are released only under the BSD 3-Clause License. | ||
| .. _6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB: | ||
| https://pgp.mit.edu/pks/lookup?op=vindex&search=0xCD54FCE3D964BEFB | ||
| Metadata-Version: 2.1 | ||
| Name: python-dateutil | ||
| Version: 2.8.1 | ||
| Version: 2.8.2 | ||
| Summary: Extensions to the standard Python datetime module | ||
| Home-page: https://dateutil.readthedocs.io | ||
| Home-page: https://github.com/dateutil/dateutil | ||
| Author: Gustavo Niemeyer | ||
@@ -11,171 +11,4 @@ Author-email: gustavo@niemeyer.net | ||
| License: Dual License | ||
| Description: dateutil - powerful extensions to datetime | ||
| ========================================== | ||
| |pypi| |support| |licence| | ||
| |gitter| |readthedocs| | ||
| |travis| |appveyor| |pipelines| |coverage| | ||
| .. |pypi| image:: https://img.shields.io/pypi/v/python-dateutil.svg?style=flat-square | ||
| :target: https://pypi.org/project/python-dateutil/ | ||
| :alt: pypi version | ||
| .. |support| image:: https://img.shields.io/pypi/pyversions/python-dateutil.svg?style=flat-square | ||
| :target: https://pypi.org/project/python-dateutil/ | ||
| :alt: supported Python version | ||
| .. |travis| image:: https://img.shields.io/travis/dateutil/dateutil/master.svg?style=flat-square&label=Travis%20Build | ||
| :target: https://travis-ci.org/dateutil/dateutil | ||
| :alt: travis build status | ||
| .. |appveyor| image:: https://img.shields.io/appveyor/ci/dateutil/dateutil/master.svg?style=flat-square&logo=appveyor | ||
| :target: https://ci.appveyor.com/project/dateutil/dateutil | ||
| :alt: appveyor build status | ||
| .. |pipelines| image:: https://dev.azure.com/pythondateutilazure/dateutil/_apis/build/status/dateutil.dateutil?branchName=master | ||
| :target: https://dev.azure.com/pythondateutilazure/dateutil/_build/latest?definitionId=1&branchName=master | ||
| :alt: azure pipelines build status | ||
| .. |coverage| image:: https://codecov.io/github/dateutil/dateutil/coverage.svg?branch=master | ||
| :target: https://codecov.io/github/dateutil/dateutil?branch=master | ||
| :alt: Code coverage | ||
| .. |gitter| image:: https://badges.gitter.im/dateutil/dateutil.svg | ||
| :alt: Join the chat at https://gitter.im/dateutil/dateutil | ||
| :target: https://gitter.im/dateutil/dateutil | ||
| .. |licence| image:: https://img.shields.io/pypi/l/python-dateutil.svg?style=flat-square | ||
| :target: https://pypi.org/project/python-dateutil/ | ||
| :alt: licence | ||
| .. |readthedocs| image:: https://img.shields.io/readthedocs/dateutil/latest.svg?style=flat-square&label=Read%20the%20Docs | ||
| :alt: Read the documentation at https://dateutil.readthedocs.io/en/latest/ | ||
| :target: https://dateutil.readthedocs.io/en/latest/ | ||
| The `dateutil` module provides powerful extensions to | ||
| the standard `datetime` module, available in Python. | ||
| Installation | ||
| ============ | ||
| `dateutil` can be installed from PyPI using `pip` (note that the package name is | ||
| different from the importable name):: | ||
| pip install python-dateutil | ||
| Download | ||
| ======== | ||
| dateutil is available on PyPI | ||
| https://pypi.org/project/python-dateutil/ | ||
| The documentation is hosted at: | ||
| https://dateutil.readthedocs.io/en/stable/ | ||
| Code | ||
| ==== | ||
| The code and issue tracker are hosted on GitHub: | ||
| https://github.com/dateutil/dateutil/ | ||
| Features | ||
| ======== | ||
| * Computing of relative deltas (next month, next year, | ||
| next Monday, last week of month, etc); | ||
| * Computing of relative deltas between two given | ||
| date and/or datetime objects; | ||
| * Computing of dates based on very flexible recurrence rules, | ||
| using a superset of the `iCalendar <https://www.ietf.org/rfc/rfc2445.txt>`_ | ||
| specification. Parsing of RFC strings is supported as well. | ||
| * Generic parsing of dates in almost any string format; | ||
| * Timezone (tzinfo) implementations for tzfile(5) format | ||
| files (/etc/localtime, /usr/share/zoneinfo, etc), TZ | ||
| environment string (in all known formats), iCalendar | ||
| format files, given ranges (with help from relative deltas), | ||
| local machine timezone, fixed offset timezone, UTC timezone, | ||
| and Windows registry-based time zones. | ||
| * Internal up-to-date world timezone information based on | ||
| Olson's database. | ||
| * Computing of Easter Sunday dates for any given year, | ||
| using Western, Orthodox or Julian algorithms; | ||
| * A comprehensive test suite. | ||
| Quick example | ||
| ============= | ||
| Here's a snapshot, just to give an idea about the power of the | ||
| package. For more examples, look at the documentation. | ||
| Suppose you want to know how much time is left, in | ||
| years/months/days/etc, before the next easter happening on a | ||
| year with a Friday 13th in August, and you want to get today's | ||
| date out of the "date" unix system command. Here is the code: | ||
| .. code-block:: python3 | ||
| >>> from dateutil.relativedelta import * | ||
| >>> from dateutil.easter import * | ||
| >>> from dateutil.rrule import * | ||
| >>> from dateutil.parser import * | ||
| >>> from datetime import * | ||
| >>> now = parse("Sat Oct 11 17:13:46 UTC 2003") | ||
| >>> today = now.date() | ||
| >>> year = rrule(YEARLY,dtstart=now,bymonth=8,bymonthday=13,byweekday=FR)[0].year | ||
| >>> rdelta = relativedelta(easter(year), today) | ||
| >>> print("Today is: %s" % today) | ||
| Today is: 2003-10-11 | ||
| >>> print("Year with next Aug 13th on a Friday is: %s" % year) | ||
| Year with next Aug 13th on a Friday is: 2004 | ||
| >>> print("How far is the Easter of that year: %s" % rdelta) | ||
| How far is the Easter of that year: relativedelta(months=+6) | ||
| >>> print("And the Easter of that year is: %s" % (today+rdelta)) | ||
| And the Easter of that year is: 2004-04-11 | ||
| Being exactly 6 months ahead was **really** a coincidence :) | ||
| Contributing | ||
| ============ | ||
| We welcome many types of contributions - bug reports, pull requests (code, infrastructure or documentation fixes). For more information about how to contribute to the project, see the ``CONTRIBUTING.md`` file in the repository. | ||
| Author | ||
| ====== | ||
| The dateutil module was written by Gustavo Niemeyer <gustavo@niemeyer.net> | ||
| in 2003. | ||
| It is maintained by: | ||
| * Gustavo Niemeyer <gustavo@niemeyer.net> 2003-2011 | ||
| * Tomi Pieviläinen <tomi.pievilainen@iki.fi> 2012-2014 | ||
| * Yaron de Leeuw <me@jarondl.net> 2014-2016 | ||
| * Paul Ganssle <paul@ganssle.io> 2015- | ||
| Starting with version 2.4.1, all source and binary distributions will be signed | ||
| by a PGP key that has, at the very least, been signed by the key which made the | ||
| previous release. A table of release signing keys can be found below: | ||
| =========== ============================ | ||
| Releases Signing key fingerprint | ||
| =========== ============================ | ||
| 2.4.1- `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ (|pgp_mirror|_) | ||
| =========== ============================ | ||
| Contact | ||
| ======= | ||
| Our mailing list is available at `dateutil@python.org <https://mail.python.org/mailman/listinfo/dateutil>`_. As it is hosted by the PSF, it is subject to the `PSF code of | ||
| conduct <https://www.python.org/psf/codeofconduct/>`_. | ||
| License | ||
| ======= | ||
| All contributions after December 1, 2017 released under dual license - either `Apache 2.0 License <https://www.apache.org/licenses/LICENSE-2.0>`_ or the `BSD 3-Clause License <https://opensource.org/licenses/BSD-3-Clause>`_. Contributions before December 1, 2017 - except those those explicitly relicensed - are released only under the BSD 3-Clause License. | ||
| .. _6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB: | ||
| https://pgp.mit.edu/pks/lookup?op=vindex&search=0xCD54FCE3D964BEFB | ||
| .. |pgp_mirror| replace:: mirror | ||
| .. _pgp_mirror: https://sks-keyservers.net/pks/lookup?op=vindex&search=0xCD54FCE3D964BEFB | ||
| Project-URL: Documentation, https://dateutil.readthedocs.io/en/stable/ | ||
| Project-URL: Source, https://github.com/dateutil/dateutil | ||
| Platform: UNKNOWN | ||
@@ -196,4 +29,177 @@ Classifier: Development Status :: 5 - Production/Stable | ||
| Classifier: Programming Language :: Python :: 3.8 | ||
| Classifier: Programming Language :: Python :: 3.9 | ||
| Classifier: Topic :: Software Development :: Libraries | ||
| Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,>=2.7 | ||
| Description-Content-Type: text/x-rst | ||
| License-File: LICENSE | ||
| dateutil - powerful extensions to datetime | ||
| ========================================== | ||
| |pypi| |support| |licence| | ||
| |gitter| |readthedocs| | ||
| |travis| |appveyor| |pipelines| |coverage| | ||
| .. |pypi| image:: https://img.shields.io/pypi/v/python-dateutil.svg?style=flat-square | ||
| :target: https://pypi.org/project/python-dateutil/ | ||
| :alt: pypi version | ||
| .. |support| image:: https://img.shields.io/pypi/pyversions/python-dateutil.svg?style=flat-square | ||
| :target: https://pypi.org/project/python-dateutil/ | ||
| :alt: supported Python version | ||
| .. |travis| image:: https://img.shields.io/travis/dateutil/dateutil/master.svg?style=flat-square&label=Travis%20Build | ||
| :target: https://travis-ci.org/dateutil/dateutil | ||
| :alt: travis build status | ||
| .. |appveyor| image:: https://img.shields.io/appveyor/ci/dateutil/dateutil/master.svg?style=flat-square&logo=appveyor | ||
| :target: https://ci.appveyor.com/project/dateutil/dateutil | ||
| :alt: appveyor build status | ||
| .. |pipelines| image:: https://dev.azure.com/pythondateutilazure/dateutil/_apis/build/status/dateutil.dateutil?branchName=master | ||
| :target: https://dev.azure.com/pythondateutilazure/dateutil/_build/latest?definitionId=1&branchName=master | ||
| :alt: azure pipelines build status | ||
| .. |coverage| image:: https://codecov.io/gh/dateutil/dateutil/branch/master/graphs/badge.svg?branch=master | ||
| :target: https://codecov.io/gh/dateutil/dateutil?branch=master | ||
| :alt: Code coverage | ||
| .. |gitter| image:: https://badges.gitter.im/dateutil/dateutil.svg | ||
| :alt: Join the chat at https://gitter.im/dateutil/dateutil | ||
| :target: https://gitter.im/dateutil/dateutil | ||
| .. |licence| image:: https://img.shields.io/pypi/l/python-dateutil.svg?style=flat-square | ||
| :target: https://pypi.org/project/python-dateutil/ | ||
| :alt: licence | ||
| .. |readthedocs| image:: https://img.shields.io/readthedocs/dateutil/latest.svg?style=flat-square&label=Read%20the%20Docs | ||
| :alt: Read the documentation at https://dateutil.readthedocs.io/en/latest/ | ||
| :target: https://dateutil.readthedocs.io/en/latest/ | ||
| The `dateutil` module provides powerful extensions to | ||
| the standard `datetime` module, available in Python. | ||
| Installation | ||
| ============ | ||
| `dateutil` can be installed from PyPI using `pip` (note that the package name is | ||
| different from the importable name):: | ||
| pip install python-dateutil | ||
| Download | ||
| ======== | ||
| dateutil is available on PyPI | ||
| https://pypi.org/project/python-dateutil/ | ||
| The documentation is hosted at: | ||
| https://dateutil.readthedocs.io/en/stable/ | ||
| Code | ||
| ==== | ||
| The code and issue tracker are hosted on GitHub: | ||
| https://github.com/dateutil/dateutil/ | ||
| Features | ||
| ======== | ||
| * Computing of relative deltas (next month, next year, | ||
| next Monday, last week of month, etc); | ||
| * Computing of relative deltas between two given | ||
| date and/or datetime objects; | ||
| * Computing of dates based on very flexible recurrence rules, | ||
| using a superset of the `iCalendar <https://www.ietf.org/rfc/rfc2445.txt>`_ | ||
| specification. Parsing of RFC strings is supported as well. | ||
| * Generic parsing of dates in almost any string format; | ||
| * Timezone (tzinfo) implementations for tzfile(5) format | ||
| files (/etc/localtime, /usr/share/zoneinfo, etc), TZ | ||
| environment string (in all known formats), iCalendar | ||
| format files, given ranges (with help from relative deltas), | ||
| local machine timezone, fixed offset timezone, UTC timezone, | ||
| and Windows registry-based time zones. | ||
| * Internal up-to-date world timezone information based on | ||
| Olson's database. | ||
| * Computing of Easter Sunday dates for any given year, | ||
| using Western, Orthodox or Julian algorithms; | ||
| * A comprehensive test suite. | ||
| Quick example | ||
| ============= | ||
| Here's a snapshot, just to give an idea about the power of the | ||
| package. For more examples, look at the documentation. | ||
| Suppose you want to know how much time is left, in | ||
| years/months/days/etc, before the next easter happening on a | ||
| year with a Friday 13th in August, and you want to get today's | ||
| date out of the "date" unix system command. Here is the code: | ||
| .. code-block:: python3 | ||
| >>> from dateutil.relativedelta import * | ||
| >>> from dateutil.easter import * | ||
| >>> from dateutil.rrule import * | ||
| >>> from dateutil.parser import * | ||
| >>> from datetime import * | ||
| >>> now = parse("Sat Oct 11 17:13:46 UTC 2003") | ||
| >>> today = now.date() | ||
| >>> year = rrule(YEARLY,dtstart=now,bymonth=8,bymonthday=13,byweekday=FR)[0].year | ||
| >>> rdelta = relativedelta(easter(year), today) | ||
| >>> print("Today is: %s" % today) | ||
| Today is: 2003-10-11 | ||
| >>> print("Year with next Aug 13th on a Friday is: %s" % year) | ||
| Year with next Aug 13th on a Friday is: 2004 | ||
| >>> print("How far is the Easter of that year: %s" % rdelta) | ||
| How far is the Easter of that year: relativedelta(months=+6) | ||
| >>> print("And the Easter of that year is: %s" % (today+rdelta)) | ||
| And the Easter of that year is: 2004-04-11 | ||
| Being exactly 6 months ahead was **really** a coincidence :) | ||
| Contributing | ||
| ============ | ||
| We welcome many types of contributions - bug reports, pull requests (code, infrastructure or documentation fixes). For more information about how to contribute to the project, see the ``CONTRIBUTING.md`` file in the repository. | ||
| Author | ||
| ====== | ||
| The dateutil module was written by Gustavo Niemeyer <gustavo@niemeyer.net> | ||
| in 2003. | ||
| It is maintained by: | ||
| * Gustavo Niemeyer <gustavo@niemeyer.net> 2003-2011 | ||
| * Tomi Pieviläinen <tomi.pievilainen@iki.fi> 2012-2014 | ||
| * Yaron de Leeuw <me@jarondl.net> 2014-2016 | ||
| * Paul Ganssle <paul@ganssle.io> 2015- | ||
| Starting with version 2.4.1 and running until 2.8.2, all source and binary | ||
| distributions will be signed by a PGP key that has, at the very least, been | ||
| signed by the key which made the previous release. A table of release signing | ||
| keys can be found below: | ||
| =========== ============================ | ||
| Releases Signing key fingerprint | ||
| =========== ============================ | ||
| 2.4.1-2.8.2 `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ | ||
| =========== ============================ | ||
| New releases *may* have signed tags, but binary and source distributions | ||
| uploaded to PyPI will no longer have GPG signatures attached. | ||
| Contact | ||
| ======= | ||
| Our mailing list is available at `dateutil@python.org <https://mail.python.org/mailman/listinfo/dateutil>`_. As it is hosted by the PSF, it is subject to the `PSF code of | ||
| conduct <https://www.python.org/psf/conduct/>`_. | ||
| License | ||
| ======= | ||
| All contributions after December 1, 2017 released under dual license - either `Apache 2.0 License <https://www.apache.org/licenses/LICENSE-2.0>`_ or the `BSD 3-Clause License <https://opensource.org/licenses/BSD-3-Clause>`_. Contributions before December 1, 2017 - except those those explicitly relicensed - are released only under the BSD 3-Clause License. | ||
| .. _6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB: | ||
| https://pgp.mit.edu/pks/lookup?op=vindex&search=0xCD54FCE3D964BEFB | ||
@@ -15,3 +15,2 @@ .gitattributes | ||
| pyproject.toml | ||
| release.py | ||
| requirements-dev.txt | ||
@@ -24,2 +23,4 @@ setup.cfg | ||
| .github/pull_request_template.md | ||
| .github/workflows/publish.yml | ||
| .github/workflows/validate.yml | ||
| changelog.d/.gitignore | ||
@@ -57,2 +58,3 @@ changelog.d/template.rst | ||
| dateutil/test/property/test_parser_prop.py | ||
| dateutil/test/property/test_tz_prop.py | ||
| dateutil/tz/__init__.py | ||
@@ -59,0 +61,0 @@ dateutil/tz/_common.py |
+10
-10
@@ -30,4 +30,4 @@ dateutil - powerful extensions to datetime | ||
| .. |coverage| image:: https://codecov.io/github/dateutil/dateutil/coverage.svg?branch=master | ||
| :target: https://codecov.io/github/dateutil/dateutil?branch=master | ||
| .. |coverage| image:: https://codecov.io/gh/dateutil/dateutil/branch/master/graphs/badge.svg?branch=master | ||
| :target: https://codecov.io/gh/dateutil/dateutil?branch=master | ||
| :alt: Code coverage | ||
@@ -143,5 +143,6 @@ | ||
| Starting with version 2.4.1, all source and binary distributions will be signed | ||
| by a PGP key that has, at the very least, been signed by the key which made the | ||
| previous release. A table of release signing keys can be found below: | ||
| Starting with version 2.4.1 and running until 2.8.2, all source and binary | ||
| distributions will be signed by a PGP key that has, at the very least, been | ||
| signed by the key which made the previous release. A table of release signing | ||
| keys can be found below: | ||
@@ -151,5 +152,7 @@ =========== ============================ | ||
| =========== ============================ | ||
| 2.4.1- `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ (|pgp_mirror|_) | ||
| 2.4.1-2.8.2 `6B49 ACBA DCF6 BD1C A206 67AB CD54 FCE3 D964 BEFB`_ | ||
| =========== ============================ | ||
| New releases *may* have signed tags, but binary and source distributions | ||
| uploaded to PyPI will no longer have GPG signatures attached. | ||
@@ -159,3 +162,3 @@ Contact | ||
| Our mailing list is available at `dateutil@python.org <https://mail.python.org/mailman/listinfo/dateutil>`_. As it is hosted by the PSF, it is subject to the `PSF code of | ||
| conduct <https://www.python.org/psf/codeofconduct/>`_. | ||
| conduct <https://www.python.org/psf/conduct/>`_. | ||
@@ -170,4 +173,1 @@ License | ||
| https://pgp.mit.edu/pks/lookup?op=vindex&search=0xCD54FCE3D964BEFB | ||
| .. |pgp_mirror| replace:: mirror | ||
| .. _pgp_mirror: https://sks-keyservers.net/pks/lookup?op=vindex&search=0xCD54FCE3D964BEFB |
@@ -8,2 +8,3 @@ six | ||
| mock ; python_version < '3.0' | ||
| pep517 >= 0.5.0 | ||
| build >= 0.3.0 ; python_version >= '3.6' | ||
| attrs!=21.1.0 |
+5
-1
@@ -11,3 +11,6 @@ [bdist_wheel] | ||
| maintainer_email = dateutil@python.org | ||
| url = https://dateutil.readthedocs.io | ||
| url = https://github.com/dateutil/dateutil | ||
| project_urls = | ||
| Documentation = https://dateutil.readthedocs.io/en/stable/ | ||
| Source = https://github.com/dateutil/dateutil | ||
| long_description_content_type = text/x-rst | ||
@@ -31,2 +34,3 @@ license = Dual License | ||
| Programming Language :: Python :: 3.8 | ||
| Programming Language :: Python :: 3.9 | ||
| Topic :: Software Development :: Libraries | ||
@@ -33,0 +37,0 @@ |
+27
-19
@@ -14,3 +14,9 @@ [tox] | ||
| skip_missing_interpreters = true | ||
| isolated_build = true | ||
| [testenv:.package] | ||
| # no additional dependencies besides PEP 517 for building the package | ||
| # Needed as we are running with an old version of tox. | ||
| deps = | ||
| [testenv] | ||
@@ -20,3 +26,3 @@ description = run the unit tests with pytest under {basepython} | ||
| passenv = DATEUTIL_MAY_CHANGE_TZ TOXENV CI TRAVIS TRAVIS_* APPVEYOR APPVEYOR_* CODECOV_* SYSTEM_* AGENT_* BUILD_* TF_BUILD | ||
| commands = python -m pytest {posargs: "{toxinidir}/dateutil/test" --cov-config="{toxinidir}/tox.ini" --cov=dateutil} | ||
| commands = python -m pytest {posargs: "{toxinidir}/dateutil/test" "{toxinidir}/docs" --cov-config="{toxinidir}/tox.ini" --cov=dateutil} | ||
| deps = -rrequirements-dev.txt | ||
@@ -28,3 +34,3 @@ | ||
| passenv = DATEUTIL_MAY_CHANGE_TZ TOXENV CI TRAVIS TRAVIS_* APPVEYOR APPVEYOR_* CODECOV_* SYSTEM_* AGENT_* BUILD_* TF_BUILD | ||
| commands = python -m pytest {posargs: "{toxinidir}/dateutil/test" --cov-config="{toxinidir}/tox.ini" --cov=dateutil} | ||
| commands = python -m pytest {posargs: "{toxinidir}/dateutil/test" "{toxinidir}/docs" --cov-config="{toxinidir}/tox.ini" --cov=dateutil} | ||
| deps = | ||
@@ -40,6 +46,6 @@ -rrequirements/3.3/requirements-dev.txt | ||
| setenv = COVERAGE_FILE=.coverage | ||
| commands = coverage erase | ||
| coverage combine | ||
| coverage report --rcfile={toxinidir}/tox.ini | ||
| coverage xml | ||
| commands = python -m coverage erase | ||
| python -m coverage combine | ||
| python -m coverage report --rcfile={toxinidir}/tox.ini | ||
| python -m coverage xml | ||
@@ -50,3 +56,3 @@ [testenv:codecov] | ||
| skip_install = True | ||
| commands = codecov --file {toxworkdir}/coverage.xml | ||
| commands = python -m codecov --file {toxworkdir}/coverage.xml | ||
@@ -97,19 +103,21 @@ [testenv:dev] | ||
| description = Build an sdist and bdist | ||
| basepython = python3.7 | ||
| basepython = python3.9 | ||
| skip_install = true | ||
| passenv = * | ||
| deps = click >= 7.0 | ||
| pep517 >= 0.5.0 | ||
| deps = build[virtualenv] >= 0.3.0 | ||
| commands = | ||
| python release.py build | ||
| python -m build --wheel --sdist --outdir dist . | ||
| [testenv:release] | ||
| description = Sign and upload the built distributions to PyPI | ||
| basepython = python3.7 | ||
| skip_install = true | ||
| passenv = * | ||
| deps = click >= 7.0 | ||
| twine >= 2.0.0 | ||
| description = Make a release; must be called after "build" | ||
| skip_install = True | ||
| deps = | ||
| twine | ||
| depends = | ||
| build | ||
| passenv = | ||
| TWINE_* | ||
| commands = | ||
| python release.py sign | ||
| python release.py upload {posargs} | ||
| twine check {toxinidir}/dist/* | ||
| twine upload {toxinidir}/dist/* \ | ||
| {posargs:-r {env:TWINE_REPOSITORY:testpypi} --non-interactive} |
@@ -7,5 +7,5 @@ { | ||
| ], | ||
| "tzdata_file": "tzdata2019c.tar.gz", | ||
| "tzdata_file_sha512": "2921cbb2fd44a6b8f7f2ed42c13fbae28195aa5c2eeefa70396bc97cdbaad679c6cc3c143da82cca5b0279065c02389e9af536904288c12886bf345baa8c6565", | ||
| "tzversion": "2019c", | ||
| "tzdata_file": "tzdata2021a.tar.gz", | ||
| "tzdata_file_sha512": "7cdd762ec90ce12a30fa36b1d66d1ea82d9fa21e514e2b9c7fcbe2541514ee0fadf30843ff352c65512fb270857b51d1517b45e1232b89c6f954ba9ff1833bb3", | ||
| "tzversion": "2021a", | ||
| "zonegroups": [ | ||
@@ -19,5 +19,3 @@ "africa", | ||
| "southamerica", | ||
| "pacificnew", | ||
| "etcetera", | ||
| "systemv", | ||
| "factory", | ||
@@ -27,2 +25,2 @@ "backzone", | ||
| ] | ||
| } | ||
| } |
-79
| """ | ||
| Release script | ||
| """ | ||
| import glob | ||
| import os | ||
| import shutil | ||
| import subprocess | ||
| import sys | ||
| import click | ||
| @click.group() | ||
| def cli(): | ||
| pass | ||
| @cli.command() | ||
| def build(): | ||
| DIST_PATH = 'dist' | ||
| if os.path.exists(DIST_PATH) and os.listdir(DIST_PATH): | ||
| if click.confirm('{} is not empty - delete contents?'.format(DIST_PATH)): | ||
| shutil.rmtree(DIST_PATH) | ||
| os.makedirs(DIST_PATH) | ||
| else: | ||
| click.echo('Aborting') | ||
| sys.exit(1) | ||
| subprocess.check_call(['python', '-m', 'pep517.build', | ||
| '--binary', '--source', '.']) | ||
| @cli.command() | ||
| def sign(): | ||
| # Sign all the distribution files | ||
| for fpath in glob.glob('dist/*'): | ||
| subprocess.check_call(['gpg', '--armor', '--output', fpath + '.asc', | ||
| '--detach-sig', fpath]) | ||
| # Verify the distribution files | ||
| for fpath in glob.glob('dist/*'): | ||
| if fpath.endswith('.asc'): | ||
| continue | ||
| subprocess.check_call(['gpg', '--verify', fpath + '.asc', fpath]) | ||
| @cli.command() | ||
| @click.option('--passfile', default=None, | ||
| help='File path to read and decrypt with gpg.') | ||
| @click.option('--release/--no-release', default=False) | ||
| def upload(passfile, release): | ||
| if release: | ||
| repository='pypi' | ||
| else: | ||
| repository='pypitest' | ||
| env = os.environ.copy() | ||
| if passfile is not None: | ||
| gpg_call = subprocess.run(['gpg', '-d', passfile], | ||
| stdout=subprocess.PIPE, | ||
| stderr=subprocess.PIPE) | ||
| username, password = gpg_call.stdout.decode('utf-8').split('\n') | ||
| env['TWINE_USERNAME'] = username | ||
| env['TWINE_PASSWORD'] = password | ||
| dist_files = glob.glob('dist/*') | ||
| for dist_file in dist_files: | ||
| if dist_file.endswith('.asc'): | ||
| continue | ||
| if dist_file + '.asc' not in dist_files: | ||
| raise ValueError('Missing signature file for: {}'.format(dist_file)) | ||
| args = ['twine', 'upload', '-r', repository] + dist_files | ||
| p = subprocess.Popen(args, env=env) | ||
| p.wait() | ||
| if __name__ == "__main__": | ||
| cli() |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
1086958
2.66%92
2.22%15406
-0.01%