Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions intervals/interval.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -725,10 +758,16 @@ class DateInterval(AbstractInterval):
step = timedelta(days=1)
type = date

def coerce_string(self, value):
return date_from_iso(value)


class DateTimeInterval(AbstractInterval):
type = datetime

def coerce_string(self, value):
return datetime_from_iso(value)


class FloatInterval(NumberInterval):
type = float
Expand Down
28 changes: 27 additions & 1 deletion tests/interval/test_initialization.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
from datetime import date
from datetime import datetime
from decimal import Decimal

from infinity import inf
from pytest import mark, raises

from intervals import (
CharacterInterval,
DateInterval,
DateTimeInterval,
DecimalInterval,
FloatInterval,
IllegalArgument,
Interval,
IntInterval,
Interval,
RangeBoundsException
)

Expand Down Expand Up @@ -186,6 +189,29 @@ 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.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, 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


class TestTypeGuessing(object):
@mark.parametrize(
Expand Down