From 12d7913840adf3af4a4e5994a525b3e24c81c3c6 Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Sat, 4 Jan 2020 14:25:54 -0500 Subject: [PATCH 01/13] Converted api_tests and arrow_tests to pytest --- tests/api_tests.py | 33 +- tests/api_tests.py.bak | 33 + tests/arrow_tests.py | 1497 ++++++++++++--------------- tests/arrow_tests.py.bak | 2081 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 2753 insertions(+), 891 deletions(-) create mode 100644 tests/api_tests.py.bak create mode 100644 tests/arrow_tests.py.bak diff --git a/tests/api_tests.py b/tests/api_tests.py index 1cf171653..9b19a27cd 100644 --- a/tests/api_tests.py +++ b/tests/api_tests.py @@ -1,33 +1,28 @@ # -*- coding: utf-8 -*- -from chai import Chai +import arrow -from arrow import api, arrow, factory +class TestModule: + def test_get(self, mocker): + mocker.patch("arrow.api._factory.get", return_value="result") -class ModuleTests(Chai): - def test_get(self): + assert arrow.api.get() == "result" - self.expect(api._factory.get).args(1, b=2).returns("result") + def test_utcnow(self, mocker): + mocker.patch("arrow.api._factory.utcnow", return_value="utcnow") - self.assertEqual(api.get(1, b=2), "result") + assert arrow.api.utcnow() == "utcnow" - def test_utcnow(self): + def test_now(self, mocker): + mocker.patch("arrow.api._factory.now", tz="tz", return_value="now") - self.expect(api._factory.utcnow).returns("utcnow") - - self.assertEqual(api.utcnow(), "utcnow") - - def test_now(self): - - self.expect(api._factory.now).args("tz").returns("now") - - self.assertEqual(api.now("tz"), "now") + assert arrow.api.now("tz") == "now" def test_factory(self): class MockCustomArrowClass(arrow.Arrow): pass - result = api.factory(MockCustomArrowClass) + result = arrow.api.factory(MockCustomArrowClass) - self.assertIsInstance(result, factory.ArrowFactory) - self.assertIsInstance(result.utcnow(), MockCustomArrowClass) + assert isinstance(result, arrow.factory.ArrowFactory) + assert isinstance(result.utcnow(), MockCustomArrowClass) diff --git a/tests/api_tests.py.bak b/tests/api_tests.py.bak new file mode 100644 index 000000000..1cf171653 --- /dev/null +++ b/tests/api_tests.py.bak @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +from chai import Chai + +from arrow import api, arrow, factory + + +class ModuleTests(Chai): + def test_get(self): + + self.expect(api._factory.get).args(1, b=2).returns("result") + + self.assertEqual(api.get(1, b=2), "result") + + def test_utcnow(self): + + self.expect(api._factory.utcnow).returns("utcnow") + + self.assertEqual(api.utcnow(), "utcnow") + + def test_now(self): + + self.expect(api._factory.now).args("tz").returns("now") + + self.assertEqual(api.now("tz"), "now") + + def test_factory(self): + class MockCustomArrowClass(arrow.Arrow): + pass + + result = api.factory(MockCustomArrowClass) + + self.assertIsInstance(result, factory.ArrowFactory) + self.assertIsInstance(result.utcnow(), MockCustomArrowClass) diff --git a/tests/arrow_tests.py b/tests/arrow_tests.py index 9d6827660..e9d7cd72e 100644 --- a/tests/arrow_tests.py +++ b/tests/arrow_tests.py @@ -7,9 +7,9 @@ import time from datetime import date, datetime, timedelta +import pytest import pytz import simplejson as json -from chai import Chai from dateutil import tz from dateutil.relativedelta import FR, MO, SA, SU, TH, TU, WE from mock import patch @@ -18,43 +18,43 @@ def assertDtEqual(dt1, dt2, within=10): - assertEqual(dt1.tzinfo, dt2.tzinfo) # noqa: F821 - assertTrue(abs(util.total_seconds(dt1 - dt2)) < within) # noqa: F821 + assert dt1.tzinfo == dt2.tzinfo + assert abs(util.total_seconds(dt1 - dt2)) < within -class ArrowInitTests(Chai): +class TestTestArrowInit: def test_init_bad_input(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): arrow.Arrow(2013) - with self.assertRaises(TypeError): + with pytest.raises(TypeError): arrow.Arrow(2013, 2) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): arrow.Arrow(2013, 2, 2, 12, 30, 45, 9999999) def test_init(self): result = arrow.Arrow(2013, 2, 2) self.expected = datetime(2013, 2, 2, tzinfo=tz.tzutc()) - self.assertEqual(result._datetime, self.expected) + assert result._datetime == self.expected result = arrow.Arrow(2013, 2, 2, 12) self.expected = datetime(2013, 2, 2, 12, tzinfo=tz.tzutc()) - self.assertEqual(result._datetime, self.expected) + assert result._datetime == self.expected result = arrow.Arrow(2013, 2, 2, 12, 30) self.expected = datetime(2013, 2, 2, 12, 30, tzinfo=tz.tzutc()) - self.assertEqual(result._datetime, self.expected) + assert result._datetime == self.expected result = arrow.Arrow(2013, 2, 2, 12, 30, 45) self.expected = datetime(2013, 2, 2, 12, 30, 45, tzinfo=tz.tzutc()) - self.assertEqual(result._datetime, self.expected) + assert result._datetime == self.expected result = arrow.Arrow(2013, 2, 2, 12, 30, 45, 999999) self.expected = datetime(2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.tzutc()) - self.assertEqual(result._datetime, self.expected) + assert result._datetime == self.expected result = arrow.Arrow( 2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.gettz("Europe/Paris") @@ -62,7 +62,7 @@ def test_init(self): self.expected = datetime( 2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.gettz("Europe/Paris") ) - self.assertEqual(result._datetime, self.expected) + assert result._datetime == self.expected # regression tests for issue #626 def test_init_pytz_timezone(self): @@ -73,11 +73,11 @@ def test_init_pytz_timezone(self): self.expected = datetime( 2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.gettz("Europe/Paris") ) - self.assertEqual(result._datetime, self.expected) + assert result._datetime == self.expected assertDtEqual(result._datetime, self.expected, 1) -class ArrowFactoryTests(Chai): +class TestTestArrowFactory: def test_now(self): result = arrow.Arrow.now() @@ -109,7 +109,7 @@ def test_fromtimestamp(self): datetime.fromtimestamp(timestamp, tz.gettz("Europe/Paris")), ) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): arrow.Arrow.fromtimestamp("invalid timestamp") def test_utcfromtimestamp(self): @@ -119,7 +119,7 @@ def test_utcfromtimestamp(self): result = arrow.Arrow.utcfromtimestamp(timestamp) assertDtEqual(result._datetime, datetime.utcnow().replace(tzinfo=tz.tzutc())) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): arrow.Arrow.utcfromtimestamp("invalid timestamp") def test_fromdatetime(self): @@ -128,7 +128,7 @@ def test_fromdatetime(self): result = arrow.Arrow.fromdatetime(dt) - self.assertEqual(result._datetime, dt.replace(tzinfo=tz.tzutc())) + assert result._datetime == dt.replace(tzinfo=tz.tzutc()) def test_fromdatetime_dt_tzinfo(self): @@ -136,7 +136,7 @@ def test_fromdatetime_dt_tzinfo(self): result = arrow.Arrow.fromdatetime(dt) - self.assertEqual(result._datetime, dt.replace(tzinfo=tz.gettz("US/Pacific"))) + assert result._datetime == dt.replace(tzinfo=tz.gettz("US/Pacific")) def test_fromdatetime_tzinfo_arg(self): @@ -144,7 +144,7 @@ def test_fromdatetime_tzinfo_arg(self): result = arrow.Arrow.fromdatetime(dt, tz.gettz("US/Pacific")) - self.assertEqual(result._datetime, dt.replace(tzinfo=tz.gettz("US/Pacific"))) + assert result._datetime == dt.replace(tzinfo=tz.gettz("US/Pacific")) def test_fromdate(self): @@ -152,94 +152,85 @@ def test_fromdate(self): result = arrow.Arrow.fromdate(dt, tz.gettz("US/Pacific")) - self.assertEqual( - result._datetime, datetime(2013, 2, 3, tzinfo=tz.gettz("US/Pacific")) - ) + assert result._datetime == datetime(2013, 2, 3, tzinfo=tz.gettz("US/Pacific")) def test_strptime(self): formatted = datetime(2013, 2, 3, 12, 30, 45).strftime("%Y-%m-%d %H:%M:%S") result = arrow.Arrow.strptime(formatted, "%Y-%m-%d %H:%M:%S") - self.assertEqual( - result._datetime, datetime(2013, 2, 3, 12, 30, 45, tzinfo=tz.tzutc()) - ) + assert result._datetime == datetime(2013, 2, 3, 12, 30, 45, tzinfo=tz.tzutc()) result = arrow.Arrow.strptime( formatted, "%Y-%m-%d %H:%M:%S", tzinfo=tz.gettz("Europe/Paris") ) - self.assertEqual( - result._datetime, - datetime(2013, 2, 3, 12, 30, 45, tzinfo=tz.gettz("Europe/Paris")), + assert result._datetime == datetime( + 2013, 2, 3, 12, 30, 45, tzinfo=tz.gettz("Europe/Paris") ) -class ArrowRepresentationTests(Chai): - def setUp(self): - super(ArrowRepresentationTests, self).setUp() - - self.arrow = arrow.Arrow(2013, 2, 3, 12, 30, 45, 1) +class TestTestArrowRepresentation: + @classmethod + def setup_class(cls): + cls.arrow = arrow.Arrow(2013, 2, 3, 12, 30, 45, 1) def test_repr(self): result = self.arrow.__repr__() - self.assertEqual( - result, "".format(self.arrow._datetime.isoformat()) - ) + assert result == "".format(self.arrow._datetime.isoformat()) def test_str(self): result = self.arrow.__str__() - self.assertEqual(result, self.arrow._datetime.isoformat()) + assert result == self.arrow._datetime.isoformat() def test_hash(self): result = self.arrow.__hash__() - self.assertEqual(result, self.arrow._datetime.__hash__()) + assert result == self.arrow._datetime.__hash__() def test_format(self): result = "{:YYYY-MM-DD}".format(self.arrow) - self.assertEqual(result, "2013-02-03") + assert result == "2013-02-03" def test_bare_format(self): result = self.arrow.format() - self.assertEqual(result, "2013-02-03 12:30:45+00:00") + assert result == "2013-02-03 12:30:45+00:00" def test_format_no_format_string(self): result = "{}".format(self.arrow) - self.assertEqual(result, str(self.arrow)) + assert result == str(self.arrow) def test_clone(self): result = self.arrow.clone() - self.assertTrue(result is not self.arrow) - self.assertEqual(result._datetime, self.arrow._datetime) - + assert result is not self.arrow + assert result._datetime == self.arrow._datetime -class ArrowAttributeTests(Chai): - def setUp(self): - super(ArrowAttributeTests, self).setUp() - self.arrow = arrow.Arrow(2013, 1, 1) +class TestArrowAttribute: + @classmethod + def setup_class(cls): + cls.arrow = arrow.Arrow(2013, 1, 1) def test_getattr_base(self): - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): self.arrow.prop def test_getattr_week(self): - self.assertEqual(self.arrow.week, 1) + assert self.arrow.week == 1 def test_getattr_quarter(self): # start dates @@ -247,189 +238,186 @@ def test_getattr_quarter(self): q2 = arrow.Arrow(2013, 4, 1) q3 = arrow.Arrow(2013, 8, 1) q4 = arrow.Arrow(2013, 10, 1) - self.assertEqual(q1.quarter, 1) - self.assertEqual(q2.quarter, 2) - self.assertEqual(q3.quarter, 3) - self.assertEqual(q4.quarter, 4) + assert q1.quarter == 1 + assert q2.quarter == 2 + assert q3.quarter == 3 + assert q4.quarter == 4 # end dates q1 = arrow.Arrow(2013, 3, 31) q2 = arrow.Arrow(2013, 6, 30) q3 = arrow.Arrow(2013, 9, 30) q4 = arrow.Arrow(2013, 12, 31) - self.assertEqual(q1.quarter, 1) - self.assertEqual(q2.quarter, 2) - self.assertEqual(q3.quarter, 3) - self.assertEqual(q4.quarter, 4) + assert q1.quarter == 1 + assert q2.quarter == 2 + assert q3.quarter == 3 + assert q4.quarter == 4 def test_getattr_dt_value(self): - self.assertEqual(self.arrow.year, 2013) + assert self.arrow.year == 2013 def test_tzinfo(self): self.arrow.tzinfo = tz.gettz("PST") - self.assertEqual(self.arrow.tzinfo, tz.gettz("PST")) + assert self.arrow.tzinfo == tz.gettz("PST") def test_naive(self): - self.assertEqual(self.arrow.naive, self.arrow._datetime.replace(tzinfo=None)) + assert self.arrow.naive == self.arrow._datetime.replace(tzinfo=None) def test_timestamp(self): - self.assertEqual( - self.arrow.timestamp, calendar.timegm(self.arrow._datetime.utctimetuple()) + assert self.arrow.timestamp == calendar.timegm( + self.arrow._datetime.utctimetuple() ) def test_float_timestamp(self): result = self.arrow.float_timestamp - self.arrow.timestamp - self.assertEqual(result, self.arrow.microsecond) - + assert result == self.arrow.microsecond -class ArrowComparisonTests(Chai): - def setUp(self): - super(ArrowComparisonTests, self).setUp() - self.arrow = arrow.Arrow.utcnow() +class TestArrowComparison: + @classmethod + def setup_class(cls): + cls.arrow = arrow.Arrow.utcnow() def test_eq(self): - self.assertTrue(self.arrow == self.arrow) - self.assertTrue(self.arrow == self.arrow.datetime) - self.assertFalse(self.arrow == "abc") + assert self.arrow == self.arrow + assert self.arrow == self.arrow.datetime + assert not (self.arrow == "abc") def test_ne(self): - self.assertFalse(self.arrow != self.arrow) - self.assertFalse(self.arrow != self.arrow.datetime) - self.assertTrue(self.arrow != "abc") + assert not (self.arrow != self.arrow) + assert not (self.arrow != self.arrow.datetime) + assert self.arrow != "abc" def test_gt(self): arrow_cmp = self.arrow.shift(minutes=1) - self.assertFalse(self.arrow > self.arrow) - self.assertFalse(self.arrow > self.arrow.datetime) + assert not (self.arrow > self.arrow) + assert not (self.arrow > self.arrow.datetime) - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.arrow > "abc" - self.assertTrue(self.arrow < arrow_cmp) - self.assertTrue(self.arrow < arrow_cmp.datetime) + assert self.arrow < arrow_cmp + assert self.arrow < arrow_cmp.datetime def test_ge(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.arrow >= "abc" - self.assertTrue(self.arrow >= self.arrow) - self.assertTrue(self.arrow >= self.arrow.datetime) + assert self.arrow >= self.arrow + assert self.arrow >= self.arrow.datetime def test_lt(self): arrow_cmp = self.arrow.shift(minutes=1) - self.assertFalse(self.arrow < self.arrow) - self.assertFalse(self.arrow < self.arrow.datetime) + assert not (self.arrow < self.arrow) + assert not (self.arrow < self.arrow.datetime) - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.arrow < "abc" - self.assertTrue(self.arrow < arrow_cmp) - self.assertTrue(self.arrow < arrow_cmp.datetime) + assert self.arrow < arrow_cmp + assert self.arrow < arrow_cmp.datetime def test_le(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.arrow <= "abc" - self.assertTrue(self.arrow <= self.arrow) - self.assertTrue(self.arrow <= self.arrow.datetime) + assert self.arrow <= self.arrow + assert self.arrow <= self.arrow.datetime -class ArrowMathTests(Chai): - def setUp(self): - super(ArrowMathTests, self).setUp() - - self.arrow = arrow.Arrow(2013, 1, 1) +class TestArrowMath: + @classmethod + def setup_class(cls): + cls.arrow = arrow.Arrow(2013, 1, 1) def test_add_timedelta(self): result = self.arrow.__add__(timedelta(days=1)) - self.assertEqual(result._datetime, datetime(2013, 1, 2, tzinfo=tz.tzutc())) + assert result._datetime == datetime(2013, 1, 2, tzinfo=tz.tzutc()) def test_add_other(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.arrow + 1 def test_radd(self): result = self.arrow.__radd__(timedelta(days=1)) - self.assertEqual(result._datetime, datetime(2013, 1, 2, tzinfo=tz.tzutc())) + assert result._datetime == datetime(2013, 1, 2, tzinfo=tz.tzutc()) def test_sub_timedelta(self): result = self.arrow.__sub__(timedelta(days=1)) - self.assertEqual(result._datetime, datetime(2012, 12, 31, tzinfo=tz.tzutc())) + assert result._datetime == datetime(2012, 12, 31, tzinfo=tz.tzutc()) def test_sub_datetime(self): result = self.arrow.__sub__(datetime(2012, 12, 21, tzinfo=tz.tzutc())) - self.assertEqual(result, timedelta(days=11)) + assert result == timedelta(days=11) def test_sub_arrow(self): result = self.arrow.__sub__(arrow.Arrow(2012, 12, 21, tzinfo=tz.tzutc())) - self.assertEqual(result, timedelta(days=11)) + assert result == timedelta(days=11) def test_sub_other(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.arrow - object() def test_rsub_datetime(self): result = self.arrow.__rsub__(datetime(2012, 12, 21, tzinfo=tz.tzutc())) - self.assertEqual(result, timedelta(days=-11)) + assert result == timedelta(days=-11) def test_rsub_other(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): timedelta(days=1) - self.arrow -class ArrowDatetimeInterfaceTests(Chai): - def setUp(self): - super(ArrowDatetimeInterfaceTests, self).setUp() - - self.arrow = arrow.Arrow.utcnow() +class TestArrowDatetimeInterface: + @classmethod + def setup_class(cls): + cls.arrow = arrow.Arrow.utcnow() def test_date(self): result = self.arrow.date() - self.assertEqual(result, self.arrow._datetime.date()) + assert result == self.arrow._datetime.date() def test_time(self): result = self.arrow.time() - self.assertEqual(result, self.arrow._datetime.time()) + assert result == self.arrow._datetime.time() def test_timetz(self): result = self.arrow.timetz() - self.assertEqual(result, self.arrow._datetime.timetz()) + assert result == self.arrow._datetime.timetz() def test_astimezone(self): @@ -437,82 +425,82 @@ def test_astimezone(self): result = self.arrow.astimezone(other_tz) - self.assertEqual(result, self.arrow._datetime.astimezone(other_tz)) + assert result == self.arrow._datetime.astimezone(other_tz) def test_utcoffset(self): result = self.arrow.utcoffset() - self.assertEqual(result, self.arrow._datetime.utcoffset()) + assert result == self.arrow._datetime.utcoffset() def test_dst(self): result = self.arrow.dst() - self.assertEqual(result, self.arrow._datetime.dst()) + assert result == self.arrow._datetime.dst() def test_timetuple(self): result = self.arrow.timetuple() - self.assertEqual(result, self.arrow._datetime.timetuple()) + assert result == self.arrow._datetime.timetuple() def test_utctimetuple(self): result = self.arrow.utctimetuple() - self.assertEqual(result, self.arrow._datetime.utctimetuple()) + assert result == self.arrow._datetime.utctimetuple() def test_toordinal(self): result = self.arrow.toordinal() - self.assertEqual(result, self.arrow._datetime.toordinal()) + assert result == self.arrow._datetime.toordinal() def test_weekday(self): result = self.arrow.weekday() - self.assertEqual(result, self.arrow._datetime.weekday()) + assert result == self.arrow._datetime.weekday() def test_isoweekday(self): result = self.arrow.isoweekday() - self.assertEqual(result, self.arrow._datetime.isoweekday()) + assert result == self.arrow._datetime.isoweekday() def test_isocalendar(self): result = self.arrow.isocalendar() - self.assertEqual(result, self.arrow._datetime.isocalendar()) + assert result == self.arrow._datetime.isocalendar() def test_isoformat(self): result = self.arrow.isoformat() - self.assertEqual(result, self.arrow._datetime.isoformat()) + assert result == self.arrow._datetime.isoformat() def test_simplejson(self): result = json.dumps({"v": self.arrow.for_json()}, for_json=True) - self.assertEqual(json.loads(result)["v"], self.arrow._datetime.isoformat()) + assert json.loads(result)["v"] == self.arrow._datetime.isoformat() def test_ctime(self): result = self.arrow.ctime() - self.assertEqual(result, self.arrow._datetime.ctime()) + assert result == self.arrow._datetime.ctime() def test_strftime(self): result = self.arrow.strftime("%Y") - self.assertEqual(result, self.arrow._datetime.strftime("%Y")) + assert result == self.arrow._datetime.strftime("%Y") -class ArrowFalsePositiveDstTests(Chai): +class TestArrowFalsePositiveDst: """These tests relate to issues #376 and #551. The key points in both issues are that arrow will assign a UTC timezone if none is provided and .to() will change other attributes to be correct whereas .replace() only changes the specified attribute. @@ -536,35 +524,34 @@ class ArrowFalsePositiveDstTests(Chai): 2018-11-04T02:00:00-05:00 """ - def setUp(self): - - super(ArrowFalsePositiveDstTests, self).setUp() - self.before_1 = arrow.Arrow( + @classmethod + def setup_class(cls): + cls.before_1 = arrow.Arrow( 2016, 11, 6, 3, 59, tzinfo=tz.gettz("America/New_York") ) - self.before_2 = arrow.Arrow(2016, 11, 6, tzinfo=tz.gettz("America/New_York")) - self.after_1 = arrow.Arrow(2016, 11, 6, 4, tzinfo=tz.gettz("America/New_York")) - self.after_2 = arrow.Arrow( + cls.before_2 = arrow.Arrow(2016, 11, 6, tzinfo=tz.gettz("America/New_York")) + cls.after_1 = arrow.Arrow(2016, 11, 6, 4, tzinfo=tz.gettz("America/New_York")) + cls.after_2 = arrow.Arrow( 2016, 11, 6, 23, 59, tzinfo=tz.gettz("America/New_York") ) - self.before_3 = arrow.Arrow( + cls.before_3 = arrow.Arrow( 2018, 11, 4, 3, 59, tzinfo=tz.gettz("America/New_York") ) - self.before_4 = arrow.Arrow(2018, 11, 4, tzinfo=tz.gettz("America/New_York")) - self.after_3 = arrow.Arrow(2018, 11, 4, 4, tzinfo=tz.gettz("America/New_York")) - self.after_4 = arrow.Arrow( + cls.before_4 = arrow.Arrow(2018, 11, 4, tzinfo=tz.gettz("America/New_York")) + cls.after_3 = arrow.Arrow(2018, 11, 4, 4, tzinfo=tz.gettz("America/New_York")) + cls.after_4 = arrow.Arrow( 2018, 11, 4, 23, 59, tzinfo=tz.gettz("America/New_York") ) def test_dst(self): - self.assertEqual(self.before_1.day, self.before_2.day) - self.assertEqual(self.after_1.day, self.after_2.day) - self.assertEqual(self.before_3.day, self.before_4.day) - self.assertEqual(self.after_3.day, self.after_4.day) + assert self.before_1.day == self.before_2.day + assert self.after_1.day == self.after_2.day + assert self.before_3.day == self.before_4.day + assert self.after_3.day == self.after_4.day -class ArrowConversionTests(Chai): +class TestArrowConversion: def test_to(self): dt_from = datetime.now() @@ -574,11 +561,11 @@ def test_to(self): tz.tzutc() ) - self.assertEqual(arrow_from.to("UTC").datetime, self.expected) - self.assertEqual(arrow_from.to(tz.tzutc()).datetime, self.expected) + assert arrow_from.to("UTC").datetime == self.expected + assert arrow_from.to(tz.tzutc()).datetime == self.expected -class ArrowPicklingTests(Chai): +class TestArrowPickling: def test_pickle_and_unpickle(self): dt = arrow.Arrow.utcnow() @@ -587,25 +574,25 @@ def test_pickle_and_unpickle(self): unpickled = pickle.loads(pickled) - self.assertEqual(unpickled, dt) + assert unpickled == dt -class ArrowReplaceTests(Chai): +class TestArrowReplace: def test_not_attr(self): - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): arrow.Arrow.utcnow().replace(abc=1) def test_replace(self): arw = arrow.Arrow(2013, 5, 5, 12, 30, 45) - self.assertEqual(arw.replace(year=2012), arrow.Arrow(2012, 5, 5, 12, 30, 45)) - self.assertEqual(arw.replace(month=1), arrow.Arrow(2013, 1, 5, 12, 30, 45)) - self.assertEqual(arw.replace(day=1), arrow.Arrow(2013, 5, 1, 12, 30, 45)) - self.assertEqual(arw.replace(hour=1), arrow.Arrow(2013, 5, 5, 1, 30, 45)) - self.assertEqual(arw.replace(minute=1), arrow.Arrow(2013, 5, 5, 12, 1, 45)) - self.assertEqual(arw.replace(second=1), arrow.Arrow(2013, 5, 5, 12, 30, 1)) + assert arw.replace(year=2012) == arrow.Arrow(2012, 5, 5, 12, 30, 45) + assert arw.replace(month=1) == arrow.Arrow(2013, 1, 5, 12, 30, 45) + assert arw.replace(day=1) == arrow.Arrow(2013, 5, 1, 12, 30, 45) + assert arw.replace(hour=1) == arrow.Arrow(2013, 5, 5, 1, 30, 45) + assert arw.replace(minute=1) == arrow.Arrow(2013, 5, 5, 12, 1, 45) + assert arw.replace(second=1) == arrow.Arrow(2013, 5, 5, 12, 30, 1) def test_replace_tzinfo(self): @@ -613,141 +600,127 @@ def test_replace_tzinfo(self): result = arw.replace(tzinfo=tz.gettz("US/Pacific")) - self.assertEqual(result, arw.datetime.replace(tzinfo=tz.gettz("US/Pacific"))) + assert result == arw.datetime.replace(tzinfo=tz.gettz("US/Pacific")) def test_replace_week(self): - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): arrow.Arrow.utcnow().replace(week=1) def test_replace_quarter(self): - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): arrow.Arrow.utcnow().replace(quarter=1) def test_replace_other_kwargs(self): - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): arrow.utcnow().replace(abc="def") -class ArrowShiftTests(Chai): +class TestArrowShift: def test_not_attr(self): now = arrow.Arrow.utcnow() - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): now.shift(abc=1) - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): now.shift(week=1) def test_shift(self): arw = arrow.Arrow(2013, 5, 5, 12, 30, 45) - self.assertEqual(arw.shift(years=1), arrow.Arrow(2014, 5, 5, 12, 30, 45)) - self.assertEqual(arw.shift(quarters=1), arrow.Arrow(2013, 8, 5, 12, 30, 45)) - self.assertEqual( - arw.shift(quarters=1, months=1), arrow.Arrow(2013, 9, 5, 12, 30, 45) - ) - self.assertEqual(arw.shift(months=1), arrow.Arrow(2013, 6, 5, 12, 30, 45)) - self.assertEqual(arw.shift(weeks=1), arrow.Arrow(2013, 5, 12, 12, 30, 45)) - self.assertEqual(arw.shift(days=1), arrow.Arrow(2013, 5, 6, 12, 30, 45)) - self.assertEqual(arw.shift(hours=1), arrow.Arrow(2013, 5, 5, 13, 30, 45)) - self.assertEqual(arw.shift(minutes=1), arrow.Arrow(2013, 5, 5, 12, 31, 45)) - self.assertEqual(arw.shift(seconds=1), arrow.Arrow(2013, 5, 5, 12, 30, 46)) - self.assertEqual( - arw.shift(microseconds=1), arrow.Arrow(2013, 5, 5, 12, 30, 45, 1) - ) + assert arw.shift(years=1) == arrow.Arrow(2014, 5, 5, 12, 30, 45) + assert arw.shift(quarters=1) == arrow.Arrow(2013, 8, 5, 12, 30, 45) + assert arw.shift(quarters=1, months=1) == arrow.Arrow(2013, 9, 5, 12, 30, 45) + assert arw.shift(months=1) == arrow.Arrow(2013, 6, 5, 12, 30, 45) + assert arw.shift(weeks=1) == arrow.Arrow(2013, 5, 12, 12, 30, 45) + assert arw.shift(days=1) == arrow.Arrow(2013, 5, 6, 12, 30, 45) + assert arw.shift(hours=1) == arrow.Arrow(2013, 5, 5, 13, 30, 45) + assert arw.shift(minutes=1) == arrow.Arrow(2013, 5, 5, 12, 31, 45) + assert arw.shift(seconds=1) == arrow.Arrow(2013, 5, 5, 12, 30, 46) + assert arw.shift(microseconds=1) == arrow.Arrow(2013, 5, 5, 12, 30, 45, 1) # Remember: Python's weekday 0 is Monday - self.assertEqual(arw.shift(weekday=0), arrow.Arrow(2013, 5, 6, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=1), arrow.Arrow(2013, 5, 7, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=2), arrow.Arrow(2013, 5, 8, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=3), arrow.Arrow(2013, 5, 9, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=4), arrow.Arrow(2013, 5, 10, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=5), arrow.Arrow(2013, 5, 11, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=6), arw) - - with self.assertRaises(IndexError): + assert arw.shift(weekday=0) == arrow.Arrow(2013, 5, 6, 12, 30, 45) + assert arw.shift(weekday=1) == arrow.Arrow(2013, 5, 7, 12, 30, 45) + assert arw.shift(weekday=2) == arrow.Arrow(2013, 5, 8, 12, 30, 45) + assert arw.shift(weekday=3) == arrow.Arrow(2013, 5, 9, 12, 30, 45) + assert arw.shift(weekday=4) == arrow.Arrow(2013, 5, 10, 12, 30, 45) + assert arw.shift(weekday=5) == arrow.Arrow(2013, 5, 11, 12, 30, 45) + assert arw.shift(weekday=6) == arw + + with pytest.raises(IndexError): arw.shift(weekday=7) # Use dateutil.relativedelta's convenient day instances - self.assertEqual(arw.shift(weekday=MO), arrow.Arrow(2013, 5, 6, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=MO(0)), arrow.Arrow(2013, 5, 6, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=MO(1)), arrow.Arrow(2013, 5, 6, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=MO(2)), arrow.Arrow(2013, 5, 13, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TU), arrow.Arrow(2013, 5, 7, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TU(0)), arrow.Arrow(2013, 5, 7, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TU(1)), arrow.Arrow(2013, 5, 7, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TU(2)), arrow.Arrow(2013, 5, 14, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=WE), arrow.Arrow(2013, 5, 8, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=WE(0)), arrow.Arrow(2013, 5, 8, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=WE(1)), arrow.Arrow(2013, 5, 8, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=WE(2)), arrow.Arrow(2013, 5, 15, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TH), arrow.Arrow(2013, 5, 9, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TH(0)), arrow.Arrow(2013, 5, 9, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TH(1)), arrow.Arrow(2013, 5, 9, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TH(2)), arrow.Arrow(2013, 5, 16, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=FR), arrow.Arrow(2013, 5, 10, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=FR(0)), arrow.Arrow(2013, 5, 10, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=FR(1)), arrow.Arrow(2013, 5, 10, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=FR(2)), arrow.Arrow(2013, 5, 17, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SA), arrow.Arrow(2013, 5, 11, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SA(0)), arrow.Arrow(2013, 5, 11, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SA(1)), arrow.Arrow(2013, 5, 11, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SA(2)), arrow.Arrow(2013, 5, 18, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SU), arw) - self.assertEqual(arw.shift(weekday=SU(0)), arw) - self.assertEqual(arw.shift(weekday=SU(1)), arw) - self.assertEqual(arw.shift(weekday=SU(2)), arrow.Arrow(2013, 5, 12, 12, 30, 45)) + assert arw.shift(weekday=MO) == arrow.Arrow(2013, 5, 6, 12, 30, 45) + assert arw.shift(weekday=MO(0)) == arrow.Arrow(2013, 5, 6, 12, 30, 45) + assert arw.shift(weekday=MO(1)) == arrow.Arrow(2013, 5, 6, 12, 30, 45) + assert arw.shift(weekday=MO(2)) == arrow.Arrow(2013, 5, 13, 12, 30, 45) + assert arw.shift(weekday=TU) == arrow.Arrow(2013, 5, 7, 12, 30, 45) + assert arw.shift(weekday=TU(0)) == arrow.Arrow(2013, 5, 7, 12, 30, 45) + assert arw.shift(weekday=TU(1)) == arrow.Arrow(2013, 5, 7, 12, 30, 45) + assert arw.shift(weekday=TU(2)) == arrow.Arrow(2013, 5, 14, 12, 30, 45) + assert arw.shift(weekday=WE) == arrow.Arrow(2013, 5, 8, 12, 30, 45) + assert arw.shift(weekday=WE(0)) == arrow.Arrow(2013, 5, 8, 12, 30, 45) + assert arw.shift(weekday=WE(1)) == arrow.Arrow(2013, 5, 8, 12, 30, 45) + assert arw.shift(weekday=WE(2)) == arrow.Arrow(2013, 5, 15, 12, 30, 45) + assert arw.shift(weekday=TH) == arrow.Arrow(2013, 5, 9, 12, 30, 45) + assert arw.shift(weekday=TH(0)) == arrow.Arrow(2013, 5, 9, 12, 30, 45) + assert arw.shift(weekday=TH(1)) == arrow.Arrow(2013, 5, 9, 12, 30, 45) + assert arw.shift(weekday=TH(2)) == arrow.Arrow(2013, 5, 16, 12, 30, 45) + assert arw.shift(weekday=FR) == arrow.Arrow(2013, 5, 10, 12, 30, 45) + assert arw.shift(weekday=FR(0)) == arrow.Arrow(2013, 5, 10, 12, 30, 45) + assert arw.shift(weekday=FR(1)) == arrow.Arrow(2013, 5, 10, 12, 30, 45) + assert arw.shift(weekday=FR(2)) == arrow.Arrow(2013, 5, 17, 12, 30, 45) + assert arw.shift(weekday=SA) == arrow.Arrow(2013, 5, 11, 12, 30, 45) + assert arw.shift(weekday=SA(0)) == arrow.Arrow(2013, 5, 11, 12, 30, 45) + assert arw.shift(weekday=SA(1)) == arrow.Arrow(2013, 5, 11, 12, 30, 45) + assert arw.shift(weekday=SA(2)) == arrow.Arrow(2013, 5, 18, 12, 30, 45) + assert arw.shift(weekday=SU) == arw + assert arw.shift(weekday=SU(0)) == arw + assert arw.shift(weekday=SU(1)) == arw + assert arw.shift(weekday=SU(2)) == arrow.Arrow(2013, 5, 12, 12, 30, 45) def test_shift_negative(self): arw = arrow.Arrow(2013, 5, 5, 12, 30, 45) - self.assertEqual(arw.shift(years=-1), arrow.Arrow(2012, 5, 5, 12, 30, 45)) - self.assertEqual(arw.shift(quarters=-1), arrow.Arrow(2013, 2, 5, 12, 30, 45)) - self.assertEqual( - arw.shift(quarters=-1, months=-1), arrow.Arrow(2013, 1, 5, 12, 30, 45) - ) - self.assertEqual(arw.shift(months=-1), arrow.Arrow(2013, 4, 5, 12, 30, 45)) - self.assertEqual(arw.shift(weeks=-1), arrow.Arrow(2013, 4, 28, 12, 30, 45)) - self.assertEqual(arw.shift(days=-1), arrow.Arrow(2013, 5, 4, 12, 30, 45)) - self.assertEqual(arw.shift(hours=-1), arrow.Arrow(2013, 5, 5, 11, 30, 45)) - self.assertEqual(arw.shift(minutes=-1), arrow.Arrow(2013, 5, 5, 12, 29, 45)) - self.assertEqual(arw.shift(seconds=-1), arrow.Arrow(2013, 5, 5, 12, 30, 44)) - self.assertEqual( - arw.shift(microseconds=-1), arrow.Arrow(2013, 5, 5, 12, 30, 44, 999999) - ) + assert arw.shift(years=-1) == arrow.Arrow(2012, 5, 5, 12, 30, 45) + assert arw.shift(quarters=-1) == arrow.Arrow(2013, 2, 5, 12, 30, 45) + assert arw.shift(quarters=-1, months=-1) == arrow.Arrow(2013, 1, 5, 12, 30, 45) + assert arw.shift(months=-1) == arrow.Arrow(2013, 4, 5, 12, 30, 45) + assert arw.shift(weeks=-1) == arrow.Arrow(2013, 4, 28, 12, 30, 45) + assert arw.shift(days=-1) == arrow.Arrow(2013, 5, 4, 12, 30, 45) + assert arw.shift(hours=-1) == arrow.Arrow(2013, 5, 5, 11, 30, 45) + assert arw.shift(minutes=-1) == arrow.Arrow(2013, 5, 5, 12, 29, 45) + assert arw.shift(seconds=-1) == arrow.Arrow(2013, 5, 5, 12, 30, 44) + assert arw.shift(microseconds=-1) == arrow.Arrow(2013, 5, 5, 12, 30, 44, 999999) # Not sure how practical these negative weekdays are - self.assertEqual(arw.shift(weekday=-1), arw.shift(weekday=SU)) - self.assertEqual(arw.shift(weekday=-2), arw.shift(weekday=SA)) - self.assertEqual(arw.shift(weekday=-3), arw.shift(weekday=FR)) - self.assertEqual(arw.shift(weekday=-4), arw.shift(weekday=TH)) - self.assertEqual(arw.shift(weekday=-5), arw.shift(weekday=WE)) - self.assertEqual(arw.shift(weekday=-6), arw.shift(weekday=TU)) - self.assertEqual(arw.shift(weekday=-7), arw.shift(weekday=MO)) - - with self.assertRaises(IndexError): + assert arw.shift(weekday=-1) == arw.shift(weekday=SU) + assert arw.shift(weekday=-2) == arw.shift(weekday=SA) + assert arw.shift(weekday=-3) == arw.shift(weekday=FR) + assert arw.shift(weekday=-4) == arw.shift(weekday=TH) + assert arw.shift(weekday=-5) == arw.shift(weekday=WE) + assert arw.shift(weekday=-6) == arw.shift(weekday=TU) + assert arw.shift(weekday=-7) == arw.shift(weekday=MO) + + with pytest.raises(IndexError): arw.shift(weekday=-8) - self.assertEqual( - arw.shift(weekday=MO(-1)), arrow.Arrow(2013, 4, 29, 12, 30, 45) - ) - self.assertEqual( - arw.shift(weekday=TU(-1)), arrow.Arrow(2013, 4, 30, 12, 30, 45) - ) - self.assertEqual(arw.shift(weekday=WE(-1)), arrow.Arrow(2013, 5, 1, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TH(-1)), arrow.Arrow(2013, 5, 2, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=FR(-1)), arrow.Arrow(2013, 5, 3, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SA(-1)), arrow.Arrow(2013, 5, 4, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SU(-1)), arw) - self.assertEqual( - arw.shift(weekday=SU(-2)), arrow.Arrow(2013, 4, 28, 12, 30, 45) - ) + assert arw.shift(weekday=MO(-1)) == arrow.Arrow(2013, 4, 29, 12, 30, 45) + assert arw.shift(weekday=TU(-1)) == arrow.Arrow(2013, 4, 30, 12, 30, 45) + assert arw.shift(weekday=WE(-1)) == arrow.Arrow(2013, 5, 1, 12, 30, 45) + assert arw.shift(weekday=TH(-1)) == arrow.Arrow(2013, 5, 2, 12, 30, 45) + assert arw.shift(weekday=FR(-1)) == arrow.Arrow(2013, 5, 3, 12, 30, 45) + assert arw.shift(weekday=SA(-1)) == arrow.Arrow(2013, 5, 4, 12, 30, 45) + assert arw.shift(weekday=SU(-1)) == arw + assert arw.shift(weekday=SU(-2)) == arrow.Arrow(2013, 4, 28, 12, 30, 45) def test_shift_quarters_bug(self): @@ -756,34 +729,19 @@ def test_shift_quarters_bug(self): # The value of the last-read argument was used instead of the ``quarters`` argument. # Recall that the keyword argument dict, like all dicts, is unordered, so only certain # combinations of arguments would exhibit this. - self.assertEqual( - arw.shift(quarters=0, years=1), arrow.Arrow(2014, 5, 5, 12, 30, 45) - ) - self.assertEqual( - arw.shift(quarters=0, months=1), arrow.Arrow(2013, 6, 5, 12, 30, 45) - ) - self.assertEqual( - arw.shift(quarters=0, weeks=1), arrow.Arrow(2013, 5, 12, 12, 30, 45) - ) - self.assertEqual( - arw.shift(quarters=0, days=1), arrow.Arrow(2013, 5, 6, 12, 30, 45) - ) - self.assertEqual( - arw.shift(quarters=0, hours=1), arrow.Arrow(2013, 5, 5, 13, 30, 45) - ) - self.assertEqual( - arw.shift(quarters=0, minutes=1), arrow.Arrow(2013, 5, 5, 12, 31, 45) - ) - self.assertEqual( - arw.shift(quarters=0, seconds=1), arrow.Arrow(2013, 5, 5, 12, 30, 46) - ) - self.assertEqual( - arw.shift(quarters=0, microseconds=1), - arrow.Arrow(2013, 5, 5, 12, 30, 45, 1), + assert arw.shift(quarters=0, years=1) == arrow.Arrow(2014, 5, 5, 12, 30, 45) + assert arw.shift(quarters=0, months=1) == arrow.Arrow(2013, 6, 5, 12, 30, 45) + assert arw.shift(quarters=0, weeks=1) == arrow.Arrow(2013, 5, 12, 12, 30, 45) + assert arw.shift(quarters=0, days=1) == arrow.Arrow(2013, 5, 6, 12, 30, 45) + assert arw.shift(quarters=0, hours=1) == arrow.Arrow(2013, 5, 5, 13, 30, 45) + assert arw.shift(quarters=0, minutes=1) == arrow.Arrow(2013, 5, 5, 12, 31, 45) + assert arw.shift(quarters=0, seconds=1) == arrow.Arrow(2013, 5, 5, 12, 30, 46) + assert arw.shift(quarters=0, microseconds=1) == arrow.Arrow( + 2013, 5, 5, 12, 30, 45, 1 ) -class ArrowRangeTests(Chai): +class TestArrowRange: def test_year(self): result = list( @@ -792,15 +750,12 @@ def test_year(self): ) ) - self.assertEqual( - result, - [ - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2014, 1, 2, 3, 4, 5), - arrow.Arrow(2015, 1, 2, 3, 4, 5), - arrow.Arrow(2016, 1, 2, 3, 4, 5), - ], - ) + assert result == [ + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2014, 1, 2, 3, 4, 5), + arrow.Arrow(2015, 1, 2, 3, 4, 5), + arrow.Arrow(2016, 1, 2, 3, 4, 5), + ] def test_quarter(self): @@ -810,9 +765,10 @@ def test_quarter(self): ) ) - self.assertEqual( - result, [arrow.Arrow(2013, 2, 3, 4, 5, 6), arrow.Arrow(2013, 5, 3, 4, 5, 6)] - ) + assert result == [ + arrow.Arrow(2013, 2, 3, 4, 5, 6), + arrow.Arrow(2013, 5, 3, 4, 5, 6), + ] def test_month(self): @@ -822,15 +778,12 @@ def test_month(self): ) ) - self.assertEqual( - result, - [ - arrow.Arrow(2013, 2, 3, 4, 5, 6), - arrow.Arrow(2013, 3, 3, 4, 5, 6), - arrow.Arrow(2013, 4, 3, 4, 5, 6), - arrow.Arrow(2013, 5, 3, 4, 5, 6), - ], - ) + assert result == [ + arrow.Arrow(2013, 2, 3, 4, 5, 6), + arrow.Arrow(2013, 3, 3, 4, 5, 6), + arrow.Arrow(2013, 4, 3, 4, 5, 6), + arrow.Arrow(2013, 5, 3, 4, 5, 6), + ] def test_week(self): @@ -840,16 +793,13 @@ def test_week(self): ) ) - self.assertEqual( - result, - [ - arrow.Arrow(2013, 9, 1, 2, 3, 4), - arrow.Arrow(2013, 9, 8, 2, 3, 4), - arrow.Arrow(2013, 9, 15, 2, 3, 4), - arrow.Arrow(2013, 9, 22, 2, 3, 4), - arrow.Arrow(2013, 9, 29, 2, 3, 4), - ], - ) + assert result == [ + arrow.Arrow(2013, 9, 1, 2, 3, 4), + arrow.Arrow(2013, 9, 8, 2, 3, 4), + arrow.Arrow(2013, 9, 15, 2, 3, 4), + arrow.Arrow(2013, 9, 22, 2, 3, 4), + arrow.Arrow(2013, 9, 29, 2, 3, 4), + ] def test_day(self): @@ -859,15 +809,12 @@ def test_day(self): ) ) - self.assertEqual( - result, - [ - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2013, 1, 3, 3, 4, 5), - arrow.Arrow(2013, 1, 4, 3, 4, 5), - arrow.Arrow(2013, 1, 5, 3, 4, 5), - ], - ) + assert result == [ + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2013, 1, 3, 3, 4, 5), + arrow.Arrow(2013, 1, 4, 3, 4, 5), + arrow.Arrow(2013, 1, 5, 3, 4, 5), + ] def test_hour(self): @@ -877,15 +824,12 @@ def test_hour(self): ) ) - self.assertEqual( - result, - [ - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2013, 1, 2, 4, 4, 5), - arrow.Arrow(2013, 1, 2, 5, 4, 5), - arrow.Arrow(2013, 1, 2, 6, 4, 5), - ], - ) + assert result == [ + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2013, 1, 2, 4, 4, 5), + arrow.Arrow(2013, 1, 2, 5, 4, 5), + arrow.Arrow(2013, 1, 2, 6, 4, 5), + ] result = list( arrow.Arrow.range( @@ -893,7 +837,7 @@ def test_hour(self): ) ) - self.assertEqual(result, [arrow.Arrow(2013, 1, 2, 3, 4, 5)]) + assert result == [arrow.Arrow(2013, 1, 2, 3, 4, 5)] def test_minute(self): @@ -903,15 +847,12 @@ def test_minute(self): ) ) - self.assertEqual( - result, - [ - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2013, 1, 2, 3, 5, 5), - arrow.Arrow(2013, 1, 2, 3, 6, 5), - arrow.Arrow(2013, 1, 2, 3, 7, 5), - ], - ) + assert result == [ + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2013, 1, 2, 3, 5, 5), + arrow.Arrow(2013, 1, 2, 3, 6, 5), + arrow.Arrow(2013, 1, 2, 3, 7, 5), + ] def test_second(self): @@ -921,15 +862,12 @@ def test_second(self): ) ) - self.assertEqual( - result, - [ - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2013, 1, 2, 3, 4, 6), - arrow.Arrow(2013, 1, 2, 3, 4, 7), - arrow.Arrow(2013, 1, 2, 3, 4, 8), - ], - ) + assert result == [ + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2013, 1, 2, 3, 4, 6), + arrow.Arrow(2013, 1, 2, 3, 4, 7), + arrow.Arrow(2013, 1, 2, 3, 4, 8), + ] def test_arrow(self): @@ -941,15 +879,12 @@ def test_arrow(self): ) ) - self.assertEqual( - result, - [ - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2013, 1, 3, 3, 4, 5), - arrow.Arrow(2013, 1, 4, 3, 4, 5), - arrow.Arrow(2013, 1, 5, 3, 4, 5), - ], - ) + assert result == [ + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2013, 1, 3, 3, 4, 5), + arrow.Arrow(2013, 1, 4, 3, 4, 5), + arrow.Arrow(2013, 1, 5, 3, 4, 5), + ] def test_naive_tz(self): @@ -957,7 +892,8 @@ def test_naive_tz(self): "year", datetime(2013, 1, 2, 3), datetime(2016, 4, 5, 6), "US/Pacific" ) - [self.assertEqual(r.tzinfo, tz.gettz("US/Pacific")) for r in result] + for r in result: + assert r.tzinfo == tz.gettz("US/Pacific") def test_aware_same_tz(self): @@ -967,7 +903,8 @@ def test_aware_same_tz(self): arrow.Arrow(2013, 1, 3, tzinfo=tz.gettz("US/Pacific")), ) - [self.assertEqual(r.tzinfo, tz.gettz("US/Pacific")) for r in result] + for r in result: + assert r.tzinfo == tz.gettz("US/Pacific") def test_aware_different_tz(self): @@ -977,7 +914,8 @@ def test_aware_different_tz(self): datetime(2013, 1, 3, tzinfo=tz.gettz("US/Pacific")), ) - [self.assertEqual(r.tzinfo, tz.gettz("US/Eastern")) for r in result] + for r in result: + assert r.tzinfo == tz.gettz("US/Eastern") def test_aware_tz(self): @@ -988,42 +926,28 @@ def test_aware_tz(self): tz=tz.gettz("US/Central"), ) - [self.assertEqual(r.tzinfo, tz.gettz("US/Central")) for r in result] + for r in result: + assert r.tzinfo == tz.gettz("US/Central") def test_unsupported(self): - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): next(arrow.Arrow.range("abc", datetime.utcnow(), datetime.utcnow())) -class ArrowSpanRangeTests(Chai): +class TestArrowSpanRange: def test_year(self): result = list( arrow.Arrow.span_range("year", datetime(2013, 2, 1), datetime(2016, 3, 31)) ) - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 1, 1), - arrow.Arrow(2013, 12, 31, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2014, 1, 1), - arrow.Arrow(2014, 12, 31, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2015, 1, 1), - arrow.Arrow(2015, 12, 31, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2016, 1, 1), - arrow.Arrow(2016, 12, 31, 23, 59, 59, 999999), - ), - ], - ) + assert result == [ + (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 12, 31, 23, 59, 59, 999999),), + (arrow.Arrow(2014, 1, 1), arrow.Arrow(2014, 12, 31, 23, 59, 59, 999999),), + (arrow.Arrow(2015, 1, 1), arrow.Arrow(2015, 12, 31, 23, 59, 59, 999999),), + (arrow.Arrow(2016, 1, 1), arrow.Arrow(2016, 12, 31, 23, 59, 59, 999999),), + ] def test_quarter(self): @@ -1033,13 +957,10 @@ def test_quarter(self): ) ) - self.assertEqual( - result, - [ - (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 3, 31, 23, 59, 59, 999999)), - (arrow.Arrow(2013, 4, 1), arrow.Arrow(2013, 6, 30, 23, 59, 59, 999999)), - ], - ) + assert result == [ + (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 3, 31, 23, 59, 59, 999999)), + (arrow.Arrow(2013, 4, 1), arrow.Arrow(2013, 6, 30, 23, 59, 59, 999999)), + ] def test_month(self): @@ -1047,15 +968,12 @@ def test_month(self): arrow.Arrow.span_range("month", datetime(2013, 1, 2), datetime(2013, 4, 15)) ) - self.assertEqual( - result, - [ - (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 1, 31, 23, 59, 59, 999999)), - (arrow.Arrow(2013, 2, 1), arrow.Arrow(2013, 2, 28, 23, 59, 59, 999999)), - (arrow.Arrow(2013, 3, 1), arrow.Arrow(2013, 3, 31, 23, 59, 59, 999999)), - (arrow.Arrow(2013, 4, 1), arrow.Arrow(2013, 4, 30, 23, 59, 59, 999999)), - ], - ) + assert result == [ + (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 1, 31, 23, 59, 59, 999999)), + (arrow.Arrow(2013, 2, 1), arrow.Arrow(2013, 2, 28, 23, 59, 59, 999999)), + (arrow.Arrow(2013, 3, 1), arrow.Arrow(2013, 3, 31, 23, 59, 59, 999999)), + (arrow.Arrow(2013, 4, 1), arrow.Arrow(2013, 4, 30, 23, 59, 59, 999999)), + ] def test_week(self): @@ -1063,22 +981,13 @@ def test_week(self): arrow.Arrow.span_range("week", datetime(2013, 2, 2), datetime(2013, 2, 28)) ) - self.assertEqual( - result, - [ - (arrow.Arrow(2013, 1, 28), arrow.Arrow(2013, 2, 3, 23, 59, 59, 999999)), - (arrow.Arrow(2013, 2, 4), arrow.Arrow(2013, 2, 10, 23, 59, 59, 999999)), - ( - arrow.Arrow(2013, 2, 11), - arrow.Arrow(2013, 2, 17, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 2, 18), - arrow.Arrow(2013, 2, 24, 23, 59, 59, 999999), - ), - (arrow.Arrow(2013, 2, 25), arrow.Arrow(2013, 3, 3, 23, 59, 59, 999999)), - ], - ) + assert result == [ + (arrow.Arrow(2013, 1, 28), arrow.Arrow(2013, 2, 3, 23, 59, 59, 999999)), + (arrow.Arrow(2013, 2, 4), arrow.Arrow(2013, 2, 10, 23, 59, 59, 999999)), + (arrow.Arrow(2013, 2, 11), arrow.Arrow(2013, 2, 17, 23, 59, 59, 999999),), + (arrow.Arrow(2013, 2, 18), arrow.Arrow(2013, 2, 24, 23, 59, 59, 999999),), + (arrow.Arrow(2013, 2, 25), arrow.Arrow(2013, 3, 3, 23, 59, 59, 999999)), + ] def test_day(self): @@ -1088,27 +997,12 @@ def test_day(self): ) ) - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 1, 1, 0), - arrow.Arrow(2013, 1, 1, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 2, 0), - arrow.Arrow(2013, 1, 2, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 3, 0), - arrow.Arrow(2013, 1, 3, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 4, 0), - arrow.Arrow(2013, 1, 4, 23, 59, 59, 999999), - ), - ], - ) + assert result == [ + (arrow.Arrow(2013, 1, 1, 0), arrow.Arrow(2013, 1, 1, 23, 59, 59, 999999),), + (arrow.Arrow(2013, 1, 2, 0), arrow.Arrow(2013, 1, 2, 23, 59, 59, 999999),), + (arrow.Arrow(2013, 1, 3, 0), arrow.Arrow(2013, 1, 3, 23, 59, 59, 999999),), + (arrow.Arrow(2013, 1, 4, 0), arrow.Arrow(2013, 1, 4, 23, 59, 59, 999999),), + ] def test_days(self): @@ -1118,27 +1012,12 @@ def test_days(self): ) ) - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 1, 1, 0), - arrow.Arrow(2013, 1, 1, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 2, 0), - arrow.Arrow(2013, 1, 2, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 3, 0), - arrow.Arrow(2013, 1, 3, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 4, 0), - arrow.Arrow(2013, 1, 4, 23, 59, 59, 999999), - ), - ], - ) + assert result == [ + (arrow.Arrow(2013, 1, 1, 0), arrow.Arrow(2013, 1, 1, 23, 59, 59, 999999),), + (arrow.Arrow(2013, 1, 2, 0), arrow.Arrow(2013, 1, 2, 23, 59, 59, 999999),), + (arrow.Arrow(2013, 1, 3, 0), arrow.Arrow(2013, 1, 3, 23, 59, 59, 999999),), + (arrow.Arrow(2013, 1, 4, 0), arrow.Arrow(2013, 1, 4, 23, 59, 59, 999999),), + ] def test_hour(self): @@ -1148,27 +1027,12 @@ def test_hour(self): ) ) - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 1, 1, 0), - arrow.Arrow(2013, 1, 1, 0, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 1), - arrow.Arrow(2013, 1, 1, 1, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 2), - arrow.Arrow(2013, 1, 1, 2, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 3), - arrow.Arrow(2013, 1, 1, 3, 59, 59, 999999), - ), - ], - ) + assert result == [ + (arrow.Arrow(2013, 1, 1, 0), arrow.Arrow(2013, 1, 1, 0, 59, 59, 999999),), + (arrow.Arrow(2013, 1, 1, 1), arrow.Arrow(2013, 1, 1, 1, 59, 59, 999999),), + (arrow.Arrow(2013, 1, 1, 2), arrow.Arrow(2013, 1, 1, 2, 59, 59, 999999),), + (arrow.Arrow(2013, 1, 1, 3), arrow.Arrow(2013, 1, 1, 3, 59, 59, 999999),), + ] result = list( arrow.Arrow.span_range( @@ -1176,10 +1040,9 @@ def test_hour(self): ) ) - self.assertEqual( - result, - [(arrow.Arrow(2013, 1, 1, 3), arrow.Arrow(2013, 1, 1, 3, 59, 59, 999999))], - ) + assert result == [ + (arrow.Arrow(2013, 1, 1, 3), arrow.Arrow(2013, 1, 1, 3, 59, 59, 999999)) + ] def test_minute(self): @@ -1189,27 +1052,12 @@ def test_minute(self): ) ) - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 1, 1, 0, 0), - arrow.Arrow(2013, 1, 1, 0, 0, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 0, 1), - arrow.Arrow(2013, 1, 1, 0, 1, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 0, 2), - arrow.Arrow(2013, 1, 1, 0, 2, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 0, 3), - arrow.Arrow(2013, 1, 1, 0, 3, 59, 999999), - ), - ], - ) + assert result == [ + (arrow.Arrow(2013, 1, 1, 0, 0), arrow.Arrow(2013, 1, 1, 0, 0, 59, 999999),), + (arrow.Arrow(2013, 1, 1, 0, 1), arrow.Arrow(2013, 1, 1, 0, 1, 59, 999999),), + (arrow.Arrow(2013, 1, 1, 0, 2), arrow.Arrow(2013, 1, 1, 0, 2, 59, 999999),), + (arrow.Arrow(2013, 1, 1, 0, 3), arrow.Arrow(2013, 1, 1, 0, 3, 59, 999999),), + ] def test_second(self): @@ -1219,27 +1067,24 @@ def test_second(self): ) ) - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 1, 1, 0, 0, 0), - arrow.Arrow(2013, 1, 1, 0, 0, 0, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 0, 0, 1), - arrow.Arrow(2013, 1, 1, 0, 0, 1, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 0, 0, 2), - arrow.Arrow(2013, 1, 1, 0, 0, 2, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 0, 0, 3), - arrow.Arrow(2013, 1, 1, 0, 0, 3, 999999), - ), - ], - ) + assert result == [ + ( + arrow.Arrow(2013, 1, 1, 0, 0, 0), + arrow.Arrow(2013, 1, 1, 0, 0, 0, 999999), + ), + ( + arrow.Arrow(2013, 1, 1, 0, 0, 1), + arrow.Arrow(2013, 1, 1, 0, 0, 1, 999999), + ), + ( + arrow.Arrow(2013, 1, 1, 0, 0, 2), + arrow.Arrow(2013, 1, 1, 0, 0, 2, 999999), + ), + ( + arrow.Arrow(2013, 1, 1, 0, 0, 3), + arrow.Arrow(2013, 1, 1, 0, 0, 3, 999999), + ), + ] def test_naive_tz(self): @@ -1250,8 +1095,8 @@ def test_naive_tz(self): ) for f, c in result: - self.assertEqual(f.tzinfo, tzinfo) - self.assertEqual(c.tzinfo, tzinfo) + assert f.tzinfo == tzinfo + assert c.tzinfo == tzinfo def test_aware_same_tz(self): @@ -1264,8 +1109,8 @@ def test_aware_same_tz(self): ) for f, c in result: - self.assertEqual(f.tzinfo, tzinfo) - self.assertEqual(c.tzinfo, tzinfo) + assert f.tzinfo == tzinfo + assert c.tzinfo == tzinfo def test_aware_different_tz(self): @@ -1279,8 +1124,8 @@ def test_aware_different_tz(self): ) for f, c in result: - self.assertEqual(f.tzinfo, tzinfo1) - self.assertEqual(c.tzinfo, tzinfo1) + assert f.tzinfo == tzinfo1 + assert c.tzinfo == tzinfo1 def test_aware_tz(self): @@ -1292,8 +1137,8 @@ def test_aware_tz(self): ) for f, c in result: - self.assertEqual(f.tzinfo, tz.gettz("US/Central")) - self.assertEqual(c.tzinfo, tz.gettz("US/Central")) + assert f.tzinfo == tz.gettz("US/Central") + assert c.tzinfo == tz.gettz("US/Central") def test_bounds_param_is_passed(self): @@ -1303,28 +1148,20 @@ def test_bounds_param_is_passed(self): ) ) - self.assertEqual( - result, - [ - (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 4, 1)), - (arrow.Arrow(2013, 4, 1), arrow.Arrow(2013, 7, 1)), - ], - ) + assert result == [ + (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 4, 1)), + (arrow.Arrow(2013, 4, 1), arrow.Arrow(2013, 7, 1)), + ] -class ArrowIntervalTests(Chai): +class TestArrowInterval: def test_incorrect_input(self): - correct = True - try: + with pytest.raises(ValueError): list( arrow.Arrow.interval( "month", datetime(2013, 1, 2), datetime(2013, 4, 15), 0 ) ) - except: # noqa: E722 - correct = False - - self.assertEqual(correct, False) def test_correct(self): result = list( @@ -1333,23 +1170,11 @@ def test_correct(self): ) ) - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 5, 5, 12), - arrow.Arrow(2013, 5, 5, 13, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 5, 5, 14), - arrow.Arrow(2013, 5, 5, 15, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 5, 5, 16), - arrow.Arrow(2013, 5, 5, 17, 59, 59, 999999), - ), - ], - ) + assert result == [ + (arrow.Arrow(2013, 5, 5, 12), arrow.Arrow(2013, 5, 5, 13, 59, 59, 999999),), + (arrow.Arrow(2013, 5, 5, 14), arrow.Arrow(2013, 5, 5, 15, 59, 59, 999999),), + (arrow.Arrow(2013, 5, 5, 16), arrow.Arrow(2013, 5, 5, 17, 59, 59, 999999),), + ] def test_bounds_param_is_passed(self): result = list( @@ -1362,355 +1187,288 @@ def test_bounds_param_is_passed(self): ) ) - self.assertEqual( - result, - [ - (arrow.Arrow(2013, 5, 5, 12), arrow.Arrow(2013, 5, 5, 14)), - (arrow.Arrow(2013, 5, 5, 14), arrow.Arrow(2013, 5, 5, 16)), - (arrow.Arrow(2013, 5, 5, 16), arrow.Arrow(2013, 5, 5, 18)), - ], - ) + assert result == [ + (arrow.Arrow(2013, 5, 5, 12), arrow.Arrow(2013, 5, 5, 14)), + (arrow.Arrow(2013, 5, 5, 14), arrow.Arrow(2013, 5, 5, 16)), + (arrow.Arrow(2013, 5, 5, 16), arrow.Arrow(2013, 5, 5, 18)), + ] -class ArrowSpanTests(Chai): - def setUp(self): - super(ArrowSpanTests, self).setUp() - - self.datetime = datetime(2013, 2, 15, 3, 41, 22, 8923) - self.arrow = arrow.Arrow.fromdatetime(self.datetime) +class TestArrowSpan: + @classmethod + def setup_class(cls): + cls.datetime = datetime(2013, 2, 15, 3, 41, 22, 8923) + cls.arrow = arrow.Arrow.fromdatetime(cls.datetime) def test_span_attribute(self): - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): self.arrow.span("span") def test_span_year(self): floor, ceil = self.arrow.span("year") - self.assertEqual(floor, datetime(2013, 1, 1, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 12, 31, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) + assert floor == datetime(2013, 1, 1, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 12, 31, 23, 59, 59, 999999, tzinfo=tz.tzutc()) def test_span_quarter(self): floor, ceil = self.arrow.span("quarter") - self.assertEqual(floor, datetime(2013, 1, 1, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 3, 31, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) + assert floor == datetime(2013, 1, 1, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 3, 31, 23, 59, 59, 999999, tzinfo=tz.tzutc()) def test_span_quarter_count(self): floor, ceil = self.arrow.span("quarter", 2) - self.assertEqual(floor, datetime(2013, 1, 1, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 6, 30, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) + assert floor == datetime(2013, 1, 1, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 6, 30, 23, 59, 59, 999999, tzinfo=tz.tzutc()) def test_span_year_count(self): floor, ceil = self.arrow.span("year", 2) - self.assertEqual(floor, datetime(2013, 1, 1, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2014, 12, 31, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) + assert floor == datetime(2013, 1, 1, tzinfo=tz.tzutc()) + assert ceil == datetime(2014, 12, 31, 23, 59, 59, 999999, tzinfo=tz.tzutc()) def test_span_month(self): floor, ceil = self.arrow.span("month") - self.assertEqual(floor, datetime(2013, 2, 1, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 28, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) + assert floor == datetime(2013, 2, 1, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 2, 28, 23, 59, 59, 999999, tzinfo=tz.tzutc()) def test_span_week(self): floor, ceil = self.arrow.span("week") - self.assertEqual(floor, datetime(2013, 2, 11, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 17, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) + assert floor == datetime(2013, 2, 11, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 2, 17, 23, 59, 59, 999999, tzinfo=tz.tzutc()) def test_span_day(self): floor, ceil = self.arrow.span("day") - self.assertEqual(floor, datetime(2013, 2, 15, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 15, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) + assert floor == datetime(2013, 2, 15, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 2, 15, 23, 59, 59, 999999, tzinfo=tz.tzutc()) def test_span_hour(self): floor, ceil = self.arrow.span("hour") - self.assertEqual(floor, datetime(2013, 2, 15, 3, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 15, 3, 59, 59, 999999, tzinfo=tz.tzutc()) - ) + assert floor == datetime(2013, 2, 15, 3, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 2, 15, 3, 59, 59, 999999, tzinfo=tz.tzutc()) def test_span_minute(self): floor, ceil = self.arrow.span("minute") - self.assertEqual(floor, datetime(2013, 2, 15, 3, 41, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 15, 3, 41, 59, 999999, tzinfo=tz.tzutc()) - ) + assert floor == datetime(2013, 2, 15, 3, 41, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 2, 15, 3, 41, 59, 999999, tzinfo=tz.tzutc()) def test_span_second(self): floor, ceil = self.arrow.span("second") - self.assertEqual(floor, datetime(2013, 2, 15, 3, 41, 22, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 15, 3, 41, 22, 999999, tzinfo=tz.tzutc()) - ) + assert floor == datetime(2013, 2, 15, 3, 41, 22, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 2, 15, 3, 41, 22, 999999, tzinfo=tz.tzutc()) def test_span_microsecond(self): floor, ceil = self.arrow.span("microsecond") - self.assertEqual( - floor, datetime(2013, 2, 15, 3, 41, 22, 8923, tzinfo=tz.tzutc()) - ) - self.assertEqual( - ceil, datetime(2013, 2, 15, 3, 41, 22, 8923, tzinfo=tz.tzutc()) - ) + assert floor == datetime(2013, 2, 15, 3, 41, 22, 8923, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 2, 15, 3, 41, 22, 8923, tzinfo=tz.tzutc()) def test_floor(self): floor, ceil = self.arrow.span("month") - self.assertEqual(floor, self.arrow.floor("month")) - self.assertEqual(ceil, self.arrow.ceil("month")) + assert floor == self.arrow.floor("month") + assert ceil == self.arrow.ceil("month") def test_span_inclusive_inclusive(self): floor, ceil = self.arrow.span("hour", bounds="[]") - self.assertEqual(floor, datetime(2013, 2, 15, 3, tzinfo=tz.tzutc())) - self.assertEqual(ceil, datetime(2013, 2, 15, 4, tzinfo=tz.tzutc())) + assert floor == datetime(2013, 2, 15, 3, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 2, 15, 4, tzinfo=tz.tzutc()) def test_span_exclusive_inclusive(self): floor, ceil = self.arrow.span("hour", bounds="(]") - self.assertEqual(floor, datetime(2013, 2, 15, 3, 0, 0, 1, tzinfo=tz.tzutc())) - self.assertEqual(ceil, datetime(2013, 2, 15, 4, tzinfo=tz.tzutc())) + assert floor == datetime(2013, 2, 15, 3, 0, 0, 1, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 2, 15, 4, tzinfo=tz.tzutc()) def test_span_exclusive_exclusive(self): floor, ceil = self.arrow.span("hour", bounds="()") - self.assertEqual(floor, datetime(2013, 2, 15, 3, 0, 0, 1, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 15, 3, 59, 59, 999999, tzinfo=tz.tzutc()) - ) + assert floor == datetime(2013, 2, 15, 3, 0, 0, 1, tzinfo=tz.tzutc()) + assert ceil == datetime(2013, 2, 15, 3, 59, 59, 999999, tzinfo=tz.tzutc()) def test_bounds_are_validated(self): - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): floor, ceil = self.arrow.span("hour", bounds="][") -class ArrowHumanizeTests(Chai): - def setUp(self): - super(ArrowHumanizeTests, self).setUp() - - self.datetime = datetime(2013, 1, 1) - self.now = arrow.Arrow.utcnow() +class TestArrowHumanize: + @classmethod + def setup_class(cls): + cls.datetime = datetime(2013, 1, 1) + cls.now = arrow.Arrow.utcnow() def test_granularity(self): - self.assertEqual(self.now.humanize(granularity="second"), "just now") + assert self.now.humanize(granularity="second") == "just now" later1 = self.now.shift(seconds=1) - self.assertEqual(self.now.humanize(later1, granularity="second"), "just now") - self.assertEqual(later1.humanize(self.now, granularity="second"), "just now") - self.assertEqual( - self.now.humanize(later1, granularity="minute"), "0 minutes ago" - ) - self.assertEqual( - later1.humanize(self.now, granularity="minute"), "in 0 minutes" - ) + assert self.now.humanize(later1, granularity="second") == "just now" + assert later1.humanize(self.now, granularity="second") == "just now" + assert self.now.humanize(later1, granularity="minute") == "0 minutes ago" + assert later1.humanize(self.now, granularity="minute") == "in 0 minutes" later100 = self.now.shift(seconds=100) - self.assertEqual( - self.now.humanize(later100, granularity="second"), "100 seconds ago" - ) - self.assertEqual( - later100.humanize(self.now, granularity="second"), "in 100 seconds" - ) - self.assertEqual( - self.now.humanize(later100, granularity="minute"), "a minute ago" - ) - self.assertEqual( - later100.humanize(self.now, granularity="minute"), "in a minute" - ) - self.assertEqual(self.now.humanize(later100, granularity="hour"), "0 hours ago") - self.assertEqual(later100.humanize(self.now, granularity="hour"), "in 0 hours") + assert self.now.humanize(later100, granularity="second") == "100 seconds ago" + assert later100.humanize(self.now, granularity="second") == "in 100 seconds" + assert self.now.humanize(later100, granularity="minute") == "a minute ago" + assert later100.humanize(self.now, granularity="minute") == "in a minute" + assert self.now.humanize(later100, granularity="hour") == "0 hours ago" + assert later100.humanize(self.now, granularity="hour") == "in 0 hours" later4000 = self.now.shift(seconds=4000) - self.assertEqual( - self.now.humanize(later4000, granularity="minute"), "66 minutes ago" - ) - self.assertEqual( - later4000.humanize(self.now, granularity="minute"), "in 66 minutes" - ) - self.assertEqual( - self.now.humanize(later4000, granularity="hour"), "an hour ago" - ) - self.assertEqual(later4000.humanize(self.now, granularity="hour"), "in an hour") - self.assertEqual(self.now.humanize(later4000, granularity="day"), "0 days ago") - self.assertEqual(later4000.humanize(self.now, granularity="day"), "in 0 days") + assert self.now.humanize(later4000, granularity="minute") == "66 minutes ago" + assert later4000.humanize(self.now, granularity="minute") == "in 66 minutes" + assert self.now.humanize(later4000, granularity="hour") == "an hour ago" + assert later4000.humanize(self.now, granularity="hour") == "in an hour" + assert self.now.humanize(later4000, granularity="day") == "0 days ago" + assert later4000.humanize(self.now, granularity="day") == "in 0 days" later105 = self.now.shift(seconds=10 ** 5) - self.assertEqual( - self.now.humanize(later105, granularity="hour"), "27 hours ago" - ) - self.assertEqual(later105.humanize(self.now, granularity="hour"), "in 27 hours") - self.assertEqual(self.now.humanize(later105, granularity="day"), "a day ago") - self.assertEqual(later105.humanize(self.now, granularity="day"), "in a day") - self.assertEqual(self.now.humanize(later105, granularity="week"), "0 weeks ago") - self.assertEqual(later105.humanize(self.now, granularity="week"), "in 0 weeks") - self.assertEqual( - self.now.humanize(later105, granularity="month"), "0 months ago" - ) - self.assertEqual( - later105.humanize(self.now, granularity="month"), "in 0 months" - ) - self.assertEqual( - self.now.humanize(later105, granularity=["month"]), "0 months ago" - ) - self.assertEqual( - later105.humanize(self.now, granularity=["month"]), "in 0 months" - ) + assert self.now.humanize(later105, granularity="hour") == "27 hours ago" + assert later105.humanize(self.now, granularity="hour") == "in 27 hours" + assert self.now.humanize(later105, granularity="day") == "a day ago" + assert later105.humanize(self.now, granularity="day") == "in a day" + assert self.now.humanize(later105, granularity="week") == "0 weeks ago" + assert later105.humanize(self.now, granularity="week") == "in 0 weeks" + assert self.now.humanize(later105, granularity="month") == "0 months ago" + assert later105.humanize(self.now, granularity="month") == "in 0 months" + assert self.now.humanize(later105, granularity=["month"]) == "0 months ago" + assert later105.humanize(self.now, granularity=["month"]) == "in 0 months" later106 = self.now.shift(seconds=3 * 10 ** 6) - self.assertEqual(self.now.humanize(later106, granularity="day"), "34 days ago") - self.assertEqual(later106.humanize(self.now, granularity="day"), "in 34 days") - self.assertEqual(self.now.humanize(later106, granularity="week"), "4 weeks ago") - self.assertEqual(later106.humanize(self.now, granularity="week"), "in 4 weeks") - self.assertEqual( - self.now.humanize(later106, granularity="month"), "a month ago" - ) - self.assertEqual(later106.humanize(self.now, granularity="month"), "in a month") - self.assertEqual(self.now.humanize(later106, granularity="year"), "0 years ago") - self.assertEqual(later106.humanize(self.now, granularity="year"), "in 0 years") + assert self.now.humanize(later106, granularity="day") == "34 days ago" + assert later106.humanize(self.now, granularity="day") == "in 34 days" + assert self.now.humanize(later106, granularity="week") == "4 weeks ago" + assert later106.humanize(self.now, granularity="week") == "in 4 weeks" + assert self.now.humanize(later106, granularity="month") == "a month ago" + assert later106.humanize(self.now, granularity="month") == "in a month" + assert self.now.humanize(later106, granularity="year") == "0 years ago" + assert later106.humanize(self.now, granularity="year") == "in 0 years" later506 = self.now.shift(seconds=50 * 10 ** 6) - self.assertEqual( - self.now.humanize(later506, granularity="week"), "82 weeks ago" - ) - self.assertEqual(later506.humanize(self.now, granularity="week"), "in 82 weeks") - self.assertEqual( - self.now.humanize(later506, granularity="month"), "18 months ago" - ) - self.assertEqual( - later506.humanize(self.now, granularity="month"), "in 18 months" - ) - self.assertEqual(self.now.humanize(later506, granularity="year"), "a year ago") - self.assertEqual(later506.humanize(self.now, granularity="year"), "in a year") + assert self.now.humanize(later506, granularity="week") == "82 weeks ago" + assert later506.humanize(self.now, granularity="week") == "in 82 weeks" + assert self.now.humanize(later506, granularity="month") == "18 months ago" + assert later506.humanize(self.now, granularity="month") == "in 18 months" + assert self.now.humanize(later506, granularity="year") == "a year ago" + assert later506.humanize(self.now, granularity="year") == "in a year" later108 = self.now.shift(seconds=10 ** 8) - self.assertEqual(self.now.humanize(later108, granularity="year"), "3 years ago") - self.assertEqual(later108.humanize(self.now, granularity="year"), "in 3 years") + assert self.now.humanize(later108, granularity="year") == "3 years ago" + assert later108.humanize(self.now, granularity="year") == "in 3 years" later108onlydistance = self.now.shift(seconds=10 ** 8) - self.assertEqual( + assert ( self.now.humanize( later108onlydistance, only_distance=True, granularity="year" - ), - "3 years", + ) + == "3 years" ) - self.assertEqual( + assert ( later108onlydistance.humanize( self.now, only_distance=True, granularity="year" - ), - "3 years", + ) + == "3 years" ) - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): self.now.humanize(later108, granularity="years") def test_multiple_granularity(self): - self.assertEqual(self.now.humanize(granularity="second"), "just now") - self.assertEqual(self.now.humanize(granularity=["second"]), "just now") - self.assertEqual( - self.now.humanize(granularity=["year", "month", "day", "hour", "second"]), - "in 0 years 0 months 0 days 0 hours and 0 seconds", + assert self.now.humanize(granularity="second") == "just now" + assert self.now.humanize(granularity=["second"]) == "just now" + assert ( + self.now.humanize(granularity=["year", "month", "day", "hour", "second"]) + == "in 0 years 0 months 0 days 0 hours and 0 seconds" ) later4000 = self.now.shift(seconds=4000) - self.assertEqual( - later4000.humanize(self.now, granularity=["hour", "minute"]), - "in an hour and 6 minutes", + assert ( + later4000.humanize(self.now, granularity=["hour", "minute"]) + == "in an hour and 6 minutes" ) - self.assertEqual( - self.now.humanize(later4000, granularity=["hour", "minute"]), - "an hour and 6 minutes ago", + assert ( + self.now.humanize(later4000, granularity=["hour", "minute"]) + == "an hour and 6 minutes ago" ) - self.assertEqual( + assert ( later4000.humanize( self.now, granularity=["hour", "minute"], only_distance=True - ), - "an hour and 6 minutes", + ) + == "an hour and 6 minutes" ) - self.assertEqual( - later4000.humanize(self.now, granularity=["day", "hour", "minute"]), - "in 0 days an hour and 6 minutes", + assert ( + later4000.humanize(self.now, granularity=["day", "hour", "minute"]) + == "in 0 days an hour and 6 minutes" ) - self.assertEqual( - self.now.humanize(later4000, granularity=["day", "hour", "minute"]), - "0 days an hour and 6 minutes ago", + assert ( + self.now.humanize(later4000, granularity=["day", "hour", "minute"]) + == "0 days an hour and 6 minutes ago" ) later105 = self.now.shift(seconds=10 ** 5) - self.assertEqual( - self.now.humanize(later105, granularity=["hour", "day", "minute"]), - "a day 3 hours and 46 minutes ago", + assert ( + self.now.humanize(later105, granularity=["hour", "day", "minute"]) + == "a day 3 hours and 46 minutes ago" ) - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): self.now.humanize(later105, granularity=["error", "second"]) later108onlydistance = self.now.shift(seconds=10 ** 8) - self.assertEqual( + assert ( self.now.humanize( later108onlydistance, only_distance=True, granularity=["year"] - ), - "3 years", + ) + == "3 years" ) - self.assertEqual( + assert ( self.now.humanize( later108onlydistance, only_distance=True, granularity=["month", "week"] - ), - "37 months and 4 weeks", + ) + == "37 months and 4 weeks" ) - self.assertEqual( + assert ( self.now.humanize( later108onlydistance, only_distance=True, granularity=["year", "second"] - ), - "3 years and 5327200 seconds", + ) + == "3 years and 5327200 seconds" ) one_min_one_sec_ago = self.now.shift(minutes=-1, seconds=-1) - self.assertEqual( - one_min_one_sec_ago.humanize(self.now, granularity=["minute", "second"]), - "a minute and a second ago", + assert ( + one_min_one_sec_ago.humanize(self.now, granularity=["minute", "second"]) + == "a minute and a second ago" ) one_min_two_secs_ago = self.now.shift(minutes=-1, seconds=-2) - self.assertEqual( - one_min_two_secs_ago.humanize(self.now, granularity=["minute", "second"]), - "a minute and 2 seconds ago", + assert ( + one_min_two_secs_ago.humanize(self.now, granularity=["minute", "second"]) + == "a minute and 2 seconds ago" ) def test_seconds(self): @@ -1718,165 +1476,165 @@ def test_seconds(self): later = self.now.shift(seconds=10) # regression test for issue #727 - self.assertEqual(self.now.humanize(later), "10 seconds ago") - self.assertEqual(later.humanize(self.now), "in 10 seconds") + assert self.now.humanize(later) == "10 seconds ago" + assert later.humanize(self.now) == "in 10 seconds" - self.assertEqual(self.now.humanize(later, only_distance=True), "10 seconds") - self.assertEqual(later.humanize(self.now, only_distance=True), "10 seconds") + assert self.now.humanize(later, only_distance=True) == "10 seconds" + assert later.humanize(self.now, only_distance=True) == "10 seconds" def test_minute(self): later = self.now.shift(minutes=1) - self.assertEqual(self.now.humanize(later), "a minute ago") - self.assertEqual(later.humanize(self.now), "in a minute") + assert self.now.humanize(later) == "a minute ago" + assert later.humanize(self.now) == "in a minute" - self.assertEqual(self.now.humanize(later, only_distance=True), "a minute") - self.assertEqual(later.humanize(self.now, only_distance=True), "a minute") + assert self.now.humanize(later, only_distance=True) == "a minute" + assert later.humanize(self.now, only_distance=True) == "a minute" def test_minutes(self): later = self.now.shift(minutes=2) - self.assertEqual(self.now.humanize(later), "2 minutes ago") - self.assertEqual(later.humanize(self.now), "in 2 minutes") + assert self.now.humanize(later) == "2 minutes ago" + assert later.humanize(self.now) == "in 2 minutes" - self.assertEqual(self.now.humanize(later, only_distance=True), "2 minutes") - self.assertEqual(later.humanize(self.now, only_distance=True), "2 minutes") + assert self.now.humanize(later, only_distance=True) == "2 minutes" + assert later.humanize(self.now, only_distance=True) == "2 minutes" def test_hour(self): later = self.now.shift(hours=1) - self.assertEqual(self.now.humanize(later), "an hour ago") - self.assertEqual(later.humanize(self.now), "in an hour") + assert self.now.humanize(later) == "an hour ago" + assert later.humanize(self.now) == "in an hour" - self.assertEqual(self.now.humanize(later, only_distance=True), "an hour") - self.assertEqual(later.humanize(self.now, only_distance=True), "an hour") + assert self.now.humanize(later, only_distance=True) == "an hour" + assert later.humanize(self.now, only_distance=True) == "an hour" def test_hours(self): later = self.now.shift(hours=2) - self.assertEqual(self.now.humanize(later), "2 hours ago") - self.assertEqual(later.humanize(self.now), "in 2 hours") + assert self.now.humanize(later) == "2 hours ago" + assert later.humanize(self.now) == "in 2 hours" - self.assertEqual(self.now.humanize(later, only_distance=True), "2 hours") - self.assertEqual(later.humanize(self.now, only_distance=True), "2 hours") + assert self.now.humanize(later, only_distance=True) == "2 hours" + assert later.humanize(self.now, only_distance=True) == "2 hours" def test_day(self): later = self.now.shift(days=1) - self.assertEqual(self.now.humanize(later), "a day ago") - self.assertEqual(later.humanize(self.now), "in a day") + assert self.now.humanize(later) == "a day ago" + assert later.humanize(self.now) == "in a day" # regression test for issue #697 less_than_48_hours = self.now.shift( days=1, hours=23, seconds=59, microseconds=999999 ) - self.assertEqual(self.now.humanize(less_than_48_hours), "a day ago") - self.assertEqual(less_than_48_hours.humanize(self.now), "in a day") + assert self.now.humanize(less_than_48_hours) == "a day ago" + assert less_than_48_hours.humanize(self.now) == "in a day" less_than_48_hours_date = less_than_48_hours._datetime.date() - with self.assertRaises(TypeError): + with pytest.raises(TypeError): # humanize other argument does not take raw datetime.date objects self.now.humanize(less_than_48_hours_date) # convert from date to arrow object less_than_48_hours_date = arrow.Arrow.fromdate(less_than_48_hours_date) - self.assertEqual(self.now.humanize(less_than_48_hours_date), "a day ago") - self.assertEqual(less_than_48_hours_date.humanize(self.now), "in a day") + assert self.now.humanize(less_than_48_hours_date) == "a day ago" + assert less_than_48_hours_date.humanize(self.now) == "in a day" - self.assertEqual(self.now.humanize(later, only_distance=True), "a day") - self.assertEqual(later.humanize(self.now, only_distance=True), "a day") + assert self.now.humanize(later, only_distance=True) == "a day" + assert later.humanize(self.now, only_distance=True) == "a day" def test_days(self): later = self.now.shift(days=2) - self.assertEqual(self.now.humanize(later), "2 days ago") - self.assertEqual(later.humanize(self.now), "in 2 days") + assert self.now.humanize(later) == "2 days ago" + assert later.humanize(self.now) == "in 2 days" - self.assertEqual(self.now.humanize(later, only_distance=True), "2 days") - self.assertEqual(later.humanize(self.now, only_distance=True), "2 days") + assert self.now.humanize(later, only_distance=True) == "2 days" + assert later.humanize(self.now, only_distance=True) == "2 days" # Regression tests for humanize bug referenced in issue 541 later = self.now.shift(days=3) - self.assertEqual(later.humanize(), "in 3 days") + assert later.humanize() == "in 3 days" later = self.now.shift(days=3, seconds=1) - self.assertEqual(later.humanize(), "in 3 days") + assert later.humanize() == "in 3 days" later = self.now.shift(days=4) - self.assertEqual(later.humanize(), "in 4 days") + assert later.humanize() == "in 4 days" def test_week(self): later = self.now.shift(weeks=1) - self.assertEqual(self.now.humanize(later), "a week ago") - self.assertEqual(later.humanize(self.now), "in a week") + assert self.now.humanize(later) == "a week ago" + assert later.humanize(self.now) == "in a week" - self.assertEqual(self.now.humanize(later, only_distance=True), "a week") - self.assertEqual(later.humanize(self.now, only_distance=True), "a week") + assert self.now.humanize(later, only_distance=True) == "a week" + assert later.humanize(self.now, only_distance=True) == "a week" def test_weeks(self): later = self.now.shift(weeks=2) - self.assertEqual(self.now.humanize(later), "2 weeks ago") - self.assertEqual(later.humanize(self.now), "in 2 weeks") + assert self.now.humanize(later) == "2 weeks ago" + assert later.humanize(self.now) == "in 2 weeks" - self.assertEqual(self.now.humanize(later, only_distance=True), "2 weeks") - self.assertEqual(later.humanize(self.now, only_distance=True), "2 weeks") + assert self.now.humanize(later, only_distance=True) == "2 weeks" + assert later.humanize(self.now, only_distance=True) == "2 weeks" def test_month(self): later = self.now.shift(months=1) - self.assertEqual(self.now.humanize(later), "a month ago") - self.assertEqual(later.humanize(self.now), "in a month") + assert self.now.humanize(later) == "a month ago" + assert later.humanize(self.now) == "in a month" - self.assertEqual(self.now.humanize(later, only_distance=True), "a month") - self.assertEqual(later.humanize(self.now, only_distance=True), "a month") + assert self.now.humanize(later, only_distance=True) == "a month" + assert later.humanize(self.now, only_distance=True) == "a month" def test_months(self): later = self.now.shift(months=2) earlier = self.now.shift(months=-2) - self.assertEqual(earlier.humanize(self.now), "2 months ago") - self.assertEqual(later.humanize(self.now), "in 2 months") + assert earlier.humanize(self.now) == "2 months ago" + assert later.humanize(self.now) == "in 2 months" - self.assertEqual(self.now.humanize(later, only_distance=True), "2 months") - self.assertEqual(later.humanize(self.now, only_distance=True), "2 months") + assert self.now.humanize(later, only_distance=True) == "2 months" + assert later.humanize(self.now, only_distance=True) == "2 months" def test_year(self): later = self.now.shift(years=1) - self.assertEqual(self.now.humanize(later), "a year ago") - self.assertEqual(later.humanize(self.now), "in a year") + assert self.now.humanize(later) == "a year ago" + assert later.humanize(self.now) == "in a year" - self.assertEqual(self.now.humanize(later, only_distance=True), "a year") - self.assertEqual(later.humanize(self.now, only_distance=True), "a year") + assert self.now.humanize(later, only_distance=True) == "a year" + assert later.humanize(self.now, only_distance=True) == "a year" def test_years(self): later = self.now.shift(years=2) - self.assertEqual(self.now.humanize(later), "2 years ago") - self.assertEqual(later.humanize(self.now), "in 2 years") + assert self.now.humanize(later) == "2 years ago" + assert later.humanize(self.now) == "in 2 years" - self.assertEqual(self.now.humanize(later, only_distance=True), "2 years") - self.assertEqual(later.humanize(self.now, only_distance=True), "2 years") + assert self.now.humanize(later, only_distance=True) == "2 years" + assert later.humanize(self.now, only_distance=True) == "2 years" arw = arrow.Arrow(2014, 7, 2) result = arw.humanize(self.datetime) - self.assertEqual(result, "in 2 years") + assert result == "in 2 years" def test_arrow(self): @@ -1884,7 +1642,7 @@ def test_arrow(self): result = arw.humanize(arrow.Arrow.fromdatetime(self.datetime)) - self.assertEqual(result, "just now") + assert result == "just now" def test_datetime_tzinfo(self): @@ -1892,20 +1650,20 @@ def test_datetime_tzinfo(self): result = arw.humanize(self.datetime.replace(tzinfo=tz.tzutc())) - self.assertEqual(result, "just now") + assert result == "just now" def test_other(self): arw = arrow.Arrow.fromdatetime(self.datetime) - with self.assertRaises(TypeError): + with pytest.raises(TypeError): arw.humanize(object()) def test_invalid_locale(self): arw = arrow.Arrow.fromdatetime(self.datetime) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): arw.humanize(locale="klingon") def test_none(self): @@ -1914,11 +1672,11 @@ def test_none(self): result = arw.humanize() - self.assertEqual(result, "just now") + assert result == "just now" result = arw.humanize(None) - self.assertEqual(result, "just now") + assert result == "just now" def test_untranslated_granularity(self): @@ -1929,15 +1687,14 @@ def test_untranslated_granularity(self): with patch.dict("arrow.locales.EnglishLocale.timeframes"): del arrow.locales.EnglishLocale.timeframes["week"] - with self.assertRaises(ValueError): + with pytest.raises(ValueError): arw.humanize(later, granularity="week") -class ArrowHumanizeTestsWithLocale(Chai): - def setUp(self): - super(ArrowHumanizeTestsWithLocale, self).setUp() - - self.datetime = datetime(2013, 1, 1) +class TestArrowHumanizeTestsWithLocale: + @classmethod + def setup_class(cls): + cls.datetime = datetime(2013, 1, 1) def test_now(self): @@ -1945,14 +1702,14 @@ def test_now(self): result = arw.humanize(self.datetime, locale="ru") - self.assertEqual(result, "сейчас") + assert result == "сейчас" def test_seconds(self): arw = arrow.Arrow(2013, 1, 1, 0, 0, 44) result = arw.humanize(self.datetime, locale="ru") - self.assertEqual(result, "через 44 несколько секунд") + assert result == "через 44 несколько секунд" def test_years(self): @@ -1960,87 +1717,87 @@ def test_years(self): result = arw.humanize(self.datetime, locale="ru") - self.assertEqual(result, "2 года назад") + assert result == "2 года назад" -class ArrowIsBetweenTests(Chai): +class TestArrowIsBetween: def test_start_before_end(self): target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) start = arrow.Arrow.fromdatetime(datetime(2013, 5, 8)) end = arrow.Arrow.fromdatetime(datetime(2013, 5, 5)) result = target.is_between(start, end) - self.assertFalse(result) + assert not result def test_exclusive_exclusive_bounds(self): target = arrow.Arrow.fromdatetime(datetime(2013, 5, 5, 12, 30, 27)) start = arrow.Arrow.fromdatetime(datetime(2013, 5, 5, 12, 30, 10)) end = arrow.Arrow.fromdatetime(datetime(2013, 5, 5, 12, 30, 36)) result = target.is_between(start, end, "()") - self.assertTrue(result) + assert result result = target.is_between(start, end) - self.assertTrue(result) + assert result def test_exclusive_exclusive_bounds_same_date(self): target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) start = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) end = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) result = target.is_between(start, end, "()") - self.assertFalse(result) + assert not result def test_inclusive_exclusive_bounds(self): target = arrow.Arrow.fromdatetime(datetime(2013, 5, 6)) start = arrow.Arrow.fromdatetime(datetime(2013, 5, 4)) end = arrow.Arrow.fromdatetime(datetime(2013, 5, 6)) result = target.is_between(start, end, "[)") - self.assertFalse(result) + assert not result def test_exclusive_inclusive_bounds(self): target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) start = arrow.Arrow.fromdatetime(datetime(2013, 5, 5)) end = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) result = target.is_between(start, end, "(]") - self.assertTrue(result) + assert result def test_inclusive_inclusive_bounds_same_date(self): target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) start = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) end = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) result = target.is_between(start, end, "[]") - self.assertTrue(result) + assert result def test_type_error_exception(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) start = datetime(2013, 5, 5) end = arrow.Arrow.fromdatetime(datetime(2013, 5, 8)) target.is_between(start, end) - with self.assertRaises(TypeError): + with pytest.raises(TypeError): target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) start = arrow.Arrow.fromdatetime(datetime(2013, 5, 5)) end = datetime(2013, 5, 8) target.is_between(start, end) - with self.assertRaises(TypeError): + with pytest.raises(TypeError): target.is_between(None, None) def test_attribute_error_exception(self): target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) start = arrow.Arrow.fromdatetime(datetime(2013, 5, 5)) end = arrow.Arrow.fromdatetime(datetime(2013, 5, 8)) - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): target.is_between(start, end, "][") - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): target.is_between(start, end, "") - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): target.is_between(start, end, "]") - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): target.is_between(start, end, "[") - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): target.is_between(start, end, "hello") -class ArrowUtilTests(Chai): +class TestArrowUtil: def test_get_datetime(self): get_datetime = arrow.Arrow._get_datetime @@ -2049,33 +1806,29 @@ def test_get_datetime(self): dt = datetime.utcnow() timestamp = time.time() - self.assertEqual(get_datetime(arw), arw.datetime) - self.assertEqual(get_datetime(dt), dt) - self.assertEqual( - get_datetime(timestamp), arrow.Arrow.utcfromtimestamp(timestamp).datetime + assert get_datetime(arw) == arw.datetime + assert get_datetime(dt) == dt + assert ( + get_datetime(timestamp) == arrow.Arrow.utcfromtimestamp(timestamp).datetime ) - with self.assertRaises(ValueError) as raise_ctx: + with pytest.raises(ValueError) as raise_ctx: get_datetime("abc") - self.assertFalse("{}" in str(raise_ctx.exception)) + assert "not recognized as a datetime or timestamp" in str(raise_ctx.value) def test_get_tzinfo(self): get_tzinfo = arrow.Arrow._get_tzinfo - with self.assertRaises(ValueError) as raise_ctx: + with pytest.raises(ValueError) as raise_ctx: get_tzinfo("abc") - self.assertFalse("{}" in str(raise_ctx.exception)) + assert "not recognized as a timezone" in str(raise_ctx.value) def test_get_iteration_params(self): - self.assertEqual( - arrow.Arrow._get_iteration_params("end", None), ("end", sys.maxsize) - ) - self.assertEqual( - arrow.Arrow._get_iteration_params(None, 100), (arrow.Arrow.max, 100) - ) - self.assertEqual(arrow.Arrow._get_iteration_params(100, 120), (100, 120)) + assert arrow.Arrow._get_iteration_params("end", None) == ("end", sys.maxsize) + assert arrow.Arrow._get_iteration_params(None, 100) == (arrow.Arrow.max, 100) + assert arrow.Arrow._get_iteration_params(100, 120) == (100, 120) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): arrow.Arrow._get_iteration_params(None, None) diff --git a/tests/arrow_tests.py.bak b/tests/arrow_tests.py.bak new file mode 100644 index 000000000..9d6827660 --- /dev/null +++ b/tests/arrow_tests.py.bak @@ -0,0 +1,2081 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import, unicode_literals + +import calendar +import pickle +import sys +import time +from datetime import date, datetime, timedelta + +import pytz +import simplejson as json +from chai import Chai +from dateutil import tz +from dateutil.relativedelta import FR, MO, SA, SU, TH, TU, WE +from mock import patch + +from arrow import arrow, util + + +def assertDtEqual(dt1, dt2, within=10): + assertEqual(dt1.tzinfo, dt2.tzinfo) # noqa: F821 + assertTrue(abs(util.total_seconds(dt1 - dt2)) < within) # noqa: F821 + + +class ArrowInitTests(Chai): + def test_init_bad_input(self): + + with self.assertRaises(TypeError): + arrow.Arrow(2013) + + with self.assertRaises(TypeError): + arrow.Arrow(2013, 2) + + with self.assertRaises(ValueError): + arrow.Arrow(2013, 2, 2, 12, 30, 45, 9999999) + + def test_init(self): + + result = arrow.Arrow(2013, 2, 2) + self.expected = datetime(2013, 2, 2, tzinfo=tz.tzutc()) + self.assertEqual(result._datetime, self.expected) + + result = arrow.Arrow(2013, 2, 2, 12) + self.expected = datetime(2013, 2, 2, 12, tzinfo=tz.tzutc()) + self.assertEqual(result._datetime, self.expected) + + result = arrow.Arrow(2013, 2, 2, 12, 30) + self.expected = datetime(2013, 2, 2, 12, 30, tzinfo=tz.tzutc()) + self.assertEqual(result._datetime, self.expected) + + result = arrow.Arrow(2013, 2, 2, 12, 30, 45) + self.expected = datetime(2013, 2, 2, 12, 30, 45, tzinfo=tz.tzutc()) + self.assertEqual(result._datetime, self.expected) + + result = arrow.Arrow(2013, 2, 2, 12, 30, 45, 999999) + self.expected = datetime(2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.tzutc()) + self.assertEqual(result._datetime, self.expected) + + result = arrow.Arrow( + 2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.gettz("Europe/Paris") + ) + self.expected = datetime( + 2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.gettz("Europe/Paris") + ) + self.assertEqual(result._datetime, self.expected) + + # regression tests for issue #626 + def test_init_pytz_timezone(self): + + result = arrow.Arrow( + 2013, 2, 2, 12, 30, 45, 999999, tzinfo=pytz.timezone("Europe/Paris") + ) + self.expected = datetime( + 2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.gettz("Europe/Paris") + ) + self.assertEqual(result._datetime, self.expected) + assertDtEqual(result._datetime, self.expected, 1) + + +class ArrowFactoryTests(Chai): + def test_now(self): + + result = arrow.Arrow.now() + + assertDtEqual(result._datetime, datetime.now().replace(tzinfo=tz.tzlocal())) + + def test_utcnow(self): + + result = arrow.Arrow.utcnow() + + assertDtEqual(result._datetime, datetime.utcnow().replace(tzinfo=tz.tzutc())) + + def test_fromtimestamp(self): + + timestamp = time.time() + + result = arrow.Arrow.fromtimestamp(timestamp) + assertDtEqual(result._datetime, datetime.now().replace(tzinfo=tz.tzlocal())) + + result = arrow.Arrow.fromtimestamp(timestamp, tzinfo=tz.gettz("Europe/Paris")) + assertDtEqual( + result._datetime, + datetime.fromtimestamp(timestamp, tz.gettz("Europe/Paris")), + ) + + result = arrow.Arrow.fromtimestamp(timestamp, tzinfo="Europe/Paris") + assertDtEqual( + result._datetime, + datetime.fromtimestamp(timestamp, tz.gettz("Europe/Paris")), + ) + + with self.assertRaises(ValueError): + arrow.Arrow.fromtimestamp("invalid timestamp") + + def test_utcfromtimestamp(self): + + timestamp = time.time() + + result = arrow.Arrow.utcfromtimestamp(timestamp) + assertDtEqual(result._datetime, datetime.utcnow().replace(tzinfo=tz.tzutc())) + + with self.assertRaises(ValueError): + arrow.Arrow.utcfromtimestamp("invalid timestamp") + + def test_fromdatetime(self): + + dt = datetime(2013, 2, 3, 12, 30, 45, 1) + + result = arrow.Arrow.fromdatetime(dt) + + self.assertEqual(result._datetime, dt.replace(tzinfo=tz.tzutc())) + + def test_fromdatetime_dt_tzinfo(self): + + dt = datetime(2013, 2, 3, 12, 30, 45, 1, tzinfo=tz.gettz("US/Pacific")) + + result = arrow.Arrow.fromdatetime(dt) + + self.assertEqual(result._datetime, dt.replace(tzinfo=tz.gettz("US/Pacific"))) + + def test_fromdatetime_tzinfo_arg(self): + + dt = datetime(2013, 2, 3, 12, 30, 45, 1) + + result = arrow.Arrow.fromdatetime(dt, tz.gettz("US/Pacific")) + + self.assertEqual(result._datetime, dt.replace(tzinfo=tz.gettz("US/Pacific"))) + + def test_fromdate(self): + + dt = date(2013, 2, 3) + + result = arrow.Arrow.fromdate(dt, tz.gettz("US/Pacific")) + + self.assertEqual( + result._datetime, datetime(2013, 2, 3, tzinfo=tz.gettz("US/Pacific")) + ) + + def test_strptime(self): + + formatted = datetime(2013, 2, 3, 12, 30, 45).strftime("%Y-%m-%d %H:%M:%S") + + result = arrow.Arrow.strptime(formatted, "%Y-%m-%d %H:%M:%S") + self.assertEqual( + result._datetime, datetime(2013, 2, 3, 12, 30, 45, tzinfo=tz.tzutc()) + ) + + result = arrow.Arrow.strptime( + formatted, "%Y-%m-%d %H:%M:%S", tzinfo=tz.gettz("Europe/Paris") + ) + self.assertEqual( + result._datetime, + datetime(2013, 2, 3, 12, 30, 45, tzinfo=tz.gettz("Europe/Paris")), + ) + + +class ArrowRepresentationTests(Chai): + def setUp(self): + super(ArrowRepresentationTests, self).setUp() + + self.arrow = arrow.Arrow(2013, 2, 3, 12, 30, 45, 1) + + def test_repr(self): + + result = self.arrow.__repr__() + + self.assertEqual( + result, "".format(self.arrow._datetime.isoformat()) + ) + + def test_str(self): + + result = self.arrow.__str__() + + self.assertEqual(result, self.arrow._datetime.isoformat()) + + def test_hash(self): + + result = self.arrow.__hash__() + + self.assertEqual(result, self.arrow._datetime.__hash__()) + + def test_format(self): + + result = "{:YYYY-MM-DD}".format(self.arrow) + + self.assertEqual(result, "2013-02-03") + + def test_bare_format(self): + + result = self.arrow.format() + + self.assertEqual(result, "2013-02-03 12:30:45+00:00") + + def test_format_no_format_string(self): + + result = "{}".format(self.arrow) + + self.assertEqual(result, str(self.arrow)) + + def test_clone(self): + + result = self.arrow.clone() + + self.assertTrue(result is not self.arrow) + self.assertEqual(result._datetime, self.arrow._datetime) + + +class ArrowAttributeTests(Chai): + def setUp(self): + super(ArrowAttributeTests, self).setUp() + + self.arrow = arrow.Arrow(2013, 1, 1) + + def test_getattr_base(self): + + with self.assertRaises(AttributeError): + self.arrow.prop + + def test_getattr_week(self): + + self.assertEqual(self.arrow.week, 1) + + def test_getattr_quarter(self): + # start dates + q1 = arrow.Arrow(2013, 1, 1) + q2 = arrow.Arrow(2013, 4, 1) + q3 = arrow.Arrow(2013, 8, 1) + q4 = arrow.Arrow(2013, 10, 1) + self.assertEqual(q1.quarter, 1) + self.assertEqual(q2.quarter, 2) + self.assertEqual(q3.quarter, 3) + self.assertEqual(q4.quarter, 4) + + # end dates + q1 = arrow.Arrow(2013, 3, 31) + q2 = arrow.Arrow(2013, 6, 30) + q3 = arrow.Arrow(2013, 9, 30) + q4 = arrow.Arrow(2013, 12, 31) + self.assertEqual(q1.quarter, 1) + self.assertEqual(q2.quarter, 2) + self.assertEqual(q3.quarter, 3) + self.assertEqual(q4.quarter, 4) + + def test_getattr_dt_value(self): + + self.assertEqual(self.arrow.year, 2013) + + def test_tzinfo(self): + + self.arrow.tzinfo = tz.gettz("PST") + self.assertEqual(self.arrow.tzinfo, tz.gettz("PST")) + + def test_naive(self): + + self.assertEqual(self.arrow.naive, self.arrow._datetime.replace(tzinfo=None)) + + def test_timestamp(self): + + self.assertEqual( + self.arrow.timestamp, calendar.timegm(self.arrow._datetime.utctimetuple()) + ) + + def test_float_timestamp(self): + + result = self.arrow.float_timestamp - self.arrow.timestamp + + self.assertEqual(result, self.arrow.microsecond) + + +class ArrowComparisonTests(Chai): + def setUp(self): + super(ArrowComparisonTests, self).setUp() + + self.arrow = arrow.Arrow.utcnow() + + def test_eq(self): + + self.assertTrue(self.arrow == self.arrow) + self.assertTrue(self.arrow == self.arrow.datetime) + self.assertFalse(self.arrow == "abc") + + def test_ne(self): + + self.assertFalse(self.arrow != self.arrow) + self.assertFalse(self.arrow != self.arrow.datetime) + self.assertTrue(self.arrow != "abc") + + def test_gt(self): + + arrow_cmp = self.arrow.shift(minutes=1) + + self.assertFalse(self.arrow > self.arrow) + self.assertFalse(self.arrow > self.arrow.datetime) + + with self.assertRaises(TypeError): + self.arrow > "abc" + + self.assertTrue(self.arrow < arrow_cmp) + self.assertTrue(self.arrow < arrow_cmp.datetime) + + def test_ge(self): + + with self.assertRaises(TypeError): + self.arrow >= "abc" + + self.assertTrue(self.arrow >= self.arrow) + self.assertTrue(self.arrow >= self.arrow.datetime) + + def test_lt(self): + + arrow_cmp = self.arrow.shift(minutes=1) + + self.assertFalse(self.arrow < self.arrow) + self.assertFalse(self.arrow < self.arrow.datetime) + + with self.assertRaises(TypeError): + self.arrow < "abc" + + self.assertTrue(self.arrow < arrow_cmp) + self.assertTrue(self.arrow < arrow_cmp.datetime) + + def test_le(self): + + with self.assertRaises(TypeError): + self.arrow <= "abc" + + self.assertTrue(self.arrow <= self.arrow) + self.assertTrue(self.arrow <= self.arrow.datetime) + + +class ArrowMathTests(Chai): + def setUp(self): + super(ArrowMathTests, self).setUp() + + self.arrow = arrow.Arrow(2013, 1, 1) + + def test_add_timedelta(self): + + result = self.arrow.__add__(timedelta(days=1)) + + self.assertEqual(result._datetime, datetime(2013, 1, 2, tzinfo=tz.tzutc())) + + def test_add_other(self): + + with self.assertRaises(TypeError): + self.arrow + 1 + + def test_radd(self): + + result = self.arrow.__radd__(timedelta(days=1)) + + self.assertEqual(result._datetime, datetime(2013, 1, 2, tzinfo=tz.tzutc())) + + def test_sub_timedelta(self): + + result = self.arrow.__sub__(timedelta(days=1)) + + self.assertEqual(result._datetime, datetime(2012, 12, 31, tzinfo=tz.tzutc())) + + def test_sub_datetime(self): + + result = self.arrow.__sub__(datetime(2012, 12, 21, tzinfo=tz.tzutc())) + + self.assertEqual(result, timedelta(days=11)) + + def test_sub_arrow(self): + + result = self.arrow.__sub__(arrow.Arrow(2012, 12, 21, tzinfo=tz.tzutc())) + + self.assertEqual(result, timedelta(days=11)) + + def test_sub_other(self): + + with self.assertRaises(TypeError): + self.arrow - object() + + def test_rsub_datetime(self): + + result = self.arrow.__rsub__(datetime(2012, 12, 21, tzinfo=tz.tzutc())) + + self.assertEqual(result, timedelta(days=-11)) + + def test_rsub_other(self): + + with self.assertRaises(TypeError): + timedelta(days=1) - self.arrow + + +class ArrowDatetimeInterfaceTests(Chai): + def setUp(self): + super(ArrowDatetimeInterfaceTests, self).setUp() + + self.arrow = arrow.Arrow.utcnow() + + def test_date(self): + + result = self.arrow.date() + + self.assertEqual(result, self.arrow._datetime.date()) + + def test_time(self): + + result = self.arrow.time() + + self.assertEqual(result, self.arrow._datetime.time()) + + def test_timetz(self): + + result = self.arrow.timetz() + + self.assertEqual(result, self.arrow._datetime.timetz()) + + def test_astimezone(self): + + other_tz = tz.gettz("US/Pacific") + + result = self.arrow.astimezone(other_tz) + + self.assertEqual(result, self.arrow._datetime.astimezone(other_tz)) + + def test_utcoffset(self): + + result = self.arrow.utcoffset() + + self.assertEqual(result, self.arrow._datetime.utcoffset()) + + def test_dst(self): + + result = self.arrow.dst() + + self.assertEqual(result, self.arrow._datetime.dst()) + + def test_timetuple(self): + + result = self.arrow.timetuple() + + self.assertEqual(result, self.arrow._datetime.timetuple()) + + def test_utctimetuple(self): + + result = self.arrow.utctimetuple() + + self.assertEqual(result, self.arrow._datetime.utctimetuple()) + + def test_toordinal(self): + + result = self.arrow.toordinal() + + self.assertEqual(result, self.arrow._datetime.toordinal()) + + def test_weekday(self): + + result = self.arrow.weekday() + + self.assertEqual(result, self.arrow._datetime.weekday()) + + def test_isoweekday(self): + + result = self.arrow.isoweekday() + + self.assertEqual(result, self.arrow._datetime.isoweekday()) + + def test_isocalendar(self): + + result = self.arrow.isocalendar() + + self.assertEqual(result, self.arrow._datetime.isocalendar()) + + def test_isoformat(self): + + result = self.arrow.isoformat() + + self.assertEqual(result, self.arrow._datetime.isoformat()) + + def test_simplejson(self): + + result = json.dumps({"v": self.arrow.for_json()}, for_json=True) + + self.assertEqual(json.loads(result)["v"], self.arrow._datetime.isoformat()) + + def test_ctime(self): + + result = self.arrow.ctime() + + self.assertEqual(result, self.arrow._datetime.ctime()) + + def test_strftime(self): + + result = self.arrow.strftime("%Y") + + self.assertEqual(result, self.arrow._datetime.strftime("%Y")) + + +class ArrowFalsePositiveDstTests(Chai): + """These tests relate to issues #376 and #551. + The key points in both issues are that arrow will assign a UTC timezone if none is provided and + .to() will change other attributes to be correct whereas .replace() only changes the specified attribute. + + Issue 376 + >>> arrow.get('2016-11-06').to('America/New_York').ceil('day') + < Arrow [2016-11-05T23:59:59.999999-04:00] > + + Issue 551 + >>> just_before = arrow.get('2018-11-04T01:59:59.999999') + >>> just_before + 2018-11-04T01:59:59.999999+00:00 + >>> just_after = just_before.shift(microseconds=1) + >>> just_after + 2018-11-04T02:00:00+00:00 + >>> just_before_eastern = just_before.replace(tzinfo='US/Eastern') + >>> just_before_eastern + 2018-11-04T01:59:59.999999-04:00 + >>> just_after_eastern = just_after.replace(tzinfo='US/Eastern') + >>> just_after_eastern + 2018-11-04T02:00:00-05:00 + """ + + def setUp(self): + + super(ArrowFalsePositiveDstTests, self).setUp() + self.before_1 = arrow.Arrow( + 2016, 11, 6, 3, 59, tzinfo=tz.gettz("America/New_York") + ) + self.before_2 = arrow.Arrow(2016, 11, 6, tzinfo=tz.gettz("America/New_York")) + self.after_1 = arrow.Arrow(2016, 11, 6, 4, tzinfo=tz.gettz("America/New_York")) + self.after_2 = arrow.Arrow( + 2016, 11, 6, 23, 59, tzinfo=tz.gettz("America/New_York") + ) + self.before_3 = arrow.Arrow( + 2018, 11, 4, 3, 59, tzinfo=tz.gettz("America/New_York") + ) + self.before_4 = arrow.Arrow(2018, 11, 4, tzinfo=tz.gettz("America/New_York")) + self.after_3 = arrow.Arrow(2018, 11, 4, 4, tzinfo=tz.gettz("America/New_York")) + self.after_4 = arrow.Arrow( + 2018, 11, 4, 23, 59, tzinfo=tz.gettz("America/New_York") + ) + + def test_dst(self): + + self.assertEqual(self.before_1.day, self.before_2.day) + self.assertEqual(self.after_1.day, self.after_2.day) + self.assertEqual(self.before_3.day, self.before_4.day) + self.assertEqual(self.after_3.day, self.after_4.day) + + +class ArrowConversionTests(Chai): + def test_to(self): + + dt_from = datetime.now() + arrow_from = arrow.Arrow.fromdatetime(dt_from, tz.gettz("US/Pacific")) + + self.expected = dt_from.replace(tzinfo=tz.gettz("US/Pacific")).astimezone( + tz.tzutc() + ) + + self.assertEqual(arrow_from.to("UTC").datetime, self.expected) + self.assertEqual(arrow_from.to(tz.tzutc()).datetime, self.expected) + + +class ArrowPicklingTests(Chai): + def test_pickle_and_unpickle(self): + + dt = arrow.Arrow.utcnow() + + pickled = pickle.dumps(dt) + + unpickled = pickle.loads(pickled) + + self.assertEqual(unpickled, dt) + + +class ArrowReplaceTests(Chai): + def test_not_attr(self): + + with self.assertRaises(AttributeError): + arrow.Arrow.utcnow().replace(abc=1) + + def test_replace(self): + + arw = arrow.Arrow(2013, 5, 5, 12, 30, 45) + + self.assertEqual(arw.replace(year=2012), arrow.Arrow(2012, 5, 5, 12, 30, 45)) + self.assertEqual(arw.replace(month=1), arrow.Arrow(2013, 1, 5, 12, 30, 45)) + self.assertEqual(arw.replace(day=1), arrow.Arrow(2013, 5, 1, 12, 30, 45)) + self.assertEqual(arw.replace(hour=1), arrow.Arrow(2013, 5, 5, 1, 30, 45)) + self.assertEqual(arw.replace(minute=1), arrow.Arrow(2013, 5, 5, 12, 1, 45)) + self.assertEqual(arw.replace(second=1), arrow.Arrow(2013, 5, 5, 12, 30, 1)) + + def test_replace_tzinfo(self): + + arw = arrow.Arrow.utcnow().to("US/Eastern") + + result = arw.replace(tzinfo=tz.gettz("US/Pacific")) + + self.assertEqual(result, arw.datetime.replace(tzinfo=tz.gettz("US/Pacific"))) + + def test_replace_week(self): + + with self.assertRaises(AttributeError): + arrow.Arrow.utcnow().replace(week=1) + + def test_replace_quarter(self): + + with self.assertRaises(AttributeError): + arrow.Arrow.utcnow().replace(quarter=1) + + def test_replace_other_kwargs(self): + + with self.assertRaises(AttributeError): + arrow.utcnow().replace(abc="def") + + +class ArrowShiftTests(Chai): + def test_not_attr(self): + + now = arrow.Arrow.utcnow() + + with self.assertRaises(AttributeError): + now.shift(abc=1) + + with self.assertRaises(AttributeError): + now.shift(week=1) + + def test_shift(self): + + arw = arrow.Arrow(2013, 5, 5, 12, 30, 45) + + self.assertEqual(arw.shift(years=1), arrow.Arrow(2014, 5, 5, 12, 30, 45)) + self.assertEqual(arw.shift(quarters=1), arrow.Arrow(2013, 8, 5, 12, 30, 45)) + self.assertEqual( + arw.shift(quarters=1, months=1), arrow.Arrow(2013, 9, 5, 12, 30, 45) + ) + self.assertEqual(arw.shift(months=1), arrow.Arrow(2013, 6, 5, 12, 30, 45)) + self.assertEqual(arw.shift(weeks=1), arrow.Arrow(2013, 5, 12, 12, 30, 45)) + self.assertEqual(arw.shift(days=1), arrow.Arrow(2013, 5, 6, 12, 30, 45)) + self.assertEqual(arw.shift(hours=1), arrow.Arrow(2013, 5, 5, 13, 30, 45)) + self.assertEqual(arw.shift(minutes=1), arrow.Arrow(2013, 5, 5, 12, 31, 45)) + self.assertEqual(arw.shift(seconds=1), arrow.Arrow(2013, 5, 5, 12, 30, 46)) + self.assertEqual( + arw.shift(microseconds=1), arrow.Arrow(2013, 5, 5, 12, 30, 45, 1) + ) + + # Remember: Python's weekday 0 is Monday + self.assertEqual(arw.shift(weekday=0), arrow.Arrow(2013, 5, 6, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=1), arrow.Arrow(2013, 5, 7, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=2), arrow.Arrow(2013, 5, 8, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=3), arrow.Arrow(2013, 5, 9, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=4), arrow.Arrow(2013, 5, 10, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=5), arrow.Arrow(2013, 5, 11, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=6), arw) + + with self.assertRaises(IndexError): + arw.shift(weekday=7) + + # Use dateutil.relativedelta's convenient day instances + self.assertEqual(arw.shift(weekday=MO), arrow.Arrow(2013, 5, 6, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=MO(0)), arrow.Arrow(2013, 5, 6, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=MO(1)), arrow.Arrow(2013, 5, 6, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=MO(2)), arrow.Arrow(2013, 5, 13, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=TU), arrow.Arrow(2013, 5, 7, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=TU(0)), arrow.Arrow(2013, 5, 7, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=TU(1)), arrow.Arrow(2013, 5, 7, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=TU(2)), arrow.Arrow(2013, 5, 14, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=WE), arrow.Arrow(2013, 5, 8, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=WE(0)), arrow.Arrow(2013, 5, 8, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=WE(1)), arrow.Arrow(2013, 5, 8, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=WE(2)), arrow.Arrow(2013, 5, 15, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=TH), arrow.Arrow(2013, 5, 9, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=TH(0)), arrow.Arrow(2013, 5, 9, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=TH(1)), arrow.Arrow(2013, 5, 9, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=TH(2)), arrow.Arrow(2013, 5, 16, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=FR), arrow.Arrow(2013, 5, 10, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=FR(0)), arrow.Arrow(2013, 5, 10, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=FR(1)), arrow.Arrow(2013, 5, 10, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=FR(2)), arrow.Arrow(2013, 5, 17, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=SA), arrow.Arrow(2013, 5, 11, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=SA(0)), arrow.Arrow(2013, 5, 11, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=SA(1)), arrow.Arrow(2013, 5, 11, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=SA(2)), arrow.Arrow(2013, 5, 18, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=SU), arw) + self.assertEqual(arw.shift(weekday=SU(0)), arw) + self.assertEqual(arw.shift(weekday=SU(1)), arw) + self.assertEqual(arw.shift(weekday=SU(2)), arrow.Arrow(2013, 5, 12, 12, 30, 45)) + + def test_shift_negative(self): + + arw = arrow.Arrow(2013, 5, 5, 12, 30, 45) + + self.assertEqual(arw.shift(years=-1), arrow.Arrow(2012, 5, 5, 12, 30, 45)) + self.assertEqual(arw.shift(quarters=-1), arrow.Arrow(2013, 2, 5, 12, 30, 45)) + self.assertEqual( + arw.shift(quarters=-1, months=-1), arrow.Arrow(2013, 1, 5, 12, 30, 45) + ) + self.assertEqual(arw.shift(months=-1), arrow.Arrow(2013, 4, 5, 12, 30, 45)) + self.assertEqual(arw.shift(weeks=-1), arrow.Arrow(2013, 4, 28, 12, 30, 45)) + self.assertEqual(arw.shift(days=-1), arrow.Arrow(2013, 5, 4, 12, 30, 45)) + self.assertEqual(arw.shift(hours=-1), arrow.Arrow(2013, 5, 5, 11, 30, 45)) + self.assertEqual(arw.shift(minutes=-1), arrow.Arrow(2013, 5, 5, 12, 29, 45)) + self.assertEqual(arw.shift(seconds=-1), arrow.Arrow(2013, 5, 5, 12, 30, 44)) + self.assertEqual( + arw.shift(microseconds=-1), arrow.Arrow(2013, 5, 5, 12, 30, 44, 999999) + ) + + # Not sure how practical these negative weekdays are + self.assertEqual(arw.shift(weekday=-1), arw.shift(weekday=SU)) + self.assertEqual(arw.shift(weekday=-2), arw.shift(weekday=SA)) + self.assertEqual(arw.shift(weekday=-3), arw.shift(weekday=FR)) + self.assertEqual(arw.shift(weekday=-4), arw.shift(weekday=TH)) + self.assertEqual(arw.shift(weekday=-5), arw.shift(weekday=WE)) + self.assertEqual(arw.shift(weekday=-6), arw.shift(weekday=TU)) + self.assertEqual(arw.shift(weekday=-7), arw.shift(weekday=MO)) + + with self.assertRaises(IndexError): + arw.shift(weekday=-8) + + self.assertEqual( + arw.shift(weekday=MO(-1)), arrow.Arrow(2013, 4, 29, 12, 30, 45) + ) + self.assertEqual( + arw.shift(weekday=TU(-1)), arrow.Arrow(2013, 4, 30, 12, 30, 45) + ) + self.assertEqual(arw.shift(weekday=WE(-1)), arrow.Arrow(2013, 5, 1, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=TH(-1)), arrow.Arrow(2013, 5, 2, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=FR(-1)), arrow.Arrow(2013, 5, 3, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=SA(-1)), arrow.Arrow(2013, 5, 4, 12, 30, 45)) + self.assertEqual(arw.shift(weekday=SU(-1)), arw) + self.assertEqual( + arw.shift(weekday=SU(-2)), arrow.Arrow(2013, 4, 28, 12, 30, 45) + ) + + def test_shift_quarters_bug(self): + + arw = arrow.Arrow(2013, 5, 5, 12, 30, 45) + + # The value of the last-read argument was used instead of the ``quarters`` argument. + # Recall that the keyword argument dict, like all dicts, is unordered, so only certain + # combinations of arguments would exhibit this. + self.assertEqual( + arw.shift(quarters=0, years=1), arrow.Arrow(2014, 5, 5, 12, 30, 45) + ) + self.assertEqual( + arw.shift(quarters=0, months=1), arrow.Arrow(2013, 6, 5, 12, 30, 45) + ) + self.assertEqual( + arw.shift(quarters=0, weeks=1), arrow.Arrow(2013, 5, 12, 12, 30, 45) + ) + self.assertEqual( + arw.shift(quarters=0, days=1), arrow.Arrow(2013, 5, 6, 12, 30, 45) + ) + self.assertEqual( + arw.shift(quarters=0, hours=1), arrow.Arrow(2013, 5, 5, 13, 30, 45) + ) + self.assertEqual( + arw.shift(quarters=0, minutes=1), arrow.Arrow(2013, 5, 5, 12, 31, 45) + ) + self.assertEqual( + arw.shift(quarters=0, seconds=1), arrow.Arrow(2013, 5, 5, 12, 30, 46) + ) + self.assertEqual( + arw.shift(quarters=0, microseconds=1), + arrow.Arrow(2013, 5, 5, 12, 30, 45, 1), + ) + + +class ArrowRangeTests(Chai): + def test_year(self): + + result = list( + arrow.Arrow.range( + "year", datetime(2013, 1, 2, 3, 4, 5), datetime(2016, 4, 5, 6, 7, 8) + ) + ) + + self.assertEqual( + result, + [ + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2014, 1, 2, 3, 4, 5), + arrow.Arrow(2015, 1, 2, 3, 4, 5), + arrow.Arrow(2016, 1, 2, 3, 4, 5), + ], + ) + + def test_quarter(self): + + result = list( + arrow.Arrow.range( + "quarter", datetime(2013, 2, 3, 4, 5, 6), datetime(2013, 5, 6, 7, 8, 9) + ) + ) + + self.assertEqual( + result, [arrow.Arrow(2013, 2, 3, 4, 5, 6), arrow.Arrow(2013, 5, 3, 4, 5, 6)] + ) + + def test_month(self): + + result = list( + arrow.Arrow.range( + "month", datetime(2013, 2, 3, 4, 5, 6), datetime(2013, 5, 6, 7, 8, 9) + ) + ) + + self.assertEqual( + result, + [ + arrow.Arrow(2013, 2, 3, 4, 5, 6), + arrow.Arrow(2013, 3, 3, 4, 5, 6), + arrow.Arrow(2013, 4, 3, 4, 5, 6), + arrow.Arrow(2013, 5, 3, 4, 5, 6), + ], + ) + + def test_week(self): + + result = list( + arrow.Arrow.range( + "week", datetime(2013, 9, 1, 2, 3, 4), datetime(2013, 10, 1, 2, 3, 4) + ) + ) + + self.assertEqual( + result, + [ + arrow.Arrow(2013, 9, 1, 2, 3, 4), + arrow.Arrow(2013, 9, 8, 2, 3, 4), + arrow.Arrow(2013, 9, 15, 2, 3, 4), + arrow.Arrow(2013, 9, 22, 2, 3, 4), + arrow.Arrow(2013, 9, 29, 2, 3, 4), + ], + ) + + def test_day(self): + + result = list( + arrow.Arrow.range( + "day", datetime(2013, 1, 2, 3, 4, 5), datetime(2013, 1, 5, 6, 7, 8) + ) + ) + + self.assertEqual( + result, + [ + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2013, 1, 3, 3, 4, 5), + arrow.Arrow(2013, 1, 4, 3, 4, 5), + arrow.Arrow(2013, 1, 5, 3, 4, 5), + ], + ) + + def test_hour(self): + + result = list( + arrow.Arrow.range( + "hour", datetime(2013, 1, 2, 3, 4, 5), datetime(2013, 1, 2, 6, 7, 8) + ) + ) + + self.assertEqual( + result, + [ + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2013, 1, 2, 4, 4, 5), + arrow.Arrow(2013, 1, 2, 5, 4, 5), + arrow.Arrow(2013, 1, 2, 6, 4, 5), + ], + ) + + result = list( + arrow.Arrow.range( + "hour", datetime(2013, 1, 2, 3, 4, 5), datetime(2013, 1, 2, 3, 4, 5) + ) + ) + + self.assertEqual(result, [arrow.Arrow(2013, 1, 2, 3, 4, 5)]) + + def test_minute(self): + + result = list( + arrow.Arrow.range( + "minute", datetime(2013, 1, 2, 3, 4, 5), datetime(2013, 1, 2, 3, 7, 8) + ) + ) + + self.assertEqual( + result, + [ + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2013, 1, 2, 3, 5, 5), + arrow.Arrow(2013, 1, 2, 3, 6, 5), + arrow.Arrow(2013, 1, 2, 3, 7, 5), + ], + ) + + def test_second(self): + + result = list( + arrow.Arrow.range( + "second", datetime(2013, 1, 2, 3, 4, 5), datetime(2013, 1, 2, 3, 4, 8) + ) + ) + + self.assertEqual( + result, + [ + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2013, 1, 2, 3, 4, 6), + arrow.Arrow(2013, 1, 2, 3, 4, 7), + arrow.Arrow(2013, 1, 2, 3, 4, 8), + ], + ) + + def test_arrow(self): + + result = list( + arrow.Arrow.range( + "day", + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2013, 1, 5, 6, 7, 8), + ) + ) + + self.assertEqual( + result, + [ + arrow.Arrow(2013, 1, 2, 3, 4, 5), + arrow.Arrow(2013, 1, 3, 3, 4, 5), + arrow.Arrow(2013, 1, 4, 3, 4, 5), + arrow.Arrow(2013, 1, 5, 3, 4, 5), + ], + ) + + def test_naive_tz(self): + + result = arrow.Arrow.range( + "year", datetime(2013, 1, 2, 3), datetime(2016, 4, 5, 6), "US/Pacific" + ) + + [self.assertEqual(r.tzinfo, tz.gettz("US/Pacific")) for r in result] + + def test_aware_same_tz(self): + + result = arrow.Arrow.range( + "day", + arrow.Arrow(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")), + arrow.Arrow(2013, 1, 3, tzinfo=tz.gettz("US/Pacific")), + ) + + [self.assertEqual(r.tzinfo, tz.gettz("US/Pacific")) for r in result] + + def test_aware_different_tz(self): + + result = arrow.Arrow.range( + "day", + datetime(2013, 1, 1, tzinfo=tz.gettz("US/Eastern")), + datetime(2013, 1, 3, tzinfo=tz.gettz("US/Pacific")), + ) + + [self.assertEqual(r.tzinfo, tz.gettz("US/Eastern")) for r in result] + + def test_aware_tz(self): + + result = arrow.Arrow.range( + "day", + datetime(2013, 1, 1, tzinfo=tz.gettz("US/Eastern")), + datetime(2013, 1, 3, tzinfo=tz.gettz("US/Pacific")), + tz=tz.gettz("US/Central"), + ) + + [self.assertEqual(r.tzinfo, tz.gettz("US/Central")) for r in result] + + def test_unsupported(self): + + with self.assertRaises(AttributeError): + next(arrow.Arrow.range("abc", datetime.utcnow(), datetime.utcnow())) + + +class ArrowSpanRangeTests(Chai): + def test_year(self): + + result = list( + arrow.Arrow.span_range("year", datetime(2013, 2, 1), datetime(2016, 3, 31)) + ) + + self.assertEqual( + result, + [ + ( + arrow.Arrow(2013, 1, 1), + arrow.Arrow(2013, 12, 31, 23, 59, 59, 999999), + ), + ( + arrow.Arrow(2014, 1, 1), + arrow.Arrow(2014, 12, 31, 23, 59, 59, 999999), + ), + ( + arrow.Arrow(2015, 1, 1), + arrow.Arrow(2015, 12, 31, 23, 59, 59, 999999), + ), + ( + arrow.Arrow(2016, 1, 1), + arrow.Arrow(2016, 12, 31, 23, 59, 59, 999999), + ), + ], + ) + + def test_quarter(self): + + result = list( + arrow.Arrow.span_range( + "quarter", datetime(2013, 2, 2), datetime(2013, 5, 15) + ) + ) + + self.assertEqual( + result, + [ + (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 3, 31, 23, 59, 59, 999999)), + (arrow.Arrow(2013, 4, 1), arrow.Arrow(2013, 6, 30, 23, 59, 59, 999999)), + ], + ) + + def test_month(self): + + result = list( + arrow.Arrow.span_range("month", datetime(2013, 1, 2), datetime(2013, 4, 15)) + ) + + self.assertEqual( + result, + [ + (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 1, 31, 23, 59, 59, 999999)), + (arrow.Arrow(2013, 2, 1), arrow.Arrow(2013, 2, 28, 23, 59, 59, 999999)), + (arrow.Arrow(2013, 3, 1), arrow.Arrow(2013, 3, 31, 23, 59, 59, 999999)), + (arrow.Arrow(2013, 4, 1), arrow.Arrow(2013, 4, 30, 23, 59, 59, 999999)), + ], + ) + + def test_week(self): + + result = list( + arrow.Arrow.span_range("week", datetime(2013, 2, 2), datetime(2013, 2, 28)) + ) + + self.assertEqual( + result, + [ + (arrow.Arrow(2013, 1, 28), arrow.Arrow(2013, 2, 3, 23, 59, 59, 999999)), + (arrow.Arrow(2013, 2, 4), arrow.Arrow(2013, 2, 10, 23, 59, 59, 999999)), + ( + arrow.Arrow(2013, 2, 11), + arrow.Arrow(2013, 2, 17, 23, 59, 59, 999999), + ), + ( + arrow.Arrow(2013, 2, 18), + arrow.Arrow(2013, 2, 24, 23, 59, 59, 999999), + ), + (arrow.Arrow(2013, 2, 25), arrow.Arrow(2013, 3, 3, 23, 59, 59, 999999)), + ], + ) + + def test_day(self): + + result = list( + arrow.Arrow.span_range( + "day", datetime(2013, 1, 1, 12), datetime(2013, 1, 4, 12) + ) + ) + + self.assertEqual( + result, + [ + ( + arrow.Arrow(2013, 1, 1, 0), + arrow.Arrow(2013, 1, 1, 23, 59, 59, 999999), + ), + ( + arrow.Arrow(2013, 1, 2, 0), + arrow.Arrow(2013, 1, 2, 23, 59, 59, 999999), + ), + ( + arrow.Arrow(2013, 1, 3, 0), + arrow.Arrow(2013, 1, 3, 23, 59, 59, 999999), + ), + ( + arrow.Arrow(2013, 1, 4, 0), + arrow.Arrow(2013, 1, 4, 23, 59, 59, 999999), + ), + ], + ) + + def test_days(self): + + result = list( + arrow.Arrow.span_range( + "days", datetime(2013, 1, 1, 12), datetime(2013, 1, 4, 12) + ) + ) + + self.assertEqual( + result, + [ + ( + arrow.Arrow(2013, 1, 1, 0), + arrow.Arrow(2013, 1, 1, 23, 59, 59, 999999), + ), + ( + arrow.Arrow(2013, 1, 2, 0), + arrow.Arrow(2013, 1, 2, 23, 59, 59, 999999), + ), + ( + arrow.Arrow(2013, 1, 3, 0), + arrow.Arrow(2013, 1, 3, 23, 59, 59, 999999), + ), + ( + arrow.Arrow(2013, 1, 4, 0), + arrow.Arrow(2013, 1, 4, 23, 59, 59, 999999), + ), + ], + ) + + def test_hour(self): + + result = list( + arrow.Arrow.span_range( + "hour", datetime(2013, 1, 1, 0, 30), datetime(2013, 1, 1, 3, 30) + ) + ) + + self.assertEqual( + result, + [ + ( + arrow.Arrow(2013, 1, 1, 0), + arrow.Arrow(2013, 1, 1, 0, 59, 59, 999999), + ), + ( + arrow.Arrow(2013, 1, 1, 1), + arrow.Arrow(2013, 1, 1, 1, 59, 59, 999999), + ), + ( + arrow.Arrow(2013, 1, 1, 2), + arrow.Arrow(2013, 1, 1, 2, 59, 59, 999999), + ), + ( + arrow.Arrow(2013, 1, 1, 3), + arrow.Arrow(2013, 1, 1, 3, 59, 59, 999999), + ), + ], + ) + + result = list( + arrow.Arrow.span_range( + "hour", datetime(2013, 1, 1, 3, 30), datetime(2013, 1, 1, 3, 30) + ) + ) + + self.assertEqual( + result, + [(arrow.Arrow(2013, 1, 1, 3), arrow.Arrow(2013, 1, 1, 3, 59, 59, 999999))], + ) + + def test_minute(self): + + result = list( + arrow.Arrow.span_range( + "minute", datetime(2013, 1, 1, 0, 0, 30), datetime(2013, 1, 1, 0, 3, 30) + ) + ) + + self.assertEqual( + result, + [ + ( + arrow.Arrow(2013, 1, 1, 0, 0), + arrow.Arrow(2013, 1, 1, 0, 0, 59, 999999), + ), + ( + arrow.Arrow(2013, 1, 1, 0, 1), + arrow.Arrow(2013, 1, 1, 0, 1, 59, 999999), + ), + ( + arrow.Arrow(2013, 1, 1, 0, 2), + arrow.Arrow(2013, 1, 1, 0, 2, 59, 999999), + ), + ( + arrow.Arrow(2013, 1, 1, 0, 3), + arrow.Arrow(2013, 1, 1, 0, 3, 59, 999999), + ), + ], + ) + + def test_second(self): + + result = list( + arrow.Arrow.span_range( + "second", datetime(2013, 1, 1), datetime(2013, 1, 1, 0, 0, 3) + ) + ) + + self.assertEqual( + result, + [ + ( + arrow.Arrow(2013, 1, 1, 0, 0, 0), + arrow.Arrow(2013, 1, 1, 0, 0, 0, 999999), + ), + ( + arrow.Arrow(2013, 1, 1, 0, 0, 1), + arrow.Arrow(2013, 1, 1, 0, 0, 1, 999999), + ), + ( + arrow.Arrow(2013, 1, 1, 0, 0, 2), + arrow.Arrow(2013, 1, 1, 0, 0, 2, 999999), + ), + ( + arrow.Arrow(2013, 1, 1, 0, 0, 3), + arrow.Arrow(2013, 1, 1, 0, 0, 3, 999999), + ), + ], + ) + + def test_naive_tz(self): + + tzinfo = tz.gettz("US/Pacific") + + result = arrow.Arrow.span_range( + "hour", datetime(2013, 1, 1, 0), datetime(2013, 1, 1, 3, 59), "US/Pacific" + ) + + for f, c in result: + self.assertEqual(f.tzinfo, tzinfo) + self.assertEqual(c.tzinfo, tzinfo) + + def test_aware_same_tz(self): + + tzinfo = tz.gettz("US/Pacific") + + result = arrow.Arrow.span_range( + "hour", + datetime(2013, 1, 1, 0, tzinfo=tzinfo), + datetime(2013, 1, 1, 2, 59, tzinfo=tzinfo), + ) + + for f, c in result: + self.assertEqual(f.tzinfo, tzinfo) + self.assertEqual(c.tzinfo, tzinfo) + + def test_aware_different_tz(self): + + tzinfo1 = tz.gettz("US/Pacific") + tzinfo2 = tz.gettz("US/Eastern") + + result = arrow.Arrow.span_range( + "hour", + datetime(2013, 1, 1, 0, tzinfo=tzinfo1), + datetime(2013, 1, 1, 2, 59, tzinfo=tzinfo2), + ) + + for f, c in result: + self.assertEqual(f.tzinfo, tzinfo1) + self.assertEqual(c.tzinfo, tzinfo1) + + def test_aware_tz(self): + + result = arrow.Arrow.span_range( + "hour", + datetime(2013, 1, 1, 0, tzinfo=tz.gettz("US/Eastern")), + datetime(2013, 1, 1, 2, 59, tzinfo=tz.gettz("US/Eastern")), + tz="US/Central", + ) + + for f, c in result: + self.assertEqual(f.tzinfo, tz.gettz("US/Central")) + self.assertEqual(c.tzinfo, tz.gettz("US/Central")) + + def test_bounds_param_is_passed(self): + + result = list( + arrow.Arrow.span_range( + "quarter", datetime(2013, 2, 2), datetime(2013, 5, 15), bounds="[]" + ) + ) + + self.assertEqual( + result, + [ + (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 4, 1)), + (arrow.Arrow(2013, 4, 1), arrow.Arrow(2013, 7, 1)), + ], + ) + + +class ArrowIntervalTests(Chai): + def test_incorrect_input(self): + correct = True + try: + list( + arrow.Arrow.interval( + "month", datetime(2013, 1, 2), datetime(2013, 4, 15), 0 + ) + ) + except: # noqa: E722 + correct = False + + self.assertEqual(correct, False) + + def test_correct(self): + result = list( + arrow.Arrow.interval( + "hour", datetime(2013, 5, 5, 12, 30), datetime(2013, 5, 5, 17, 15), 2 + ) + ) + + self.assertEqual( + result, + [ + ( + arrow.Arrow(2013, 5, 5, 12), + arrow.Arrow(2013, 5, 5, 13, 59, 59, 999999), + ), + ( + arrow.Arrow(2013, 5, 5, 14), + arrow.Arrow(2013, 5, 5, 15, 59, 59, 999999), + ), + ( + arrow.Arrow(2013, 5, 5, 16), + arrow.Arrow(2013, 5, 5, 17, 59, 59, 999999), + ), + ], + ) + + def test_bounds_param_is_passed(self): + result = list( + arrow.Arrow.interval( + "hour", + datetime(2013, 5, 5, 12, 30), + datetime(2013, 5, 5, 17, 15), + 2, + bounds="[]", + ) + ) + + self.assertEqual( + result, + [ + (arrow.Arrow(2013, 5, 5, 12), arrow.Arrow(2013, 5, 5, 14)), + (arrow.Arrow(2013, 5, 5, 14), arrow.Arrow(2013, 5, 5, 16)), + (arrow.Arrow(2013, 5, 5, 16), arrow.Arrow(2013, 5, 5, 18)), + ], + ) + + +class ArrowSpanTests(Chai): + def setUp(self): + super(ArrowSpanTests, self).setUp() + + self.datetime = datetime(2013, 2, 15, 3, 41, 22, 8923) + self.arrow = arrow.Arrow.fromdatetime(self.datetime) + + def test_span_attribute(self): + + with self.assertRaises(AttributeError): + self.arrow.span("span") + + def test_span_year(self): + + floor, ceil = self.arrow.span("year") + + self.assertEqual(floor, datetime(2013, 1, 1, tzinfo=tz.tzutc())) + self.assertEqual( + ceil, datetime(2013, 12, 31, 23, 59, 59, 999999, tzinfo=tz.tzutc()) + ) + + def test_span_quarter(self): + + floor, ceil = self.arrow.span("quarter") + + self.assertEqual(floor, datetime(2013, 1, 1, tzinfo=tz.tzutc())) + self.assertEqual( + ceil, datetime(2013, 3, 31, 23, 59, 59, 999999, tzinfo=tz.tzutc()) + ) + + def test_span_quarter_count(self): + + floor, ceil = self.arrow.span("quarter", 2) + + self.assertEqual(floor, datetime(2013, 1, 1, tzinfo=tz.tzutc())) + self.assertEqual( + ceil, datetime(2013, 6, 30, 23, 59, 59, 999999, tzinfo=tz.tzutc()) + ) + + def test_span_year_count(self): + + floor, ceil = self.arrow.span("year", 2) + + self.assertEqual(floor, datetime(2013, 1, 1, tzinfo=tz.tzutc())) + self.assertEqual( + ceil, datetime(2014, 12, 31, 23, 59, 59, 999999, tzinfo=tz.tzutc()) + ) + + def test_span_month(self): + + floor, ceil = self.arrow.span("month") + + self.assertEqual(floor, datetime(2013, 2, 1, tzinfo=tz.tzutc())) + self.assertEqual( + ceil, datetime(2013, 2, 28, 23, 59, 59, 999999, tzinfo=tz.tzutc()) + ) + + def test_span_week(self): + + floor, ceil = self.arrow.span("week") + + self.assertEqual(floor, datetime(2013, 2, 11, tzinfo=tz.tzutc())) + self.assertEqual( + ceil, datetime(2013, 2, 17, 23, 59, 59, 999999, tzinfo=tz.tzutc()) + ) + + def test_span_day(self): + + floor, ceil = self.arrow.span("day") + + self.assertEqual(floor, datetime(2013, 2, 15, tzinfo=tz.tzutc())) + self.assertEqual( + ceil, datetime(2013, 2, 15, 23, 59, 59, 999999, tzinfo=tz.tzutc()) + ) + + def test_span_hour(self): + + floor, ceil = self.arrow.span("hour") + + self.assertEqual(floor, datetime(2013, 2, 15, 3, tzinfo=tz.tzutc())) + self.assertEqual( + ceil, datetime(2013, 2, 15, 3, 59, 59, 999999, tzinfo=tz.tzutc()) + ) + + def test_span_minute(self): + + floor, ceil = self.arrow.span("minute") + + self.assertEqual(floor, datetime(2013, 2, 15, 3, 41, tzinfo=tz.tzutc())) + self.assertEqual( + ceil, datetime(2013, 2, 15, 3, 41, 59, 999999, tzinfo=tz.tzutc()) + ) + + def test_span_second(self): + + floor, ceil = self.arrow.span("second") + + self.assertEqual(floor, datetime(2013, 2, 15, 3, 41, 22, tzinfo=tz.tzutc())) + self.assertEqual( + ceil, datetime(2013, 2, 15, 3, 41, 22, 999999, tzinfo=tz.tzutc()) + ) + + def test_span_microsecond(self): + + floor, ceil = self.arrow.span("microsecond") + + self.assertEqual( + floor, datetime(2013, 2, 15, 3, 41, 22, 8923, tzinfo=tz.tzutc()) + ) + self.assertEqual( + ceil, datetime(2013, 2, 15, 3, 41, 22, 8923, tzinfo=tz.tzutc()) + ) + + def test_floor(self): + + floor, ceil = self.arrow.span("month") + + self.assertEqual(floor, self.arrow.floor("month")) + self.assertEqual(ceil, self.arrow.ceil("month")) + + def test_span_inclusive_inclusive(self): + + floor, ceil = self.arrow.span("hour", bounds="[]") + + self.assertEqual(floor, datetime(2013, 2, 15, 3, tzinfo=tz.tzutc())) + self.assertEqual(ceil, datetime(2013, 2, 15, 4, tzinfo=tz.tzutc())) + + def test_span_exclusive_inclusive(self): + + floor, ceil = self.arrow.span("hour", bounds="(]") + + self.assertEqual(floor, datetime(2013, 2, 15, 3, 0, 0, 1, tzinfo=tz.tzutc())) + self.assertEqual(ceil, datetime(2013, 2, 15, 4, tzinfo=tz.tzutc())) + + def test_span_exclusive_exclusive(self): + + floor, ceil = self.arrow.span("hour", bounds="()") + + self.assertEqual(floor, datetime(2013, 2, 15, 3, 0, 0, 1, tzinfo=tz.tzutc())) + self.assertEqual( + ceil, datetime(2013, 2, 15, 3, 59, 59, 999999, tzinfo=tz.tzutc()) + ) + + def test_bounds_are_validated(self): + + with self.assertRaises(AttributeError): + floor, ceil = self.arrow.span("hour", bounds="][") + + +class ArrowHumanizeTests(Chai): + def setUp(self): + super(ArrowHumanizeTests, self).setUp() + + self.datetime = datetime(2013, 1, 1) + self.now = arrow.Arrow.utcnow() + + def test_granularity(self): + + self.assertEqual(self.now.humanize(granularity="second"), "just now") + + later1 = self.now.shift(seconds=1) + self.assertEqual(self.now.humanize(later1, granularity="second"), "just now") + self.assertEqual(later1.humanize(self.now, granularity="second"), "just now") + self.assertEqual( + self.now.humanize(later1, granularity="minute"), "0 minutes ago" + ) + self.assertEqual( + later1.humanize(self.now, granularity="minute"), "in 0 minutes" + ) + + later100 = self.now.shift(seconds=100) + self.assertEqual( + self.now.humanize(later100, granularity="second"), "100 seconds ago" + ) + self.assertEqual( + later100.humanize(self.now, granularity="second"), "in 100 seconds" + ) + self.assertEqual( + self.now.humanize(later100, granularity="minute"), "a minute ago" + ) + self.assertEqual( + later100.humanize(self.now, granularity="minute"), "in a minute" + ) + self.assertEqual(self.now.humanize(later100, granularity="hour"), "0 hours ago") + self.assertEqual(later100.humanize(self.now, granularity="hour"), "in 0 hours") + + later4000 = self.now.shift(seconds=4000) + self.assertEqual( + self.now.humanize(later4000, granularity="minute"), "66 minutes ago" + ) + self.assertEqual( + later4000.humanize(self.now, granularity="minute"), "in 66 minutes" + ) + self.assertEqual( + self.now.humanize(later4000, granularity="hour"), "an hour ago" + ) + self.assertEqual(later4000.humanize(self.now, granularity="hour"), "in an hour") + self.assertEqual(self.now.humanize(later4000, granularity="day"), "0 days ago") + self.assertEqual(later4000.humanize(self.now, granularity="day"), "in 0 days") + + later105 = self.now.shift(seconds=10 ** 5) + self.assertEqual( + self.now.humanize(later105, granularity="hour"), "27 hours ago" + ) + self.assertEqual(later105.humanize(self.now, granularity="hour"), "in 27 hours") + self.assertEqual(self.now.humanize(later105, granularity="day"), "a day ago") + self.assertEqual(later105.humanize(self.now, granularity="day"), "in a day") + self.assertEqual(self.now.humanize(later105, granularity="week"), "0 weeks ago") + self.assertEqual(later105.humanize(self.now, granularity="week"), "in 0 weeks") + self.assertEqual( + self.now.humanize(later105, granularity="month"), "0 months ago" + ) + self.assertEqual( + later105.humanize(self.now, granularity="month"), "in 0 months" + ) + self.assertEqual( + self.now.humanize(later105, granularity=["month"]), "0 months ago" + ) + self.assertEqual( + later105.humanize(self.now, granularity=["month"]), "in 0 months" + ) + + later106 = self.now.shift(seconds=3 * 10 ** 6) + self.assertEqual(self.now.humanize(later106, granularity="day"), "34 days ago") + self.assertEqual(later106.humanize(self.now, granularity="day"), "in 34 days") + self.assertEqual(self.now.humanize(later106, granularity="week"), "4 weeks ago") + self.assertEqual(later106.humanize(self.now, granularity="week"), "in 4 weeks") + self.assertEqual( + self.now.humanize(later106, granularity="month"), "a month ago" + ) + self.assertEqual(later106.humanize(self.now, granularity="month"), "in a month") + self.assertEqual(self.now.humanize(later106, granularity="year"), "0 years ago") + self.assertEqual(later106.humanize(self.now, granularity="year"), "in 0 years") + + later506 = self.now.shift(seconds=50 * 10 ** 6) + self.assertEqual( + self.now.humanize(later506, granularity="week"), "82 weeks ago" + ) + self.assertEqual(later506.humanize(self.now, granularity="week"), "in 82 weeks") + self.assertEqual( + self.now.humanize(later506, granularity="month"), "18 months ago" + ) + self.assertEqual( + later506.humanize(self.now, granularity="month"), "in 18 months" + ) + self.assertEqual(self.now.humanize(later506, granularity="year"), "a year ago") + self.assertEqual(later506.humanize(self.now, granularity="year"), "in a year") + + later108 = self.now.shift(seconds=10 ** 8) + self.assertEqual(self.now.humanize(later108, granularity="year"), "3 years ago") + self.assertEqual(later108.humanize(self.now, granularity="year"), "in 3 years") + + later108onlydistance = self.now.shift(seconds=10 ** 8) + self.assertEqual( + self.now.humanize( + later108onlydistance, only_distance=True, granularity="year" + ), + "3 years", + ) + self.assertEqual( + later108onlydistance.humanize( + self.now, only_distance=True, granularity="year" + ), + "3 years", + ) + + with self.assertRaises(AttributeError): + self.now.humanize(later108, granularity="years") + + def test_multiple_granularity(self): + self.assertEqual(self.now.humanize(granularity="second"), "just now") + self.assertEqual(self.now.humanize(granularity=["second"]), "just now") + self.assertEqual( + self.now.humanize(granularity=["year", "month", "day", "hour", "second"]), + "in 0 years 0 months 0 days 0 hours and 0 seconds", + ) + + later4000 = self.now.shift(seconds=4000) + self.assertEqual( + later4000.humanize(self.now, granularity=["hour", "minute"]), + "in an hour and 6 minutes", + ) + self.assertEqual( + self.now.humanize(later4000, granularity=["hour", "minute"]), + "an hour and 6 minutes ago", + ) + self.assertEqual( + later4000.humanize( + self.now, granularity=["hour", "minute"], only_distance=True + ), + "an hour and 6 minutes", + ) + self.assertEqual( + later4000.humanize(self.now, granularity=["day", "hour", "minute"]), + "in 0 days an hour and 6 minutes", + ) + self.assertEqual( + self.now.humanize(later4000, granularity=["day", "hour", "minute"]), + "0 days an hour and 6 minutes ago", + ) + + later105 = self.now.shift(seconds=10 ** 5) + self.assertEqual( + self.now.humanize(later105, granularity=["hour", "day", "minute"]), + "a day 3 hours and 46 minutes ago", + ) + with self.assertRaises(AttributeError): + self.now.humanize(later105, granularity=["error", "second"]) + + later108onlydistance = self.now.shift(seconds=10 ** 8) + self.assertEqual( + self.now.humanize( + later108onlydistance, only_distance=True, granularity=["year"] + ), + "3 years", + ) + self.assertEqual( + self.now.humanize( + later108onlydistance, only_distance=True, granularity=["month", "week"] + ), + "37 months and 4 weeks", + ) + self.assertEqual( + self.now.humanize( + later108onlydistance, only_distance=True, granularity=["year", "second"] + ), + "3 years and 5327200 seconds", + ) + + one_min_one_sec_ago = self.now.shift(minutes=-1, seconds=-1) + self.assertEqual( + one_min_one_sec_ago.humanize(self.now, granularity=["minute", "second"]), + "a minute and a second ago", + ) + + one_min_two_secs_ago = self.now.shift(minutes=-1, seconds=-2) + self.assertEqual( + one_min_two_secs_ago.humanize(self.now, granularity=["minute", "second"]), + "a minute and 2 seconds ago", + ) + + def test_seconds(self): + + later = self.now.shift(seconds=10) + + # regression test for issue #727 + self.assertEqual(self.now.humanize(later), "10 seconds ago") + self.assertEqual(later.humanize(self.now), "in 10 seconds") + + self.assertEqual(self.now.humanize(later, only_distance=True), "10 seconds") + self.assertEqual(later.humanize(self.now, only_distance=True), "10 seconds") + + def test_minute(self): + + later = self.now.shift(minutes=1) + + self.assertEqual(self.now.humanize(later), "a minute ago") + self.assertEqual(later.humanize(self.now), "in a minute") + + self.assertEqual(self.now.humanize(later, only_distance=True), "a minute") + self.assertEqual(later.humanize(self.now, only_distance=True), "a minute") + + def test_minutes(self): + + later = self.now.shift(minutes=2) + + self.assertEqual(self.now.humanize(later), "2 minutes ago") + self.assertEqual(later.humanize(self.now), "in 2 minutes") + + self.assertEqual(self.now.humanize(later, only_distance=True), "2 minutes") + self.assertEqual(later.humanize(self.now, only_distance=True), "2 minutes") + + def test_hour(self): + + later = self.now.shift(hours=1) + + self.assertEqual(self.now.humanize(later), "an hour ago") + self.assertEqual(later.humanize(self.now), "in an hour") + + self.assertEqual(self.now.humanize(later, only_distance=True), "an hour") + self.assertEqual(later.humanize(self.now, only_distance=True), "an hour") + + def test_hours(self): + + later = self.now.shift(hours=2) + + self.assertEqual(self.now.humanize(later), "2 hours ago") + self.assertEqual(later.humanize(self.now), "in 2 hours") + + self.assertEqual(self.now.humanize(later, only_distance=True), "2 hours") + self.assertEqual(later.humanize(self.now, only_distance=True), "2 hours") + + def test_day(self): + + later = self.now.shift(days=1) + + self.assertEqual(self.now.humanize(later), "a day ago") + self.assertEqual(later.humanize(self.now), "in a day") + + # regression test for issue #697 + less_than_48_hours = self.now.shift( + days=1, hours=23, seconds=59, microseconds=999999 + ) + self.assertEqual(self.now.humanize(less_than_48_hours), "a day ago") + self.assertEqual(less_than_48_hours.humanize(self.now), "in a day") + + less_than_48_hours_date = less_than_48_hours._datetime.date() + with self.assertRaises(TypeError): + # humanize other argument does not take raw datetime.date objects + self.now.humanize(less_than_48_hours_date) + + # convert from date to arrow object + less_than_48_hours_date = arrow.Arrow.fromdate(less_than_48_hours_date) + self.assertEqual(self.now.humanize(less_than_48_hours_date), "a day ago") + self.assertEqual(less_than_48_hours_date.humanize(self.now), "in a day") + + self.assertEqual(self.now.humanize(later, only_distance=True), "a day") + self.assertEqual(later.humanize(self.now, only_distance=True), "a day") + + def test_days(self): + + later = self.now.shift(days=2) + + self.assertEqual(self.now.humanize(later), "2 days ago") + self.assertEqual(later.humanize(self.now), "in 2 days") + + self.assertEqual(self.now.humanize(later, only_distance=True), "2 days") + self.assertEqual(later.humanize(self.now, only_distance=True), "2 days") + + # Regression tests for humanize bug referenced in issue 541 + later = self.now.shift(days=3) + self.assertEqual(later.humanize(), "in 3 days") + + later = self.now.shift(days=3, seconds=1) + self.assertEqual(later.humanize(), "in 3 days") + + later = self.now.shift(days=4) + self.assertEqual(later.humanize(), "in 4 days") + + def test_week(self): + + later = self.now.shift(weeks=1) + + self.assertEqual(self.now.humanize(later), "a week ago") + self.assertEqual(later.humanize(self.now), "in a week") + + self.assertEqual(self.now.humanize(later, only_distance=True), "a week") + self.assertEqual(later.humanize(self.now, only_distance=True), "a week") + + def test_weeks(self): + + later = self.now.shift(weeks=2) + + self.assertEqual(self.now.humanize(later), "2 weeks ago") + self.assertEqual(later.humanize(self.now), "in 2 weeks") + + self.assertEqual(self.now.humanize(later, only_distance=True), "2 weeks") + self.assertEqual(later.humanize(self.now, only_distance=True), "2 weeks") + + def test_month(self): + + later = self.now.shift(months=1) + + self.assertEqual(self.now.humanize(later), "a month ago") + self.assertEqual(later.humanize(self.now), "in a month") + + self.assertEqual(self.now.humanize(later, only_distance=True), "a month") + self.assertEqual(later.humanize(self.now, only_distance=True), "a month") + + def test_months(self): + + later = self.now.shift(months=2) + earlier = self.now.shift(months=-2) + + self.assertEqual(earlier.humanize(self.now), "2 months ago") + self.assertEqual(later.humanize(self.now), "in 2 months") + + self.assertEqual(self.now.humanize(later, only_distance=True), "2 months") + self.assertEqual(later.humanize(self.now, only_distance=True), "2 months") + + def test_year(self): + + later = self.now.shift(years=1) + + self.assertEqual(self.now.humanize(later), "a year ago") + self.assertEqual(later.humanize(self.now), "in a year") + + self.assertEqual(self.now.humanize(later, only_distance=True), "a year") + self.assertEqual(later.humanize(self.now, only_distance=True), "a year") + + def test_years(self): + + later = self.now.shift(years=2) + + self.assertEqual(self.now.humanize(later), "2 years ago") + self.assertEqual(later.humanize(self.now), "in 2 years") + + self.assertEqual(self.now.humanize(later, only_distance=True), "2 years") + self.assertEqual(later.humanize(self.now, only_distance=True), "2 years") + + arw = arrow.Arrow(2014, 7, 2) + + result = arw.humanize(self.datetime) + + self.assertEqual(result, "in 2 years") + + def test_arrow(self): + + arw = arrow.Arrow.fromdatetime(self.datetime) + + result = arw.humanize(arrow.Arrow.fromdatetime(self.datetime)) + + self.assertEqual(result, "just now") + + def test_datetime_tzinfo(self): + + arw = arrow.Arrow.fromdatetime(self.datetime) + + result = arw.humanize(self.datetime.replace(tzinfo=tz.tzutc())) + + self.assertEqual(result, "just now") + + def test_other(self): + + arw = arrow.Arrow.fromdatetime(self.datetime) + + with self.assertRaises(TypeError): + arw.humanize(object()) + + def test_invalid_locale(self): + + arw = arrow.Arrow.fromdatetime(self.datetime) + + with self.assertRaises(ValueError): + arw.humanize(locale="klingon") + + def test_none(self): + + arw = arrow.Arrow.utcnow() + + result = arw.humanize() + + self.assertEqual(result, "just now") + + result = arw.humanize(None) + + self.assertEqual(result, "just now") + + def test_untranslated_granularity(self): + + arw = arrow.Arrow.utcnow() + later = arw.shift(weeks=1) + + # simulate an untranslated timeframe key + with patch.dict("arrow.locales.EnglishLocale.timeframes"): + del arrow.locales.EnglishLocale.timeframes["week"] + + with self.assertRaises(ValueError): + arw.humanize(later, granularity="week") + + +class ArrowHumanizeTestsWithLocale(Chai): + def setUp(self): + super(ArrowHumanizeTestsWithLocale, self).setUp() + + self.datetime = datetime(2013, 1, 1) + + def test_now(self): + + arw = arrow.Arrow(2013, 1, 1, 0, 0, 0) + + result = arw.humanize(self.datetime, locale="ru") + + self.assertEqual(result, "сейчас") + + def test_seconds(self): + arw = arrow.Arrow(2013, 1, 1, 0, 0, 44) + + result = arw.humanize(self.datetime, locale="ru") + + self.assertEqual(result, "через 44 несколько секунд") + + def test_years(self): + + arw = arrow.Arrow(2011, 7, 2) + + result = arw.humanize(self.datetime, locale="ru") + + self.assertEqual(result, "2 года назад") + + +class ArrowIsBetweenTests(Chai): + def test_start_before_end(self): + target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) + start = arrow.Arrow.fromdatetime(datetime(2013, 5, 8)) + end = arrow.Arrow.fromdatetime(datetime(2013, 5, 5)) + result = target.is_between(start, end) + self.assertFalse(result) + + def test_exclusive_exclusive_bounds(self): + target = arrow.Arrow.fromdatetime(datetime(2013, 5, 5, 12, 30, 27)) + start = arrow.Arrow.fromdatetime(datetime(2013, 5, 5, 12, 30, 10)) + end = arrow.Arrow.fromdatetime(datetime(2013, 5, 5, 12, 30, 36)) + result = target.is_between(start, end, "()") + self.assertTrue(result) + result = target.is_between(start, end) + self.assertTrue(result) + + def test_exclusive_exclusive_bounds_same_date(self): + target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) + start = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) + end = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) + result = target.is_between(start, end, "()") + self.assertFalse(result) + + def test_inclusive_exclusive_bounds(self): + target = arrow.Arrow.fromdatetime(datetime(2013, 5, 6)) + start = arrow.Arrow.fromdatetime(datetime(2013, 5, 4)) + end = arrow.Arrow.fromdatetime(datetime(2013, 5, 6)) + result = target.is_between(start, end, "[)") + self.assertFalse(result) + + def test_exclusive_inclusive_bounds(self): + target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) + start = arrow.Arrow.fromdatetime(datetime(2013, 5, 5)) + end = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) + result = target.is_between(start, end, "(]") + self.assertTrue(result) + + def test_inclusive_inclusive_bounds_same_date(self): + target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) + start = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) + end = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) + result = target.is_between(start, end, "[]") + self.assertTrue(result) + + def test_type_error_exception(self): + with self.assertRaises(TypeError): + target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) + start = datetime(2013, 5, 5) + end = arrow.Arrow.fromdatetime(datetime(2013, 5, 8)) + target.is_between(start, end) + + with self.assertRaises(TypeError): + target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) + start = arrow.Arrow.fromdatetime(datetime(2013, 5, 5)) + end = datetime(2013, 5, 8) + target.is_between(start, end) + + with self.assertRaises(TypeError): + target.is_between(None, None) + + def test_attribute_error_exception(self): + target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) + start = arrow.Arrow.fromdatetime(datetime(2013, 5, 5)) + end = arrow.Arrow.fromdatetime(datetime(2013, 5, 8)) + with self.assertRaises(AttributeError): + target.is_between(start, end, "][") + with self.assertRaises(AttributeError): + target.is_between(start, end, "") + with self.assertRaises(AttributeError): + target.is_between(start, end, "]") + with self.assertRaises(AttributeError): + target.is_between(start, end, "[") + with self.assertRaises(AttributeError): + target.is_between(start, end, "hello") + + +class ArrowUtilTests(Chai): + def test_get_datetime(self): + + get_datetime = arrow.Arrow._get_datetime + + arw = arrow.Arrow.utcnow() + dt = datetime.utcnow() + timestamp = time.time() + + self.assertEqual(get_datetime(arw), arw.datetime) + self.assertEqual(get_datetime(dt), dt) + self.assertEqual( + get_datetime(timestamp), arrow.Arrow.utcfromtimestamp(timestamp).datetime + ) + + with self.assertRaises(ValueError) as raise_ctx: + get_datetime("abc") + self.assertFalse("{}" in str(raise_ctx.exception)) + + def test_get_tzinfo(self): + + get_tzinfo = arrow.Arrow._get_tzinfo + + with self.assertRaises(ValueError) as raise_ctx: + get_tzinfo("abc") + self.assertFalse("{}" in str(raise_ctx.exception)) + + def test_get_iteration_params(self): + + self.assertEqual( + arrow.Arrow._get_iteration_params("end", None), ("end", sys.maxsize) + ) + self.assertEqual( + arrow.Arrow._get_iteration_params(None, 100), (arrow.Arrow.max, 100) + ) + self.assertEqual(arrow.Arrow._get_iteration_params(100, 120), (100, 120)) + + with self.assertRaises(ValueError): + arrow.Arrow._get_iteration_params(None, None) From 338e132c6d6af8a6e723e1a049b874254eed9fb2 Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Sat, 4 Jan 2020 14:28:46 -0500 Subject: [PATCH 02/13] Removed mock from arrow_tests --- tests/arrow_tests.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/arrow_tests.py b/tests/arrow_tests.py index e9d7cd72e..561b81973 100644 --- a/tests/arrow_tests.py +++ b/tests/arrow_tests.py @@ -12,7 +12,6 @@ import simplejson as json from dateutil import tz from dateutil.relativedelta import FR, MO, SA, SU, TH, TU, WE -from mock import patch from arrow import arrow, util @@ -1678,17 +1677,16 @@ def test_none(self): assert result == "just now" - def test_untranslated_granularity(self): + def test_untranslated_granularity(self, mocker): arw = arrow.Arrow.utcnow() later = arw.shift(weeks=1) # simulate an untranslated timeframe key - with patch.dict("arrow.locales.EnglishLocale.timeframes"): - del arrow.locales.EnglishLocale.timeframes["week"] - - with pytest.raises(ValueError): - arw.humanize(later, granularity="week") + mocker.patch.dict("arrow.locales.EnglishLocale.timeframes") + del arrow.locales.EnglishLocale.timeframes["week"] + with pytest.raises(ValueError): + arw.humanize(later, granularity="week") class TestArrowHumanizeTestsWithLocale: From e2c55d7abd1e3170afd46e6bfe2e16cd38c90577 Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Sat, 4 Jan 2020 14:33:15 -0500 Subject: [PATCH 03/13] Moved factory to pytest --- tests/factory_tests.py | 158 +++++++-------- tests/factory_tests.py.bak | 383 +++++++++++++++++++++++++++++++++++++ 2 files changed, 449 insertions(+), 92 deletions(-) create mode 100644 tests/factory_tests.py.bak diff --git a/tests/factory_tests.py b/tests/factory_tests.py index abdd0d029..840e9651c 100644 --- a/tests/factory_tests.py +++ b/tests/factory_tests.py @@ -3,23 +3,22 @@ from datetime import date, datetime import dateparser -from chai import Chai from dateutil import tz from arrow import factory, util from arrow.parser import ParserError +import pytest def assertDtEqual(dt1, dt2, within=10): - assertEqual(dt1.tzinfo, dt2.tzinfo) # noqa: F821 - assertTrue(abs(util.total_seconds(dt1 - dt2)) < within) # noqa: F821 + assert dt1.tzinfo == dt2.tzinfo + assert abs(util.total_seconds(dt1 - dt2)) < within -class GetTests(Chai): - def setUp(self): - super(GetTests, self).setUp() - - self.factory = factory.ArrowFactory() +class TestGet: + @classmethod + def setup_class(cls): + cls.factory = factory.ArrowFactory() def test_no_args(self): @@ -30,7 +29,7 @@ def test_timestamp_one_arg_no_arg(self): no_arg = self.factory.get(1406430900).timestamp one_arg = self.factory.get("1406430900", "X").timestamp - self.assertEqual(no_arg, one_arg) + assert no_arg == one_arg def test_one_arg_none(self): @@ -52,9 +51,9 @@ def test_one_arg_timestamp(self): tzinfo=tz.tzutc() ) - self.assertEqual(self.factory.get(int_timestamp), timestamp_dt) + assert self.factory.get(int_timestamp) == timestamp_dt - with self.assertRaises(ParserError): + with pytest.raises(ParserError): self.factory.get(str(int_timestamp)) float_timestamp = time.time() @@ -62,15 +61,15 @@ def test_one_arg_timestamp(self): tzinfo=tz.tzutc() ) - self.assertEqual(self.factory.get(float_timestamp), timestamp_dt) + assert self.factory.get(float_timestamp) == timestamp_dt - with self.assertRaises(ParserError): + with pytest.raises(ParserError): self.factory.get(str(float_timestamp)) # Regression test for issue #216 # Python 3 raises OverflowError, Python 2 raises ValueError timestamp = 99999999999999999999999999.99999999999999999999999999 - with self.assertRaises((OverflowError, ValueError)): + with pytest.raises((OverflowError, ValueError)): self.factory.get(timestamp) def test_one_arg_timestamp_with_tzinfo(self): @@ -88,20 +87,20 @@ def test_one_arg_arrow(self): arw = self.factory.utcnow() result = self.factory.get(arw) - self.assertEqual(arw, result) + assert arw == result def test_one_arg_datetime(self): dt = datetime.utcnow().replace(tzinfo=tz.tzutc()) - self.assertEqual(self.factory.get(dt), dt) + assert self.factory.get(dt) == dt def test_one_arg_date(self): d = date.today() dt = datetime(d.year, d.month, d.day, tzinfo=tz.tzutc()) - self.assertEqual(self.factory.get(d), dt) + assert self.factory.get(d) == dt def test_one_arg_tzinfo(self): @@ -119,7 +118,7 @@ def test_one_arg_dateparser_datetime(self): # dateparser outputs: datetime.datetime(1990, 1, 1, 0, 0, tzinfo=) parsed_date = dateparser.parse("1990-01-01T00:00:00+00:00") dt_output = self.factory.get(parsed_date)._datetime.replace(tzinfo=tz.tzutc()) - self.assertEqual(dt_output, expected) + assert dt_output == expected def test_kwarg_tzinfo(self): @@ -141,7 +140,7 @@ def test_kwarg_tzinfo_string(self): assertDtEqual(self.factory.get(tzinfo="US/Pacific"), self.expected) - with self.assertRaises(ParserError): + with pytest.raises(ParserError): self.factory.get(tzinfo="US/PacificInvalidTzinfo") def test_one_arg_iso_str(self): @@ -165,80 +164,72 @@ def test_one_arg_iso_calendar(self): for pair in pairs: dt, iso = pair - self.assertEqual(self.factory.get(iso), self.factory.get(dt)) + assert self.factory.get(iso) == self.factory.get(dt) - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.factory.get((2014, 7, 1, 4)) - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.factory.get((2014, 7)) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): self.factory.get((2014, 70, 1)) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): self.factory.get((2014, 7, 10)) def test_one_arg_other(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.factory.get(object()) def test_one_arg_bool(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.factory.get(False) - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.factory.get(True) def test_two_args_datetime_tzinfo(self): result = self.factory.get(datetime(2013, 1, 1), tz.gettz("US/Pacific")) - self.assertEqual( - result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) - ) + assert result._datetime == datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) def test_two_args_datetime_tz_str(self): result = self.factory.get(datetime(2013, 1, 1), "US/Pacific") - self.assertEqual( - result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) - ) + assert result._datetime == datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) def test_two_args_date_tzinfo(self): result = self.factory.get(date(2013, 1, 1), tz.gettz("US/Pacific")) - self.assertEqual( - result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) - ) + assert result._datetime == datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) def test_two_args_date_tz_str(self): result = self.factory.get(date(2013, 1, 1), "US/Pacific") - self.assertEqual( - result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) - ) + assert result._datetime == datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) def test_two_args_datetime_other(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.factory.get(datetime.utcnow(), object()) def test_two_args_date_other(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.factory.get(date.today(), object()) def test_two_args_str_str(self): result = self.factory.get("2013-01-01", "YYYY-MM-DD") - self.assertEqual(result._datetime, datetime(2013, 1, 1, tzinfo=tz.tzutc())) + assert result._datetime == datetime(2013, 1, 1, tzinfo=tz.tzutc()) def test_two_args_str_tzinfo(self): @@ -254,25 +245,23 @@ def test_two_args_twitter_format(self): twitter_date = "Fri Apr 08 21:08:54 +0000 2016" result = self.factory.get(twitter_date, "ddd MMM DD HH:mm:ss Z YYYY") - self.assertEqual( - result._datetime, datetime(2016, 4, 8, 21, 8, 54, tzinfo=tz.tzutc()) - ) + assert result._datetime == datetime(2016, 4, 8, 21, 8, 54, tzinfo=tz.tzutc()) def test_two_args_str_list(self): result = self.factory.get("2013-01-01", ["MM/DD/YYYY", "YYYY-MM-DD"]) - self.assertEqual(result._datetime, datetime(2013, 1, 1, tzinfo=tz.tzutc())) + assert result._datetime == datetime(2013, 1, 1, tzinfo=tz.tzutc()) def test_two_args_unicode_unicode(self): result = self.factory.get(u"2013-01-01", u"YYYY-MM-DD") - self.assertEqual(result._datetime, datetime(2013, 1, 1, tzinfo=tz.tzutc())) + assert result._datetime == datetime(2013, 1, 1, tzinfo=tz.tzutc()) def test_two_args_other(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.factory.get(object(), object()) def test_three_args_with_tzinfo(self): @@ -280,81 +269,67 @@ def test_three_args_with_tzinfo(self): timefmt = "YYYYMMDD" d = "20150514" - self.assertEqual( - self.factory.get(d, timefmt, tzinfo=tz.tzlocal()), - datetime(2015, 5, 14, tzinfo=tz.tzlocal()), + assert self.factory.get(d, timefmt, tzinfo=tz.tzlocal()) == datetime( + 2015, 5, 14, tzinfo=tz.tzlocal() ) def test_three_args(self): - self.assertEqual( - self.factory.get(2013, 1, 1), datetime(2013, 1, 1, tzinfo=tz.tzutc()) - ) + assert self.factory.get(2013, 1, 1) == datetime(2013, 1, 1, tzinfo=tz.tzutc()) def test_full_kwargs(self): - self.assertEqual( - self.factory.get( - year=2016, - month=7, - day=14, - hour=7, - minute=16, - second=45, - microsecond=631092, - ), - datetime(2016, 7, 14, 7, 16, 45, 631092, tzinfo=tz.tzutc()), - ) + assert self.factory.get( + year=2016, + month=7, + day=14, + hour=7, + minute=16, + second=45, + microsecond=631092, + ) == datetime(2016, 7, 14, 7, 16, 45, 631092, tzinfo=tz.tzutc()) def test_three_kwargs(self): - self.assertEqual( - self.factory.get(year=2016, month=7, day=14), - datetime(2016, 7, 14, 0, 0, tzinfo=tz.tzutc()), + assert self.factory.get(year=2016, month=7, day=14) == datetime( + 2016, 7, 14, 0, 0, tzinfo=tz.tzutc() ) def test_tzinfo_string_kwargs(self): result = self.factory.get("2019072807", "YYYYMMDDHH", tzinfo="UTC") - self.assertEqual( - result._datetime, datetime(2019, 7, 28, 7, 0, 0, 0, tzinfo=tz.tzutc()) - ) + assert result._datetime == datetime(2019, 7, 28, 7, 0, 0, 0, tzinfo=tz.tzutc()) def test_insufficient_kwargs(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.factory.get(year=2016) - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.factory.get(year=2016, month=7) def test_locale(self): result = self.factory.get("2010", "YYYY", locale="ja") - self.assertEqual( - result._datetime, datetime(2010, 1, 1, 0, 0, 0, 0, tzinfo=tz.tzutc()) - ) + assert result._datetime == datetime(2010, 1, 1, 0, 0, 0, 0, tzinfo=tz.tzutc()) # regression test for issue #701 result = self.factory.get( "Montag, 9. September 2019, 16:15-20:00", "dddd, D. MMMM YYYY", locale="de" ) - self.assertEqual( - result._datetime, datetime(2019, 9, 9, 0, 0, 0, 0, tzinfo=tz.tzutc()) - ) + assert result._datetime == datetime(2019, 9, 9, 0, 0, 0, 0, tzinfo=tz.tzutc()) def test_locale_kwarg_only(self): res = self.factory.get(locale="ja") - self.assertEqual(res.tzinfo, tz.tzutc()) + assert res.tzinfo == tz.tzutc() def test_locale_with_tzinfo(self): res = self.factory.get(locale="ja", tzinfo=tz.gettz("Asia/Tokyo")) - self.assertEqual(res.tzinfo, tz.gettz("Asia/Tokyo")) + assert res.tzinfo == tz.gettz("Asia/Tokyo") -class UtcNowTests(Chai): - def setUp(self): - super(UtcNowTests, self).setUp() - - self.factory = factory.ArrowFactory() +class TestUtcNow: + @classmethod + def setup_class(cls): + cls.factory = factory.ArrowFactory() def test_utcnow(self): @@ -364,11 +339,10 @@ def test_utcnow(self): ) -class NowTests(Chai): - def setUp(self): - super(NowTests, self).setUp() - - self.factory = factory.ArrowFactory() +class TestNow: + @classmethod + def setup_class(cls): + cls.factory = factory.ArrowFactory() def test_no_tz(self): diff --git a/tests/factory_tests.py.bak b/tests/factory_tests.py.bak new file mode 100644 index 000000000..abdd0d029 --- /dev/null +++ b/tests/factory_tests.py.bak @@ -0,0 +1,383 @@ +# -*- coding: utf-8 -*- +import time +from datetime import date, datetime + +import dateparser +from chai import Chai +from dateutil import tz + +from arrow import factory, util +from arrow.parser import ParserError + + +def assertDtEqual(dt1, dt2, within=10): + assertEqual(dt1.tzinfo, dt2.tzinfo) # noqa: F821 + assertTrue(abs(util.total_seconds(dt1 - dt2)) < within) # noqa: F821 + + +class GetTests(Chai): + def setUp(self): + super(GetTests, self).setUp() + + self.factory = factory.ArrowFactory() + + def test_no_args(self): + + assertDtEqual(self.factory.get(), datetime.utcnow().replace(tzinfo=tz.tzutc())) + + def test_timestamp_one_arg_no_arg(self): + + no_arg = self.factory.get(1406430900).timestamp + one_arg = self.factory.get("1406430900", "X").timestamp + + self.assertEqual(no_arg, one_arg) + + def test_one_arg_none(self): + + assertDtEqual( + self.factory.get(None), datetime.utcnow().replace(tzinfo=tz.tzutc()) + ) + + def test_struct_time(self): + + assertDtEqual( + self.factory.get(time.gmtime()), + datetime.utcnow().replace(tzinfo=tz.tzutc()), + ) + + def test_one_arg_timestamp(self): + + int_timestamp = int(time.time()) + timestamp_dt = datetime.utcfromtimestamp(int_timestamp).replace( + tzinfo=tz.tzutc() + ) + + self.assertEqual(self.factory.get(int_timestamp), timestamp_dt) + + with self.assertRaises(ParserError): + self.factory.get(str(int_timestamp)) + + float_timestamp = time.time() + timestamp_dt = datetime.utcfromtimestamp(float_timestamp).replace( + tzinfo=tz.tzutc() + ) + + self.assertEqual(self.factory.get(float_timestamp), timestamp_dt) + + with self.assertRaises(ParserError): + self.factory.get(str(float_timestamp)) + + # Regression test for issue #216 + # Python 3 raises OverflowError, Python 2 raises ValueError + timestamp = 99999999999999999999999999.99999999999999999999999999 + with self.assertRaises((OverflowError, ValueError)): + self.factory.get(timestamp) + + def test_one_arg_timestamp_with_tzinfo(self): + + timestamp = time.time() + timestamp_dt = datetime.fromtimestamp(timestamp, tz=tz.tzutc()).astimezone( + tz.gettz("US/Pacific") + ) + timezone = tz.gettz("US/Pacific") + + assertDtEqual(self.factory.get(timestamp, tzinfo=timezone), timestamp_dt) + + def test_one_arg_arrow(self): + + arw = self.factory.utcnow() + result = self.factory.get(arw) + + self.assertEqual(arw, result) + + def test_one_arg_datetime(self): + + dt = datetime.utcnow().replace(tzinfo=tz.tzutc()) + + self.assertEqual(self.factory.get(dt), dt) + + def test_one_arg_date(self): + + d = date.today() + dt = datetime(d.year, d.month, d.day, tzinfo=tz.tzutc()) + + self.assertEqual(self.factory.get(d), dt) + + def test_one_arg_tzinfo(self): + + self.expected = ( + datetime.utcnow() + .replace(tzinfo=tz.tzutc()) + .astimezone(tz.gettz("US/Pacific")) + ) + + assertDtEqual(self.factory.get(tz.gettz("US/Pacific")), self.expected) + + # regression test for issue #658 + def test_one_arg_dateparser_datetime(self): + expected = datetime(1990, 1, 1).replace(tzinfo=tz.tzutc()) + # dateparser outputs: datetime.datetime(1990, 1, 1, 0, 0, tzinfo=) + parsed_date = dateparser.parse("1990-01-01T00:00:00+00:00") + dt_output = self.factory.get(parsed_date)._datetime.replace(tzinfo=tz.tzutc()) + self.assertEqual(dt_output, expected) + + def test_kwarg_tzinfo(self): + + self.expected = ( + datetime.utcnow() + .replace(tzinfo=tz.tzutc()) + .astimezone(tz.gettz("US/Pacific")) + ) + + assertDtEqual(self.factory.get(tzinfo=tz.gettz("US/Pacific")), self.expected) + + def test_kwarg_tzinfo_string(self): + + self.expected = ( + datetime.utcnow() + .replace(tzinfo=tz.tzutc()) + .astimezone(tz.gettz("US/Pacific")) + ) + + assertDtEqual(self.factory.get(tzinfo="US/Pacific"), self.expected) + + with self.assertRaises(ParserError): + self.factory.get(tzinfo="US/PacificInvalidTzinfo") + + def test_one_arg_iso_str(self): + + dt = datetime.utcnow() + + assertDtEqual(self.factory.get(dt.isoformat()), dt.replace(tzinfo=tz.tzutc())) + + def test_one_arg_iso_calendar(self): + + pairs = [ + (datetime(2004, 1, 4), (2004, 1, 7)), + (datetime(2008, 12, 30), (2009, 1, 2)), + (datetime(2010, 1, 2), (2009, 53, 6)), + (datetime(2000, 2, 29), (2000, 9, 2)), + (datetime(2005, 1, 1), (2004, 53, 6)), + (datetime(2010, 1, 4), (2010, 1, 1)), + (datetime(2010, 1, 3), (2009, 53, 7)), + (datetime(2003, 12, 29), (2004, 1, 1)), + ] + + for pair in pairs: + dt, iso = pair + self.assertEqual(self.factory.get(iso), self.factory.get(dt)) + + with self.assertRaises(TypeError): + self.factory.get((2014, 7, 1, 4)) + + with self.assertRaises(TypeError): + self.factory.get((2014, 7)) + + with self.assertRaises(ValueError): + self.factory.get((2014, 70, 1)) + + with self.assertRaises(ValueError): + self.factory.get((2014, 7, 10)) + + def test_one_arg_other(self): + + with self.assertRaises(TypeError): + self.factory.get(object()) + + def test_one_arg_bool(self): + + with self.assertRaises(TypeError): + self.factory.get(False) + + with self.assertRaises(TypeError): + self.factory.get(True) + + def test_two_args_datetime_tzinfo(self): + + result = self.factory.get(datetime(2013, 1, 1), tz.gettz("US/Pacific")) + + self.assertEqual( + result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) + ) + + def test_two_args_datetime_tz_str(self): + + result = self.factory.get(datetime(2013, 1, 1), "US/Pacific") + + self.assertEqual( + result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) + ) + + def test_two_args_date_tzinfo(self): + + result = self.factory.get(date(2013, 1, 1), tz.gettz("US/Pacific")) + + self.assertEqual( + result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) + ) + + def test_two_args_date_tz_str(self): + + result = self.factory.get(date(2013, 1, 1), "US/Pacific") + + self.assertEqual( + result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) + ) + + def test_two_args_datetime_other(self): + + with self.assertRaises(TypeError): + self.factory.get(datetime.utcnow(), object()) + + def test_two_args_date_other(self): + + with self.assertRaises(TypeError): + self.factory.get(date.today(), object()) + + def test_two_args_str_str(self): + + result = self.factory.get("2013-01-01", "YYYY-MM-DD") + + self.assertEqual(result._datetime, datetime(2013, 1, 1, tzinfo=tz.tzutc())) + + def test_two_args_str_tzinfo(self): + + result = self.factory.get("2013-01-01", tzinfo=tz.gettz("US/Pacific")) + + assertDtEqual( + result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) + ) + + def test_two_args_twitter_format(self): + + # format returned by twitter API for created_at: + twitter_date = "Fri Apr 08 21:08:54 +0000 2016" + result = self.factory.get(twitter_date, "ddd MMM DD HH:mm:ss Z YYYY") + + self.assertEqual( + result._datetime, datetime(2016, 4, 8, 21, 8, 54, tzinfo=tz.tzutc()) + ) + + def test_two_args_str_list(self): + + result = self.factory.get("2013-01-01", ["MM/DD/YYYY", "YYYY-MM-DD"]) + + self.assertEqual(result._datetime, datetime(2013, 1, 1, tzinfo=tz.tzutc())) + + def test_two_args_unicode_unicode(self): + + result = self.factory.get(u"2013-01-01", u"YYYY-MM-DD") + + self.assertEqual(result._datetime, datetime(2013, 1, 1, tzinfo=tz.tzutc())) + + def test_two_args_other(self): + + with self.assertRaises(TypeError): + self.factory.get(object(), object()) + + def test_three_args_with_tzinfo(self): + + timefmt = "YYYYMMDD" + d = "20150514" + + self.assertEqual( + self.factory.get(d, timefmt, tzinfo=tz.tzlocal()), + datetime(2015, 5, 14, tzinfo=tz.tzlocal()), + ) + + def test_three_args(self): + + self.assertEqual( + self.factory.get(2013, 1, 1), datetime(2013, 1, 1, tzinfo=tz.tzutc()) + ) + + def test_full_kwargs(self): + + self.assertEqual( + self.factory.get( + year=2016, + month=7, + day=14, + hour=7, + minute=16, + second=45, + microsecond=631092, + ), + datetime(2016, 7, 14, 7, 16, 45, 631092, tzinfo=tz.tzutc()), + ) + + def test_three_kwargs(self): + + self.assertEqual( + self.factory.get(year=2016, month=7, day=14), + datetime(2016, 7, 14, 0, 0, tzinfo=tz.tzutc()), + ) + + def test_tzinfo_string_kwargs(self): + result = self.factory.get("2019072807", "YYYYMMDDHH", tzinfo="UTC") + self.assertEqual( + result._datetime, datetime(2019, 7, 28, 7, 0, 0, 0, tzinfo=tz.tzutc()) + ) + + def test_insufficient_kwargs(self): + + with self.assertRaises(TypeError): + self.factory.get(year=2016) + + with self.assertRaises(TypeError): + self.factory.get(year=2016, month=7) + + def test_locale(self): + result = self.factory.get("2010", "YYYY", locale="ja") + self.assertEqual( + result._datetime, datetime(2010, 1, 1, 0, 0, 0, 0, tzinfo=tz.tzutc()) + ) + + # regression test for issue #701 + result = self.factory.get( + "Montag, 9. September 2019, 16:15-20:00", "dddd, D. MMMM YYYY", locale="de" + ) + self.assertEqual( + result._datetime, datetime(2019, 9, 9, 0, 0, 0, 0, tzinfo=tz.tzutc()) + ) + + def test_locale_kwarg_only(self): + res = self.factory.get(locale="ja") + self.assertEqual(res.tzinfo, tz.tzutc()) + + def test_locale_with_tzinfo(self): + res = self.factory.get(locale="ja", tzinfo=tz.gettz("Asia/Tokyo")) + self.assertEqual(res.tzinfo, tz.gettz("Asia/Tokyo")) + + +class UtcNowTests(Chai): + def setUp(self): + super(UtcNowTests, self).setUp() + + self.factory = factory.ArrowFactory() + + def test_utcnow(self): + + assertDtEqual( + self.factory.utcnow()._datetime, + datetime.utcnow().replace(tzinfo=tz.tzutc()), + ) + + +class NowTests(Chai): + def setUp(self): + super(NowTests, self).setUp() + + self.factory = factory.ArrowFactory() + + def test_no_tz(self): + + assertDtEqual(self.factory.now(), datetime.now(tz.tzlocal())) + + def test_tzinfo(self): + + assertDtEqual(self.factory.now(tz.gettz("EST")), datetime.now(tz.gettz("EST"))) + + def test_tz_str(self): + + assertDtEqual(self.factory.now("EST"), datetime.now(tz.gettz("EST"))) From ef43261208bce0e42a4e006b3acc1366e32bbce5 Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Sat, 4 Jan 2020 14:35:05 -0500 Subject: [PATCH 04/13] Moved formatter tests to pytest --- tests/formatter_tests.py | 150 +++++++++++++------------- tests/formatter_tests.py.bak | 199 +++++++++++++++++++++++++++++++++++ 2 files changed, 273 insertions(+), 76 deletions(-) create mode 100644 tests/formatter_tests.py.bak diff --git a/tests/formatter_tests.py b/tests/formatter_tests.py index 848ac260a..33accf755 100644 --- a/tests/formatter_tests.py +++ b/tests/formatter_tests.py @@ -3,7 +3,6 @@ from datetime import datetime import pytz -from chai import Chai from dateutil import tz as dateutil_tz from arrow import formatter @@ -11,11 +10,10 @@ from .utils import make_full_tz_list -class DateTimeFormatterFormatTokenTests(Chai): - def setUp(self): - super(DateTimeFormatterFormatTokenTests, self).setUp() - - self.formatter = formatter.DateTimeFormatter() +class TestDateTimeFormatterFormatToken: + @classmethod + def setup_class(cls): + cls.formatter = formatter.DateTimeFormatter() def test_format(self): @@ -23,103 +21,103 @@ def test_format(self): result = self.formatter.format(dt, "MM-DD-YYYY hh:mm:ss a") - self.assertEqual(result, "02-05-2013 12:32:51 pm") + assert result == "02-05-2013 12:32:51 pm" def test_year(self): dt = datetime(2013, 1, 1) - self.assertEqual(self.formatter._format_token(dt, "YYYY"), "2013") - self.assertEqual(self.formatter._format_token(dt, "YY"), "13") + assert self.formatter._format_token(dt, "YYYY") == "2013" + assert self.formatter._format_token(dt, "YY") == "13" def test_month(self): dt = datetime(2013, 1, 1) - self.assertEqual(self.formatter._format_token(dt, "MMMM"), "January") - self.assertEqual(self.formatter._format_token(dt, "MMM"), "Jan") - self.assertEqual(self.formatter._format_token(dt, "MM"), "01") - self.assertEqual(self.formatter._format_token(dt, "M"), "1") + assert self.formatter._format_token(dt, "MMMM") == "January" + assert self.formatter._format_token(dt, "MMM") == "Jan" + assert self.formatter._format_token(dt, "MM") == "01" + assert self.formatter._format_token(dt, "M") == "1" def test_day(self): dt = datetime(2013, 2, 1) - self.assertEqual(self.formatter._format_token(dt, "DDDD"), "032") - self.assertEqual(self.formatter._format_token(dt, "DDD"), "32") - self.assertEqual(self.formatter._format_token(dt, "DD"), "01") - self.assertEqual(self.formatter._format_token(dt, "D"), "1") - self.assertEqual(self.formatter._format_token(dt, "Do"), "1st") + assert self.formatter._format_token(dt, "DDDD") == "032" + assert self.formatter._format_token(dt, "DDD") == "32" + assert self.formatter._format_token(dt, "DD") == "01" + assert self.formatter._format_token(dt, "D") == "1" + assert self.formatter._format_token(dt, "Do") == "1st" - self.assertEqual(self.formatter._format_token(dt, "dddd"), "Friday") - self.assertEqual(self.formatter._format_token(dt, "ddd"), "Fri") - self.assertEqual(self.formatter._format_token(dt, "d"), "5") + assert self.formatter._format_token(dt, "dddd") == "Friday" + assert self.formatter._format_token(dt, "ddd") == "Fri" + assert self.formatter._format_token(dt, "d") == "5" def test_hour(self): dt = datetime(2013, 1, 1, 2) - self.assertEqual(self.formatter._format_token(dt, "HH"), "02") - self.assertEqual(self.formatter._format_token(dt, "H"), "2") + assert self.formatter._format_token(dt, "HH") == "02" + assert self.formatter._format_token(dt, "H") == "2" dt = datetime(2013, 1, 1, 13) - self.assertEqual(self.formatter._format_token(dt, "HH"), "13") - self.assertEqual(self.formatter._format_token(dt, "H"), "13") + assert self.formatter._format_token(dt, "HH") == "13" + assert self.formatter._format_token(dt, "H") == "13" dt = datetime(2013, 1, 1, 2) - self.assertEqual(self.formatter._format_token(dt, "hh"), "02") - self.assertEqual(self.formatter._format_token(dt, "h"), "2") + assert self.formatter._format_token(dt, "hh") == "02" + assert self.formatter._format_token(dt, "h") == "2" dt = datetime(2013, 1, 1, 13) - self.assertEqual(self.formatter._format_token(dt, "hh"), "01") - self.assertEqual(self.formatter._format_token(dt, "h"), "1") + assert self.formatter._format_token(dt, "hh") == "01" + assert self.formatter._format_token(dt, "h") == "1" # test that 12-hour time converts to '12' at midnight dt = datetime(2013, 1, 1, 0) - self.assertEqual(self.formatter._format_token(dt, "hh"), "12") - self.assertEqual(self.formatter._format_token(dt, "h"), "12") + assert self.formatter._format_token(dt, "hh") == "12" + assert self.formatter._format_token(dt, "h") == "12" def test_minute(self): dt = datetime(2013, 1, 1, 0, 1) - self.assertEqual(self.formatter._format_token(dt, "mm"), "01") - self.assertEqual(self.formatter._format_token(dt, "m"), "1") + assert self.formatter._format_token(dt, "mm") == "01" + assert self.formatter._format_token(dt, "m") == "1" def test_second(self): dt = datetime(2013, 1, 1, 0, 0, 1) - self.assertEqual(self.formatter._format_token(dt, "ss"), "01") - self.assertEqual(self.formatter._format_token(dt, "s"), "1") + assert self.formatter._format_token(dt, "ss") == "01" + assert self.formatter._format_token(dt, "s") == "1" def test_sub_second(self): dt = datetime(2013, 1, 1, 0, 0, 0, 123456) - self.assertEqual(self.formatter._format_token(dt, "SSSSSS"), "123456") - self.assertEqual(self.formatter._format_token(dt, "SSSSS"), "12345") - self.assertEqual(self.formatter._format_token(dt, "SSSS"), "1234") - self.assertEqual(self.formatter._format_token(dt, "SSS"), "123") - self.assertEqual(self.formatter._format_token(dt, "SS"), "12") - self.assertEqual(self.formatter._format_token(dt, "S"), "1") + assert self.formatter._format_token(dt, "SSSSSS") == "123456" + assert self.formatter._format_token(dt, "SSSSS") == "12345" + assert self.formatter._format_token(dt, "SSSS") == "1234" + assert self.formatter._format_token(dt, "SSS") == "123" + assert self.formatter._format_token(dt, "SS") == "12" + assert self.formatter._format_token(dt, "S") == "1" dt = datetime(2013, 1, 1, 0, 0, 0, 2000) - self.assertEqual(self.formatter._format_token(dt, "SSSSSS"), "002000") - self.assertEqual(self.formatter._format_token(dt, "SSSSS"), "00200") - self.assertEqual(self.formatter._format_token(dt, "SSSS"), "0020") - self.assertEqual(self.formatter._format_token(dt, "SSS"), "002") - self.assertEqual(self.formatter._format_token(dt, "SS"), "00") - self.assertEqual(self.formatter._format_token(dt, "S"), "0") + assert self.formatter._format_token(dt, "SSSSSS") == "002000" + assert self.formatter._format_token(dt, "SSSSS") == "00200" + assert self.formatter._format_token(dt, "SSSS") == "0020" + assert self.formatter._format_token(dt, "SSS") == "002" + assert self.formatter._format_token(dt, "SS") == "00" + assert self.formatter._format_token(dt, "S") == "0" def test_timestamp(self): timestamp = time.time() dt = datetime.utcfromtimestamp(timestamp) - self.assertEqual(self.formatter._format_token(dt, "X"), str(int(timestamp))) + assert self.formatter._format_token(dt, "X") == str(int(timestamp)) def test_timezone(self): dt = datetime.utcnow().replace(tzinfo=dateutil_tz.gettz("US/Pacific")) result = self.formatter._format_token(dt, "ZZ") - self.assertTrue(result == "-07:00" or result == "-08:00") + assert result == "-07:00" or result == "-08:00" result = self.formatter._format_token(dt, "Z") - self.assertTrue(result == "-0700" or result == "-0800") + assert result == "-0700" or result == "-0800" def test_timezone_formatter(self): @@ -131,69 +129,69 @@ def test_timezone_formatter(self): abbreviation = dt.tzname() result = self.formatter._format_token(dt, "ZZZ") - self.assertEqual(result, abbreviation) + assert result == abbreviation def test_am_pm(self): dt = datetime(2012, 1, 1, 11) - self.assertEqual(self.formatter._format_token(dt, "a"), "am") - self.assertEqual(self.formatter._format_token(dt, "A"), "AM") + assert self.formatter._format_token(dt, "a") == "am" + assert self.formatter._format_token(dt, "A") == "AM" dt = datetime(2012, 1, 1, 13) - self.assertEqual(self.formatter._format_token(dt, "a"), "pm") - self.assertEqual(self.formatter._format_token(dt, "A"), "PM") + assert self.formatter._format_token(dt, "a") == "pm" + assert self.formatter._format_token(dt, "A") == "PM" def test_nonsense(self): dt = datetime(2012, 1, 1, 11) - self.assertEqual(self.formatter._format_token(dt, None), None) - self.assertEqual(self.formatter._format_token(dt, "NONSENSE"), None) + assert self.formatter._format_token(dt, None) == None + assert self.formatter._format_token(dt, "NONSENSE") == None def test_escape(self): - self.assertEqual( + assert ( self.formatter.format( datetime(2015, 12, 10, 17, 9), "MMMM D, YYYY [at] h:mma" - ), - "December 10, 2015 at 5:09pm", + ) + == "December 10, 2015 at 5:09pm" ) - self.assertEqual( + assert ( self.formatter.format( datetime(2015, 12, 10, 17, 9), "[MMMM] M D, YYYY [at] h:mma" - ), - "MMMM 12 10, 2015 at 5:09pm", + ) + == "MMMM 12 10, 2015 at 5:09pm" ) - self.assertEqual( + assert ( self.formatter.format( datetime(1990, 11, 25), "[It happened on] MMMM Do [in the year] YYYY [a long time ago]", - ), - "It happened on November 25th in the year 1990 a long time ago", + ) + == "It happened on November 25th in the year 1990 a long time ago" ) - self.assertEqual( + assert ( self.formatter.format( datetime(1990, 11, 25), "[It happened on] MMMM Do [in the][ year] YYYY [a long time ago]", - ), - "It happened on November 25th in the year 1990 a long time ago", + ) + == "It happened on November 25th in the year 1990 a long time ago" ) - self.assertEqual( + assert ( self.formatter.format( datetime(1, 1, 1), "[I'm][ entirely][ escaped,][ weee!]" - ), - "I'm entirely escaped, weee!", + ) + == "I'm entirely escaped, weee!" ) # Special RegEx characters - self.assertEqual( + assert ( self.formatter.format( datetime(2017, 12, 31, 2, 0), "MMM DD, YYYY |^${}().*+?<>-& h:mm A" - ), - "Dec 31, 2017 |^${}().*+?<>-& 2:00 AM", + ) + == "Dec 31, 2017 |^${}().*+?<>-& 2:00 AM" ) # Escaping is atomic: brackets inside brackets are treated litterally - self.assertEqual(self.formatter.format(datetime(1, 1, 1), "[[[ ]]"), "[[ ]") + assert self.formatter.format(datetime(1, 1, 1), "[[[ ]]") == "[[ ]" diff --git a/tests/formatter_tests.py.bak b/tests/formatter_tests.py.bak new file mode 100644 index 000000000..848ac260a --- /dev/null +++ b/tests/formatter_tests.py.bak @@ -0,0 +1,199 @@ +# -*- coding: utf-8 -*- +import time +from datetime import datetime + +import pytz +from chai import Chai +from dateutil import tz as dateutil_tz + +from arrow import formatter + +from .utils import make_full_tz_list + + +class DateTimeFormatterFormatTokenTests(Chai): + def setUp(self): + super(DateTimeFormatterFormatTokenTests, self).setUp() + + self.formatter = formatter.DateTimeFormatter() + + def test_format(self): + + dt = datetime(2013, 2, 5, 12, 32, 51) + + result = self.formatter.format(dt, "MM-DD-YYYY hh:mm:ss a") + + self.assertEqual(result, "02-05-2013 12:32:51 pm") + + def test_year(self): + + dt = datetime(2013, 1, 1) + self.assertEqual(self.formatter._format_token(dt, "YYYY"), "2013") + self.assertEqual(self.formatter._format_token(dt, "YY"), "13") + + def test_month(self): + + dt = datetime(2013, 1, 1) + self.assertEqual(self.formatter._format_token(dt, "MMMM"), "January") + self.assertEqual(self.formatter._format_token(dt, "MMM"), "Jan") + self.assertEqual(self.formatter._format_token(dt, "MM"), "01") + self.assertEqual(self.formatter._format_token(dt, "M"), "1") + + def test_day(self): + + dt = datetime(2013, 2, 1) + self.assertEqual(self.formatter._format_token(dt, "DDDD"), "032") + self.assertEqual(self.formatter._format_token(dt, "DDD"), "32") + self.assertEqual(self.formatter._format_token(dt, "DD"), "01") + self.assertEqual(self.formatter._format_token(dt, "D"), "1") + self.assertEqual(self.formatter._format_token(dt, "Do"), "1st") + + self.assertEqual(self.formatter._format_token(dt, "dddd"), "Friday") + self.assertEqual(self.formatter._format_token(dt, "ddd"), "Fri") + self.assertEqual(self.formatter._format_token(dt, "d"), "5") + + def test_hour(self): + + dt = datetime(2013, 1, 1, 2) + self.assertEqual(self.formatter._format_token(dt, "HH"), "02") + self.assertEqual(self.formatter._format_token(dt, "H"), "2") + + dt = datetime(2013, 1, 1, 13) + self.assertEqual(self.formatter._format_token(dt, "HH"), "13") + self.assertEqual(self.formatter._format_token(dt, "H"), "13") + + dt = datetime(2013, 1, 1, 2) + self.assertEqual(self.formatter._format_token(dt, "hh"), "02") + self.assertEqual(self.formatter._format_token(dt, "h"), "2") + + dt = datetime(2013, 1, 1, 13) + self.assertEqual(self.formatter._format_token(dt, "hh"), "01") + self.assertEqual(self.formatter._format_token(dt, "h"), "1") + + # test that 12-hour time converts to '12' at midnight + dt = datetime(2013, 1, 1, 0) + self.assertEqual(self.formatter._format_token(dt, "hh"), "12") + self.assertEqual(self.formatter._format_token(dt, "h"), "12") + + def test_minute(self): + + dt = datetime(2013, 1, 1, 0, 1) + self.assertEqual(self.formatter._format_token(dt, "mm"), "01") + self.assertEqual(self.formatter._format_token(dt, "m"), "1") + + def test_second(self): + + dt = datetime(2013, 1, 1, 0, 0, 1) + self.assertEqual(self.formatter._format_token(dt, "ss"), "01") + self.assertEqual(self.formatter._format_token(dt, "s"), "1") + + def test_sub_second(self): + + dt = datetime(2013, 1, 1, 0, 0, 0, 123456) + self.assertEqual(self.formatter._format_token(dt, "SSSSSS"), "123456") + self.assertEqual(self.formatter._format_token(dt, "SSSSS"), "12345") + self.assertEqual(self.formatter._format_token(dt, "SSSS"), "1234") + self.assertEqual(self.formatter._format_token(dt, "SSS"), "123") + self.assertEqual(self.formatter._format_token(dt, "SS"), "12") + self.assertEqual(self.formatter._format_token(dt, "S"), "1") + + dt = datetime(2013, 1, 1, 0, 0, 0, 2000) + self.assertEqual(self.formatter._format_token(dt, "SSSSSS"), "002000") + self.assertEqual(self.formatter._format_token(dt, "SSSSS"), "00200") + self.assertEqual(self.formatter._format_token(dt, "SSSS"), "0020") + self.assertEqual(self.formatter._format_token(dt, "SSS"), "002") + self.assertEqual(self.formatter._format_token(dt, "SS"), "00") + self.assertEqual(self.formatter._format_token(dt, "S"), "0") + + def test_timestamp(self): + + timestamp = time.time() + dt = datetime.utcfromtimestamp(timestamp) + self.assertEqual(self.formatter._format_token(dt, "X"), str(int(timestamp))) + + def test_timezone(self): + + dt = datetime.utcnow().replace(tzinfo=dateutil_tz.gettz("US/Pacific")) + + result = self.formatter._format_token(dt, "ZZ") + self.assertTrue(result == "-07:00" or result == "-08:00") + + result = self.formatter._format_token(dt, "Z") + self.assertTrue(result == "-0700" or result == "-0800") + + def test_timezone_formatter(self): + + for full_name in make_full_tz_list(): + # This test will fail if we use "now" as date as soon as we change from/to DST + dt = datetime(1986, 2, 14, tzinfo=pytz.timezone("UTC")).replace( + tzinfo=dateutil_tz.gettz(full_name) + ) + abbreviation = dt.tzname() + + result = self.formatter._format_token(dt, "ZZZ") + self.assertEqual(result, abbreviation) + + def test_am_pm(self): + + dt = datetime(2012, 1, 1, 11) + self.assertEqual(self.formatter._format_token(dt, "a"), "am") + self.assertEqual(self.formatter._format_token(dt, "A"), "AM") + + dt = datetime(2012, 1, 1, 13) + self.assertEqual(self.formatter._format_token(dt, "a"), "pm") + self.assertEqual(self.formatter._format_token(dt, "A"), "PM") + + def test_nonsense(self): + dt = datetime(2012, 1, 1, 11) + self.assertEqual(self.formatter._format_token(dt, None), None) + self.assertEqual(self.formatter._format_token(dt, "NONSENSE"), None) + + def test_escape(self): + + self.assertEqual( + self.formatter.format( + datetime(2015, 12, 10, 17, 9), "MMMM D, YYYY [at] h:mma" + ), + "December 10, 2015 at 5:09pm", + ) + + self.assertEqual( + self.formatter.format( + datetime(2015, 12, 10, 17, 9), "[MMMM] M D, YYYY [at] h:mma" + ), + "MMMM 12 10, 2015 at 5:09pm", + ) + + self.assertEqual( + self.formatter.format( + datetime(1990, 11, 25), + "[It happened on] MMMM Do [in the year] YYYY [a long time ago]", + ), + "It happened on November 25th in the year 1990 a long time ago", + ) + + self.assertEqual( + self.formatter.format( + datetime(1990, 11, 25), + "[It happened on] MMMM Do [in the][ year] YYYY [a long time ago]", + ), + "It happened on November 25th in the year 1990 a long time ago", + ) + + self.assertEqual( + self.formatter.format( + datetime(1, 1, 1), "[I'm][ entirely][ escaped,][ weee!]" + ), + "I'm entirely escaped, weee!", + ) + + # Special RegEx characters + self.assertEqual( + self.formatter.format( + datetime(2017, 12, 31, 2, 0), "MMM DD, YYYY |^${}().*+?<>-& h:mm A" + ), + "Dec 31, 2017 |^${}().*+?<>-& 2:00 AM", + ) + + # Escaping is atomic: brackets inside brackets are treated litterally + self.assertEqual(self.formatter.format(datetime(1, 1, 1), "[[[ ]]"), "[[ ]") From db5ac7e6204c1316fc708d5287dca3539b1ee536 Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Sat, 4 Jan 2020 14:43:18 -0500 Subject: [PATCH 05/13] Moved locales tests to pytest --- tests/formatter_tests.py | 4 +- tests/locales_tests.py | 1170 +++++++++++++++++------------------- tests/locales_tests.py.bak | 954 +++++++++++++++++++++++++++++ 3 files changed, 1507 insertions(+), 621 deletions(-) create mode 100644 tests/locales_tests.py.bak diff --git a/tests/formatter_tests.py b/tests/formatter_tests.py index 33accf755..dbf287364 100644 --- a/tests/formatter_tests.py +++ b/tests/formatter_tests.py @@ -143,8 +143,8 @@ def test_am_pm(self): def test_nonsense(self): dt = datetime(2012, 1, 1, 11) - assert self.formatter._format_token(dt, None) == None - assert self.formatter._format_token(dt, "NONSENSE") == None + assert self.formatter._format_token(dt, None) is None + assert self.formatter._format_token(dt, "NONSENSE") is None def test_escape(self): diff --git a/tests/locales_tests.py b/tests/locales_tests.py index af205b435..cd1e2e611 100644 --- a/tests/locales_tests.py +++ b/tests/locales_tests.py @@ -1,616 +1,586 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from chai import Chai - from arrow import arrow, locales +import pytest -class LocaleValidationTests(Chai): +class TestLocaleValidation: """Validate locales to ensure that translations are valid and complete""" - def setUp(self): - super(LocaleValidationTests, self).setUp() - - self.locales = locales._locales + @classmethod + def setup_class(cls): + cls.locales = locales._locales def test_locale_validation(self): for _, locale_cls in self.locales.items(): # 7 days + 1 spacer to allow for 1-indexing of months - self.assertEqual(len(locale_cls.day_names), 8) - self.assertTrue(locale_cls.day_names[0] == "") + assert len(locale_cls.day_names) == 8 + assert locale_cls.day_names[0] == "" # ensure that all string from index 1 onward are valid (not blank or None) - self.assertTrue(all(locale_cls.day_names[1:])) + assert all(locale_cls.day_names[1:]) - self.assertEqual(len(locale_cls.day_abbreviations), 8) - self.assertTrue(locale_cls.day_abbreviations[0] == "") - self.assertTrue(all(locale_cls.day_abbreviations[1:])) + assert len(locale_cls.day_abbreviations) == 8 + assert locale_cls.day_abbreviations[0] == "" + assert all(locale_cls.day_abbreviations[1:]) # 12 months + 1 spacer to allow for 1-indexing of months - self.assertEqual(len(locale_cls.month_names), 13) - self.assertTrue(locale_cls.month_names[0] == "") - self.assertTrue(all(locale_cls.month_names[1:])) + assert len(locale_cls.month_names) == 13 + assert locale_cls.month_names[0] == "" + assert all(locale_cls.month_names[1:]) - self.assertEqual(len(locale_cls.month_abbreviations), 13) - self.assertTrue(locale_cls.month_abbreviations[0] == "") - self.assertTrue(all(locale_cls.month_abbreviations[1:])) + assert len(locale_cls.month_abbreviations) == 13 + assert locale_cls.month_abbreviations[0] == "" + assert all(locale_cls.month_abbreviations[1:]) - self.assertTrue(len(locale_cls.names) > 0) - self.assertTrue(locale_cls.past is not None) - self.assertTrue(locale_cls.future is not None) + assert len(locale_cls.names) > 0 + assert locale_cls.past is not None + assert locale_cls.future is not None -class ModuleTests(Chai): - def test_get_locale(self): +class TestModule: + def test_get_locale(self, mocker): + mock_locale = mocker.Mock() + mock_locale_cls = mocker.Mock() + mock_locale_cls.return_value = mock_locale - mock_locales = self.mock(locales, "_locales") - mock_locale_cls = self.mock() - mock_locale = self.mock() + with pytest.raises(ValueError): + arrow.locales.get_locale("locale_name") - self.expect(mock_locales.get).args("name").returns(mock_locale_cls) - self.expect(mock_locale_cls).returns(mock_locale) + cls_dict = arrow.locales._locales + mocker.patch.dict(cls_dict, {"locale_name": mock_locale_cls}) - result = locales.get_locale("name") + result = arrow.locales.get_locale("locale_name") - self.assertEqual(result, mock_locale) + assert result == mock_locale def test_locales(self): - self.assertTrue(len(locales._locales) > 0) + assert len(locales._locales) > 0 -class LocaleTests(Chai): - def setUp(self): - super(LocaleTests, self).setUp() - - self.locale = locales.EnglishLocale() +class TestLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.EnglishLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 hours") - self.assertEqual(self.locale._format_timeframe("hour", 0), "an hour") + assert self.locale._format_timeframe("hours", 2) == "2 hours" + assert self.locale._format_timeframe("hour", 0) == "an hour" def test_format_relative_now(self): result = self.locale._format_relative("just now", "now", 0) - self.assertEqual(result, "just now") + assert result == "just now" def test_format_relative_past(self): result = self.locale._format_relative("an hour", "hour", 1) - self.assertEqual(result, "in an hour") + assert result == "in an hour" def test_format_relative_future(self): result = self.locale._format_relative("an hour", "hour", -1) - self.assertEqual(result, "an hour ago") + assert result == "an hour ago" def test_ordinal_number(self): - self.assertEqual(self.locale.ordinal_number(0), "0th") - self.assertEqual(self.locale.ordinal_number(1), "1st") - self.assertEqual(self.locale.ordinal_number(2), "2nd") - self.assertEqual(self.locale.ordinal_number(3), "3rd") - self.assertEqual(self.locale.ordinal_number(4), "4th") - self.assertEqual(self.locale.ordinal_number(10), "10th") - self.assertEqual(self.locale.ordinal_number(11), "11th") - self.assertEqual(self.locale.ordinal_number(12), "12th") - self.assertEqual(self.locale.ordinal_number(13), "13th") - self.assertEqual(self.locale.ordinal_number(14), "14th") - self.assertEqual(self.locale.ordinal_number(21), "21st") - self.assertEqual(self.locale.ordinal_number(22), "22nd") - self.assertEqual(self.locale.ordinal_number(23), "23rd") - self.assertEqual(self.locale.ordinal_number(24), "24th") - - self.assertEqual(self.locale.ordinal_number(100), "100th") - self.assertEqual(self.locale.ordinal_number(101), "101st") - self.assertEqual(self.locale.ordinal_number(102), "102nd") - self.assertEqual(self.locale.ordinal_number(103), "103rd") - self.assertEqual(self.locale.ordinal_number(104), "104th") - self.assertEqual(self.locale.ordinal_number(110), "110th") - self.assertEqual(self.locale.ordinal_number(111), "111th") - self.assertEqual(self.locale.ordinal_number(112), "112th") - self.assertEqual(self.locale.ordinal_number(113), "113th") - self.assertEqual(self.locale.ordinal_number(114), "114th") - self.assertEqual(self.locale.ordinal_number(121), "121st") - self.assertEqual(self.locale.ordinal_number(122), "122nd") - self.assertEqual(self.locale.ordinal_number(123), "123rd") - self.assertEqual(self.locale.ordinal_number(124), "124th") + assert self.locale.ordinal_number(0) == "0th" + assert self.locale.ordinal_number(1) == "1st" + assert self.locale.ordinal_number(2) == "2nd" + assert self.locale.ordinal_number(3) == "3rd" + assert self.locale.ordinal_number(4) == "4th" + assert self.locale.ordinal_number(10) == "10th" + assert self.locale.ordinal_number(11) == "11th" + assert self.locale.ordinal_number(12) == "12th" + assert self.locale.ordinal_number(13) == "13th" + assert self.locale.ordinal_number(14) == "14th" + assert self.locale.ordinal_number(21) == "21st" + assert self.locale.ordinal_number(22) == "22nd" + assert self.locale.ordinal_number(23) == "23rd" + assert self.locale.ordinal_number(24) == "24th" + + assert self.locale.ordinal_number(100) == "100th" + assert self.locale.ordinal_number(101) == "101st" + assert self.locale.ordinal_number(102) == "102nd" + assert self.locale.ordinal_number(103) == "103rd" + assert self.locale.ordinal_number(104) == "104th" + assert self.locale.ordinal_number(110) == "110th" + assert self.locale.ordinal_number(111) == "111th" + assert self.locale.ordinal_number(112) == "112th" + assert self.locale.ordinal_number(113) == "113th" + assert self.locale.ordinal_number(114) == "114th" + assert self.locale.ordinal_number(121) == "121st" + assert self.locale.ordinal_number(122) == "122nd" + assert self.locale.ordinal_number(123) == "123rd" + assert self.locale.ordinal_number(124) == "124th" def test_meridian_invalid_token(self): - self.assertEqual(self.locale.meridian(7, None), None) - self.assertEqual(self.locale.meridian(7, "B"), None) - self.assertEqual(self.locale.meridian(7, "NONSENSE"), None) - + assert self.locale.meridian(7, None) is None + assert self.locale.meridian(7, "B") is None + assert self.locale.meridian(7, "NONSENSE") is None -class EnglishLocaleTests(Chai): - def setUp(self): - super(EnglishLocaleTests, self).setUp() - self.locale = locales.EnglishLocale() +class TestEnglishLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.EnglishLocale() def test_describe(self): - self.assertEqual(self.locale.describe("now", only_distance=True), "instantly") - self.assertEqual(self.locale.describe("now", only_distance=False), "just now") + assert self.locale.describe("now", only_distance=True) == "instantly" + assert self.locale.describe("now", only_distance=False) == "just now" -class ItalianLocalesTests(Chai): +class TestItalianLocales: def test_ordinal_number(self): locale = locales.ItalianLocale() - self.assertEqual(locale.ordinal_number(1), "1º") + assert locale.ordinal_number(1) == "1º" -class SpanishLocalesTests(Chai): +class TestSpanishLocales: def test_ordinal_number(self): locale = locales.SpanishLocale() - self.assertEqual(locale.ordinal_number(1), "1º") + assert locale.ordinal_number(1) == "1º" def test_format_timeframe(self): locale = locales.SpanishLocale() - self.assertEqual(locale._format_timeframe("now", 0), "ahora") - self.assertEqual(locale._format_timeframe("seconds", 1), "1 segundos") - self.assertEqual(locale._format_timeframe("seconds", 3), "3 segundos") - self.assertEqual(locale._format_timeframe("seconds", 30), "30 segundos") - self.assertEqual(locale._format_timeframe("minute", 1), "un minuto") - self.assertEqual(locale._format_timeframe("minutes", 4), "4 minutos") - self.assertEqual(locale._format_timeframe("minutes", 40), "40 minutos") - self.assertEqual(locale._format_timeframe("hour", 1), "una hora") - self.assertEqual(locale._format_timeframe("hours", 5), "5 horas") - self.assertEqual(locale._format_timeframe("hours", 23), "23 horas") - self.assertEqual(locale._format_timeframe("day", 1), "un día") - self.assertEqual(locale._format_timeframe("days", 6), "6 días") - self.assertEqual(locale._format_timeframe("days", 12), "12 días") - self.assertEqual(locale._format_timeframe("week", 1), "una semana") - self.assertEqual(locale._format_timeframe("weeks", 2), "2 semanas") - self.assertEqual(locale._format_timeframe("weeks", 3), "3 semanas") - self.assertEqual(locale._format_timeframe("month", 1), "un mes") - self.assertEqual(locale._format_timeframe("months", 7), "7 meses") - self.assertEqual(locale._format_timeframe("months", 11), "11 meses") - self.assertEqual(locale._format_timeframe("year", 1), "un año") - self.assertEqual(locale._format_timeframe("years", 8), "8 años") - self.assertEqual(locale._format_timeframe("years", 12), "12 años") - - self.assertEqual(locale._format_timeframe("now", 0), "ahora") - self.assertEqual(locale._format_timeframe("seconds", -1), "1 segundos") - self.assertEqual(locale._format_timeframe("seconds", -9), "9 segundos") - self.assertEqual(locale._format_timeframe("seconds", -12), "12 segundos") - self.assertEqual(locale._format_timeframe("minute", -1), "un minuto") - self.assertEqual(locale._format_timeframe("minutes", -2), "2 minutos") - self.assertEqual(locale._format_timeframe("minutes", -10), "10 minutos") - self.assertEqual(locale._format_timeframe("hour", -1), "una hora") - self.assertEqual(locale._format_timeframe("hours", -3), "3 horas") - self.assertEqual(locale._format_timeframe("hours", -11), "11 horas") - self.assertEqual(locale._format_timeframe("day", -1), "un día") - self.assertEqual(locale._format_timeframe("days", -2), "2 días") - self.assertEqual(locale._format_timeframe("days", -12), "12 días") - self.assertEqual(locale._format_timeframe("week", -1), "una semana") - self.assertEqual(locale._format_timeframe("weeks", -2), "2 semanas") - self.assertEqual(locale._format_timeframe("weeks", -3), "3 semanas") - self.assertEqual(locale._format_timeframe("month", -1), "un mes") - self.assertEqual(locale._format_timeframe("months", -3), "3 meses") - self.assertEqual(locale._format_timeframe("months", -13), "13 meses") - self.assertEqual(locale._format_timeframe("year", -1), "un año") - self.assertEqual(locale._format_timeframe("years", -4), "4 años") - self.assertEqual(locale._format_timeframe("years", -14), "14 años") - - -class FrenchLocalesTests(Chai): + assert locale._format_timeframe("now", 0) == "ahora" + assert locale._format_timeframe("seconds", 1) == "1 segundos" + assert locale._format_timeframe("seconds", 3) == "3 segundos" + assert locale._format_timeframe("seconds", 30) == "30 segundos" + assert locale._format_timeframe("minute", 1) == "un minuto" + assert locale._format_timeframe("minutes", 4) == "4 minutos" + assert locale._format_timeframe("minutes", 40) == "40 minutos" + assert locale._format_timeframe("hour", 1) == "una hora" + assert locale._format_timeframe("hours", 5) == "5 horas" + assert locale._format_timeframe("hours", 23) == "23 horas" + assert locale._format_timeframe("day", 1) == "un día" + assert locale._format_timeframe("days", 6) == "6 días" + assert locale._format_timeframe("days", 12) == "12 días" + assert locale._format_timeframe("week", 1) == "una semana" + assert locale._format_timeframe("weeks", 2) == "2 semanas" + assert locale._format_timeframe("weeks", 3) == "3 semanas" + assert locale._format_timeframe("month", 1) == "un mes" + assert locale._format_timeframe("months", 7) == "7 meses" + assert locale._format_timeframe("months", 11) == "11 meses" + assert locale._format_timeframe("year", 1) == "un año" + assert locale._format_timeframe("years", 8) == "8 años" + assert locale._format_timeframe("years", 12) == "12 años" + + assert locale._format_timeframe("now", 0) == "ahora" + assert locale._format_timeframe("seconds", -1) == "1 segundos" + assert locale._format_timeframe("seconds", -9) == "9 segundos" + assert locale._format_timeframe("seconds", -12) == "12 segundos" + assert locale._format_timeframe("minute", -1) == "un minuto" + assert locale._format_timeframe("minutes", -2) == "2 minutos" + assert locale._format_timeframe("minutes", -10) == "10 minutos" + assert locale._format_timeframe("hour", -1) == "una hora" + assert locale._format_timeframe("hours", -3) == "3 horas" + assert locale._format_timeframe("hours", -11) == "11 horas" + assert locale._format_timeframe("day", -1) == "un día" + assert locale._format_timeframe("days", -2) == "2 días" + assert locale._format_timeframe("days", -12) == "12 días" + assert locale._format_timeframe("week", -1) == "una semana" + assert locale._format_timeframe("weeks", -2) == "2 semanas" + assert locale._format_timeframe("weeks", -3) == "3 semanas" + assert locale._format_timeframe("month", -1) == "un mes" + assert locale._format_timeframe("months", -3) == "3 meses" + assert locale._format_timeframe("months", -13) == "13 meses" + assert locale._format_timeframe("year", -1) == "un año" + assert locale._format_timeframe("years", -4) == "4 años" + assert locale._format_timeframe("years", -14) == "14 años" + + +class TestFrenchLocales: def test_ordinal_number(self): locale = locales.FrenchLocale() - self.assertEqual(locale.ordinal_number(1), "1er") - self.assertEqual(locale.ordinal_number(2), "2e") + assert locale.ordinal_number(1) == "1er" + assert locale.ordinal_number(2) == "2e" -class RussianLocalesTests(Chai): +class TestRussianLocales: def test_plurals2(self): locale = locales.RussianLocale() - self.assertEqual(locale._format_timeframe("hours", 0), "0 часов") - self.assertEqual(locale._format_timeframe("hours", 1), "1 час") - self.assertEqual(locale._format_timeframe("hours", 2), "2 часа") - self.assertEqual(locale._format_timeframe("hours", 4), "4 часа") - self.assertEqual(locale._format_timeframe("hours", 5), "5 часов") - self.assertEqual(locale._format_timeframe("hours", 21), "21 час") - self.assertEqual(locale._format_timeframe("hours", 22), "22 часа") - self.assertEqual(locale._format_timeframe("hours", 25), "25 часов") + assert locale._format_timeframe("hours", 0) == "0 часов" + assert locale._format_timeframe("hours", 1) == "1 час" + assert locale._format_timeframe("hours", 2) == "2 часа" + assert locale._format_timeframe("hours", 4) == "4 часа" + assert locale._format_timeframe("hours", 5) == "5 часов" + assert locale._format_timeframe("hours", 21) == "21 час" + assert locale._format_timeframe("hours", 22) == "22 часа" + assert locale._format_timeframe("hours", 25) == "25 часов" # feminine grammatical gender should be tested separately - self.assertEqual(locale._format_timeframe("minutes", 0), "0 минут") - self.assertEqual(locale._format_timeframe("minutes", 1), "1 минуту") - self.assertEqual(locale._format_timeframe("minutes", 2), "2 минуты") - self.assertEqual(locale._format_timeframe("minutes", 4), "4 минуты") - self.assertEqual(locale._format_timeframe("minutes", 5), "5 минут") - self.assertEqual(locale._format_timeframe("minutes", 21), "21 минуту") - self.assertEqual(locale._format_timeframe("minutes", 22), "22 минуты") - self.assertEqual(locale._format_timeframe("minutes", 25), "25 минут") + assert locale._format_timeframe("minutes", 0) == "0 минут" + assert locale._format_timeframe("minutes", 1) == "1 минуту" + assert locale._format_timeframe("minutes", 2) == "2 минуты" + assert locale._format_timeframe("minutes", 4) == "4 минуты" + assert locale._format_timeframe("minutes", 5) == "5 минут" + assert locale._format_timeframe("minutes", 21) == "21 минуту" + assert locale._format_timeframe("minutes", 22) == "22 минуты" + assert locale._format_timeframe("minutes", 25) == "25 минут" -class PolishLocalesTests(Chai): +class TestPolishLocales: def test_plurals(self): locale = locales.PolishLocale() - self.assertEqual(locale._format_timeframe("hours", 0), "0 godzin") - self.assertEqual(locale._format_timeframe("hours", 1), "1 godzin") - self.assertEqual(locale._format_timeframe("hours", 2), "2 godziny") - self.assertEqual(locale._format_timeframe("hours", 4), "4 godziny") - self.assertEqual(locale._format_timeframe("hours", 5), "5 godzin") - self.assertEqual(locale._format_timeframe("hours", 21), "21 godzin") - self.assertEqual(locale._format_timeframe("hours", 22), "22 godziny") - self.assertEqual(locale._format_timeframe("hours", 25), "25 godzin") + assert locale._format_timeframe("hours", 0) == "0 godzin" + assert locale._format_timeframe("hours", 1) == "1 godzin" + assert locale._format_timeframe("hours", 2) == "2 godziny" + assert locale._format_timeframe("hours", 4) == "4 godziny" + assert locale._format_timeframe("hours", 5) == "5 godzin" + assert locale._format_timeframe("hours", 21) == "21 godzin" + assert locale._format_timeframe("hours", 22) == "22 godziny" + assert locale._format_timeframe("hours", 25) == "25 godzin" -class IcelandicLocalesTests(Chai): - def setUp(self): - super(IcelandicLocalesTests, self).setUp() - - self.locale = locales.IcelandicLocale() +class TestIcelandicLocales: + @classmethod + def setup_class(cls): + cls.locale = locales.IcelandicLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("minute", -1), "einni mínútu") - self.assertEqual(self.locale._format_timeframe("minute", 1), "eina mínútu") - - self.assertEqual(self.locale._format_timeframe("hours", -2), "2 tímum") - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 tíma") - self.assertEqual(self.locale._format_timeframe("now", 0), "rétt í þessu") + assert self.locale._format_timeframe("minute", -1) == "einni mínútu" + assert self.locale._format_timeframe("minute", 1) == "eina mínútu" + assert self.locale._format_timeframe("hours", -2) == "2 tímum" + assert self.locale._format_timeframe("hours", 2) == "2 tíma" + assert self.locale._format_timeframe("now", 0) == "rétt í þessu" -class MalayalamLocaleTests(Chai): - def setUp(self): - super(MalayalamLocaleTests, self).setUp() - self.locale = locales.MalayalamLocale() +class TestMalayalamLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.MalayalamLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 മണിക്കൂർ") - self.assertEqual(self.locale._format_timeframe("hour", 0), "ഒരു മണിക്കൂർ") + assert self.locale._format_timeframe("hours", 2) == "2 മണിക്കൂർ" + assert self.locale._format_timeframe("hour", 0) == "ഒരു മണിക്കൂർ" def test_format_relative_now(self): result = self.locale._format_relative("ഇപ്പോൾ", "now", 0) - self.assertEqual(result, "ഇപ്പോൾ") + assert result == "ഇപ്പോൾ" def test_format_relative_past(self): result = self.locale._format_relative("ഒരു മണിക്കൂർ", "hour", 1) - self.assertEqual(result, "ഒരു മണിക്കൂർ ശേഷം") + assert result == "ഒരു മണിക്കൂർ ശേഷം" def test_format_relative_future(self): result = self.locale._format_relative("ഒരു മണിക്കൂർ", "hour", -1) - self.assertEqual(result, "ഒരു മണിക്കൂർ മുമ്പ്") - + assert result == "ഒരു മണിക്കൂർ മുമ്പ്" -class HindiLocaleTests(Chai): - def setUp(self): - super(HindiLocaleTests, self).setUp() - self.locale = locales.HindiLocale() +class TestHindiLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.HindiLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 घंटे") - self.assertEqual(self.locale._format_timeframe("hour", 0), "एक घंटा") + assert self.locale._format_timeframe("hours", 2) == "2 घंटे" + assert self.locale._format_timeframe("hour", 0) == "एक घंटा" def test_format_relative_now(self): result = self.locale._format_relative("अभी", "now", 0) - self.assertEqual(result, "अभी") + assert result == "अभी" def test_format_relative_past(self): result = self.locale._format_relative("एक घंटा", "hour", 1) - self.assertEqual(result, "एक घंटा बाद") + assert result == "एक घंटा बाद" def test_format_relative_future(self): result = self.locale._format_relative("एक घंटा", "hour", -1) - self.assertEqual(result, "एक घंटा पहले") + assert result == "एक घंटा पहले" -class CzechLocaleTests(Chai): - def setUp(self): - super(CzechLocaleTests, self).setUp() - - self.locale = locales.CzechLocale() +class TestCzechLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.CzechLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 hodiny") - self.assertEqual(self.locale._format_timeframe("hours", 5), "5 hodin") - self.assertEqual(self.locale._format_timeframe("hour", 0), "0 hodin") - self.assertEqual(self.locale._format_timeframe("hours", -2), "2 hodinami") - self.assertEqual(self.locale._format_timeframe("hours", -5), "5 hodinami") - self.assertEqual(self.locale._format_timeframe("now", 0), "Teď") + assert self.locale._format_timeframe("hours", 2) == "2 hodiny" + assert self.locale._format_timeframe("hours", 5) == "5 hodin" + assert self.locale._format_timeframe("hour", 0) == "0 hodin" + assert self.locale._format_timeframe("hours", -2) == "2 hodinami" + assert self.locale._format_timeframe("hours", -5) == "5 hodinami" + assert self.locale._format_timeframe("now", 0) == "Teď" def test_format_relative_now(self): result = self.locale._format_relative("Teď", "now", 0) - self.assertEqual(result, "Teď") + assert result == "Teď" def test_format_relative_future(self): result = self.locale._format_relative("hodinu", "hour", 1) - self.assertEqual(result, "Za hodinu") + assert result == "Za hodinu" def test_format_relative_past(self): result = self.locale._format_relative("hodinou", "hour", -1) - self.assertEqual(result, "Před hodinou") - + assert result == "Před hodinou" -class SlovakLocaleTests(Chai): - def setUp(self): - super(SlovakLocaleTests, self).setUp() - self.locale = locales.SlovakLocale() +class TestSlovakLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.SlovakLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 hodiny") - self.assertEqual(self.locale._format_timeframe("hours", 5), "5 hodín") - self.assertEqual(self.locale._format_timeframe("hour", 0), "0 hodín") - self.assertEqual(self.locale._format_timeframe("hours", -2), "2 hodinami") - self.assertEqual(self.locale._format_timeframe("hours", -5), "5 hodinami") - self.assertEqual(self.locale._format_timeframe("now", 0), "Teraz") + assert self.locale._format_timeframe("hours", 2) == "2 hodiny" + assert self.locale._format_timeframe("hours", 5) == "5 hodín" + assert self.locale._format_timeframe("hour", 0) == "0 hodín" + assert self.locale._format_timeframe("hours", -2) == "2 hodinami" + assert self.locale._format_timeframe("hours", -5) == "5 hodinami" + assert self.locale._format_timeframe("now", 0) == "Teraz" def test_format_relative_now(self): result = self.locale._format_relative("Teraz", "now", 0) - self.assertEqual(result, "Teraz") + assert result == "Teraz" def test_format_relative_future(self): result = self.locale._format_relative("hodinu", "hour", 1) - self.assertEqual(result, "O hodinu") + assert result == "O hodinu" def test_format_relative_past(self): result = self.locale._format_relative("hodinou", "hour", -1) - self.assertEqual(result, "Pred hodinou") + assert result == "Pred hodinou" -class BulgarianLocaleTests(Chai): +class TestBulgarianLocale: def test_plurals2(self): locale = locales.BulgarianLocale() - self.assertEqual(locale._format_timeframe("hours", 0), "0 часа") - self.assertEqual(locale._format_timeframe("hours", 1), "1 час") - self.assertEqual(locale._format_timeframe("hours", 2), "2 часа") - self.assertEqual(locale._format_timeframe("hours", 4), "4 часа") - self.assertEqual(locale._format_timeframe("hours", 5), "5 часа") - self.assertEqual(locale._format_timeframe("hours", 21), "21 час") - self.assertEqual(locale._format_timeframe("hours", 22), "22 часа") - self.assertEqual(locale._format_timeframe("hours", 25), "25 часа") + assert locale._format_timeframe("hours", 0) == "0 часа" + assert locale._format_timeframe("hours", 1) == "1 час" + assert locale._format_timeframe("hours", 2) == "2 часа" + assert locale._format_timeframe("hours", 4) == "4 часа" + assert locale._format_timeframe("hours", 5) == "5 часа" + assert locale._format_timeframe("hours", 21) == "21 час" + assert locale._format_timeframe("hours", 22) == "22 часа" + assert locale._format_timeframe("hours", 25) == "25 часа" # feminine grammatical gender should be tested separately - self.assertEqual(locale._format_timeframe("minutes", 0), "0 минути") - self.assertEqual(locale._format_timeframe("minutes", 1), "1 минута") - self.assertEqual(locale._format_timeframe("minutes", 2), "2 минути") - self.assertEqual(locale._format_timeframe("minutes", 4), "4 минути") - self.assertEqual(locale._format_timeframe("minutes", 5), "5 минути") - self.assertEqual(locale._format_timeframe("minutes", 21), "21 минута") - self.assertEqual(locale._format_timeframe("minutes", 22), "22 минути") - self.assertEqual(locale._format_timeframe("minutes", 25), "25 минути") + assert locale._format_timeframe("minutes", 0) == "0 минути" + assert locale._format_timeframe("minutes", 1) == "1 минута" + assert locale._format_timeframe("minutes", 2) == "2 минути" + assert locale._format_timeframe("minutes", 4) == "4 минути" + assert locale._format_timeframe("minutes", 5) == "5 минути" + assert locale._format_timeframe("minutes", 21) == "21 минута" + assert locale._format_timeframe("minutes", 22) == "22 минути" + assert locale._format_timeframe("minutes", 25) == "25 минути" -class MacedonianLocaleTests(Chai): +class TestMacedonianLocale: def test_plurals_mk(self): locale = locales.MacedonianLocale() # time - self.assertEqual(locale._format_relative("сега", "now", 0), "сега") + assert locale._format_relative("сега", "now", 0) == "сега" # Hours - self.assertEqual(locale._format_timeframe("hours", 0), "0 саати") - self.assertEqual(locale._format_timeframe("hours", 1), "1 саат") - self.assertEqual(locale._format_timeframe("hours", 2), "2 саати") - self.assertEqual(locale._format_timeframe("hours", 4), "4 саати") - self.assertEqual(locale._format_timeframe("hours", 5), "5 саати") - self.assertEqual(locale._format_timeframe("hours", 21), "21 саат") - self.assertEqual(locale._format_timeframe("hours", 22), "22 саати") - self.assertEqual(locale._format_timeframe("hours", 25), "25 саати") + assert locale._format_timeframe("hours", 0) == "0 саати" + assert locale._format_timeframe("hours", 1) == "1 саат" + assert locale._format_timeframe("hours", 2) == "2 саати" + assert locale._format_timeframe("hours", 4) == "4 саати" + assert locale._format_timeframe("hours", 5) == "5 саати" + assert locale._format_timeframe("hours", 21) == "21 саат" + assert locale._format_timeframe("hours", 22) == "22 саати" + assert locale._format_timeframe("hours", 25) == "25 саати" # Minutes - self.assertEqual(locale._format_timeframe("minutes", 0), "0 минути") - self.assertEqual(locale._format_timeframe("minutes", 1), "1 минута") - self.assertEqual(locale._format_timeframe("minutes", 2), "2 минути") - self.assertEqual(locale._format_timeframe("minutes", 4), "4 минути") - self.assertEqual(locale._format_timeframe("minutes", 5), "5 минути") - self.assertEqual(locale._format_timeframe("minutes", 21), "21 минута") - self.assertEqual(locale._format_timeframe("minutes", 22), "22 минути") - self.assertEqual(locale._format_timeframe("minutes", 25), "25 минути") + assert locale._format_timeframe("minutes", 0) == "0 минути" + assert locale._format_timeframe("minutes", 1) == "1 минута" + assert locale._format_timeframe("minutes", 2) == "2 минути" + assert locale._format_timeframe("minutes", 4) == "4 минути" + assert locale._format_timeframe("minutes", 5) == "5 минути" + assert locale._format_timeframe("minutes", 21) == "21 минута" + assert locale._format_timeframe("minutes", 22) == "22 минути" + assert locale._format_timeframe("minutes", 25) == "25 минути" -class HebrewLocaleTests(Chai): +class TestHebrewLocale: def test_couple_of_timeframe(self): locale = locales.HebrewLocale() - self.assertEqual(locale._format_timeframe("hours", 2), "שעתיים") - self.assertEqual(locale._format_timeframe("months", 2), "חודשיים") - self.assertEqual(locale._format_timeframe("days", 2), "יומיים") - self.assertEqual(locale._format_timeframe("years", 2), "שנתיים") - - self.assertEqual(locale._format_timeframe("hours", 3), "3 שעות") - self.assertEqual(locale._format_timeframe("months", 4), "4 חודשים") - self.assertEqual(locale._format_timeframe("days", 3), "3 ימים") - self.assertEqual(locale._format_timeframe("years", 5), "5 שנים") + assert locale._format_timeframe("hours", 2) == "שעתיים" + assert locale._format_timeframe("months", 2) == "חודשיים" + assert locale._format_timeframe("days", 2) == "יומיים" + assert locale._format_timeframe("years", 2) == "שנתיים" + assert locale._format_timeframe("hours", 3) == "3 שעות" + assert locale._format_timeframe("months", 4) == "4 חודשים" + assert locale._format_timeframe("days", 3) == "3 ימים" + assert locale._format_timeframe("years", 5) == "5 שנים" -class MarathiLocaleTests(Chai): - def setUp(self): - super(MarathiLocaleTests, self).setUp() - self.locale = locales.MarathiLocale() +class TestMarathiLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.MarathiLocale() def test_dateCoreFunctionality(self): dt = arrow.Arrow(2015, 4, 11, 17, 30, 00) - self.assertEqual(self.locale.month_name(dt.month), "एप्रिल") - self.assertEqual(self.locale.month_abbreviation(dt.month), "एप्रि") - self.assertEqual(self.locale.day_name(dt.isoweekday()), "शनिवार") - self.assertEqual(self.locale.day_abbreviation(dt.isoweekday()), "शनि") + assert self.locale.month_name(dt.month) == "एप्रिल" + assert self.locale.month_abbreviation(dt.month) == "एप्रि" + assert self.locale.day_name(dt.isoweekday()) == "शनिवार" + assert self.locale.day_abbreviation(dt.isoweekday()) == "शनि" def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 तास") - self.assertEqual(self.locale._format_timeframe("hour", 0), "एक तास") + assert self.locale._format_timeframe("hours", 2) == "2 तास" + assert self.locale._format_timeframe("hour", 0) == "एक तास" def test_format_relative_now(self): result = self.locale._format_relative("सद्य", "now", 0) - self.assertEqual(result, "सद्य") + assert result == "सद्य" def test_format_relative_past(self): result = self.locale._format_relative("एक तास", "hour", 1) - self.assertEqual(result, "एक तास नंतर") + assert result == "एक तास नंतर" def test_format_relative_future(self): result = self.locale._format_relative("एक तास", "hour", -1) - self.assertEqual(result, "एक तास आधी") + assert result == "एक तास आधी" # Not currently implemented def test_ordinal_number(self): - self.assertEqual(self.locale.ordinal_number(1), "1") + assert self.locale.ordinal_number(1) == "1" -class FinnishLocaleTests(Chai): - def setUp(self): - super(FinnishLocaleTests, self).setUp() - - self.locale = locales.FinnishLocale() +class TestFinnishLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.FinnishLocale() def test_format_timeframe(self): - self.assertEqual( - self.locale._format_timeframe("hours", 2), ("2 tuntia", "2 tunnin") - ) - self.assertEqual(self.locale._format_timeframe("hour", 0), ("tunti", "tunnin")) + assert self.locale._format_timeframe("hours", 2) == ("2 tuntia", "2 tunnin") + assert self.locale._format_timeframe("hour", 0) == ("tunti", "tunnin") def test_format_relative_now(self): result = self.locale._format_relative(["juuri nyt", "juuri nyt"], "now", 0) - self.assertEqual(result, "juuri nyt") + assert result == "juuri nyt" def test_format_relative_past(self): result = self.locale._format_relative(["tunti", "tunnin"], "hour", 1) - self.assertEqual(result, "tunnin kuluttua") + assert result == "tunnin kuluttua" def test_format_relative_future(self): result = self.locale._format_relative(["tunti", "tunnin"], "hour", -1) - self.assertEqual(result, "tunti sitten") + assert result == "tunti sitten" def test_ordinal_number(self): - self.assertEqual(self.locale.ordinal_number(1), "1.") - + assert self.locale.ordinal_number(1) == "1." -class GermanLocaleTests(Chai): - def setUp(self): - super(GermanLocaleTests, self).setUp() - self.locale = locales.GermanLocale() +class TestGermanLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.GermanLocale() def test_ordinal_number(self): - self.assertEqual(self.locale.ordinal_number(1), "1.") + assert self.locale.ordinal_number(1) == "1." def test_define(self): - self.assertEqual( - self.locale.describe("minute", only_distance=True), "eine Minute" - ) - self.assertEqual( - self.locale.describe("minute", only_distance=False), "in einer Minute" - ) - self.assertEqual( - self.locale.describe("hour", only_distance=True), "eine Stunde" - ) - self.assertEqual( - self.locale.describe("hour", only_distance=False), "in einer Stunde" - ) - self.assertEqual(self.locale.describe("day", only_distance=True), "ein Tag") - self.assertEqual( - self.locale.describe("day", only_distance=False), "in einem Tag" - ) - self.assertEqual(self.locale.describe("month", only_distance=True), "ein Monat") - self.assertEqual( - self.locale.describe("month", only_distance=False), "in einem Monat" - ) - self.assertEqual(self.locale.describe("year", only_distance=True), "ein Jahr") - self.assertEqual( - self.locale.describe("year", only_distance=False), "in einem Jahr" - ) - - -class HungarianLocaleTests(Chai): - def setUp(self): - super(HungarianLocaleTests, self).setUp() - - self.locale = locales.HungarianLocale() + assert self.locale.describe("minute", only_distance=True) == "eine Minute" + assert self.locale.describe("minute", only_distance=False) == "in einer Minute" + assert self.locale.describe("hour", only_distance=True) == "eine Stunde" + assert self.locale.describe("hour", only_distance=False) == "in einer Stunde" + assert self.locale.describe("day", only_distance=True) == "ein Tag" + assert self.locale.describe("day", only_distance=False) == "in einem Tag" + assert self.locale.describe("month", only_distance=True) == "ein Monat" + assert self.locale.describe("month", only_distance=False) == "in einem Monat" + assert self.locale.describe("year", only_distance=True) == "ein Jahr" + assert self.locale.describe("year", only_distance=False) == "in einem Jahr" + + +class TestHungarianLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.HungarianLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 óra") - self.assertEqual(self.locale._format_timeframe("hour", 0), "egy órával") - self.assertEqual(self.locale._format_timeframe("hours", -2), "2 órával") - self.assertEqual(self.locale._format_timeframe("now", 0), "éppen most") - + assert self.locale._format_timeframe("hours", 2) == "2 óra" + assert self.locale._format_timeframe("hour", 0) == "egy órával" + assert self.locale._format_timeframe("hours", -2) == "2 órával" + assert self.locale._format_timeframe("now", 0) == "éppen most" -class EsperantoLocaleTests(Chai): - def setUp(self): - super(EsperantoLocaleTests, self).setUp() - self.locale = locales.EsperantoLocale() +class TestEsperantoLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.EsperantoLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 horoj") - self.assertEqual(self.locale._format_timeframe("hour", 0), "un horo") - self.assertEqual(self.locale._format_timeframe("hours", -2), "2 horoj") - self.assertEqual(self.locale._format_timeframe("now", 0), "nun") + assert self.locale._format_timeframe("hours", 2) == "2 horoj" + assert self.locale._format_timeframe("hour", 0) == "un horo" + assert self.locale._format_timeframe("hours", -2) == "2 horoj" + assert self.locale._format_timeframe("now", 0) == "nun" def test_ordinal_number(self): - self.assertEqual(self.locale.ordinal_number(1), "1a") + assert self.locale.ordinal_number(1) == "1a" -class ThaiLocaleTests(Chai): - def setUp(self): - super(ThaiLocaleTests, self).setUp() - - self.locale = locales.ThaiLocale() +class TestThaiLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.ThaiLocale() def test_year_full(self): - self.assertEqual(self.locale.year_full(2015), "2558") + assert self.locale.year_full(2015) == "2558" def test_year_abbreviation(self): - self.assertEqual(self.locale.year_abbreviation(2015), "58") + assert self.locale.year_abbreviation(2015) == "58" def test_format_relative_now(self): result = self.locale._format_relative("ขณะนี้", "now", 0) - self.assertEqual(result, "ขณะนี้") + assert result == "ขณะนี้" def test_format_relative_past(self): result = self.locale._format_relative("1 ชั่วโมง", "hour", 1) - self.assertEqual(result, "ในอีก 1 ชั่วโมง") + assert result == "ในอีก 1 ชั่วโมง" result = self.locale._format_relative("{0} ชั่วโมง", "hours", 2) - self.assertEqual(result, "ในอีก {0} ชั่วโมง") + assert result == "ในอีก {0} ชั่วโมง" result = self.locale._format_relative("ไม่กี่วินาที", "seconds", 42) - self.assertEqual(result, "ในอีกไม่กี่วินาที") + assert result == "ในอีกไม่กี่วินาที" def test_format_relative_future(self): result = self.locale._format_relative("1 ชั่วโมง", "hour", -1) - self.assertEqual(result, "1 ชั่วโมง ที่ผ่านมา") - + assert result == "1 ชั่วโมง ที่ผ่านมา" -class BengaliLocaleTests(Chai): - def setUp(self): - super(BengaliLocaleTests, self).setUp() - self.locale = locales.BengaliLocale() +class TestBengaliLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.BengaliLocale() def test_ordinal_number(self): result0 = self.locale._ordinal_number(0) @@ -622,333 +592,295 @@ def test_ordinal_number(self): result10 = self.locale._ordinal_number(10) result11 = self.locale._ordinal_number(11) result42 = self.locale._ordinal_number(42) - self.assertEqual(result0, "0তম") - self.assertEqual(result1, "1ম") - self.assertEqual(result3, "3য়") - self.assertEqual(result4, "4র্থ") - self.assertEqual(result5, "5ম") - self.assertEqual(result6, "6ষ্ঠ") - self.assertEqual(result10, "10ম") - self.assertEqual(result11, "11তম") - self.assertEqual(result42, "42তম") - self.assertEqual(self.locale._ordinal_number(-1), None) - - -class SwissLocaleTests(Chai): - def setUp(self): - super(SwissLocaleTests, self).setUp() - - self.locale = locales.SwissLocale() + assert result0 == "0তম" + assert result1 == "1ম" + assert result3 == "3য়" + assert result4 == "4র্থ" + assert result5 == "5ম" + assert result6 == "6ষ্ঠ" + assert result10 == "10ম" + assert result11 == "11তম" + assert result42 == "42তম" + assert self.locale._ordinal_number(-1) is None + + +class TestSwissLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.SwissLocale() def test_ordinal_number(self): dt = arrow.Arrow(2015, 4, 11, 17, 30, 00) - self.assertEqual(self.locale._format_timeframe("minute", 1), "einer Minute") - self.assertEqual(self.locale._format_timeframe("hour", 1), "einer Stunde") - self.assertEqual(self.locale.day_abbreviation(dt.isoweekday()), "Sa") - + assert self.locale._format_timeframe("minute", 1) == "einer Minute" + assert self.locale._format_timeframe("hour", 1) == "einer Stunde" + assert self.locale.day_abbreviation(dt.isoweekday()) == "Sa" -class RomanianLocaleTests(Chai): - def setUp(self): - super(RomanianLocaleTests, self).setUp() - self.locale = locales.RomanianLocale() +class TestRomanianLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.RomanianLocale() def test_timeframes(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 ore") - self.assertEqual(self.locale._format_timeframe("months", 2), "2 luni") + assert self.locale._format_timeframe("hours", 2) == "2 ore" + assert self.locale._format_timeframe("months", 2) == "2 luni" - self.assertEqual(self.locale._format_timeframe("days", 2), "2 zile") - self.assertEqual(self.locale._format_timeframe("years", 2), "2 ani") + assert self.locale._format_timeframe("days", 2) == "2 zile" + assert self.locale._format_timeframe("years", 2) == "2 ani" - self.assertEqual(self.locale._format_timeframe("hours", 3), "3 ore") - self.assertEqual(self.locale._format_timeframe("months", 4), "4 luni") - self.assertEqual(self.locale._format_timeframe("days", 3), "3 zile") - self.assertEqual(self.locale._format_timeframe("years", 5), "5 ani") + assert self.locale._format_timeframe("hours", 3) == "3 ore" + assert self.locale._format_timeframe("months", 4) == "4 luni" + assert self.locale._format_timeframe("days", 3) == "3 zile" + assert self.locale._format_timeframe("years", 5) == "5 ani" def test_relative_timeframes(self): - self.assertEqual(self.locale._format_relative("acum", "now", 0), "acum") - self.assertEqual( - self.locale._format_relative("o oră", "hour", 1), "peste o oră" - ) - self.assertEqual( - self.locale._format_relative("o oră", "hour", -1), "o oră în urmă" - ) - self.assertEqual( - self.locale._format_relative("un minut", "minute", 1), "peste un minut" - ) - self.assertEqual( - self.locale._format_relative("un minut", "minute", -1), "un minut în urmă" - ) - self.assertEqual( - self.locale._format_relative("câteva secunde", "seconds", -1), - "câteva secunde în urmă", - ) - self.assertEqual( - self.locale._format_relative("câteva secunde", "seconds", 1), - "peste câteva secunde", - ) - self.assertEqual( - self.locale._format_relative("o zi", "day", -1), "o zi în urmă" - ) - self.assertEqual(self.locale._format_relative("o zi", "day", 1), "peste o zi") - - -class ArabicLocalesTest(Chai): - def setUp(self): - super(ArabicLocalesTest, self).setUp() - - self.locale = locales.ArabicLocale() + assert self.locale._format_relative("acum", "now", 0) == "acum" + assert self.locale._format_relative("o oră", "hour", 1) == "peste o oră" + assert self.locale._format_relative("o oră", "hour", -1) == "o oră în urmă" + assert self.locale._format_relative("un minut", "minute", 1) == "peste un minut" + assert self.locale._format_relative("un minut", "minute", -1) == "un minut în urmă" + assert self.locale._format_relative("câteva secunde", "seconds", -1) == \ + "câteva secunde în urmă" + assert self.locale._format_relative("câteva secunde", "seconds", 1) == \ + "peste câteva secunde" + assert self.locale._format_relative("o zi", "day", -1) == "o zi în urmă" + assert self.locale._format_relative("o zi", "day", 1) == "peste o zi" + + +class TestArabicLocales: + @classmethod + def setup_class(cls): + cls.locale = locales.ArabicLocale() def test_timeframes(self): # single - self.assertEqual(self.locale._format_timeframe("minute", 1), "دقيقة") - self.assertEqual(self.locale._format_timeframe("hour", 1), "ساعة") - self.assertEqual(self.locale._format_timeframe("day", 1), "يوم") - self.assertEqual(self.locale._format_timeframe("month", 1), "شهر") - self.assertEqual(self.locale._format_timeframe("year", 1), "سنة") + assert self.locale._format_timeframe("minute", 1) == "دقيقة" + assert self.locale._format_timeframe("hour", 1) == "ساعة" + assert self.locale._format_timeframe("day", 1) == "يوم" + assert self.locale._format_timeframe("month", 1) == "شهر" + assert self.locale._format_timeframe("year", 1) == "سنة" # double - self.assertEqual(self.locale._format_timeframe("minutes", 2), "دقيقتين") - self.assertEqual(self.locale._format_timeframe("hours", 2), "ساعتين") - self.assertEqual(self.locale._format_timeframe("days", 2), "يومين") - self.assertEqual(self.locale._format_timeframe("months", 2), "شهرين") - self.assertEqual(self.locale._format_timeframe("years", 2), "سنتين") + assert self.locale._format_timeframe("minutes", 2) == "دقيقتين" + assert self.locale._format_timeframe("hours", 2) == "ساعتين" + assert self.locale._format_timeframe("days", 2) == "يومين" + assert self.locale._format_timeframe("months", 2) == "شهرين" + assert self.locale._format_timeframe("years", 2) == "سنتين" # up to ten - self.assertEqual(self.locale._format_timeframe("minutes", 3), "3 دقائق") - self.assertEqual(self.locale._format_timeframe("hours", 4), "4 ساعات") - self.assertEqual(self.locale._format_timeframe("days", 5), "5 أيام") - self.assertEqual(self.locale._format_timeframe("months", 6), "6 أشهر") - self.assertEqual(self.locale._format_timeframe("years", 10), "10 سنوات") + assert self.locale._format_timeframe("minutes", 3) == "3 دقائق" + assert self.locale._format_timeframe("hours", 4) == "4 ساعات" + assert self.locale._format_timeframe("days", 5) == "5 أيام" + assert self.locale._format_timeframe("months", 6) == "6 أشهر" + assert self.locale._format_timeframe("years", 10) == "10 سنوات" # more than ten - self.assertEqual(self.locale._format_timeframe("minutes", 11), "11 دقيقة") - self.assertEqual(self.locale._format_timeframe("hours", 19), "19 ساعة") - self.assertEqual(self.locale._format_timeframe("months", 24), "24 شهر") - self.assertEqual(self.locale._format_timeframe("days", 50), "50 يوم") - self.assertEqual(self.locale._format_timeframe("years", 115), "115 سنة") + assert self.locale._format_timeframe("minutes", 11) == "11 دقيقة" + assert self.locale._format_timeframe("hours", 19) == "19 ساعة" + assert self.locale._format_timeframe("months", 24) == "24 شهر" + assert self.locale._format_timeframe("days", 50) == "50 يوم" + assert self.locale._format_timeframe("years", 115) == "115 سنة" -class NepaliLocaleTests(Chai): - def setUp(self): - super(NepaliLocaleTests, self).setUp() - - self.locale = locales.NepaliLocale() +class TestNepaliLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.NepaliLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 3), "3 घण्टा") - self.assertEqual(self.locale._format_timeframe("hour", 0), "एक घण्टा") + assert self.locale._format_timeframe("hours", 3) == "3 घण्टा" + assert self.locale._format_timeframe("hour", 0) == "एक घण्टा" def test_format_relative_now(self): result = self.locale._format_relative("अहिले", "now", 0) - self.assertEqual(result, "अहिले") + assert result == "अहिले" def test_format_relative_future(self): result = self.locale._format_relative("एक घण्टा", "hour", 1) - self.assertEqual(result, "एक घण्टा पछी") + assert result == "एक घण्टा पछी" def test_format_relative_past(self): result = self.locale._format_relative("एक घण्टा", "hour", -1) - self.assertEqual(result, "एक घण्टा पहिले") - + assert result == "एक घण्टा पहिले" -class IndonesianLocaleTests(Chai): - def setUp(self): - super(IndonesianLocaleTests, self).setUp() - self.locale = locales.IndonesianLocale() +class TestIndonesianLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.IndonesianLocale() def test_timeframes(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 jam") - self.assertEqual(self.locale._format_timeframe("months", 2), "2 bulan") + assert self.locale._format_timeframe("hours", 2) == "2 jam" + assert self.locale._format_timeframe("months", 2) == "2 bulan" - self.assertEqual(self.locale._format_timeframe("days", 2), "2 hari") - self.assertEqual(self.locale._format_timeframe("years", 2), "2 tahun") + assert self.locale._format_timeframe("days", 2) == "2 hari" + assert self.locale._format_timeframe("years", 2) == "2 tahun" - self.assertEqual(self.locale._format_timeframe("hours", 3), "3 jam") - self.assertEqual(self.locale._format_timeframe("months", 4), "4 bulan") - self.assertEqual(self.locale._format_timeframe("days", 3), "3 hari") - self.assertEqual(self.locale._format_timeframe("years", 5), "5 tahun") + assert self.locale._format_timeframe("hours", 3) == "3 jam" + assert self.locale._format_timeframe("months", 4) == "4 bulan" + assert self.locale._format_timeframe("days", 3) == "3 hari" + assert self.locale._format_timeframe("years", 5) == "5 tahun" def test_format_relative_now(self): - self.assertEqual( - self.locale._format_relative("baru saja", "now", 0), "baru saja" - ) + assert self.locale._format_relative("baru saja", "now", 0) == "baru saja" def test_format_relative_past(self): - self.assertEqual( - self.locale._format_relative("1 jam", "hour", 1), "dalam 1 jam" - ) - self.assertEqual( - self.locale._format_relative("1 detik", "seconds", 1), "dalam 1 detik" - ) + assert self.locale._format_relative("1 jam", "hour", 1) == "dalam 1 jam" + assert self.locale._format_relative("1 detik", "seconds", 1) == "dalam 1 detik" def test_format_relative_future(self): - self.assertEqual( - self.locale._format_relative("1 jam", "hour", -1), "1 jam yang lalu" - ) - + assert self.locale._format_relative("1 jam", "hour", -1) == "1 jam yang lalu" -class TagalogLocaleTests(Chai): - def setUp(self): - super(TagalogLocaleTests, self).setUp() - self.locale = locales.TagalogLocale() +class TestTagalogLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.TagalogLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("minute", 1), "isang minuto") - self.assertEqual(self.locale._format_timeframe("hour", 1), "isang oras") - self.assertEqual(self.locale._format_timeframe("month", 1), "isang buwan") - self.assertEqual(self.locale._format_timeframe("year", 1), "isang taon") + assert self.locale._format_timeframe("minute", 1) == "isang minuto" + assert self.locale._format_timeframe("hour", 1) == "isang oras" + assert self.locale._format_timeframe("month", 1) == "isang buwan" + assert self.locale._format_timeframe("year", 1) == "isang taon" - self.assertEqual(self.locale._format_timeframe("seconds", 2), "2 segundo") - self.assertEqual(self.locale._format_timeframe("minutes", 3), "3 minuto") - self.assertEqual(self.locale._format_timeframe("hours", 4), "4 oras") - self.assertEqual(self.locale._format_timeframe("months", 5), "5 buwan") - self.assertEqual(self.locale._format_timeframe("years", 6), "6 taon") + assert self.locale._format_timeframe("seconds", 2) == "2 segundo" + assert self.locale._format_timeframe("minutes", 3) == "3 minuto" + assert self.locale._format_timeframe("hours", 4) == "4 oras" + assert self.locale._format_timeframe("months", 5) == "5 buwan" + assert self.locale._format_timeframe("years", 6) == "6 taon" def test_format_relative_now(self): - self.assertEqual( - self.locale._format_relative("ngayon lang", "now", 0), "ngayon lang" - ) + assert self.locale._format_relative("ngayon lang", "now", 0) == "ngayon lang" def test_format_relative_past(self): - self.assertEqual( - self.locale._format_relative("2 oras", "hour", 2), "2 oras mula ngayon" - ) + assert self.locale._format_relative("2 oras", "hour", 2) == "2 oras mula ngayon" def test_format_relative_future(self): - self.assertEqual( - self.locale._format_relative("3 oras", "hour", -3), "nakaraang 3 oras" - ) + assert self.locale._format_relative("3 oras", "hour", -3) == "nakaraang 3 oras" def test_ordinal_number(self): - self.assertEqual(self.locale.ordinal_number(0), "ika-0") - self.assertEqual(self.locale.ordinal_number(1), "ika-1") - self.assertEqual(self.locale.ordinal_number(2), "ika-2") - self.assertEqual(self.locale.ordinal_number(3), "ika-3") - self.assertEqual(self.locale.ordinal_number(10), "ika-10") - self.assertEqual(self.locale.ordinal_number(23), "ika-23") - self.assertEqual(self.locale.ordinal_number(100), "ika-100") - self.assertEqual(self.locale.ordinal_number(103), "ika-103") - self.assertEqual(self.locale.ordinal_number(114), "ika-114") - - -class EstonianLocaleTests(Chai): - def setUp(self): - super(EstonianLocaleTests, self).setUp() - - self.locale = locales.EstonianLocale() + assert self.locale.ordinal_number(0) == "ika-0" + assert self.locale.ordinal_number(1) == "ika-1" + assert self.locale.ordinal_number(2) == "ika-2" + assert self.locale.ordinal_number(3) == "ika-3" + assert self.locale.ordinal_number(10) == "ika-10" + assert self.locale.ordinal_number(23) == "ika-23" + assert self.locale.ordinal_number(100) == "ika-100" + assert self.locale.ordinal_number(103) == "ika-103" + assert self.locale.ordinal_number(114) == "ika-114" + + +class TestEstonianLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.EstonianLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("now", 0), "just nüüd") - self.assertEqual(self.locale._format_timeframe("second", 1), "ühe sekundi") - self.assertEqual(self.locale._format_timeframe("seconds", 3), "3 sekundi") - self.assertEqual(self.locale._format_timeframe("seconds", 30), "30 sekundi") - self.assertEqual(self.locale._format_timeframe("minute", 1), "ühe minuti") - self.assertEqual(self.locale._format_timeframe("minutes", 4), "4 minuti") - self.assertEqual(self.locale._format_timeframe("minutes", 40), "40 minuti") - self.assertEqual(self.locale._format_timeframe("hour", 1), "tunni aja") - self.assertEqual(self.locale._format_timeframe("hours", 5), "5 tunni") - self.assertEqual(self.locale._format_timeframe("hours", 23), "23 tunni") - self.assertEqual(self.locale._format_timeframe("day", 1), "ühe päeva") - self.assertEqual(self.locale._format_timeframe("days", 6), "6 päeva") - self.assertEqual(self.locale._format_timeframe("days", 12), "12 päeva") - self.assertEqual(self.locale._format_timeframe("month", 1), "ühe kuu") - self.assertEqual(self.locale._format_timeframe("months", 7), "7 kuu") - self.assertEqual(self.locale._format_timeframe("months", 11), "11 kuu") - self.assertEqual(self.locale._format_timeframe("year", 1), "ühe aasta") - self.assertEqual(self.locale._format_timeframe("years", 8), "8 aasta") - self.assertEqual(self.locale._format_timeframe("years", 12), "12 aasta") - - self.assertEqual(self.locale._format_timeframe("now", 0), "just nüüd") - self.assertEqual(self.locale._format_timeframe("second", -1), "üks sekund") - self.assertEqual(self.locale._format_timeframe("seconds", -9), "9 sekundit") - self.assertEqual(self.locale._format_timeframe("seconds", -12), "12 sekundit") - self.assertEqual(self.locale._format_timeframe("minute", -1), "üks minut") - self.assertEqual(self.locale._format_timeframe("minutes", -2), "2 minutit") - self.assertEqual(self.locale._format_timeframe("minutes", -10), "10 minutit") - self.assertEqual(self.locale._format_timeframe("hour", -1), "tund aega") - self.assertEqual(self.locale._format_timeframe("hours", -3), "3 tundi") - self.assertEqual(self.locale._format_timeframe("hours", -11), "11 tundi") - self.assertEqual(self.locale._format_timeframe("day", -1), "üks päev") - self.assertEqual(self.locale._format_timeframe("days", -2), "2 päeva") - self.assertEqual(self.locale._format_timeframe("days", -12), "12 päeva") - self.assertEqual(self.locale._format_timeframe("month", -1), "üks kuu") - self.assertEqual(self.locale._format_timeframe("months", -3), "3 kuud") - self.assertEqual(self.locale._format_timeframe("months", -13), "13 kuud") - self.assertEqual(self.locale._format_timeframe("year", -1), "üks aasta") - self.assertEqual(self.locale._format_timeframe("years", -4), "4 aastat") - self.assertEqual(self.locale._format_timeframe("years", -14), "14 aastat") - - -class PortugueseLocaleTests(Chai): - def setUp(self): - super(PortugueseLocaleTests, self).setUp() - - self.locale = locales.PortugueseLocale() + assert self.locale._format_timeframe("now", 0) == "just nüüd" + assert self.locale._format_timeframe("second", 1) == "ühe sekundi" + assert self.locale._format_timeframe("seconds", 3) == "3 sekundi" + assert self.locale._format_timeframe("seconds", 30) == "30 sekundi" + assert self.locale._format_timeframe("minute", 1) == "ühe minuti" + assert self.locale._format_timeframe("minutes", 4) == "4 minuti" + assert self.locale._format_timeframe("minutes", 40) == "40 minuti" + assert self.locale._format_timeframe("hour", 1) == "tunni aja" + assert self.locale._format_timeframe("hours", 5) == "5 tunni" + assert self.locale._format_timeframe("hours", 23) == "23 tunni" + assert self.locale._format_timeframe("day", 1) == "ühe päeva" + assert self.locale._format_timeframe("days", 6) == "6 päeva" + assert self.locale._format_timeframe("days", 12) == "12 päeva" + assert self.locale._format_timeframe("month", 1) == "ühe kuu" + assert self.locale._format_timeframe("months", 7) == "7 kuu" + assert self.locale._format_timeframe("months", 11) == "11 kuu" + assert self.locale._format_timeframe("year", 1) == "ühe aasta" + assert self.locale._format_timeframe("years", 8) == "8 aasta" + assert self.locale._format_timeframe("years", 12) == "12 aasta" + + assert self.locale._format_timeframe("now", 0) == "just nüüd" + assert self.locale._format_timeframe("second", -1) == "üks sekund" + assert self.locale._format_timeframe("seconds", -9) == "9 sekundit" + assert self.locale._format_timeframe("seconds", -12) == "12 sekundit" + assert self.locale._format_timeframe("minute", -1) == "üks minut" + assert self.locale._format_timeframe("minutes", -2) == "2 minutit" + assert self.locale._format_timeframe("minutes", -10) == "10 minutit" + assert self.locale._format_timeframe("hour", -1) == "tund aega" + assert self.locale._format_timeframe("hours", -3) == "3 tundi" + assert self.locale._format_timeframe("hours", -11) == "11 tundi" + assert self.locale._format_timeframe("day", -1) == "üks päev" + assert self.locale._format_timeframe("days", -2) == "2 päeva" + assert self.locale._format_timeframe("days", -12) == "12 päeva" + assert self.locale._format_timeframe("month", -1) == "üks kuu" + assert self.locale._format_timeframe("months", -3) == "3 kuud" + assert self.locale._format_timeframe("months", -13) == "13 kuud" + assert self.locale._format_timeframe("year", -1) == "üks aasta" + assert self.locale._format_timeframe("years", -4) == "4 aastat" + assert self.locale._format_timeframe("years", -14) == "14 aastat" + + +class TestPortugueseLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.PortugueseLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("now", 0), "agora") - self.assertEqual(self.locale._format_timeframe("second", 1), "um segundo") - self.assertEqual(self.locale._format_timeframe("seconds", 30), "30 segundos") - self.assertEqual(self.locale._format_timeframe("minute", 1), "um minuto") - self.assertEqual(self.locale._format_timeframe("minutes", 40), "40 minutos") - self.assertEqual(self.locale._format_timeframe("hour", 1), "uma hora") - self.assertEqual(self.locale._format_timeframe("hours", 23), "23 horas") - self.assertEqual(self.locale._format_timeframe("day", 1), "um dia") - self.assertEqual(self.locale._format_timeframe("days", 12), "12 dias") - self.assertEqual(self.locale._format_timeframe("month", 1), "um mês") - self.assertEqual(self.locale._format_timeframe("months", 11), "11 meses") - self.assertEqual(self.locale._format_timeframe("year", 1), "um ano") - self.assertEqual(self.locale._format_timeframe("years", 12), "12 anos") - - -class BrazilianLocaleTests(Chai): - def setUp(self): - super(BrazilianLocaleTests, self).setUp() - - self.locale = locales.BrazilianPortugueseLocale() + assert self.locale._format_timeframe("now", 0) == "agora" + assert self.locale._format_timeframe("second", 1) == "um segundo" + assert self.locale._format_timeframe("seconds", 30) == "30 segundos" + assert self.locale._format_timeframe("minute", 1) == "um minuto" + assert self.locale._format_timeframe("minutes", 40) == "40 minutos" + assert self.locale._format_timeframe("hour", 1) == "uma hora" + assert self.locale._format_timeframe("hours", 23) == "23 horas" + assert self.locale._format_timeframe("day", 1) == "um dia" + assert self.locale._format_timeframe("days", 12) == "12 dias" + assert self.locale._format_timeframe("month", 1) == "um mês" + assert self.locale._format_timeframe("months", 11) == "11 meses" + assert self.locale._format_timeframe("year", 1) == "um ano" + assert self.locale._format_timeframe("years", 12) == "12 anos" + + +class TestBrazilianLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.BrazilianPortugueseLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("now", 0), "agora") - self.assertEqual(self.locale._format_timeframe("second", 1), "um segundo") - self.assertEqual(self.locale._format_timeframe("seconds", 30), "30 segundos") - self.assertEqual(self.locale._format_timeframe("minute", 1), "um minuto") - self.assertEqual(self.locale._format_timeframe("minutes", 40), "40 minutos") - self.assertEqual(self.locale._format_timeframe("hour", 1), "uma hora") - self.assertEqual(self.locale._format_timeframe("hours", 23), "23 horas") - self.assertEqual(self.locale._format_timeframe("day", 1), "um dia") - self.assertEqual(self.locale._format_timeframe("days", 12), "12 dias") - self.assertEqual(self.locale._format_timeframe("month", 1), "um mês") - self.assertEqual(self.locale._format_timeframe("months", 11), "11 meses") - self.assertEqual(self.locale._format_timeframe("year", 1), "um ano") - self.assertEqual(self.locale._format_timeframe("years", 12), "12 anos") - - -class HongKongLocaleTests(Chai): - def setUp(self): - super(HongKongLocaleTests, self).setUp() - - self.locale = locales.HongKongLocale() + assert self.locale._format_timeframe("now", 0) == "agora" + assert self.locale._format_timeframe("second", 1) == "um segundo" + assert self.locale._format_timeframe("seconds", 30) == "30 segundos" + assert self.locale._format_timeframe("minute", 1) == "um minuto" + assert self.locale._format_timeframe("minutes", 40) == "40 minutos" + assert self.locale._format_timeframe("hour", 1) == "uma hora" + assert self.locale._format_timeframe("hours", 23) == "23 horas" + assert self.locale._format_timeframe("day", 1) == "um dia" + assert self.locale._format_timeframe("days", 12) == "12 dias" + assert self.locale._format_timeframe("month", 1) == "um mês" + assert self.locale._format_timeframe("months", 11) == "11 meses" + assert self.locale._format_timeframe("year", 1) == "um ano" + assert self.locale._format_timeframe("years", 12) == "12 anos" + + +class TestHongKongLocale: + @classmethod + def setup_class(cls): + cls.locale = locales.HongKongLocale() def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("now", 0), "剛才") - self.assertEqual(self.locale._format_timeframe("second", 1), "1秒") - self.assertEqual(self.locale._format_timeframe("seconds", 30), "30秒") - self.assertEqual(self.locale._format_timeframe("minute", 1), "1分鐘") - self.assertEqual(self.locale._format_timeframe("minutes", 40), "40分鐘") - self.assertEqual(self.locale._format_timeframe("hour", 1), "1小時") - self.assertEqual(self.locale._format_timeframe("hours", 23), "23小時") - self.assertEqual(self.locale._format_timeframe("day", 1), "1天") - self.assertEqual(self.locale._format_timeframe("days", 12), "12天") - self.assertEqual(self.locale._format_timeframe("week", 1), "1星期") - self.assertEqual(self.locale._format_timeframe("weeks", 38), "38星期") - self.assertEqual(self.locale._format_timeframe("month", 1), "1個月") - self.assertEqual(self.locale._format_timeframe("months", 11), "11個月") - self.assertEqual(self.locale._format_timeframe("year", 1), "1年") - self.assertEqual(self.locale._format_timeframe("years", 12), "12年") + assert self.locale._format_timeframe("now", 0) == "剛才" + assert self.locale._format_timeframe("second", 1) == "1秒" + assert self.locale._format_timeframe("seconds", 30) == "30秒" + assert self.locale._format_timeframe("minute", 1) == "1分鐘" + assert self.locale._format_timeframe("minutes", 40) == "40分鐘" + assert self.locale._format_timeframe("hour", 1) == "1小時" + assert self.locale._format_timeframe("hours", 23) == "23小時" + assert self.locale._format_timeframe("day", 1) == "1天" + assert self.locale._format_timeframe("days", 12) == "12天" + assert self.locale._format_timeframe("week", 1) == "1星期" + assert self.locale._format_timeframe("weeks", 38) == "38星期" + assert self.locale._format_timeframe("month", 1) == "1個月" + assert self.locale._format_timeframe("months", 11) == "11個月" + assert self.locale._format_timeframe("year", 1) == "1年" + assert self.locale._format_timeframe("years", 12) == "12年" diff --git a/tests/locales_tests.py.bak b/tests/locales_tests.py.bak new file mode 100644 index 000000000..af205b435 --- /dev/null +++ b/tests/locales_tests.py.bak @@ -0,0 +1,954 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from chai import Chai + +from arrow import arrow, locales + + +class LocaleValidationTests(Chai): + """Validate locales to ensure that translations are valid and complete""" + + def setUp(self): + super(LocaleValidationTests, self).setUp() + + self.locales = locales._locales + + def test_locale_validation(self): + + for _, locale_cls in self.locales.items(): + # 7 days + 1 spacer to allow for 1-indexing of months + self.assertEqual(len(locale_cls.day_names), 8) + self.assertTrue(locale_cls.day_names[0] == "") + # ensure that all string from index 1 onward are valid (not blank or None) + self.assertTrue(all(locale_cls.day_names[1:])) + + self.assertEqual(len(locale_cls.day_abbreviations), 8) + self.assertTrue(locale_cls.day_abbreviations[0] == "") + self.assertTrue(all(locale_cls.day_abbreviations[1:])) + + # 12 months + 1 spacer to allow for 1-indexing of months + self.assertEqual(len(locale_cls.month_names), 13) + self.assertTrue(locale_cls.month_names[0] == "") + self.assertTrue(all(locale_cls.month_names[1:])) + + self.assertEqual(len(locale_cls.month_abbreviations), 13) + self.assertTrue(locale_cls.month_abbreviations[0] == "") + self.assertTrue(all(locale_cls.month_abbreviations[1:])) + + self.assertTrue(len(locale_cls.names) > 0) + self.assertTrue(locale_cls.past is not None) + self.assertTrue(locale_cls.future is not None) + + +class ModuleTests(Chai): + def test_get_locale(self): + + mock_locales = self.mock(locales, "_locales") + mock_locale_cls = self.mock() + mock_locale = self.mock() + + self.expect(mock_locales.get).args("name").returns(mock_locale_cls) + self.expect(mock_locale_cls).returns(mock_locale) + + result = locales.get_locale("name") + + self.assertEqual(result, mock_locale) + + def test_locales(self): + + self.assertTrue(len(locales._locales) > 0) + + +class LocaleTests(Chai): + def setUp(self): + super(LocaleTests, self).setUp() + + self.locale = locales.EnglishLocale() + + def test_format_timeframe(self): + + self.assertEqual(self.locale._format_timeframe("hours", 2), "2 hours") + self.assertEqual(self.locale._format_timeframe("hour", 0), "an hour") + + def test_format_relative_now(self): + + result = self.locale._format_relative("just now", "now", 0) + + self.assertEqual(result, "just now") + + def test_format_relative_past(self): + + result = self.locale._format_relative("an hour", "hour", 1) + + self.assertEqual(result, "in an hour") + + def test_format_relative_future(self): + + result = self.locale._format_relative("an hour", "hour", -1) + + self.assertEqual(result, "an hour ago") + + def test_ordinal_number(self): + self.assertEqual(self.locale.ordinal_number(0), "0th") + self.assertEqual(self.locale.ordinal_number(1), "1st") + self.assertEqual(self.locale.ordinal_number(2), "2nd") + self.assertEqual(self.locale.ordinal_number(3), "3rd") + self.assertEqual(self.locale.ordinal_number(4), "4th") + self.assertEqual(self.locale.ordinal_number(10), "10th") + self.assertEqual(self.locale.ordinal_number(11), "11th") + self.assertEqual(self.locale.ordinal_number(12), "12th") + self.assertEqual(self.locale.ordinal_number(13), "13th") + self.assertEqual(self.locale.ordinal_number(14), "14th") + self.assertEqual(self.locale.ordinal_number(21), "21st") + self.assertEqual(self.locale.ordinal_number(22), "22nd") + self.assertEqual(self.locale.ordinal_number(23), "23rd") + self.assertEqual(self.locale.ordinal_number(24), "24th") + + self.assertEqual(self.locale.ordinal_number(100), "100th") + self.assertEqual(self.locale.ordinal_number(101), "101st") + self.assertEqual(self.locale.ordinal_number(102), "102nd") + self.assertEqual(self.locale.ordinal_number(103), "103rd") + self.assertEqual(self.locale.ordinal_number(104), "104th") + self.assertEqual(self.locale.ordinal_number(110), "110th") + self.assertEqual(self.locale.ordinal_number(111), "111th") + self.assertEqual(self.locale.ordinal_number(112), "112th") + self.assertEqual(self.locale.ordinal_number(113), "113th") + self.assertEqual(self.locale.ordinal_number(114), "114th") + self.assertEqual(self.locale.ordinal_number(121), "121st") + self.assertEqual(self.locale.ordinal_number(122), "122nd") + self.assertEqual(self.locale.ordinal_number(123), "123rd") + self.assertEqual(self.locale.ordinal_number(124), "124th") + + def test_meridian_invalid_token(self): + self.assertEqual(self.locale.meridian(7, None), None) + self.assertEqual(self.locale.meridian(7, "B"), None) + self.assertEqual(self.locale.meridian(7, "NONSENSE"), None) + + +class EnglishLocaleTests(Chai): + def setUp(self): + super(EnglishLocaleTests, self).setUp() + + self.locale = locales.EnglishLocale() + + def test_describe(self): + self.assertEqual(self.locale.describe("now", only_distance=True), "instantly") + self.assertEqual(self.locale.describe("now", only_distance=False), "just now") + + +class ItalianLocalesTests(Chai): + def test_ordinal_number(self): + locale = locales.ItalianLocale() + + self.assertEqual(locale.ordinal_number(1), "1º") + + +class SpanishLocalesTests(Chai): + def test_ordinal_number(self): + locale = locales.SpanishLocale() + + self.assertEqual(locale.ordinal_number(1), "1º") + + def test_format_timeframe(self): + locale = locales.SpanishLocale() + self.assertEqual(locale._format_timeframe("now", 0), "ahora") + self.assertEqual(locale._format_timeframe("seconds", 1), "1 segundos") + self.assertEqual(locale._format_timeframe("seconds", 3), "3 segundos") + self.assertEqual(locale._format_timeframe("seconds", 30), "30 segundos") + self.assertEqual(locale._format_timeframe("minute", 1), "un minuto") + self.assertEqual(locale._format_timeframe("minutes", 4), "4 minutos") + self.assertEqual(locale._format_timeframe("minutes", 40), "40 minutos") + self.assertEqual(locale._format_timeframe("hour", 1), "una hora") + self.assertEqual(locale._format_timeframe("hours", 5), "5 horas") + self.assertEqual(locale._format_timeframe("hours", 23), "23 horas") + self.assertEqual(locale._format_timeframe("day", 1), "un día") + self.assertEqual(locale._format_timeframe("days", 6), "6 días") + self.assertEqual(locale._format_timeframe("days", 12), "12 días") + self.assertEqual(locale._format_timeframe("week", 1), "una semana") + self.assertEqual(locale._format_timeframe("weeks", 2), "2 semanas") + self.assertEqual(locale._format_timeframe("weeks", 3), "3 semanas") + self.assertEqual(locale._format_timeframe("month", 1), "un mes") + self.assertEqual(locale._format_timeframe("months", 7), "7 meses") + self.assertEqual(locale._format_timeframe("months", 11), "11 meses") + self.assertEqual(locale._format_timeframe("year", 1), "un año") + self.assertEqual(locale._format_timeframe("years", 8), "8 años") + self.assertEqual(locale._format_timeframe("years", 12), "12 años") + + self.assertEqual(locale._format_timeframe("now", 0), "ahora") + self.assertEqual(locale._format_timeframe("seconds", -1), "1 segundos") + self.assertEqual(locale._format_timeframe("seconds", -9), "9 segundos") + self.assertEqual(locale._format_timeframe("seconds", -12), "12 segundos") + self.assertEqual(locale._format_timeframe("minute", -1), "un minuto") + self.assertEqual(locale._format_timeframe("minutes", -2), "2 minutos") + self.assertEqual(locale._format_timeframe("minutes", -10), "10 minutos") + self.assertEqual(locale._format_timeframe("hour", -1), "una hora") + self.assertEqual(locale._format_timeframe("hours", -3), "3 horas") + self.assertEqual(locale._format_timeframe("hours", -11), "11 horas") + self.assertEqual(locale._format_timeframe("day", -1), "un día") + self.assertEqual(locale._format_timeframe("days", -2), "2 días") + self.assertEqual(locale._format_timeframe("days", -12), "12 días") + self.assertEqual(locale._format_timeframe("week", -1), "una semana") + self.assertEqual(locale._format_timeframe("weeks", -2), "2 semanas") + self.assertEqual(locale._format_timeframe("weeks", -3), "3 semanas") + self.assertEqual(locale._format_timeframe("month", -1), "un mes") + self.assertEqual(locale._format_timeframe("months", -3), "3 meses") + self.assertEqual(locale._format_timeframe("months", -13), "13 meses") + self.assertEqual(locale._format_timeframe("year", -1), "un año") + self.assertEqual(locale._format_timeframe("years", -4), "4 años") + self.assertEqual(locale._format_timeframe("years", -14), "14 años") + + +class FrenchLocalesTests(Chai): + def test_ordinal_number(self): + locale = locales.FrenchLocale() + + self.assertEqual(locale.ordinal_number(1), "1er") + self.assertEqual(locale.ordinal_number(2), "2e") + + +class RussianLocalesTests(Chai): + def test_plurals2(self): + + locale = locales.RussianLocale() + + self.assertEqual(locale._format_timeframe("hours", 0), "0 часов") + self.assertEqual(locale._format_timeframe("hours", 1), "1 час") + self.assertEqual(locale._format_timeframe("hours", 2), "2 часа") + self.assertEqual(locale._format_timeframe("hours", 4), "4 часа") + self.assertEqual(locale._format_timeframe("hours", 5), "5 часов") + self.assertEqual(locale._format_timeframe("hours", 21), "21 час") + self.assertEqual(locale._format_timeframe("hours", 22), "22 часа") + self.assertEqual(locale._format_timeframe("hours", 25), "25 часов") + + # feminine grammatical gender should be tested separately + self.assertEqual(locale._format_timeframe("minutes", 0), "0 минут") + self.assertEqual(locale._format_timeframe("minutes", 1), "1 минуту") + self.assertEqual(locale._format_timeframe("minutes", 2), "2 минуты") + self.assertEqual(locale._format_timeframe("minutes", 4), "4 минуты") + self.assertEqual(locale._format_timeframe("minutes", 5), "5 минут") + self.assertEqual(locale._format_timeframe("minutes", 21), "21 минуту") + self.assertEqual(locale._format_timeframe("minutes", 22), "22 минуты") + self.assertEqual(locale._format_timeframe("minutes", 25), "25 минут") + + +class PolishLocalesTests(Chai): + def test_plurals(self): + + locale = locales.PolishLocale() + + self.assertEqual(locale._format_timeframe("hours", 0), "0 godzin") + self.assertEqual(locale._format_timeframe("hours", 1), "1 godzin") + self.assertEqual(locale._format_timeframe("hours", 2), "2 godziny") + self.assertEqual(locale._format_timeframe("hours", 4), "4 godziny") + self.assertEqual(locale._format_timeframe("hours", 5), "5 godzin") + self.assertEqual(locale._format_timeframe("hours", 21), "21 godzin") + self.assertEqual(locale._format_timeframe("hours", 22), "22 godziny") + self.assertEqual(locale._format_timeframe("hours", 25), "25 godzin") + + +class IcelandicLocalesTests(Chai): + def setUp(self): + super(IcelandicLocalesTests, self).setUp() + + self.locale = locales.IcelandicLocale() + + def test_format_timeframe(self): + + self.assertEqual(self.locale._format_timeframe("minute", -1), "einni mínútu") + self.assertEqual(self.locale._format_timeframe("minute", 1), "eina mínútu") + + self.assertEqual(self.locale._format_timeframe("hours", -2), "2 tímum") + self.assertEqual(self.locale._format_timeframe("hours", 2), "2 tíma") + self.assertEqual(self.locale._format_timeframe("now", 0), "rétt í þessu") + + +class MalayalamLocaleTests(Chai): + def setUp(self): + super(MalayalamLocaleTests, self).setUp() + + self.locale = locales.MalayalamLocale() + + def test_format_timeframe(self): + + self.assertEqual(self.locale._format_timeframe("hours", 2), "2 മണിക്കൂർ") + self.assertEqual(self.locale._format_timeframe("hour", 0), "ഒരു മണിക്കൂർ") + + def test_format_relative_now(self): + + result = self.locale._format_relative("ഇപ്പോൾ", "now", 0) + + self.assertEqual(result, "ഇപ്പോൾ") + + def test_format_relative_past(self): + + result = self.locale._format_relative("ഒരു മണിക്കൂർ", "hour", 1) + self.assertEqual(result, "ഒരു മണിക്കൂർ ശേഷം") + + def test_format_relative_future(self): + + result = self.locale._format_relative("ഒരു മണിക്കൂർ", "hour", -1) + self.assertEqual(result, "ഒരു മണിക്കൂർ മുമ്പ്") + + +class HindiLocaleTests(Chai): + def setUp(self): + super(HindiLocaleTests, self).setUp() + + self.locale = locales.HindiLocale() + + def test_format_timeframe(self): + + self.assertEqual(self.locale._format_timeframe("hours", 2), "2 घंटे") + self.assertEqual(self.locale._format_timeframe("hour", 0), "एक घंटा") + + def test_format_relative_now(self): + + result = self.locale._format_relative("अभी", "now", 0) + + self.assertEqual(result, "अभी") + + def test_format_relative_past(self): + + result = self.locale._format_relative("एक घंटा", "hour", 1) + self.assertEqual(result, "एक घंटा बाद") + + def test_format_relative_future(self): + + result = self.locale._format_relative("एक घंटा", "hour", -1) + self.assertEqual(result, "एक घंटा पहले") + + +class CzechLocaleTests(Chai): + def setUp(self): + super(CzechLocaleTests, self).setUp() + + self.locale = locales.CzechLocale() + + def test_format_timeframe(self): + + self.assertEqual(self.locale._format_timeframe("hours", 2), "2 hodiny") + self.assertEqual(self.locale._format_timeframe("hours", 5), "5 hodin") + self.assertEqual(self.locale._format_timeframe("hour", 0), "0 hodin") + self.assertEqual(self.locale._format_timeframe("hours", -2), "2 hodinami") + self.assertEqual(self.locale._format_timeframe("hours", -5), "5 hodinami") + self.assertEqual(self.locale._format_timeframe("now", 0), "Teď") + + def test_format_relative_now(self): + + result = self.locale._format_relative("Teď", "now", 0) + self.assertEqual(result, "Teď") + + def test_format_relative_future(self): + + result = self.locale._format_relative("hodinu", "hour", 1) + self.assertEqual(result, "Za hodinu") + + def test_format_relative_past(self): + + result = self.locale._format_relative("hodinou", "hour", -1) + self.assertEqual(result, "Před hodinou") + + +class SlovakLocaleTests(Chai): + def setUp(self): + super(SlovakLocaleTests, self).setUp() + + self.locale = locales.SlovakLocale() + + def test_format_timeframe(self): + + self.assertEqual(self.locale._format_timeframe("hours", 2), "2 hodiny") + self.assertEqual(self.locale._format_timeframe("hours", 5), "5 hodín") + self.assertEqual(self.locale._format_timeframe("hour", 0), "0 hodín") + self.assertEqual(self.locale._format_timeframe("hours", -2), "2 hodinami") + self.assertEqual(self.locale._format_timeframe("hours", -5), "5 hodinami") + self.assertEqual(self.locale._format_timeframe("now", 0), "Teraz") + + def test_format_relative_now(self): + + result = self.locale._format_relative("Teraz", "now", 0) + self.assertEqual(result, "Teraz") + + def test_format_relative_future(self): + + result = self.locale._format_relative("hodinu", "hour", 1) + self.assertEqual(result, "O hodinu") + + def test_format_relative_past(self): + + result = self.locale._format_relative("hodinou", "hour", -1) + self.assertEqual(result, "Pred hodinou") + + +class BulgarianLocaleTests(Chai): + def test_plurals2(self): + + locale = locales.BulgarianLocale() + + self.assertEqual(locale._format_timeframe("hours", 0), "0 часа") + self.assertEqual(locale._format_timeframe("hours", 1), "1 час") + self.assertEqual(locale._format_timeframe("hours", 2), "2 часа") + self.assertEqual(locale._format_timeframe("hours", 4), "4 часа") + self.assertEqual(locale._format_timeframe("hours", 5), "5 часа") + self.assertEqual(locale._format_timeframe("hours", 21), "21 час") + self.assertEqual(locale._format_timeframe("hours", 22), "22 часа") + self.assertEqual(locale._format_timeframe("hours", 25), "25 часа") + + # feminine grammatical gender should be tested separately + self.assertEqual(locale._format_timeframe("minutes", 0), "0 минути") + self.assertEqual(locale._format_timeframe("minutes", 1), "1 минута") + self.assertEqual(locale._format_timeframe("minutes", 2), "2 минути") + self.assertEqual(locale._format_timeframe("minutes", 4), "4 минути") + self.assertEqual(locale._format_timeframe("minutes", 5), "5 минути") + self.assertEqual(locale._format_timeframe("minutes", 21), "21 минута") + self.assertEqual(locale._format_timeframe("minutes", 22), "22 минути") + self.assertEqual(locale._format_timeframe("minutes", 25), "25 минути") + + +class MacedonianLocaleTests(Chai): + def test_plurals_mk(self): + + locale = locales.MacedonianLocale() + + # time + self.assertEqual(locale._format_relative("сега", "now", 0), "сега") + + # Hours + self.assertEqual(locale._format_timeframe("hours", 0), "0 саати") + self.assertEqual(locale._format_timeframe("hours", 1), "1 саат") + self.assertEqual(locale._format_timeframe("hours", 2), "2 саати") + self.assertEqual(locale._format_timeframe("hours", 4), "4 саати") + self.assertEqual(locale._format_timeframe("hours", 5), "5 саати") + self.assertEqual(locale._format_timeframe("hours", 21), "21 саат") + self.assertEqual(locale._format_timeframe("hours", 22), "22 саати") + self.assertEqual(locale._format_timeframe("hours", 25), "25 саати") + + # Minutes + self.assertEqual(locale._format_timeframe("minutes", 0), "0 минути") + self.assertEqual(locale._format_timeframe("minutes", 1), "1 минута") + self.assertEqual(locale._format_timeframe("minutes", 2), "2 минути") + self.assertEqual(locale._format_timeframe("minutes", 4), "4 минути") + self.assertEqual(locale._format_timeframe("minutes", 5), "5 минути") + self.assertEqual(locale._format_timeframe("minutes", 21), "21 минута") + self.assertEqual(locale._format_timeframe("minutes", 22), "22 минути") + self.assertEqual(locale._format_timeframe("minutes", 25), "25 минути") + + +class HebrewLocaleTests(Chai): + def test_couple_of_timeframe(self): + locale = locales.HebrewLocale() + + self.assertEqual(locale._format_timeframe("hours", 2), "שעתיים") + self.assertEqual(locale._format_timeframe("months", 2), "חודשיים") + self.assertEqual(locale._format_timeframe("days", 2), "יומיים") + self.assertEqual(locale._format_timeframe("years", 2), "שנתיים") + + self.assertEqual(locale._format_timeframe("hours", 3), "3 שעות") + self.assertEqual(locale._format_timeframe("months", 4), "4 חודשים") + self.assertEqual(locale._format_timeframe("days", 3), "3 ימים") + self.assertEqual(locale._format_timeframe("years", 5), "5 שנים") + + +class MarathiLocaleTests(Chai): + def setUp(self): + super(MarathiLocaleTests, self).setUp() + + self.locale = locales.MarathiLocale() + + def test_dateCoreFunctionality(self): + dt = arrow.Arrow(2015, 4, 11, 17, 30, 00) + self.assertEqual(self.locale.month_name(dt.month), "एप्रिल") + self.assertEqual(self.locale.month_abbreviation(dt.month), "एप्रि") + self.assertEqual(self.locale.day_name(dt.isoweekday()), "शनिवार") + self.assertEqual(self.locale.day_abbreviation(dt.isoweekday()), "शनि") + + def test_format_timeframe(self): + self.assertEqual(self.locale._format_timeframe("hours", 2), "2 तास") + self.assertEqual(self.locale._format_timeframe("hour", 0), "एक तास") + + def test_format_relative_now(self): + result = self.locale._format_relative("सद्य", "now", 0) + self.assertEqual(result, "सद्य") + + def test_format_relative_past(self): + result = self.locale._format_relative("एक तास", "hour", 1) + self.assertEqual(result, "एक तास नंतर") + + def test_format_relative_future(self): + result = self.locale._format_relative("एक तास", "hour", -1) + self.assertEqual(result, "एक तास आधी") + + # Not currently implemented + def test_ordinal_number(self): + self.assertEqual(self.locale.ordinal_number(1), "1") + + +class FinnishLocaleTests(Chai): + def setUp(self): + super(FinnishLocaleTests, self).setUp() + + self.locale = locales.FinnishLocale() + + def test_format_timeframe(self): + self.assertEqual( + self.locale._format_timeframe("hours", 2), ("2 tuntia", "2 tunnin") + ) + self.assertEqual(self.locale._format_timeframe("hour", 0), ("tunti", "tunnin")) + + def test_format_relative_now(self): + result = self.locale._format_relative(["juuri nyt", "juuri nyt"], "now", 0) + self.assertEqual(result, "juuri nyt") + + def test_format_relative_past(self): + result = self.locale._format_relative(["tunti", "tunnin"], "hour", 1) + self.assertEqual(result, "tunnin kuluttua") + + def test_format_relative_future(self): + result = self.locale._format_relative(["tunti", "tunnin"], "hour", -1) + self.assertEqual(result, "tunti sitten") + + def test_ordinal_number(self): + self.assertEqual(self.locale.ordinal_number(1), "1.") + + +class GermanLocaleTests(Chai): + def setUp(self): + super(GermanLocaleTests, self).setUp() + + self.locale = locales.GermanLocale() + + def test_ordinal_number(self): + self.assertEqual(self.locale.ordinal_number(1), "1.") + + def test_define(self): + self.assertEqual( + self.locale.describe("minute", only_distance=True), "eine Minute" + ) + self.assertEqual( + self.locale.describe("minute", only_distance=False), "in einer Minute" + ) + self.assertEqual( + self.locale.describe("hour", only_distance=True), "eine Stunde" + ) + self.assertEqual( + self.locale.describe("hour", only_distance=False), "in einer Stunde" + ) + self.assertEqual(self.locale.describe("day", only_distance=True), "ein Tag") + self.assertEqual( + self.locale.describe("day", only_distance=False), "in einem Tag" + ) + self.assertEqual(self.locale.describe("month", only_distance=True), "ein Monat") + self.assertEqual( + self.locale.describe("month", only_distance=False), "in einem Monat" + ) + self.assertEqual(self.locale.describe("year", only_distance=True), "ein Jahr") + self.assertEqual( + self.locale.describe("year", only_distance=False), "in einem Jahr" + ) + + +class HungarianLocaleTests(Chai): + def setUp(self): + super(HungarianLocaleTests, self).setUp() + + self.locale = locales.HungarianLocale() + + def test_format_timeframe(self): + self.assertEqual(self.locale._format_timeframe("hours", 2), "2 óra") + self.assertEqual(self.locale._format_timeframe("hour", 0), "egy órával") + self.assertEqual(self.locale._format_timeframe("hours", -2), "2 órával") + self.assertEqual(self.locale._format_timeframe("now", 0), "éppen most") + + +class EsperantoLocaleTests(Chai): + def setUp(self): + super(EsperantoLocaleTests, self).setUp() + + self.locale = locales.EsperantoLocale() + + def test_format_timeframe(self): + self.assertEqual(self.locale._format_timeframe("hours", 2), "2 horoj") + self.assertEqual(self.locale._format_timeframe("hour", 0), "un horo") + self.assertEqual(self.locale._format_timeframe("hours", -2), "2 horoj") + self.assertEqual(self.locale._format_timeframe("now", 0), "nun") + + def test_ordinal_number(self): + self.assertEqual(self.locale.ordinal_number(1), "1a") + + +class ThaiLocaleTests(Chai): + def setUp(self): + super(ThaiLocaleTests, self).setUp() + + self.locale = locales.ThaiLocale() + + def test_year_full(self): + self.assertEqual(self.locale.year_full(2015), "2558") + + def test_year_abbreviation(self): + self.assertEqual(self.locale.year_abbreviation(2015), "58") + + def test_format_relative_now(self): + result = self.locale._format_relative("ขณะนี้", "now", 0) + self.assertEqual(result, "ขณะนี้") + + def test_format_relative_past(self): + result = self.locale._format_relative("1 ชั่วโมง", "hour", 1) + self.assertEqual(result, "ในอีก 1 ชั่วโมง") + result = self.locale._format_relative("{0} ชั่วโมง", "hours", 2) + self.assertEqual(result, "ในอีก {0} ชั่วโมง") + result = self.locale._format_relative("ไม่กี่วินาที", "seconds", 42) + self.assertEqual(result, "ในอีกไม่กี่วินาที") + + def test_format_relative_future(self): + result = self.locale._format_relative("1 ชั่วโมง", "hour", -1) + self.assertEqual(result, "1 ชั่วโมง ที่ผ่านมา") + + +class BengaliLocaleTests(Chai): + def setUp(self): + super(BengaliLocaleTests, self).setUp() + + self.locale = locales.BengaliLocale() + + def test_ordinal_number(self): + result0 = self.locale._ordinal_number(0) + result1 = self.locale._ordinal_number(1) + result3 = self.locale._ordinal_number(3) + result4 = self.locale._ordinal_number(4) + result5 = self.locale._ordinal_number(5) + result6 = self.locale._ordinal_number(6) + result10 = self.locale._ordinal_number(10) + result11 = self.locale._ordinal_number(11) + result42 = self.locale._ordinal_number(42) + self.assertEqual(result0, "0তম") + self.assertEqual(result1, "1ম") + self.assertEqual(result3, "3য়") + self.assertEqual(result4, "4র্থ") + self.assertEqual(result5, "5ম") + self.assertEqual(result6, "6ষ্ঠ") + self.assertEqual(result10, "10ম") + self.assertEqual(result11, "11তম") + self.assertEqual(result42, "42তম") + self.assertEqual(self.locale._ordinal_number(-1), None) + + +class SwissLocaleTests(Chai): + def setUp(self): + super(SwissLocaleTests, self).setUp() + + self.locale = locales.SwissLocale() + + def test_ordinal_number(self): + dt = arrow.Arrow(2015, 4, 11, 17, 30, 00) + + self.assertEqual(self.locale._format_timeframe("minute", 1), "einer Minute") + self.assertEqual(self.locale._format_timeframe("hour", 1), "einer Stunde") + self.assertEqual(self.locale.day_abbreviation(dt.isoweekday()), "Sa") + + +class RomanianLocaleTests(Chai): + def setUp(self): + super(RomanianLocaleTests, self).setUp() + + self.locale = locales.RomanianLocale() + + def test_timeframes(self): + + self.assertEqual(self.locale._format_timeframe("hours", 2), "2 ore") + self.assertEqual(self.locale._format_timeframe("months", 2), "2 luni") + + self.assertEqual(self.locale._format_timeframe("days", 2), "2 zile") + self.assertEqual(self.locale._format_timeframe("years", 2), "2 ani") + + self.assertEqual(self.locale._format_timeframe("hours", 3), "3 ore") + self.assertEqual(self.locale._format_timeframe("months", 4), "4 luni") + self.assertEqual(self.locale._format_timeframe("days", 3), "3 zile") + self.assertEqual(self.locale._format_timeframe("years", 5), "5 ani") + + def test_relative_timeframes(self): + self.assertEqual(self.locale._format_relative("acum", "now", 0), "acum") + self.assertEqual( + self.locale._format_relative("o oră", "hour", 1), "peste o oră" + ) + self.assertEqual( + self.locale._format_relative("o oră", "hour", -1), "o oră în urmă" + ) + self.assertEqual( + self.locale._format_relative("un minut", "minute", 1), "peste un minut" + ) + self.assertEqual( + self.locale._format_relative("un minut", "minute", -1), "un minut în urmă" + ) + self.assertEqual( + self.locale._format_relative("câteva secunde", "seconds", -1), + "câteva secunde în urmă", + ) + self.assertEqual( + self.locale._format_relative("câteva secunde", "seconds", 1), + "peste câteva secunde", + ) + self.assertEqual( + self.locale._format_relative("o zi", "day", -1), "o zi în urmă" + ) + self.assertEqual(self.locale._format_relative("o zi", "day", 1), "peste o zi") + + +class ArabicLocalesTest(Chai): + def setUp(self): + super(ArabicLocalesTest, self).setUp() + + self.locale = locales.ArabicLocale() + + def test_timeframes(self): + + # single + self.assertEqual(self.locale._format_timeframe("minute", 1), "دقيقة") + self.assertEqual(self.locale._format_timeframe("hour", 1), "ساعة") + self.assertEqual(self.locale._format_timeframe("day", 1), "يوم") + self.assertEqual(self.locale._format_timeframe("month", 1), "شهر") + self.assertEqual(self.locale._format_timeframe("year", 1), "سنة") + + # double + self.assertEqual(self.locale._format_timeframe("minutes", 2), "دقيقتين") + self.assertEqual(self.locale._format_timeframe("hours", 2), "ساعتين") + self.assertEqual(self.locale._format_timeframe("days", 2), "يومين") + self.assertEqual(self.locale._format_timeframe("months", 2), "شهرين") + self.assertEqual(self.locale._format_timeframe("years", 2), "سنتين") + + # up to ten + self.assertEqual(self.locale._format_timeframe("minutes", 3), "3 دقائق") + self.assertEqual(self.locale._format_timeframe("hours", 4), "4 ساعات") + self.assertEqual(self.locale._format_timeframe("days", 5), "5 أيام") + self.assertEqual(self.locale._format_timeframe("months", 6), "6 أشهر") + self.assertEqual(self.locale._format_timeframe("years", 10), "10 سنوات") + + # more than ten + self.assertEqual(self.locale._format_timeframe("minutes", 11), "11 دقيقة") + self.assertEqual(self.locale._format_timeframe("hours", 19), "19 ساعة") + self.assertEqual(self.locale._format_timeframe("months", 24), "24 شهر") + self.assertEqual(self.locale._format_timeframe("days", 50), "50 يوم") + self.assertEqual(self.locale._format_timeframe("years", 115), "115 سنة") + + +class NepaliLocaleTests(Chai): + def setUp(self): + super(NepaliLocaleTests, self).setUp() + + self.locale = locales.NepaliLocale() + + def test_format_timeframe(self): + self.assertEqual(self.locale._format_timeframe("hours", 3), "3 घण्टा") + self.assertEqual(self.locale._format_timeframe("hour", 0), "एक घण्टा") + + def test_format_relative_now(self): + result = self.locale._format_relative("अहिले", "now", 0) + self.assertEqual(result, "अहिले") + + def test_format_relative_future(self): + result = self.locale._format_relative("एक घण्टा", "hour", 1) + self.assertEqual(result, "एक घण्टा पछी") + + def test_format_relative_past(self): + result = self.locale._format_relative("एक घण्टा", "hour", -1) + self.assertEqual(result, "एक घण्टा पहिले") + + +class IndonesianLocaleTests(Chai): + def setUp(self): + super(IndonesianLocaleTests, self).setUp() + + self.locale = locales.IndonesianLocale() + + def test_timeframes(self): + self.assertEqual(self.locale._format_timeframe("hours", 2), "2 jam") + self.assertEqual(self.locale._format_timeframe("months", 2), "2 bulan") + + self.assertEqual(self.locale._format_timeframe("days", 2), "2 hari") + self.assertEqual(self.locale._format_timeframe("years", 2), "2 tahun") + + self.assertEqual(self.locale._format_timeframe("hours", 3), "3 jam") + self.assertEqual(self.locale._format_timeframe("months", 4), "4 bulan") + self.assertEqual(self.locale._format_timeframe("days", 3), "3 hari") + self.assertEqual(self.locale._format_timeframe("years", 5), "5 tahun") + + def test_format_relative_now(self): + self.assertEqual( + self.locale._format_relative("baru saja", "now", 0), "baru saja" + ) + + def test_format_relative_past(self): + self.assertEqual( + self.locale._format_relative("1 jam", "hour", 1), "dalam 1 jam" + ) + self.assertEqual( + self.locale._format_relative("1 detik", "seconds", 1), "dalam 1 detik" + ) + + def test_format_relative_future(self): + self.assertEqual( + self.locale._format_relative("1 jam", "hour", -1), "1 jam yang lalu" + ) + + +class TagalogLocaleTests(Chai): + def setUp(self): + super(TagalogLocaleTests, self).setUp() + + self.locale = locales.TagalogLocale() + + def test_format_timeframe(self): + + self.assertEqual(self.locale._format_timeframe("minute", 1), "isang minuto") + self.assertEqual(self.locale._format_timeframe("hour", 1), "isang oras") + self.assertEqual(self.locale._format_timeframe("month", 1), "isang buwan") + self.assertEqual(self.locale._format_timeframe("year", 1), "isang taon") + + self.assertEqual(self.locale._format_timeframe("seconds", 2), "2 segundo") + self.assertEqual(self.locale._format_timeframe("minutes", 3), "3 minuto") + self.assertEqual(self.locale._format_timeframe("hours", 4), "4 oras") + self.assertEqual(self.locale._format_timeframe("months", 5), "5 buwan") + self.assertEqual(self.locale._format_timeframe("years", 6), "6 taon") + + def test_format_relative_now(self): + self.assertEqual( + self.locale._format_relative("ngayon lang", "now", 0), "ngayon lang" + ) + + def test_format_relative_past(self): + self.assertEqual( + self.locale._format_relative("2 oras", "hour", 2), "2 oras mula ngayon" + ) + + def test_format_relative_future(self): + self.assertEqual( + self.locale._format_relative("3 oras", "hour", -3), "nakaraang 3 oras" + ) + + def test_ordinal_number(self): + self.assertEqual(self.locale.ordinal_number(0), "ika-0") + self.assertEqual(self.locale.ordinal_number(1), "ika-1") + self.assertEqual(self.locale.ordinal_number(2), "ika-2") + self.assertEqual(self.locale.ordinal_number(3), "ika-3") + self.assertEqual(self.locale.ordinal_number(10), "ika-10") + self.assertEqual(self.locale.ordinal_number(23), "ika-23") + self.assertEqual(self.locale.ordinal_number(100), "ika-100") + self.assertEqual(self.locale.ordinal_number(103), "ika-103") + self.assertEqual(self.locale.ordinal_number(114), "ika-114") + + +class EstonianLocaleTests(Chai): + def setUp(self): + super(EstonianLocaleTests, self).setUp() + + self.locale = locales.EstonianLocale() + + def test_format_timeframe(self): + self.assertEqual(self.locale._format_timeframe("now", 0), "just nüüd") + self.assertEqual(self.locale._format_timeframe("second", 1), "ühe sekundi") + self.assertEqual(self.locale._format_timeframe("seconds", 3), "3 sekundi") + self.assertEqual(self.locale._format_timeframe("seconds", 30), "30 sekundi") + self.assertEqual(self.locale._format_timeframe("minute", 1), "ühe minuti") + self.assertEqual(self.locale._format_timeframe("minutes", 4), "4 minuti") + self.assertEqual(self.locale._format_timeframe("minutes", 40), "40 minuti") + self.assertEqual(self.locale._format_timeframe("hour", 1), "tunni aja") + self.assertEqual(self.locale._format_timeframe("hours", 5), "5 tunni") + self.assertEqual(self.locale._format_timeframe("hours", 23), "23 tunni") + self.assertEqual(self.locale._format_timeframe("day", 1), "ühe päeva") + self.assertEqual(self.locale._format_timeframe("days", 6), "6 päeva") + self.assertEqual(self.locale._format_timeframe("days", 12), "12 päeva") + self.assertEqual(self.locale._format_timeframe("month", 1), "ühe kuu") + self.assertEqual(self.locale._format_timeframe("months", 7), "7 kuu") + self.assertEqual(self.locale._format_timeframe("months", 11), "11 kuu") + self.assertEqual(self.locale._format_timeframe("year", 1), "ühe aasta") + self.assertEqual(self.locale._format_timeframe("years", 8), "8 aasta") + self.assertEqual(self.locale._format_timeframe("years", 12), "12 aasta") + + self.assertEqual(self.locale._format_timeframe("now", 0), "just nüüd") + self.assertEqual(self.locale._format_timeframe("second", -1), "üks sekund") + self.assertEqual(self.locale._format_timeframe("seconds", -9), "9 sekundit") + self.assertEqual(self.locale._format_timeframe("seconds", -12), "12 sekundit") + self.assertEqual(self.locale._format_timeframe("minute", -1), "üks minut") + self.assertEqual(self.locale._format_timeframe("minutes", -2), "2 minutit") + self.assertEqual(self.locale._format_timeframe("minutes", -10), "10 minutit") + self.assertEqual(self.locale._format_timeframe("hour", -1), "tund aega") + self.assertEqual(self.locale._format_timeframe("hours", -3), "3 tundi") + self.assertEqual(self.locale._format_timeframe("hours", -11), "11 tundi") + self.assertEqual(self.locale._format_timeframe("day", -1), "üks päev") + self.assertEqual(self.locale._format_timeframe("days", -2), "2 päeva") + self.assertEqual(self.locale._format_timeframe("days", -12), "12 päeva") + self.assertEqual(self.locale._format_timeframe("month", -1), "üks kuu") + self.assertEqual(self.locale._format_timeframe("months", -3), "3 kuud") + self.assertEqual(self.locale._format_timeframe("months", -13), "13 kuud") + self.assertEqual(self.locale._format_timeframe("year", -1), "üks aasta") + self.assertEqual(self.locale._format_timeframe("years", -4), "4 aastat") + self.assertEqual(self.locale._format_timeframe("years", -14), "14 aastat") + + +class PortugueseLocaleTests(Chai): + def setUp(self): + super(PortugueseLocaleTests, self).setUp() + + self.locale = locales.PortugueseLocale() + + def test_format_timeframe(self): + self.assertEqual(self.locale._format_timeframe("now", 0), "agora") + self.assertEqual(self.locale._format_timeframe("second", 1), "um segundo") + self.assertEqual(self.locale._format_timeframe("seconds", 30), "30 segundos") + self.assertEqual(self.locale._format_timeframe("minute", 1), "um minuto") + self.assertEqual(self.locale._format_timeframe("minutes", 40), "40 minutos") + self.assertEqual(self.locale._format_timeframe("hour", 1), "uma hora") + self.assertEqual(self.locale._format_timeframe("hours", 23), "23 horas") + self.assertEqual(self.locale._format_timeframe("day", 1), "um dia") + self.assertEqual(self.locale._format_timeframe("days", 12), "12 dias") + self.assertEqual(self.locale._format_timeframe("month", 1), "um mês") + self.assertEqual(self.locale._format_timeframe("months", 11), "11 meses") + self.assertEqual(self.locale._format_timeframe("year", 1), "um ano") + self.assertEqual(self.locale._format_timeframe("years", 12), "12 anos") + + +class BrazilianLocaleTests(Chai): + def setUp(self): + super(BrazilianLocaleTests, self).setUp() + + self.locale = locales.BrazilianPortugueseLocale() + + def test_format_timeframe(self): + self.assertEqual(self.locale._format_timeframe("now", 0), "agora") + self.assertEqual(self.locale._format_timeframe("second", 1), "um segundo") + self.assertEqual(self.locale._format_timeframe("seconds", 30), "30 segundos") + self.assertEqual(self.locale._format_timeframe("minute", 1), "um minuto") + self.assertEqual(self.locale._format_timeframe("minutes", 40), "40 minutos") + self.assertEqual(self.locale._format_timeframe("hour", 1), "uma hora") + self.assertEqual(self.locale._format_timeframe("hours", 23), "23 horas") + self.assertEqual(self.locale._format_timeframe("day", 1), "um dia") + self.assertEqual(self.locale._format_timeframe("days", 12), "12 dias") + self.assertEqual(self.locale._format_timeframe("month", 1), "um mês") + self.assertEqual(self.locale._format_timeframe("months", 11), "11 meses") + self.assertEqual(self.locale._format_timeframe("year", 1), "um ano") + self.assertEqual(self.locale._format_timeframe("years", 12), "12 anos") + + +class HongKongLocaleTests(Chai): + def setUp(self): + super(HongKongLocaleTests, self).setUp() + + self.locale = locales.HongKongLocale() + + def test_format_timeframe(self): + self.assertEqual(self.locale._format_timeframe("now", 0), "剛才") + self.assertEqual(self.locale._format_timeframe("second", 1), "1秒") + self.assertEqual(self.locale._format_timeframe("seconds", 30), "30秒") + self.assertEqual(self.locale._format_timeframe("minute", 1), "1分鐘") + self.assertEqual(self.locale._format_timeframe("minutes", 40), "40分鐘") + self.assertEqual(self.locale._format_timeframe("hour", 1), "1小時") + self.assertEqual(self.locale._format_timeframe("hours", 23), "23小時") + self.assertEqual(self.locale._format_timeframe("day", 1), "1天") + self.assertEqual(self.locale._format_timeframe("days", 12), "12天") + self.assertEqual(self.locale._format_timeframe("week", 1), "1星期") + self.assertEqual(self.locale._format_timeframe("weeks", 38), "38星期") + self.assertEqual(self.locale._format_timeframe("month", 1), "1個月") + self.assertEqual(self.locale._format_timeframe("months", 11), "11個月") + self.assertEqual(self.locale._format_timeframe("year", 1), "1年") + self.assertEqual(self.locale._format_timeframe("years", 12), "12年") From 760cab284c451480f85b31fbdfd58b76336ed086 Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Sat, 4 Jan 2020 14:45:18 -0500 Subject: [PATCH 06/13] Moved util tests to pytest --- tests/locales_tests.py | 1 + tests/parser_tests.py.bak | 1629 +++++++++++++++++++++++++++++++++++++ tests/util_tests.py | 27 +- tests/util_tests.py.bak | 40 + 4 files changed, 1683 insertions(+), 14 deletions(-) create mode 100644 tests/parser_tests.py.bak create mode 100644 tests/util_tests.py.bak diff --git a/tests/locales_tests.py b/tests/locales_tests.py index cd1e2e611..1b279ffa7 100644 --- a/tests/locales_tests.py +++ b/tests/locales_tests.py @@ -5,6 +5,7 @@ import pytest + class TestLocaleValidation: """Validate locales to ensure that translations are valid and complete""" diff --git a/tests/parser_tests.py.bak b/tests/parser_tests.py.bak new file mode 100644 index 000000000..c72da044b --- /dev/null +++ b/tests/parser_tests.py.bak @@ -0,0 +1,1629 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import calendar +import os +import time +from datetime import datetime + +from chai import Chai +from dateutil import tz + +from arrow import parser +from arrow.constants import MAX_TIMESTAMP_US +from arrow.parser import DateTimeParser, ParserError, ParserMatchError + +from .utils import make_full_tz_list + + +class DateTimeParserTests(Chai): + def setUp(self): + super(DateTimeParserTests, self).setUp() + + self.parser = parser.DateTimeParser() + + def test_parse_multiformat(self): + + mock_datetime = self.mock() + + self.expect(self.parser.parse).args("str", "fmt_a").raises(ParserMatchError) + self.expect(self.parser.parse).args("str", "fmt_b").returns(mock_datetime) + + result = self.parser._parse_multiformat("str", ["fmt_a", "fmt_b"]) + + self.assertEqual(result, mock_datetime) + + def test_parse_multiformat_all_fail(self): + + self.expect(self.parser.parse).args("str", "fmt_a").raises(ParserMatchError) + self.expect(self.parser.parse).args("str", "fmt_b").raises(ParserMatchError) + + with self.assertRaises(ParserError): + self.parser._parse_multiformat("str", ["fmt_a", "fmt_b"]) + + def test_parse_multiformat_unself_expected_fail(self): + class UnselfExpectedError(Exception): + pass + + self.expect(self.parser.parse).args("str", "fmt_a").raises(UnselfExpectedError) + + with self.assertRaises(UnselfExpectedError): + self.parser._parse_multiformat("str", ["fmt_a", "fmt_b"]) + + def test_parse_token_nonsense(self): + parts = {} + self.parser._parse_token("NONSENSE", "1900", parts) + self.assertEqual(parts, {}) + + def test_parse_token_invalid_meridians(self): + parts = {} + self.parser._parse_token("A", "a..m", parts) + self.assertEqual(parts, {}) + self.parser._parse_token("a", "p..m", parts) + self.assertEqual(parts, {}) + + def test_parser_no_caching(self): + + self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( + 100 + ) + self.parser = parser.DateTimeParser(cache_size=0) + for _ in range(100): + self.parser._generate_pattern_re("fmt_a") + + def test_parser_1_line_caching(self): + + self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( + 1 + ) + self.parser = parser.DateTimeParser(cache_size=1) + for _ in range(100): + self.parser._generate_pattern_re("fmt_a") + + self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_b").times( + 1 + ) + for _ in range(100): + self.parser._generate_pattern_re("fmt_a") + self.parser._generate_pattern_re("fmt_b") + + self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( + 1 + ) + for _ in range(100): + self.parser._generate_pattern_re("fmt_a") + + def test_parser_multiple_line_caching(self): + + self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( + 1 + ) + self.parser = parser.DateTimeParser(cache_size=2) + for _ in range(100): + self.parser._generate_pattern_re("fmt_a") + + self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_b").times( + 1 + ) + for _ in range(100): + self.parser._generate_pattern_re("fmt_a") + self.parser._generate_pattern_re("fmt_b") + + self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( + 0 + ) + for _ in range(100): + self.parser._generate_pattern_re("fmt_a") + + def test_YY_and_YYYY_format_list(self): + + self.assertEqual( + self.parser.parse("15/01/19", ["DD/MM/YY", "DD/MM/YYYY"]), + datetime(2019, 1, 15), + ) + + # Regression test for issue #580 + self.assertEqual( + self.parser.parse("15/01/2019", ["DD/MM/YY", "DD/MM/YYYY"]), + datetime(2019, 1, 15), + ) + + self.assertEqual( + self.parser.parse( + "15/01/2019T04:05:06.789120Z", + ["D/M/YYThh:mm:ss.SZ", "D/M/YYYYThh:mm:ss.SZ"], + ), + datetime(2019, 1, 15, 4, 5, 6, 789120, tzinfo=tz.tzutc()), + ) + + # regression test for issue #447 + def test_timestamp_format_list(self): + # should not match on the "X" token + self.assertEqual( + self.parser.parse( + "15 Jul 2000", + ["MM/DD/YYYY", "YYYY-MM-DD", "X", "DD-MMMM-YYYY", "D MMM YYYY"], + ), + datetime(2000, 7, 15), + ) + + with self.assertRaises(ParserError): + self.parser.parse("15 Jul", "X") + + +class DateTimeParserParseTests(Chai): + def setUp(self): + super(DateTimeParserParseTests, self).setUp() + + self.parser = parser.DateTimeParser() + + def test_parse_list(self): + + self.expect(self.parser._parse_multiformat).args( + "str", ["fmt_a", "fmt_b"] + ).returns("result") + + result = self.parser.parse("str", ["fmt_a", "fmt_b"]) + + self.assertEqual(result, "result") + + def test_parse_unrecognized_token(self): + + mock_input_re_map = self.mock(self.parser, "_input_re_map") + + self.expect(mock_input_re_map.__getitem__).args("YYYY").raises(KeyError) + + with self.assertRaises(parser.ParserError): + self.parser.parse("2013-01-01", "YYYY-MM-DD") + + def test_parse_parse_no_match(self): + + with self.assertRaises(ParserError): + self.parser.parse("01-01", "YYYY-MM-DD") + + def test_parse_separators(self): + + with self.assertRaises(ParserError): + self.parser.parse("1403549231", "YYYY-MM-DD") + + def test_parse_numbers(self): + + self.expected = datetime(2012, 1, 1, 12, 5, 10) + self.assertEqual( + self.parser.parse("2012-01-01 12:05:10", "YYYY-MM-DD HH:mm:ss"), + self.expected, + ) + + def test_parse_year_two_digit(self): + + self.expected = datetime(1979, 1, 1, 12, 5, 10) + self.assertEqual( + self.parser.parse("79-01-01 12:05:10", "YY-MM-DD HH:mm:ss"), self.expected + ) + + def test_parse_timestamp(self): + + tz_utc = tz.tzutc() + int_timestamp = int(time.time()) + self.expected = datetime.fromtimestamp(int_timestamp, tz=tz_utc) + self.assertEqual( + self.parser.parse("{:d}".format(int_timestamp), "X"), self.expected + ) + + float_timestamp = time.time() + self.expected = datetime.fromtimestamp(float_timestamp, tz=tz_utc) + self.assertEqual( + self.parser.parse("{:f}".format(float_timestamp), "X"), self.expected + ) + + # test handling of ns timestamp (arrow will round to 6 digits regardless) + self.expected = datetime.fromtimestamp(float_timestamp, tz=tz_utc) + self.assertEqual( + self.parser.parse("{:f}123".format(float_timestamp), "X"), self.expected + ) + + # test ps timestamp (arrow will round to 6 digits regardless) + self.expected = datetime.fromtimestamp(float_timestamp, tz=tz_utc) + self.assertEqual( + self.parser.parse("{:f}123456".format(float_timestamp), "X"), self.expected + ) + + # NOTE: negative timestamps cannot be handled by datetime on Window + # Must use timedelta to handle them. ref: https://stackoverflow.com/questions/36179914 + if os.name != "nt": + # regression test for issue #662 + negative_int_timestamp = -int_timestamp + self.expected = datetime.fromtimestamp(negative_int_timestamp, tz=tz_utc) + self.assertEqual( + self.parser.parse("{:d}".format(negative_int_timestamp), "X"), + self.expected, + ) + + negative_float_timestamp = -float_timestamp + self.expected = datetime.fromtimestamp(negative_float_timestamp, tz=tz_utc) + self.assertEqual( + self.parser.parse("{:f}".format(negative_float_timestamp), "X"), + self.expected, + ) + + # NOTE: timestamps cannot be parsed from natural language strings (by removing the ^...$) because it will + # break cases like "15 Jul 2000" and a format list (see issue #447) + with self.assertRaises(ParserError): + natural_lang_string = "Meet me at {} at the restaurant.".format( + float_timestamp + ) + self.parser.parse(natural_lang_string, "X") + + with self.assertRaises(ParserError): + self.parser.parse("1565982019.", "X") + + with self.assertRaises(ParserError): + self.parser.parse(".1565982019", "X") + + def test_parse_expanded_timestamp(self): + # test expanded timestamps that include milliseconds + # and microseconds as multiples rather than decimals + # requested in issue #357 + + tz_utc = tz.tzutc() + timestamp = 1569982581.413132 + timestamp_milli = int(round(timestamp * 1000)) + timestamp_micro = int(round(timestamp * 1000000)) + + # "x" token should parse integer timestamps below MAX_TIMESTAMP normally + self.expected = datetime.fromtimestamp(int(timestamp), tz=tz_utc) + self.assertEqual( + self.parser.parse("{:d}".format(int(timestamp)), "x"), self.expected + ) + + self.expected = datetime.fromtimestamp(round(timestamp, 3), tz=tz_utc) + self.assertEqual( + self.parser.parse("{:d}".format(timestamp_milli), "x"), self.expected + ) + + self.expected = datetime.fromtimestamp(timestamp, tz=tz_utc) + self.assertEqual( + self.parser.parse("{:d}".format(timestamp_micro), "x"), self.expected + ) + + # anything above max µs timestamp should fail + with self.assertRaises(ValueError): + self.parser.parse("{:d}".format(int(MAX_TIMESTAMP_US) + 1), "x") + + # floats are not allowed with the "x" token + with self.assertRaises(ParserMatchError): + self.parser.parse("{:f}".format(timestamp), "x") + + def test_parse_names(self): + + self.expected = datetime(2012, 1, 1) + + self.assertEqual( + self.parser.parse("January 1, 2012", "MMMM D, YYYY"), self.expected + ) + self.assertEqual(self.parser.parse("Jan 1, 2012", "MMM D, YYYY"), self.expected) + + def test_parse_pm(self): + + self.expected = datetime(1, 1, 1, 13, 0, 0) + self.assertEqual(self.parser.parse("1 pm", "H a"), self.expected) + self.assertEqual(self.parser.parse("1 pm", "h a"), self.expected) + + self.expected = datetime(1, 1, 1, 1, 0, 0) + self.assertEqual(self.parser.parse("1 am", "H A"), self.expected) + self.assertEqual(self.parser.parse("1 am", "h A"), self.expected) + + self.expected = datetime(1, 1, 1, 0, 0, 0) + self.assertEqual(self.parser.parse("12 am", "H A"), self.expected) + self.assertEqual(self.parser.parse("12 am", "h A"), self.expected) + + self.expected = datetime(1, 1, 1, 12, 0, 0) + self.assertEqual(self.parser.parse("12 pm", "H A"), self.expected) + self.assertEqual(self.parser.parse("12 pm", "h A"), self.expected) + + def test_parse_tz_hours_only(self): + self.expected = datetime(2025, 10, 17, 5, 30, 10, tzinfo=tz.tzoffset(None, 0)) + parsed = self.parser.parse("2025-10-17 05:30:10+00", "YYYY-MM-DD HH:mm:ssZ") + self.assertEqual(parsed, self.expected) + + def test_parse_tz_zz(self): + + self.expected = datetime(2013, 1, 1, tzinfo=tz.tzoffset(None, -7 * 3600)) + self.assertEqual( + self.parser.parse("2013-01-01 -07:00", "YYYY-MM-DD ZZ"), self.expected + ) + + def test_parse_tz_name_zzz(self): + for tz_name in make_full_tz_list(): + self.expected = datetime(2013, 1, 1, tzinfo=tz.gettz(tz_name)) + self.assertEqual( + self.parser.parse("2013-01-01 %s" % tz_name, "YYYY-MM-DD ZZZ"), + self.expected, + ) + + # note that offsets are not timezones + with self.assertRaises(ParserError): + self.parser.parse("2013-01-01 12:30:45.9+1000", "YYYY-MM-DDZZZ") + + with self.assertRaises(ParserError): + self.parser.parse("2013-01-01 12:30:45.9+10:00", "YYYY-MM-DDZZZ") + + with self.assertRaises(ParserError): + self.parser.parse("2013-01-01 12:30:45.9-10", "YYYY-MM-DDZZZ") + + def test_parse_subsecond(self): + # TODO: make both test_parse_subsecond functions in Parse and ParseISO + # tests use the same expected objects (use pytest fixtures) + self.expected = datetime(2013, 1, 1, 12, 30, 45, 900000) + self.assertEqual( + self.parser.parse("2013-01-01 12:30:45.9", "YYYY-MM-DD HH:mm:ss.S"), + self.expected, + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 980000) + self.assertEqual( + self.parser.parse("2013-01-01 12:30:45.98", "YYYY-MM-DD HH:mm:ss.SS"), + self.expected, + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987000) + self.assertEqual( + self.parser.parse("2013-01-01 12:30:45.987", "YYYY-MM-DD HH:mm:ss.SSS"), + self.expected, + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987600) + self.assertEqual( + self.parser.parse("2013-01-01 12:30:45.9876", "YYYY-MM-DD HH:mm:ss.SSSS"), + self.expected, + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987650) + self.assertEqual( + self.parser.parse("2013-01-01 12:30:45.98765", "YYYY-MM-DD HH:mm:ss.SSSSS"), + self.expected, + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) + self.assertEqual( + self.parser.parse( + "2013-01-01 12:30:45.987654", "YYYY-MM-DD HH:mm:ss.SSSSSS" + ), + self.expected, + ) + + def test_parse_subsecond_rounding(self): + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) + datetime_format = "YYYY-MM-DD HH:mm:ss.S" + + # round up + string = "2013-01-01 12:30:45.9876539" + self.assertEqual(self.parser.parse(string, datetime_format), self.expected) + self.assertEqual(self.parser.parse_iso(string), self.expected) + + # round down + string = "2013-01-01 12:30:45.98765432" + self.assertEqual(self.parser.parse(string, datetime_format), self.expected) + self.assertEqual(self.parser.parse_iso(string), self.expected) + + # round half-up + string = "2013-01-01 12:30:45.987653521" + self.assertEqual(self.parser.parse(string, datetime_format), self.expected) + self.assertEqual(self.parser.parse_iso(string), self.expected) + + # round half-down + string = "2013-01-01 12:30:45.9876545210" + self.assertEqual(self.parser.parse(string, datetime_format), self.expected) + self.assertEqual(self.parser.parse_iso(string), self.expected) + + # overflow (zero out the subseconds and increment the seconds) + # regression tests for issue #636 + def test_parse_subsecond_rounding_overflow(self): + datetime_format = "YYYY-MM-DD HH:mm:ss.S" + + self.expected = datetime(2013, 1, 1, 12, 30, 46) + string = "2013-01-01 12:30:45.9999995" + self.assertEqual(self.parser.parse(string, datetime_format), self.expected) + self.assertEqual(self.parser.parse_iso(string), self.expected) + + self.expected = datetime(2013, 1, 1, 12, 31, 0) + string = "2013-01-01 12:30:59.9999999" + self.assertEqual(self.parser.parse(string, datetime_format), self.expected) + self.assertEqual(self.parser.parse_iso(string), self.expected) + + self.expected = datetime(2013, 1, 2, 0, 0, 0) + string = "2013-01-01 23:59:59.9999999" + self.assertEqual(self.parser.parse(string, datetime_format), self.expected) + self.assertEqual(self.parser.parse_iso(string), self.expected) + + # 6 digits should remain unrounded + self.expected = datetime(2013, 1, 1, 12, 30, 45, 999999) + string = "2013-01-01 12:30:45.999999" + self.assertEqual(self.parser.parse(string, datetime_format), self.expected) + self.assertEqual(self.parser.parse_iso(string), self.expected) + + # Regression tests for issue #560 + def test_parse_long_year(self): + with self.assertRaises(ParserError): + self.parser.parse("09 January 123456789101112", "DD MMMM YYYY") + + with self.assertRaises(ParserError): + self.parser.parse("123456789101112 09 January", "YYYY DD MMMM") + + with self.assertRaises(ParserError): + self.parser.parse("68096653015/01/19", "YY/M/DD") + + def test_parse_with_extra_words_at_start_and_end_invalid(self): + input_format_pairs = [ + ("blah2016", "YYYY"), + ("blah2016blah", "YYYY"), + ("2016blah", "YYYY"), + ("2016-05blah", "YYYY-MM"), + ("2016-05-16blah", "YYYY-MM-DD"), + ("2016-05-16T04:05:06.789120blah", "YYYY-MM-DDThh:mm:ss.S"), + ("2016-05-16T04:05:06.789120ZblahZ", "YYYY-MM-DDThh:mm:ss.SZ"), + ("2016-05-16T04:05:06.789120Zblah", "YYYY-MM-DDThh:mm:ss.SZ"), + ("2016-05-16T04:05:06.789120blahZ", "YYYY-MM-DDThh:mm:ss.SZ"), + ] + + for pair in input_format_pairs: + with self.assertRaises(ParserError): + self.parser.parse(pair[0], pair[1]) + + def test_parse_with_extra_words_at_start_and_end_valid(self): + # Spaces surrounding the parsable date are ok because we + # allow the parsing of natural language input. Additionally, a single + # character of specific punctuation before or after the date is okay. + # See docs for full list of valid punctuation. + + self.assertEqual( + self.parser.parse("blah 2016 blah", "YYYY"), datetime(2016, 1, 1) + ) + + self.assertEqual(self.parser.parse("blah 2016", "YYYY"), datetime(2016, 1, 1)) + + self.assertEqual(self.parser.parse("2016 blah", "YYYY"), datetime(2016, 1, 1)) + + # test one additional space along with space divider + self.assertEqual( + self.parser.parse( + "blah 2016-05-16 04:05:06.789120", "YYYY-MM-DD hh:mm:ss.S" + ), + datetime(2016, 5, 16, 4, 5, 6, 789120), + ) + + self.assertEqual( + self.parser.parse( + "2016-05-16 04:05:06.789120 blah", "YYYY-MM-DD hh:mm:ss.S" + ), + datetime(2016, 5, 16, 4, 5, 6, 789120), + ) + + # test one additional space along with T divider + self.assertEqual( + self.parser.parse( + "blah 2016-05-16T04:05:06.789120", "YYYY-MM-DDThh:mm:ss.S" + ), + datetime(2016, 5, 16, 4, 5, 6, 789120), + ) + + self.assertEqual( + self.parser.parse( + "2016-05-16T04:05:06.789120 blah", "YYYY-MM-DDThh:mm:ss.S" + ), + datetime(2016, 5, 16, 4, 5, 6, 789120), + ) + + self.assertEqual( + self.parser.parse( + "Meet me at 2016-05-16T04:05:06.789120 at the restaurant.", + "YYYY-MM-DDThh:mm:ss.S", + ), + datetime(2016, 5, 16, 4, 5, 6, 789120), + ) + + self.assertEqual( + self.parser.parse( + "Meet me at 2016-05-16 04:05:06.789120 at the restaurant.", + "YYYY-MM-DD hh:mm:ss.S", + ), + datetime(2016, 5, 16, 4, 5, 6, 789120), + ) + + # regression test for issue #701 + # tests cases of a partial match surrounded by punctuation + # for the list of valid punctuation, see documentation + def test_parse_with_punctuation_fences(self): + self.assertEqual( + self.parser.parse( + "Meet me at my house on Halloween (2019-31-10)", "YYYY-DD-MM" + ), + datetime(2019, 10, 31), + ) + + self.assertEqual( + self.parser.parse( + "Monday, 9. September 2019, 16:15-20:00", "dddd, D. MMMM YYYY" + ), + datetime(2019, 9, 9), + ) + + self.assertEqual( + self.parser.parse("A date is 11.11.2011.", "DD.MM.YYYY"), + datetime(2011, 11, 11), + ) + + with self.assertRaises(ParserMatchError): + self.parser.parse("11.11.2011.1 is not a valid date.", "DD.MM.YYYY") + + with self.assertRaises(ParserMatchError): + self.parser.parse( + "This date has too many punctuation marks following it (11.11.2011).", + "DD.MM.YYYY", + ) + + def test_parse_with_leading_and_trailing_whitespace(self): + self.assertEqual(self.parser.parse(" 2016", "YYYY"), datetime(2016, 1, 1)) + + self.assertEqual(self.parser.parse("2016 ", "YYYY"), datetime(2016, 1, 1)) + + self.assertEqual( + self.parser.parse(" 2016 ", "YYYY"), datetime(2016, 1, 1) + ) + + self.assertEqual( + self.parser.parse( + " 2016-05-16 04:05:06.789120 ", "YYYY-MM-DD hh:mm:ss.S" + ), + datetime(2016, 5, 16, 4, 5, 6, 789120), + ) + + self.assertEqual( + self.parser.parse( + " 2016-05-16T04:05:06.789120 ", "YYYY-MM-DDThh:mm:ss.S" + ), + datetime(2016, 5, 16, 4, 5, 6, 789120), + ) + + def test_parse_YYYY_DDDD(self): + self.assertEqual( + self.parser.parse("1998-136", "YYYY-DDDD"), datetime(1998, 5, 16) + ) + + self.assertEqual( + self.parser.parse("1998-006", "YYYY-DDDD"), datetime(1998, 1, 6) + ) + + with self.assertRaises(ParserError): + self.parser.parse("1998-456", "YYYY-DDDD") + + def test_parse_YYYY_DDD(self): + self.assertEqual(self.parser.parse("1998-6", "YYYY-DDD"), datetime(1998, 1, 6)) + + self.assertEqual( + self.parser.parse("1998-136", "YYYY-DDD"), datetime(1998, 5, 16) + ) + + with self.assertRaises(ParserError): + self.parser.parse("1998-756", "YYYY-DDD") + + # month cannot be passed with DDD and DDDD tokens + def test_parse_YYYY_MM_DDDD(self): + with self.assertRaises(ParserError): + self.parser.parse("2015-01-009", "YYYY-MM-DDDD") + + # year is required with the DDD and DDDD tokens + def test_parse_DDD_only(self): + with self.assertRaises(ParserError): + self.parser.parse("5", "DDD") + + def test_parse_DDDD_only(self): + with self.assertRaises(ParserError): + self.parser.parse("145", "DDDD") + + def test_parse_HH_24(self): + self.assertEqual( + self.parser.parse("2019-10-30T24:00:00", "YYYY-MM-DDTHH:mm:ss"), + datetime(2019, 10, 31, 0, 0, 0, 0), + ) + self.assertEqual( + self.parser.parse("2019-10-30T24:00", "YYYY-MM-DDTHH:mm"), + datetime(2019, 10, 31, 0, 0, 0, 0), + ) + self.assertEqual( + self.parser.parse("2019-10-30T24", "YYYY-MM-DDTHH"), + datetime(2019, 10, 31, 0, 0, 0, 0), + ) + self.assertEqual( + self.parser.parse("2019-10-30T24:00:00.0", "YYYY-MM-DDTHH:mm:ss.S"), + datetime(2019, 10, 31, 0, 0, 0, 0), + ) + self.assertEqual( + self.parser.parse("2019-10-31T24:00:00", "YYYY-MM-DDTHH:mm:ss"), + datetime(2019, 11, 1, 0, 0, 0, 0), + ) + self.assertEqual( + self.parser.parse("2019-12-31T24:00:00", "YYYY-MM-DDTHH:mm:ss"), + datetime(2020, 1, 1, 0, 0, 0, 0), + ) + self.assertEqual( + self.parser.parse("2019-12-31T23:59:59.9999999", "YYYY-MM-DDTHH:mm:ss.S"), + datetime(2020, 1, 1, 0, 0, 0, 0), + ) + + with self.assertRaises(ParserError): + self.parser.parse("2019-12-31T24:01:00", "YYYY-MM-DDTHH:mm:ss") + + with self.assertRaises(ParserError): + self.parser.parse("2019-12-31T24:00:01", "YYYY-MM-DDTHH:mm:ss") + + with self.assertRaises(ParserError): + self.parser.parse("2019-12-31T24:00:00.1", "YYYY-MM-DDTHH:mm:ss.S") + + with self.assertRaises(ParserError): + self.parser.parse("2019-12-31T24:00:00.999999", "YYYY-MM-DDTHH:mm:ss.S") + + +class DateTimeParserRegexTests(Chai): + def setUp(self): + super(DateTimeParserRegexTests, self).setUp() + + self.format_regex = parser.DateTimeParser._FORMAT_RE + + def test_format_year(self): + + self.assertEqual(self.format_regex.findall("YYYY-YY"), ["YYYY", "YY"]) + + def test_format_month(self): + + self.assertEqual( + self.format_regex.findall("MMMM-MMM-MM-M"), ["MMMM", "MMM", "MM", "M"] + ) + + def test_format_day(self): + + self.assertEqual( + self.format_regex.findall("DDDD-DDD-DD-D"), ["DDDD", "DDD", "DD", "D"] + ) + + def test_format_hour(self): + + self.assertEqual(self.format_regex.findall("HH-H-hh-h"), ["HH", "H", "hh", "h"]) + + def test_format_minute(self): + + self.assertEqual(self.format_regex.findall("mm-m"), ["mm", "m"]) + + def test_format_second(self): + + self.assertEqual(self.format_regex.findall("ss-s"), ["ss", "s"]) + + def test_format_subsecond(self): + + self.assertEqual( + self.format_regex.findall("SSSSSS-SSSSS-SSSS-SSS-SS-S"), + ["SSSSSS", "SSSSS", "SSSS", "SSS", "SS", "S"], + ) + + def test_format_tz(self): + + self.assertEqual(self.format_regex.findall("ZZZ-ZZ-Z"), ["ZZZ", "ZZ", "Z"]) + + def test_format_am_pm(self): + + self.assertEqual(self.format_regex.findall("A-a"), ["A", "a"]) + + def test_format_timestamp(self): + + self.assertEqual(self.format_regex.findall("X"), ["X"]) + + def test_format_timestamp_milli(self): + + self.assertEqual(self.format_regex.findall("x"), ["x"]) + + def test_escape(self): + + escape_regex = parser.DateTimeParser._ESCAPE_RE + + self.assertEqual( + escape_regex.findall("2018-03-09 8 [h] 40 [hello]"), ["[h]", "[hello]"] + ) + + def test_month_names(self): + p = parser.DateTimeParser("en_us") + + text = "_".join(calendar.month_name[1:]) + + result = p._input_re_map["MMMM"].findall(text) + + self.assertEqual(result, calendar.month_name[1:]) + + def test_month_abbreviations(self): + p = parser.DateTimeParser("en_us") + + text = "_".join(calendar.month_abbr[1:]) + + result = p._input_re_map["MMM"].findall(text) + + self.assertEqual(result, calendar.month_abbr[1:]) + + def test_digits(self): + + self.assertEqual( + parser.DateTimeParser._ONE_OR_TWO_DIGIT_RE.findall("4-56"), ["4", "56"] + ) + self.assertEqual( + parser.DateTimeParser._ONE_OR_TWO_OR_THREE_DIGIT_RE.findall("4-56-789"), + ["4", "56", "789"], + ) + self.assertEqual( + parser.DateTimeParser._ONE_OR_MORE_DIGIT_RE.findall("4-56-789-1234-12345"), + ["4", "56", "789", "1234", "12345"], + ) + self.assertEqual( + parser.DateTimeParser._TWO_DIGIT_RE.findall("12-3-45"), ["12", "45"] + ) + self.assertEqual( + parser.DateTimeParser._THREE_DIGIT_RE.findall("123-4-56"), ["123"] + ) + self.assertEqual( + parser.DateTimeParser._FOUR_DIGIT_RE.findall("1234-56"), ["1234"] + ) + + def test_tz(self): + tz_z_re = parser.DateTimeParser._TZ_Z_RE + self.assertEqual(tz_z_re.findall("-0700"), [("-", "07", "00")]) + self.assertEqual(tz_z_re.findall("+07"), [("+", "07", "")]) + self.assertTrue(tz_z_re.search("15/01/2019T04:05:06.789120Z") is not None) + self.assertTrue(tz_z_re.search("15/01/2019T04:05:06.789120") is None) + + tz_zz_re = parser.DateTimeParser._TZ_ZZ_RE + self.assertEqual(tz_zz_re.findall("-07:00"), [("-", "07", "00")]) + self.assertEqual(tz_zz_re.findall("+07"), [("+", "07", "")]) + self.assertTrue(tz_zz_re.search("15/01/2019T04:05:06.789120Z") is not None) + self.assertTrue(tz_zz_re.search("15/01/2019T04:05:06.789120") is None) + + tz_name_re = parser.DateTimeParser._TZ_NAME_RE + self.assertEqual(tz_name_re.findall("Europe/Warsaw"), ["Europe/Warsaw"]) + self.assertEqual(tz_name_re.findall("GMT"), ["GMT"]) + + def test_timestamp(self): + timestamp_re = parser.DateTimeParser._TIMESTAMP_RE + self.assertEqual( + timestamp_re.findall("1565707550.452729"), ["1565707550.452729"] + ) + self.assertEqual( + timestamp_re.findall("-1565707550.452729"), ["-1565707550.452729"] + ) + self.assertEqual(timestamp_re.findall("-1565707550"), ["-1565707550"]) + self.assertEqual(timestamp_re.findall("1565707550"), ["1565707550"]) + self.assertEqual(timestamp_re.findall("1565707550."), []) + self.assertEqual(timestamp_re.findall(".1565707550"), []) + + def test_timestamp_milli(self): + timestamp_expanded_re = parser.DateTimeParser._TIMESTAMP_EXPANDED_RE + self.assertEqual(timestamp_expanded_re.findall("-1565707550"), ["-1565707550"]) + self.assertEqual(timestamp_expanded_re.findall("1565707550"), ["1565707550"]) + self.assertEqual(timestamp_expanded_re.findall("1565707550.452729"), []) + self.assertEqual(timestamp_expanded_re.findall("1565707550."), []) + self.assertEqual(timestamp_expanded_re.findall(".1565707550"), []) + + def test_time(self): + time_re = parser.DateTimeParser._TIME_RE + time_seperators = [":", ""] + + for sep in time_seperators: + self.assertEqual(time_re.findall("12"), [("12", "", "", "", "")]) + self.assertEqual( + time_re.findall("12{sep}35".format(sep=sep)), [("12", "35", "", "", "")] + ) + self.assertEqual( + time_re.findall("12{sep}35{sep}46".format(sep=sep)), + [("12", "35", "46", "", "")], + ) + self.assertEqual( + time_re.findall("12{sep}35{sep}46.952313".format(sep=sep)), + [("12", "35", "46", ".", "952313")], + ) + self.assertEqual( + time_re.findall("12{sep}35{sep}46,952313".format(sep=sep)), + [("12", "35", "46", ",", "952313")], + ) + + self.assertEqual(time_re.findall("12:"), []) + self.assertEqual(time_re.findall("12:35:46."), []) + self.assertEqual(time_re.findall("12:35:46,"), []) + + +class DateTimeParserISOTests(Chai): + def setUp(self): + super(DateTimeParserISOTests, self).setUp() + + self.parser = parser.DateTimeParser("en_us") + + def test_YYYY(self): + + self.assertEqual(self.parser.parse_iso("2013"), datetime(2013, 1, 1)) + + def test_YYYY_DDDD(self): + self.assertEqual(self.parser.parse_iso("1998-136"), datetime(1998, 5, 16)) + + self.assertEqual(self.parser.parse_iso("1998-006"), datetime(1998, 1, 6)) + + with self.assertRaises(ParserError): + self.parser.parse_iso("1998-456") + + # 2016 is a leap year, so Feb 29 exists (leap day) + self.assertEqual(self.parser.parse_iso("2016-059"), datetime(2016, 2, 28)) + self.assertEqual(self.parser.parse_iso("2016-060"), datetime(2016, 2, 29)) + self.assertEqual(self.parser.parse_iso("2016-061"), datetime(2016, 3, 1)) + + # 2017 is not a leap year, so Feb 29 does not exist + self.assertEqual(self.parser.parse_iso("2017-059"), datetime(2017, 2, 28)) + self.assertEqual(self.parser.parse_iso("2017-060"), datetime(2017, 3, 1)) + self.assertEqual(self.parser.parse_iso("2017-061"), datetime(2017, 3, 2)) + + # Since 2016 is a leap year, the 366th day falls in the same year + self.assertEqual(self.parser.parse_iso("2016-366"), datetime(2016, 12, 31)) + + # Since 2017 is not a leap year, the 366th day falls in the next year + self.assertEqual(self.parser.parse_iso("2017-366"), datetime(2018, 1, 1)) + + def test_YYYY_DDDD_HH_mm_ssZ(self): + + self.assertEqual( + self.parser.parse_iso("2013-036 04:05:06+01:00"), + datetime(2013, 2, 5, 4, 5, 6, tzinfo=tz.tzoffset(None, 3600)), + ) + + self.assertEqual( + self.parser.parse_iso("2013-036 04:05:06Z"), + datetime(2013, 2, 5, 4, 5, 6, tzinfo=tz.tzutc()), + ) + + def test_YYYY_MM_DDDD(self): + with self.assertRaises(ParserError): + self.parser.parse_iso("2014-05-125") + + def test_YYYY_MM(self): + + for separator in DateTimeParser.SEPARATORS: + self.assertEqual( + self.parser.parse_iso(separator.join(("2013", "02"))), + datetime(2013, 2, 1), + ) + + def test_YYYY_MM_DD(self): + + for separator in DateTimeParser.SEPARATORS: + self.assertEqual( + self.parser.parse_iso(separator.join(("2013", "02", "03"))), + datetime(2013, 2, 3), + ) + + def test_YYYY_MM_DDTHH_mmZ(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05+01:00"), + datetime(2013, 2, 3, 4, 5, tzinfo=tz.tzoffset(None, 3600)), + ) + + def test_YYYY_MM_DDTHH_mm(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05"), datetime(2013, 2, 3, 4, 5) + ) + + def test_YYYY_MM_DDTHH(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04"), datetime(2013, 2, 3, 4) + ) + + def test_YYYY_MM_DDTHHZ(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04+01:00"), + datetime(2013, 2, 3, 4, tzinfo=tz.tzoffset(None, 3600)), + ) + + def test_YYYY_MM_DDTHH_mm_ssZ(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06+01:00"), + datetime(2013, 2, 3, 4, 5, 6, tzinfo=tz.tzoffset(None, 3600)), + ) + + def test_YYYY_MM_DDTHH_mm_ss(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06"), datetime(2013, 2, 3, 4, 5, 6) + ) + + def test_YYYY_MM_DD_HH_mmZ(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03 04:05+01:00"), + datetime(2013, 2, 3, 4, 5, tzinfo=tz.tzoffset(None, 3600)), + ) + + def test_YYYY_MM_DD_HH_mm(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03 04:05"), datetime(2013, 2, 3, 4, 5) + ) + + def test_YYYY_MM_DD_HH(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03 04"), datetime(2013, 2, 3, 4) + ) + + def test_invalid_time(self): + + with self.assertRaises(ParserError): + self.parser.parse_iso("2013-02-03T") + + with self.assertRaises(ParserError): + self.parser.parse_iso("2013-02-03 044") + + with self.assertRaises(ParserError): + self.parser.parse_iso("2013-02-03 04:05:06.") + + def test_YYYY_MM_DD_HH_mm_ssZ(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03 04:05:06+01:00"), + datetime(2013, 2, 3, 4, 5, 6, tzinfo=tz.tzoffset(None, 3600)), + ) + + def test_YYYY_MM_DD_HH_mm_ss(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03 04:05:06"), datetime(2013, 2, 3, 4, 5, 6) + ) + + def test_YYYY_MM_DDTHH_mm_ss_S(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06.7"), + datetime(2013, 2, 3, 4, 5, 6, 700000), + ) + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06.78"), + datetime(2013, 2, 3, 4, 5, 6, 780000), + ) + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06.789"), + datetime(2013, 2, 3, 4, 5, 6, 789000), + ) + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06.7891"), + datetime(2013, 2, 3, 4, 5, 6, 789100), + ) + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06.78912"), + datetime(2013, 2, 3, 4, 5, 6, 789120), + ) + + # ISO 8601:2004(E), ISO, 2004-12-01, 4.2.2.4 ... the decimal fraction + # shall be divided from the integer part by the decimal sign specified + # in ISO 31-0, i.e. the comma [,] or full stop [.]. Of these, the comma + # is the preferred sign. + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06,789123678"), + datetime(2013, 2, 3, 4, 5, 6, 789124), + ) + + # there is no limit on the number of decimal places + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06.789123678"), + datetime(2013, 2, 3, 4, 5, 6, 789124), + ) + + def test_YYYY_MM_DDTHH_mm_ss_SZ(self): + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06.7+01:00"), + datetime(2013, 2, 3, 4, 5, 6, 700000, tzinfo=tz.tzoffset(None, 3600)), + ) + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06.78+01:00"), + datetime(2013, 2, 3, 4, 5, 6, 780000, tzinfo=tz.tzoffset(None, 3600)), + ) + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06.789+01:00"), + datetime(2013, 2, 3, 4, 5, 6, 789000, tzinfo=tz.tzoffset(None, 3600)), + ) + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06.7891+01:00"), + datetime(2013, 2, 3, 4, 5, 6, 789100, tzinfo=tz.tzoffset(None, 3600)), + ) + + self.assertEqual( + self.parser.parse_iso("2013-02-03T04:05:06.78912+01:00"), + datetime(2013, 2, 3, 4, 5, 6, 789120, tzinfo=tz.tzoffset(None, 3600)), + ) + + self.assertEqual( + self.parser.parse_iso("2013-02-03 04:05:06.78912Z"), + datetime(2013, 2, 3, 4, 5, 6, 789120, tzinfo=tz.tzutc()), + ) + + def test_invalid_Z(self): + + with self.assertRaises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912z") + + with self.assertRaises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912zz") + + with self.assertRaises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912Zz") + + with self.assertRaises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912ZZ") + + with self.assertRaises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912+Z") + + with self.assertRaises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912-Z") + + with self.assertRaises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912 Z") + + def test_parse_subsecond(self): + # TODO: make both test_parse_subsecond functions in Parse and ParseISO + # tests use the same expected objects (use pytest fixtures) + self.expected = datetime(2013, 1, 1, 12, 30, 45, 900000) + self.assertEqual(self.parser.parse_iso("2013-01-01 12:30:45.9"), self.expected) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 980000) + self.assertEqual(self.parser.parse_iso("2013-01-01 12:30:45.98"), self.expected) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987000) + self.assertEqual( + self.parser.parse_iso("2013-01-01 12:30:45.987"), self.expected + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987600) + self.assertEqual( + self.parser.parse_iso("2013-01-01 12:30:45.9876"), self.expected + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987650) + self.assertEqual( + self.parser.parse_iso("2013-01-01 12:30:45.98765"), self.expected + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) + self.assertEqual( + self.parser.parse_iso("2013-01-01 12:30:45.987654"), self.expected + ) + + # use comma as subsecond separator + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) + self.assertEqual( + self.parser.parse_iso("2013-01-01 12:30:45,987654"), self.expected + ) + + def test_gnu_date(self): + """ + regression tests for parsing output from GNU date(1) + """ + # date -Ins + self.assertEqual( + self.parser.parse_iso("2016-11-16T09:46:30,895636557-0800"), + datetime( + 2016, 11, 16, 9, 46, 30, 895636, tzinfo=tz.tzoffset(None, -3600 * 8) + ), + ) + + # date --rfc-3339=ns + self.assertEqual( + self.parser.parse_iso("2016-11-16 09:51:14.682141526-08:00"), + datetime( + 2016, 11, 16, 9, 51, 14, 682142, tzinfo=tz.tzoffset(None, -3600 * 8) + ), + ) + + def test_isoformat(self): + + dt = datetime.utcnow() + + self.assertEqual(self.parser.parse_iso(dt.isoformat()), dt) + + def test_parse_iso_with_leading_and_trailing_whitespace(self): + datetime_string = " 2016-11-15T06:37:19.123456" + with self.assertRaises(ParserError): + self.parser.parse_iso(datetime_string) + + datetime_string = " 2016-11-15T06:37:19.123456 " + with self.assertRaises(ParserError): + self.parser.parse_iso(datetime_string) + + datetime_string = "2016-11-15T06:37:19.123456 " + with self.assertRaises(ParserError): + self.parser.parse_iso(datetime_string) + + datetime_string = "2016-11-15T 06:37:19.123456" + with self.assertRaises(ParserError): + self.parser.parse_iso(datetime_string) + + # leading whitespace + datetime_string = " 2016-11-15 06:37:19.123456" + with self.assertRaises(ParserError): + self.parser.parse_iso(datetime_string) + + # trailing whitespace + datetime_string = "2016-11-15 06:37:19.123456 " + with self.assertRaises(ParserError): + self.parser.parse_iso(datetime_string) + + datetime_string = " 2016-11-15 06:37:19.123456 " + with self.assertRaises(ParserError): + self.parser.parse_iso(datetime_string) + + # two dividing spaces + datetime_string = "2016-11-15 06:37:19.123456" + with self.assertRaises(ParserError): + self.parser.parse_iso(datetime_string) + + def test_parse_iso_with_extra_words_at_start_and_end_invalid(self): + test_inputs = [ + "blah2016", + "blah2016blah", + "blah 2016 blah", + "blah 2016", + "2016 blah", + "blah 2016-05-16 04:05:06.789120", + "2016-05-16 04:05:06.789120 blah", + "blah 2016-05-16T04:05:06.789120", + "2016-05-16T04:05:06.789120 blah", + "2016blah", + "2016-05blah", + "2016-05-16blah", + "2016-05-16T04:05:06.789120blah", + "2016-05-16T04:05:06.789120ZblahZ", + "2016-05-16T04:05:06.789120Zblah", + "2016-05-16T04:05:06.789120blahZ", + "Meet me at 2016-05-16T04:05:06.789120 at the restaurant.", + "Meet me at 2016-05-16 04:05:06.789120 at the restaurant.", + ] + + for ti in test_inputs: + with self.assertRaises(ParserError): + self.parser.parse_iso(ti) + + def test_iso8601_basic_format(self): + self.assertEqual(self.parser.parse_iso("20180517"), datetime(2018, 5, 17)) + + self.assertEqual( + self.parser.parse_iso("20180517T10"), datetime(2018, 5, 17, 10) + ) + + self.assertEqual( + self.parser.parse_iso("20180517T105513.843456"), + datetime(2018, 5, 17, 10, 55, 13, 843456), + ) + + self.assertEqual( + self.parser.parse_iso("20180517T105513Z"), + datetime(2018, 5, 17, 10, 55, 13, tzinfo=tz.tzutc()), + ) + + self.assertEqual( + self.parser.parse_iso("20180517T105513.843456-0700"), + datetime(2018, 5, 17, 10, 55, 13, 843456, tzinfo=tz.tzoffset(None, -25200)), + ) + + self.assertEqual( + self.parser.parse_iso("20180517T105513-0700"), + datetime(2018, 5, 17, 10, 55, 13, tzinfo=tz.tzoffset(None, -25200)), + ) + + self.assertEqual( + self.parser.parse_iso("20180517T105513-07"), + datetime(2018, 5, 17, 10, 55, 13, tzinfo=tz.tzoffset(None, -25200)), + ) + + # ordinal in basic format: YYYYDDDD + self.assertEqual(self.parser.parse_iso("1998136"), datetime(1998, 5, 16)) + + # timezone requires +- seperator + with self.assertRaises(ParserError): + self.parser.parse_iso("20180517T1055130700") + + with self.assertRaises(ParserError): + self.parser.parse_iso("20180517T10551307") + + # too many digits in date + with self.assertRaises(ParserError): + self.parser.parse_iso("201860517T105513Z") + + # too many digits in time + with self.assertRaises(ParserError): + self.parser.parse_iso("20180517T1055213Z") + + def test_midnight_end_day(self): + self.assertEqual( + self.parser.parse_iso("2019-10-30T24:00:00"), + datetime(2019, 10, 31, 0, 0, 0, 0), + ) + self.assertEqual( + self.parser.parse_iso("2019-10-30T24:00"), + datetime(2019, 10, 31, 0, 0, 0, 0), + ) + self.assertEqual( + self.parser.parse_iso("2019-10-30T24:00:00.0"), + datetime(2019, 10, 31, 0, 0, 0, 0), + ) + self.assertEqual( + self.parser.parse_iso("2019-10-31T24:00:00"), + datetime(2019, 11, 1, 0, 0, 0, 0), + ) + self.assertEqual( + self.parser.parse_iso("2019-12-31T24:00:00"), + datetime(2020, 1, 1, 0, 0, 0, 0), + ) + self.assertEqual( + self.parser.parse_iso("2019-12-31T23:59:59.9999999"), + datetime(2020, 1, 1, 0, 0, 0, 0), + ) + + with self.assertRaises(ParserError): + self.parser.parse_iso("2019-12-31T24:01:00") + + with self.assertRaises(ParserError): + self.parser.parse_iso("2019-12-31T24:00:01") + + with self.assertRaises(ParserError): + self.parser.parse_iso("2019-12-31T24:00:00.1") + + with self.assertRaises(ParserError): + self.parser.parse_iso("2019-12-31T24:00:00.999999") + + +class TzinfoParserTests(Chai): + def setUp(self): + super(TzinfoParserTests, self).setUp() + + self.parser = parser.TzinfoParser() + + def test_parse_local(self): + + self.assertEqual(self.parser.parse("local"), tz.tzlocal()) + + def test_parse_utc(self): + + self.assertEqual(self.parser.parse("utc"), tz.tzutc()) + self.assertEqual(self.parser.parse("UTC"), tz.tzutc()) + + def test_parse_iso(self): + + self.assertEqual(self.parser.parse("01:00"), tz.tzoffset(None, 3600)) + self.assertEqual( + self.parser.parse("11:35"), tz.tzoffset(None, 11 * 3600 + 2100) + ) + self.assertEqual(self.parser.parse("+01:00"), tz.tzoffset(None, 3600)) + self.assertEqual(self.parser.parse("-01:00"), tz.tzoffset(None, -3600)) + + self.assertEqual(self.parser.parse("0100"), tz.tzoffset(None, 3600)) + self.assertEqual(self.parser.parse("+0100"), tz.tzoffset(None, 3600)) + self.assertEqual(self.parser.parse("-0100"), tz.tzoffset(None, -3600)) + + self.assertEqual(self.parser.parse("01"), tz.tzoffset(None, 3600)) + self.assertEqual(self.parser.parse("+01"), tz.tzoffset(None, 3600)) + self.assertEqual(self.parser.parse("-01"), tz.tzoffset(None, -3600)) + + def test_parse_str(self): + + self.assertEqual(self.parser.parse("US/Pacific"), tz.gettz("US/Pacific")) + + def test_parse_fails(self): + + with self.assertRaises(parser.ParserError): + self.parser.parse("fail") + + +class DateTimeParserMonthNameTests(Chai): + def setUp(self): + super(DateTimeParserMonthNameTests, self).setUp() + + self.parser = parser.DateTimeParser("en_us") + + def test_shortmonth_capitalized(self): + + self.assertEqual( + self.parser.parse("2013-Jan-01", "YYYY-MMM-DD"), datetime(2013, 1, 1) + ) + + def test_shortmonth_allupper(self): + + self.assertEqual( + self.parser.parse("2013-JAN-01", "YYYY-MMM-DD"), datetime(2013, 1, 1) + ) + + def test_shortmonth_alllower(self): + + self.assertEqual( + self.parser.parse("2013-jan-01", "YYYY-MMM-DD"), datetime(2013, 1, 1) + ) + + def test_month_capitalized(self): + + self.assertEqual( + self.parser.parse("2013-January-01", "YYYY-MMMM-DD"), datetime(2013, 1, 1) + ) + + def test_month_allupper(self): + + self.assertEqual( + self.parser.parse("2013-JANUARY-01", "YYYY-MMMM-DD"), datetime(2013, 1, 1) + ) + + def test_month_alllower(self): + + self.assertEqual( + self.parser.parse("2013-january-01", "YYYY-MMMM-DD"), datetime(2013, 1, 1) + ) + + def test_localized_month_name(self): + parser_ = parser.DateTimeParser("fr_fr") + + self.assertEqual( + parser_.parse("2013-Janvier-01", "YYYY-MMMM-DD"), datetime(2013, 1, 1) + ) + + def test_localized_month_abbreviation(self): + parser_ = parser.DateTimeParser("it_it") + + self.assertEqual( + parser_.parse("2013-Gen-01", "YYYY-MMM-DD"), datetime(2013, 1, 1) + ) + + +class DateTimeParserMeridiansTests(Chai): + def setUp(self): + super(DateTimeParserMeridiansTests, self).setUp() + + self.parser = parser.DateTimeParser("en_us") + + def test_meridians_lowercase(self): + self.assertEqual( + self.parser.parse("2013-01-01 5am", "YYYY-MM-DD ha"), + datetime(2013, 1, 1, 5), + ) + + self.assertEqual( + self.parser.parse("2013-01-01 5pm", "YYYY-MM-DD ha"), + datetime(2013, 1, 1, 17), + ) + + def test_meridians_capitalized(self): + self.assertEqual( + self.parser.parse("2013-01-01 5AM", "YYYY-MM-DD hA"), + datetime(2013, 1, 1, 5), + ) + + self.assertEqual( + self.parser.parse("2013-01-01 5PM", "YYYY-MM-DD hA"), + datetime(2013, 1, 1, 17), + ) + + def test_localized_meridians_lowercase(self): + parser_ = parser.DateTimeParser("hu_hu") + self.assertEqual( + parser_.parse("2013-01-01 5 de", "YYYY-MM-DD h a"), datetime(2013, 1, 1, 5) + ) + + self.assertEqual( + parser_.parse("2013-01-01 5 du", "YYYY-MM-DD h a"), datetime(2013, 1, 1, 17) + ) + + def test_localized_meridians_capitalized(self): + parser_ = parser.DateTimeParser("hu_hu") + self.assertEqual( + parser_.parse("2013-01-01 5 DE", "YYYY-MM-DD h A"), datetime(2013, 1, 1, 5) + ) + + self.assertEqual( + parser_.parse("2013-01-01 5 DU", "YYYY-MM-DD h A"), datetime(2013, 1, 1, 17) + ) + + # regression test for issue #607 + def test_es_meridians(self): + parser_ = parser.DateTimeParser("es") + + self.assertEqual( + parser_.parse("Junio 30, 2019 - 08:00 pm", "MMMM DD, YYYY - hh:mm a"), + datetime(2019, 6, 30, 20, 0), + ) + + with self.assertRaises(ParserError): + parser_.parse( + "Junio 30, 2019 - 08:00 pasdfasdfm", "MMMM DD, YYYY - hh:mm a" + ) + + def test_fr_meridians(self): + parser_ = parser.DateTimeParser("fr") + + # the French locale always uses a 24 hour clock, so it does not support meridians + with self.assertRaises(ParserError): + parser_.parse("Janvier 30, 2019 - 08:00 pm", "MMMM DD, YYYY - hh:mm a") + + +class DateTimeParserMonthOrdinalDayTests(Chai): + def setUp(self): + super(DateTimeParserMonthOrdinalDayTests, self).setUp() + + self.parser = parser.DateTimeParser("en_us") + + def test_english(self): + parser_ = parser.DateTimeParser("en_us") + + self.assertEqual( + parser_.parse("January 1st, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 1) + ) + self.assertEqual( + parser_.parse("January 2nd, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 2) + ) + self.assertEqual( + parser_.parse("January 3rd, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 3) + ) + self.assertEqual( + parser_.parse("January 4th, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 4) + ) + self.assertEqual( + parser_.parse("January 11th, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 11) + ) + self.assertEqual( + parser_.parse("January 12th, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 12) + ) + self.assertEqual( + parser_.parse("January 13th, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 13) + ) + self.assertEqual( + parser_.parse("January 21st, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 21) + ) + self.assertEqual( + parser_.parse("January 31st, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 31) + ) + + with self.assertRaises(ParserError): + parser_.parse("January 1th, 2013", "MMMM Do, YYYY") + + with self.assertRaises(ParserError): + parser_.parse("January 11st, 2013", "MMMM Do, YYYY") + + def test_italian(self): + parser_ = parser.DateTimeParser("it_it") + + self.assertEqual( + parser_.parse("Gennaio 1º, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 1) + ) + + def test_spanish(self): + parser_ = parser.DateTimeParser("es_es") + + self.assertEqual( + parser_.parse("Enero 1º, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 1) + ) + + def test_french(self): + parser_ = parser.DateTimeParser("fr_fr") + + self.assertEqual( + parser_.parse("Janvier 1er, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 1) + ) + + self.assertEqual( + parser_.parse("Janvier 2e, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 2) + ) + + self.assertEqual( + parser_.parse("Janvier 11e, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 11) + ) + + +class DateTimeParserSearchDateTests(Chai): + def setUp(self): + super(DateTimeParserSearchDateTests, self).setUp() + self.parser = parser.DateTimeParser() + + def test_parse_search(self): + + self.assertEqual( + self.parser.parse("Today is 25 of September of 2003", "DD of MMMM of YYYY"), + datetime(2003, 9, 25), + ) + + def test_parse_search_with_numbers(self): + + self.assertEqual( + self.parser.parse( + "2000 people met the 2012-01-01 12:05:10", "YYYY-MM-DD HH:mm:ss" + ), + datetime(2012, 1, 1, 12, 5, 10), + ) + + self.assertEqual( + self.parser.parse( + "Call 01-02-03 on 79-01-01 12:05:10", "YY-MM-DD HH:mm:ss" + ), + datetime(1979, 1, 1, 12, 5, 10), + ) + + def test_parse_search_with_names(self): + + self.assertEqual( + self.parser.parse("June was born in May 1980", "MMMM YYYY"), + datetime(1980, 5, 1), + ) + + def test_parse_search_locale_with_names(self): + p = parser.DateTimeParser("sv_se") + + self.assertEqual( + p.parse("Jan föddes den 31 Dec 1980", "DD MMM YYYY"), datetime(1980, 12, 31) + ) + + self.assertEqual( + p.parse("Jag föddes den 25 Augusti 1975", "DD MMMM YYYY"), + datetime(1975, 8, 25), + ) + + def test_parse_search_fails(self): + + with self.assertRaises(parser.ParserError): + self.parser.parse("Jag föddes den 25 Augusti 1975", "DD MMMM YYYY") + + def test_escape(self): + + format = "MMMM D, YYYY [at] h:mma" + self.assertEqual( + self.parser.parse("Thursday, December 10, 2015 at 5:09pm", format), + datetime(2015, 12, 10, 17, 9), + ) + + format = "[MMMM] M D, YYYY [at] h:mma" + self.assertEqual( + self.parser.parse("MMMM 12 10, 2015 at 5:09pm", format), + datetime(2015, 12, 10, 17, 9), + ) + + format = "[It happened on] MMMM Do [in the year] YYYY [a long time ago]" + self.assertEqual( + self.parser.parse( + "It happened on November 25th in the year 1990 a long time ago", format + ), + datetime(1990, 11, 25), + ) + + format = "[It happened on] MMMM Do [in the][ year] YYYY [a long time ago]" + self.assertEqual( + self.parser.parse( + "It happened on November 25th in the year 1990 a long time ago", format + ), + datetime(1990, 11, 25), + ) + + format = "[I'm][ entirely][ escaped,][ weee!]" + self.assertEqual( + self.parser.parse("I'm entirely escaped, weee!", format), datetime(1, 1, 1) + ) + + # Special RegEx characters + format = "MMM DD, YYYY |^${}().*+?<>-& h:mm A" + self.assertEqual( + self.parser.parse("Dec 31, 2017 |^${}().*+?<>-& 2:00 AM", format), + datetime(2017, 12, 31, 2, 0), + ) diff --git a/tests/util_tests.py b/tests/util_tests.py index 804ae62a2..b8a2c1360 100644 --- a/tests/util_tests.py +++ b/tests/util_tests.py @@ -2,39 +2,38 @@ import time from datetime import datetime -from chai import Chai - from arrow import util +import pytest -class UtilTests(Chai): +class TestUtil: def test_total_seconds(self): td = datetime(2019, 1, 1) - datetime(2018, 1, 1) - self.assertEqual(util.total_seconds(td), td.total_seconds()) + assert util.total_seconds(td) == td.total_seconds() def test_is_timestamp(self): timestamp_float = time.time() timestamp_int = int(timestamp_float) - self.assertTrue(util.is_timestamp(timestamp_int)) - self.assertTrue(util.is_timestamp(timestamp_float)) - self.assertTrue(util.is_timestamp(str(timestamp_int))) - self.assertTrue(util.is_timestamp(str(timestamp_float))) + assert util.is_timestamp(timestamp_int) + assert util.is_timestamp(timestamp_float) + assert util.is_timestamp(str(timestamp_int)) + assert util.is_timestamp(str(timestamp_float)) - self.assertFalse(util.is_timestamp(True)) - self.assertFalse(util.is_timestamp(False)) + assert not util.is_timestamp(True) + assert not util.is_timestamp(False) class InvalidTimestamp: pass - self.assertFalse(util.is_timestamp(InvalidTimestamp())) + assert not util.is_timestamp(InvalidTimestamp()) full_datetime = "2019-06-23T13:12:42" - self.assertFalse(util.is_timestamp(full_datetime)) + assert not util.is_timestamp(full_datetime) def test_iso_gregorian(self): - with self.assertRaises(ValueError): + with pytest.raises(ValueError): util.iso_to_gregorian(2013, 0, 5) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): util.iso_to_gregorian(2013, 8, 0) diff --git a/tests/util_tests.py.bak b/tests/util_tests.py.bak new file mode 100644 index 000000000..804ae62a2 --- /dev/null +++ b/tests/util_tests.py.bak @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +import time +from datetime import datetime + +from chai import Chai + +from arrow import util + + +class UtilTests(Chai): + def test_total_seconds(self): + td = datetime(2019, 1, 1) - datetime(2018, 1, 1) + self.assertEqual(util.total_seconds(td), td.total_seconds()) + + def test_is_timestamp(self): + timestamp_float = time.time() + timestamp_int = int(timestamp_float) + + self.assertTrue(util.is_timestamp(timestamp_int)) + self.assertTrue(util.is_timestamp(timestamp_float)) + self.assertTrue(util.is_timestamp(str(timestamp_int))) + self.assertTrue(util.is_timestamp(str(timestamp_float))) + + self.assertFalse(util.is_timestamp(True)) + self.assertFalse(util.is_timestamp(False)) + + class InvalidTimestamp: + pass + + self.assertFalse(util.is_timestamp(InvalidTimestamp())) + + full_datetime = "2019-06-23T13:12:42" + self.assertFalse(util.is_timestamp(full_datetime)) + + def test_iso_gregorian(self): + with self.assertRaises(ValueError): + util.iso_to_gregorian(2013, 0, 5) + + with self.assertRaises(ValueError): + util.iso_to_gregorian(2013, 8, 0) From 7b4a7b81d78f78c22cc0f3ba39bbef03472e23a7 Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Sat, 4 Jan 2020 17:00:19 -0500 Subject: [PATCH 07/13] Finished full revamp of test suite to use pytest --- Makefile | 4 +- requirements.txt | 7 +- setup.cfg | 30 +- tests/api_tests.py.bak | 33 - tests/arrow_tests.py.bak | 2081 ----------------- tests/factory_tests.py.bak | 383 --- tests/formatter_tests.py.bak | 199 -- tests/locales_tests.py.bak | 954 -------- tests/parser_tests.py | 1629 ------------- tests/parser_tests.py.bak | 1629 ------------- tests/{api_tests.py => test_api.py} | 0 tests/{arrow_tests.py => test_arrow.py} | 29 +- tests/{factory_tests.py => test_factory.py} | 47 +- .../{formatter_tests.py => test_formatter.py} | 0 tests/{locales_tests.py => test_locales.py} | 20 +- tests/test_parser.py | 1462 ++++++++++++ tests/{util_tests.py => test_util.py} | 3 +- tests/util_tests.py.bak | 40 - tests/utils.py | 7 + tox.ini | 4 +- 20 files changed, 1543 insertions(+), 7018 deletions(-) delete mode 100644 tests/api_tests.py.bak delete mode 100644 tests/arrow_tests.py.bak delete mode 100644 tests/factory_tests.py.bak delete mode 100644 tests/formatter_tests.py.bak delete mode 100644 tests/locales_tests.py.bak delete mode 100644 tests/parser_tests.py delete mode 100644 tests/parser_tests.py.bak rename tests/{api_tests.py => test_api.py} (100%) rename tests/{arrow_tests.py => test_arrow.py} (98%) rename tests/{factory_tests.py => test_factory.py} (89%) rename tests/{formatter_tests.py => test_formatter.py} (100%) rename tests/{locales_tests.py => test_locales.py} (98%) create mode 100644 tests/test_parser.py rename tests/{util_tests.py => test_util.py} (99%) delete mode 100644 tests/util_tests.py.bak diff --git a/Makefile b/Makefile index e7d324d1a..a05957d4a 100644 --- a/Makefile +++ b/Makefile @@ -14,8 +14,8 @@ build27 build35 build36 build37 build38: venv/bin/pre-commit install test: - rm -f .coverage - . venv/bin/activate && nosetests + rm -f .coverage coverage.xml + . venv/bin/activate && pytest lint: venv/bin/pre-commit run --all-files --show-diff-on-failure diff --git a/requirements.txt b/requirements.txt index 8281e8e91..11c0c72cf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,9 @@ backports.functools_lru_cache==1.6.1; python_version == "2.7" -chai==1.1.2 dateparser==0.7.* -mock==3.0.* -nose==1.3.7 -nose-cov==1.6 pre-commit==1.20.* +pytest +pytest-cov +pytest-mock python-dateutil==2.8.* pytz==2019.* simplejson==3.16.* diff --git a/setup.cfg b/setup.cfg index 08cae3ddf..1f7575065 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,31 +1,15 @@ -[nosetests] -where = tests -verbosity = 2 -all-modules = true -with-coverage = true -cover-min-percentage = 100 -cover-package = arrow -cover-erase = true - -[coverage:run] -branch = true -source = - arrow - tests - -[coverage:report] -show_missing = true -fail_under = 100 - -[flake8] -per-file-ignores = arrow/__init__.py:F401 -ignore = E203,E501,W503 +[tool:pytest] +# addopts = -v --nf --cov-branch --cov=arrow tests --cov-fail-under=100 --cov-report=term-missing --cov-report=xml [tool:isort] line_length = 88 multi_line_output = 3 include_trailing_comma = true -known_third_party = chai,dateparser,dateutil,mock,pytz,setuptools,simplejson +known_third_party = dateparser,dateutil,pytest,pytz,setuptools,simplejson + +[flake8] +per-file-ignores = arrow/__init__.py:F401 +ignore = E203,E501,W503 [bdist_wheel] universal = 1 diff --git a/tests/api_tests.py.bak b/tests/api_tests.py.bak deleted file mode 100644 index 1cf171653..000000000 --- a/tests/api_tests.py.bak +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -from chai import Chai - -from arrow import api, arrow, factory - - -class ModuleTests(Chai): - def test_get(self): - - self.expect(api._factory.get).args(1, b=2).returns("result") - - self.assertEqual(api.get(1, b=2), "result") - - def test_utcnow(self): - - self.expect(api._factory.utcnow).returns("utcnow") - - self.assertEqual(api.utcnow(), "utcnow") - - def test_now(self): - - self.expect(api._factory.now).args("tz").returns("now") - - self.assertEqual(api.now("tz"), "now") - - def test_factory(self): - class MockCustomArrowClass(arrow.Arrow): - pass - - result = api.factory(MockCustomArrowClass) - - self.assertIsInstance(result, factory.ArrowFactory) - self.assertIsInstance(result.utcnow(), MockCustomArrowClass) diff --git a/tests/arrow_tests.py.bak b/tests/arrow_tests.py.bak deleted file mode 100644 index 9d6827660..000000000 --- a/tests/arrow_tests.py.bak +++ /dev/null @@ -1,2081 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import absolute_import, unicode_literals - -import calendar -import pickle -import sys -import time -from datetime import date, datetime, timedelta - -import pytz -import simplejson as json -from chai import Chai -from dateutil import tz -from dateutil.relativedelta import FR, MO, SA, SU, TH, TU, WE -from mock import patch - -from arrow import arrow, util - - -def assertDtEqual(dt1, dt2, within=10): - assertEqual(dt1.tzinfo, dt2.tzinfo) # noqa: F821 - assertTrue(abs(util.total_seconds(dt1 - dt2)) < within) # noqa: F821 - - -class ArrowInitTests(Chai): - def test_init_bad_input(self): - - with self.assertRaises(TypeError): - arrow.Arrow(2013) - - with self.assertRaises(TypeError): - arrow.Arrow(2013, 2) - - with self.assertRaises(ValueError): - arrow.Arrow(2013, 2, 2, 12, 30, 45, 9999999) - - def test_init(self): - - result = arrow.Arrow(2013, 2, 2) - self.expected = datetime(2013, 2, 2, tzinfo=tz.tzutc()) - self.assertEqual(result._datetime, self.expected) - - result = arrow.Arrow(2013, 2, 2, 12) - self.expected = datetime(2013, 2, 2, 12, tzinfo=tz.tzutc()) - self.assertEqual(result._datetime, self.expected) - - result = arrow.Arrow(2013, 2, 2, 12, 30) - self.expected = datetime(2013, 2, 2, 12, 30, tzinfo=tz.tzutc()) - self.assertEqual(result._datetime, self.expected) - - result = arrow.Arrow(2013, 2, 2, 12, 30, 45) - self.expected = datetime(2013, 2, 2, 12, 30, 45, tzinfo=tz.tzutc()) - self.assertEqual(result._datetime, self.expected) - - result = arrow.Arrow(2013, 2, 2, 12, 30, 45, 999999) - self.expected = datetime(2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.tzutc()) - self.assertEqual(result._datetime, self.expected) - - result = arrow.Arrow( - 2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.gettz("Europe/Paris") - ) - self.expected = datetime( - 2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.gettz("Europe/Paris") - ) - self.assertEqual(result._datetime, self.expected) - - # regression tests for issue #626 - def test_init_pytz_timezone(self): - - result = arrow.Arrow( - 2013, 2, 2, 12, 30, 45, 999999, tzinfo=pytz.timezone("Europe/Paris") - ) - self.expected = datetime( - 2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.gettz("Europe/Paris") - ) - self.assertEqual(result._datetime, self.expected) - assertDtEqual(result._datetime, self.expected, 1) - - -class ArrowFactoryTests(Chai): - def test_now(self): - - result = arrow.Arrow.now() - - assertDtEqual(result._datetime, datetime.now().replace(tzinfo=tz.tzlocal())) - - def test_utcnow(self): - - result = arrow.Arrow.utcnow() - - assertDtEqual(result._datetime, datetime.utcnow().replace(tzinfo=tz.tzutc())) - - def test_fromtimestamp(self): - - timestamp = time.time() - - result = arrow.Arrow.fromtimestamp(timestamp) - assertDtEqual(result._datetime, datetime.now().replace(tzinfo=tz.tzlocal())) - - result = arrow.Arrow.fromtimestamp(timestamp, tzinfo=tz.gettz("Europe/Paris")) - assertDtEqual( - result._datetime, - datetime.fromtimestamp(timestamp, tz.gettz("Europe/Paris")), - ) - - result = arrow.Arrow.fromtimestamp(timestamp, tzinfo="Europe/Paris") - assertDtEqual( - result._datetime, - datetime.fromtimestamp(timestamp, tz.gettz("Europe/Paris")), - ) - - with self.assertRaises(ValueError): - arrow.Arrow.fromtimestamp("invalid timestamp") - - def test_utcfromtimestamp(self): - - timestamp = time.time() - - result = arrow.Arrow.utcfromtimestamp(timestamp) - assertDtEqual(result._datetime, datetime.utcnow().replace(tzinfo=tz.tzutc())) - - with self.assertRaises(ValueError): - arrow.Arrow.utcfromtimestamp("invalid timestamp") - - def test_fromdatetime(self): - - dt = datetime(2013, 2, 3, 12, 30, 45, 1) - - result = arrow.Arrow.fromdatetime(dt) - - self.assertEqual(result._datetime, dt.replace(tzinfo=tz.tzutc())) - - def test_fromdatetime_dt_tzinfo(self): - - dt = datetime(2013, 2, 3, 12, 30, 45, 1, tzinfo=tz.gettz("US/Pacific")) - - result = arrow.Arrow.fromdatetime(dt) - - self.assertEqual(result._datetime, dt.replace(tzinfo=tz.gettz("US/Pacific"))) - - def test_fromdatetime_tzinfo_arg(self): - - dt = datetime(2013, 2, 3, 12, 30, 45, 1) - - result = arrow.Arrow.fromdatetime(dt, tz.gettz("US/Pacific")) - - self.assertEqual(result._datetime, dt.replace(tzinfo=tz.gettz("US/Pacific"))) - - def test_fromdate(self): - - dt = date(2013, 2, 3) - - result = arrow.Arrow.fromdate(dt, tz.gettz("US/Pacific")) - - self.assertEqual( - result._datetime, datetime(2013, 2, 3, tzinfo=tz.gettz("US/Pacific")) - ) - - def test_strptime(self): - - formatted = datetime(2013, 2, 3, 12, 30, 45).strftime("%Y-%m-%d %H:%M:%S") - - result = arrow.Arrow.strptime(formatted, "%Y-%m-%d %H:%M:%S") - self.assertEqual( - result._datetime, datetime(2013, 2, 3, 12, 30, 45, tzinfo=tz.tzutc()) - ) - - result = arrow.Arrow.strptime( - formatted, "%Y-%m-%d %H:%M:%S", tzinfo=tz.gettz("Europe/Paris") - ) - self.assertEqual( - result._datetime, - datetime(2013, 2, 3, 12, 30, 45, tzinfo=tz.gettz("Europe/Paris")), - ) - - -class ArrowRepresentationTests(Chai): - def setUp(self): - super(ArrowRepresentationTests, self).setUp() - - self.arrow = arrow.Arrow(2013, 2, 3, 12, 30, 45, 1) - - def test_repr(self): - - result = self.arrow.__repr__() - - self.assertEqual( - result, "".format(self.arrow._datetime.isoformat()) - ) - - def test_str(self): - - result = self.arrow.__str__() - - self.assertEqual(result, self.arrow._datetime.isoformat()) - - def test_hash(self): - - result = self.arrow.__hash__() - - self.assertEqual(result, self.arrow._datetime.__hash__()) - - def test_format(self): - - result = "{:YYYY-MM-DD}".format(self.arrow) - - self.assertEqual(result, "2013-02-03") - - def test_bare_format(self): - - result = self.arrow.format() - - self.assertEqual(result, "2013-02-03 12:30:45+00:00") - - def test_format_no_format_string(self): - - result = "{}".format(self.arrow) - - self.assertEqual(result, str(self.arrow)) - - def test_clone(self): - - result = self.arrow.clone() - - self.assertTrue(result is not self.arrow) - self.assertEqual(result._datetime, self.arrow._datetime) - - -class ArrowAttributeTests(Chai): - def setUp(self): - super(ArrowAttributeTests, self).setUp() - - self.arrow = arrow.Arrow(2013, 1, 1) - - def test_getattr_base(self): - - with self.assertRaises(AttributeError): - self.arrow.prop - - def test_getattr_week(self): - - self.assertEqual(self.arrow.week, 1) - - def test_getattr_quarter(self): - # start dates - q1 = arrow.Arrow(2013, 1, 1) - q2 = arrow.Arrow(2013, 4, 1) - q3 = arrow.Arrow(2013, 8, 1) - q4 = arrow.Arrow(2013, 10, 1) - self.assertEqual(q1.quarter, 1) - self.assertEqual(q2.quarter, 2) - self.assertEqual(q3.quarter, 3) - self.assertEqual(q4.quarter, 4) - - # end dates - q1 = arrow.Arrow(2013, 3, 31) - q2 = arrow.Arrow(2013, 6, 30) - q3 = arrow.Arrow(2013, 9, 30) - q4 = arrow.Arrow(2013, 12, 31) - self.assertEqual(q1.quarter, 1) - self.assertEqual(q2.quarter, 2) - self.assertEqual(q3.quarter, 3) - self.assertEqual(q4.quarter, 4) - - def test_getattr_dt_value(self): - - self.assertEqual(self.arrow.year, 2013) - - def test_tzinfo(self): - - self.arrow.tzinfo = tz.gettz("PST") - self.assertEqual(self.arrow.tzinfo, tz.gettz("PST")) - - def test_naive(self): - - self.assertEqual(self.arrow.naive, self.arrow._datetime.replace(tzinfo=None)) - - def test_timestamp(self): - - self.assertEqual( - self.arrow.timestamp, calendar.timegm(self.arrow._datetime.utctimetuple()) - ) - - def test_float_timestamp(self): - - result = self.arrow.float_timestamp - self.arrow.timestamp - - self.assertEqual(result, self.arrow.microsecond) - - -class ArrowComparisonTests(Chai): - def setUp(self): - super(ArrowComparisonTests, self).setUp() - - self.arrow = arrow.Arrow.utcnow() - - def test_eq(self): - - self.assertTrue(self.arrow == self.arrow) - self.assertTrue(self.arrow == self.arrow.datetime) - self.assertFalse(self.arrow == "abc") - - def test_ne(self): - - self.assertFalse(self.arrow != self.arrow) - self.assertFalse(self.arrow != self.arrow.datetime) - self.assertTrue(self.arrow != "abc") - - def test_gt(self): - - arrow_cmp = self.arrow.shift(minutes=1) - - self.assertFalse(self.arrow > self.arrow) - self.assertFalse(self.arrow > self.arrow.datetime) - - with self.assertRaises(TypeError): - self.arrow > "abc" - - self.assertTrue(self.arrow < arrow_cmp) - self.assertTrue(self.arrow < arrow_cmp.datetime) - - def test_ge(self): - - with self.assertRaises(TypeError): - self.arrow >= "abc" - - self.assertTrue(self.arrow >= self.arrow) - self.assertTrue(self.arrow >= self.arrow.datetime) - - def test_lt(self): - - arrow_cmp = self.arrow.shift(minutes=1) - - self.assertFalse(self.arrow < self.arrow) - self.assertFalse(self.arrow < self.arrow.datetime) - - with self.assertRaises(TypeError): - self.arrow < "abc" - - self.assertTrue(self.arrow < arrow_cmp) - self.assertTrue(self.arrow < arrow_cmp.datetime) - - def test_le(self): - - with self.assertRaises(TypeError): - self.arrow <= "abc" - - self.assertTrue(self.arrow <= self.arrow) - self.assertTrue(self.arrow <= self.arrow.datetime) - - -class ArrowMathTests(Chai): - def setUp(self): - super(ArrowMathTests, self).setUp() - - self.arrow = arrow.Arrow(2013, 1, 1) - - def test_add_timedelta(self): - - result = self.arrow.__add__(timedelta(days=1)) - - self.assertEqual(result._datetime, datetime(2013, 1, 2, tzinfo=tz.tzutc())) - - def test_add_other(self): - - with self.assertRaises(TypeError): - self.arrow + 1 - - def test_radd(self): - - result = self.arrow.__radd__(timedelta(days=1)) - - self.assertEqual(result._datetime, datetime(2013, 1, 2, tzinfo=tz.tzutc())) - - def test_sub_timedelta(self): - - result = self.arrow.__sub__(timedelta(days=1)) - - self.assertEqual(result._datetime, datetime(2012, 12, 31, tzinfo=tz.tzutc())) - - def test_sub_datetime(self): - - result = self.arrow.__sub__(datetime(2012, 12, 21, tzinfo=tz.tzutc())) - - self.assertEqual(result, timedelta(days=11)) - - def test_sub_arrow(self): - - result = self.arrow.__sub__(arrow.Arrow(2012, 12, 21, tzinfo=tz.tzutc())) - - self.assertEqual(result, timedelta(days=11)) - - def test_sub_other(self): - - with self.assertRaises(TypeError): - self.arrow - object() - - def test_rsub_datetime(self): - - result = self.arrow.__rsub__(datetime(2012, 12, 21, tzinfo=tz.tzutc())) - - self.assertEqual(result, timedelta(days=-11)) - - def test_rsub_other(self): - - with self.assertRaises(TypeError): - timedelta(days=1) - self.arrow - - -class ArrowDatetimeInterfaceTests(Chai): - def setUp(self): - super(ArrowDatetimeInterfaceTests, self).setUp() - - self.arrow = arrow.Arrow.utcnow() - - def test_date(self): - - result = self.arrow.date() - - self.assertEqual(result, self.arrow._datetime.date()) - - def test_time(self): - - result = self.arrow.time() - - self.assertEqual(result, self.arrow._datetime.time()) - - def test_timetz(self): - - result = self.arrow.timetz() - - self.assertEqual(result, self.arrow._datetime.timetz()) - - def test_astimezone(self): - - other_tz = tz.gettz("US/Pacific") - - result = self.arrow.astimezone(other_tz) - - self.assertEqual(result, self.arrow._datetime.astimezone(other_tz)) - - def test_utcoffset(self): - - result = self.arrow.utcoffset() - - self.assertEqual(result, self.arrow._datetime.utcoffset()) - - def test_dst(self): - - result = self.arrow.dst() - - self.assertEqual(result, self.arrow._datetime.dst()) - - def test_timetuple(self): - - result = self.arrow.timetuple() - - self.assertEqual(result, self.arrow._datetime.timetuple()) - - def test_utctimetuple(self): - - result = self.arrow.utctimetuple() - - self.assertEqual(result, self.arrow._datetime.utctimetuple()) - - def test_toordinal(self): - - result = self.arrow.toordinal() - - self.assertEqual(result, self.arrow._datetime.toordinal()) - - def test_weekday(self): - - result = self.arrow.weekday() - - self.assertEqual(result, self.arrow._datetime.weekday()) - - def test_isoweekday(self): - - result = self.arrow.isoweekday() - - self.assertEqual(result, self.arrow._datetime.isoweekday()) - - def test_isocalendar(self): - - result = self.arrow.isocalendar() - - self.assertEqual(result, self.arrow._datetime.isocalendar()) - - def test_isoformat(self): - - result = self.arrow.isoformat() - - self.assertEqual(result, self.arrow._datetime.isoformat()) - - def test_simplejson(self): - - result = json.dumps({"v": self.arrow.for_json()}, for_json=True) - - self.assertEqual(json.loads(result)["v"], self.arrow._datetime.isoformat()) - - def test_ctime(self): - - result = self.arrow.ctime() - - self.assertEqual(result, self.arrow._datetime.ctime()) - - def test_strftime(self): - - result = self.arrow.strftime("%Y") - - self.assertEqual(result, self.arrow._datetime.strftime("%Y")) - - -class ArrowFalsePositiveDstTests(Chai): - """These tests relate to issues #376 and #551. - The key points in both issues are that arrow will assign a UTC timezone if none is provided and - .to() will change other attributes to be correct whereas .replace() only changes the specified attribute. - - Issue 376 - >>> arrow.get('2016-11-06').to('America/New_York').ceil('day') - < Arrow [2016-11-05T23:59:59.999999-04:00] > - - Issue 551 - >>> just_before = arrow.get('2018-11-04T01:59:59.999999') - >>> just_before - 2018-11-04T01:59:59.999999+00:00 - >>> just_after = just_before.shift(microseconds=1) - >>> just_after - 2018-11-04T02:00:00+00:00 - >>> just_before_eastern = just_before.replace(tzinfo='US/Eastern') - >>> just_before_eastern - 2018-11-04T01:59:59.999999-04:00 - >>> just_after_eastern = just_after.replace(tzinfo='US/Eastern') - >>> just_after_eastern - 2018-11-04T02:00:00-05:00 - """ - - def setUp(self): - - super(ArrowFalsePositiveDstTests, self).setUp() - self.before_1 = arrow.Arrow( - 2016, 11, 6, 3, 59, tzinfo=tz.gettz("America/New_York") - ) - self.before_2 = arrow.Arrow(2016, 11, 6, tzinfo=tz.gettz("America/New_York")) - self.after_1 = arrow.Arrow(2016, 11, 6, 4, tzinfo=tz.gettz("America/New_York")) - self.after_2 = arrow.Arrow( - 2016, 11, 6, 23, 59, tzinfo=tz.gettz("America/New_York") - ) - self.before_3 = arrow.Arrow( - 2018, 11, 4, 3, 59, tzinfo=tz.gettz("America/New_York") - ) - self.before_4 = arrow.Arrow(2018, 11, 4, tzinfo=tz.gettz("America/New_York")) - self.after_3 = arrow.Arrow(2018, 11, 4, 4, tzinfo=tz.gettz("America/New_York")) - self.after_4 = arrow.Arrow( - 2018, 11, 4, 23, 59, tzinfo=tz.gettz("America/New_York") - ) - - def test_dst(self): - - self.assertEqual(self.before_1.day, self.before_2.day) - self.assertEqual(self.after_1.day, self.after_2.day) - self.assertEqual(self.before_3.day, self.before_4.day) - self.assertEqual(self.after_3.day, self.after_4.day) - - -class ArrowConversionTests(Chai): - def test_to(self): - - dt_from = datetime.now() - arrow_from = arrow.Arrow.fromdatetime(dt_from, tz.gettz("US/Pacific")) - - self.expected = dt_from.replace(tzinfo=tz.gettz("US/Pacific")).astimezone( - tz.tzutc() - ) - - self.assertEqual(arrow_from.to("UTC").datetime, self.expected) - self.assertEqual(arrow_from.to(tz.tzutc()).datetime, self.expected) - - -class ArrowPicklingTests(Chai): - def test_pickle_and_unpickle(self): - - dt = arrow.Arrow.utcnow() - - pickled = pickle.dumps(dt) - - unpickled = pickle.loads(pickled) - - self.assertEqual(unpickled, dt) - - -class ArrowReplaceTests(Chai): - def test_not_attr(self): - - with self.assertRaises(AttributeError): - arrow.Arrow.utcnow().replace(abc=1) - - def test_replace(self): - - arw = arrow.Arrow(2013, 5, 5, 12, 30, 45) - - self.assertEqual(arw.replace(year=2012), arrow.Arrow(2012, 5, 5, 12, 30, 45)) - self.assertEqual(arw.replace(month=1), arrow.Arrow(2013, 1, 5, 12, 30, 45)) - self.assertEqual(arw.replace(day=1), arrow.Arrow(2013, 5, 1, 12, 30, 45)) - self.assertEqual(arw.replace(hour=1), arrow.Arrow(2013, 5, 5, 1, 30, 45)) - self.assertEqual(arw.replace(minute=1), arrow.Arrow(2013, 5, 5, 12, 1, 45)) - self.assertEqual(arw.replace(second=1), arrow.Arrow(2013, 5, 5, 12, 30, 1)) - - def test_replace_tzinfo(self): - - arw = arrow.Arrow.utcnow().to("US/Eastern") - - result = arw.replace(tzinfo=tz.gettz("US/Pacific")) - - self.assertEqual(result, arw.datetime.replace(tzinfo=tz.gettz("US/Pacific"))) - - def test_replace_week(self): - - with self.assertRaises(AttributeError): - arrow.Arrow.utcnow().replace(week=1) - - def test_replace_quarter(self): - - with self.assertRaises(AttributeError): - arrow.Arrow.utcnow().replace(quarter=1) - - def test_replace_other_kwargs(self): - - with self.assertRaises(AttributeError): - arrow.utcnow().replace(abc="def") - - -class ArrowShiftTests(Chai): - def test_not_attr(self): - - now = arrow.Arrow.utcnow() - - with self.assertRaises(AttributeError): - now.shift(abc=1) - - with self.assertRaises(AttributeError): - now.shift(week=1) - - def test_shift(self): - - arw = arrow.Arrow(2013, 5, 5, 12, 30, 45) - - self.assertEqual(arw.shift(years=1), arrow.Arrow(2014, 5, 5, 12, 30, 45)) - self.assertEqual(arw.shift(quarters=1), arrow.Arrow(2013, 8, 5, 12, 30, 45)) - self.assertEqual( - arw.shift(quarters=1, months=1), arrow.Arrow(2013, 9, 5, 12, 30, 45) - ) - self.assertEqual(arw.shift(months=1), arrow.Arrow(2013, 6, 5, 12, 30, 45)) - self.assertEqual(arw.shift(weeks=1), arrow.Arrow(2013, 5, 12, 12, 30, 45)) - self.assertEqual(arw.shift(days=1), arrow.Arrow(2013, 5, 6, 12, 30, 45)) - self.assertEqual(arw.shift(hours=1), arrow.Arrow(2013, 5, 5, 13, 30, 45)) - self.assertEqual(arw.shift(minutes=1), arrow.Arrow(2013, 5, 5, 12, 31, 45)) - self.assertEqual(arw.shift(seconds=1), arrow.Arrow(2013, 5, 5, 12, 30, 46)) - self.assertEqual( - arw.shift(microseconds=1), arrow.Arrow(2013, 5, 5, 12, 30, 45, 1) - ) - - # Remember: Python's weekday 0 is Monday - self.assertEqual(arw.shift(weekday=0), arrow.Arrow(2013, 5, 6, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=1), arrow.Arrow(2013, 5, 7, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=2), arrow.Arrow(2013, 5, 8, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=3), arrow.Arrow(2013, 5, 9, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=4), arrow.Arrow(2013, 5, 10, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=5), arrow.Arrow(2013, 5, 11, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=6), arw) - - with self.assertRaises(IndexError): - arw.shift(weekday=7) - - # Use dateutil.relativedelta's convenient day instances - self.assertEqual(arw.shift(weekday=MO), arrow.Arrow(2013, 5, 6, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=MO(0)), arrow.Arrow(2013, 5, 6, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=MO(1)), arrow.Arrow(2013, 5, 6, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=MO(2)), arrow.Arrow(2013, 5, 13, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TU), arrow.Arrow(2013, 5, 7, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TU(0)), arrow.Arrow(2013, 5, 7, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TU(1)), arrow.Arrow(2013, 5, 7, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TU(2)), arrow.Arrow(2013, 5, 14, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=WE), arrow.Arrow(2013, 5, 8, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=WE(0)), arrow.Arrow(2013, 5, 8, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=WE(1)), arrow.Arrow(2013, 5, 8, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=WE(2)), arrow.Arrow(2013, 5, 15, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TH), arrow.Arrow(2013, 5, 9, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TH(0)), arrow.Arrow(2013, 5, 9, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TH(1)), arrow.Arrow(2013, 5, 9, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TH(2)), arrow.Arrow(2013, 5, 16, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=FR), arrow.Arrow(2013, 5, 10, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=FR(0)), arrow.Arrow(2013, 5, 10, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=FR(1)), arrow.Arrow(2013, 5, 10, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=FR(2)), arrow.Arrow(2013, 5, 17, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SA), arrow.Arrow(2013, 5, 11, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SA(0)), arrow.Arrow(2013, 5, 11, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SA(1)), arrow.Arrow(2013, 5, 11, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SA(2)), arrow.Arrow(2013, 5, 18, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SU), arw) - self.assertEqual(arw.shift(weekday=SU(0)), arw) - self.assertEqual(arw.shift(weekday=SU(1)), arw) - self.assertEqual(arw.shift(weekday=SU(2)), arrow.Arrow(2013, 5, 12, 12, 30, 45)) - - def test_shift_negative(self): - - arw = arrow.Arrow(2013, 5, 5, 12, 30, 45) - - self.assertEqual(arw.shift(years=-1), arrow.Arrow(2012, 5, 5, 12, 30, 45)) - self.assertEqual(arw.shift(quarters=-1), arrow.Arrow(2013, 2, 5, 12, 30, 45)) - self.assertEqual( - arw.shift(quarters=-1, months=-1), arrow.Arrow(2013, 1, 5, 12, 30, 45) - ) - self.assertEqual(arw.shift(months=-1), arrow.Arrow(2013, 4, 5, 12, 30, 45)) - self.assertEqual(arw.shift(weeks=-1), arrow.Arrow(2013, 4, 28, 12, 30, 45)) - self.assertEqual(arw.shift(days=-1), arrow.Arrow(2013, 5, 4, 12, 30, 45)) - self.assertEqual(arw.shift(hours=-1), arrow.Arrow(2013, 5, 5, 11, 30, 45)) - self.assertEqual(arw.shift(minutes=-1), arrow.Arrow(2013, 5, 5, 12, 29, 45)) - self.assertEqual(arw.shift(seconds=-1), arrow.Arrow(2013, 5, 5, 12, 30, 44)) - self.assertEqual( - arw.shift(microseconds=-1), arrow.Arrow(2013, 5, 5, 12, 30, 44, 999999) - ) - - # Not sure how practical these negative weekdays are - self.assertEqual(arw.shift(weekday=-1), arw.shift(weekday=SU)) - self.assertEqual(arw.shift(weekday=-2), arw.shift(weekday=SA)) - self.assertEqual(arw.shift(weekday=-3), arw.shift(weekday=FR)) - self.assertEqual(arw.shift(weekday=-4), arw.shift(weekday=TH)) - self.assertEqual(arw.shift(weekday=-5), arw.shift(weekday=WE)) - self.assertEqual(arw.shift(weekday=-6), arw.shift(weekday=TU)) - self.assertEqual(arw.shift(weekday=-7), arw.shift(weekday=MO)) - - with self.assertRaises(IndexError): - arw.shift(weekday=-8) - - self.assertEqual( - arw.shift(weekday=MO(-1)), arrow.Arrow(2013, 4, 29, 12, 30, 45) - ) - self.assertEqual( - arw.shift(weekday=TU(-1)), arrow.Arrow(2013, 4, 30, 12, 30, 45) - ) - self.assertEqual(arw.shift(weekday=WE(-1)), arrow.Arrow(2013, 5, 1, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=TH(-1)), arrow.Arrow(2013, 5, 2, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=FR(-1)), arrow.Arrow(2013, 5, 3, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SA(-1)), arrow.Arrow(2013, 5, 4, 12, 30, 45)) - self.assertEqual(arw.shift(weekday=SU(-1)), arw) - self.assertEqual( - arw.shift(weekday=SU(-2)), arrow.Arrow(2013, 4, 28, 12, 30, 45) - ) - - def test_shift_quarters_bug(self): - - arw = arrow.Arrow(2013, 5, 5, 12, 30, 45) - - # The value of the last-read argument was used instead of the ``quarters`` argument. - # Recall that the keyword argument dict, like all dicts, is unordered, so only certain - # combinations of arguments would exhibit this. - self.assertEqual( - arw.shift(quarters=0, years=1), arrow.Arrow(2014, 5, 5, 12, 30, 45) - ) - self.assertEqual( - arw.shift(quarters=0, months=1), arrow.Arrow(2013, 6, 5, 12, 30, 45) - ) - self.assertEqual( - arw.shift(quarters=0, weeks=1), arrow.Arrow(2013, 5, 12, 12, 30, 45) - ) - self.assertEqual( - arw.shift(quarters=0, days=1), arrow.Arrow(2013, 5, 6, 12, 30, 45) - ) - self.assertEqual( - arw.shift(quarters=0, hours=1), arrow.Arrow(2013, 5, 5, 13, 30, 45) - ) - self.assertEqual( - arw.shift(quarters=0, minutes=1), arrow.Arrow(2013, 5, 5, 12, 31, 45) - ) - self.assertEqual( - arw.shift(quarters=0, seconds=1), arrow.Arrow(2013, 5, 5, 12, 30, 46) - ) - self.assertEqual( - arw.shift(quarters=0, microseconds=1), - arrow.Arrow(2013, 5, 5, 12, 30, 45, 1), - ) - - -class ArrowRangeTests(Chai): - def test_year(self): - - result = list( - arrow.Arrow.range( - "year", datetime(2013, 1, 2, 3, 4, 5), datetime(2016, 4, 5, 6, 7, 8) - ) - ) - - self.assertEqual( - result, - [ - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2014, 1, 2, 3, 4, 5), - arrow.Arrow(2015, 1, 2, 3, 4, 5), - arrow.Arrow(2016, 1, 2, 3, 4, 5), - ], - ) - - def test_quarter(self): - - result = list( - arrow.Arrow.range( - "quarter", datetime(2013, 2, 3, 4, 5, 6), datetime(2013, 5, 6, 7, 8, 9) - ) - ) - - self.assertEqual( - result, [arrow.Arrow(2013, 2, 3, 4, 5, 6), arrow.Arrow(2013, 5, 3, 4, 5, 6)] - ) - - def test_month(self): - - result = list( - arrow.Arrow.range( - "month", datetime(2013, 2, 3, 4, 5, 6), datetime(2013, 5, 6, 7, 8, 9) - ) - ) - - self.assertEqual( - result, - [ - arrow.Arrow(2013, 2, 3, 4, 5, 6), - arrow.Arrow(2013, 3, 3, 4, 5, 6), - arrow.Arrow(2013, 4, 3, 4, 5, 6), - arrow.Arrow(2013, 5, 3, 4, 5, 6), - ], - ) - - def test_week(self): - - result = list( - arrow.Arrow.range( - "week", datetime(2013, 9, 1, 2, 3, 4), datetime(2013, 10, 1, 2, 3, 4) - ) - ) - - self.assertEqual( - result, - [ - arrow.Arrow(2013, 9, 1, 2, 3, 4), - arrow.Arrow(2013, 9, 8, 2, 3, 4), - arrow.Arrow(2013, 9, 15, 2, 3, 4), - arrow.Arrow(2013, 9, 22, 2, 3, 4), - arrow.Arrow(2013, 9, 29, 2, 3, 4), - ], - ) - - def test_day(self): - - result = list( - arrow.Arrow.range( - "day", datetime(2013, 1, 2, 3, 4, 5), datetime(2013, 1, 5, 6, 7, 8) - ) - ) - - self.assertEqual( - result, - [ - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2013, 1, 3, 3, 4, 5), - arrow.Arrow(2013, 1, 4, 3, 4, 5), - arrow.Arrow(2013, 1, 5, 3, 4, 5), - ], - ) - - def test_hour(self): - - result = list( - arrow.Arrow.range( - "hour", datetime(2013, 1, 2, 3, 4, 5), datetime(2013, 1, 2, 6, 7, 8) - ) - ) - - self.assertEqual( - result, - [ - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2013, 1, 2, 4, 4, 5), - arrow.Arrow(2013, 1, 2, 5, 4, 5), - arrow.Arrow(2013, 1, 2, 6, 4, 5), - ], - ) - - result = list( - arrow.Arrow.range( - "hour", datetime(2013, 1, 2, 3, 4, 5), datetime(2013, 1, 2, 3, 4, 5) - ) - ) - - self.assertEqual(result, [arrow.Arrow(2013, 1, 2, 3, 4, 5)]) - - def test_minute(self): - - result = list( - arrow.Arrow.range( - "minute", datetime(2013, 1, 2, 3, 4, 5), datetime(2013, 1, 2, 3, 7, 8) - ) - ) - - self.assertEqual( - result, - [ - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2013, 1, 2, 3, 5, 5), - arrow.Arrow(2013, 1, 2, 3, 6, 5), - arrow.Arrow(2013, 1, 2, 3, 7, 5), - ], - ) - - def test_second(self): - - result = list( - arrow.Arrow.range( - "second", datetime(2013, 1, 2, 3, 4, 5), datetime(2013, 1, 2, 3, 4, 8) - ) - ) - - self.assertEqual( - result, - [ - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2013, 1, 2, 3, 4, 6), - arrow.Arrow(2013, 1, 2, 3, 4, 7), - arrow.Arrow(2013, 1, 2, 3, 4, 8), - ], - ) - - def test_arrow(self): - - result = list( - arrow.Arrow.range( - "day", - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2013, 1, 5, 6, 7, 8), - ) - ) - - self.assertEqual( - result, - [ - arrow.Arrow(2013, 1, 2, 3, 4, 5), - arrow.Arrow(2013, 1, 3, 3, 4, 5), - arrow.Arrow(2013, 1, 4, 3, 4, 5), - arrow.Arrow(2013, 1, 5, 3, 4, 5), - ], - ) - - def test_naive_tz(self): - - result = arrow.Arrow.range( - "year", datetime(2013, 1, 2, 3), datetime(2016, 4, 5, 6), "US/Pacific" - ) - - [self.assertEqual(r.tzinfo, tz.gettz("US/Pacific")) for r in result] - - def test_aware_same_tz(self): - - result = arrow.Arrow.range( - "day", - arrow.Arrow(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")), - arrow.Arrow(2013, 1, 3, tzinfo=tz.gettz("US/Pacific")), - ) - - [self.assertEqual(r.tzinfo, tz.gettz("US/Pacific")) for r in result] - - def test_aware_different_tz(self): - - result = arrow.Arrow.range( - "day", - datetime(2013, 1, 1, tzinfo=tz.gettz("US/Eastern")), - datetime(2013, 1, 3, tzinfo=tz.gettz("US/Pacific")), - ) - - [self.assertEqual(r.tzinfo, tz.gettz("US/Eastern")) for r in result] - - def test_aware_tz(self): - - result = arrow.Arrow.range( - "day", - datetime(2013, 1, 1, tzinfo=tz.gettz("US/Eastern")), - datetime(2013, 1, 3, tzinfo=tz.gettz("US/Pacific")), - tz=tz.gettz("US/Central"), - ) - - [self.assertEqual(r.tzinfo, tz.gettz("US/Central")) for r in result] - - def test_unsupported(self): - - with self.assertRaises(AttributeError): - next(arrow.Arrow.range("abc", datetime.utcnow(), datetime.utcnow())) - - -class ArrowSpanRangeTests(Chai): - def test_year(self): - - result = list( - arrow.Arrow.span_range("year", datetime(2013, 2, 1), datetime(2016, 3, 31)) - ) - - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 1, 1), - arrow.Arrow(2013, 12, 31, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2014, 1, 1), - arrow.Arrow(2014, 12, 31, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2015, 1, 1), - arrow.Arrow(2015, 12, 31, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2016, 1, 1), - arrow.Arrow(2016, 12, 31, 23, 59, 59, 999999), - ), - ], - ) - - def test_quarter(self): - - result = list( - arrow.Arrow.span_range( - "quarter", datetime(2013, 2, 2), datetime(2013, 5, 15) - ) - ) - - self.assertEqual( - result, - [ - (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 3, 31, 23, 59, 59, 999999)), - (arrow.Arrow(2013, 4, 1), arrow.Arrow(2013, 6, 30, 23, 59, 59, 999999)), - ], - ) - - def test_month(self): - - result = list( - arrow.Arrow.span_range("month", datetime(2013, 1, 2), datetime(2013, 4, 15)) - ) - - self.assertEqual( - result, - [ - (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 1, 31, 23, 59, 59, 999999)), - (arrow.Arrow(2013, 2, 1), arrow.Arrow(2013, 2, 28, 23, 59, 59, 999999)), - (arrow.Arrow(2013, 3, 1), arrow.Arrow(2013, 3, 31, 23, 59, 59, 999999)), - (arrow.Arrow(2013, 4, 1), arrow.Arrow(2013, 4, 30, 23, 59, 59, 999999)), - ], - ) - - def test_week(self): - - result = list( - arrow.Arrow.span_range("week", datetime(2013, 2, 2), datetime(2013, 2, 28)) - ) - - self.assertEqual( - result, - [ - (arrow.Arrow(2013, 1, 28), arrow.Arrow(2013, 2, 3, 23, 59, 59, 999999)), - (arrow.Arrow(2013, 2, 4), arrow.Arrow(2013, 2, 10, 23, 59, 59, 999999)), - ( - arrow.Arrow(2013, 2, 11), - arrow.Arrow(2013, 2, 17, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 2, 18), - arrow.Arrow(2013, 2, 24, 23, 59, 59, 999999), - ), - (arrow.Arrow(2013, 2, 25), arrow.Arrow(2013, 3, 3, 23, 59, 59, 999999)), - ], - ) - - def test_day(self): - - result = list( - arrow.Arrow.span_range( - "day", datetime(2013, 1, 1, 12), datetime(2013, 1, 4, 12) - ) - ) - - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 1, 1, 0), - arrow.Arrow(2013, 1, 1, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 2, 0), - arrow.Arrow(2013, 1, 2, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 3, 0), - arrow.Arrow(2013, 1, 3, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 4, 0), - arrow.Arrow(2013, 1, 4, 23, 59, 59, 999999), - ), - ], - ) - - def test_days(self): - - result = list( - arrow.Arrow.span_range( - "days", datetime(2013, 1, 1, 12), datetime(2013, 1, 4, 12) - ) - ) - - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 1, 1, 0), - arrow.Arrow(2013, 1, 1, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 2, 0), - arrow.Arrow(2013, 1, 2, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 3, 0), - arrow.Arrow(2013, 1, 3, 23, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 4, 0), - arrow.Arrow(2013, 1, 4, 23, 59, 59, 999999), - ), - ], - ) - - def test_hour(self): - - result = list( - arrow.Arrow.span_range( - "hour", datetime(2013, 1, 1, 0, 30), datetime(2013, 1, 1, 3, 30) - ) - ) - - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 1, 1, 0), - arrow.Arrow(2013, 1, 1, 0, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 1), - arrow.Arrow(2013, 1, 1, 1, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 2), - arrow.Arrow(2013, 1, 1, 2, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 3), - arrow.Arrow(2013, 1, 1, 3, 59, 59, 999999), - ), - ], - ) - - result = list( - arrow.Arrow.span_range( - "hour", datetime(2013, 1, 1, 3, 30), datetime(2013, 1, 1, 3, 30) - ) - ) - - self.assertEqual( - result, - [(arrow.Arrow(2013, 1, 1, 3), arrow.Arrow(2013, 1, 1, 3, 59, 59, 999999))], - ) - - def test_minute(self): - - result = list( - arrow.Arrow.span_range( - "minute", datetime(2013, 1, 1, 0, 0, 30), datetime(2013, 1, 1, 0, 3, 30) - ) - ) - - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 1, 1, 0, 0), - arrow.Arrow(2013, 1, 1, 0, 0, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 0, 1), - arrow.Arrow(2013, 1, 1, 0, 1, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 0, 2), - arrow.Arrow(2013, 1, 1, 0, 2, 59, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 0, 3), - arrow.Arrow(2013, 1, 1, 0, 3, 59, 999999), - ), - ], - ) - - def test_second(self): - - result = list( - arrow.Arrow.span_range( - "second", datetime(2013, 1, 1), datetime(2013, 1, 1, 0, 0, 3) - ) - ) - - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 1, 1, 0, 0, 0), - arrow.Arrow(2013, 1, 1, 0, 0, 0, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 0, 0, 1), - arrow.Arrow(2013, 1, 1, 0, 0, 1, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 0, 0, 2), - arrow.Arrow(2013, 1, 1, 0, 0, 2, 999999), - ), - ( - arrow.Arrow(2013, 1, 1, 0, 0, 3), - arrow.Arrow(2013, 1, 1, 0, 0, 3, 999999), - ), - ], - ) - - def test_naive_tz(self): - - tzinfo = tz.gettz("US/Pacific") - - result = arrow.Arrow.span_range( - "hour", datetime(2013, 1, 1, 0), datetime(2013, 1, 1, 3, 59), "US/Pacific" - ) - - for f, c in result: - self.assertEqual(f.tzinfo, tzinfo) - self.assertEqual(c.tzinfo, tzinfo) - - def test_aware_same_tz(self): - - tzinfo = tz.gettz("US/Pacific") - - result = arrow.Arrow.span_range( - "hour", - datetime(2013, 1, 1, 0, tzinfo=tzinfo), - datetime(2013, 1, 1, 2, 59, tzinfo=tzinfo), - ) - - for f, c in result: - self.assertEqual(f.tzinfo, tzinfo) - self.assertEqual(c.tzinfo, tzinfo) - - def test_aware_different_tz(self): - - tzinfo1 = tz.gettz("US/Pacific") - tzinfo2 = tz.gettz("US/Eastern") - - result = arrow.Arrow.span_range( - "hour", - datetime(2013, 1, 1, 0, tzinfo=tzinfo1), - datetime(2013, 1, 1, 2, 59, tzinfo=tzinfo2), - ) - - for f, c in result: - self.assertEqual(f.tzinfo, tzinfo1) - self.assertEqual(c.tzinfo, tzinfo1) - - def test_aware_tz(self): - - result = arrow.Arrow.span_range( - "hour", - datetime(2013, 1, 1, 0, tzinfo=tz.gettz("US/Eastern")), - datetime(2013, 1, 1, 2, 59, tzinfo=tz.gettz("US/Eastern")), - tz="US/Central", - ) - - for f, c in result: - self.assertEqual(f.tzinfo, tz.gettz("US/Central")) - self.assertEqual(c.tzinfo, tz.gettz("US/Central")) - - def test_bounds_param_is_passed(self): - - result = list( - arrow.Arrow.span_range( - "quarter", datetime(2013, 2, 2), datetime(2013, 5, 15), bounds="[]" - ) - ) - - self.assertEqual( - result, - [ - (arrow.Arrow(2013, 1, 1), arrow.Arrow(2013, 4, 1)), - (arrow.Arrow(2013, 4, 1), arrow.Arrow(2013, 7, 1)), - ], - ) - - -class ArrowIntervalTests(Chai): - def test_incorrect_input(self): - correct = True - try: - list( - arrow.Arrow.interval( - "month", datetime(2013, 1, 2), datetime(2013, 4, 15), 0 - ) - ) - except: # noqa: E722 - correct = False - - self.assertEqual(correct, False) - - def test_correct(self): - result = list( - arrow.Arrow.interval( - "hour", datetime(2013, 5, 5, 12, 30), datetime(2013, 5, 5, 17, 15), 2 - ) - ) - - self.assertEqual( - result, - [ - ( - arrow.Arrow(2013, 5, 5, 12), - arrow.Arrow(2013, 5, 5, 13, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 5, 5, 14), - arrow.Arrow(2013, 5, 5, 15, 59, 59, 999999), - ), - ( - arrow.Arrow(2013, 5, 5, 16), - arrow.Arrow(2013, 5, 5, 17, 59, 59, 999999), - ), - ], - ) - - def test_bounds_param_is_passed(self): - result = list( - arrow.Arrow.interval( - "hour", - datetime(2013, 5, 5, 12, 30), - datetime(2013, 5, 5, 17, 15), - 2, - bounds="[]", - ) - ) - - self.assertEqual( - result, - [ - (arrow.Arrow(2013, 5, 5, 12), arrow.Arrow(2013, 5, 5, 14)), - (arrow.Arrow(2013, 5, 5, 14), arrow.Arrow(2013, 5, 5, 16)), - (arrow.Arrow(2013, 5, 5, 16), arrow.Arrow(2013, 5, 5, 18)), - ], - ) - - -class ArrowSpanTests(Chai): - def setUp(self): - super(ArrowSpanTests, self).setUp() - - self.datetime = datetime(2013, 2, 15, 3, 41, 22, 8923) - self.arrow = arrow.Arrow.fromdatetime(self.datetime) - - def test_span_attribute(self): - - with self.assertRaises(AttributeError): - self.arrow.span("span") - - def test_span_year(self): - - floor, ceil = self.arrow.span("year") - - self.assertEqual(floor, datetime(2013, 1, 1, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 12, 31, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) - - def test_span_quarter(self): - - floor, ceil = self.arrow.span("quarter") - - self.assertEqual(floor, datetime(2013, 1, 1, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 3, 31, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) - - def test_span_quarter_count(self): - - floor, ceil = self.arrow.span("quarter", 2) - - self.assertEqual(floor, datetime(2013, 1, 1, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 6, 30, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) - - def test_span_year_count(self): - - floor, ceil = self.arrow.span("year", 2) - - self.assertEqual(floor, datetime(2013, 1, 1, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2014, 12, 31, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) - - def test_span_month(self): - - floor, ceil = self.arrow.span("month") - - self.assertEqual(floor, datetime(2013, 2, 1, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 28, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) - - def test_span_week(self): - - floor, ceil = self.arrow.span("week") - - self.assertEqual(floor, datetime(2013, 2, 11, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 17, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) - - def test_span_day(self): - - floor, ceil = self.arrow.span("day") - - self.assertEqual(floor, datetime(2013, 2, 15, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 15, 23, 59, 59, 999999, tzinfo=tz.tzutc()) - ) - - def test_span_hour(self): - - floor, ceil = self.arrow.span("hour") - - self.assertEqual(floor, datetime(2013, 2, 15, 3, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 15, 3, 59, 59, 999999, tzinfo=tz.tzutc()) - ) - - def test_span_minute(self): - - floor, ceil = self.arrow.span("minute") - - self.assertEqual(floor, datetime(2013, 2, 15, 3, 41, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 15, 3, 41, 59, 999999, tzinfo=tz.tzutc()) - ) - - def test_span_second(self): - - floor, ceil = self.arrow.span("second") - - self.assertEqual(floor, datetime(2013, 2, 15, 3, 41, 22, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 15, 3, 41, 22, 999999, tzinfo=tz.tzutc()) - ) - - def test_span_microsecond(self): - - floor, ceil = self.arrow.span("microsecond") - - self.assertEqual( - floor, datetime(2013, 2, 15, 3, 41, 22, 8923, tzinfo=tz.tzutc()) - ) - self.assertEqual( - ceil, datetime(2013, 2, 15, 3, 41, 22, 8923, tzinfo=tz.tzutc()) - ) - - def test_floor(self): - - floor, ceil = self.arrow.span("month") - - self.assertEqual(floor, self.arrow.floor("month")) - self.assertEqual(ceil, self.arrow.ceil("month")) - - def test_span_inclusive_inclusive(self): - - floor, ceil = self.arrow.span("hour", bounds="[]") - - self.assertEqual(floor, datetime(2013, 2, 15, 3, tzinfo=tz.tzutc())) - self.assertEqual(ceil, datetime(2013, 2, 15, 4, tzinfo=tz.tzutc())) - - def test_span_exclusive_inclusive(self): - - floor, ceil = self.arrow.span("hour", bounds="(]") - - self.assertEqual(floor, datetime(2013, 2, 15, 3, 0, 0, 1, tzinfo=tz.tzutc())) - self.assertEqual(ceil, datetime(2013, 2, 15, 4, tzinfo=tz.tzutc())) - - def test_span_exclusive_exclusive(self): - - floor, ceil = self.arrow.span("hour", bounds="()") - - self.assertEqual(floor, datetime(2013, 2, 15, 3, 0, 0, 1, tzinfo=tz.tzutc())) - self.assertEqual( - ceil, datetime(2013, 2, 15, 3, 59, 59, 999999, tzinfo=tz.tzutc()) - ) - - def test_bounds_are_validated(self): - - with self.assertRaises(AttributeError): - floor, ceil = self.arrow.span("hour", bounds="][") - - -class ArrowHumanizeTests(Chai): - def setUp(self): - super(ArrowHumanizeTests, self).setUp() - - self.datetime = datetime(2013, 1, 1) - self.now = arrow.Arrow.utcnow() - - def test_granularity(self): - - self.assertEqual(self.now.humanize(granularity="second"), "just now") - - later1 = self.now.shift(seconds=1) - self.assertEqual(self.now.humanize(later1, granularity="second"), "just now") - self.assertEqual(later1.humanize(self.now, granularity="second"), "just now") - self.assertEqual( - self.now.humanize(later1, granularity="minute"), "0 minutes ago" - ) - self.assertEqual( - later1.humanize(self.now, granularity="minute"), "in 0 minutes" - ) - - later100 = self.now.shift(seconds=100) - self.assertEqual( - self.now.humanize(later100, granularity="second"), "100 seconds ago" - ) - self.assertEqual( - later100.humanize(self.now, granularity="second"), "in 100 seconds" - ) - self.assertEqual( - self.now.humanize(later100, granularity="minute"), "a minute ago" - ) - self.assertEqual( - later100.humanize(self.now, granularity="minute"), "in a minute" - ) - self.assertEqual(self.now.humanize(later100, granularity="hour"), "0 hours ago") - self.assertEqual(later100.humanize(self.now, granularity="hour"), "in 0 hours") - - later4000 = self.now.shift(seconds=4000) - self.assertEqual( - self.now.humanize(later4000, granularity="minute"), "66 minutes ago" - ) - self.assertEqual( - later4000.humanize(self.now, granularity="minute"), "in 66 minutes" - ) - self.assertEqual( - self.now.humanize(later4000, granularity="hour"), "an hour ago" - ) - self.assertEqual(later4000.humanize(self.now, granularity="hour"), "in an hour") - self.assertEqual(self.now.humanize(later4000, granularity="day"), "0 days ago") - self.assertEqual(later4000.humanize(self.now, granularity="day"), "in 0 days") - - later105 = self.now.shift(seconds=10 ** 5) - self.assertEqual( - self.now.humanize(later105, granularity="hour"), "27 hours ago" - ) - self.assertEqual(later105.humanize(self.now, granularity="hour"), "in 27 hours") - self.assertEqual(self.now.humanize(later105, granularity="day"), "a day ago") - self.assertEqual(later105.humanize(self.now, granularity="day"), "in a day") - self.assertEqual(self.now.humanize(later105, granularity="week"), "0 weeks ago") - self.assertEqual(later105.humanize(self.now, granularity="week"), "in 0 weeks") - self.assertEqual( - self.now.humanize(later105, granularity="month"), "0 months ago" - ) - self.assertEqual( - later105.humanize(self.now, granularity="month"), "in 0 months" - ) - self.assertEqual( - self.now.humanize(later105, granularity=["month"]), "0 months ago" - ) - self.assertEqual( - later105.humanize(self.now, granularity=["month"]), "in 0 months" - ) - - later106 = self.now.shift(seconds=3 * 10 ** 6) - self.assertEqual(self.now.humanize(later106, granularity="day"), "34 days ago") - self.assertEqual(later106.humanize(self.now, granularity="day"), "in 34 days") - self.assertEqual(self.now.humanize(later106, granularity="week"), "4 weeks ago") - self.assertEqual(later106.humanize(self.now, granularity="week"), "in 4 weeks") - self.assertEqual( - self.now.humanize(later106, granularity="month"), "a month ago" - ) - self.assertEqual(later106.humanize(self.now, granularity="month"), "in a month") - self.assertEqual(self.now.humanize(later106, granularity="year"), "0 years ago") - self.assertEqual(later106.humanize(self.now, granularity="year"), "in 0 years") - - later506 = self.now.shift(seconds=50 * 10 ** 6) - self.assertEqual( - self.now.humanize(later506, granularity="week"), "82 weeks ago" - ) - self.assertEqual(later506.humanize(self.now, granularity="week"), "in 82 weeks") - self.assertEqual( - self.now.humanize(later506, granularity="month"), "18 months ago" - ) - self.assertEqual( - later506.humanize(self.now, granularity="month"), "in 18 months" - ) - self.assertEqual(self.now.humanize(later506, granularity="year"), "a year ago") - self.assertEqual(later506.humanize(self.now, granularity="year"), "in a year") - - later108 = self.now.shift(seconds=10 ** 8) - self.assertEqual(self.now.humanize(later108, granularity="year"), "3 years ago") - self.assertEqual(later108.humanize(self.now, granularity="year"), "in 3 years") - - later108onlydistance = self.now.shift(seconds=10 ** 8) - self.assertEqual( - self.now.humanize( - later108onlydistance, only_distance=True, granularity="year" - ), - "3 years", - ) - self.assertEqual( - later108onlydistance.humanize( - self.now, only_distance=True, granularity="year" - ), - "3 years", - ) - - with self.assertRaises(AttributeError): - self.now.humanize(later108, granularity="years") - - def test_multiple_granularity(self): - self.assertEqual(self.now.humanize(granularity="second"), "just now") - self.assertEqual(self.now.humanize(granularity=["second"]), "just now") - self.assertEqual( - self.now.humanize(granularity=["year", "month", "day", "hour", "second"]), - "in 0 years 0 months 0 days 0 hours and 0 seconds", - ) - - later4000 = self.now.shift(seconds=4000) - self.assertEqual( - later4000.humanize(self.now, granularity=["hour", "minute"]), - "in an hour and 6 minutes", - ) - self.assertEqual( - self.now.humanize(later4000, granularity=["hour", "minute"]), - "an hour and 6 minutes ago", - ) - self.assertEqual( - later4000.humanize( - self.now, granularity=["hour", "minute"], only_distance=True - ), - "an hour and 6 minutes", - ) - self.assertEqual( - later4000.humanize(self.now, granularity=["day", "hour", "minute"]), - "in 0 days an hour and 6 minutes", - ) - self.assertEqual( - self.now.humanize(later4000, granularity=["day", "hour", "minute"]), - "0 days an hour and 6 minutes ago", - ) - - later105 = self.now.shift(seconds=10 ** 5) - self.assertEqual( - self.now.humanize(later105, granularity=["hour", "day", "minute"]), - "a day 3 hours and 46 minutes ago", - ) - with self.assertRaises(AttributeError): - self.now.humanize(later105, granularity=["error", "second"]) - - later108onlydistance = self.now.shift(seconds=10 ** 8) - self.assertEqual( - self.now.humanize( - later108onlydistance, only_distance=True, granularity=["year"] - ), - "3 years", - ) - self.assertEqual( - self.now.humanize( - later108onlydistance, only_distance=True, granularity=["month", "week"] - ), - "37 months and 4 weeks", - ) - self.assertEqual( - self.now.humanize( - later108onlydistance, only_distance=True, granularity=["year", "second"] - ), - "3 years and 5327200 seconds", - ) - - one_min_one_sec_ago = self.now.shift(minutes=-1, seconds=-1) - self.assertEqual( - one_min_one_sec_ago.humanize(self.now, granularity=["minute", "second"]), - "a minute and a second ago", - ) - - one_min_two_secs_ago = self.now.shift(minutes=-1, seconds=-2) - self.assertEqual( - one_min_two_secs_ago.humanize(self.now, granularity=["minute", "second"]), - "a minute and 2 seconds ago", - ) - - def test_seconds(self): - - later = self.now.shift(seconds=10) - - # regression test for issue #727 - self.assertEqual(self.now.humanize(later), "10 seconds ago") - self.assertEqual(later.humanize(self.now), "in 10 seconds") - - self.assertEqual(self.now.humanize(later, only_distance=True), "10 seconds") - self.assertEqual(later.humanize(self.now, only_distance=True), "10 seconds") - - def test_minute(self): - - later = self.now.shift(minutes=1) - - self.assertEqual(self.now.humanize(later), "a minute ago") - self.assertEqual(later.humanize(self.now), "in a minute") - - self.assertEqual(self.now.humanize(later, only_distance=True), "a minute") - self.assertEqual(later.humanize(self.now, only_distance=True), "a minute") - - def test_minutes(self): - - later = self.now.shift(minutes=2) - - self.assertEqual(self.now.humanize(later), "2 minutes ago") - self.assertEqual(later.humanize(self.now), "in 2 minutes") - - self.assertEqual(self.now.humanize(later, only_distance=True), "2 minutes") - self.assertEqual(later.humanize(self.now, only_distance=True), "2 minutes") - - def test_hour(self): - - later = self.now.shift(hours=1) - - self.assertEqual(self.now.humanize(later), "an hour ago") - self.assertEqual(later.humanize(self.now), "in an hour") - - self.assertEqual(self.now.humanize(later, only_distance=True), "an hour") - self.assertEqual(later.humanize(self.now, only_distance=True), "an hour") - - def test_hours(self): - - later = self.now.shift(hours=2) - - self.assertEqual(self.now.humanize(later), "2 hours ago") - self.assertEqual(later.humanize(self.now), "in 2 hours") - - self.assertEqual(self.now.humanize(later, only_distance=True), "2 hours") - self.assertEqual(later.humanize(self.now, only_distance=True), "2 hours") - - def test_day(self): - - later = self.now.shift(days=1) - - self.assertEqual(self.now.humanize(later), "a day ago") - self.assertEqual(later.humanize(self.now), "in a day") - - # regression test for issue #697 - less_than_48_hours = self.now.shift( - days=1, hours=23, seconds=59, microseconds=999999 - ) - self.assertEqual(self.now.humanize(less_than_48_hours), "a day ago") - self.assertEqual(less_than_48_hours.humanize(self.now), "in a day") - - less_than_48_hours_date = less_than_48_hours._datetime.date() - with self.assertRaises(TypeError): - # humanize other argument does not take raw datetime.date objects - self.now.humanize(less_than_48_hours_date) - - # convert from date to arrow object - less_than_48_hours_date = arrow.Arrow.fromdate(less_than_48_hours_date) - self.assertEqual(self.now.humanize(less_than_48_hours_date), "a day ago") - self.assertEqual(less_than_48_hours_date.humanize(self.now), "in a day") - - self.assertEqual(self.now.humanize(later, only_distance=True), "a day") - self.assertEqual(later.humanize(self.now, only_distance=True), "a day") - - def test_days(self): - - later = self.now.shift(days=2) - - self.assertEqual(self.now.humanize(later), "2 days ago") - self.assertEqual(later.humanize(self.now), "in 2 days") - - self.assertEqual(self.now.humanize(later, only_distance=True), "2 days") - self.assertEqual(later.humanize(self.now, only_distance=True), "2 days") - - # Regression tests for humanize bug referenced in issue 541 - later = self.now.shift(days=3) - self.assertEqual(later.humanize(), "in 3 days") - - later = self.now.shift(days=3, seconds=1) - self.assertEqual(later.humanize(), "in 3 days") - - later = self.now.shift(days=4) - self.assertEqual(later.humanize(), "in 4 days") - - def test_week(self): - - later = self.now.shift(weeks=1) - - self.assertEqual(self.now.humanize(later), "a week ago") - self.assertEqual(later.humanize(self.now), "in a week") - - self.assertEqual(self.now.humanize(later, only_distance=True), "a week") - self.assertEqual(later.humanize(self.now, only_distance=True), "a week") - - def test_weeks(self): - - later = self.now.shift(weeks=2) - - self.assertEqual(self.now.humanize(later), "2 weeks ago") - self.assertEqual(later.humanize(self.now), "in 2 weeks") - - self.assertEqual(self.now.humanize(later, only_distance=True), "2 weeks") - self.assertEqual(later.humanize(self.now, only_distance=True), "2 weeks") - - def test_month(self): - - later = self.now.shift(months=1) - - self.assertEqual(self.now.humanize(later), "a month ago") - self.assertEqual(later.humanize(self.now), "in a month") - - self.assertEqual(self.now.humanize(later, only_distance=True), "a month") - self.assertEqual(later.humanize(self.now, only_distance=True), "a month") - - def test_months(self): - - later = self.now.shift(months=2) - earlier = self.now.shift(months=-2) - - self.assertEqual(earlier.humanize(self.now), "2 months ago") - self.assertEqual(later.humanize(self.now), "in 2 months") - - self.assertEqual(self.now.humanize(later, only_distance=True), "2 months") - self.assertEqual(later.humanize(self.now, only_distance=True), "2 months") - - def test_year(self): - - later = self.now.shift(years=1) - - self.assertEqual(self.now.humanize(later), "a year ago") - self.assertEqual(later.humanize(self.now), "in a year") - - self.assertEqual(self.now.humanize(later, only_distance=True), "a year") - self.assertEqual(later.humanize(self.now, only_distance=True), "a year") - - def test_years(self): - - later = self.now.shift(years=2) - - self.assertEqual(self.now.humanize(later), "2 years ago") - self.assertEqual(later.humanize(self.now), "in 2 years") - - self.assertEqual(self.now.humanize(later, only_distance=True), "2 years") - self.assertEqual(later.humanize(self.now, only_distance=True), "2 years") - - arw = arrow.Arrow(2014, 7, 2) - - result = arw.humanize(self.datetime) - - self.assertEqual(result, "in 2 years") - - def test_arrow(self): - - arw = arrow.Arrow.fromdatetime(self.datetime) - - result = arw.humanize(arrow.Arrow.fromdatetime(self.datetime)) - - self.assertEqual(result, "just now") - - def test_datetime_tzinfo(self): - - arw = arrow.Arrow.fromdatetime(self.datetime) - - result = arw.humanize(self.datetime.replace(tzinfo=tz.tzutc())) - - self.assertEqual(result, "just now") - - def test_other(self): - - arw = arrow.Arrow.fromdatetime(self.datetime) - - with self.assertRaises(TypeError): - arw.humanize(object()) - - def test_invalid_locale(self): - - arw = arrow.Arrow.fromdatetime(self.datetime) - - with self.assertRaises(ValueError): - arw.humanize(locale="klingon") - - def test_none(self): - - arw = arrow.Arrow.utcnow() - - result = arw.humanize() - - self.assertEqual(result, "just now") - - result = arw.humanize(None) - - self.assertEqual(result, "just now") - - def test_untranslated_granularity(self): - - arw = arrow.Arrow.utcnow() - later = arw.shift(weeks=1) - - # simulate an untranslated timeframe key - with patch.dict("arrow.locales.EnglishLocale.timeframes"): - del arrow.locales.EnglishLocale.timeframes["week"] - - with self.assertRaises(ValueError): - arw.humanize(later, granularity="week") - - -class ArrowHumanizeTestsWithLocale(Chai): - def setUp(self): - super(ArrowHumanizeTestsWithLocale, self).setUp() - - self.datetime = datetime(2013, 1, 1) - - def test_now(self): - - arw = arrow.Arrow(2013, 1, 1, 0, 0, 0) - - result = arw.humanize(self.datetime, locale="ru") - - self.assertEqual(result, "сейчас") - - def test_seconds(self): - arw = arrow.Arrow(2013, 1, 1, 0, 0, 44) - - result = arw.humanize(self.datetime, locale="ru") - - self.assertEqual(result, "через 44 несколько секунд") - - def test_years(self): - - arw = arrow.Arrow(2011, 7, 2) - - result = arw.humanize(self.datetime, locale="ru") - - self.assertEqual(result, "2 года назад") - - -class ArrowIsBetweenTests(Chai): - def test_start_before_end(self): - target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) - start = arrow.Arrow.fromdatetime(datetime(2013, 5, 8)) - end = arrow.Arrow.fromdatetime(datetime(2013, 5, 5)) - result = target.is_between(start, end) - self.assertFalse(result) - - def test_exclusive_exclusive_bounds(self): - target = arrow.Arrow.fromdatetime(datetime(2013, 5, 5, 12, 30, 27)) - start = arrow.Arrow.fromdatetime(datetime(2013, 5, 5, 12, 30, 10)) - end = arrow.Arrow.fromdatetime(datetime(2013, 5, 5, 12, 30, 36)) - result = target.is_between(start, end, "()") - self.assertTrue(result) - result = target.is_between(start, end) - self.assertTrue(result) - - def test_exclusive_exclusive_bounds_same_date(self): - target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) - start = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) - end = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) - result = target.is_between(start, end, "()") - self.assertFalse(result) - - def test_inclusive_exclusive_bounds(self): - target = arrow.Arrow.fromdatetime(datetime(2013, 5, 6)) - start = arrow.Arrow.fromdatetime(datetime(2013, 5, 4)) - end = arrow.Arrow.fromdatetime(datetime(2013, 5, 6)) - result = target.is_between(start, end, "[)") - self.assertFalse(result) - - def test_exclusive_inclusive_bounds(self): - target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) - start = arrow.Arrow.fromdatetime(datetime(2013, 5, 5)) - end = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) - result = target.is_between(start, end, "(]") - self.assertTrue(result) - - def test_inclusive_inclusive_bounds_same_date(self): - target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) - start = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) - end = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) - result = target.is_between(start, end, "[]") - self.assertTrue(result) - - def test_type_error_exception(self): - with self.assertRaises(TypeError): - target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) - start = datetime(2013, 5, 5) - end = arrow.Arrow.fromdatetime(datetime(2013, 5, 8)) - target.is_between(start, end) - - with self.assertRaises(TypeError): - target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) - start = arrow.Arrow.fromdatetime(datetime(2013, 5, 5)) - end = datetime(2013, 5, 8) - target.is_between(start, end) - - with self.assertRaises(TypeError): - target.is_between(None, None) - - def test_attribute_error_exception(self): - target = arrow.Arrow.fromdatetime(datetime(2013, 5, 7)) - start = arrow.Arrow.fromdatetime(datetime(2013, 5, 5)) - end = arrow.Arrow.fromdatetime(datetime(2013, 5, 8)) - with self.assertRaises(AttributeError): - target.is_between(start, end, "][") - with self.assertRaises(AttributeError): - target.is_between(start, end, "") - with self.assertRaises(AttributeError): - target.is_between(start, end, "]") - with self.assertRaises(AttributeError): - target.is_between(start, end, "[") - with self.assertRaises(AttributeError): - target.is_between(start, end, "hello") - - -class ArrowUtilTests(Chai): - def test_get_datetime(self): - - get_datetime = arrow.Arrow._get_datetime - - arw = arrow.Arrow.utcnow() - dt = datetime.utcnow() - timestamp = time.time() - - self.assertEqual(get_datetime(arw), arw.datetime) - self.assertEqual(get_datetime(dt), dt) - self.assertEqual( - get_datetime(timestamp), arrow.Arrow.utcfromtimestamp(timestamp).datetime - ) - - with self.assertRaises(ValueError) as raise_ctx: - get_datetime("abc") - self.assertFalse("{}" in str(raise_ctx.exception)) - - def test_get_tzinfo(self): - - get_tzinfo = arrow.Arrow._get_tzinfo - - with self.assertRaises(ValueError) as raise_ctx: - get_tzinfo("abc") - self.assertFalse("{}" in str(raise_ctx.exception)) - - def test_get_iteration_params(self): - - self.assertEqual( - arrow.Arrow._get_iteration_params("end", None), ("end", sys.maxsize) - ) - self.assertEqual( - arrow.Arrow._get_iteration_params(None, 100), (arrow.Arrow.max, 100) - ) - self.assertEqual(arrow.Arrow._get_iteration_params(100, 120), (100, 120)) - - with self.assertRaises(ValueError): - arrow.Arrow._get_iteration_params(None, None) diff --git a/tests/factory_tests.py.bak b/tests/factory_tests.py.bak deleted file mode 100644 index abdd0d029..000000000 --- a/tests/factory_tests.py.bak +++ /dev/null @@ -1,383 +0,0 @@ -# -*- coding: utf-8 -*- -import time -from datetime import date, datetime - -import dateparser -from chai import Chai -from dateutil import tz - -from arrow import factory, util -from arrow.parser import ParserError - - -def assertDtEqual(dt1, dt2, within=10): - assertEqual(dt1.tzinfo, dt2.tzinfo) # noqa: F821 - assertTrue(abs(util.total_seconds(dt1 - dt2)) < within) # noqa: F821 - - -class GetTests(Chai): - def setUp(self): - super(GetTests, self).setUp() - - self.factory = factory.ArrowFactory() - - def test_no_args(self): - - assertDtEqual(self.factory.get(), datetime.utcnow().replace(tzinfo=tz.tzutc())) - - def test_timestamp_one_arg_no_arg(self): - - no_arg = self.factory.get(1406430900).timestamp - one_arg = self.factory.get("1406430900", "X").timestamp - - self.assertEqual(no_arg, one_arg) - - def test_one_arg_none(self): - - assertDtEqual( - self.factory.get(None), datetime.utcnow().replace(tzinfo=tz.tzutc()) - ) - - def test_struct_time(self): - - assertDtEqual( - self.factory.get(time.gmtime()), - datetime.utcnow().replace(tzinfo=tz.tzutc()), - ) - - def test_one_arg_timestamp(self): - - int_timestamp = int(time.time()) - timestamp_dt = datetime.utcfromtimestamp(int_timestamp).replace( - tzinfo=tz.tzutc() - ) - - self.assertEqual(self.factory.get(int_timestamp), timestamp_dt) - - with self.assertRaises(ParserError): - self.factory.get(str(int_timestamp)) - - float_timestamp = time.time() - timestamp_dt = datetime.utcfromtimestamp(float_timestamp).replace( - tzinfo=tz.tzutc() - ) - - self.assertEqual(self.factory.get(float_timestamp), timestamp_dt) - - with self.assertRaises(ParserError): - self.factory.get(str(float_timestamp)) - - # Regression test for issue #216 - # Python 3 raises OverflowError, Python 2 raises ValueError - timestamp = 99999999999999999999999999.99999999999999999999999999 - with self.assertRaises((OverflowError, ValueError)): - self.factory.get(timestamp) - - def test_one_arg_timestamp_with_tzinfo(self): - - timestamp = time.time() - timestamp_dt = datetime.fromtimestamp(timestamp, tz=tz.tzutc()).astimezone( - tz.gettz("US/Pacific") - ) - timezone = tz.gettz("US/Pacific") - - assertDtEqual(self.factory.get(timestamp, tzinfo=timezone), timestamp_dt) - - def test_one_arg_arrow(self): - - arw = self.factory.utcnow() - result = self.factory.get(arw) - - self.assertEqual(arw, result) - - def test_one_arg_datetime(self): - - dt = datetime.utcnow().replace(tzinfo=tz.tzutc()) - - self.assertEqual(self.factory.get(dt), dt) - - def test_one_arg_date(self): - - d = date.today() - dt = datetime(d.year, d.month, d.day, tzinfo=tz.tzutc()) - - self.assertEqual(self.factory.get(d), dt) - - def test_one_arg_tzinfo(self): - - self.expected = ( - datetime.utcnow() - .replace(tzinfo=tz.tzutc()) - .astimezone(tz.gettz("US/Pacific")) - ) - - assertDtEqual(self.factory.get(tz.gettz("US/Pacific")), self.expected) - - # regression test for issue #658 - def test_one_arg_dateparser_datetime(self): - expected = datetime(1990, 1, 1).replace(tzinfo=tz.tzutc()) - # dateparser outputs: datetime.datetime(1990, 1, 1, 0, 0, tzinfo=) - parsed_date = dateparser.parse("1990-01-01T00:00:00+00:00") - dt_output = self.factory.get(parsed_date)._datetime.replace(tzinfo=tz.tzutc()) - self.assertEqual(dt_output, expected) - - def test_kwarg_tzinfo(self): - - self.expected = ( - datetime.utcnow() - .replace(tzinfo=tz.tzutc()) - .astimezone(tz.gettz("US/Pacific")) - ) - - assertDtEqual(self.factory.get(tzinfo=tz.gettz("US/Pacific")), self.expected) - - def test_kwarg_tzinfo_string(self): - - self.expected = ( - datetime.utcnow() - .replace(tzinfo=tz.tzutc()) - .astimezone(tz.gettz("US/Pacific")) - ) - - assertDtEqual(self.factory.get(tzinfo="US/Pacific"), self.expected) - - with self.assertRaises(ParserError): - self.factory.get(tzinfo="US/PacificInvalidTzinfo") - - def test_one_arg_iso_str(self): - - dt = datetime.utcnow() - - assertDtEqual(self.factory.get(dt.isoformat()), dt.replace(tzinfo=tz.tzutc())) - - def test_one_arg_iso_calendar(self): - - pairs = [ - (datetime(2004, 1, 4), (2004, 1, 7)), - (datetime(2008, 12, 30), (2009, 1, 2)), - (datetime(2010, 1, 2), (2009, 53, 6)), - (datetime(2000, 2, 29), (2000, 9, 2)), - (datetime(2005, 1, 1), (2004, 53, 6)), - (datetime(2010, 1, 4), (2010, 1, 1)), - (datetime(2010, 1, 3), (2009, 53, 7)), - (datetime(2003, 12, 29), (2004, 1, 1)), - ] - - for pair in pairs: - dt, iso = pair - self.assertEqual(self.factory.get(iso), self.factory.get(dt)) - - with self.assertRaises(TypeError): - self.factory.get((2014, 7, 1, 4)) - - with self.assertRaises(TypeError): - self.factory.get((2014, 7)) - - with self.assertRaises(ValueError): - self.factory.get((2014, 70, 1)) - - with self.assertRaises(ValueError): - self.factory.get((2014, 7, 10)) - - def test_one_arg_other(self): - - with self.assertRaises(TypeError): - self.factory.get(object()) - - def test_one_arg_bool(self): - - with self.assertRaises(TypeError): - self.factory.get(False) - - with self.assertRaises(TypeError): - self.factory.get(True) - - def test_two_args_datetime_tzinfo(self): - - result = self.factory.get(datetime(2013, 1, 1), tz.gettz("US/Pacific")) - - self.assertEqual( - result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) - ) - - def test_two_args_datetime_tz_str(self): - - result = self.factory.get(datetime(2013, 1, 1), "US/Pacific") - - self.assertEqual( - result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) - ) - - def test_two_args_date_tzinfo(self): - - result = self.factory.get(date(2013, 1, 1), tz.gettz("US/Pacific")) - - self.assertEqual( - result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) - ) - - def test_two_args_date_tz_str(self): - - result = self.factory.get(date(2013, 1, 1), "US/Pacific") - - self.assertEqual( - result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) - ) - - def test_two_args_datetime_other(self): - - with self.assertRaises(TypeError): - self.factory.get(datetime.utcnow(), object()) - - def test_two_args_date_other(self): - - with self.assertRaises(TypeError): - self.factory.get(date.today(), object()) - - def test_two_args_str_str(self): - - result = self.factory.get("2013-01-01", "YYYY-MM-DD") - - self.assertEqual(result._datetime, datetime(2013, 1, 1, tzinfo=tz.tzutc())) - - def test_two_args_str_tzinfo(self): - - result = self.factory.get("2013-01-01", tzinfo=tz.gettz("US/Pacific")) - - assertDtEqual( - result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) - ) - - def test_two_args_twitter_format(self): - - # format returned by twitter API for created_at: - twitter_date = "Fri Apr 08 21:08:54 +0000 2016" - result = self.factory.get(twitter_date, "ddd MMM DD HH:mm:ss Z YYYY") - - self.assertEqual( - result._datetime, datetime(2016, 4, 8, 21, 8, 54, tzinfo=tz.tzutc()) - ) - - def test_two_args_str_list(self): - - result = self.factory.get("2013-01-01", ["MM/DD/YYYY", "YYYY-MM-DD"]) - - self.assertEqual(result._datetime, datetime(2013, 1, 1, tzinfo=tz.tzutc())) - - def test_two_args_unicode_unicode(self): - - result = self.factory.get(u"2013-01-01", u"YYYY-MM-DD") - - self.assertEqual(result._datetime, datetime(2013, 1, 1, tzinfo=tz.tzutc())) - - def test_two_args_other(self): - - with self.assertRaises(TypeError): - self.factory.get(object(), object()) - - def test_three_args_with_tzinfo(self): - - timefmt = "YYYYMMDD" - d = "20150514" - - self.assertEqual( - self.factory.get(d, timefmt, tzinfo=tz.tzlocal()), - datetime(2015, 5, 14, tzinfo=tz.tzlocal()), - ) - - def test_three_args(self): - - self.assertEqual( - self.factory.get(2013, 1, 1), datetime(2013, 1, 1, tzinfo=tz.tzutc()) - ) - - def test_full_kwargs(self): - - self.assertEqual( - self.factory.get( - year=2016, - month=7, - day=14, - hour=7, - minute=16, - second=45, - microsecond=631092, - ), - datetime(2016, 7, 14, 7, 16, 45, 631092, tzinfo=tz.tzutc()), - ) - - def test_three_kwargs(self): - - self.assertEqual( - self.factory.get(year=2016, month=7, day=14), - datetime(2016, 7, 14, 0, 0, tzinfo=tz.tzutc()), - ) - - def test_tzinfo_string_kwargs(self): - result = self.factory.get("2019072807", "YYYYMMDDHH", tzinfo="UTC") - self.assertEqual( - result._datetime, datetime(2019, 7, 28, 7, 0, 0, 0, tzinfo=tz.tzutc()) - ) - - def test_insufficient_kwargs(self): - - with self.assertRaises(TypeError): - self.factory.get(year=2016) - - with self.assertRaises(TypeError): - self.factory.get(year=2016, month=7) - - def test_locale(self): - result = self.factory.get("2010", "YYYY", locale="ja") - self.assertEqual( - result._datetime, datetime(2010, 1, 1, 0, 0, 0, 0, tzinfo=tz.tzutc()) - ) - - # regression test for issue #701 - result = self.factory.get( - "Montag, 9. September 2019, 16:15-20:00", "dddd, D. MMMM YYYY", locale="de" - ) - self.assertEqual( - result._datetime, datetime(2019, 9, 9, 0, 0, 0, 0, tzinfo=tz.tzutc()) - ) - - def test_locale_kwarg_only(self): - res = self.factory.get(locale="ja") - self.assertEqual(res.tzinfo, tz.tzutc()) - - def test_locale_with_tzinfo(self): - res = self.factory.get(locale="ja", tzinfo=tz.gettz("Asia/Tokyo")) - self.assertEqual(res.tzinfo, tz.gettz("Asia/Tokyo")) - - -class UtcNowTests(Chai): - def setUp(self): - super(UtcNowTests, self).setUp() - - self.factory = factory.ArrowFactory() - - def test_utcnow(self): - - assertDtEqual( - self.factory.utcnow()._datetime, - datetime.utcnow().replace(tzinfo=tz.tzutc()), - ) - - -class NowTests(Chai): - def setUp(self): - super(NowTests, self).setUp() - - self.factory = factory.ArrowFactory() - - def test_no_tz(self): - - assertDtEqual(self.factory.now(), datetime.now(tz.tzlocal())) - - def test_tzinfo(self): - - assertDtEqual(self.factory.now(tz.gettz("EST")), datetime.now(tz.gettz("EST"))) - - def test_tz_str(self): - - assertDtEqual(self.factory.now("EST"), datetime.now(tz.gettz("EST"))) diff --git a/tests/formatter_tests.py.bak b/tests/formatter_tests.py.bak deleted file mode 100644 index 848ac260a..000000000 --- a/tests/formatter_tests.py.bak +++ /dev/null @@ -1,199 +0,0 @@ -# -*- coding: utf-8 -*- -import time -from datetime import datetime - -import pytz -from chai import Chai -from dateutil import tz as dateutil_tz - -from arrow import formatter - -from .utils import make_full_tz_list - - -class DateTimeFormatterFormatTokenTests(Chai): - def setUp(self): - super(DateTimeFormatterFormatTokenTests, self).setUp() - - self.formatter = formatter.DateTimeFormatter() - - def test_format(self): - - dt = datetime(2013, 2, 5, 12, 32, 51) - - result = self.formatter.format(dt, "MM-DD-YYYY hh:mm:ss a") - - self.assertEqual(result, "02-05-2013 12:32:51 pm") - - def test_year(self): - - dt = datetime(2013, 1, 1) - self.assertEqual(self.formatter._format_token(dt, "YYYY"), "2013") - self.assertEqual(self.formatter._format_token(dt, "YY"), "13") - - def test_month(self): - - dt = datetime(2013, 1, 1) - self.assertEqual(self.formatter._format_token(dt, "MMMM"), "January") - self.assertEqual(self.formatter._format_token(dt, "MMM"), "Jan") - self.assertEqual(self.formatter._format_token(dt, "MM"), "01") - self.assertEqual(self.formatter._format_token(dt, "M"), "1") - - def test_day(self): - - dt = datetime(2013, 2, 1) - self.assertEqual(self.formatter._format_token(dt, "DDDD"), "032") - self.assertEqual(self.formatter._format_token(dt, "DDD"), "32") - self.assertEqual(self.formatter._format_token(dt, "DD"), "01") - self.assertEqual(self.formatter._format_token(dt, "D"), "1") - self.assertEqual(self.formatter._format_token(dt, "Do"), "1st") - - self.assertEqual(self.formatter._format_token(dt, "dddd"), "Friday") - self.assertEqual(self.formatter._format_token(dt, "ddd"), "Fri") - self.assertEqual(self.formatter._format_token(dt, "d"), "5") - - def test_hour(self): - - dt = datetime(2013, 1, 1, 2) - self.assertEqual(self.formatter._format_token(dt, "HH"), "02") - self.assertEqual(self.formatter._format_token(dt, "H"), "2") - - dt = datetime(2013, 1, 1, 13) - self.assertEqual(self.formatter._format_token(dt, "HH"), "13") - self.assertEqual(self.formatter._format_token(dt, "H"), "13") - - dt = datetime(2013, 1, 1, 2) - self.assertEqual(self.formatter._format_token(dt, "hh"), "02") - self.assertEqual(self.formatter._format_token(dt, "h"), "2") - - dt = datetime(2013, 1, 1, 13) - self.assertEqual(self.formatter._format_token(dt, "hh"), "01") - self.assertEqual(self.formatter._format_token(dt, "h"), "1") - - # test that 12-hour time converts to '12' at midnight - dt = datetime(2013, 1, 1, 0) - self.assertEqual(self.formatter._format_token(dt, "hh"), "12") - self.assertEqual(self.formatter._format_token(dt, "h"), "12") - - def test_minute(self): - - dt = datetime(2013, 1, 1, 0, 1) - self.assertEqual(self.formatter._format_token(dt, "mm"), "01") - self.assertEqual(self.formatter._format_token(dt, "m"), "1") - - def test_second(self): - - dt = datetime(2013, 1, 1, 0, 0, 1) - self.assertEqual(self.formatter._format_token(dt, "ss"), "01") - self.assertEqual(self.formatter._format_token(dt, "s"), "1") - - def test_sub_second(self): - - dt = datetime(2013, 1, 1, 0, 0, 0, 123456) - self.assertEqual(self.formatter._format_token(dt, "SSSSSS"), "123456") - self.assertEqual(self.formatter._format_token(dt, "SSSSS"), "12345") - self.assertEqual(self.formatter._format_token(dt, "SSSS"), "1234") - self.assertEqual(self.formatter._format_token(dt, "SSS"), "123") - self.assertEqual(self.formatter._format_token(dt, "SS"), "12") - self.assertEqual(self.formatter._format_token(dt, "S"), "1") - - dt = datetime(2013, 1, 1, 0, 0, 0, 2000) - self.assertEqual(self.formatter._format_token(dt, "SSSSSS"), "002000") - self.assertEqual(self.formatter._format_token(dt, "SSSSS"), "00200") - self.assertEqual(self.formatter._format_token(dt, "SSSS"), "0020") - self.assertEqual(self.formatter._format_token(dt, "SSS"), "002") - self.assertEqual(self.formatter._format_token(dt, "SS"), "00") - self.assertEqual(self.formatter._format_token(dt, "S"), "0") - - def test_timestamp(self): - - timestamp = time.time() - dt = datetime.utcfromtimestamp(timestamp) - self.assertEqual(self.formatter._format_token(dt, "X"), str(int(timestamp))) - - def test_timezone(self): - - dt = datetime.utcnow().replace(tzinfo=dateutil_tz.gettz("US/Pacific")) - - result = self.formatter._format_token(dt, "ZZ") - self.assertTrue(result == "-07:00" or result == "-08:00") - - result = self.formatter._format_token(dt, "Z") - self.assertTrue(result == "-0700" or result == "-0800") - - def test_timezone_formatter(self): - - for full_name in make_full_tz_list(): - # This test will fail if we use "now" as date as soon as we change from/to DST - dt = datetime(1986, 2, 14, tzinfo=pytz.timezone("UTC")).replace( - tzinfo=dateutil_tz.gettz(full_name) - ) - abbreviation = dt.tzname() - - result = self.formatter._format_token(dt, "ZZZ") - self.assertEqual(result, abbreviation) - - def test_am_pm(self): - - dt = datetime(2012, 1, 1, 11) - self.assertEqual(self.formatter._format_token(dt, "a"), "am") - self.assertEqual(self.formatter._format_token(dt, "A"), "AM") - - dt = datetime(2012, 1, 1, 13) - self.assertEqual(self.formatter._format_token(dt, "a"), "pm") - self.assertEqual(self.formatter._format_token(dt, "A"), "PM") - - def test_nonsense(self): - dt = datetime(2012, 1, 1, 11) - self.assertEqual(self.formatter._format_token(dt, None), None) - self.assertEqual(self.formatter._format_token(dt, "NONSENSE"), None) - - def test_escape(self): - - self.assertEqual( - self.formatter.format( - datetime(2015, 12, 10, 17, 9), "MMMM D, YYYY [at] h:mma" - ), - "December 10, 2015 at 5:09pm", - ) - - self.assertEqual( - self.formatter.format( - datetime(2015, 12, 10, 17, 9), "[MMMM] M D, YYYY [at] h:mma" - ), - "MMMM 12 10, 2015 at 5:09pm", - ) - - self.assertEqual( - self.formatter.format( - datetime(1990, 11, 25), - "[It happened on] MMMM Do [in the year] YYYY [a long time ago]", - ), - "It happened on November 25th in the year 1990 a long time ago", - ) - - self.assertEqual( - self.formatter.format( - datetime(1990, 11, 25), - "[It happened on] MMMM Do [in the][ year] YYYY [a long time ago]", - ), - "It happened on November 25th in the year 1990 a long time ago", - ) - - self.assertEqual( - self.formatter.format( - datetime(1, 1, 1), "[I'm][ entirely][ escaped,][ weee!]" - ), - "I'm entirely escaped, weee!", - ) - - # Special RegEx characters - self.assertEqual( - self.formatter.format( - datetime(2017, 12, 31, 2, 0), "MMM DD, YYYY |^${}().*+?<>-& h:mm A" - ), - "Dec 31, 2017 |^${}().*+?<>-& 2:00 AM", - ) - - # Escaping is atomic: brackets inside brackets are treated litterally - self.assertEqual(self.formatter.format(datetime(1, 1, 1), "[[[ ]]"), "[[ ]") diff --git a/tests/locales_tests.py.bak b/tests/locales_tests.py.bak deleted file mode 100644 index af205b435..000000000 --- a/tests/locales_tests.py.bak +++ /dev/null @@ -1,954 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from chai import Chai - -from arrow import arrow, locales - - -class LocaleValidationTests(Chai): - """Validate locales to ensure that translations are valid and complete""" - - def setUp(self): - super(LocaleValidationTests, self).setUp() - - self.locales = locales._locales - - def test_locale_validation(self): - - for _, locale_cls in self.locales.items(): - # 7 days + 1 spacer to allow for 1-indexing of months - self.assertEqual(len(locale_cls.day_names), 8) - self.assertTrue(locale_cls.day_names[0] == "") - # ensure that all string from index 1 onward are valid (not blank or None) - self.assertTrue(all(locale_cls.day_names[1:])) - - self.assertEqual(len(locale_cls.day_abbreviations), 8) - self.assertTrue(locale_cls.day_abbreviations[0] == "") - self.assertTrue(all(locale_cls.day_abbreviations[1:])) - - # 12 months + 1 spacer to allow for 1-indexing of months - self.assertEqual(len(locale_cls.month_names), 13) - self.assertTrue(locale_cls.month_names[0] == "") - self.assertTrue(all(locale_cls.month_names[1:])) - - self.assertEqual(len(locale_cls.month_abbreviations), 13) - self.assertTrue(locale_cls.month_abbreviations[0] == "") - self.assertTrue(all(locale_cls.month_abbreviations[1:])) - - self.assertTrue(len(locale_cls.names) > 0) - self.assertTrue(locale_cls.past is not None) - self.assertTrue(locale_cls.future is not None) - - -class ModuleTests(Chai): - def test_get_locale(self): - - mock_locales = self.mock(locales, "_locales") - mock_locale_cls = self.mock() - mock_locale = self.mock() - - self.expect(mock_locales.get).args("name").returns(mock_locale_cls) - self.expect(mock_locale_cls).returns(mock_locale) - - result = locales.get_locale("name") - - self.assertEqual(result, mock_locale) - - def test_locales(self): - - self.assertTrue(len(locales._locales) > 0) - - -class LocaleTests(Chai): - def setUp(self): - super(LocaleTests, self).setUp() - - self.locale = locales.EnglishLocale() - - def test_format_timeframe(self): - - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 hours") - self.assertEqual(self.locale._format_timeframe("hour", 0), "an hour") - - def test_format_relative_now(self): - - result = self.locale._format_relative("just now", "now", 0) - - self.assertEqual(result, "just now") - - def test_format_relative_past(self): - - result = self.locale._format_relative("an hour", "hour", 1) - - self.assertEqual(result, "in an hour") - - def test_format_relative_future(self): - - result = self.locale._format_relative("an hour", "hour", -1) - - self.assertEqual(result, "an hour ago") - - def test_ordinal_number(self): - self.assertEqual(self.locale.ordinal_number(0), "0th") - self.assertEqual(self.locale.ordinal_number(1), "1st") - self.assertEqual(self.locale.ordinal_number(2), "2nd") - self.assertEqual(self.locale.ordinal_number(3), "3rd") - self.assertEqual(self.locale.ordinal_number(4), "4th") - self.assertEqual(self.locale.ordinal_number(10), "10th") - self.assertEqual(self.locale.ordinal_number(11), "11th") - self.assertEqual(self.locale.ordinal_number(12), "12th") - self.assertEqual(self.locale.ordinal_number(13), "13th") - self.assertEqual(self.locale.ordinal_number(14), "14th") - self.assertEqual(self.locale.ordinal_number(21), "21st") - self.assertEqual(self.locale.ordinal_number(22), "22nd") - self.assertEqual(self.locale.ordinal_number(23), "23rd") - self.assertEqual(self.locale.ordinal_number(24), "24th") - - self.assertEqual(self.locale.ordinal_number(100), "100th") - self.assertEqual(self.locale.ordinal_number(101), "101st") - self.assertEqual(self.locale.ordinal_number(102), "102nd") - self.assertEqual(self.locale.ordinal_number(103), "103rd") - self.assertEqual(self.locale.ordinal_number(104), "104th") - self.assertEqual(self.locale.ordinal_number(110), "110th") - self.assertEqual(self.locale.ordinal_number(111), "111th") - self.assertEqual(self.locale.ordinal_number(112), "112th") - self.assertEqual(self.locale.ordinal_number(113), "113th") - self.assertEqual(self.locale.ordinal_number(114), "114th") - self.assertEqual(self.locale.ordinal_number(121), "121st") - self.assertEqual(self.locale.ordinal_number(122), "122nd") - self.assertEqual(self.locale.ordinal_number(123), "123rd") - self.assertEqual(self.locale.ordinal_number(124), "124th") - - def test_meridian_invalid_token(self): - self.assertEqual(self.locale.meridian(7, None), None) - self.assertEqual(self.locale.meridian(7, "B"), None) - self.assertEqual(self.locale.meridian(7, "NONSENSE"), None) - - -class EnglishLocaleTests(Chai): - def setUp(self): - super(EnglishLocaleTests, self).setUp() - - self.locale = locales.EnglishLocale() - - def test_describe(self): - self.assertEqual(self.locale.describe("now", only_distance=True), "instantly") - self.assertEqual(self.locale.describe("now", only_distance=False), "just now") - - -class ItalianLocalesTests(Chai): - def test_ordinal_number(self): - locale = locales.ItalianLocale() - - self.assertEqual(locale.ordinal_number(1), "1º") - - -class SpanishLocalesTests(Chai): - def test_ordinal_number(self): - locale = locales.SpanishLocale() - - self.assertEqual(locale.ordinal_number(1), "1º") - - def test_format_timeframe(self): - locale = locales.SpanishLocale() - self.assertEqual(locale._format_timeframe("now", 0), "ahora") - self.assertEqual(locale._format_timeframe("seconds", 1), "1 segundos") - self.assertEqual(locale._format_timeframe("seconds", 3), "3 segundos") - self.assertEqual(locale._format_timeframe("seconds", 30), "30 segundos") - self.assertEqual(locale._format_timeframe("minute", 1), "un minuto") - self.assertEqual(locale._format_timeframe("minutes", 4), "4 minutos") - self.assertEqual(locale._format_timeframe("minutes", 40), "40 minutos") - self.assertEqual(locale._format_timeframe("hour", 1), "una hora") - self.assertEqual(locale._format_timeframe("hours", 5), "5 horas") - self.assertEqual(locale._format_timeframe("hours", 23), "23 horas") - self.assertEqual(locale._format_timeframe("day", 1), "un día") - self.assertEqual(locale._format_timeframe("days", 6), "6 días") - self.assertEqual(locale._format_timeframe("days", 12), "12 días") - self.assertEqual(locale._format_timeframe("week", 1), "una semana") - self.assertEqual(locale._format_timeframe("weeks", 2), "2 semanas") - self.assertEqual(locale._format_timeframe("weeks", 3), "3 semanas") - self.assertEqual(locale._format_timeframe("month", 1), "un mes") - self.assertEqual(locale._format_timeframe("months", 7), "7 meses") - self.assertEqual(locale._format_timeframe("months", 11), "11 meses") - self.assertEqual(locale._format_timeframe("year", 1), "un año") - self.assertEqual(locale._format_timeframe("years", 8), "8 años") - self.assertEqual(locale._format_timeframe("years", 12), "12 años") - - self.assertEqual(locale._format_timeframe("now", 0), "ahora") - self.assertEqual(locale._format_timeframe("seconds", -1), "1 segundos") - self.assertEqual(locale._format_timeframe("seconds", -9), "9 segundos") - self.assertEqual(locale._format_timeframe("seconds", -12), "12 segundos") - self.assertEqual(locale._format_timeframe("minute", -1), "un minuto") - self.assertEqual(locale._format_timeframe("minutes", -2), "2 minutos") - self.assertEqual(locale._format_timeframe("minutes", -10), "10 minutos") - self.assertEqual(locale._format_timeframe("hour", -1), "una hora") - self.assertEqual(locale._format_timeframe("hours", -3), "3 horas") - self.assertEqual(locale._format_timeframe("hours", -11), "11 horas") - self.assertEqual(locale._format_timeframe("day", -1), "un día") - self.assertEqual(locale._format_timeframe("days", -2), "2 días") - self.assertEqual(locale._format_timeframe("days", -12), "12 días") - self.assertEqual(locale._format_timeframe("week", -1), "una semana") - self.assertEqual(locale._format_timeframe("weeks", -2), "2 semanas") - self.assertEqual(locale._format_timeframe("weeks", -3), "3 semanas") - self.assertEqual(locale._format_timeframe("month", -1), "un mes") - self.assertEqual(locale._format_timeframe("months", -3), "3 meses") - self.assertEqual(locale._format_timeframe("months", -13), "13 meses") - self.assertEqual(locale._format_timeframe("year", -1), "un año") - self.assertEqual(locale._format_timeframe("years", -4), "4 años") - self.assertEqual(locale._format_timeframe("years", -14), "14 años") - - -class FrenchLocalesTests(Chai): - def test_ordinal_number(self): - locale = locales.FrenchLocale() - - self.assertEqual(locale.ordinal_number(1), "1er") - self.assertEqual(locale.ordinal_number(2), "2e") - - -class RussianLocalesTests(Chai): - def test_plurals2(self): - - locale = locales.RussianLocale() - - self.assertEqual(locale._format_timeframe("hours", 0), "0 часов") - self.assertEqual(locale._format_timeframe("hours", 1), "1 час") - self.assertEqual(locale._format_timeframe("hours", 2), "2 часа") - self.assertEqual(locale._format_timeframe("hours", 4), "4 часа") - self.assertEqual(locale._format_timeframe("hours", 5), "5 часов") - self.assertEqual(locale._format_timeframe("hours", 21), "21 час") - self.assertEqual(locale._format_timeframe("hours", 22), "22 часа") - self.assertEqual(locale._format_timeframe("hours", 25), "25 часов") - - # feminine grammatical gender should be tested separately - self.assertEqual(locale._format_timeframe("minutes", 0), "0 минут") - self.assertEqual(locale._format_timeframe("minutes", 1), "1 минуту") - self.assertEqual(locale._format_timeframe("minutes", 2), "2 минуты") - self.assertEqual(locale._format_timeframe("minutes", 4), "4 минуты") - self.assertEqual(locale._format_timeframe("minutes", 5), "5 минут") - self.assertEqual(locale._format_timeframe("minutes", 21), "21 минуту") - self.assertEqual(locale._format_timeframe("minutes", 22), "22 минуты") - self.assertEqual(locale._format_timeframe("minutes", 25), "25 минут") - - -class PolishLocalesTests(Chai): - def test_plurals(self): - - locale = locales.PolishLocale() - - self.assertEqual(locale._format_timeframe("hours", 0), "0 godzin") - self.assertEqual(locale._format_timeframe("hours", 1), "1 godzin") - self.assertEqual(locale._format_timeframe("hours", 2), "2 godziny") - self.assertEqual(locale._format_timeframe("hours", 4), "4 godziny") - self.assertEqual(locale._format_timeframe("hours", 5), "5 godzin") - self.assertEqual(locale._format_timeframe("hours", 21), "21 godzin") - self.assertEqual(locale._format_timeframe("hours", 22), "22 godziny") - self.assertEqual(locale._format_timeframe("hours", 25), "25 godzin") - - -class IcelandicLocalesTests(Chai): - def setUp(self): - super(IcelandicLocalesTests, self).setUp() - - self.locale = locales.IcelandicLocale() - - def test_format_timeframe(self): - - self.assertEqual(self.locale._format_timeframe("minute", -1), "einni mínútu") - self.assertEqual(self.locale._format_timeframe("minute", 1), "eina mínútu") - - self.assertEqual(self.locale._format_timeframe("hours", -2), "2 tímum") - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 tíma") - self.assertEqual(self.locale._format_timeframe("now", 0), "rétt í þessu") - - -class MalayalamLocaleTests(Chai): - def setUp(self): - super(MalayalamLocaleTests, self).setUp() - - self.locale = locales.MalayalamLocale() - - def test_format_timeframe(self): - - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 മണിക്കൂർ") - self.assertEqual(self.locale._format_timeframe("hour", 0), "ഒരു മണിക്കൂർ") - - def test_format_relative_now(self): - - result = self.locale._format_relative("ഇപ്പോൾ", "now", 0) - - self.assertEqual(result, "ഇപ്പോൾ") - - def test_format_relative_past(self): - - result = self.locale._format_relative("ഒരു മണിക്കൂർ", "hour", 1) - self.assertEqual(result, "ഒരു മണിക്കൂർ ശേഷം") - - def test_format_relative_future(self): - - result = self.locale._format_relative("ഒരു മണിക്കൂർ", "hour", -1) - self.assertEqual(result, "ഒരു മണിക്കൂർ മുമ്പ്") - - -class HindiLocaleTests(Chai): - def setUp(self): - super(HindiLocaleTests, self).setUp() - - self.locale = locales.HindiLocale() - - def test_format_timeframe(self): - - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 घंटे") - self.assertEqual(self.locale._format_timeframe("hour", 0), "एक घंटा") - - def test_format_relative_now(self): - - result = self.locale._format_relative("अभी", "now", 0) - - self.assertEqual(result, "अभी") - - def test_format_relative_past(self): - - result = self.locale._format_relative("एक घंटा", "hour", 1) - self.assertEqual(result, "एक घंटा बाद") - - def test_format_relative_future(self): - - result = self.locale._format_relative("एक घंटा", "hour", -1) - self.assertEqual(result, "एक घंटा पहले") - - -class CzechLocaleTests(Chai): - def setUp(self): - super(CzechLocaleTests, self).setUp() - - self.locale = locales.CzechLocale() - - def test_format_timeframe(self): - - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 hodiny") - self.assertEqual(self.locale._format_timeframe("hours", 5), "5 hodin") - self.assertEqual(self.locale._format_timeframe("hour", 0), "0 hodin") - self.assertEqual(self.locale._format_timeframe("hours", -2), "2 hodinami") - self.assertEqual(self.locale._format_timeframe("hours", -5), "5 hodinami") - self.assertEqual(self.locale._format_timeframe("now", 0), "Teď") - - def test_format_relative_now(self): - - result = self.locale._format_relative("Teď", "now", 0) - self.assertEqual(result, "Teď") - - def test_format_relative_future(self): - - result = self.locale._format_relative("hodinu", "hour", 1) - self.assertEqual(result, "Za hodinu") - - def test_format_relative_past(self): - - result = self.locale._format_relative("hodinou", "hour", -1) - self.assertEqual(result, "Před hodinou") - - -class SlovakLocaleTests(Chai): - def setUp(self): - super(SlovakLocaleTests, self).setUp() - - self.locale = locales.SlovakLocale() - - def test_format_timeframe(self): - - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 hodiny") - self.assertEqual(self.locale._format_timeframe("hours", 5), "5 hodín") - self.assertEqual(self.locale._format_timeframe("hour", 0), "0 hodín") - self.assertEqual(self.locale._format_timeframe("hours", -2), "2 hodinami") - self.assertEqual(self.locale._format_timeframe("hours", -5), "5 hodinami") - self.assertEqual(self.locale._format_timeframe("now", 0), "Teraz") - - def test_format_relative_now(self): - - result = self.locale._format_relative("Teraz", "now", 0) - self.assertEqual(result, "Teraz") - - def test_format_relative_future(self): - - result = self.locale._format_relative("hodinu", "hour", 1) - self.assertEqual(result, "O hodinu") - - def test_format_relative_past(self): - - result = self.locale._format_relative("hodinou", "hour", -1) - self.assertEqual(result, "Pred hodinou") - - -class BulgarianLocaleTests(Chai): - def test_plurals2(self): - - locale = locales.BulgarianLocale() - - self.assertEqual(locale._format_timeframe("hours", 0), "0 часа") - self.assertEqual(locale._format_timeframe("hours", 1), "1 час") - self.assertEqual(locale._format_timeframe("hours", 2), "2 часа") - self.assertEqual(locale._format_timeframe("hours", 4), "4 часа") - self.assertEqual(locale._format_timeframe("hours", 5), "5 часа") - self.assertEqual(locale._format_timeframe("hours", 21), "21 час") - self.assertEqual(locale._format_timeframe("hours", 22), "22 часа") - self.assertEqual(locale._format_timeframe("hours", 25), "25 часа") - - # feminine grammatical gender should be tested separately - self.assertEqual(locale._format_timeframe("minutes", 0), "0 минути") - self.assertEqual(locale._format_timeframe("minutes", 1), "1 минута") - self.assertEqual(locale._format_timeframe("minutes", 2), "2 минути") - self.assertEqual(locale._format_timeframe("minutes", 4), "4 минути") - self.assertEqual(locale._format_timeframe("minutes", 5), "5 минути") - self.assertEqual(locale._format_timeframe("minutes", 21), "21 минута") - self.assertEqual(locale._format_timeframe("minutes", 22), "22 минути") - self.assertEqual(locale._format_timeframe("minutes", 25), "25 минути") - - -class MacedonianLocaleTests(Chai): - def test_plurals_mk(self): - - locale = locales.MacedonianLocale() - - # time - self.assertEqual(locale._format_relative("сега", "now", 0), "сега") - - # Hours - self.assertEqual(locale._format_timeframe("hours", 0), "0 саати") - self.assertEqual(locale._format_timeframe("hours", 1), "1 саат") - self.assertEqual(locale._format_timeframe("hours", 2), "2 саати") - self.assertEqual(locale._format_timeframe("hours", 4), "4 саати") - self.assertEqual(locale._format_timeframe("hours", 5), "5 саати") - self.assertEqual(locale._format_timeframe("hours", 21), "21 саат") - self.assertEqual(locale._format_timeframe("hours", 22), "22 саати") - self.assertEqual(locale._format_timeframe("hours", 25), "25 саати") - - # Minutes - self.assertEqual(locale._format_timeframe("minutes", 0), "0 минути") - self.assertEqual(locale._format_timeframe("minutes", 1), "1 минута") - self.assertEqual(locale._format_timeframe("minutes", 2), "2 минути") - self.assertEqual(locale._format_timeframe("minutes", 4), "4 минути") - self.assertEqual(locale._format_timeframe("minutes", 5), "5 минути") - self.assertEqual(locale._format_timeframe("minutes", 21), "21 минута") - self.assertEqual(locale._format_timeframe("minutes", 22), "22 минути") - self.assertEqual(locale._format_timeframe("minutes", 25), "25 минути") - - -class HebrewLocaleTests(Chai): - def test_couple_of_timeframe(self): - locale = locales.HebrewLocale() - - self.assertEqual(locale._format_timeframe("hours", 2), "שעתיים") - self.assertEqual(locale._format_timeframe("months", 2), "חודשיים") - self.assertEqual(locale._format_timeframe("days", 2), "יומיים") - self.assertEqual(locale._format_timeframe("years", 2), "שנתיים") - - self.assertEqual(locale._format_timeframe("hours", 3), "3 שעות") - self.assertEqual(locale._format_timeframe("months", 4), "4 חודשים") - self.assertEqual(locale._format_timeframe("days", 3), "3 ימים") - self.assertEqual(locale._format_timeframe("years", 5), "5 שנים") - - -class MarathiLocaleTests(Chai): - def setUp(self): - super(MarathiLocaleTests, self).setUp() - - self.locale = locales.MarathiLocale() - - def test_dateCoreFunctionality(self): - dt = arrow.Arrow(2015, 4, 11, 17, 30, 00) - self.assertEqual(self.locale.month_name(dt.month), "एप्रिल") - self.assertEqual(self.locale.month_abbreviation(dt.month), "एप्रि") - self.assertEqual(self.locale.day_name(dt.isoweekday()), "शनिवार") - self.assertEqual(self.locale.day_abbreviation(dt.isoweekday()), "शनि") - - def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 तास") - self.assertEqual(self.locale._format_timeframe("hour", 0), "एक तास") - - def test_format_relative_now(self): - result = self.locale._format_relative("सद्य", "now", 0) - self.assertEqual(result, "सद्य") - - def test_format_relative_past(self): - result = self.locale._format_relative("एक तास", "hour", 1) - self.assertEqual(result, "एक तास नंतर") - - def test_format_relative_future(self): - result = self.locale._format_relative("एक तास", "hour", -1) - self.assertEqual(result, "एक तास आधी") - - # Not currently implemented - def test_ordinal_number(self): - self.assertEqual(self.locale.ordinal_number(1), "1") - - -class FinnishLocaleTests(Chai): - def setUp(self): - super(FinnishLocaleTests, self).setUp() - - self.locale = locales.FinnishLocale() - - def test_format_timeframe(self): - self.assertEqual( - self.locale._format_timeframe("hours", 2), ("2 tuntia", "2 tunnin") - ) - self.assertEqual(self.locale._format_timeframe("hour", 0), ("tunti", "tunnin")) - - def test_format_relative_now(self): - result = self.locale._format_relative(["juuri nyt", "juuri nyt"], "now", 0) - self.assertEqual(result, "juuri nyt") - - def test_format_relative_past(self): - result = self.locale._format_relative(["tunti", "tunnin"], "hour", 1) - self.assertEqual(result, "tunnin kuluttua") - - def test_format_relative_future(self): - result = self.locale._format_relative(["tunti", "tunnin"], "hour", -1) - self.assertEqual(result, "tunti sitten") - - def test_ordinal_number(self): - self.assertEqual(self.locale.ordinal_number(1), "1.") - - -class GermanLocaleTests(Chai): - def setUp(self): - super(GermanLocaleTests, self).setUp() - - self.locale = locales.GermanLocale() - - def test_ordinal_number(self): - self.assertEqual(self.locale.ordinal_number(1), "1.") - - def test_define(self): - self.assertEqual( - self.locale.describe("minute", only_distance=True), "eine Minute" - ) - self.assertEqual( - self.locale.describe("minute", only_distance=False), "in einer Minute" - ) - self.assertEqual( - self.locale.describe("hour", only_distance=True), "eine Stunde" - ) - self.assertEqual( - self.locale.describe("hour", only_distance=False), "in einer Stunde" - ) - self.assertEqual(self.locale.describe("day", only_distance=True), "ein Tag") - self.assertEqual( - self.locale.describe("day", only_distance=False), "in einem Tag" - ) - self.assertEqual(self.locale.describe("month", only_distance=True), "ein Monat") - self.assertEqual( - self.locale.describe("month", only_distance=False), "in einem Monat" - ) - self.assertEqual(self.locale.describe("year", only_distance=True), "ein Jahr") - self.assertEqual( - self.locale.describe("year", only_distance=False), "in einem Jahr" - ) - - -class HungarianLocaleTests(Chai): - def setUp(self): - super(HungarianLocaleTests, self).setUp() - - self.locale = locales.HungarianLocale() - - def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 óra") - self.assertEqual(self.locale._format_timeframe("hour", 0), "egy órával") - self.assertEqual(self.locale._format_timeframe("hours", -2), "2 órával") - self.assertEqual(self.locale._format_timeframe("now", 0), "éppen most") - - -class EsperantoLocaleTests(Chai): - def setUp(self): - super(EsperantoLocaleTests, self).setUp() - - self.locale = locales.EsperantoLocale() - - def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 horoj") - self.assertEqual(self.locale._format_timeframe("hour", 0), "un horo") - self.assertEqual(self.locale._format_timeframe("hours", -2), "2 horoj") - self.assertEqual(self.locale._format_timeframe("now", 0), "nun") - - def test_ordinal_number(self): - self.assertEqual(self.locale.ordinal_number(1), "1a") - - -class ThaiLocaleTests(Chai): - def setUp(self): - super(ThaiLocaleTests, self).setUp() - - self.locale = locales.ThaiLocale() - - def test_year_full(self): - self.assertEqual(self.locale.year_full(2015), "2558") - - def test_year_abbreviation(self): - self.assertEqual(self.locale.year_abbreviation(2015), "58") - - def test_format_relative_now(self): - result = self.locale._format_relative("ขณะนี้", "now", 0) - self.assertEqual(result, "ขณะนี้") - - def test_format_relative_past(self): - result = self.locale._format_relative("1 ชั่วโมง", "hour", 1) - self.assertEqual(result, "ในอีก 1 ชั่วโมง") - result = self.locale._format_relative("{0} ชั่วโมง", "hours", 2) - self.assertEqual(result, "ในอีก {0} ชั่วโมง") - result = self.locale._format_relative("ไม่กี่วินาที", "seconds", 42) - self.assertEqual(result, "ในอีกไม่กี่วินาที") - - def test_format_relative_future(self): - result = self.locale._format_relative("1 ชั่วโมง", "hour", -1) - self.assertEqual(result, "1 ชั่วโมง ที่ผ่านมา") - - -class BengaliLocaleTests(Chai): - def setUp(self): - super(BengaliLocaleTests, self).setUp() - - self.locale = locales.BengaliLocale() - - def test_ordinal_number(self): - result0 = self.locale._ordinal_number(0) - result1 = self.locale._ordinal_number(1) - result3 = self.locale._ordinal_number(3) - result4 = self.locale._ordinal_number(4) - result5 = self.locale._ordinal_number(5) - result6 = self.locale._ordinal_number(6) - result10 = self.locale._ordinal_number(10) - result11 = self.locale._ordinal_number(11) - result42 = self.locale._ordinal_number(42) - self.assertEqual(result0, "0তম") - self.assertEqual(result1, "1ম") - self.assertEqual(result3, "3য়") - self.assertEqual(result4, "4র্থ") - self.assertEqual(result5, "5ম") - self.assertEqual(result6, "6ষ্ঠ") - self.assertEqual(result10, "10ম") - self.assertEqual(result11, "11তম") - self.assertEqual(result42, "42তম") - self.assertEqual(self.locale._ordinal_number(-1), None) - - -class SwissLocaleTests(Chai): - def setUp(self): - super(SwissLocaleTests, self).setUp() - - self.locale = locales.SwissLocale() - - def test_ordinal_number(self): - dt = arrow.Arrow(2015, 4, 11, 17, 30, 00) - - self.assertEqual(self.locale._format_timeframe("minute", 1), "einer Minute") - self.assertEqual(self.locale._format_timeframe("hour", 1), "einer Stunde") - self.assertEqual(self.locale.day_abbreviation(dt.isoweekday()), "Sa") - - -class RomanianLocaleTests(Chai): - def setUp(self): - super(RomanianLocaleTests, self).setUp() - - self.locale = locales.RomanianLocale() - - def test_timeframes(self): - - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 ore") - self.assertEqual(self.locale._format_timeframe("months", 2), "2 luni") - - self.assertEqual(self.locale._format_timeframe("days", 2), "2 zile") - self.assertEqual(self.locale._format_timeframe("years", 2), "2 ani") - - self.assertEqual(self.locale._format_timeframe("hours", 3), "3 ore") - self.assertEqual(self.locale._format_timeframe("months", 4), "4 luni") - self.assertEqual(self.locale._format_timeframe("days", 3), "3 zile") - self.assertEqual(self.locale._format_timeframe("years", 5), "5 ani") - - def test_relative_timeframes(self): - self.assertEqual(self.locale._format_relative("acum", "now", 0), "acum") - self.assertEqual( - self.locale._format_relative("o oră", "hour", 1), "peste o oră" - ) - self.assertEqual( - self.locale._format_relative("o oră", "hour", -1), "o oră în urmă" - ) - self.assertEqual( - self.locale._format_relative("un minut", "minute", 1), "peste un minut" - ) - self.assertEqual( - self.locale._format_relative("un minut", "minute", -1), "un minut în urmă" - ) - self.assertEqual( - self.locale._format_relative("câteva secunde", "seconds", -1), - "câteva secunde în urmă", - ) - self.assertEqual( - self.locale._format_relative("câteva secunde", "seconds", 1), - "peste câteva secunde", - ) - self.assertEqual( - self.locale._format_relative("o zi", "day", -1), "o zi în urmă" - ) - self.assertEqual(self.locale._format_relative("o zi", "day", 1), "peste o zi") - - -class ArabicLocalesTest(Chai): - def setUp(self): - super(ArabicLocalesTest, self).setUp() - - self.locale = locales.ArabicLocale() - - def test_timeframes(self): - - # single - self.assertEqual(self.locale._format_timeframe("minute", 1), "دقيقة") - self.assertEqual(self.locale._format_timeframe("hour", 1), "ساعة") - self.assertEqual(self.locale._format_timeframe("day", 1), "يوم") - self.assertEqual(self.locale._format_timeframe("month", 1), "شهر") - self.assertEqual(self.locale._format_timeframe("year", 1), "سنة") - - # double - self.assertEqual(self.locale._format_timeframe("minutes", 2), "دقيقتين") - self.assertEqual(self.locale._format_timeframe("hours", 2), "ساعتين") - self.assertEqual(self.locale._format_timeframe("days", 2), "يومين") - self.assertEqual(self.locale._format_timeframe("months", 2), "شهرين") - self.assertEqual(self.locale._format_timeframe("years", 2), "سنتين") - - # up to ten - self.assertEqual(self.locale._format_timeframe("minutes", 3), "3 دقائق") - self.assertEqual(self.locale._format_timeframe("hours", 4), "4 ساعات") - self.assertEqual(self.locale._format_timeframe("days", 5), "5 أيام") - self.assertEqual(self.locale._format_timeframe("months", 6), "6 أشهر") - self.assertEqual(self.locale._format_timeframe("years", 10), "10 سنوات") - - # more than ten - self.assertEqual(self.locale._format_timeframe("minutes", 11), "11 دقيقة") - self.assertEqual(self.locale._format_timeframe("hours", 19), "19 ساعة") - self.assertEqual(self.locale._format_timeframe("months", 24), "24 شهر") - self.assertEqual(self.locale._format_timeframe("days", 50), "50 يوم") - self.assertEqual(self.locale._format_timeframe("years", 115), "115 سنة") - - -class NepaliLocaleTests(Chai): - def setUp(self): - super(NepaliLocaleTests, self).setUp() - - self.locale = locales.NepaliLocale() - - def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("hours", 3), "3 घण्टा") - self.assertEqual(self.locale._format_timeframe("hour", 0), "एक घण्टा") - - def test_format_relative_now(self): - result = self.locale._format_relative("अहिले", "now", 0) - self.assertEqual(result, "अहिले") - - def test_format_relative_future(self): - result = self.locale._format_relative("एक घण्टा", "hour", 1) - self.assertEqual(result, "एक घण्टा पछी") - - def test_format_relative_past(self): - result = self.locale._format_relative("एक घण्टा", "hour", -1) - self.assertEqual(result, "एक घण्टा पहिले") - - -class IndonesianLocaleTests(Chai): - def setUp(self): - super(IndonesianLocaleTests, self).setUp() - - self.locale = locales.IndonesianLocale() - - def test_timeframes(self): - self.assertEqual(self.locale._format_timeframe("hours", 2), "2 jam") - self.assertEqual(self.locale._format_timeframe("months", 2), "2 bulan") - - self.assertEqual(self.locale._format_timeframe("days", 2), "2 hari") - self.assertEqual(self.locale._format_timeframe("years", 2), "2 tahun") - - self.assertEqual(self.locale._format_timeframe("hours", 3), "3 jam") - self.assertEqual(self.locale._format_timeframe("months", 4), "4 bulan") - self.assertEqual(self.locale._format_timeframe("days", 3), "3 hari") - self.assertEqual(self.locale._format_timeframe("years", 5), "5 tahun") - - def test_format_relative_now(self): - self.assertEqual( - self.locale._format_relative("baru saja", "now", 0), "baru saja" - ) - - def test_format_relative_past(self): - self.assertEqual( - self.locale._format_relative("1 jam", "hour", 1), "dalam 1 jam" - ) - self.assertEqual( - self.locale._format_relative("1 detik", "seconds", 1), "dalam 1 detik" - ) - - def test_format_relative_future(self): - self.assertEqual( - self.locale._format_relative("1 jam", "hour", -1), "1 jam yang lalu" - ) - - -class TagalogLocaleTests(Chai): - def setUp(self): - super(TagalogLocaleTests, self).setUp() - - self.locale = locales.TagalogLocale() - - def test_format_timeframe(self): - - self.assertEqual(self.locale._format_timeframe("minute", 1), "isang minuto") - self.assertEqual(self.locale._format_timeframe("hour", 1), "isang oras") - self.assertEqual(self.locale._format_timeframe("month", 1), "isang buwan") - self.assertEqual(self.locale._format_timeframe("year", 1), "isang taon") - - self.assertEqual(self.locale._format_timeframe("seconds", 2), "2 segundo") - self.assertEqual(self.locale._format_timeframe("minutes", 3), "3 minuto") - self.assertEqual(self.locale._format_timeframe("hours", 4), "4 oras") - self.assertEqual(self.locale._format_timeframe("months", 5), "5 buwan") - self.assertEqual(self.locale._format_timeframe("years", 6), "6 taon") - - def test_format_relative_now(self): - self.assertEqual( - self.locale._format_relative("ngayon lang", "now", 0), "ngayon lang" - ) - - def test_format_relative_past(self): - self.assertEqual( - self.locale._format_relative("2 oras", "hour", 2), "2 oras mula ngayon" - ) - - def test_format_relative_future(self): - self.assertEqual( - self.locale._format_relative("3 oras", "hour", -3), "nakaraang 3 oras" - ) - - def test_ordinal_number(self): - self.assertEqual(self.locale.ordinal_number(0), "ika-0") - self.assertEqual(self.locale.ordinal_number(1), "ika-1") - self.assertEqual(self.locale.ordinal_number(2), "ika-2") - self.assertEqual(self.locale.ordinal_number(3), "ika-3") - self.assertEqual(self.locale.ordinal_number(10), "ika-10") - self.assertEqual(self.locale.ordinal_number(23), "ika-23") - self.assertEqual(self.locale.ordinal_number(100), "ika-100") - self.assertEqual(self.locale.ordinal_number(103), "ika-103") - self.assertEqual(self.locale.ordinal_number(114), "ika-114") - - -class EstonianLocaleTests(Chai): - def setUp(self): - super(EstonianLocaleTests, self).setUp() - - self.locale = locales.EstonianLocale() - - def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("now", 0), "just nüüd") - self.assertEqual(self.locale._format_timeframe("second", 1), "ühe sekundi") - self.assertEqual(self.locale._format_timeframe("seconds", 3), "3 sekundi") - self.assertEqual(self.locale._format_timeframe("seconds", 30), "30 sekundi") - self.assertEqual(self.locale._format_timeframe("minute", 1), "ühe minuti") - self.assertEqual(self.locale._format_timeframe("minutes", 4), "4 minuti") - self.assertEqual(self.locale._format_timeframe("minutes", 40), "40 minuti") - self.assertEqual(self.locale._format_timeframe("hour", 1), "tunni aja") - self.assertEqual(self.locale._format_timeframe("hours", 5), "5 tunni") - self.assertEqual(self.locale._format_timeframe("hours", 23), "23 tunni") - self.assertEqual(self.locale._format_timeframe("day", 1), "ühe päeva") - self.assertEqual(self.locale._format_timeframe("days", 6), "6 päeva") - self.assertEqual(self.locale._format_timeframe("days", 12), "12 päeva") - self.assertEqual(self.locale._format_timeframe("month", 1), "ühe kuu") - self.assertEqual(self.locale._format_timeframe("months", 7), "7 kuu") - self.assertEqual(self.locale._format_timeframe("months", 11), "11 kuu") - self.assertEqual(self.locale._format_timeframe("year", 1), "ühe aasta") - self.assertEqual(self.locale._format_timeframe("years", 8), "8 aasta") - self.assertEqual(self.locale._format_timeframe("years", 12), "12 aasta") - - self.assertEqual(self.locale._format_timeframe("now", 0), "just nüüd") - self.assertEqual(self.locale._format_timeframe("second", -1), "üks sekund") - self.assertEqual(self.locale._format_timeframe("seconds", -9), "9 sekundit") - self.assertEqual(self.locale._format_timeframe("seconds", -12), "12 sekundit") - self.assertEqual(self.locale._format_timeframe("minute", -1), "üks minut") - self.assertEqual(self.locale._format_timeframe("minutes", -2), "2 minutit") - self.assertEqual(self.locale._format_timeframe("minutes", -10), "10 minutit") - self.assertEqual(self.locale._format_timeframe("hour", -1), "tund aega") - self.assertEqual(self.locale._format_timeframe("hours", -3), "3 tundi") - self.assertEqual(self.locale._format_timeframe("hours", -11), "11 tundi") - self.assertEqual(self.locale._format_timeframe("day", -1), "üks päev") - self.assertEqual(self.locale._format_timeframe("days", -2), "2 päeva") - self.assertEqual(self.locale._format_timeframe("days", -12), "12 päeva") - self.assertEqual(self.locale._format_timeframe("month", -1), "üks kuu") - self.assertEqual(self.locale._format_timeframe("months", -3), "3 kuud") - self.assertEqual(self.locale._format_timeframe("months", -13), "13 kuud") - self.assertEqual(self.locale._format_timeframe("year", -1), "üks aasta") - self.assertEqual(self.locale._format_timeframe("years", -4), "4 aastat") - self.assertEqual(self.locale._format_timeframe("years", -14), "14 aastat") - - -class PortugueseLocaleTests(Chai): - def setUp(self): - super(PortugueseLocaleTests, self).setUp() - - self.locale = locales.PortugueseLocale() - - def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("now", 0), "agora") - self.assertEqual(self.locale._format_timeframe("second", 1), "um segundo") - self.assertEqual(self.locale._format_timeframe("seconds", 30), "30 segundos") - self.assertEqual(self.locale._format_timeframe("minute", 1), "um minuto") - self.assertEqual(self.locale._format_timeframe("minutes", 40), "40 minutos") - self.assertEqual(self.locale._format_timeframe("hour", 1), "uma hora") - self.assertEqual(self.locale._format_timeframe("hours", 23), "23 horas") - self.assertEqual(self.locale._format_timeframe("day", 1), "um dia") - self.assertEqual(self.locale._format_timeframe("days", 12), "12 dias") - self.assertEqual(self.locale._format_timeframe("month", 1), "um mês") - self.assertEqual(self.locale._format_timeframe("months", 11), "11 meses") - self.assertEqual(self.locale._format_timeframe("year", 1), "um ano") - self.assertEqual(self.locale._format_timeframe("years", 12), "12 anos") - - -class BrazilianLocaleTests(Chai): - def setUp(self): - super(BrazilianLocaleTests, self).setUp() - - self.locale = locales.BrazilianPortugueseLocale() - - def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("now", 0), "agora") - self.assertEqual(self.locale._format_timeframe("second", 1), "um segundo") - self.assertEqual(self.locale._format_timeframe("seconds", 30), "30 segundos") - self.assertEqual(self.locale._format_timeframe("minute", 1), "um minuto") - self.assertEqual(self.locale._format_timeframe("minutes", 40), "40 minutos") - self.assertEqual(self.locale._format_timeframe("hour", 1), "uma hora") - self.assertEqual(self.locale._format_timeframe("hours", 23), "23 horas") - self.assertEqual(self.locale._format_timeframe("day", 1), "um dia") - self.assertEqual(self.locale._format_timeframe("days", 12), "12 dias") - self.assertEqual(self.locale._format_timeframe("month", 1), "um mês") - self.assertEqual(self.locale._format_timeframe("months", 11), "11 meses") - self.assertEqual(self.locale._format_timeframe("year", 1), "um ano") - self.assertEqual(self.locale._format_timeframe("years", 12), "12 anos") - - -class HongKongLocaleTests(Chai): - def setUp(self): - super(HongKongLocaleTests, self).setUp() - - self.locale = locales.HongKongLocale() - - def test_format_timeframe(self): - self.assertEqual(self.locale._format_timeframe("now", 0), "剛才") - self.assertEqual(self.locale._format_timeframe("second", 1), "1秒") - self.assertEqual(self.locale._format_timeframe("seconds", 30), "30秒") - self.assertEqual(self.locale._format_timeframe("minute", 1), "1分鐘") - self.assertEqual(self.locale._format_timeframe("minutes", 40), "40分鐘") - self.assertEqual(self.locale._format_timeframe("hour", 1), "1小時") - self.assertEqual(self.locale._format_timeframe("hours", 23), "23小時") - self.assertEqual(self.locale._format_timeframe("day", 1), "1天") - self.assertEqual(self.locale._format_timeframe("days", 12), "12天") - self.assertEqual(self.locale._format_timeframe("week", 1), "1星期") - self.assertEqual(self.locale._format_timeframe("weeks", 38), "38星期") - self.assertEqual(self.locale._format_timeframe("month", 1), "1個月") - self.assertEqual(self.locale._format_timeframe("months", 11), "11個月") - self.assertEqual(self.locale._format_timeframe("year", 1), "1年") - self.assertEqual(self.locale._format_timeframe("years", 12), "12年") diff --git a/tests/parser_tests.py b/tests/parser_tests.py deleted file mode 100644 index c72da044b..000000000 --- a/tests/parser_tests.py +++ /dev/null @@ -1,1629 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import calendar -import os -import time -from datetime import datetime - -from chai import Chai -from dateutil import tz - -from arrow import parser -from arrow.constants import MAX_TIMESTAMP_US -from arrow.parser import DateTimeParser, ParserError, ParserMatchError - -from .utils import make_full_tz_list - - -class DateTimeParserTests(Chai): - def setUp(self): - super(DateTimeParserTests, self).setUp() - - self.parser = parser.DateTimeParser() - - def test_parse_multiformat(self): - - mock_datetime = self.mock() - - self.expect(self.parser.parse).args("str", "fmt_a").raises(ParserMatchError) - self.expect(self.parser.parse).args("str", "fmt_b").returns(mock_datetime) - - result = self.parser._parse_multiformat("str", ["fmt_a", "fmt_b"]) - - self.assertEqual(result, mock_datetime) - - def test_parse_multiformat_all_fail(self): - - self.expect(self.parser.parse).args("str", "fmt_a").raises(ParserMatchError) - self.expect(self.parser.parse).args("str", "fmt_b").raises(ParserMatchError) - - with self.assertRaises(ParserError): - self.parser._parse_multiformat("str", ["fmt_a", "fmt_b"]) - - def test_parse_multiformat_unself_expected_fail(self): - class UnselfExpectedError(Exception): - pass - - self.expect(self.parser.parse).args("str", "fmt_a").raises(UnselfExpectedError) - - with self.assertRaises(UnselfExpectedError): - self.parser._parse_multiformat("str", ["fmt_a", "fmt_b"]) - - def test_parse_token_nonsense(self): - parts = {} - self.parser._parse_token("NONSENSE", "1900", parts) - self.assertEqual(parts, {}) - - def test_parse_token_invalid_meridians(self): - parts = {} - self.parser._parse_token("A", "a..m", parts) - self.assertEqual(parts, {}) - self.parser._parse_token("a", "p..m", parts) - self.assertEqual(parts, {}) - - def test_parser_no_caching(self): - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( - 100 - ) - self.parser = parser.DateTimeParser(cache_size=0) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - - def test_parser_1_line_caching(self): - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( - 1 - ) - self.parser = parser.DateTimeParser(cache_size=1) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_b").times( - 1 - ) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - self.parser._generate_pattern_re("fmt_b") - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( - 1 - ) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - - def test_parser_multiple_line_caching(self): - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( - 1 - ) - self.parser = parser.DateTimeParser(cache_size=2) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_b").times( - 1 - ) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - self.parser._generate_pattern_re("fmt_b") - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( - 0 - ) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - - def test_YY_and_YYYY_format_list(self): - - self.assertEqual( - self.parser.parse("15/01/19", ["DD/MM/YY", "DD/MM/YYYY"]), - datetime(2019, 1, 15), - ) - - # Regression test for issue #580 - self.assertEqual( - self.parser.parse("15/01/2019", ["DD/MM/YY", "DD/MM/YYYY"]), - datetime(2019, 1, 15), - ) - - self.assertEqual( - self.parser.parse( - "15/01/2019T04:05:06.789120Z", - ["D/M/YYThh:mm:ss.SZ", "D/M/YYYYThh:mm:ss.SZ"], - ), - datetime(2019, 1, 15, 4, 5, 6, 789120, tzinfo=tz.tzutc()), - ) - - # regression test for issue #447 - def test_timestamp_format_list(self): - # should not match on the "X" token - self.assertEqual( - self.parser.parse( - "15 Jul 2000", - ["MM/DD/YYYY", "YYYY-MM-DD", "X", "DD-MMMM-YYYY", "D MMM YYYY"], - ), - datetime(2000, 7, 15), - ) - - with self.assertRaises(ParserError): - self.parser.parse("15 Jul", "X") - - -class DateTimeParserParseTests(Chai): - def setUp(self): - super(DateTimeParserParseTests, self).setUp() - - self.parser = parser.DateTimeParser() - - def test_parse_list(self): - - self.expect(self.parser._parse_multiformat).args( - "str", ["fmt_a", "fmt_b"] - ).returns("result") - - result = self.parser.parse("str", ["fmt_a", "fmt_b"]) - - self.assertEqual(result, "result") - - def test_parse_unrecognized_token(self): - - mock_input_re_map = self.mock(self.parser, "_input_re_map") - - self.expect(mock_input_re_map.__getitem__).args("YYYY").raises(KeyError) - - with self.assertRaises(parser.ParserError): - self.parser.parse("2013-01-01", "YYYY-MM-DD") - - def test_parse_parse_no_match(self): - - with self.assertRaises(ParserError): - self.parser.parse("01-01", "YYYY-MM-DD") - - def test_parse_separators(self): - - with self.assertRaises(ParserError): - self.parser.parse("1403549231", "YYYY-MM-DD") - - def test_parse_numbers(self): - - self.expected = datetime(2012, 1, 1, 12, 5, 10) - self.assertEqual( - self.parser.parse("2012-01-01 12:05:10", "YYYY-MM-DD HH:mm:ss"), - self.expected, - ) - - def test_parse_year_two_digit(self): - - self.expected = datetime(1979, 1, 1, 12, 5, 10) - self.assertEqual( - self.parser.parse("79-01-01 12:05:10", "YY-MM-DD HH:mm:ss"), self.expected - ) - - def test_parse_timestamp(self): - - tz_utc = tz.tzutc() - int_timestamp = int(time.time()) - self.expected = datetime.fromtimestamp(int_timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:d}".format(int_timestamp), "X"), self.expected - ) - - float_timestamp = time.time() - self.expected = datetime.fromtimestamp(float_timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:f}".format(float_timestamp), "X"), self.expected - ) - - # test handling of ns timestamp (arrow will round to 6 digits regardless) - self.expected = datetime.fromtimestamp(float_timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:f}123".format(float_timestamp), "X"), self.expected - ) - - # test ps timestamp (arrow will round to 6 digits regardless) - self.expected = datetime.fromtimestamp(float_timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:f}123456".format(float_timestamp), "X"), self.expected - ) - - # NOTE: negative timestamps cannot be handled by datetime on Window - # Must use timedelta to handle them. ref: https://stackoverflow.com/questions/36179914 - if os.name != "nt": - # regression test for issue #662 - negative_int_timestamp = -int_timestamp - self.expected = datetime.fromtimestamp(negative_int_timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:d}".format(negative_int_timestamp), "X"), - self.expected, - ) - - negative_float_timestamp = -float_timestamp - self.expected = datetime.fromtimestamp(negative_float_timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:f}".format(negative_float_timestamp), "X"), - self.expected, - ) - - # NOTE: timestamps cannot be parsed from natural language strings (by removing the ^...$) because it will - # break cases like "15 Jul 2000" and a format list (see issue #447) - with self.assertRaises(ParserError): - natural_lang_string = "Meet me at {} at the restaurant.".format( - float_timestamp - ) - self.parser.parse(natural_lang_string, "X") - - with self.assertRaises(ParserError): - self.parser.parse("1565982019.", "X") - - with self.assertRaises(ParserError): - self.parser.parse(".1565982019", "X") - - def test_parse_expanded_timestamp(self): - # test expanded timestamps that include milliseconds - # and microseconds as multiples rather than decimals - # requested in issue #357 - - tz_utc = tz.tzutc() - timestamp = 1569982581.413132 - timestamp_milli = int(round(timestamp * 1000)) - timestamp_micro = int(round(timestamp * 1000000)) - - # "x" token should parse integer timestamps below MAX_TIMESTAMP normally - self.expected = datetime.fromtimestamp(int(timestamp), tz=tz_utc) - self.assertEqual( - self.parser.parse("{:d}".format(int(timestamp)), "x"), self.expected - ) - - self.expected = datetime.fromtimestamp(round(timestamp, 3), tz=tz_utc) - self.assertEqual( - self.parser.parse("{:d}".format(timestamp_milli), "x"), self.expected - ) - - self.expected = datetime.fromtimestamp(timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:d}".format(timestamp_micro), "x"), self.expected - ) - - # anything above max µs timestamp should fail - with self.assertRaises(ValueError): - self.parser.parse("{:d}".format(int(MAX_TIMESTAMP_US) + 1), "x") - - # floats are not allowed with the "x" token - with self.assertRaises(ParserMatchError): - self.parser.parse("{:f}".format(timestamp), "x") - - def test_parse_names(self): - - self.expected = datetime(2012, 1, 1) - - self.assertEqual( - self.parser.parse("January 1, 2012", "MMMM D, YYYY"), self.expected - ) - self.assertEqual(self.parser.parse("Jan 1, 2012", "MMM D, YYYY"), self.expected) - - def test_parse_pm(self): - - self.expected = datetime(1, 1, 1, 13, 0, 0) - self.assertEqual(self.parser.parse("1 pm", "H a"), self.expected) - self.assertEqual(self.parser.parse("1 pm", "h a"), self.expected) - - self.expected = datetime(1, 1, 1, 1, 0, 0) - self.assertEqual(self.parser.parse("1 am", "H A"), self.expected) - self.assertEqual(self.parser.parse("1 am", "h A"), self.expected) - - self.expected = datetime(1, 1, 1, 0, 0, 0) - self.assertEqual(self.parser.parse("12 am", "H A"), self.expected) - self.assertEqual(self.parser.parse("12 am", "h A"), self.expected) - - self.expected = datetime(1, 1, 1, 12, 0, 0) - self.assertEqual(self.parser.parse("12 pm", "H A"), self.expected) - self.assertEqual(self.parser.parse("12 pm", "h A"), self.expected) - - def test_parse_tz_hours_only(self): - self.expected = datetime(2025, 10, 17, 5, 30, 10, tzinfo=tz.tzoffset(None, 0)) - parsed = self.parser.parse("2025-10-17 05:30:10+00", "YYYY-MM-DD HH:mm:ssZ") - self.assertEqual(parsed, self.expected) - - def test_parse_tz_zz(self): - - self.expected = datetime(2013, 1, 1, tzinfo=tz.tzoffset(None, -7 * 3600)) - self.assertEqual( - self.parser.parse("2013-01-01 -07:00", "YYYY-MM-DD ZZ"), self.expected - ) - - def test_parse_tz_name_zzz(self): - for tz_name in make_full_tz_list(): - self.expected = datetime(2013, 1, 1, tzinfo=tz.gettz(tz_name)) - self.assertEqual( - self.parser.parse("2013-01-01 %s" % tz_name, "YYYY-MM-DD ZZZ"), - self.expected, - ) - - # note that offsets are not timezones - with self.assertRaises(ParserError): - self.parser.parse("2013-01-01 12:30:45.9+1000", "YYYY-MM-DDZZZ") - - with self.assertRaises(ParserError): - self.parser.parse("2013-01-01 12:30:45.9+10:00", "YYYY-MM-DDZZZ") - - with self.assertRaises(ParserError): - self.parser.parse("2013-01-01 12:30:45.9-10", "YYYY-MM-DDZZZ") - - def test_parse_subsecond(self): - # TODO: make both test_parse_subsecond functions in Parse and ParseISO - # tests use the same expected objects (use pytest fixtures) - self.expected = datetime(2013, 1, 1, 12, 30, 45, 900000) - self.assertEqual( - self.parser.parse("2013-01-01 12:30:45.9", "YYYY-MM-DD HH:mm:ss.S"), - self.expected, - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 980000) - self.assertEqual( - self.parser.parse("2013-01-01 12:30:45.98", "YYYY-MM-DD HH:mm:ss.SS"), - self.expected, - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987000) - self.assertEqual( - self.parser.parse("2013-01-01 12:30:45.987", "YYYY-MM-DD HH:mm:ss.SSS"), - self.expected, - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987600) - self.assertEqual( - self.parser.parse("2013-01-01 12:30:45.9876", "YYYY-MM-DD HH:mm:ss.SSSS"), - self.expected, - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987650) - self.assertEqual( - self.parser.parse("2013-01-01 12:30:45.98765", "YYYY-MM-DD HH:mm:ss.SSSSS"), - self.expected, - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) - self.assertEqual( - self.parser.parse( - "2013-01-01 12:30:45.987654", "YYYY-MM-DD HH:mm:ss.SSSSSS" - ), - self.expected, - ) - - def test_parse_subsecond_rounding(self): - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) - datetime_format = "YYYY-MM-DD HH:mm:ss.S" - - # round up - string = "2013-01-01 12:30:45.9876539" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - # round down - string = "2013-01-01 12:30:45.98765432" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - # round half-up - string = "2013-01-01 12:30:45.987653521" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - # round half-down - string = "2013-01-01 12:30:45.9876545210" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - # overflow (zero out the subseconds and increment the seconds) - # regression tests for issue #636 - def test_parse_subsecond_rounding_overflow(self): - datetime_format = "YYYY-MM-DD HH:mm:ss.S" - - self.expected = datetime(2013, 1, 1, 12, 30, 46) - string = "2013-01-01 12:30:45.9999995" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - self.expected = datetime(2013, 1, 1, 12, 31, 0) - string = "2013-01-01 12:30:59.9999999" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - self.expected = datetime(2013, 1, 2, 0, 0, 0) - string = "2013-01-01 23:59:59.9999999" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - # 6 digits should remain unrounded - self.expected = datetime(2013, 1, 1, 12, 30, 45, 999999) - string = "2013-01-01 12:30:45.999999" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - # Regression tests for issue #560 - def test_parse_long_year(self): - with self.assertRaises(ParserError): - self.parser.parse("09 January 123456789101112", "DD MMMM YYYY") - - with self.assertRaises(ParserError): - self.parser.parse("123456789101112 09 January", "YYYY DD MMMM") - - with self.assertRaises(ParserError): - self.parser.parse("68096653015/01/19", "YY/M/DD") - - def test_parse_with_extra_words_at_start_and_end_invalid(self): - input_format_pairs = [ - ("blah2016", "YYYY"), - ("blah2016blah", "YYYY"), - ("2016blah", "YYYY"), - ("2016-05blah", "YYYY-MM"), - ("2016-05-16blah", "YYYY-MM-DD"), - ("2016-05-16T04:05:06.789120blah", "YYYY-MM-DDThh:mm:ss.S"), - ("2016-05-16T04:05:06.789120ZblahZ", "YYYY-MM-DDThh:mm:ss.SZ"), - ("2016-05-16T04:05:06.789120Zblah", "YYYY-MM-DDThh:mm:ss.SZ"), - ("2016-05-16T04:05:06.789120blahZ", "YYYY-MM-DDThh:mm:ss.SZ"), - ] - - for pair in input_format_pairs: - with self.assertRaises(ParserError): - self.parser.parse(pair[0], pair[1]) - - def test_parse_with_extra_words_at_start_and_end_valid(self): - # Spaces surrounding the parsable date are ok because we - # allow the parsing of natural language input. Additionally, a single - # character of specific punctuation before or after the date is okay. - # See docs for full list of valid punctuation. - - self.assertEqual( - self.parser.parse("blah 2016 blah", "YYYY"), datetime(2016, 1, 1) - ) - - self.assertEqual(self.parser.parse("blah 2016", "YYYY"), datetime(2016, 1, 1)) - - self.assertEqual(self.parser.parse("2016 blah", "YYYY"), datetime(2016, 1, 1)) - - # test one additional space along with space divider - self.assertEqual( - self.parser.parse( - "blah 2016-05-16 04:05:06.789120", "YYYY-MM-DD hh:mm:ss.S" - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - self.assertEqual( - self.parser.parse( - "2016-05-16 04:05:06.789120 blah", "YYYY-MM-DD hh:mm:ss.S" - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - # test one additional space along with T divider - self.assertEqual( - self.parser.parse( - "blah 2016-05-16T04:05:06.789120", "YYYY-MM-DDThh:mm:ss.S" - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - self.assertEqual( - self.parser.parse( - "2016-05-16T04:05:06.789120 blah", "YYYY-MM-DDThh:mm:ss.S" - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - self.assertEqual( - self.parser.parse( - "Meet me at 2016-05-16T04:05:06.789120 at the restaurant.", - "YYYY-MM-DDThh:mm:ss.S", - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - self.assertEqual( - self.parser.parse( - "Meet me at 2016-05-16 04:05:06.789120 at the restaurant.", - "YYYY-MM-DD hh:mm:ss.S", - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - # regression test for issue #701 - # tests cases of a partial match surrounded by punctuation - # for the list of valid punctuation, see documentation - def test_parse_with_punctuation_fences(self): - self.assertEqual( - self.parser.parse( - "Meet me at my house on Halloween (2019-31-10)", "YYYY-DD-MM" - ), - datetime(2019, 10, 31), - ) - - self.assertEqual( - self.parser.parse( - "Monday, 9. September 2019, 16:15-20:00", "dddd, D. MMMM YYYY" - ), - datetime(2019, 9, 9), - ) - - self.assertEqual( - self.parser.parse("A date is 11.11.2011.", "DD.MM.YYYY"), - datetime(2011, 11, 11), - ) - - with self.assertRaises(ParserMatchError): - self.parser.parse("11.11.2011.1 is not a valid date.", "DD.MM.YYYY") - - with self.assertRaises(ParserMatchError): - self.parser.parse( - "This date has too many punctuation marks following it (11.11.2011).", - "DD.MM.YYYY", - ) - - def test_parse_with_leading_and_trailing_whitespace(self): - self.assertEqual(self.parser.parse(" 2016", "YYYY"), datetime(2016, 1, 1)) - - self.assertEqual(self.parser.parse("2016 ", "YYYY"), datetime(2016, 1, 1)) - - self.assertEqual( - self.parser.parse(" 2016 ", "YYYY"), datetime(2016, 1, 1) - ) - - self.assertEqual( - self.parser.parse( - " 2016-05-16 04:05:06.789120 ", "YYYY-MM-DD hh:mm:ss.S" - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - self.assertEqual( - self.parser.parse( - " 2016-05-16T04:05:06.789120 ", "YYYY-MM-DDThh:mm:ss.S" - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - def test_parse_YYYY_DDDD(self): - self.assertEqual( - self.parser.parse("1998-136", "YYYY-DDDD"), datetime(1998, 5, 16) - ) - - self.assertEqual( - self.parser.parse("1998-006", "YYYY-DDDD"), datetime(1998, 1, 6) - ) - - with self.assertRaises(ParserError): - self.parser.parse("1998-456", "YYYY-DDDD") - - def test_parse_YYYY_DDD(self): - self.assertEqual(self.parser.parse("1998-6", "YYYY-DDD"), datetime(1998, 1, 6)) - - self.assertEqual( - self.parser.parse("1998-136", "YYYY-DDD"), datetime(1998, 5, 16) - ) - - with self.assertRaises(ParserError): - self.parser.parse("1998-756", "YYYY-DDD") - - # month cannot be passed with DDD and DDDD tokens - def test_parse_YYYY_MM_DDDD(self): - with self.assertRaises(ParserError): - self.parser.parse("2015-01-009", "YYYY-MM-DDDD") - - # year is required with the DDD and DDDD tokens - def test_parse_DDD_only(self): - with self.assertRaises(ParserError): - self.parser.parse("5", "DDD") - - def test_parse_DDDD_only(self): - with self.assertRaises(ParserError): - self.parser.parse("145", "DDDD") - - def test_parse_HH_24(self): - self.assertEqual( - self.parser.parse("2019-10-30T24:00:00", "YYYY-MM-DDTHH:mm:ss"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse("2019-10-30T24:00", "YYYY-MM-DDTHH:mm"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse("2019-10-30T24", "YYYY-MM-DDTHH"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse("2019-10-30T24:00:00.0", "YYYY-MM-DDTHH:mm:ss.S"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse("2019-10-31T24:00:00", "YYYY-MM-DDTHH:mm:ss"), - datetime(2019, 11, 1, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse("2019-12-31T24:00:00", "YYYY-MM-DDTHH:mm:ss"), - datetime(2020, 1, 1, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse("2019-12-31T23:59:59.9999999", "YYYY-MM-DDTHH:mm:ss.S"), - datetime(2020, 1, 1, 0, 0, 0, 0), - ) - - with self.assertRaises(ParserError): - self.parser.parse("2019-12-31T24:01:00", "YYYY-MM-DDTHH:mm:ss") - - with self.assertRaises(ParserError): - self.parser.parse("2019-12-31T24:00:01", "YYYY-MM-DDTHH:mm:ss") - - with self.assertRaises(ParserError): - self.parser.parse("2019-12-31T24:00:00.1", "YYYY-MM-DDTHH:mm:ss.S") - - with self.assertRaises(ParserError): - self.parser.parse("2019-12-31T24:00:00.999999", "YYYY-MM-DDTHH:mm:ss.S") - - -class DateTimeParserRegexTests(Chai): - def setUp(self): - super(DateTimeParserRegexTests, self).setUp() - - self.format_regex = parser.DateTimeParser._FORMAT_RE - - def test_format_year(self): - - self.assertEqual(self.format_regex.findall("YYYY-YY"), ["YYYY", "YY"]) - - def test_format_month(self): - - self.assertEqual( - self.format_regex.findall("MMMM-MMM-MM-M"), ["MMMM", "MMM", "MM", "M"] - ) - - def test_format_day(self): - - self.assertEqual( - self.format_regex.findall("DDDD-DDD-DD-D"), ["DDDD", "DDD", "DD", "D"] - ) - - def test_format_hour(self): - - self.assertEqual(self.format_regex.findall("HH-H-hh-h"), ["HH", "H", "hh", "h"]) - - def test_format_minute(self): - - self.assertEqual(self.format_regex.findall("mm-m"), ["mm", "m"]) - - def test_format_second(self): - - self.assertEqual(self.format_regex.findall("ss-s"), ["ss", "s"]) - - def test_format_subsecond(self): - - self.assertEqual( - self.format_regex.findall("SSSSSS-SSSSS-SSSS-SSS-SS-S"), - ["SSSSSS", "SSSSS", "SSSS", "SSS", "SS", "S"], - ) - - def test_format_tz(self): - - self.assertEqual(self.format_regex.findall("ZZZ-ZZ-Z"), ["ZZZ", "ZZ", "Z"]) - - def test_format_am_pm(self): - - self.assertEqual(self.format_regex.findall("A-a"), ["A", "a"]) - - def test_format_timestamp(self): - - self.assertEqual(self.format_regex.findall("X"), ["X"]) - - def test_format_timestamp_milli(self): - - self.assertEqual(self.format_regex.findall("x"), ["x"]) - - def test_escape(self): - - escape_regex = parser.DateTimeParser._ESCAPE_RE - - self.assertEqual( - escape_regex.findall("2018-03-09 8 [h] 40 [hello]"), ["[h]", "[hello]"] - ) - - def test_month_names(self): - p = parser.DateTimeParser("en_us") - - text = "_".join(calendar.month_name[1:]) - - result = p._input_re_map["MMMM"].findall(text) - - self.assertEqual(result, calendar.month_name[1:]) - - def test_month_abbreviations(self): - p = parser.DateTimeParser("en_us") - - text = "_".join(calendar.month_abbr[1:]) - - result = p._input_re_map["MMM"].findall(text) - - self.assertEqual(result, calendar.month_abbr[1:]) - - def test_digits(self): - - self.assertEqual( - parser.DateTimeParser._ONE_OR_TWO_DIGIT_RE.findall("4-56"), ["4", "56"] - ) - self.assertEqual( - parser.DateTimeParser._ONE_OR_TWO_OR_THREE_DIGIT_RE.findall("4-56-789"), - ["4", "56", "789"], - ) - self.assertEqual( - parser.DateTimeParser._ONE_OR_MORE_DIGIT_RE.findall("4-56-789-1234-12345"), - ["4", "56", "789", "1234", "12345"], - ) - self.assertEqual( - parser.DateTimeParser._TWO_DIGIT_RE.findall("12-3-45"), ["12", "45"] - ) - self.assertEqual( - parser.DateTimeParser._THREE_DIGIT_RE.findall("123-4-56"), ["123"] - ) - self.assertEqual( - parser.DateTimeParser._FOUR_DIGIT_RE.findall("1234-56"), ["1234"] - ) - - def test_tz(self): - tz_z_re = parser.DateTimeParser._TZ_Z_RE - self.assertEqual(tz_z_re.findall("-0700"), [("-", "07", "00")]) - self.assertEqual(tz_z_re.findall("+07"), [("+", "07", "")]) - self.assertTrue(tz_z_re.search("15/01/2019T04:05:06.789120Z") is not None) - self.assertTrue(tz_z_re.search("15/01/2019T04:05:06.789120") is None) - - tz_zz_re = parser.DateTimeParser._TZ_ZZ_RE - self.assertEqual(tz_zz_re.findall("-07:00"), [("-", "07", "00")]) - self.assertEqual(tz_zz_re.findall("+07"), [("+", "07", "")]) - self.assertTrue(tz_zz_re.search("15/01/2019T04:05:06.789120Z") is not None) - self.assertTrue(tz_zz_re.search("15/01/2019T04:05:06.789120") is None) - - tz_name_re = parser.DateTimeParser._TZ_NAME_RE - self.assertEqual(tz_name_re.findall("Europe/Warsaw"), ["Europe/Warsaw"]) - self.assertEqual(tz_name_re.findall("GMT"), ["GMT"]) - - def test_timestamp(self): - timestamp_re = parser.DateTimeParser._TIMESTAMP_RE - self.assertEqual( - timestamp_re.findall("1565707550.452729"), ["1565707550.452729"] - ) - self.assertEqual( - timestamp_re.findall("-1565707550.452729"), ["-1565707550.452729"] - ) - self.assertEqual(timestamp_re.findall("-1565707550"), ["-1565707550"]) - self.assertEqual(timestamp_re.findall("1565707550"), ["1565707550"]) - self.assertEqual(timestamp_re.findall("1565707550."), []) - self.assertEqual(timestamp_re.findall(".1565707550"), []) - - def test_timestamp_milli(self): - timestamp_expanded_re = parser.DateTimeParser._TIMESTAMP_EXPANDED_RE - self.assertEqual(timestamp_expanded_re.findall("-1565707550"), ["-1565707550"]) - self.assertEqual(timestamp_expanded_re.findall("1565707550"), ["1565707550"]) - self.assertEqual(timestamp_expanded_re.findall("1565707550.452729"), []) - self.assertEqual(timestamp_expanded_re.findall("1565707550."), []) - self.assertEqual(timestamp_expanded_re.findall(".1565707550"), []) - - def test_time(self): - time_re = parser.DateTimeParser._TIME_RE - time_seperators = [":", ""] - - for sep in time_seperators: - self.assertEqual(time_re.findall("12"), [("12", "", "", "", "")]) - self.assertEqual( - time_re.findall("12{sep}35".format(sep=sep)), [("12", "35", "", "", "")] - ) - self.assertEqual( - time_re.findall("12{sep}35{sep}46".format(sep=sep)), - [("12", "35", "46", "", "")], - ) - self.assertEqual( - time_re.findall("12{sep}35{sep}46.952313".format(sep=sep)), - [("12", "35", "46", ".", "952313")], - ) - self.assertEqual( - time_re.findall("12{sep}35{sep}46,952313".format(sep=sep)), - [("12", "35", "46", ",", "952313")], - ) - - self.assertEqual(time_re.findall("12:"), []) - self.assertEqual(time_re.findall("12:35:46."), []) - self.assertEqual(time_re.findall("12:35:46,"), []) - - -class DateTimeParserISOTests(Chai): - def setUp(self): - super(DateTimeParserISOTests, self).setUp() - - self.parser = parser.DateTimeParser("en_us") - - def test_YYYY(self): - - self.assertEqual(self.parser.parse_iso("2013"), datetime(2013, 1, 1)) - - def test_YYYY_DDDD(self): - self.assertEqual(self.parser.parse_iso("1998-136"), datetime(1998, 5, 16)) - - self.assertEqual(self.parser.parse_iso("1998-006"), datetime(1998, 1, 6)) - - with self.assertRaises(ParserError): - self.parser.parse_iso("1998-456") - - # 2016 is a leap year, so Feb 29 exists (leap day) - self.assertEqual(self.parser.parse_iso("2016-059"), datetime(2016, 2, 28)) - self.assertEqual(self.parser.parse_iso("2016-060"), datetime(2016, 2, 29)) - self.assertEqual(self.parser.parse_iso("2016-061"), datetime(2016, 3, 1)) - - # 2017 is not a leap year, so Feb 29 does not exist - self.assertEqual(self.parser.parse_iso("2017-059"), datetime(2017, 2, 28)) - self.assertEqual(self.parser.parse_iso("2017-060"), datetime(2017, 3, 1)) - self.assertEqual(self.parser.parse_iso("2017-061"), datetime(2017, 3, 2)) - - # Since 2016 is a leap year, the 366th day falls in the same year - self.assertEqual(self.parser.parse_iso("2016-366"), datetime(2016, 12, 31)) - - # Since 2017 is not a leap year, the 366th day falls in the next year - self.assertEqual(self.parser.parse_iso("2017-366"), datetime(2018, 1, 1)) - - def test_YYYY_DDDD_HH_mm_ssZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-036 04:05:06+01:00"), - datetime(2013, 2, 5, 4, 5, 6, tzinfo=tz.tzoffset(None, 3600)), - ) - - self.assertEqual( - self.parser.parse_iso("2013-036 04:05:06Z"), - datetime(2013, 2, 5, 4, 5, 6, tzinfo=tz.tzutc()), - ) - - def test_YYYY_MM_DDDD(self): - with self.assertRaises(ParserError): - self.parser.parse_iso("2014-05-125") - - def test_YYYY_MM(self): - - for separator in DateTimeParser.SEPARATORS: - self.assertEqual( - self.parser.parse_iso(separator.join(("2013", "02"))), - datetime(2013, 2, 1), - ) - - def test_YYYY_MM_DD(self): - - for separator in DateTimeParser.SEPARATORS: - self.assertEqual( - self.parser.parse_iso(separator.join(("2013", "02", "03"))), - datetime(2013, 2, 3), - ) - - def test_YYYY_MM_DDTHH_mmZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05+01:00"), - datetime(2013, 2, 3, 4, 5, tzinfo=tz.tzoffset(None, 3600)), - ) - - def test_YYYY_MM_DDTHH_mm(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05"), datetime(2013, 2, 3, 4, 5) - ) - - def test_YYYY_MM_DDTHH(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04"), datetime(2013, 2, 3, 4) - ) - - def test_YYYY_MM_DDTHHZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04+01:00"), - datetime(2013, 2, 3, 4, tzinfo=tz.tzoffset(None, 3600)), - ) - - def test_YYYY_MM_DDTHH_mm_ssZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06+01:00"), - datetime(2013, 2, 3, 4, 5, 6, tzinfo=tz.tzoffset(None, 3600)), - ) - - def test_YYYY_MM_DDTHH_mm_ss(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06"), datetime(2013, 2, 3, 4, 5, 6) - ) - - def test_YYYY_MM_DD_HH_mmZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03 04:05+01:00"), - datetime(2013, 2, 3, 4, 5, tzinfo=tz.tzoffset(None, 3600)), - ) - - def test_YYYY_MM_DD_HH_mm(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03 04:05"), datetime(2013, 2, 3, 4, 5) - ) - - def test_YYYY_MM_DD_HH(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03 04"), datetime(2013, 2, 3, 4) - ) - - def test_invalid_time(self): - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03 044") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03 04:05:06.") - - def test_YYYY_MM_DD_HH_mm_ssZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03 04:05:06+01:00"), - datetime(2013, 2, 3, 4, 5, 6, tzinfo=tz.tzoffset(None, 3600)), - ) - - def test_YYYY_MM_DD_HH_mm_ss(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03 04:05:06"), datetime(2013, 2, 3, 4, 5, 6) - ) - - def test_YYYY_MM_DDTHH_mm_ss_S(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.7"), - datetime(2013, 2, 3, 4, 5, 6, 700000), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.78"), - datetime(2013, 2, 3, 4, 5, 6, 780000), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.789"), - datetime(2013, 2, 3, 4, 5, 6, 789000), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.7891"), - datetime(2013, 2, 3, 4, 5, 6, 789100), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.78912"), - datetime(2013, 2, 3, 4, 5, 6, 789120), - ) - - # ISO 8601:2004(E), ISO, 2004-12-01, 4.2.2.4 ... the decimal fraction - # shall be divided from the integer part by the decimal sign specified - # in ISO 31-0, i.e. the comma [,] or full stop [.]. Of these, the comma - # is the preferred sign. - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06,789123678"), - datetime(2013, 2, 3, 4, 5, 6, 789124), - ) - - # there is no limit on the number of decimal places - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.789123678"), - datetime(2013, 2, 3, 4, 5, 6, 789124), - ) - - def test_YYYY_MM_DDTHH_mm_ss_SZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.7+01:00"), - datetime(2013, 2, 3, 4, 5, 6, 700000, tzinfo=tz.tzoffset(None, 3600)), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.78+01:00"), - datetime(2013, 2, 3, 4, 5, 6, 780000, tzinfo=tz.tzoffset(None, 3600)), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.789+01:00"), - datetime(2013, 2, 3, 4, 5, 6, 789000, tzinfo=tz.tzoffset(None, 3600)), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.7891+01:00"), - datetime(2013, 2, 3, 4, 5, 6, 789100, tzinfo=tz.tzoffset(None, 3600)), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.78912+01:00"), - datetime(2013, 2, 3, 4, 5, 6, 789120, tzinfo=tz.tzoffset(None, 3600)), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03 04:05:06.78912Z"), - datetime(2013, 2, 3, 4, 5, 6, 789120, tzinfo=tz.tzutc()), - ) - - def test_invalid_Z(self): - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912z") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912zz") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912Zz") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912ZZ") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912+Z") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912-Z") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912 Z") - - def test_parse_subsecond(self): - # TODO: make both test_parse_subsecond functions in Parse and ParseISO - # tests use the same expected objects (use pytest fixtures) - self.expected = datetime(2013, 1, 1, 12, 30, 45, 900000) - self.assertEqual(self.parser.parse_iso("2013-01-01 12:30:45.9"), self.expected) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 980000) - self.assertEqual(self.parser.parse_iso("2013-01-01 12:30:45.98"), self.expected) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987000) - self.assertEqual( - self.parser.parse_iso("2013-01-01 12:30:45.987"), self.expected - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987600) - self.assertEqual( - self.parser.parse_iso("2013-01-01 12:30:45.9876"), self.expected - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987650) - self.assertEqual( - self.parser.parse_iso("2013-01-01 12:30:45.98765"), self.expected - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) - self.assertEqual( - self.parser.parse_iso("2013-01-01 12:30:45.987654"), self.expected - ) - - # use comma as subsecond separator - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) - self.assertEqual( - self.parser.parse_iso("2013-01-01 12:30:45,987654"), self.expected - ) - - def test_gnu_date(self): - """ - regression tests for parsing output from GNU date(1) - """ - # date -Ins - self.assertEqual( - self.parser.parse_iso("2016-11-16T09:46:30,895636557-0800"), - datetime( - 2016, 11, 16, 9, 46, 30, 895636, tzinfo=tz.tzoffset(None, -3600 * 8) - ), - ) - - # date --rfc-3339=ns - self.assertEqual( - self.parser.parse_iso("2016-11-16 09:51:14.682141526-08:00"), - datetime( - 2016, 11, 16, 9, 51, 14, 682142, tzinfo=tz.tzoffset(None, -3600 * 8) - ), - ) - - def test_isoformat(self): - - dt = datetime.utcnow() - - self.assertEqual(self.parser.parse_iso(dt.isoformat()), dt) - - def test_parse_iso_with_leading_and_trailing_whitespace(self): - datetime_string = " 2016-11-15T06:37:19.123456" - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - datetime_string = " 2016-11-15T06:37:19.123456 " - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - datetime_string = "2016-11-15T06:37:19.123456 " - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - datetime_string = "2016-11-15T 06:37:19.123456" - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - # leading whitespace - datetime_string = " 2016-11-15 06:37:19.123456" - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - # trailing whitespace - datetime_string = "2016-11-15 06:37:19.123456 " - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - datetime_string = " 2016-11-15 06:37:19.123456 " - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - # two dividing spaces - datetime_string = "2016-11-15 06:37:19.123456" - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - def test_parse_iso_with_extra_words_at_start_and_end_invalid(self): - test_inputs = [ - "blah2016", - "blah2016blah", - "blah 2016 blah", - "blah 2016", - "2016 blah", - "blah 2016-05-16 04:05:06.789120", - "2016-05-16 04:05:06.789120 blah", - "blah 2016-05-16T04:05:06.789120", - "2016-05-16T04:05:06.789120 blah", - "2016blah", - "2016-05blah", - "2016-05-16blah", - "2016-05-16T04:05:06.789120blah", - "2016-05-16T04:05:06.789120ZblahZ", - "2016-05-16T04:05:06.789120Zblah", - "2016-05-16T04:05:06.789120blahZ", - "Meet me at 2016-05-16T04:05:06.789120 at the restaurant.", - "Meet me at 2016-05-16 04:05:06.789120 at the restaurant.", - ] - - for ti in test_inputs: - with self.assertRaises(ParserError): - self.parser.parse_iso(ti) - - def test_iso8601_basic_format(self): - self.assertEqual(self.parser.parse_iso("20180517"), datetime(2018, 5, 17)) - - self.assertEqual( - self.parser.parse_iso("20180517T10"), datetime(2018, 5, 17, 10) - ) - - self.assertEqual( - self.parser.parse_iso("20180517T105513.843456"), - datetime(2018, 5, 17, 10, 55, 13, 843456), - ) - - self.assertEqual( - self.parser.parse_iso("20180517T105513Z"), - datetime(2018, 5, 17, 10, 55, 13, tzinfo=tz.tzutc()), - ) - - self.assertEqual( - self.parser.parse_iso("20180517T105513.843456-0700"), - datetime(2018, 5, 17, 10, 55, 13, 843456, tzinfo=tz.tzoffset(None, -25200)), - ) - - self.assertEqual( - self.parser.parse_iso("20180517T105513-0700"), - datetime(2018, 5, 17, 10, 55, 13, tzinfo=tz.tzoffset(None, -25200)), - ) - - self.assertEqual( - self.parser.parse_iso("20180517T105513-07"), - datetime(2018, 5, 17, 10, 55, 13, tzinfo=tz.tzoffset(None, -25200)), - ) - - # ordinal in basic format: YYYYDDDD - self.assertEqual(self.parser.parse_iso("1998136"), datetime(1998, 5, 16)) - - # timezone requires +- seperator - with self.assertRaises(ParserError): - self.parser.parse_iso("20180517T1055130700") - - with self.assertRaises(ParserError): - self.parser.parse_iso("20180517T10551307") - - # too many digits in date - with self.assertRaises(ParserError): - self.parser.parse_iso("201860517T105513Z") - - # too many digits in time - with self.assertRaises(ParserError): - self.parser.parse_iso("20180517T1055213Z") - - def test_midnight_end_day(self): - self.assertEqual( - self.parser.parse_iso("2019-10-30T24:00:00"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse_iso("2019-10-30T24:00"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse_iso("2019-10-30T24:00:00.0"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse_iso("2019-10-31T24:00:00"), - datetime(2019, 11, 1, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse_iso("2019-12-31T24:00:00"), - datetime(2020, 1, 1, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse_iso("2019-12-31T23:59:59.9999999"), - datetime(2020, 1, 1, 0, 0, 0, 0), - ) - - with self.assertRaises(ParserError): - self.parser.parse_iso("2019-12-31T24:01:00") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2019-12-31T24:00:01") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2019-12-31T24:00:00.1") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2019-12-31T24:00:00.999999") - - -class TzinfoParserTests(Chai): - def setUp(self): - super(TzinfoParserTests, self).setUp() - - self.parser = parser.TzinfoParser() - - def test_parse_local(self): - - self.assertEqual(self.parser.parse("local"), tz.tzlocal()) - - def test_parse_utc(self): - - self.assertEqual(self.parser.parse("utc"), tz.tzutc()) - self.assertEqual(self.parser.parse("UTC"), tz.tzutc()) - - def test_parse_iso(self): - - self.assertEqual(self.parser.parse("01:00"), tz.tzoffset(None, 3600)) - self.assertEqual( - self.parser.parse("11:35"), tz.tzoffset(None, 11 * 3600 + 2100) - ) - self.assertEqual(self.parser.parse("+01:00"), tz.tzoffset(None, 3600)) - self.assertEqual(self.parser.parse("-01:00"), tz.tzoffset(None, -3600)) - - self.assertEqual(self.parser.parse("0100"), tz.tzoffset(None, 3600)) - self.assertEqual(self.parser.parse("+0100"), tz.tzoffset(None, 3600)) - self.assertEqual(self.parser.parse("-0100"), tz.tzoffset(None, -3600)) - - self.assertEqual(self.parser.parse("01"), tz.tzoffset(None, 3600)) - self.assertEqual(self.parser.parse("+01"), tz.tzoffset(None, 3600)) - self.assertEqual(self.parser.parse("-01"), tz.tzoffset(None, -3600)) - - def test_parse_str(self): - - self.assertEqual(self.parser.parse("US/Pacific"), tz.gettz("US/Pacific")) - - def test_parse_fails(self): - - with self.assertRaises(parser.ParserError): - self.parser.parse("fail") - - -class DateTimeParserMonthNameTests(Chai): - def setUp(self): - super(DateTimeParserMonthNameTests, self).setUp() - - self.parser = parser.DateTimeParser("en_us") - - def test_shortmonth_capitalized(self): - - self.assertEqual( - self.parser.parse("2013-Jan-01", "YYYY-MMM-DD"), datetime(2013, 1, 1) - ) - - def test_shortmonth_allupper(self): - - self.assertEqual( - self.parser.parse("2013-JAN-01", "YYYY-MMM-DD"), datetime(2013, 1, 1) - ) - - def test_shortmonth_alllower(self): - - self.assertEqual( - self.parser.parse("2013-jan-01", "YYYY-MMM-DD"), datetime(2013, 1, 1) - ) - - def test_month_capitalized(self): - - self.assertEqual( - self.parser.parse("2013-January-01", "YYYY-MMMM-DD"), datetime(2013, 1, 1) - ) - - def test_month_allupper(self): - - self.assertEqual( - self.parser.parse("2013-JANUARY-01", "YYYY-MMMM-DD"), datetime(2013, 1, 1) - ) - - def test_month_alllower(self): - - self.assertEqual( - self.parser.parse("2013-january-01", "YYYY-MMMM-DD"), datetime(2013, 1, 1) - ) - - def test_localized_month_name(self): - parser_ = parser.DateTimeParser("fr_fr") - - self.assertEqual( - parser_.parse("2013-Janvier-01", "YYYY-MMMM-DD"), datetime(2013, 1, 1) - ) - - def test_localized_month_abbreviation(self): - parser_ = parser.DateTimeParser("it_it") - - self.assertEqual( - parser_.parse("2013-Gen-01", "YYYY-MMM-DD"), datetime(2013, 1, 1) - ) - - -class DateTimeParserMeridiansTests(Chai): - def setUp(self): - super(DateTimeParserMeridiansTests, self).setUp() - - self.parser = parser.DateTimeParser("en_us") - - def test_meridians_lowercase(self): - self.assertEqual( - self.parser.parse("2013-01-01 5am", "YYYY-MM-DD ha"), - datetime(2013, 1, 1, 5), - ) - - self.assertEqual( - self.parser.parse("2013-01-01 5pm", "YYYY-MM-DD ha"), - datetime(2013, 1, 1, 17), - ) - - def test_meridians_capitalized(self): - self.assertEqual( - self.parser.parse("2013-01-01 5AM", "YYYY-MM-DD hA"), - datetime(2013, 1, 1, 5), - ) - - self.assertEqual( - self.parser.parse("2013-01-01 5PM", "YYYY-MM-DD hA"), - datetime(2013, 1, 1, 17), - ) - - def test_localized_meridians_lowercase(self): - parser_ = parser.DateTimeParser("hu_hu") - self.assertEqual( - parser_.parse("2013-01-01 5 de", "YYYY-MM-DD h a"), datetime(2013, 1, 1, 5) - ) - - self.assertEqual( - parser_.parse("2013-01-01 5 du", "YYYY-MM-DD h a"), datetime(2013, 1, 1, 17) - ) - - def test_localized_meridians_capitalized(self): - parser_ = parser.DateTimeParser("hu_hu") - self.assertEqual( - parser_.parse("2013-01-01 5 DE", "YYYY-MM-DD h A"), datetime(2013, 1, 1, 5) - ) - - self.assertEqual( - parser_.parse("2013-01-01 5 DU", "YYYY-MM-DD h A"), datetime(2013, 1, 1, 17) - ) - - # regression test for issue #607 - def test_es_meridians(self): - parser_ = parser.DateTimeParser("es") - - self.assertEqual( - parser_.parse("Junio 30, 2019 - 08:00 pm", "MMMM DD, YYYY - hh:mm a"), - datetime(2019, 6, 30, 20, 0), - ) - - with self.assertRaises(ParserError): - parser_.parse( - "Junio 30, 2019 - 08:00 pasdfasdfm", "MMMM DD, YYYY - hh:mm a" - ) - - def test_fr_meridians(self): - parser_ = parser.DateTimeParser("fr") - - # the French locale always uses a 24 hour clock, so it does not support meridians - with self.assertRaises(ParserError): - parser_.parse("Janvier 30, 2019 - 08:00 pm", "MMMM DD, YYYY - hh:mm a") - - -class DateTimeParserMonthOrdinalDayTests(Chai): - def setUp(self): - super(DateTimeParserMonthOrdinalDayTests, self).setUp() - - self.parser = parser.DateTimeParser("en_us") - - def test_english(self): - parser_ = parser.DateTimeParser("en_us") - - self.assertEqual( - parser_.parse("January 1st, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 1) - ) - self.assertEqual( - parser_.parse("January 2nd, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 2) - ) - self.assertEqual( - parser_.parse("January 3rd, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 3) - ) - self.assertEqual( - parser_.parse("January 4th, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 4) - ) - self.assertEqual( - parser_.parse("January 11th, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 11) - ) - self.assertEqual( - parser_.parse("January 12th, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 12) - ) - self.assertEqual( - parser_.parse("January 13th, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 13) - ) - self.assertEqual( - parser_.parse("January 21st, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 21) - ) - self.assertEqual( - parser_.parse("January 31st, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 31) - ) - - with self.assertRaises(ParserError): - parser_.parse("January 1th, 2013", "MMMM Do, YYYY") - - with self.assertRaises(ParserError): - parser_.parse("January 11st, 2013", "MMMM Do, YYYY") - - def test_italian(self): - parser_ = parser.DateTimeParser("it_it") - - self.assertEqual( - parser_.parse("Gennaio 1º, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 1) - ) - - def test_spanish(self): - parser_ = parser.DateTimeParser("es_es") - - self.assertEqual( - parser_.parse("Enero 1º, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 1) - ) - - def test_french(self): - parser_ = parser.DateTimeParser("fr_fr") - - self.assertEqual( - parser_.parse("Janvier 1er, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 1) - ) - - self.assertEqual( - parser_.parse("Janvier 2e, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 2) - ) - - self.assertEqual( - parser_.parse("Janvier 11e, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 11) - ) - - -class DateTimeParserSearchDateTests(Chai): - def setUp(self): - super(DateTimeParserSearchDateTests, self).setUp() - self.parser = parser.DateTimeParser() - - def test_parse_search(self): - - self.assertEqual( - self.parser.parse("Today is 25 of September of 2003", "DD of MMMM of YYYY"), - datetime(2003, 9, 25), - ) - - def test_parse_search_with_numbers(self): - - self.assertEqual( - self.parser.parse( - "2000 people met the 2012-01-01 12:05:10", "YYYY-MM-DD HH:mm:ss" - ), - datetime(2012, 1, 1, 12, 5, 10), - ) - - self.assertEqual( - self.parser.parse( - "Call 01-02-03 on 79-01-01 12:05:10", "YY-MM-DD HH:mm:ss" - ), - datetime(1979, 1, 1, 12, 5, 10), - ) - - def test_parse_search_with_names(self): - - self.assertEqual( - self.parser.parse("June was born in May 1980", "MMMM YYYY"), - datetime(1980, 5, 1), - ) - - def test_parse_search_locale_with_names(self): - p = parser.DateTimeParser("sv_se") - - self.assertEqual( - p.parse("Jan föddes den 31 Dec 1980", "DD MMM YYYY"), datetime(1980, 12, 31) - ) - - self.assertEqual( - p.parse("Jag föddes den 25 Augusti 1975", "DD MMMM YYYY"), - datetime(1975, 8, 25), - ) - - def test_parse_search_fails(self): - - with self.assertRaises(parser.ParserError): - self.parser.parse("Jag föddes den 25 Augusti 1975", "DD MMMM YYYY") - - def test_escape(self): - - format = "MMMM D, YYYY [at] h:mma" - self.assertEqual( - self.parser.parse("Thursday, December 10, 2015 at 5:09pm", format), - datetime(2015, 12, 10, 17, 9), - ) - - format = "[MMMM] M D, YYYY [at] h:mma" - self.assertEqual( - self.parser.parse("MMMM 12 10, 2015 at 5:09pm", format), - datetime(2015, 12, 10, 17, 9), - ) - - format = "[It happened on] MMMM Do [in the year] YYYY [a long time ago]" - self.assertEqual( - self.parser.parse( - "It happened on November 25th in the year 1990 a long time ago", format - ), - datetime(1990, 11, 25), - ) - - format = "[It happened on] MMMM Do [in the][ year] YYYY [a long time ago]" - self.assertEqual( - self.parser.parse( - "It happened on November 25th in the year 1990 a long time ago", format - ), - datetime(1990, 11, 25), - ) - - format = "[I'm][ entirely][ escaped,][ weee!]" - self.assertEqual( - self.parser.parse("I'm entirely escaped, weee!", format), datetime(1, 1, 1) - ) - - # Special RegEx characters - format = "MMM DD, YYYY |^${}().*+?<>-& h:mm A" - self.assertEqual( - self.parser.parse("Dec 31, 2017 |^${}().*+?<>-& 2:00 AM", format), - datetime(2017, 12, 31, 2, 0), - ) diff --git a/tests/parser_tests.py.bak b/tests/parser_tests.py.bak deleted file mode 100644 index c72da044b..000000000 --- a/tests/parser_tests.py.bak +++ /dev/null @@ -1,1629 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import calendar -import os -import time -from datetime import datetime - -from chai import Chai -from dateutil import tz - -from arrow import parser -from arrow.constants import MAX_TIMESTAMP_US -from arrow.parser import DateTimeParser, ParserError, ParserMatchError - -from .utils import make_full_tz_list - - -class DateTimeParserTests(Chai): - def setUp(self): - super(DateTimeParserTests, self).setUp() - - self.parser = parser.DateTimeParser() - - def test_parse_multiformat(self): - - mock_datetime = self.mock() - - self.expect(self.parser.parse).args("str", "fmt_a").raises(ParserMatchError) - self.expect(self.parser.parse).args("str", "fmt_b").returns(mock_datetime) - - result = self.parser._parse_multiformat("str", ["fmt_a", "fmt_b"]) - - self.assertEqual(result, mock_datetime) - - def test_parse_multiformat_all_fail(self): - - self.expect(self.parser.parse).args("str", "fmt_a").raises(ParserMatchError) - self.expect(self.parser.parse).args("str", "fmt_b").raises(ParserMatchError) - - with self.assertRaises(ParserError): - self.parser._parse_multiformat("str", ["fmt_a", "fmt_b"]) - - def test_parse_multiformat_unself_expected_fail(self): - class UnselfExpectedError(Exception): - pass - - self.expect(self.parser.parse).args("str", "fmt_a").raises(UnselfExpectedError) - - with self.assertRaises(UnselfExpectedError): - self.parser._parse_multiformat("str", ["fmt_a", "fmt_b"]) - - def test_parse_token_nonsense(self): - parts = {} - self.parser._parse_token("NONSENSE", "1900", parts) - self.assertEqual(parts, {}) - - def test_parse_token_invalid_meridians(self): - parts = {} - self.parser._parse_token("A", "a..m", parts) - self.assertEqual(parts, {}) - self.parser._parse_token("a", "p..m", parts) - self.assertEqual(parts, {}) - - def test_parser_no_caching(self): - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( - 100 - ) - self.parser = parser.DateTimeParser(cache_size=0) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - - def test_parser_1_line_caching(self): - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( - 1 - ) - self.parser = parser.DateTimeParser(cache_size=1) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_b").times( - 1 - ) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - self.parser._generate_pattern_re("fmt_b") - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( - 1 - ) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - - def test_parser_multiple_line_caching(self): - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( - 1 - ) - self.parser = parser.DateTimeParser(cache_size=2) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_b").times( - 1 - ) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - self.parser._generate_pattern_re("fmt_b") - - self.expect(parser.DateTimeParser, "_generate_pattern_re").args("fmt_a").times( - 0 - ) - for _ in range(100): - self.parser._generate_pattern_re("fmt_a") - - def test_YY_and_YYYY_format_list(self): - - self.assertEqual( - self.parser.parse("15/01/19", ["DD/MM/YY", "DD/MM/YYYY"]), - datetime(2019, 1, 15), - ) - - # Regression test for issue #580 - self.assertEqual( - self.parser.parse("15/01/2019", ["DD/MM/YY", "DD/MM/YYYY"]), - datetime(2019, 1, 15), - ) - - self.assertEqual( - self.parser.parse( - "15/01/2019T04:05:06.789120Z", - ["D/M/YYThh:mm:ss.SZ", "D/M/YYYYThh:mm:ss.SZ"], - ), - datetime(2019, 1, 15, 4, 5, 6, 789120, tzinfo=tz.tzutc()), - ) - - # regression test for issue #447 - def test_timestamp_format_list(self): - # should not match on the "X" token - self.assertEqual( - self.parser.parse( - "15 Jul 2000", - ["MM/DD/YYYY", "YYYY-MM-DD", "X", "DD-MMMM-YYYY", "D MMM YYYY"], - ), - datetime(2000, 7, 15), - ) - - with self.assertRaises(ParserError): - self.parser.parse("15 Jul", "X") - - -class DateTimeParserParseTests(Chai): - def setUp(self): - super(DateTimeParserParseTests, self).setUp() - - self.parser = parser.DateTimeParser() - - def test_parse_list(self): - - self.expect(self.parser._parse_multiformat).args( - "str", ["fmt_a", "fmt_b"] - ).returns("result") - - result = self.parser.parse("str", ["fmt_a", "fmt_b"]) - - self.assertEqual(result, "result") - - def test_parse_unrecognized_token(self): - - mock_input_re_map = self.mock(self.parser, "_input_re_map") - - self.expect(mock_input_re_map.__getitem__).args("YYYY").raises(KeyError) - - with self.assertRaises(parser.ParserError): - self.parser.parse("2013-01-01", "YYYY-MM-DD") - - def test_parse_parse_no_match(self): - - with self.assertRaises(ParserError): - self.parser.parse("01-01", "YYYY-MM-DD") - - def test_parse_separators(self): - - with self.assertRaises(ParserError): - self.parser.parse("1403549231", "YYYY-MM-DD") - - def test_parse_numbers(self): - - self.expected = datetime(2012, 1, 1, 12, 5, 10) - self.assertEqual( - self.parser.parse("2012-01-01 12:05:10", "YYYY-MM-DD HH:mm:ss"), - self.expected, - ) - - def test_parse_year_two_digit(self): - - self.expected = datetime(1979, 1, 1, 12, 5, 10) - self.assertEqual( - self.parser.parse("79-01-01 12:05:10", "YY-MM-DD HH:mm:ss"), self.expected - ) - - def test_parse_timestamp(self): - - tz_utc = tz.tzutc() - int_timestamp = int(time.time()) - self.expected = datetime.fromtimestamp(int_timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:d}".format(int_timestamp), "X"), self.expected - ) - - float_timestamp = time.time() - self.expected = datetime.fromtimestamp(float_timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:f}".format(float_timestamp), "X"), self.expected - ) - - # test handling of ns timestamp (arrow will round to 6 digits regardless) - self.expected = datetime.fromtimestamp(float_timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:f}123".format(float_timestamp), "X"), self.expected - ) - - # test ps timestamp (arrow will round to 6 digits regardless) - self.expected = datetime.fromtimestamp(float_timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:f}123456".format(float_timestamp), "X"), self.expected - ) - - # NOTE: negative timestamps cannot be handled by datetime on Window - # Must use timedelta to handle them. ref: https://stackoverflow.com/questions/36179914 - if os.name != "nt": - # regression test for issue #662 - negative_int_timestamp = -int_timestamp - self.expected = datetime.fromtimestamp(negative_int_timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:d}".format(negative_int_timestamp), "X"), - self.expected, - ) - - negative_float_timestamp = -float_timestamp - self.expected = datetime.fromtimestamp(negative_float_timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:f}".format(negative_float_timestamp), "X"), - self.expected, - ) - - # NOTE: timestamps cannot be parsed from natural language strings (by removing the ^...$) because it will - # break cases like "15 Jul 2000" and a format list (see issue #447) - with self.assertRaises(ParserError): - natural_lang_string = "Meet me at {} at the restaurant.".format( - float_timestamp - ) - self.parser.parse(natural_lang_string, "X") - - with self.assertRaises(ParserError): - self.parser.parse("1565982019.", "X") - - with self.assertRaises(ParserError): - self.parser.parse(".1565982019", "X") - - def test_parse_expanded_timestamp(self): - # test expanded timestamps that include milliseconds - # and microseconds as multiples rather than decimals - # requested in issue #357 - - tz_utc = tz.tzutc() - timestamp = 1569982581.413132 - timestamp_milli = int(round(timestamp * 1000)) - timestamp_micro = int(round(timestamp * 1000000)) - - # "x" token should parse integer timestamps below MAX_TIMESTAMP normally - self.expected = datetime.fromtimestamp(int(timestamp), tz=tz_utc) - self.assertEqual( - self.parser.parse("{:d}".format(int(timestamp)), "x"), self.expected - ) - - self.expected = datetime.fromtimestamp(round(timestamp, 3), tz=tz_utc) - self.assertEqual( - self.parser.parse("{:d}".format(timestamp_milli), "x"), self.expected - ) - - self.expected = datetime.fromtimestamp(timestamp, tz=tz_utc) - self.assertEqual( - self.parser.parse("{:d}".format(timestamp_micro), "x"), self.expected - ) - - # anything above max µs timestamp should fail - with self.assertRaises(ValueError): - self.parser.parse("{:d}".format(int(MAX_TIMESTAMP_US) + 1), "x") - - # floats are not allowed with the "x" token - with self.assertRaises(ParserMatchError): - self.parser.parse("{:f}".format(timestamp), "x") - - def test_parse_names(self): - - self.expected = datetime(2012, 1, 1) - - self.assertEqual( - self.parser.parse("January 1, 2012", "MMMM D, YYYY"), self.expected - ) - self.assertEqual(self.parser.parse("Jan 1, 2012", "MMM D, YYYY"), self.expected) - - def test_parse_pm(self): - - self.expected = datetime(1, 1, 1, 13, 0, 0) - self.assertEqual(self.parser.parse("1 pm", "H a"), self.expected) - self.assertEqual(self.parser.parse("1 pm", "h a"), self.expected) - - self.expected = datetime(1, 1, 1, 1, 0, 0) - self.assertEqual(self.parser.parse("1 am", "H A"), self.expected) - self.assertEqual(self.parser.parse("1 am", "h A"), self.expected) - - self.expected = datetime(1, 1, 1, 0, 0, 0) - self.assertEqual(self.parser.parse("12 am", "H A"), self.expected) - self.assertEqual(self.parser.parse("12 am", "h A"), self.expected) - - self.expected = datetime(1, 1, 1, 12, 0, 0) - self.assertEqual(self.parser.parse("12 pm", "H A"), self.expected) - self.assertEqual(self.parser.parse("12 pm", "h A"), self.expected) - - def test_parse_tz_hours_only(self): - self.expected = datetime(2025, 10, 17, 5, 30, 10, tzinfo=tz.tzoffset(None, 0)) - parsed = self.parser.parse("2025-10-17 05:30:10+00", "YYYY-MM-DD HH:mm:ssZ") - self.assertEqual(parsed, self.expected) - - def test_parse_tz_zz(self): - - self.expected = datetime(2013, 1, 1, tzinfo=tz.tzoffset(None, -7 * 3600)) - self.assertEqual( - self.parser.parse("2013-01-01 -07:00", "YYYY-MM-DD ZZ"), self.expected - ) - - def test_parse_tz_name_zzz(self): - for tz_name in make_full_tz_list(): - self.expected = datetime(2013, 1, 1, tzinfo=tz.gettz(tz_name)) - self.assertEqual( - self.parser.parse("2013-01-01 %s" % tz_name, "YYYY-MM-DD ZZZ"), - self.expected, - ) - - # note that offsets are not timezones - with self.assertRaises(ParserError): - self.parser.parse("2013-01-01 12:30:45.9+1000", "YYYY-MM-DDZZZ") - - with self.assertRaises(ParserError): - self.parser.parse("2013-01-01 12:30:45.9+10:00", "YYYY-MM-DDZZZ") - - with self.assertRaises(ParserError): - self.parser.parse("2013-01-01 12:30:45.9-10", "YYYY-MM-DDZZZ") - - def test_parse_subsecond(self): - # TODO: make both test_parse_subsecond functions in Parse and ParseISO - # tests use the same expected objects (use pytest fixtures) - self.expected = datetime(2013, 1, 1, 12, 30, 45, 900000) - self.assertEqual( - self.parser.parse("2013-01-01 12:30:45.9", "YYYY-MM-DD HH:mm:ss.S"), - self.expected, - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 980000) - self.assertEqual( - self.parser.parse("2013-01-01 12:30:45.98", "YYYY-MM-DD HH:mm:ss.SS"), - self.expected, - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987000) - self.assertEqual( - self.parser.parse("2013-01-01 12:30:45.987", "YYYY-MM-DD HH:mm:ss.SSS"), - self.expected, - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987600) - self.assertEqual( - self.parser.parse("2013-01-01 12:30:45.9876", "YYYY-MM-DD HH:mm:ss.SSSS"), - self.expected, - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987650) - self.assertEqual( - self.parser.parse("2013-01-01 12:30:45.98765", "YYYY-MM-DD HH:mm:ss.SSSSS"), - self.expected, - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) - self.assertEqual( - self.parser.parse( - "2013-01-01 12:30:45.987654", "YYYY-MM-DD HH:mm:ss.SSSSSS" - ), - self.expected, - ) - - def test_parse_subsecond_rounding(self): - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) - datetime_format = "YYYY-MM-DD HH:mm:ss.S" - - # round up - string = "2013-01-01 12:30:45.9876539" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - # round down - string = "2013-01-01 12:30:45.98765432" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - # round half-up - string = "2013-01-01 12:30:45.987653521" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - # round half-down - string = "2013-01-01 12:30:45.9876545210" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - # overflow (zero out the subseconds and increment the seconds) - # regression tests for issue #636 - def test_parse_subsecond_rounding_overflow(self): - datetime_format = "YYYY-MM-DD HH:mm:ss.S" - - self.expected = datetime(2013, 1, 1, 12, 30, 46) - string = "2013-01-01 12:30:45.9999995" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - self.expected = datetime(2013, 1, 1, 12, 31, 0) - string = "2013-01-01 12:30:59.9999999" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - self.expected = datetime(2013, 1, 2, 0, 0, 0) - string = "2013-01-01 23:59:59.9999999" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - # 6 digits should remain unrounded - self.expected = datetime(2013, 1, 1, 12, 30, 45, 999999) - string = "2013-01-01 12:30:45.999999" - self.assertEqual(self.parser.parse(string, datetime_format), self.expected) - self.assertEqual(self.parser.parse_iso(string), self.expected) - - # Regression tests for issue #560 - def test_parse_long_year(self): - with self.assertRaises(ParserError): - self.parser.parse("09 January 123456789101112", "DD MMMM YYYY") - - with self.assertRaises(ParserError): - self.parser.parse("123456789101112 09 January", "YYYY DD MMMM") - - with self.assertRaises(ParserError): - self.parser.parse("68096653015/01/19", "YY/M/DD") - - def test_parse_with_extra_words_at_start_and_end_invalid(self): - input_format_pairs = [ - ("blah2016", "YYYY"), - ("blah2016blah", "YYYY"), - ("2016blah", "YYYY"), - ("2016-05blah", "YYYY-MM"), - ("2016-05-16blah", "YYYY-MM-DD"), - ("2016-05-16T04:05:06.789120blah", "YYYY-MM-DDThh:mm:ss.S"), - ("2016-05-16T04:05:06.789120ZblahZ", "YYYY-MM-DDThh:mm:ss.SZ"), - ("2016-05-16T04:05:06.789120Zblah", "YYYY-MM-DDThh:mm:ss.SZ"), - ("2016-05-16T04:05:06.789120blahZ", "YYYY-MM-DDThh:mm:ss.SZ"), - ] - - for pair in input_format_pairs: - with self.assertRaises(ParserError): - self.parser.parse(pair[0], pair[1]) - - def test_parse_with_extra_words_at_start_and_end_valid(self): - # Spaces surrounding the parsable date are ok because we - # allow the parsing of natural language input. Additionally, a single - # character of specific punctuation before or after the date is okay. - # See docs for full list of valid punctuation. - - self.assertEqual( - self.parser.parse("blah 2016 blah", "YYYY"), datetime(2016, 1, 1) - ) - - self.assertEqual(self.parser.parse("blah 2016", "YYYY"), datetime(2016, 1, 1)) - - self.assertEqual(self.parser.parse("2016 blah", "YYYY"), datetime(2016, 1, 1)) - - # test one additional space along with space divider - self.assertEqual( - self.parser.parse( - "blah 2016-05-16 04:05:06.789120", "YYYY-MM-DD hh:mm:ss.S" - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - self.assertEqual( - self.parser.parse( - "2016-05-16 04:05:06.789120 blah", "YYYY-MM-DD hh:mm:ss.S" - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - # test one additional space along with T divider - self.assertEqual( - self.parser.parse( - "blah 2016-05-16T04:05:06.789120", "YYYY-MM-DDThh:mm:ss.S" - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - self.assertEqual( - self.parser.parse( - "2016-05-16T04:05:06.789120 blah", "YYYY-MM-DDThh:mm:ss.S" - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - self.assertEqual( - self.parser.parse( - "Meet me at 2016-05-16T04:05:06.789120 at the restaurant.", - "YYYY-MM-DDThh:mm:ss.S", - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - self.assertEqual( - self.parser.parse( - "Meet me at 2016-05-16 04:05:06.789120 at the restaurant.", - "YYYY-MM-DD hh:mm:ss.S", - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - # regression test for issue #701 - # tests cases of a partial match surrounded by punctuation - # for the list of valid punctuation, see documentation - def test_parse_with_punctuation_fences(self): - self.assertEqual( - self.parser.parse( - "Meet me at my house on Halloween (2019-31-10)", "YYYY-DD-MM" - ), - datetime(2019, 10, 31), - ) - - self.assertEqual( - self.parser.parse( - "Monday, 9. September 2019, 16:15-20:00", "dddd, D. MMMM YYYY" - ), - datetime(2019, 9, 9), - ) - - self.assertEqual( - self.parser.parse("A date is 11.11.2011.", "DD.MM.YYYY"), - datetime(2011, 11, 11), - ) - - with self.assertRaises(ParserMatchError): - self.parser.parse("11.11.2011.1 is not a valid date.", "DD.MM.YYYY") - - with self.assertRaises(ParserMatchError): - self.parser.parse( - "This date has too many punctuation marks following it (11.11.2011).", - "DD.MM.YYYY", - ) - - def test_parse_with_leading_and_trailing_whitespace(self): - self.assertEqual(self.parser.parse(" 2016", "YYYY"), datetime(2016, 1, 1)) - - self.assertEqual(self.parser.parse("2016 ", "YYYY"), datetime(2016, 1, 1)) - - self.assertEqual( - self.parser.parse(" 2016 ", "YYYY"), datetime(2016, 1, 1) - ) - - self.assertEqual( - self.parser.parse( - " 2016-05-16 04:05:06.789120 ", "YYYY-MM-DD hh:mm:ss.S" - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - self.assertEqual( - self.parser.parse( - " 2016-05-16T04:05:06.789120 ", "YYYY-MM-DDThh:mm:ss.S" - ), - datetime(2016, 5, 16, 4, 5, 6, 789120), - ) - - def test_parse_YYYY_DDDD(self): - self.assertEqual( - self.parser.parse("1998-136", "YYYY-DDDD"), datetime(1998, 5, 16) - ) - - self.assertEqual( - self.parser.parse("1998-006", "YYYY-DDDD"), datetime(1998, 1, 6) - ) - - with self.assertRaises(ParserError): - self.parser.parse("1998-456", "YYYY-DDDD") - - def test_parse_YYYY_DDD(self): - self.assertEqual(self.parser.parse("1998-6", "YYYY-DDD"), datetime(1998, 1, 6)) - - self.assertEqual( - self.parser.parse("1998-136", "YYYY-DDD"), datetime(1998, 5, 16) - ) - - with self.assertRaises(ParserError): - self.parser.parse("1998-756", "YYYY-DDD") - - # month cannot be passed with DDD and DDDD tokens - def test_parse_YYYY_MM_DDDD(self): - with self.assertRaises(ParserError): - self.parser.parse("2015-01-009", "YYYY-MM-DDDD") - - # year is required with the DDD and DDDD tokens - def test_parse_DDD_only(self): - with self.assertRaises(ParserError): - self.parser.parse("5", "DDD") - - def test_parse_DDDD_only(self): - with self.assertRaises(ParserError): - self.parser.parse("145", "DDDD") - - def test_parse_HH_24(self): - self.assertEqual( - self.parser.parse("2019-10-30T24:00:00", "YYYY-MM-DDTHH:mm:ss"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse("2019-10-30T24:00", "YYYY-MM-DDTHH:mm"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse("2019-10-30T24", "YYYY-MM-DDTHH"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse("2019-10-30T24:00:00.0", "YYYY-MM-DDTHH:mm:ss.S"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse("2019-10-31T24:00:00", "YYYY-MM-DDTHH:mm:ss"), - datetime(2019, 11, 1, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse("2019-12-31T24:00:00", "YYYY-MM-DDTHH:mm:ss"), - datetime(2020, 1, 1, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse("2019-12-31T23:59:59.9999999", "YYYY-MM-DDTHH:mm:ss.S"), - datetime(2020, 1, 1, 0, 0, 0, 0), - ) - - with self.assertRaises(ParserError): - self.parser.parse("2019-12-31T24:01:00", "YYYY-MM-DDTHH:mm:ss") - - with self.assertRaises(ParserError): - self.parser.parse("2019-12-31T24:00:01", "YYYY-MM-DDTHH:mm:ss") - - with self.assertRaises(ParserError): - self.parser.parse("2019-12-31T24:00:00.1", "YYYY-MM-DDTHH:mm:ss.S") - - with self.assertRaises(ParserError): - self.parser.parse("2019-12-31T24:00:00.999999", "YYYY-MM-DDTHH:mm:ss.S") - - -class DateTimeParserRegexTests(Chai): - def setUp(self): - super(DateTimeParserRegexTests, self).setUp() - - self.format_regex = parser.DateTimeParser._FORMAT_RE - - def test_format_year(self): - - self.assertEqual(self.format_regex.findall("YYYY-YY"), ["YYYY", "YY"]) - - def test_format_month(self): - - self.assertEqual( - self.format_regex.findall("MMMM-MMM-MM-M"), ["MMMM", "MMM", "MM", "M"] - ) - - def test_format_day(self): - - self.assertEqual( - self.format_regex.findall("DDDD-DDD-DD-D"), ["DDDD", "DDD", "DD", "D"] - ) - - def test_format_hour(self): - - self.assertEqual(self.format_regex.findall("HH-H-hh-h"), ["HH", "H", "hh", "h"]) - - def test_format_minute(self): - - self.assertEqual(self.format_regex.findall("mm-m"), ["mm", "m"]) - - def test_format_second(self): - - self.assertEqual(self.format_regex.findall("ss-s"), ["ss", "s"]) - - def test_format_subsecond(self): - - self.assertEqual( - self.format_regex.findall("SSSSSS-SSSSS-SSSS-SSS-SS-S"), - ["SSSSSS", "SSSSS", "SSSS", "SSS", "SS", "S"], - ) - - def test_format_tz(self): - - self.assertEqual(self.format_regex.findall("ZZZ-ZZ-Z"), ["ZZZ", "ZZ", "Z"]) - - def test_format_am_pm(self): - - self.assertEqual(self.format_regex.findall("A-a"), ["A", "a"]) - - def test_format_timestamp(self): - - self.assertEqual(self.format_regex.findall("X"), ["X"]) - - def test_format_timestamp_milli(self): - - self.assertEqual(self.format_regex.findall("x"), ["x"]) - - def test_escape(self): - - escape_regex = parser.DateTimeParser._ESCAPE_RE - - self.assertEqual( - escape_regex.findall("2018-03-09 8 [h] 40 [hello]"), ["[h]", "[hello]"] - ) - - def test_month_names(self): - p = parser.DateTimeParser("en_us") - - text = "_".join(calendar.month_name[1:]) - - result = p._input_re_map["MMMM"].findall(text) - - self.assertEqual(result, calendar.month_name[1:]) - - def test_month_abbreviations(self): - p = parser.DateTimeParser("en_us") - - text = "_".join(calendar.month_abbr[1:]) - - result = p._input_re_map["MMM"].findall(text) - - self.assertEqual(result, calendar.month_abbr[1:]) - - def test_digits(self): - - self.assertEqual( - parser.DateTimeParser._ONE_OR_TWO_DIGIT_RE.findall("4-56"), ["4", "56"] - ) - self.assertEqual( - parser.DateTimeParser._ONE_OR_TWO_OR_THREE_DIGIT_RE.findall("4-56-789"), - ["4", "56", "789"], - ) - self.assertEqual( - parser.DateTimeParser._ONE_OR_MORE_DIGIT_RE.findall("4-56-789-1234-12345"), - ["4", "56", "789", "1234", "12345"], - ) - self.assertEqual( - parser.DateTimeParser._TWO_DIGIT_RE.findall("12-3-45"), ["12", "45"] - ) - self.assertEqual( - parser.DateTimeParser._THREE_DIGIT_RE.findall("123-4-56"), ["123"] - ) - self.assertEqual( - parser.DateTimeParser._FOUR_DIGIT_RE.findall("1234-56"), ["1234"] - ) - - def test_tz(self): - tz_z_re = parser.DateTimeParser._TZ_Z_RE - self.assertEqual(tz_z_re.findall("-0700"), [("-", "07", "00")]) - self.assertEqual(tz_z_re.findall("+07"), [("+", "07", "")]) - self.assertTrue(tz_z_re.search("15/01/2019T04:05:06.789120Z") is not None) - self.assertTrue(tz_z_re.search("15/01/2019T04:05:06.789120") is None) - - tz_zz_re = parser.DateTimeParser._TZ_ZZ_RE - self.assertEqual(tz_zz_re.findall("-07:00"), [("-", "07", "00")]) - self.assertEqual(tz_zz_re.findall("+07"), [("+", "07", "")]) - self.assertTrue(tz_zz_re.search("15/01/2019T04:05:06.789120Z") is not None) - self.assertTrue(tz_zz_re.search("15/01/2019T04:05:06.789120") is None) - - tz_name_re = parser.DateTimeParser._TZ_NAME_RE - self.assertEqual(tz_name_re.findall("Europe/Warsaw"), ["Europe/Warsaw"]) - self.assertEqual(tz_name_re.findall("GMT"), ["GMT"]) - - def test_timestamp(self): - timestamp_re = parser.DateTimeParser._TIMESTAMP_RE - self.assertEqual( - timestamp_re.findall("1565707550.452729"), ["1565707550.452729"] - ) - self.assertEqual( - timestamp_re.findall("-1565707550.452729"), ["-1565707550.452729"] - ) - self.assertEqual(timestamp_re.findall("-1565707550"), ["-1565707550"]) - self.assertEqual(timestamp_re.findall("1565707550"), ["1565707550"]) - self.assertEqual(timestamp_re.findall("1565707550."), []) - self.assertEqual(timestamp_re.findall(".1565707550"), []) - - def test_timestamp_milli(self): - timestamp_expanded_re = parser.DateTimeParser._TIMESTAMP_EXPANDED_RE - self.assertEqual(timestamp_expanded_re.findall("-1565707550"), ["-1565707550"]) - self.assertEqual(timestamp_expanded_re.findall("1565707550"), ["1565707550"]) - self.assertEqual(timestamp_expanded_re.findall("1565707550.452729"), []) - self.assertEqual(timestamp_expanded_re.findall("1565707550."), []) - self.assertEqual(timestamp_expanded_re.findall(".1565707550"), []) - - def test_time(self): - time_re = parser.DateTimeParser._TIME_RE - time_seperators = [":", ""] - - for sep in time_seperators: - self.assertEqual(time_re.findall("12"), [("12", "", "", "", "")]) - self.assertEqual( - time_re.findall("12{sep}35".format(sep=sep)), [("12", "35", "", "", "")] - ) - self.assertEqual( - time_re.findall("12{sep}35{sep}46".format(sep=sep)), - [("12", "35", "46", "", "")], - ) - self.assertEqual( - time_re.findall("12{sep}35{sep}46.952313".format(sep=sep)), - [("12", "35", "46", ".", "952313")], - ) - self.assertEqual( - time_re.findall("12{sep}35{sep}46,952313".format(sep=sep)), - [("12", "35", "46", ",", "952313")], - ) - - self.assertEqual(time_re.findall("12:"), []) - self.assertEqual(time_re.findall("12:35:46."), []) - self.assertEqual(time_re.findall("12:35:46,"), []) - - -class DateTimeParserISOTests(Chai): - def setUp(self): - super(DateTimeParserISOTests, self).setUp() - - self.parser = parser.DateTimeParser("en_us") - - def test_YYYY(self): - - self.assertEqual(self.parser.parse_iso("2013"), datetime(2013, 1, 1)) - - def test_YYYY_DDDD(self): - self.assertEqual(self.parser.parse_iso("1998-136"), datetime(1998, 5, 16)) - - self.assertEqual(self.parser.parse_iso("1998-006"), datetime(1998, 1, 6)) - - with self.assertRaises(ParserError): - self.parser.parse_iso("1998-456") - - # 2016 is a leap year, so Feb 29 exists (leap day) - self.assertEqual(self.parser.parse_iso("2016-059"), datetime(2016, 2, 28)) - self.assertEqual(self.parser.parse_iso("2016-060"), datetime(2016, 2, 29)) - self.assertEqual(self.parser.parse_iso("2016-061"), datetime(2016, 3, 1)) - - # 2017 is not a leap year, so Feb 29 does not exist - self.assertEqual(self.parser.parse_iso("2017-059"), datetime(2017, 2, 28)) - self.assertEqual(self.parser.parse_iso("2017-060"), datetime(2017, 3, 1)) - self.assertEqual(self.parser.parse_iso("2017-061"), datetime(2017, 3, 2)) - - # Since 2016 is a leap year, the 366th day falls in the same year - self.assertEqual(self.parser.parse_iso("2016-366"), datetime(2016, 12, 31)) - - # Since 2017 is not a leap year, the 366th day falls in the next year - self.assertEqual(self.parser.parse_iso("2017-366"), datetime(2018, 1, 1)) - - def test_YYYY_DDDD_HH_mm_ssZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-036 04:05:06+01:00"), - datetime(2013, 2, 5, 4, 5, 6, tzinfo=tz.tzoffset(None, 3600)), - ) - - self.assertEqual( - self.parser.parse_iso("2013-036 04:05:06Z"), - datetime(2013, 2, 5, 4, 5, 6, tzinfo=tz.tzutc()), - ) - - def test_YYYY_MM_DDDD(self): - with self.assertRaises(ParserError): - self.parser.parse_iso("2014-05-125") - - def test_YYYY_MM(self): - - for separator in DateTimeParser.SEPARATORS: - self.assertEqual( - self.parser.parse_iso(separator.join(("2013", "02"))), - datetime(2013, 2, 1), - ) - - def test_YYYY_MM_DD(self): - - for separator in DateTimeParser.SEPARATORS: - self.assertEqual( - self.parser.parse_iso(separator.join(("2013", "02", "03"))), - datetime(2013, 2, 3), - ) - - def test_YYYY_MM_DDTHH_mmZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05+01:00"), - datetime(2013, 2, 3, 4, 5, tzinfo=tz.tzoffset(None, 3600)), - ) - - def test_YYYY_MM_DDTHH_mm(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05"), datetime(2013, 2, 3, 4, 5) - ) - - def test_YYYY_MM_DDTHH(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04"), datetime(2013, 2, 3, 4) - ) - - def test_YYYY_MM_DDTHHZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04+01:00"), - datetime(2013, 2, 3, 4, tzinfo=tz.tzoffset(None, 3600)), - ) - - def test_YYYY_MM_DDTHH_mm_ssZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06+01:00"), - datetime(2013, 2, 3, 4, 5, 6, tzinfo=tz.tzoffset(None, 3600)), - ) - - def test_YYYY_MM_DDTHH_mm_ss(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06"), datetime(2013, 2, 3, 4, 5, 6) - ) - - def test_YYYY_MM_DD_HH_mmZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03 04:05+01:00"), - datetime(2013, 2, 3, 4, 5, tzinfo=tz.tzoffset(None, 3600)), - ) - - def test_YYYY_MM_DD_HH_mm(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03 04:05"), datetime(2013, 2, 3, 4, 5) - ) - - def test_YYYY_MM_DD_HH(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03 04"), datetime(2013, 2, 3, 4) - ) - - def test_invalid_time(self): - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03 044") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03 04:05:06.") - - def test_YYYY_MM_DD_HH_mm_ssZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03 04:05:06+01:00"), - datetime(2013, 2, 3, 4, 5, 6, tzinfo=tz.tzoffset(None, 3600)), - ) - - def test_YYYY_MM_DD_HH_mm_ss(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03 04:05:06"), datetime(2013, 2, 3, 4, 5, 6) - ) - - def test_YYYY_MM_DDTHH_mm_ss_S(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.7"), - datetime(2013, 2, 3, 4, 5, 6, 700000), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.78"), - datetime(2013, 2, 3, 4, 5, 6, 780000), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.789"), - datetime(2013, 2, 3, 4, 5, 6, 789000), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.7891"), - datetime(2013, 2, 3, 4, 5, 6, 789100), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.78912"), - datetime(2013, 2, 3, 4, 5, 6, 789120), - ) - - # ISO 8601:2004(E), ISO, 2004-12-01, 4.2.2.4 ... the decimal fraction - # shall be divided from the integer part by the decimal sign specified - # in ISO 31-0, i.e. the comma [,] or full stop [.]. Of these, the comma - # is the preferred sign. - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06,789123678"), - datetime(2013, 2, 3, 4, 5, 6, 789124), - ) - - # there is no limit on the number of decimal places - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.789123678"), - datetime(2013, 2, 3, 4, 5, 6, 789124), - ) - - def test_YYYY_MM_DDTHH_mm_ss_SZ(self): - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.7+01:00"), - datetime(2013, 2, 3, 4, 5, 6, 700000, tzinfo=tz.tzoffset(None, 3600)), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.78+01:00"), - datetime(2013, 2, 3, 4, 5, 6, 780000, tzinfo=tz.tzoffset(None, 3600)), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.789+01:00"), - datetime(2013, 2, 3, 4, 5, 6, 789000, tzinfo=tz.tzoffset(None, 3600)), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.7891+01:00"), - datetime(2013, 2, 3, 4, 5, 6, 789100, tzinfo=tz.tzoffset(None, 3600)), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03T04:05:06.78912+01:00"), - datetime(2013, 2, 3, 4, 5, 6, 789120, tzinfo=tz.tzoffset(None, 3600)), - ) - - self.assertEqual( - self.parser.parse_iso("2013-02-03 04:05:06.78912Z"), - datetime(2013, 2, 3, 4, 5, 6, 789120, tzinfo=tz.tzutc()), - ) - - def test_invalid_Z(self): - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912z") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912zz") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912Zz") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912ZZ") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912+Z") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912-Z") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2013-02-03T04:05:06.78912 Z") - - def test_parse_subsecond(self): - # TODO: make both test_parse_subsecond functions in Parse and ParseISO - # tests use the same expected objects (use pytest fixtures) - self.expected = datetime(2013, 1, 1, 12, 30, 45, 900000) - self.assertEqual(self.parser.parse_iso("2013-01-01 12:30:45.9"), self.expected) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 980000) - self.assertEqual(self.parser.parse_iso("2013-01-01 12:30:45.98"), self.expected) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987000) - self.assertEqual( - self.parser.parse_iso("2013-01-01 12:30:45.987"), self.expected - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987600) - self.assertEqual( - self.parser.parse_iso("2013-01-01 12:30:45.9876"), self.expected - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987650) - self.assertEqual( - self.parser.parse_iso("2013-01-01 12:30:45.98765"), self.expected - ) - - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) - self.assertEqual( - self.parser.parse_iso("2013-01-01 12:30:45.987654"), self.expected - ) - - # use comma as subsecond separator - self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) - self.assertEqual( - self.parser.parse_iso("2013-01-01 12:30:45,987654"), self.expected - ) - - def test_gnu_date(self): - """ - regression tests for parsing output from GNU date(1) - """ - # date -Ins - self.assertEqual( - self.parser.parse_iso("2016-11-16T09:46:30,895636557-0800"), - datetime( - 2016, 11, 16, 9, 46, 30, 895636, tzinfo=tz.tzoffset(None, -3600 * 8) - ), - ) - - # date --rfc-3339=ns - self.assertEqual( - self.parser.parse_iso("2016-11-16 09:51:14.682141526-08:00"), - datetime( - 2016, 11, 16, 9, 51, 14, 682142, tzinfo=tz.tzoffset(None, -3600 * 8) - ), - ) - - def test_isoformat(self): - - dt = datetime.utcnow() - - self.assertEqual(self.parser.parse_iso(dt.isoformat()), dt) - - def test_parse_iso_with_leading_and_trailing_whitespace(self): - datetime_string = " 2016-11-15T06:37:19.123456" - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - datetime_string = " 2016-11-15T06:37:19.123456 " - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - datetime_string = "2016-11-15T06:37:19.123456 " - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - datetime_string = "2016-11-15T 06:37:19.123456" - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - # leading whitespace - datetime_string = " 2016-11-15 06:37:19.123456" - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - # trailing whitespace - datetime_string = "2016-11-15 06:37:19.123456 " - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - datetime_string = " 2016-11-15 06:37:19.123456 " - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - # two dividing spaces - datetime_string = "2016-11-15 06:37:19.123456" - with self.assertRaises(ParserError): - self.parser.parse_iso(datetime_string) - - def test_parse_iso_with_extra_words_at_start_and_end_invalid(self): - test_inputs = [ - "blah2016", - "blah2016blah", - "blah 2016 blah", - "blah 2016", - "2016 blah", - "blah 2016-05-16 04:05:06.789120", - "2016-05-16 04:05:06.789120 blah", - "blah 2016-05-16T04:05:06.789120", - "2016-05-16T04:05:06.789120 blah", - "2016blah", - "2016-05blah", - "2016-05-16blah", - "2016-05-16T04:05:06.789120blah", - "2016-05-16T04:05:06.789120ZblahZ", - "2016-05-16T04:05:06.789120Zblah", - "2016-05-16T04:05:06.789120blahZ", - "Meet me at 2016-05-16T04:05:06.789120 at the restaurant.", - "Meet me at 2016-05-16 04:05:06.789120 at the restaurant.", - ] - - for ti in test_inputs: - with self.assertRaises(ParserError): - self.parser.parse_iso(ti) - - def test_iso8601_basic_format(self): - self.assertEqual(self.parser.parse_iso("20180517"), datetime(2018, 5, 17)) - - self.assertEqual( - self.parser.parse_iso("20180517T10"), datetime(2018, 5, 17, 10) - ) - - self.assertEqual( - self.parser.parse_iso("20180517T105513.843456"), - datetime(2018, 5, 17, 10, 55, 13, 843456), - ) - - self.assertEqual( - self.parser.parse_iso("20180517T105513Z"), - datetime(2018, 5, 17, 10, 55, 13, tzinfo=tz.tzutc()), - ) - - self.assertEqual( - self.parser.parse_iso("20180517T105513.843456-0700"), - datetime(2018, 5, 17, 10, 55, 13, 843456, tzinfo=tz.tzoffset(None, -25200)), - ) - - self.assertEqual( - self.parser.parse_iso("20180517T105513-0700"), - datetime(2018, 5, 17, 10, 55, 13, tzinfo=tz.tzoffset(None, -25200)), - ) - - self.assertEqual( - self.parser.parse_iso("20180517T105513-07"), - datetime(2018, 5, 17, 10, 55, 13, tzinfo=tz.tzoffset(None, -25200)), - ) - - # ordinal in basic format: YYYYDDDD - self.assertEqual(self.parser.parse_iso("1998136"), datetime(1998, 5, 16)) - - # timezone requires +- seperator - with self.assertRaises(ParserError): - self.parser.parse_iso("20180517T1055130700") - - with self.assertRaises(ParserError): - self.parser.parse_iso("20180517T10551307") - - # too many digits in date - with self.assertRaises(ParserError): - self.parser.parse_iso("201860517T105513Z") - - # too many digits in time - with self.assertRaises(ParserError): - self.parser.parse_iso("20180517T1055213Z") - - def test_midnight_end_day(self): - self.assertEqual( - self.parser.parse_iso("2019-10-30T24:00:00"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse_iso("2019-10-30T24:00"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse_iso("2019-10-30T24:00:00.0"), - datetime(2019, 10, 31, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse_iso("2019-10-31T24:00:00"), - datetime(2019, 11, 1, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse_iso("2019-12-31T24:00:00"), - datetime(2020, 1, 1, 0, 0, 0, 0), - ) - self.assertEqual( - self.parser.parse_iso("2019-12-31T23:59:59.9999999"), - datetime(2020, 1, 1, 0, 0, 0, 0), - ) - - with self.assertRaises(ParserError): - self.parser.parse_iso("2019-12-31T24:01:00") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2019-12-31T24:00:01") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2019-12-31T24:00:00.1") - - with self.assertRaises(ParserError): - self.parser.parse_iso("2019-12-31T24:00:00.999999") - - -class TzinfoParserTests(Chai): - def setUp(self): - super(TzinfoParserTests, self).setUp() - - self.parser = parser.TzinfoParser() - - def test_parse_local(self): - - self.assertEqual(self.parser.parse("local"), tz.tzlocal()) - - def test_parse_utc(self): - - self.assertEqual(self.parser.parse("utc"), tz.tzutc()) - self.assertEqual(self.parser.parse("UTC"), tz.tzutc()) - - def test_parse_iso(self): - - self.assertEqual(self.parser.parse("01:00"), tz.tzoffset(None, 3600)) - self.assertEqual( - self.parser.parse("11:35"), tz.tzoffset(None, 11 * 3600 + 2100) - ) - self.assertEqual(self.parser.parse("+01:00"), tz.tzoffset(None, 3600)) - self.assertEqual(self.parser.parse("-01:00"), tz.tzoffset(None, -3600)) - - self.assertEqual(self.parser.parse("0100"), tz.tzoffset(None, 3600)) - self.assertEqual(self.parser.parse("+0100"), tz.tzoffset(None, 3600)) - self.assertEqual(self.parser.parse("-0100"), tz.tzoffset(None, -3600)) - - self.assertEqual(self.parser.parse("01"), tz.tzoffset(None, 3600)) - self.assertEqual(self.parser.parse("+01"), tz.tzoffset(None, 3600)) - self.assertEqual(self.parser.parse("-01"), tz.tzoffset(None, -3600)) - - def test_parse_str(self): - - self.assertEqual(self.parser.parse("US/Pacific"), tz.gettz("US/Pacific")) - - def test_parse_fails(self): - - with self.assertRaises(parser.ParserError): - self.parser.parse("fail") - - -class DateTimeParserMonthNameTests(Chai): - def setUp(self): - super(DateTimeParserMonthNameTests, self).setUp() - - self.parser = parser.DateTimeParser("en_us") - - def test_shortmonth_capitalized(self): - - self.assertEqual( - self.parser.parse("2013-Jan-01", "YYYY-MMM-DD"), datetime(2013, 1, 1) - ) - - def test_shortmonth_allupper(self): - - self.assertEqual( - self.parser.parse("2013-JAN-01", "YYYY-MMM-DD"), datetime(2013, 1, 1) - ) - - def test_shortmonth_alllower(self): - - self.assertEqual( - self.parser.parse("2013-jan-01", "YYYY-MMM-DD"), datetime(2013, 1, 1) - ) - - def test_month_capitalized(self): - - self.assertEqual( - self.parser.parse("2013-January-01", "YYYY-MMMM-DD"), datetime(2013, 1, 1) - ) - - def test_month_allupper(self): - - self.assertEqual( - self.parser.parse("2013-JANUARY-01", "YYYY-MMMM-DD"), datetime(2013, 1, 1) - ) - - def test_month_alllower(self): - - self.assertEqual( - self.parser.parse("2013-january-01", "YYYY-MMMM-DD"), datetime(2013, 1, 1) - ) - - def test_localized_month_name(self): - parser_ = parser.DateTimeParser("fr_fr") - - self.assertEqual( - parser_.parse("2013-Janvier-01", "YYYY-MMMM-DD"), datetime(2013, 1, 1) - ) - - def test_localized_month_abbreviation(self): - parser_ = parser.DateTimeParser("it_it") - - self.assertEqual( - parser_.parse("2013-Gen-01", "YYYY-MMM-DD"), datetime(2013, 1, 1) - ) - - -class DateTimeParserMeridiansTests(Chai): - def setUp(self): - super(DateTimeParserMeridiansTests, self).setUp() - - self.parser = parser.DateTimeParser("en_us") - - def test_meridians_lowercase(self): - self.assertEqual( - self.parser.parse("2013-01-01 5am", "YYYY-MM-DD ha"), - datetime(2013, 1, 1, 5), - ) - - self.assertEqual( - self.parser.parse("2013-01-01 5pm", "YYYY-MM-DD ha"), - datetime(2013, 1, 1, 17), - ) - - def test_meridians_capitalized(self): - self.assertEqual( - self.parser.parse("2013-01-01 5AM", "YYYY-MM-DD hA"), - datetime(2013, 1, 1, 5), - ) - - self.assertEqual( - self.parser.parse("2013-01-01 5PM", "YYYY-MM-DD hA"), - datetime(2013, 1, 1, 17), - ) - - def test_localized_meridians_lowercase(self): - parser_ = parser.DateTimeParser("hu_hu") - self.assertEqual( - parser_.parse("2013-01-01 5 de", "YYYY-MM-DD h a"), datetime(2013, 1, 1, 5) - ) - - self.assertEqual( - parser_.parse("2013-01-01 5 du", "YYYY-MM-DD h a"), datetime(2013, 1, 1, 17) - ) - - def test_localized_meridians_capitalized(self): - parser_ = parser.DateTimeParser("hu_hu") - self.assertEqual( - parser_.parse("2013-01-01 5 DE", "YYYY-MM-DD h A"), datetime(2013, 1, 1, 5) - ) - - self.assertEqual( - parser_.parse("2013-01-01 5 DU", "YYYY-MM-DD h A"), datetime(2013, 1, 1, 17) - ) - - # regression test for issue #607 - def test_es_meridians(self): - parser_ = parser.DateTimeParser("es") - - self.assertEqual( - parser_.parse("Junio 30, 2019 - 08:00 pm", "MMMM DD, YYYY - hh:mm a"), - datetime(2019, 6, 30, 20, 0), - ) - - with self.assertRaises(ParserError): - parser_.parse( - "Junio 30, 2019 - 08:00 pasdfasdfm", "MMMM DD, YYYY - hh:mm a" - ) - - def test_fr_meridians(self): - parser_ = parser.DateTimeParser("fr") - - # the French locale always uses a 24 hour clock, so it does not support meridians - with self.assertRaises(ParserError): - parser_.parse("Janvier 30, 2019 - 08:00 pm", "MMMM DD, YYYY - hh:mm a") - - -class DateTimeParserMonthOrdinalDayTests(Chai): - def setUp(self): - super(DateTimeParserMonthOrdinalDayTests, self).setUp() - - self.parser = parser.DateTimeParser("en_us") - - def test_english(self): - parser_ = parser.DateTimeParser("en_us") - - self.assertEqual( - parser_.parse("January 1st, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 1) - ) - self.assertEqual( - parser_.parse("January 2nd, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 2) - ) - self.assertEqual( - parser_.parse("January 3rd, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 3) - ) - self.assertEqual( - parser_.parse("January 4th, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 4) - ) - self.assertEqual( - parser_.parse("January 11th, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 11) - ) - self.assertEqual( - parser_.parse("January 12th, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 12) - ) - self.assertEqual( - parser_.parse("January 13th, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 13) - ) - self.assertEqual( - parser_.parse("January 21st, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 21) - ) - self.assertEqual( - parser_.parse("January 31st, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 31) - ) - - with self.assertRaises(ParserError): - parser_.parse("January 1th, 2013", "MMMM Do, YYYY") - - with self.assertRaises(ParserError): - parser_.parse("January 11st, 2013", "MMMM Do, YYYY") - - def test_italian(self): - parser_ = parser.DateTimeParser("it_it") - - self.assertEqual( - parser_.parse("Gennaio 1º, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 1) - ) - - def test_spanish(self): - parser_ = parser.DateTimeParser("es_es") - - self.assertEqual( - parser_.parse("Enero 1º, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 1) - ) - - def test_french(self): - parser_ = parser.DateTimeParser("fr_fr") - - self.assertEqual( - parser_.parse("Janvier 1er, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 1) - ) - - self.assertEqual( - parser_.parse("Janvier 2e, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 2) - ) - - self.assertEqual( - parser_.parse("Janvier 11e, 2013", "MMMM Do, YYYY"), datetime(2013, 1, 11) - ) - - -class DateTimeParserSearchDateTests(Chai): - def setUp(self): - super(DateTimeParserSearchDateTests, self).setUp() - self.parser = parser.DateTimeParser() - - def test_parse_search(self): - - self.assertEqual( - self.parser.parse("Today is 25 of September of 2003", "DD of MMMM of YYYY"), - datetime(2003, 9, 25), - ) - - def test_parse_search_with_numbers(self): - - self.assertEqual( - self.parser.parse( - "2000 people met the 2012-01-01 12:05:10", "YYYY-MM-DD HH:mm:ss" - ), - datetime(2012, 1, 1, 12, 5, 10), - ) - - self.assertEqual( - self.parser.parse( - "Call 01-02-03 on 79-01-01 12:05:10", "YY-MM-DD HH:mm:ss" - ), - datetime(1979, 1, 1, 12, 5, 10), - ) - - def test_parse_search_with_names(self): - - self.assertEqual( - self.parser.parse("June was born in May 1980", "MMMM YYYY"), - datetime(1980, 5, 1), - ) - - def test_parse_search_locale_with_names(self): - p = parser.DateTimeParser("sv_se") - - self.assertEqual( - p.parse("Jan föddes den 31 Dec 1980", "DD MMM YYYY"), datetime(1980, 12, 31) - ) - - self.assertEqual( - p.parse("Jag föddes den 25 Augusti 1975", "DD MMMM YYYY"), - datetime(1975, 8, 25), - ) - - def test_parse_search_fails(self): - - with self.assertRaises(parser.ParserError): - self.parser.parse("Jag föddes den 25 Augusti 1975", "DD MMMM YYYY") - - def test_escape(self): - - format = "MMMM D, YYYY [at] h:mma" - self.assertEqual( - self.parser.parse("Thursday, December 10, 2015 at 5:09pm", format), - datetime(2015, 12, 10, 17, 9), - ) - - format = "[MMMM] M D, YYYY [at] h:mma" - self.assertEqual( - self.parser.parse("MMMM 12 10, 2015 at 5:09pm", format), - datetime(2015, 12, 10, 17, 9), - ) - - format = "[It happened on] MMMM Do [in the year] YYYY [a long time ago]" - self.assertEqual( - self.parser.parse( - "It happened on November 25th in the year 1990 a long time ago", format - ), - datetime(1990, 11, 25), - ) - - format = "[It happened on] MMMM Do [in the][ year] YYYY [a long time ago]" - self.assertEqual( - self.parser.parse( - "It happened on November 25th in the year 1990 a long time ago", format - ), - datetime(1990, 11, 25), - ) - - format = "[I'm][ entirely][ escaped,][ weee!]" - self.assertEqual( - self.parser.parse("I'm entirely escaped, weee!", format), datetime(1, 1, 1) - ) - - # Special RegEx characters - format = "MMM DD, YYYY |^${}().*+?<>-& h:mm A" - self.assertEqual( - self.parser.parse("Dec 31, 2017 |^${}().*+?<>-& 2:00 AM", format), - datetime(2017, 12, 31, 2, 0), - ) diff --git a/tests/api_tests.py b/tests/test_api.py similarity index 100% rename from tests/api_tests.py rename to tests/test_api.py diff --git a/tests/arrow_tests.py b/tests/test_arrow.py similarity index 98% rename from tests/arrow_tests.py rename to tests/test_arrow.py index 561b81973..58c035e00 100644 --- a/tests/arrow_tests.py +++ b/tests/test_arrow.py @@ -13,12 +13,9 @@ from dateutil import tz from dateutil.relativedelta import FR, MO, SA, SU, TH, TU, WE -from arrow import arrow, util +from arrow import arrow - -def assertDtEqual(dt1, dt2, within=10): - assert dt1.tzinfo == dt2.tzinfo - assert abs(util.total_seconds(dt1 - dt2)) < within +from .utils import assert_datetime_equality class TestTestArrowInit: @@ -73,7 +70,7 @@ def test_init_pytz_timezone(self): 2013, 2, 2, 12, 30, 45, 999999, tzinfo=tz.gettz("Europe/Paris") ) assert result._datetime == self.expected - assertDtEqual(result._datetime, self.expected, 1) + assert_datetime_equality(result._datetime, self.expected, 1) class TestTestArrowFactory: @@ -81,29 +78,35 @@ def test_now(self): result = arrow.Arrow.now() - assertDtEqual(result._datetime, datetime.now().replace(tzinfo=tz.tzlocal())) + assert_datetime_equality( + result._datetime, datetime.now().replace(tzinfo=tz.tzlocal()) + ) def test_utcnow(self): result = arrow.Arrow.utcnow() - assertDtEqual(result._datetime, datetime.utcnow().replace(tzinfo=tz.tzutc())) + assert_datetime_equality( + result._datetime, datetime.utcnow().replace(tzinfo=tz.tzutc()) + ) def test_fromtimestamp(self): timestamp = time.time() result = arrow.Arrow.fromtimestamp(timestamp) - assertDtEqual(result._datetime, datetime.now().replace(tzinfo=tz.tzlocal())) + assert_datetime_equality( + result._datetime, datetime.now().replace(tzinfo=tz.tzlocal()) + ) result = arrow.Arrow.fromtimestamp(timestamp, tzinfo=tz.gettz("Europe/Paris")) - assertDtEqual( + assert_datetime_equality( result._datetime, datetime.fromtimestamp(timestamp, tz.gettz("Europe/Paris")), ) result = arrow.Arrow.fromtimestamp(timestamp, tzinfo="Europe/Paris") - assertDtEqual( + assert_datetime_equality( result._datetime, datetime.fromtimestamp(timestamp, tz.gettz("Europe/Paris")), ) @@ -116,7 +119,9 @@ def test_utcfromtimestamp(self): timestamp = time.time() result = arrow.Arrow.utcfromtimestamp(timestamp) - assertDtEqual(result._datetime, datetime.utcnow().replace(tzinfo=tz.tzutc())) + assert_datetime_equality( + result._datetime, datetime.utcnow().replace(tzinfo=tz.tzutc()) + ) with pytest.raises(ValueError): arrow.Arrow.utcfromtimestamp("invalid timestamp") diff --git a/tests/factory_tests.py b/tests/test_factory.py similarity index 89% rename from tests/factory_tests.py rename to tests/test_factory.py index 840e9651c..a94a5ade9 100644 --- a/tests/factory_tests.py +++ b/tests/test_factory.py @@ -3,16 +3,13 @@ from datetime import date, datetime import dateparser +import pytest from dateutil import tz -from arrow import factory, util +from arrow import factory from arrow.parser import ParserError -import pytest - -def assertDtEqual(dt1, dt2, within=10): - assert dt1.tzinfo == dt2.tzinfo - assert abs(util.total_seconds(dt1 - dt2)) < within +from .utils import assert_datetime_equality class TestGet: @@ -22,7 +19,9 @@ def setup_class(cls): def test_no_args(self): - assertDtEqual(self.factory.get(), datetime.utcnow().replace(tzinfo=tz.tzutc())) + assert_datetime_equality( + self.factory.get(), datetime.utcnow().replace(tzinfo=tz.tzutc()) + ) def test_timestamp_one_arg_no_arg(self): @@ -33,13 +32,13 @@ def test_timestamp_one_arg_no_arg(self): def test_one_arg_none(self): - assertDtEqual( + assert_datetime_equality( self.factory.get(None), datetime.utcnow().replace(tzinfo=tz.tzutc()) ) def test_struct_time(self): - assertDtEqual( + assert_datetime_equality( self.factory.get(time.gmtime()), datetime.utcnow().replace(tzinfo=tz.tzutc()), ) @@ -80,7 +79,9 @@ def test_one_arg_timestamp_with_tzinfo(self): ) timezone = tz.gettz("US/Pacific") - assertDtEqual(self.factory.get(timestamp, tzinfo=timezone), timestamp_dt) + assert_datetime_equality( + self.factory.get(timestamp, tzinfo=timezone), timestamp_dt + ) def test_one_arg_arrow(self): @@ -110,7 +111,9 @@ def test_one_arg_tzinfo(self): .astimezone(tz.gettz("US/Pacific")) ) - assertDtEqual(self.factory.get(tz.gettz("US/Pacific")), self.expected) + assert_datetime_equality( + self.factory.get(tz.gettz("US/Pacific")), self.expected + ) # regression test for issue #658 def test_one_arg_dateparser_datetime(self): @@ -128,7 +131,9 @@ def test_kwarg_tzinfo(self): .astimezone(tz.gettz("US/Pacific")) ) - assertDtEqual(self.factory.get(tzinfo=tz.gettz("US/Pacific")), self.expected) + assert_datetime_equality( + self.factory.get(tzinfo=tz.gettz("US/Pacific")), self.expected + ) def test_kwarg_tzinfo_string(self): @@ -138,7 +143,7 @@ def test_kwarg_tzinfo_string(self): .astimezone(tz.gettz("US/Pacific")) ) - assertDtEqual(self.factory.get(tzinfo="US/Pacific"), self.expected) + assert_datetime_equality(self.factory.get(tzinfo="US/Pacific"), self.expected) with pytest.raises(ParserError): self.factory.get(tzinfo="US/PacificInvalidTzinfo") @@ -147,7 +152,9 @@ def test_one_arg_iso_str(self): dt = datetime.utcnow() - assertDtEqual(self.factory.get(dt.isoformat()), dt.replace(tzinfo=tz.tzutc())) + assert_datetime_equality( + self.factory.get(dt.isoformat()), dt.replace(tzinfo=tz.tzutc()) + ) def test_one_arg_iso_calendar(self): @@ -235,7 +242,7 @@ def test_two_args_str_tzinfo(self): result = self.factory.get("2013-01-01", tzinfo=tz.gettz("US/Pacific")) - assertDtEqual( + assert_datetime_equality( result._datetime, datetime(2013, 1, 1, tzinfo=tz.gettz("US/Pacific")) ) @@ -333,7 +340,7 @@ def setup_class(cls): def test_utcnow(self): - assertDtEqual( + assert_datetime_equality( self.factory.utcnow()._datetime, datetime.utcnow().replace(tzinfo=tz.tzutc()), ) @@ -346,12 +353,14 @@ def setup_class(cls): def test_no_tz(self): - assertDtEqual(self.factory.now(), datetime.now(tz.tzlocal())) + assert_datetime_equality(self.factory.now(), datetime.now(tz.tzlocal())) def test_tzinfo(self): - assertDtEqual(self.factory.now(tz.gettz("EST")), datetime.now(tz.gettz("EST"))) + assert_datetime_equality( + self.factory.now(tz.gettz("EST")), datetime.now(tz.gettz("EST")) + ) def test_tz_str(self): - assertDtEqual(self.factory.now("EST"), datetime.now(tz.gettz("EST"))) + assert_datetime_equality(self.factory.now("EST"), datetime.now(tz.gettz("EST"))) diff --git a/tests/formatter_tests.py b/tests/test_formatter.py similarity index 100% rename from tests/formatter_tests.py rename to tests/test_formatter.py diff --git a/tests/locales_tests.py b/tests/test_locales.py similarity index 98% rename from tests/locales_tests.py rename to tests/test_locales.py index 1b279ffa7..6002968f6 100644 --- a/tests/locales_tests.py +++ b/tests/test_locales.py @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from arrow import arrow, locales - import pytest +from arrow import arrow, locales + class TestLocaleValidation: """Validate locales to ensure that translations are valid and complete""" @@ -641,11 +641,17 @@ def test_relative_timeframes(self): assert self.locale._format_relative("o oră", "hour", 1) == "peste o oră" assert self.locale._format_relative("o oră", "hour", -1) == "o oră în urmă" assert self.locale._format_relative("un minut", "minute", 1) == "peste un minut" - assert self.locale._format_relative("un minut", "minute", -1) == "un minut în urmă" - assert self.locale._format_relative("câteva secunde", "seconds", -1) == \ - "câteva secunde în urmă" - assert self.locale._format_relative("câteva secunde", "seconds", 1) == \ - "peste câteva secunde" + assert ( + self.locale._format_relative("un minut", "minute", -1) == "un minut în urmă" + ) + assert ( + self.locale._format_relative("câteva secunde", "seconds", -1) + == "câteva secunde în urmă" + ) + assert ( + self.locale._format_relative("câteva secunde", "seconds", 1) + == "peste câteva secunde" + ) assert self.locale._format_relative("o zi", "day", -1) == "o zi în urmă" assert self.locale._format_relative("o zi", "day", 1) == "peste o zi" diff --git a/tests/test_parser.py b/tests/test_parser.py new file mode 100644 index 000000000..039eb4c0a --- /dev/null +++ b/tests/test_parser.py @@ -0,0 +1,1462 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import calendar +import os +import time +from datetime import datetime + +import pytest +from dateutil import tz + +import arrow +from arrow import parser +from arrow.constants import MAX_TIMESTAMP_US +from arrow.parser import DateTimeParser, ParserError, ParserMatchError + +from .utils import make_full_tz_list + + +class TestDateTimeParser: + @classmethod + def setup_class(cls): + cls.parser = parser.DateTimeParser() + + def test_parse_multiformat(self, mocker): + mocker.patch( + "arrow.parser.DateTimeParser.parse", + string="str", + fmt="fmt_a", + side_effect=parser.ParserError, + ) + + with pytest.raises(parser.ParserError): + self.parser._parse_multiformat("str", ["fmt_a"]) + + mock_datetime = mocker.Mock() + mocker.patch( + "arrow.parser.DateTimeParser.parse", + string="str", + fmt="fmt_b", + return_value=mock_datetime, + ) + + result = self.parser._parse_multiformat("str", ["fmt_a", "fmt_b"]) + assert result == mock_datetime + + def test_parse_multiformat_all_fail(self, mocker): + mocker.patch( + "arrow.parser.DateTimeParser.parse", + string="str", + fmt="fmt_a", + side_effect=parser.ParserError, + ) + + mocker.patch( + "arrow.parser.DateTimeParser.parse", + string="str", + fmt="fmt_b", + side_effect=parser.ParserError, + ) + + with pytest.raises(parser.ParserError): + self.parser._parse_multiformat("str", ["fmt_a", "fmt_b"]) + + def test_parse_multiformat_unself_expected_fail(self, mocker): + class UnselfExpectedError(Exception): + pass + + mocker.patch( + "arrow.parser.DateTimeParser.parse", + string="str", + fmt="fmt_a", + side_effect=UnselfExpectedError, + ) + + with pytest.raises(UnselfExpectedError): + self.parser._parse_multiformat("str", ["fmt_a", "fmt_b"]) + + def test_parse_token_nonsense(self): + parts = {} + self.parser._parse_token("NONSENSE", "1900", parts) + assert parts == {} + + def test_parse_token_invalid_meridians(self): + parts = {} + self.parser._parse_token("A", "a..m", parts) + assert parts == {} + self.parser._parse_token("a", "p..m", parts) + assert parts == {} + + def test_parser_no_caching(self, mocker): + + mocked_parser = mocker.patch( + "arrow.parser.DateTimeParser._generate_pattern_re", fmt="fmt_a" + ) + self.parser = parser.DateTimeParser(cache_size=0) + for _ in range(100): + self.parser._generate_pattern_re("fmt_a") + assert mocked_parser.call_count == 100 + + def test_parser_1_line_caching(self, mocker): + mocked_parser = mocker.patch("arrow.parser.DateTimeParser._generate_pattern_re") + self.parser = parser.DateTimeParser(cache_size=1) + + for _ in range(100): + self.parser._generate_pattern_re(fmt="fmt_a") + assert mocked_parser.call_count == 1 + assert mocked_parser.call_args_list[0] == mocker.call(fmt="fmt_a") + + for _ in range(100): + self.parser._generate_pattern_re(fmt="fmt_b") + assert mocked_parser.call_count == 2 + assert mocked_parser.call_args_list[1] == mocker.call(fmt="fmt_b") + + for _ in range(100): + self.parser._generate_pattern_re(fmt="fmt_a") + assert mocked_parser.call_count == 3 + assert mocked_parser.call_args_list[2] == mocker.call(fmt="fmt_a") + + def test_parser_multiple_line_caching(self, mocker): + mocked_parser = mocker.patch("arrow.parser.DateTimeParser._generate_pattern_re") + self.parser = parser.DateTimeParser(cache_size=2) + + for _ in range(100): + self.parser._generate_pattern_re(fmt="fmt_a") + assert mocked_parser.call_count == 1 + assert mocked_parser.call_args_list[0] == mocker.call(fmt="fmt_a") + + for _ in range(100): + self.parser._generate_pattern_re(fmt="fmt_b") + assert mocked_parser.call_count == 2 + assert mocked_parser.call_args_list[1] == mocker.call(fmt="fmt_b") + + # fmt_a and fmt_b are in the cache, so no new calls should be made + for _ in range(100): + self.parser._generate_pattern_re(fmt="fmt_a") + for _ in range(100): + self.parser._generate_pattern_re(fmt="fmt_b") + assert mocked_parser.call_count == 2 + assert mocked_parser.call_args_list[0] == mocker.call(fmt="fmt_a") + assert mocked_parser.call_args_list[1] == mocker.call(fmt="fmt_b") + + def test_YY_and_YYYY_format_list(self): + + assert self.parser.parse("15/01/19", ["DD/MM/YY", "DD/MM/YYYY"]) == datetime( + 2019, 1, 15 + ) + + # Regression test for issue #580 + assert self.parser.parse("15/01/2019", ["DD/MM/YY", "DD/MM/YYYY"]) == datetime( + 2019, 1, 15 + ) + + assert self.parser.parse( + "15/01/2019T04:05:06.789120Z", + ["D/M/YYThh:mm:ss.SZ", "D/M/YYYYThh:mm:ss.SZ"], + ) == datetime(2019, 1, 15, 4, 5, 6, 789120, tzinfo=tz.tzutc()) + + # regression test for issue #447 + def test_timestamp_format_list(self): + # should not match on the "X" token + assert self.parser.parse( + "15 Jul 2000", + ["MM/DD/YYYY", "YYYY-MM-DD", "X", "DD-MMMM-YYYY", "D MMM YYYY"], + ) == datetime(2000, 7, 15) + + with pytest.raises(ParserError): + self.parser.parse("15 Jul", "X") + + +class TestDateTimeParserParse: + @classmethod + def setup_class(cls): + cls.parser = parser.DateTimeParser() + + def test_parse_list(self, mocker): + + mocker.patch( + "arrow.parser.DateTimeParser._parse_multiformat", + string="str", + formats=["fmt_a", "fmt_b"], + return_value="result", + ) + + result = self.parser.parse("str", ["fmt_a", "fmt_b"]) + assert result == "result" + + def test_parse_unrecognized_token(self, mocker): + + mocker.patch.dict("arrow.parser.DateTimeParser._BASE_INPUT_RE_MAP") + del arrow.parser.DateTimeParser._BASE_INPUT_RE_MAP["YYYY"] + + # need to make another local parser to apply patch changes + _parser = parser.DateTimeParser() + with pytest.raises(parser.ParserError): + _parser.parse("2013-01-01", "YYYY-MM-DD") + + def test_parse_parse_no_match(self): + + with pytest.raises(ParserError): + self.parser.parse("01-01", "YYYY-MM-DD") + + def test_parse_separators(self): + + with pytest.raises(ParserError): + self.parser.parse("1403549231", "YYYY-MM-DD") + + def test_parse_numbers(self): + + self.expected = datetime(2012, 1, 1, 12, 5, 10) + assert ( + self.parser.parse("2012-01-01 12:05:10", "YYYY-MM-DD HH:mm:ss") + == self.expected + ) + + def test_parse_year_two_digit(self): + + self.expected = datetime(1979, 1, 1, 12, 5, 10) + assert ( + self.parser.parse("79-01-01 12:05:10", "YY-MM-DD HH:mm:ss") == self.expected + ) + + def test_parse_timestamp(self): + + tz_utc = tz.tzutc() + int_timestamp = int(time.time()) + self.expected = datetime.fromtimestamp(int_timestamp, tz=tz_utc) + assert self.parser.parse("{:d}".format(int_timestamp), "X") == self.expected + + float_timestamp = time.time() + self.expected = datetime.fromtimestamp(float_timestamp, tz=tz_utc) + assert self.parser.parse("{:f}".format(float_timestamp), "X") == self.expected + + # test handling of ns timestamp (arrow will round to 6 digits regardless) + self.expected = datetime.fromtimestamp(float_timestamp, tz=tz_utc) + assert ( + self.parser.parse("{:f}123".format(float_timestamp), "X") == self.expected + ) + + # test ps timestamp (arrow will round to 6 digits regardless) + self.expected = datetime.fromtimestamp(float_timestamp, tz=tz_utc) + assert ( + self.parser.parse("{:f}123456".format(float_timestamp), "X") + == self.expected + ) + + # NOTE: negative timestamps cannot be handled by datetime on Window + # Must use timedelta to handle them. ref: https://stackoverflow.com/questions/36179914 + if os.name != "nt": + # regression test for issue #662 + negative_int_timestamp = -int_timestamp + self.expected = datetime.fromtimestamp(negative_int_timestamp, tz=tz_utc) + assert ( + self.parser.parse("{:d}".format(negative_int_timestamp), "X") + == self.expected + ) + + negative_float_timestamp = -float_timestamp + self.expected = datetime.fromtimestamp(negative_float_timestamp, tz=tz_utc) + assert ( + self.parser.parse("{:f}".format(negative_float_timestamp), "X") + == self.expected + ) + + # NOTE: timestamps cannot be parsed from natural language strings (by removing the ^...$) because it will + # break cases like "15 Jul 2000" and a format list (see issue #447) + with pytest.raises(ParserError): + natural_lang_string = "Meet me at {} at the restaurant.".format( + float_timestamp + ) + self.parser.parse(natural_lang_string, "X") + + with pytest.raises(ParserError): + self.parser.parse("1565982019.", "X") + + with pytest.raises(ParserError): + self.parser.parse(".1565982019", "X") + + def test_parse_expanded_timestamp(self): + # test expanded timestamps that include milliseconds + # and microseconds as multiples rather than decimals + # requested in issue #357 + + tz_utc = tz.tzutc() + timestamp = 1569982581.413132 + timestamp_milli = int(round(timestamp * 1000)) + timestamp_micro = int(round(timestamp * 1000000)) + + # "x" token should parse integer timestamps below MAX_TIMESTAMP normally + self.expected = datetime.fromtimestamp(int(timestamp), tz=tz_utc) + assert self.parser.parse("{:d}".format(int(timestamp)), "x") == self.expected + + self.expected = datetime.fromtimestamp(round(timestamp, 3), tz=tz_utc) + assert self.parser.parse("{:d}".format(timestamp_milli), "x") == self.expected + + self.expected = datetime.fromtimestamp(timestamp, tz=tz_utc) + assert self.parser.parse("{:d}".format(timestamp_micro), "x") == self.expected + + # anything above max µs timestamp should fail + with pytest.raises(ValueError): + self.parser.parse("{:d}".format(int(MAX_TIMESTAMP_US) + 1), "x") + + # floats are not allowed with the "x" token + with pytest.raises(ParserMatchError): + self.parser.parse("{:f}".format(timestamp), "x") + + def test_parse_names(self): + + self.expected = datetime(2012, 1, 1) + + assert self.parser.parse("January 1, 2012", "MMMM D, YYYY") == self.expected + assert self.parser.parse("Jan 1, 2012", "MMM D, YYYY") == self.expected + + def test_parse_pm(self): + + self.expected = datetime(1, 1, 1, 13, 0, 0) + assert self.parser.parse("1 pm", "H a") == self.expected + assert self.parser.parse("1 pm", "h a") == self.expected + + self.expected = datetime(1, 1, 1, 1, 0, 0) + assert self.parser.parse("1 am", "H A") == self.expected + assert self.parser.parse("1 am", "h A") == self.expected + + self.expected = datetime(1, 1, 1, 0, 0, 0) + assert self.parser.parse("12 am", "H A") == self.expected + assert self.parser.parse("12 am", "h A") == self.expected + + self.expected = datetime(1, 1, 1, 12, 0, 0) + assert self.parser.parse("12 pm", "H A") == self.expected + assert self.parser.parse("12 pm", "h A") == self.expected + + def test_parse_tz_hours_only(self): + self.expected = datetime(2025, 10, 17, 5, 30, 10, tzinfo=tz.tzoffset(None, 0)) + parsed = self.parser.parse("2025-10-17 05:30:10+00", "YYYY-MM-DD HH:mm:ssZ") + assert parsed == self.expected + + def test_parse_tz_zz(self): + + self.expected = datetime(2013, 1, 1, tzinfo=tz.tzoffset(None, -7 * 3600)) + assert self.parser.parse("2013-01-01 -07:00", "YYYY-MM-DD ZZ") == self.expected + + def test_parse_tz_name_zzz(self): + for tz_name in make_full_tz_list(): + self.expected = datetime(2013, 1, 1, tzinfo=tz.gettz(tz_name)) + assert ( + self.parser.parse("2013-01-01 %s" % tz_name, "YYYY-MM-DD ZZZ") + == self.expected + ) + + # note that offsets are not timezones + with pytest.raises(ParserError): + self.parser.parse("2013-01-01 12:30:45.9+1000", "YYYY-MM-DDZZZ") + + with pytest.raises(ParserError): + self.parser.parse("2013-01-01 12:30:45.9+10:00", "YYYY-MM-DDZZZ") + + with pytest.raises(ParserError): + self.parser.parse("2013-01-01 12:30:45.9-10", "YYYY-MM-DDZZZ") + + def test_parse_subsecond(self): + # TODO: make both test_parse_subsecond functions in Parse and ParseISO + # tests use the same expected objects (use pytest fixtures) + self.expected = datetime(2013, 1, 1, 12, 30, 45, 900000) + assert ( + self.parser.parse("2013-01-01 12:30:45.9", "YYYY-MM-DD HH:mm:ss.S") + == self.expected + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 980000) + assert ( + self.parser.parse("2013-01-01 12:30:45.98", "YYYY-MM-DD HH:mm:ss.SS") + == self.expected + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987000) + assert ( + self.parser.parse("2013-01-01 12:30:45.987", "YYYY-MM-DD HH:mm:ss.SSS") + == self.expected + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987600) + assert ( + self.parser.parse("2013-01-01 12:30:45.9876", "YYYY-MM-DD HH:mm:ss.SSSS") + == self.expected + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987650) + assert ( + self.parser.parse("2013-01-01 12:30:45.98765", "YYYY-MM-DD HH:mm:ss.SSSSS") + == self.expected + ) + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) + assert ( + self.parser.parse( + "2013-01-01 12:30:45.987654", "YYYY-MM-DD HH:mm:ss.SSSSSS" + ) + == self.expected + ) + + def test_parse_subsecond_rounding(self): + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) + datetime_format = "YYYY-MM-DD HH:mm:ss.S" + + # round up + string = "2013-01-01 12:30:45.9876539" + assert self.parser.parse(string, datetime_format) == self.expected + assert self.parser.parse_iso(string) == self.expected + + # round down + string = "2013-01-01 12:30:45.98765432" + assert self.parser.parse(string, datetime_format) == self.expected + assert self.parser.parse_iso(string) == self.expected + + # round half-up + string = "2013-01-01 12:30:45.987653521" + assert self.parser.parse(string, datetime_format) == self.expected + assert self.parser.parse_iso(string) == self.expected + + # round half-down + string = "2013-01-01 12:30:45.9876545210" + assert self.parser.parse(string, datetime_format) == self.expected + assert self.parser.parse_iso(string) == self.expected + + # overflow (zero out the subseconds and increment the seconds) + # regression tests for issue #636 + def test_parse_subsecond_rounding_overflow(self): + datetime_format = "YYYY-MM-DD HH:mm:ss.S" + + self.expected = datetime(2013, 1, 1, 12, 30, 46) + string = "2013-01-01 12:30:45.9999995" + assert self.parser.parse(string, datetime_format) == self.expected + assert self.parser.parse_iso(string) == self.expected + + self.expected = datetime(2013, 1, 1, 12, 31, 0) + string = "2013-01-01 12:30:59.9999999" + assert self.parser.parse(string, datetime_format) == self.expected + assert self.parser.parse_iso(string) == self.expected + + self.expected = datetime(2013, 1, 2, 0, 0, 0) + string = "2013-01-01 23:59:59.9999999" + assert self.parser.parse(string, datetime_format) == self.expected + assert self.parser.parse_iso(string) == self.expected + + # 6 digits should remain unrounded + self.expected = datetime(2013, 1, 1, 12, 30, 45, 999999) + string = "2013-01-01 12:30:45.999999" + assert self.parser.parse(string, datetime_format) == self.expected + assert self.parser.parse_iso(string) == self.expected + + # Regression tests for issue #560 + def test_parse_long_year(self): + with pytest.raises(ParserError): + self.parser.parse("09 January 123456789101112", "DD MMMM YYYY") + + with pytest.raises(ParserError): + self.parser.parse("123456789101112 09 January", "YYYY DD MMMM") + + with pytest.raises(ParserError): + self.parser.parse("68096653015/01/19", "YY/M/DD") + + def test_parse_with_extra_words_at_start_and_end_invalid(self): + input_format_pairs = [ + ("blah2016", "YYYY"), + ("blah2016blah", "YYYY"), + ("2016blah", "YYYY"), + ("2016-05blah", "YYYY-MM"), + ("2016-05-16blah", "YYYY-MM-DD"), + ("2016-05-16T04:05:06.789120blah", "YYYY-MM-DDThh:mm:ss.S"), + ("2016-05-16T04:05:06.789120ZblahZ", "YYYY-MM-DDThh:mm:ss.SZ"), + ("2016-05-16T04:05:06.789120Zblah", "YYYY-MM-DDThh:mm:ss.SZ"), + ("2016-05-16T04:05:06.789120blahZ", "YYYY-MM-DDThh:mm:ss.SZ"), + ] + + for pair in input_format_pairs: + with pytest.raises(ParserError): + self.parser.parse(pair[0], pair[1]) + + def test_parse_with_extra_words_at_start_and_end_valid(self): + # Spaces surrounding the parsable date are ok because we + # allow the parsing of natural language input. Additionally, a single + # character of specific punctuation before or after the date is okay. + # See docs for full list of valid punctuation. + + assert self.parser.parse("blah 2016 blah", "YYYY") == datetime(2016, 1, 1) + + assert self.parser.parse("blah 2016", "YYYY") == datetime(2016, 1, 1) + + assert self.parser.parse("2016 blah", "YYYY") == datetime(2016, 1, 1) + + # test one additional space along with space divider + assert self.parser.parse( + "blah 2016-05-16 04:05:06.789120", "YYYY-MM-DD hh:mm:ss.S" + ) == datetime(2016, 5, 16, 4, 5, 6, 789120) + + assert self.parser.parse( + "2016-05-16 04:05:06.789120 blah", "YYYY-MM-DD hh:mm:ss.S" + ) == datetime(2016, 5, 16, 4, 5, 6, 789120) + + # test one additional space along with T divider + assert self.parser.parse( + "blah 2016-05-16T04:05:06.789120", "YYYY-MM-DDThh:mm:ss.S" + ) == datetime(2016, 5, 16, 4, 5, 6, 789120) + + assert self.parser.parse( + "2016-05-16T04:05:06.789120 blah", "YYYY-MM-DDThh:mm:ss.S" + ) == datetime(2016, 5, 16, 4, 5, 6, 789120) + + assert self.parser.parse( + "Meet me at 2016-05-16T04:05:06.789120 at the restaurant.", + "YYYY-MM-DDThh:mm:ss.S", + ) == datetime(2016, 5, 16, 4, 5, 6, 789120) + + assert self.parser.parse( + "Meet me at 2016-05-16 04:05:06.789120 at the restaurant.", + "YYYY-MM-DD hh:mm:ss.S", + ) == datetime(2016, 5, 16, 4, 5, 6, 789120) + + # regression test for issue #701 + # tests cases of a partial match surrounded by punctuation + # for the list of valid punctuation, see documentation + def test_parse_with_punctuation_fences(self): + assert self.parser.parse( + "Meet me at my house on Halloween (2019-31-10)", "YYYY-DD-MM" + ) == datetime(2019, 10, 31) + + assert self.parser.parse( + "Monday, 9. September 2019, 16:15-20:00", "dddd, D. MMMM YYYY" + ) == datetime(2019, 9, 9) + + assert self.parser.parse("A date is 11.11.2011.", "DD.MM.YYYY") == datetime( + 2011, 11, 11 + ) + + with pytest.raises(ParserMatchError): + self.parser.parse("11.11.2011.1 is not a valid date.", "DD.MM.YYYY") + + with pytest.raises(ParserMatchError): + self.parser.parse( + "This date has too many punctuation marks following it (11.11.2011).", + "DD.MM.YYYY", + ) + + def test_parse_with_leading_and_trailing_whitespace(self): + assert self.parser.parse(" 2016", "YYYY") == datetime(2016, 1, 1) + + assert self.parser.parse("2016 ", "YYYY") == datetime(2016, 1, 1) + + assert self.parser.parse(" 2016 ", "YYYY") == datetime(2016, 1, 1) + + assert self.parser.parse( + " 2016-05-16 04:05:06.789120 ", "YYYY-MM-DD hh:mm:ss.S" + ) == datetime(2016, 5, 16, 4, 5, 6, 789120) + + assert self.parser.parse( + " 2016-05-16T04:05:06.789120 ", "YYYY-MM-DDThh:mm:ss.S" + ) == datetime(2016, 5, 16, 4, 5, 6, 789120) + + def test_parse_YYYY_DDDD(self): + assert self.parser.parse("1998-136", "YYYY-DDDD") == datetime(1998, 5, 16) + + assert self.parser.parse("1998-006", "YYYY-DDDD") == datetime(1998, 1, 6) + + with pytest.raises(ParserError): + self.parser.parse("1998-456", "YYYY-DDDD") + + def test_parse_YYYY_DDD(self): + assert self.parser.parse("1998-6", "YYYY-DDD") == datetime(1998, 1, 6) + + assert self.parser.parse("1998-136", "YYYY-DDD") == datetime(1998, 5, 16) + + with pytest.raises(ParserError): + self.parser.parse("1998-756", "YYYY-DDD") + + # month cannot be passed with DDD and DDDD tokens + def test_parse_YYYY_MM_DDDD(self): + with pytest.raises(ParserError): + self.parser.parse("2015-01-009", "YYYY-MM-DDDD") + + # year is required with the DDD and DDDD tokens + def test_parse_DDD_only(self): + with pytest.raises(ParserError): + self.parser.parse("5", "DDD") + + def test_parse_DDDD_only(self): + with pytest.raises(ParserError): + self.parser.parse("145", "DDDD") + + def test_parse_HH_24(self): + assert self.parser.parse( + "2019-10-30T24:00:00", "YYYY-MM-DDTHH:mm:ss" + ) == datetime(2019, 10, 31, 0, 0, 0, 0) + assert self.parser.parse("2019-10-30T24:00", "YYYY-MM-DDTHH:mm") == datetime( + 2019, 10, 31, 0, 0, 0, 0 + ) + assert self.parser.parse("2019-10-30T24", "YYYY-MM-DDTHH") == datetime( + 2019, 10, 31, 0, 0, 0, 0 + ) + assert self.parser.parse( + "2019-10-30T24:00:00.0", "YYYY-MM-DDTHH:mm:ss.S" + ) == datetime(2019, 10, 31, 0, 0, 0, 0) + assert self.parser.parse( + "2019-10-31T24:00:00", "YYYY-MM-DDTHH:mm:ss" + ) == datetime(2019, 11, 1, 0, 0, 0, 0) + assert self.parser.parse( + "2019-12-31T24:00:00", "YYYY-MM-DDTHH:mm:ss" + ) == datetime(2020, 1, 1, 0, 0, 0, 0) + assert self.parser.parse( + "2019-12-31T23:59:59.9999999", "YYYY-MM-DDTHH:mm:ss.S" + ) == datetime(2020, 1, 1, 0, 0, 0, 0) + + with pytest.raises(ParserError): + self.parser.parse("2019-12-31T24:01:00", "YYYY-MM-DDTHH:mm:ss") + + with pytest.raises(ParserError): + self.parser.parse("2019-12-31T24:00:01", "YYYY-MM-DDTHH:mm:ss") + + with pytest.raises(ParserError): + self.parser.parse("2019-12-31T24:00:00.1", "YYYY-MM-DDTHH:mm:ss.S") + + with pytest.raises(ParserError): + self.parser.parse("2019-12-31T24:00:00.999999", "YYYY-MM-DDTHH:mm:ss.S") + + +class TestDateTimeParserRegex: + @classmethod + def setup_class(cls): + cls.format_regex = parser.DateTimeParser._FORMAT_RE + + def test_format_year(self): + + assert self.format_regex.findall("YYYY-YY") == ["YYYY", "YY"] + + def test_format_month(self): + + assert self.format_regex.findall("MMMM-MMM-MM-M") == ["MMMM", "MMM", "MM", "M"] + + def test_format_day(self): + + assert self.format_regex.findall("DDDD-DDD-DD-D") == ["DDDD", "DDD", "DD", "D"] + + def test_format_hour(self): + + assert self.format_regex.findall("HH-H-hh-h") == ["HH", "H", "hh", "h"] + + def test_format_minute(self): + + assert self.format_regex.findall("mm-m") == ["mm", "m"] + + def test_format_second(self): + + assert self.format_regex.findall("ss-s") == ["ss", "s"] + + def test_format_subsecond(self): + + assert self.format_regex.findall("SSSSSS-SSSSS-SSSS-SSS-SS-S") == [ + "SSSSSS", + "SSSSS", + "SSSS", + "SSS", + "SS", + "S", + ] + + def test_format_tz(self): + + assert self.format_regex.findall("ZZZ-ZZ-Z") == ["ZZZ", "ZZ", "Z"] + + def test_format_am_pm(self): + + assert self.format_regex.findall("A-a") == ["A", "a"] + + def test_format_timestamp(self): + + assert self.format_regex.findall("X") == ["X"] + + def test_format_timestamp_milli(self): + + assert self.format_regex.findall("x") == ["x"] + + def test_escape(self): + + escape_regex = parser.DateTimeParser._ESCAPE_RE + + assert escape_regex.findall("2018-03-09 8 [h] 40 [hello]") == ["[h]", "[hello]"] + + def test_month_names(self): + p = parser.DateTimeParser("en_us") + + text = "_".join(calendar.month_name[1:]) + + result = p._input_re_map["MMMM"].findall(text) + + assert result == calendar.month_name[1:] + + def test_month_abbreviations(self): + p = parser.DateTimeParser("en_us") + + text = "_".join(calendar.month_abbr[1:]) + + result = p._input_re_map["MMM"].findall(text) + + assert result == calendar.month_abbr[1:] + + def test_digits(self): + + assert parser.DateTimeParser._ONE_OR_TWO_DIGIT_RE.findall("4-56") == ["4", "56"] + assert parser.DateTimeParser._ONE_OR_TWO_OR_THREE_DIGIT_RE.findall( + "4-56-789" + ) == ["4", "56", "789"] + assert parser.DateTimeParser._ONE_OR_MORE_DIGIT_RE.findall( + "4-56-789-1234-12345" + ) == ["4", "56", "789", "1234", "12345"] + assert parser.DateTimeParser._TWO_DIGIT_RE.findall("12-3-45") == ["12", "45"] + assert parser.DateTimeParser._THREE_DIGIT_RE.findall("123-4-56") == ["123"] + assert parser.DateTimeParser._FOUR_DIGIT_RE.findall("1234-56") == ["1234"] + + def test_tz(self): + tz_z_re = parser.DateTimeParser._TZ_Z_RE + assert tz_z_re.findall("-0700") == [("-", "07", "00")] + assert tz_z_re.findall("+07") == [("+", "07", "")] + assert tz_z_re.search("15/01/2019T04:05:06.789120Z") is not None + assert tz_z_re.search("15/01/2019T04:05:06.789120") is None + + tz_zz_re = parser.DateTimeParser._TZ_ZZ_RE + assert tz_zz_re.findall("-07:00") == [("-", "07", "00")] + assert tz_zz_re.findall("+07") == [("+", "07", "")] + assert tz_zz_re.search("15/01/2019T04:05:06.789120Z") is not None + assert tz_zz_re.search("15/01/2019T04:05:06.789120") is None + + tz_name_re = parser.DateTimeParser._TZ_NAME_RE + assert tz_name_re.findall("Europe/Warsaw") == ["Europe/Warsaw"] + assert tz_name_re.findall("GMT") == ["GMT"] + + def test_timestamp(self): + timestamp_re = parser.DateTimeParser._TIMESTAMP_RE + assert timestamp_re.findall("1565707550.452729") == ["1565707550.452729"] + assert timestamp_re.findall("-1565707550.452729") == ["-1565707550.452729"] + assert timestamp_re.findall("-1565707550") == ["-1565707550"] + assert timestamp_re.findall("1565707550") == ["1565707550"] + assert timestamp_re.findall("1565707550.") == [] + assert timestamp_re.findall(".1565707550") == [] + + def test_timestamp_milli(self): + timestamp_expanded_re = parser.DateTimeParser._TIMESTAMP_EXPANDED_RE + assert timestamp_expanded_re.findall("-1565707550") == ["-1565707550"] + assert timestamp_expanded_re.findall("1565707550") == ["1565707550"] + assert timestamp_expanded_re.findall("1565707550.452729") == [] + assert timestamp_expanded_re.findall("1565707550.") == [] + assert timestamp_expanded_re.findall(".1565707550") == [] + + def test_time(self): + time_re = parser.DateTimeParser._TIME_RE + time_seperators = [":", ""] + + for sep in time_seperators: + assert time_re.findall("12") == [("12", "", "", "", "")] + assert time_re.findall("12{sep}35".format(sep=sep)) == [ + ("12", "35", "", "", "") + ] + assert time_re.findall("12{sep}35{sep}46".format(sep=sep)) == [ + ("12", "35", "46", "", "") + ] + assert time_re.findall("12{sep}35{sep}46.952313".format(sep=sep)) == [ + ("12", "35", "46", ".", "952313") + ] + assert time_re.findall("12{sep}35{sep}46,952313".format(sep=sep)) == [ + ("12", "35", "46", ",", "952313") + ] + + assert time_re.findall("12:") == [] + assert time_re.findall("12:35:46.") == [] + assert time_re.findall("12:35:46,") == [] + + +class TestDateTimeParserISO: + @classmethod + def setup_class(cls): + cls.parser = parser.DateTimeParser("en_us") + + def test_YYYY(self): + + assert self.parser.parse_iso("2013") == datetime(2013, 1, 1) + + def test_YYYY_DDDD(self): + assert self.parser.parse_iso("1998-136") == datetime(1998, 5, 16) + + assert self.parser.parse_iso("1998-006") == datetime(1998, 1, 6) + + with pytest.raises(ParserError): + self.parser.parse_iso("1998-456") + + # 2016 is a leap year, so Feb 29 exists (leap day) + assert self.parser.parse_iso("2016-059") == datetime(2016, 2, 28) + assert self.parser.parse_iso("2016-060") == datetime(2016, 2, 29) + assert self.parser.parse_iso("2016-061") == datetime(2016, 3, 1) + + # 2017 is not a leap year, so Feb 29 does not exist + assert self.parser.parse_iso("2017-059") == datetime(2017, 2, 28) + assert self.parser.parse_iso("2017-060") == datetime(2017, 3, 1) + assert self.parser.parse_iso("2017-061") == datetime(2017, 3, 2) + + # Since 2016 is a leap year, the 366th day falls in the same year + assert self.parser.parse_iso("2016-366") == datetime(2016, 12, 31) + + # Since 2017 is not a leap year, the 366th day falls in the next year + assert self.parser.parse_iso("2017-366") == datetime(2018, 1, 1) + + def test_YYYY_DDDD_HH_mm_ssZ(self): + + assert self.parser.parse_iso("2013-036 04:05:06+01:00") == datetime( + 2013, 2, 5, 4, 5, 6, tzinfo=tz.tzoffset(None, 3600) + ) + + assert self.parser.parse_iso("2013-036 04:05:06Z") == datetime( + 2013, 2, 5, 4, 5, 6, tzinfo=tz.tzutc() + ) + + def test_YYYY_MM_DDDD(self): + with pytest.raises(ParserError): + self.parser.parse_iso("2014-05-125") + + def test_YYYY_MM(self): + + for separator in DateTimeParser.SEPARATORS: + assert self.parser.parse_iso(separator.join(("2013", "02"))) == datetime( + 2013, 2, 1 + ) + + def test_YYYY_MM_DD(self): + + for separator in DateTimeParser.SEPARATORS: + assert self.parser.parse_iso( + separator.join(("2013", "02", "03")) + ) == datetime(2013, 2, 3) + + def test_YYYY_MM_DDTHH_mmZ(self): + + assert self.parser.parse_iso("2013-02-03T04:05+01:00") == datetime( + 2013, 2, 3, 4, 5, tzinfo=tz.tzoffset(None, 3600) + ) + + def test_YYYY_MM_DDTHH_mm(self): + + assert self.parser.parse_iso("2013-02-03T04:05") == datetime(2013, 2, 3, 4, 5) + + def test_YYYY_MM_DDTHH(self): + + assert self.parser.parse_iso("2013-02-03T04") == datetime(2013, 2, 3, 4) + + def test_YYYY_MM_DDTHHZ(self): + + assert self.parser.parse_iso("2013-02-03T04+01:00") == datetime( + 2013, 2, 3, 4, tzinfo=tz.tzoffset(None, 3600) + ) + + def test_YYYY_MM_DDTHH_mm_ssZ(self): + + assert self.parser.parse_iso("2013-02-03T04:05:06+01:00") == datetime( + 2013, 2, 3, 4, 5, 6, tzinfo=tz.tzoffset(None, 3600) + ) + + def test_YYYY_MM_DDTHH_mm_ss(self): + + assert self.parser.parse_iso("2013-02-03T04:05:06") == datetime( + 2013, 2, 3, 4, 5, 6 + ) + + def test_YYYY_MM_DD_HH_mmZ(self): + + assert self.parser.parse_iso("2013-02-03 04:05+01:00") == datetime( + 2013, 2, 3, 4, 5, tzinfo=tz.tzoffset(None, 3600) + ) + + def test_YYYY_MM_DD_HH_mm(self): + + assert self.parser.parse_iso("2013-02-03 04:05") == datetime(2013, 2, 3, 4, 5) + + def test_YYYY_MM_DD_HH(self): + + assert self.parser.parse_iso("2013-02-03 04") == datetime(2013, 2, 3, 4) + + def test_invalid_time(self): + + with pytest.raises(ParserError): + self.parser.parse_iso("2013-02-03T") + + with pytest.raises(ParserError): + self.parser.parse_iso("2013-02-03 044") + + with pytest.raises(ParserError): + self.parser.parse_iso("2013-02-03 04:05:06.") + + def test_YYYY_MM_DD_HH_mm_ssZ(self): + + assert self.parser.parse_iso("2013-02-03 04:05:06+01:00") == datetime( + 2013, 2, 3, 4, 5, 6, tzinfo=tz.tzoffset(None, 3600) + ) + + def test_YYYY_MM_DD_HH_mm_ss(self): + + assert self.parser.parse_iso("2013-02-03 04:05:06") == datetime( + 2013, 2, 3, 4, 5, 6 + ) + + def test_YYYY_MM_DDTHH_mm_ss_S(self): + + assert self.parser.parse_iso("2013-02-03T04:05:06.7") == datetime( + 2013, 2, 3, 4, 5, 6, 700000 + ) + + assert self.parser.parse_iso("2013-02-03T04:05:06.78") == datetime( + 2013, 2, 3, 4, 5, 6, 780000 + ) + + assert self.parser.parse_iso("2013-02-03T04:05:06.789") == datetime( + 2013, 2, 3, 4, 5, 6, 789000 + ) + + assert self.parser.parse_iso("2013-02-03T04:05:06.7891") == datetime( + 2013, 2, 3, 4, 5, 6, 789100 + ) + + assert self.parser.parse_iso("2013-02-03T04:05:06.78912") == datetime( + 2013, 2, 3, 4, 5, 6, 789120 + ) + + # ISO 8601:2004(E), ISO, 2004-12-01, 4.2.2.4 ... the decimal fraction + # shall be divided from the integer part by the decimal sign specified + # in ISO 31-0, i.e. the comma [,] or full stop [.]. Of these, the comma + # is the preferred sign. + assert self.parser.parse_iso("2013-02-03T04:05:06,789123678") == datetime( + 2013, 2, 3, 4, 5, 6, 789124 + ) + + # there is no limit on the number of decimal places + assert self.parser.parse_iso("2013-02-03T04:05:06.789123678") == datetime( + 2013, 2, 3, 4, 5, 6, 789124 + ) + + def test_YYYY_MM_DDTHH_mm_ss_SZ(self): + + assert self.parser.parse_iso("2013-02-03T04:05:06.7+01:00") == datetime( + 2013, 2, 3, 4, 5, 6, 700000, tzinfo=tz.tzoffset(None, 3600) + ) + + assert self.parser.parse_iso("2013-02-03T04:05:06.78+01:00") == datetime( + 2013, 2, 3, 4, 5, 6, 780000, tzinfo=tz.tzoffset(None, 3600) + ) + + assert self.parser.parse_iso("2013-02-03T04:05:06.789+01:00") == datetime( + 2013, 2, 3, 4, 5, 6, 789000, tzinfo=tz.tzoffset(None, 3600) + ) + + assert self.parser.parse_iso("2013-02-03T04:05:06.7891+01:00") == datetime( + 2013, 2, 3, 4, 5, 6, 789100, tzinfo=tz.tzoffset(None, 3600) + ) + + assert self.parser.parse_iso("2013-02-03T04:05:06.78912+01:00") == datetime( + 2013, 2, 3, 4, 5, 6, 789120, tzinfo=tz.tzoffset(None, 3600) + ) + + assert self.parser.parse_iso("2013-02-03 04:05:06.78912Z") == datetime( + 2013, 2, 3, 4, 5, 6, 789120, tzinfo=tz.tzutc() + ) + + def test_invalid_Z(self): + + with pytest.raises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912z") + + with pytest.raises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912zz") + + with pytest.raises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912Zz") + + with pytest.raises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912ZZ") + + with pytest.raises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912+Z") + + with pytest.raises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912-Z") + + with pytest.raises(ParserError): + self.parser.parse_iso("2013-02-03T04:05:06.78912 Z") + + def test_parse_subsecond(self): + self.expected = datetime(2013, 1, 1, 12, 30, 45, 900000) + assert self.parser.parse_iso("2013-01-01 12:30:45.9") == self.expected + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 980000) + assert self.parser.parse_iso("2013-01-01 12:30:45.98") == self.expected + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987000) + assert self.parser.parse_iso("2013-01-01 12:30:45.987") == self.expected + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987600) + assert self.parser.parse_iso("2013-01-01 12:30:45.9876") == self.expected + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987650) + assert self.parser.parse_iso("2013-01-01 12:30:45.98765") == self.expected + + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) + assert self.parser.parse_iso("2013-01-01 12:30:45.987654") == self.expected + + # use comma as subsecond separator + self.expected = datetime(2013, 1, 1, 12, 30, 45, 987654) + assert self.parser.parse_iso("2013-01-01 12:30:45,987654") == self.expected + + def test_gnu_date(self): + """Regression tests for parsing output from GNU date.""" + # date -Ins + assert self.parser.parse_iso("2016-11-16T09:46:30,895636557-0800") == datetime( + 2016, 11, 16, 9, 46, 30, 895636, tzinfo=tz.tzoffset(None, -3600 * 8) + ) + + # date --rfc-3339=ns + assert self.parser.parse_iso("2016-11-16 09:51:14.682141526-08:00") == datetime( + 2016, 11, 16, 9, 51, 14, 682142, tzinfo=tz.tzoffset(None, -3600 * 8) + ) + + def test_isoformat(self): + + dt = datetime.utcnow() + + assert self.parser.parse_iso(dt.isoformat()) == dt + + def test_parse_iso_with_leading_and_trailing_whitespace(self): + datetime_string = " 2016-11-15T06:37:19.123456" + with pytest.raises(ParserError): + self.parser.parse_iso(datetime_string) + + datetime_string = " 2016-11-15T06:37:19.123456 " + with pytest.raises(ParserError): + self.parser.parse_iso(datetime_string) + + datetime_string = "2016-11-15T06:37:19.123456 " + with pytest.raises(ParserError): + self.parser.parse_iso(datetime_string) + + datetime_string = "2016-11-15T 06:37:19.123456" + with pytest.raises(ParserError): + self.parser.parse_iso(datetime_string) + + # leading whitespace + datetime_string = " 2016-11-15 06:37:19.123456" + with pytest.raises(ParserError): + self.parser.parse_iso(datetime_string) + + # trailing whitespace + datetime_string = "2016-11-15 06:37:19.123456 " + with pytest.raises(ParserError): + self.parser.parse_iso(datetime_string) + + datetime_string = " 2016-11-15 06:37:19.123456 " + with pytest.raises(ParserError): + self.parser.parse_iso(datetime_string) + + # two dividing spaces + datetime_string = "2016-11-15 06:37:19.123456" + with pytest.raises(ParserError): + self.parser.parse_iso(datetime_string) + + def test_parse_iso_with_extra_words_at_start_and_end_invalid(self): + test_inputs = [ + "blah2016", + "blah2016blah", + "blah 2016 blah", + "blah 2016", + "2016 blah", + "blah 2016-05-16 04:05:06.789120", + "2016-05-16 04:05:06.789120 blah", + "blah 2016-05-16T04:05:06.789120", + "2016-05-16T04:05:06.789120 blah", + "2016blah", + "2016-05blah", + "2016-05-16blah", + "2016-05-16T04:05:06.789120blah", + "2016-05-16T04:05:06.789120ZblahZ", + "2016-05-16T04:05:06.789120Zblah", + "2016-05-16T04:05:06.789120blahZ", + "Meet me at 2016-05-16T04:05:06.789120 at the restaurant.", + "Meet me at 2016-05-16 04:05:06.789120 at the restaurant.", + ] + + for ti in test_inputs: + with pytest.raises(ParserError): + self.parser.parse_iso(ti) + + def test_iso8601_basic_format(self): + assert self.parser.parse_iso("20180517") == datetime(2018, 5, 17) + + assert self.parser.parse_iso("20180517T10") == datetime(2018, 5, 17, 10) + + assert self.parser.parse_iso("20180517T105513.843456") == datetime( + 2018, 5, 17, 10, 55, 13, 843456 + ) + + assert self.parser.parse_iso("20180517T105513Z") == datetime( + 2018, 5, 17, 10, 55, 13, tzinfo=tz.tzutc() + ) + + assert self.parser.parse_iso("20180517T105513.843456-0700") == datetime( + 2018, 5, 17, 10, 55, 13, 843456, tzinfo=tz.tzoffset(None, -25200) + ) + + assert self.parser.parse_iso("20180517T105513-0700") == datetime( + 2018, 5, 17, 10, 55, 13, tzinfo=tz.tzoffset(None, -25200) + ) + + assert self.parser.parse_iso("20180517T105513-07") == datetime( + 2018, 5, 17, 10, 55, 13, tzinfo=tz.tzoffset(None, -25200) + ) + + # ordinal in basic format: YYYYDDDD + assert self.parser.parse_iso("1998136") == datetime(1998, 5, 16) + + # timezone requires +- seperator + with pytest.raises(ParserError): + self.parser.parse_iso("20180517T1055130700") + + with pytest.raises(ParserError): + self.parser.parse_iso("20180517T10551307") + + # too many digits in date + with pytest.raises(ParserError): + self.parser.parse_iso("201860517T105513Z") + + # too many digits in time + with pytest.raises(ParserError): + self.parser.parse_iso("20180517T1055213Z") + + def test_midnight_end_day(self): + assert self.parser.parse_iso("2019-10-30T24:00:00") == datetime( + 2019, 10, 31, 0, 0, 0, 0 + ) + assert self.parser.parse_iso("2019-10-30T24:00") == datetime( + 2019, 10, 31, 0, 0, 0, 0 + ) + assert self.parser.parse_iso("2019-10-30T24:00:00.0") == datetime( + 2019, 10, 31, 0, 0, 0, 0 + ) + assert self.parser.parse_iso("2019-10-31T24:00:00") == datetime( + 2019, 11, 1, 0, 0, 0, 0 + ) + assert self.parser.parse_iso("2019-12-31T24:00:00") == datetime( + 2020, 1, 1, 0, 0, 0, 0 + ) + assert self.parser.parse_iso("2019-12-31T23:59:59.9999999") == datetime( + 2020, 1, 1, 0, 0, 0, 0 + ) + + with pytest.raises(ParserError): + self.parser.parse_iso("2019-12-31T24:01:00") + + with pytest.raises(ParserError): + self.parser.parse_iso("2019-12-31T24:00:01") + + with pytest.raises(ParserError): + self.parser.parse_iso("2019-12-31T24:00:00.1") + + with pytest.raises(ParserError): + self.parser.parse_iso("2019-12-31T24:00:00.999999") + + +class TestTzinfoParser: + @classmethod + def setup_class(cls): + cls.parser = parser.TzinfoParser() + + def test_parse_local(self): + + assert self.parser.parse("local") == tz.tzlocal() + + def test_parse_utc(self): + + assert self.parser.parse("utc") == tz.tzutc() + assert self.parser.parse("UTC") == tz.tzutc() + + def test_parse_iso(self): + + assert self.parser.parse("01:00") == tz.tzoffset(None, 3600) + assert self.parser.parse("11:35") == tz.tzoffset(None, 11 * 3600 + 2100) + assert self.parser.parse("+01:00") == tz.tzoffset(None, 3600) + assert self.parser.parse("-01:00") == tz.tzoffset(None, -3600) + + assert self.parser.parse("0100") == tz.tzoffset(None, 3600) + assert self.parser.parse("+0100") == tz.tzoffset(None, 3600) + assert self.parser.parse("-0100") == tz.tzoffset(None, -3600) + + assert self.parser.parse("01") == tz.tzoffset(None, 3600) + assert self.parser.parse("+01") == tz.tzoffset(None, 3600) + assert self.parser.parse("-01") == tz.tzoffset(None, -3600) + + def test_parse_str(self): + + assert self.parser.parse("US/Pacific") == tz.gettz("US/Pacific") + + def test_parse_fails(self): + + with pytest.raises(parser.ParserError): + self.parser.parse("fail") + + +class TestDateTimeParserMonthName: + @classmethod + def setup_class(cls): + cls.parser = parser.DateTimeParser("en_us") + + def test_shortmonth_capitalized(self): + + assert self.parser.parse("2013-Jan-01", "YYYY-MMM-DD") == datetime(2013, 1, 1) + + def test_shortmonth_allupper(self): + + assert self.parser.parse("2013-JAN-01", "YYYY-MMM-DD") == datetime(2013, 1, 1) + + def test_shortmonth_alllower(self): + + assert self.parser.parse("2013-jan-01", "YYYY-MMM-DD") == datetime(2013, 1, 1) + + def test_month_capitalized(self): + + assert self.parser.parse("2013-January-01", "YYYY-MMMM-DD") == datetime( + 2013, 1, 1 + ) + + def test_month_allupper(self): + + assert self.parser.parse("2013-JANUARY-01", "YYYY-MMMM-DD") == datetime( + 2013, 1, 1 + ) + + def test_month_alllower(self): + + assert self.parser.parse("2013-january-01", "YYYY-MMMM-DD") == datetime( + 2013, 1, 1 + ) + + def test_localized_month_name(self): + parser_ = parser.DateTimeParser("fr_fr") + + assert parser_.parse("2013-Janvier-01", "YYYY-MMMM-DD") == datetime(2013, 1, 1) + + def test_localized_month_abbreviation(self): + parser_ = parser.DateTimeParser("it_it") + + assert parser_.parse("2013-Gen-01", "YYYY-MMM-DD") == datetime(2013, 1, 1) + + +class TestDateTimeParserMeridians: + @classmethod + def setup_class(cls): + cls.parser = parser.DateTimeParser("en_us") + + def test_meridians_lowercase(self): + assert self.parser.parse("2013-01-01 5am", "YYYY-MM-DD ha") == datetime( + 2013, 1, 1, 5 + ) + + assert self.parser.parse("2013-01-01 5pm", "YYYY-MM-DD ha") == datetime( + 2013, 1, 1, 17 + ) + + def test_meridians_capitalized(self): + assert self.parser.parse("2013-01-01 5AM", "YYYY-MM-DD hA") == datetime( + 2013, 1, 1, 5 + ) + + assert self.parser.parse("2013-01-01 5PM", "YYYY-MM-DD hA") == datetime( + 2013, 1, 1, 17 + ) + + def test_localized_meridians_lowercase(self): + parser_ = parser.DateTimeParser("hu_hu") + assert parser_.parse("2013-01-01 5 de", "YYYY-MM-DD h a") == datetime( + 2013, 1, 1, 5 + ) + + assert parser_.parse("2013-01-01 5 du", "YYYY-MM-DD h a") == datetime( + 2013, 1, 1, 17 + ) + + def test_localized_meridians_capitalized(self): + parser_ = parser.DateTimeParser("hu_hu") + assert parser_.parse("2013-01-01 5 DE", "YYYY-MM-DD h A") == datetime( + 2013, 1, 1, 5 + ) + + assert parser_.parse("2013-01-01 5 DU", "YYYY-MM-DD h A") == datetime( + 2013, 1, 1, 17 + ) + + # regression test for issue #607 + def test_es_meridians(self): + parser_ = parser.DateTimeParser("es") + + assert parser_.parse( + "Junio 30, 2019 - 08:00 pm", "MMMM DD, YYYY - hh:mm a" + ) == datetime(2019, 6, 30, 20, 0) + + with pytest.raises(ParserError): + parser_.parse( + "Junio 30, 2019 - 08:00 pasdfasdfm", "MMMM DD, YYYY - hh:mm a" + ) + + def test_fr_meridians(self): + parser_ = parser.DateTimeParser("fr") + + # the French locale always uses a 24 hour clock, so it does not support meridians + with pytest.raises(ParserError): + parser_.parse("Janvier 30, 2019 - 08:00 pm", "MMMM DD, YYYY - hh:mm a") + + +class TestDateTimeParserMonthOrdinalDay: + @classmethod + def setup_class(cls): + cls.parser = parser.DateTimeParser("en_us") + + def test_english(self): + parser_ = parser.DateTimeParser("en_us") + + assert parser_.parse("January 1st, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 1 + ) + assert parser_.parse("January 2nd, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 2 + ) + assert parser_.parse("January 3rd, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 3 + ) + assert parser_.parse("January 4th, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 4 + ) + assert parser_.parse("January 11th, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 11 + ) + assert parser_.parse("January 12th, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 12 + ) + assert parser_.parse("January 13th, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 13 + ) + assert parser_.parse("January 21st, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 21 + ) + assert parser_.parse("January 31st, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 31 + ) + + with pytest.raises(ParserError): + parser_.parse("January 1th, 2013", "MMMM Do, YYYY") + + with pytest.raises(ParserError): + parser_.parse("January 11st, 2013", "MMMM Do, YYYY") + + def test_italian(self): + parser_ = parser.DateTimeParser("it_it") + + assert parser_.parse("Gennaio 1º, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 1 + ) + + def test_spanish(self): + parser_ = parser.DateTimeParser("es_es") + + assert parser_.parse("Enero 1º, 2013", "MMMM Do, YYYY") == datetime(2013, 1, 1) + + def test_french(self): + parser_ = parser.DateTimeParser("fr_fr") + + assert parser_.parse("Janvier 1er, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 1 + ) + + assert parser_.parse("Janvier 2e, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 2 + ) + + assert parser_.parse("Janvier 11e, 2013", "MMMM Do, YYYY") == datetime( + 2013, 1, 11 + ) + + +class TestDateTimeParserSearchDate: + @classmethod + def setup_class(cls): + cls.parser = parser.DateTimeParser() + + def test_parse_search(self): + + assert self.parser.parse( + "Today is 25 of September of 2003", "DD of MMMM of YYYY" + ) == datetime(2003, 9, 25) + + def test_parse_search_with_numbers(self): + + assert self.parser.parse( + "2000 people met the 2012-01-01 12:05:10", "YYYY-MM-DD HH:mm:ss" + ) == datetime(2012, 1, 1, 12, 5, 10) + + assert self.parser.parse( + "Call 01-02-03 on 79-01-01 12:05:10", "YY-MM-DD HH:mm:ss" + ) == datetime(1979, 1, 1, 12, 5, 10) + + def test_parse_search_with_names(self): + + assert self.parser.parse("June was born in May 1980", "MMMM YYYY") == datetime( + 1980, 5, 1 + ) + + def test_parse_search_locale_with_names(self): + p = parser.DateTimeParser("sv_se") + + assert p.parse("Jan föddes den 31 Dec 1980", "DD MMM YYYY") == datetime( + 1980, 12, 31 + ) + + assert p.parse("Jag föddes den 25 Augusti 1975", "DD MMMM YYYY") == datetime( + 1975, 8, 25 + ) + + def test_parse_search_fails(self): + + with pytest.raises(parser.ParserError): + self.parser.parse("Jag föddes den 25 Augusti 1975", "DD MMMM YYYY") + + def test_escape(self): + + format = "MMMM D, YYYY [at] h:mma" + assert self.parser.parse( + "Thursday, December 10, 2015 at 5:09pm", format + ) == datetime(2015, 12, 10, 17, 9) + + format = "[MMMM] M D, YYYY [at] h:mma" + assert self.parser.parse("MMMM 12 10, 2015 at 5:09pm", format) == datetime( + 2015, 12, 10, 17, 9 + ) + + format = "[It happened on] MMMM Do [in the year] YYYY [a long time ago]" + assert self.parser.parse( + "It happened on November 25th in the year 1990 a long time ago", format + ) == datetime(1990, 11, 25) + + format = "[It happened on] MMMM Do [in the][ year] YYYY [a long time ago]" + assert self.parser.parse( + "It happened on November 25th in the year 1990 a long time ago", format + ) == datetime(1990, 11, 25) + + format = "[I'm][ entirely][ escaped,][ weee!]" + assert self.parser.parse("I'm entirely escaped, weee!", format) == datetime( + 1, 1, 1 + ) + + # Special RegEx characters + format = "MMM DD, YYYY |^${}().*+?<>-& h:mm A" + assert self.parser.parse( + "Dec 31, 2017 |^${}().*+?<>-& 2:00 AM", format + ) == datetime(2017, 12, 31, 2, 0) diff --git a/tests/util_tests.py b/tests/test_util.py similarity index 99% rename from tests/util_tests.py rename to tests/test_util.py index b8a2c1360..7a0b974de 100644 --- a/tests/util_tests.py +++ b/tests/test_util.py @@ -2,9 +2,10 @@ import time from datetime import datetime -from arrow import util import pytest +from arrow import util + class TestUtil: def test_total_seconds(self): diff --git a/tests/util_tests.py.bak b/tests/util_tests.py.bak deleted file mode 100644 index 804ae62a2..000000000 --- a/tests/util_tests.py.bak +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -import time -from datetime import datetime - -from chai import Chai - -from arrow import util - - -class UtilTests(Chai): - def test_total_seconds(self): - td = datetime(2019, 1, 1) - datetime(2018, 1, 1) - self.assertEqual(util.total_seconds(td), td.total_seconds()) - - def test_is_timestamp(self): - timestamp_float = time.time() - timestamp_int = int(timestamp_float) - - self.assertTrue(util.is_timestamp(timestamp_int)) - self.assertTrue(util.is_timestamp(timestamp_float)) - self.assertTrue(util.is_timestamp(str(timestamp_int))) - self.assertTrue(util.is_timestamp(str(timestamp_float))) - - self.assertFalse(util.is_timestamp(True)) - self.assertFalse(util.is_timestamp(False)) - - class InvalidTimestamp: - pass - - self.assertFalse(util.is_timestamp(InvalidTimestamp())) - - full_datetime = "2019-06-23T13:12:42" - self.assertFalse(util.is_timestamp(full_datetime)) - - def test_iso_gregorian(self): - with self.assertRaises(ValueError): - util.iso_to_gregorian(2013, 0, 5) - - with self.assertRaises(ValueError): - util.iso_to_gregorian(2013, 8, 0) diff --git a/tests/utils.py b/tests/utils.py index bb469b165..2a048feb3 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -2,8 +2,15 @@ import pytz from dateutil.zoneinfo import get_zonefile_instance +from arrow import util + def make_full_tz_list(): dateutil_zones = set(get_zonefile_instance().zones) pytz_zones = set(pytz.all_timezones) return dateutil_zones.union(pytz_zones) + + +def assert_datetime_equality(dt1, dt2, within=10): + assert dt1.tzinfo == dt2.tzinfo + assert abs(util.total_seconds(dt1 - dt2)) < within diff --git a/tox.ini b/tox.ini index 061f39261..071edf7c3 100644 --- a/tox.ini +++ b/tox.ini @@ -4,8 +4,8 @@ skip_missing_interpreters = true [testenv] deps = -rrequirements.txt -whitelist_externals = nosetests -commands = nosetests +whitelist_externals = pytest +commands = pytest [testenv:lint] basepython = python3 From f664c139c140824fd9dde650f9eade7d1af4be4d Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Sat, 4 Jan 2020 17:11:10 -0500 Subject: [PATCH 08/13] Remove test suite support from setup.py as it will soon be deprecated --- setup.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/setup.py b/setup.py index 8778bebf1..a60250a03 100644 --- a/setup.py +++ b/setup.py @@ -27,8 +27,6 @@ "python-dateutil", "backports.functools_lru_cache>=1.2.1;python_version=='2.7'", ], - test_suite="tests", - tests_require=["chai", "mock"], classifiers=[ "Development Status :: 4 - Beta", "Intended Audience :: Developers", From 3d667ed14d85bfd2a7b56b52f399fcb189a4d76d Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Sat, 4 Jan 2020 17:37:45 -0500 Subject: [PATCH 09/13] Added Pytest options to setup.cfg --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 1f7575065..227bb8b65 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [tool:pytest] -# addopts = -v --nf --cov-branch --cov=arrow tests --cov-fail-under=100 --cov-report=term-missing --cov-report=xml +addopts = -v --nf --cov-branch --cov=arrow tests --cov-fail-under=100 --cov-report=term-missing --cov-report=xml [tool:isort] line_length = 88 From 0e2f45bceb6db321c5832e6797baf3041908bba8 Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Sun, 5 Jan 2020 16:22:51 -0500 Subject: [PATCH 10/13] Added coverage.xml to make clean command --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a05957d4a..f15a106ae 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ docs: clean: rm -rf venv .tox ./**/__pycache__ rm -rf dist build .egg .eggs arrow.egg-info - rm -f ./**/*.pyc .coverage + rm -f ./**/*.pyc .coverage coverage.xml publish: rm -rf dist build .egg .eggs arrow.egg-info From 82fe11f47e4934390afbc4109d0769dbb1204e70 Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Mon, 6 Jan 2020 14:14:45 -0500 Subject: [PATCH 11/13] Remove new first --nf argument from pytest --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 227bb8b65..f8ea7e011 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [tool:pytest] -addopts = -v --nf --cov-branch --cov=arrow tests --cov-fail-under=100 --cov-report=term-missing --cov-report=xml +addopts = -v --cov-branch --cov=arrow tests --cov-fail-under=100 --cov-report=term-missing --cov-report=xml [tool:isort] line_length = 88 From 0ee8d5021d932f6ee798248f3a7ae695d63a2a4c Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Wed, 8 Jan 2020 16:33:46 -0500 Subject: [PATCH 12/13] Locked dependency versions --- requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 11c0c72cf..79f0e53ad 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ backports.functools_lru_cache==1.6.1; python_version == "2.7" dateparser==0.7.* pre-commit==1.20.* -pytest -pytest-cov -pytest-mock +pytest==5.3.* +pytest-cov==2.8.* +pytest-mock==2.0.* python-dateutil==2.8.* pytz==2019.* simplejson==3.16.* From c1ca3b037b730207c6d8583b12626787c0879e55 Mon Sep 17 00:00:00 2001 From: Jad Chaar Date: Thu, 9 Jan 2020 08:27:54 -0500 Subject: [PATCH 13/13] Lock pytest for specific Python versions. --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 79f0e53ad..e1d16ca9a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,8 @@ backports.functools_lru_cache==1.6.1; python_version == "2.7" dateparser==0.7.* pre-commit==1.20.* -pytest==5.3.* +pytest==4.6.*; python_version == "2.7" +pytest==5.3.*; python_version >= "3.5" pytest-cov==2.8.* pytest-mock==2.0.* python-dateutil==2.8.*