Hello community, here is the log from the commit of package python-arrow for openSUSE:Factory checked in at 2020-10-25 18:08:50 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-arrow (Old) and /work/SRC/openSUSE:Factory/.python-arrow.new.3463 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-arrow" Sun Oct 25 18:08:50 2020 rev:17 rq:835653 version:0.16.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-arrow/python-arrow.changes 2020-08-01 12:30:52.306439607 +0200 +++ /work/SRC/openSUSE:Factory/.python-arrow.new.3463/python-arrow.changes 2020-10-25 18:08:58.383478899 +0100 @@ -1,0 +2,13 @@ +Sat Sep 19 15:29:03 UTC 2020 - Arun Persaud <a...@gmx.de> + +- update to version 0.16.0: + * [WARN] Arrow will drop support for Python 2.7 and 3.5 in the 1.0.0 + release in late September. The 0.16.x and 0.17.x releases are the + last to support Python 2.7 and 3.5. + * [NEW] Implemented PEP 495 to handle ambiguous datetimes. This is + achieved by the addition of the fold attribute for Arrow objects. + * [NEW] Added normalize_whitespace flag to arrow.get. This is useful + for parsing log files and/or any files that may contain + inconsistent spacing. + +------------------------------------------------------------------- Old: ---- arrow-0.15.8.tar.gz New: ---- arrow-0.16.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-arrow.spec ++++++ --- /var/tmp/diff_new_pack.J8zxno/_old 2020-10-25 18:09:00.771481159 +0100 +++ /var/tmp/diff_new_pack.J8zxno/_new 2020-10-25 18:09:00.775481163 +0100 @@ -26,7 +26,7 @@ %endif %bcond_without python2 Name: python-arrow%{?psuffix} -Version: 0.15.8 +Version: 0.16.0 Release: 0 Summary: Better dates and times for Python License: Apache-2.0 @@ -35,13 +35,13 @@ BuildRequires: %{python_module setuptools} BuildRequires: fdupes BuildRequires: python-rpm-macros -Requires: python-python-dateutil +Requires: python-python-dateutil >= 2.7.0 BuildArch: noarch %if %{with test} BuildRequires: %{python_module arrow == %{version}} BuildRequires: %{python_module chai} BuildRequires: %{python_module dateparser} -BuildRequires: %{python_module dateutil} +BuildRequires: %{python_module dateutil >= 2.7.0} BuildRequires: %{python_module mock} BuildRequires: %{python_module pytest-mock} BuildRequires: %{python_module pytest} ++++++ arrow-0.15.8.tar.gz -> arrow-0.16.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/CHANGELOG.rst new/arrow-0.16.0/CHANGELOG.rst --- old/arrow-0.15.8/CHANGELOG.rst 2020-07-24 04:50:10.000000000 +0200 +++ new/arrow-0.16.0/CHANGELOG.rst 2020-08-23 23:33:36.000000000 +0200 @@ -1,10 +1,38 @@ Changelog ========= +0.16.0 (2020-08-23) +------------------- + +- [WARN] Arrow will **drop support** for Python 2.7 and 3.5 in the 1.0.0 release in late September. The 0.16.x and 0.17.x releases are the last to support Python 2.7 and 3.5. +- [NEW] Implemented `PEP 495 <https://www.python.org/dev/peps/pep-0495/>`_ to handle ambiguous datetimes. This is achieved by the addition of the ``fold`` attribute for Arrow objects. For example: + +.. code-block:: python + + >>> before = Arrow(2017, 10, 29, 2, 0, tzinfo='Europe/Stockholm') + <Arrow [2017-10-29T02:00:00+02:00]> + >>> before.fold + 0 + >>> before.ambiguous + True + >>> after = Arrow(2017, 10, 29, 2, 0, tzinfo='Europe/Stockholm', fold=1) + <Arrow [2017-10-29T02:00:00+01:00]> + >>> after = before.replace(fold=1) + <Arrow [2017-10-29T02:00:00+01:00]> + +- [NEW] Added ``normalize_whitespace`` flag to ``arrow.get``. This is useful for parsing log files and/or any files that may contain inconsistent spacing. For example: + +.. code-block:: python + + >>> arrow.get("Jun 1 2005 1:33PM", "MMM D YYYY H:mmA", normalize_whitespace=True) + <Arrow [2005-06-01T13:33:00+00:00]> + >>> arrow.get("2013-036 \t 04:05:06Z", normalize_whitespace=True) + <Arrow [2013-02-05T04:05:06+00:00]> + 0.15.8 (2020-07-23) ------------------- -- [WARN] arrow will **drop support** for Python 2.7 and 3.5 in the 1.0.0 release in late September. The 0.15.x and 0.16.x releases are the last to support Python 2.7 and 3.5. +- [WARN] Arrow will **drop support** for Python 2.7 and 3.5 in the 1.0.0 release in late September. The 0.15.x, 0.16.x, and 0.17.x releases are the last to support Python 2.7 and 3.5. - [NEW] Added ``humanize`` week granularity translation for Czech. - [FIX] ``arrow.get`` will now pick sane defaults when weekdays are passed with particular token combinations, see `#446 <https://github.com/arrow-py/arrow/issues/446>`_. - [INTERNAL] Moved arrow to an organization. The repo can now be found `here <https://github.com/arrow-py/arrow>`_. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/PKG-INFO new/arrow-0.16.0/PKG-INFO --- old/arrow-0.15.8/PKG-INFO 2020-07-24 04:55:26.461238000 +0200 +++ new/arrow-0.16.0/PKG-INFO 2020-08-23 23:37:20.100347000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: arrow -Version: 0.15.8 +Version: 0.16.0 Summary: Better dates & times for Python Home-page: https://arrow.readthedocs.io Author: Chris Smith diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/arrow/_version.py new/arrow-0.16.0/arrow/_version.py --- old/arrow-0.15.8/arrow/_version.py 2020-07-24 04:50:10.000000000 +0200 +++ new/arrow-0.16.0/arrow/_version.py 2020-08-23 23:33:36.000000000 +0200 @@ -1 +1 @@ -__version__ = "0.15.8" +__version__ = "0.16.0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/arrow/arrow.py new/arrow-0.16.0/arrow/arrow.py --- old/arrow-0.15.8/arrow/arrow.py 2020-07-24 04:50:10.000000000 +0200 +++ new/arrow-0.16.0/arrow/arrow.py 2020-08-23 23:32:16.000000000 +0200 @@ -41,8 +41,9 @@ :param hour: (optional) the hour. Defaults to 0. :param minute: (optional) the minute, Defaults to 0. :param second: (optional) the second, Defaults to 0. - :param microsecond: (optional) the microsecond. Defaults 0. + :param microsecond: (optional) the microsecond. Defaults to 0. :param tzinfo: (optional) A timezone expression. Defaults to UTC. + :param fold: (optional) 0 or 1, used to disambiguate repeated times. Defaults to 0. .. _tz-expr: @@ -74,7 +75,16 @@ _SECS_PER_YEAR = float(60 * 60 * 24 * 365.25) def __init__( - self, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None + self, + year, + month, + day, + hour=0, + minute=0, + second=0, + microsecond=0, + tzinfo=None, + **kwargs ): if tzinfo is None: tzinfo = dateutil_tz.tzutc() @@ -89,8 +99,12 @@ elif util.isstr(tzinfo): tzinfo = parser.TzinfoParser.parse(tzinfo) - self._datetime = datetime( - year, month, day, hour, minute, second, microsecond, tzinfo + fold = kwargs.get("fold", 0) + + # use enfold here to cover direct arrow.Arrow init on 2.7/3.5 + self._datetime = dateutil_tz.enfold( + datetime(year, month, day, hour, minute, second, microsecond, tzinfo), + fold=fold, ) # factories: single object, both original and from datetime. @@ -111,6 +125,7 @@ if tzinfo is None: tzinfo = dateutil_tz.tzlocal() + dt = datetime.now(tzinfo) return cls( @@ -122,6 +137,7 @@ dt.second, dt.microsecond, dt.tzinfo, + fold=getattr(dt, "fold", 0), ) @classmethod @@ -147,6 +163,7 @@ dt.second, dt.microsecond, dt.tzinfo, + fold=getattr(dt, "fold", 0), ) @classmethod @@ -180,6 +197,7 @@ dt.second, dt.microsecond, dt.tzinfo, + fold=getattr(dt, "fold", 0), ) @classmethod @@ -207,6 +225,7 @@ dt.second, dt.microsecond, dateutil_tz.tzutc(), + fold=getattr(dt, "fold", 0), ) @classmethod @@ -242,6 +261,7 @@ dt.second, dt.microsecond, tzinfo, + fold=getattr(dt, "fold", 0), ) @classmethod @@ -288,6 +308,7 @@ dt.second, dt.microsecond, tzinfo, + fold=getattr(dt, "fold", 0), ) # factories: ranges and spans @@ -587,6 +608,20 @@ return self.timestamp + float(self.microsecond) / 1000000 + @property + def fold(self): + """ Returns the ``fold`` value of the :class:`Arrow <arrow.arrow.Arrow>` object. """ + + # in python < 3.6 _datetime will be a _DatetimeWithFold if fold=1 and a datetime with no fold attribute + # otherwise, so we need to return zero to cover the latter case + return getattr(self._datetime, "fold", 0) + + @property + def ambiguous(self): + """ Returns a boolean indicating whether the :class:`Arrow <arrow.arrow.Arrow>` object is ambiguous""" + + return dateutil_tz.datetime_ambiguous(self._datetime) + # mutation and duplication. def clone(self): @@ -630,7 +665,7 @@ absolute_kwargs[key] = value elif key in ["week", "quarter"]: raise AttributeError("setting absolute {} is not supported".format(key)) - elif key != "tzinfo": + elif key not in ["tzinfo", "fold"]: raise AttributeError('unknown attribute: "{}"'.format(key)) current = self._datetime.replace(**absolute_kwargs) @@ -641,6 +676,12 @@ tzinfo = self._get_tzinfo(tzinfo) current = current.replace(tzinfo=tzinfo) + fold = kwargs.get("fold") + + # TODO revisit this once we drop support for 2.7/3.5 + if fold is not None: + current = dateutil_tz.enfold(current, fold=fold) + return self.fromdatetime(current) def shift(self, **kwargs): @@ -740,6 +781,7 @@ dt.second, dt.microsecond, dt.tzinfo, + fold=getattr(dt, "fold", 0), ) @classmethod diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/arrow/factory.py new/arrow-0.16.0/arrow/factory.py --- old/arrow-0.15.8/arrow/factory.py 2020-07-20 06:56:36.000000000 +0200 +++ new/arrow-0.16.0/arrow/factory.py 2020-08-17 17:16:52.000000000 +0200 @@ -34,11 +34,13 @@ def get(self, *args, **kwargs): """ Returns an :class:`Arrow <arrow.arrow.Arrow>` object based on flexible inputs. - :param locale: (optional) a ``str`` specifying a locale for the parser. Defaults to - 'en_us'. + :param locale: (optional) a ``str`` specifying a locale for the parser. Defaults to 'en_us'. :param tzinfo: (optional) a :ref:`timezone expression <tz-expr>` or tzinfo object. Replaces the timezone unless using an input form that is explicitly UTC or specifies the timezone in a positional argument. Defaults to UTC. + :param normalize_whitespace: (optional) a ``bool`` specifying whether or not to normalize + redundant whitespace (spaces, tabs, and newlines) in a datetime string before parsing. + Defaults to false. Usage:: @@ -141,6 +143,7 @@ arg_count = len(args) locale = kwargs.pop("locale", "en_us") tz = kwargs.get("tzinfo", None) + normalize_whitespace = kwargs.pop("normalize_whitespace", False) # if kwargs given, send to constructor unless only tzinfo provided if len(kwargs) > 1: @@ -193,7 +196,7 @@ # (str) -> parse. elif isstr(arg): - dt = parser.DateTimeParser(locale).parse_iso(arg) + dt = parser.DateTimeParser(locale).parse_iso(arg, normalize_whitespace) return self.type.fromdatetime(dt, tz) # (struct_time) -> from struct_time @@ -240,7 +243,9 @@ # (str, format) -> parse. elif isstr(arg_1) and (isstr(arg_2) or isinstance(arg_2, list)): - dt = parser.DateTimeParser(locale).parse(args[0], args[1]) + dt = parser.DateTimeParser(locale).parse( + args[0], args[1], normalize_whitespace + ) return self.type.fromdatetime(dt, tzinfo=tz) else: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/arrow/parser.py new/arrow-0.16.0/arrow/parser.py --- old/arrow-0.15.8/arrow/parser.py 2020-07-20 06:56:36.000000000 +0200 +++ new/arrow-0.16.0/arrow/parser.py 2020-08-17 17:16:52.000000000 +0200 @@ -114,8 +114,11 @@ # TODO: since we support more than ISO 8601, we should rename this function # IDEA: break into multiple functions - def parse_iso(self, datetime_string): - # TODO: add a flag to normalize whitespace (useful in logs, ref issue #421) + def parse_iso(self, datetime_string, normalize_whitespace=False): + + if normalize_whitespace: + datetime_string = re.sub(r"\s+", " ", datetime_string.strip()) + has_space_divider = " " in datetime_string has_t_divider = "T" in datetime_string @@ -213,7 +216,10 @@ return self._parse_multiformat(datetime_string, formats) - def parse(self, datetime_string, fmt): + def parse(self, datetime_string, fmt, normalize_whitespace=False): + + if normalize_whitespace: + datetime_string = re.sub(r"\s+", " ", datetime_string) if isinstance(fmt, list): return self._parse_multiformat(datetime_string, fmt) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/arrow.egg-info/PKG-INFO new/arrow-0.16.0/arrow.egg-info/PKG-INFO --- old/arrow-0.15.8/arrow.egg-info/PKG-INFO 2020-07-24 04:55:26.000000000 +0200 +++ new/arrow-0.16.0/arrow.egg-info/PKG-INFO 2020-08-23 23:37:19.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: arrow -Version: 0.15.8 +Version: 0.16.0 Summary: Better dates & times for Python Home-page: https://arrow.readthedocs.io Author: Chris Smith diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/arrow.egg-info/requires.txt new/arrow-0.16.0/arrow.egg-info/requires.txt --- old/arrow-0.15.8/arrow.egg-info/requires.txt 2020-07-24 04:55:26.000000000 +0200 +++ new/arrow-0.16.0/arrow.egg-info/requires.txt 2020-08-23 23:37:19.000000000 +0200 @@ -1,4 +1,4 @@ -python-dateutil +python-dateutil>=2.7.0 [:python_version == "2.7"] backports.functools_lru_cache>=1.2.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/docs/index.rst new/arrow-0.16.0/docs/index.rst --- old/arrow-0.15.8/docs/index.rst 2020-07-20 06:56:36.000000000 +0200 +++ new/arrow-0.16.0/docs/index.rst 2020-08-21 23:14:48.000000000 +0200 @@ -151,6 +151,17 @@ >>> arw.replace(tzinfo='US/Pacific') <Arrow [2013-05-12T03:29:35.334214-07:00]> +Move between the earlier and later moments of an ambiguous time: + +.. code-block:: python + + >>> paris_transition = arrow.Arrow(2019, 10, 27, 2, tzinfo="Europe/Paris", fold=0) + >>> paris_transition + <Arrow [2019-10-27T02:00:00+02:00]> + >>> paris_transition.ambiguous + True + >>> paris_transition.replace(fold=1) + <Arrow [2019-10-27T02:00:00+01:00]> Format ~~~~~~ @@ -405,7 +416,7 @@ .. [#t1] localization support for parsing and formatting .. [#t2] localization support only for formatting .. [#t3] the result is truncated to microseconds, with `half-to-even rounding <https://en.wikipedia.org/wiki/IEEE_floating_point#Roundings_to_nearest>`_. -.. [#t4] timezone names from `tz database <https://www.iana.org/time-zones>`_ provided via dateutil package +.. [#t4] timezone names from `tz database <https://www.iana.org/time-zones>`_ provided via dateutil package, note that abbreviations such as MST, PDT, BRST are unlikely to parse due to ambiguity. Use the full IANA zone name instead (Asia/Shanghai, Europe/London, America/Chicago etc). .. [#t5] this token cannot be used for parsing timestamps out of natural language strings due to compatibility reasons Built-in Formats @@ -489,10 +500,13 @@ Punctuation ~~~~~~~~~~~ -Date formats may be fenced on either side by one punctuation character from the following list: :literal:`, . ; : ? ! " \` ' [ ] { } ( ) < >` +Date and time formats may be fenced on either side by one punctuation character from the following list: ``, . ; : ? ! " \` ' [ ] { } ( ) < >`` .. code-block:: python + >>> arrow.get("Cool date: 2019-10-31T09:12:45.123456+04:30.", "YYYY-MM-DDTHH:mm:ss.SZZ") + <Arrow [2019-10-31T09:12:45.123456+04:30]> + >>> arrow.get("Tomorrow (2019-10-31) is Halloween!", "YYYY-MM-DD") <Arrow [2019-10-31T00:00:00+00:00]> @@ -502,6 +516,19 @@ >>> arrow.get("It's Halloween tomorrow (2019-10-31)!", "YYYY-MM-DD") # Raises exception because there are multiple punctuation marks following the date +Redundant Whitespace +~~~~~~~~~~~~~~~~~~~~ + +Redundant whitespace characters (spaces, tabs, and newlines) can be normalized automatically by passing in the ``normalize_whitespace`` flag to ``arrow.get``: + +.. code-block:: python + + >>> arrow.get('\t \n 2013-05-05T12:30:45.123456 \t \n', normalize_whitespace=True) + <Arrow [2013-05-05T12:30:45.123456+00:00]> + + >>> arrow.get('2013-05-05 T \n 12:30:45\t123456', 'YYYY-MM-DD T HH:mm:ss S', normalize_whitespace=True) + <Arrow [2013-05-05T12:30:45.123456+00:00]> + API Guide --------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/requirements.txt new/arrow-0.16.0/requirements.txt --- old/arrow-0.15.8/requirements.txt 2020-07-20 06:56:36.000000000 +0200 +++ new/arrow-0.16.0/requirements.txt 2020-08-21 23:14:48.000000000 +0200 @@ -3,7 +3,7 @@ pre-commit==1.21.*; python_version <= "3.5" pre-commit==2.6.*; python_version >= "3.6" pytest==4.6.*; python_version == "2.7" -pytest==5.4.*; python_version >= "3.5" +pytest==6.0.*; python_version >= "3.5" pytest-cov==2.10.* pytest-mock==2.0.*; python_version == "2.7" pytest-mock==3.2.*; python_version >= "3.5" @@ -11,4 +11,4 @@ pytz==2019.* simplejson==3.17.* sphinx==1.8.*; python_version == "2.7" -sphinx==3.1.*; python_version >= "3.5" +sphinx==3.2.*; python_version >= "3.5" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/setup.py new/arrow-0.16.0/setup.py --- old/arrow-0.15.8/setup.py 2020-07-24 04:50:10.000000000 +0200 +++ new/arrow-0.16.0/setup.py 2020-08-21 23:14:48.000000000 +0200 @@ -24,7 +24,7 @@ zip_safe=False, python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", install_requires=[ - "python-dateutil", + "python-dateutil>=2.7.0", "backports.functools_lru_cache>=1.2.1;python_version=='2.7'", ], classifiers=[ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/tests/test_arrow.py new/arrow-0.16.0/tests/test_arrow.py --- old/arrow-0.15.8/tests/test_arrow.py 2020-07-22 03:47:54.000000000 +0200 +++ new/arrow-0.16.0/tests/test_arrow.py 2020-08-23 23:32:16.000000000 +0200 @@ -72,6 +72,17 @@ assert result._datetime == self.expected assert_datetime_equality(result._datetime, self.expected, 1) + def test_init_with_fold(self): + before = arrow.Arrow(2017, 10, 29, 2, 0, tzinfo="Europe/Stockholm") + after = arrow.Arrow(2017, 10, 29, 2, 0, tzinfo="Europe/Stockholm", fold=1) + + assert hasattr(before, "fold") + assert hasattr(after, "fold") + + # PEP-495 requires the comparisons below to be true + assert before == after + assert before.utcoffset() != after.utcoffset() + class TestTestArrowFactory: def test_now(self): @@ -90,6 +101,8 @@ result._datetime, datetime.utcnow().replace(tzinfo=tz.tzutc()) ) + assert result.fold == 0 + def test_fromtimestamp(self): timestamp = time.time() @@ -276,6 +289,27 @@ assert result == self.arrow.microsecond + def test_getattr_fold(self): + + # UTC is always unambiguous + assert self.now.fold == 0 + + ambiguous_dt = arrow.Arrow( + 2017, 10, 29, 2, 0, tzinfo="Europe/Stockholm", fold=1 + ) + assert ambiguous_dt.fold == 1 + + with pytest.raises(AttributeError): + ambiguous_dt.fold = 0 + + def test_getattr_ambiguous(self): + + assert not self.now.ambiguous + + ambiguous_dt = arrow.Arrow(2017, 10, 29, 2, 0, tzinfo="Europe/Stockholm") + + assert ambiguous_dt.ambiguous + @pytest.mark.usefixtures("time_utcnow") class TestArrowComparison: @@ -549,6 +583,61 @@ assert arrow_from.to("UTC").datetime == self.expected assert arrow_from.to(tz.tzutc()).datetime == self.expected + # issue #368 + def test_to_pacific_then_utc(self): + result = arrow.Arrow(2018, 11, 4, 1, tzinfo="-08:00").to("US/Pacific").to("UTC") + assert result == arrow.Arrow(2018, 11, 4, 9) + + # issue #368 + def test_to_amsterdam_then_utc(self): + result = arrow.Arrow(2016, 10, 30).to("Europe/Amsterdam") + assert result.utcoffset() == timedelta(seconds=7200) + + # regression test for #690 + def test_to_israel_same_offset(self): + + result = arrow.Arrow(2019, 10, 27, 2, 21, 1, tzinfo="+03:00").to("Israel") + expected = arrow.Arrow(2019, 10, 27, 1, 21, 1, tzinfo="Israel") + + assert result == expected + assert result.utcoffset() != expected.utcoffset() + + # issue 315 + def test_anchorage_dst(self): + before = arrow.Arrow(2016, 3, 13, 1, 59, tzinfo="America/Anchorage") + after = arrow.Arrow(2016, 3, 13, 2, 1, tzinfo="America/Anchorage") + + assert before.utcoffset() != after.utcoffset() + + # issue 476 + def test_chicago_fall(self): + + result = arrow.Arrow(2017, 11, 5, 2, 1, tzinfo="-05:00").to("America/Chicago") + expected = arrow.Arrow(2017, 11, 5, 1, 1, tzinfo="America/Chicago") + + assert result == expected + assert result.utcoffset() != expected.utcoffset() + + def test_toronto_gap(self): + + before = arrow.Arrow(2011, 3, 13, 6, 30, tzinfo="UTC").to("America/Toronto") + after = arrow.Arrow(2011, 3, 13, 7, 30, tzinfo="UTC").to("America/Toronto") + + assert before.datetime.replace(tzinfo=None) == datetime(2011, 3, 13, 1, 30) + assert after.datetime.replace(tzinfo=None) == datetime(2011, 3, 13, 3, 30) + + assert before.utcoffset() != after.utcoffset() + + def test_sydney_gap(self): + + before = arrow.Arrow(2012, 10, 6, 15, 30, tzinfo="UTC").to("Australia/Sydney") + after = arrow.Arrow(2012, 10, 6, 16, 30, tzinfo="UTC").to("Australia/Sydney") + + assert before.datetime.replace(tzinfo=None) == datetime(2012, 10, 7, 1, 30) + assert after.datetime.replace(tzinfo=None) == datetime(2012, 10, 7, 3, 30) + + assert before.utcoffset() != after.utcoffset() + class TestArrowPickling: def test_pickle_and_unpickle(self): @@ -587,6 +676,23 @@ assert result == arw.datetime.replace(tzinfo=tz.gettz("US/Pacific")) + def test_replace_fold(self): + + before = arrow.Arrow(2017, 11, 5, 1, tzinfo="America/New_York") + after = before.replace(fold=1) + + assert before.fold == 0 + assert after.fold == 1 + assert before == after + assert before.utcoffset() != after.utcoffset() + + def test_replace_fold_and_other(self): + + arw = arrow.Arrow(2013, 5, 5, 12, 30, 45) + + assert arw.replace(fold=1, minute=50) == arrow.Arrow(2013, 5, 5, 12, 50, 45) + assert arw.replace(minute=50, fold=1) == arrow.Arrow(2013, 5, 5, 12, 50, 45) + def test_replace_week(self): with pytest.raises(AttributeError): @@ -597,6 +703,13 @@ with pytest.raises(AttributeError): arrow.Arrow.utcnow().replace(quarter=1) + def test_replace_quarter_and_fold(self): + with pytest.raises(AttributeError): + arrow.utcnow().replace(fold=1, quarter=1) + + with pytest.raises(AttributeError): + arrow.utcnow().replace(quarter=1, fold=1) + def test_replace_other_kwargs(self): with pytest.raises(AttributeError): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/tests/test_factory.py new/arrow-0.16.0/tests/test_factory.py --- old/arrow-0.15.8/tests/test_factory.py 2020-07-20 06:56:36.000000000 +0200 +++ new/arrow-0.16.0/tests/test_factory.py 2020-08-17 17:16:52.000000000 +0200 @@ -157,6 +157,24 @@ with pytest.raises(ParserError): self.factory.get(tzinfo="US/PacificInvalidTzinfo") + def test_kwarg_normalize_whitespace(self): + result = self.factory.get( + "Jun 1 2005 1:33PM", + "MMM D YYYY H:mmA", + tzinfo=tz.tzutc(), + normalize_whitespace=True, + ) + assert result._datetime == datetime(2005, 6, 1, 13, 33, tzinfo=tz.tzutc()) + + result = self.factory.get( + "\t 2013-05-05T12:30:45.123456 \t \n", + tzinfo=tz.tzutc(), + normalize_whitespace=True, + ) + assert result._datetime == datetime( + 2013, 5, 5, 12, 30, 45, 123456, tzinfo=tz.tzutc() + ) + def test_one_arg_iso_str(self): dt = datetime.utcnow() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/tests/test_parser.py new/arrow-0.16.0/tests/test_parser.py --- old/arrow-0.15.8/tests/test_parser.py 2020-07-20 06:56:36.000000000 +0200 +++ new/arrow-0.16.0/tests/test_parser.py 2020-08-17 17:16:52.000000000 +0200 @@ -742,6 +742,33 @@ with pytest.raises(ParserError): self.parser.parse(fmt, "W") + def test_parse_normalize_whitespace(self): + assert self.parser.parse( + "Jun 1 2005 1:33PM", "MMM D YYYY H:mmA", normalize_whitespace=True + ) == datetime(2005, 6, 1, 13, 33) + + with pytest.raises(ParserError): + self.parser.parse("Jun 1 2005 1:33PM", "MMM D YYYY H:mmA") + + assert self.parser.parse( + "\t 2013-05-05 T \n 12:30:45\t123456 \t \n", + "YYYY-MM-DD T HH:mm:ss S", + normalize_whitespace=True, + ) == datetime(2013, 5, 5, 12, 30, 45, 123456) + + with pytest.raises(ParserError): + self.parser.parse( + "\t 2013-05-05 T \n 12:30:45\t123456 \t \n", + "YYYY-MM-DD T HH:mm:ss S", + ) + + assert self.parser.parse( + " \n Jun 1\t 2005\n ", "MMM D YYYY", normalize_whitespace=True + ) == datetime(2005, 6, 1) + + with pytest.raises(ParserError): + self.parser.parse(" \n Jun 1\t 2005\n ", "MMM D YYYY") + @pytest.mark.usefixtures("dt_parser_regex") class TestDateTimeParserRegex: @@ -1157,6 +1184,21 @@ assert self.parser.parse_iso(dt.isoformat()) == dt + def test_parse_iso_normalize_whitespace(self): + assert self.parser.parse_iso( + "2013-036 \t 04:05:06Z", normalize_whitespace=True + ) == datetime(2013, 2, 5, 4, 5, 6, tzinfo=tz.tzutc()) + + with pytest.raises(ParserError): + self.parser.parse_iso("2013-036 \t 04:05:06Z") + + assert self.parser.parse_iso( + "\t 2013-05-05T12:30:45.123456 \t \n", normalize_whitespace=True + ) == datetime(2013, 5, 5, 12, 30, 45, 123456) + + with pytest.raises(ParserError): + self.parser.parse_iso("\t 2013-05-05T12:30:45.123456 \t \n") + def test_parse_iso_with_leading_and_trailing_whitespace(self): datetime_string = " 2016-11-15T06:37:19.123456" with pytest.raises(ParserError): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/arrow-0.15.8/tox.ini new/arrow-0.16.0/tox.ini --- old/arrow-0.15.8/tox.ini 2020-07-20 06:56:36.000000000 +0200 +++ new/arrow-0.16.0/tox.ini 2020-08-21 23:14:48.000000000 +0200 @@ -12,11 +12,9 @@ 3.8: py38 3.9: py39 -# Configure testing environments - [testenv] deps = -rrequirements.txt -whitelist_externals = pytest +allowlist_externals = pytest commands = pytest [testenv:lint] @@ -35,21 +33,19 @@ doc8 sphinx python-dateutil -whitelist_externals = make +allowlist_externals = make commands = doc8 index.rst ../README.rst --extension .rst --ignore D001 make html SPHINXOPTS="-W --keep-going" -# Configure settings for pytest, isort, and flake8 - [pytest] -addopts = -v --cov-branch --cov=arrow tests --cov-fail-under=100 --cov-report=term-missing --cov-report=xml +addopts = -v --cov-branch --cov=arrow --cov-fail-under=100 --cov-report=term-missing --cov-report=xml +testpaths = tests [isort] line_length = 88 multi_line_output = 3 include_trailing_comma = true -known_third_party = dateutil,pytest,pytz,setuptools,simplejson [flake8] per-file-ignores = arrow/__init__.py:F401