summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerhard Weis <gerhard.weis@gmail.com>2013-01-24 15:55:42 +1000
committerGerhard Weis <gerhard.weis@gmail.com>2013-01-24 15:56:03 +1000
commit27eb4b1b7a0b21cb5bf36094bd56c34ee2a73112 (patch)
treed831bdd8b5dce63e39bb30d574db47bb6cc43941
parent74392567b6fef5890a1beb77ff6585f5a40b8f59 (diff)
downloadisodate-27eb4b1b7a0b21cb5bf36094bd56c34ee2a73112.tar.gz
- raise Exception for unsupported operations with duration and date/datetime objects
- store year and month as Decimal in Duration object. - added test cases to support changes closes #2
-rw-r--r--src/isodate/duration.py6
-rw-r--r--src/isodate/isoduration.py7
-rw-r--r--src/isodate/tests/test_duration.py24
3 files changed, 29 insertions, 8 deletions
diff --git a/src/isodate/duration.py b/src/isodate/duration.py
index fa501cd..0d5e0fa 100644
--- a/src/isodate/duration.py
+++ b/src/isodate/duration.py
@@ -140,6 +140,8 @@ class Duration(object):
newduration.tdelta = self.tdelta + other.tdelta
return newduration
if isinstance(other, (date, datetime)):
+ if (not( float(self.years).is_integer() and float(self.months).is_integer())):
+ raise ValueError('fractional years or months not supported for date calculations')
newmonth = other.month + self.months
carry, newmonth = fquotmod(newmonth, 1, 13)
newyear = other.year + self.years + carry
@@ -162,6 +164,8 @@ class Duration(object):
newduration.tdelta = self.tdelta + other
return newduration
if isinstance(other, (date, datetime)):
+ if (not( float(self.years).is_integer() and float(self.months).is_integer())):
+ raise ValueError('fractional years or months not supported for date calculations')
newmonth = other.month + self.months
carry, newmonth = fquotmod(newmonth, 1, 13)
newyear = other.year + self.years + carry
@@ -199,6 +203,8 @@ class Duration(object):
'''
#print '__rsub__:', self, other
if isinstance(other, (date, datetime)):
+ if (not( float(self.years).is_integer() and float(self.months).is_integer())):
+ raise ValueError('fractional years or months not supported for date calculations')
newmonth = other.month - self.months
carry, newmonth = fquotmod(newmonth, 1, 13)
newyear = other.year - self.years + carry
diff --git a/src/isodate/isoduration.py b/src/isodate/isoduration.py
index 3554b1f..97affdc 100644
--- a/src/isodate/isoduration.py
+++ b/src/isodate/isoduration.py
@@ -31,6 +31,7 @@ It also provides a wrapper to strftime. This wrapper makes it easier to
format timedelta or Duration instances as ISO conforming strings.
'''
from datetime import timedelta
+from decimal import Decimal
import re
from isodate.duration import Duration
@@ -103,7 +104,11 @@ def parse_duration(datestring):
if val is None:
groups[key] = "0n"
#print groups[key]
- groups[key] = float(groups[key][:-1].replace(',', '.'))
+ if key in ('years', 'months'):
+ groups[key] = Decimal(groups[key][:-1].replace(',', '.'))
+ else:
+ # these values are passed into a timedelta object, which works with floats.
+ groups[key] = float(groups[key][:-1].replace(',', '.'))
if groups["years"] == 0 and groups["months"] == 0:
ret = timedelta(days=groups["days"], hours=groups["hours"],
minutes=groups["minutes"], seconds=groups["seconds"],
diff --git a/src/isodate/tests/test_duration.py b/src/isodate/tests/test_duration.py
index d8b4cf2..a66652e 100644
--- a/src/isodate/tests/test_duration.py
+++ b/src/isodate/tests/test_duration.py
@@ -192,12 +192,18 @@ DATE_CALC_TEST_CASES = (
(Duration(years=1, months=1, weeks=5),
date(2000, 1, 30),
date(2001, 4, 4)),
- (Duration(years=1, months=1, weeks=5),
- 'raise exception',
- None),
- ('raise exception',
- Duration(years=1, months=1, weeks=5),
+ (parse_duration("P1Y1M5W"),
+ date(2000, 1, 30),
+ date(2001, 4, 4)),
+ (parse_duration("P0.5Y"),
+ date(2000, 1, 30),
None),
+ (Duration(years=1, months=1, hours=3),
+ datetime(2000, 1, 30, 12, 15, 00),
+ datetime(2001, 2, 28, 15, 15, 00)),
+ (parse_duration("P1Y1MT3H"),
+ datetime(2000, 1, 30, 12, 15, 00),
+ datetime(2001, 2, 28, 15, 15, 00)),
(Duration(years=1, months=2),
timedelta(days=1),
Duration(years=1, months=2, days=1)),
@@ -239,7 +245,11 @@ class DurationTest(unittest.TestCase):
date(2000, 1, 1))
self.assertRaises(TypeError, operator.sub, 'raise exc',
Duration(years=1))
-
+ self.assertRaises(TypeError, operator.add, Duration(years=1, months=1, weeks=5),
+ 'raise exception')
+ self.assertRaises(TypeError, operator.add, 'raise exception',
+ Duration(years=1, months=1, weeks=5))
+
def test_parseerror(self):
'''
Test for unparseable duration string.
@@ -451,7 +461,7 @@ def create_datecalctestcase(start, duration, expectation):
Test operator +.
'''
if expectation is None:
- self.assertRaises(TypeError, operator.add, start, duration)
+ self.assertRaises(ValueError, operator.add, start, duration)
else:
self.assertEqual(start + duration, expectation)