From 9296c58305c2e66a4fcaa0c3bfca6bc6e06e3574 Mon Sep 17 00:00:00 2001 From: Carl Harris Date: Fri, 21 Feb 2020 03:44:39 -0500 Subject: [PATCH 1/2] fix date and datetime fromstring --- intervals/interval.py | 6 ++++++ tests/interval/test_initialization.py | 21 ++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/intervals/interval.py b/intervals/interval.py index 0e3ad96..8838255 100644 --- a/intervals/interval.py +++ b/intervals/interval.py @@ -725,10 +725,16 @@ class DateInterval(AbstractInterval): step = timedelta(days=1) type = date + def coerce_string(self, value): + return self.type.fromisoformat(value) + class DateTimeInterval(AbstractInterval): type = datetime + def coerce_string(self, value): + return self.type.fromisoformat(value) + class FloatInterval(NumberInterval): type = float diff --git a/tests/interval/test_initialization.py b/tests/interval/test_initialization.py index c28e582..6e78fe4 100644 --- a/tests/interval/test_initialization.py +++ b/tests/interval/test_initialization.py @@ -1,4 +1,5 @@ from datetime import date +from datetime import datetime from decimal import Decimal from infinity import inf @@ -6,11 +7,13 @@ from intervals import ( CharacterInterval, + DateInterval, + DateTimeInterval, DecimalInterval, FloatInterval, IllegalArgument, - Interval, IntInterval, + Interval, RangeBoundsException ) @@ -186,6 +189,22 @@ def test_raises_exception_for_badly_constructed_range( with raises(RangeBoundsException): constructor(number_range) + def test_dateinterval_fromstring(self): + s = '[2020-01-02, 2020-03-04]' + interval = DateInterval.from_string(s) + assert interval.lower == date(2020, 1, 2) + assert interval.upper == date(2020, 3, 4) + assert interval.lower_inc + assert interval.upper_inc + + def test_datetimeinterval_fromstring(self): + s = '[2020-01-02 03:04:05, 2020-06-07 08:09:10]' + interval = DateTimeInterval.from_string(s) + assert interval.lower == datetime(2020, 1, 2, 3, 4, 5) + assert interval.upper == datetime(2020, 6, 7, 8, 9, 10) + assert interval.lower_inc + assert interval.upper_inc + class TestTypeGuessing(object): @mark.parametrize( From 9a44a83971ff995263fd494d002af10c491f9306 Mon Sep 17 00:00:00 2001 From: Carl Harris Date: Fri, 21 Feb 2020 04:57:59 -0500 Subject: [PATCH 2/2] be more compatible with python versions --- intervals/interval.py | 37 +++++++++++++++++++++++++-- tests/interval/test_initialization.py | 11 ++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/intervals/interval.py b/intervals/interval.py index 8838255..fd452cd 100644 --- a/intervals/interval.py +++ b/intervals/interval.py @@ -8,12 +8,45 @@ # -*- coding: utf-8 -*- import operator +import sys from datetime import date, datetime, timedelta from decimal import Decimal from math import ceil, floor from infinity import inf, is_infinite +try: + import arrow + + def date_from_iso(s): + return arrow.get(s).naive.date() + + def datetime_from_iso(s): + return arrow.get(s).naive + +except ImportError: + if ( + sys.version_info.major > 3 or + (sys.version_info.major == 3 and sys.version_info.minor >= 7) + ): + def date_from_iso(s): + return date.fromisoformat(s) + + def datetime_from_iso(s): + return datetime.fromisoformat(s) + else: + def date_from_iso(s): + return datetime.strptime(s, '%Y-%m-%d').date() + + def datetime_from_iso(s): + n = len(s) + if n == 10: + return datetime.strptime(s, '%Y-%m-%d') + elif n == 19: + return datetime.strptime(s, '%Y-%m-%d %H:%M:%S') + elif n > 19: + return datetime.strptime(s, '%Y-%m-%d %H:%M:%S.%f') + from .exc import IllegalArgument, IntervalException, RangeBoundsException from .parser import IntervalParser, IntervalStringParser @@ -726,14 +759,14 @@ class DateInterval(AbstractInterval): type = date def coerce_string(self, value): - return self.type.fromisoformat(value) + return date_from_iso(value) class DateTimeInterval(AbstractInterval): type = datetime def coerce_string(self, value): - return self.type.fromisoformat(value) + return datetime_from_iso(value) class FloatInterval(NumberInterval): diff --git a/tests/interval/test_initialization.py b/tests/interval/test_initialization.py index 6e78fe4..eae660b 100644 --- a/tests/interval/test_initialization.py +++ b/tests/interval/test_initialization.py @@ -198,10 +198,17 @@ def test_dateinterval_fromstring(self): assert interval.upper_inc def test_datetimeinterval_fromstring(self): - s = '[2020-01-02 03:04:05, 2020-06-07 08:09:10]' + s = '[2020-01-02 03:04:05, 2020-06-07 08:09:10.000001]' interval = DateTimeInterval.from_string(s) assert interval.lower == datetime(2020, 1, 2, 3, 4, 5) - assert interval.upper == datetime(2020, 6, 7, 8, 9, 10) + assert interval.upper == datetime(2020, 6, 7, 8, 9, 10, 1) + assert interval.lower_inc + assert interval.upper_inc + # without time part + s = '[2020-01-02, 2020-06-07]' + interval = DateTimeInterval.from_string(s) + assert interval.lower == datetime(2020, 1, 2, 0, 0, 0) + assert interval.upper == datetime(2020, 6, 7, 0, 0, 0) assert interval.lower_inc assert interval.upper_inc