Codebase list isodate / 06693cb
Import Upstream version 0.5.4 Sandro Tosi 4 years ago
11 changed file(s) with 201 addition(s) and 72 deletion(s). Raw diff Collapse all Expand all
00
11 CHANGES
22 =======
3
4 0.5.4 (2015-08-06)
5 ------------------
6
7 - Fix parsing of Periods (Fabien Bochu)
8 - Make Duration objects hashable (Geoffrey Fairchild)
9 - Add multiplication to duration (Reinoud Elhorst)
10
311
412 0.5.1 (2014-11-07)
513 ------------------
00 Metadata-Version: 1.1
11 Name: isodate
2 Version: 0.5.1
3 Summary: An ISO 8601 date/time/duration parser and formater
2 Version: 0.5.4
3 Summary: An ISO 8601 date/time/duration parser and formatter
44 Home-page: http://cheeseshop.python.org/pypi/isodate
55 Author: Gerhard Weis
66 Author-email: gerhard.weis@proclos.com
99 ISO 8601 date/time parser
1010 =========================
1111
12 .. image:: https://travis-ci.org/gweis/isodate.png?branch=master
12 .. image:: https://travis-ci.org/gweis/isodate.svg?branch=master
1313 :target: https://travis-ci.org/gweis/isodate
1414 :alt: Travis-CI
15 .. image:: https://coveralls.io/repos/gweis/isodate/badge.png?branch=master
15 .. image:: https://coveralls.io/repos/gweis/isodate/badge.svg?branch=master
1616 :target: https://coveralls.io/r/gweis/isodate?branch=master
1717 :alt: Coveralls
18 .. image:: https://pypip.in/v/isodate/badge.png
18 .. image:: https://pypip.in/version/isodate/badge.svg
1919 :target: https://pypi.python.org/pypi/isodate/
2020 :alt: Latest Version
21 .. image:: https://pypip.in/d/isodate/badge.png
22 :target: https://pypi.python.org/pypi//isodate/
21 .. image:: https://pypip.in/download/isodate/badge.svg
22 :target: https://pypi.python.org/pypi/isodate/
2323 :alt: Downloads
24 .. image:: https://pypip.in/license/isodate/badge.png
24 .. image:: https://pypip.in/license/isodate/badge.svg
2525 :target: https://pypi.python.org/pypi/isodate/
2626 :alt: License
2727
6767 which can be used almost like a *timedelta* object (with some limitations).
6868 However, a *Duration* object can be converted into a *timedelta* object.
6969
70 There are also ISO formating methods for all supported data types. Each
70 There are also ISO formatting methods for all supported data types. Each
7171 *xxx_isoformat* method accepts a format parameter. The default format is
7272 always the ISO 8601 expanded format. This is the same format used by
7373 *datetime.isoformat*:
128128 CHANGES
129129 =======
130130
131 0.5.4 (2015-08-06)
132 ------------------
133
134 - Fix parsing of Periods (Fabien Bochu)
135 - Make Duration objects hashable (Geoffrey Fairchild)
136 - Add multiplication to duration (Reinoud Elhorst)
137
138
131139 0.5.1 (2014-11-07)
132140 ------------------
133141
11 ISO 8601 date/time parser
22 =========================
33
4 .. image:: https://travis-ci.org/gweis/isodate.png?branch=master
4 .. image:: https://travis-ci.org/gweis/isodate.svg?branch=master
55 :target: https://travis-ci.org/gweis/isodate
66 :alt: Travis-CI
7 .. image:: https://coveralls.io/repos/gweis/isodate/badge.png?branch=master
7 .. image:: https://coveralls.io/repos/gweis/isodate/badge.svg?branch=master
88 :target: https://coveralls.io/r/gweis/isodate?branch=master
99 :alt: Coveralls
10 .. image:: https://pypip.in/v/isodate/badge.png
10 .. image:: https://pypip.in/version/isodate/badge.svg
1111 :target: https://pypi.python.org/pypi/isodate/
1212 :alt: Latest Version
13 .. image:: https://pypip.in/d/isodate/badge.png
14 :target: https://pypi.python.org/pypi//isodate/
13 .. image:: https://pypip.in/download/isodate/badge.svg
14 :target: https://pypi.python.org/pypi/isodate/
1515 :alt: Downloads
16 .. image:: https://pypip.in/license/isodate/badge.png
16 .. image:: https://pypip.in/license/isodate/badge.svg
1717 :target: https://pypi.python.org/pypi/isodate/
1818 :alt: License
1919
5959 which can be used almost like a *timedelta* object (with some limitations).
6060 However, a *Duration* object can be converted into a *timedelta* object.
6161
62 There are also ISO formating methods for all supported data types. Each
62 There are also ISO formatting methods for all supported data types. Each
6363 *xxx_isoformat* method accepts a format parameter. The default format is
6464 always the ISO 8601 expanded format. This is the same format used by
6565 *datetime.isoformat*:
00 [egg_info]
1 tag_date = 0
21 tag_build =
32 tag_svn_revision = 0
3 tag_date = 0
44
4545 return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
4646
4747 setup(name='isodate',
48 version='0.5.1',
48 version='0.5.4',
4949 packages=['isodate', 'isodate.tests'],
5050 package_dir={'': 'src'},
5151
5555 # PyPI metadata
5656 author='Gerhard Weis',
5757 author_email='gerhard.weis@proclos.com',
58 description='An ISO 8601 date/time/duration parser and formater',
58 description='An ISO 8601 date/time/duration parser and formatter',
5959 license='BSD',
6060 # keywords = '',
6161 url='http://cheeseshop.python.org/pypi/isodate',
5353 from isodate.isostrf import D_DEFAULT, D_WEEK, D_ALT_EXT, D_ALT_BAS
5454 from isodate.isostrf import D_ALT_BAS_ORD, D_ALT_EXT_ORD
5555
56 __all__ = (parse_date, date_isoformat, parse_time, time_isoformat,
57 parse_datetime, datetime_isoformat, parse_duration,
58 duration_isoformat, ISO8601Error, parse_tzinfo,
59 tz_isoformat, UTC, FixedOffset, LOCAL, Duration,
60 strftime, DATE_BAS_COMPLETE, DATE_BAS_ORD_COMPLETE,
61 DATE_BAS_WEEK, DATE_BAS_WEEK_COMPLETE, DATE_CENTURY,
62 DATE_EXT_COMPLETE, DATE_EXT_ORD_COMPLETE, DATE_EXT_WEEK,
63 DATE_EXT_WEEK_COMPLETE, DATE_MONTH, DATE_YEAR,
64 TIME_BAS_COMPLETE, TIME_BAS_MINUTE, TIME_EXT_COMPLETE,
65 TIME_EXT_MINUTE, TIME_HOUR, TZ_BAS, TZ_EXT, TZ_HOUR,
66 DT_BAS_COMPLETE, DT_EXT_COMPLETE, DT_BAS_ORD_COMPLETE,
67 DT_EXT_ORD_COMPLETE, DT_BAS_WEEK_COMPLETE,
68 DT_EXT_WEEK_COMPLETE, D_DEFAULT, D_WEEK, D_ALT_EXT,
69 D_ALT_BAS, D_ALT_BAS_ORD, D_ALT_EXT_ORD)
56 __all__ = ['parse_date', 'date_isoformat', 'parse_time', 'time_isoformat',
57 'parse_datetime', 'datetime_isoformat', 'parse_duration',
58 'duration_isoformat', 'ISO8601Error', 'parse_tzinfo',
59 'tz_isoformat', 'UTC', 'FixedOffset', 'LOCAL', 'Duration',
60 'strftime', 'DATE_BAS_COMPLETE', 'DATE_BAS_ORD_COMPLETE',
61 'DATE_BAS_WEEK', 'DATE_BAS_WEEK_COMPLETE', 'DATE_CENTURY',
62 'DATE_EXT_COMPLETE', 'DATE_EXT_ORD_COMPLETE', 'DATE_EXT_WEEK',
63 'DATE_EXT_WEEK_COMPLETE', 'DATE_MONTH', 'DATE_YEAR',
64 'TIME_BAS_COMPLETE', 'TIME_BAS_MINUTE', 'TIME_EXT_COMPLETE',
65 'TIME_EXT_MINUTE', 'TIME_HOUR', 'TZ_BAS', 'TZ_EXT', 'TZ_HOUR',
66 'DT_BAS_COMPLETE', 'DT_EXT_COMPLETE', 'DT_BAS_ORD_COMPLETE',
67 'DT_EXT_ORD_COMPLETE', 'DT_BAS_WEEK_COMPLETE',
68 'DT_EXT_WEEK_COMPLETE', 'D_DEFAULT', 'D_WEEK', 'D_ALT_EXT',
69 'D_ALT_BAS', 'D_ALT_BAS_ORD', 'D_ALT_EXT_ORD']
133133 self.tdelta.days, self.tdelta.seconds,
134134 self.tdelta.microseconds, self.years, self.months)
135135
136 def __hash__(self):
137 '''
138 Return a hash of this instance so that it can be used in, for
139 example, dicts and sets.
140 '''
141 return hash((self.tdelta, self.months, self.years))
142
136143 def __neg__(self):
137144 """
138145 A simple unary minus.
158165 newduration.tdelta = self.tdelta + other.tdelta
159166 return newduration
160167 if isinstance(other, (date, datetime)):
161 if (not(float(self.years).is_integer()
162 and float(self.months).is_integer())):
168 if (not(float(self.years).is_integer() and
169 float(self.months).is_integer())):
163170 raise ValueError('fractional years or months not supported'
164171 ' for date calculations')
165172 newmonth = other.month + self.months
184191 newduration.tdelta = self.tdelta + other
185192 return newduration
186193 if isinstance(other, (date, datetime)):
187 if (not(float(self.years).is_integer()
188 and float(self.months).is_integer())):
194 if (not(float(self.years).is_integer() and
195 float(self.months).is_integer())):
189196 raise ValueError('fractional years or months not supported'
190197 ' for date calculations')
191198 newmonth = other.month + self.months
201208 raise TypeError('unsupported operand type(s) for +: %s and %s' %
202209 (other.__class__, self.__class__))
203210
211 def __mul__(self, other):
212 if isinstance(other, int):
213 newduration = Duration(
214 years=self.years * other,
215 months=self.months * other)
216 newduration.tdelta = self.tdelta * other
217 return newduration
218 raise TypeError('unsupported operand type(s) for +: %s and %s' %
219 (self.__class__, other.__class__))
220
221 def __rmul__(self, other):
222
223 if isinstance(other, int):
224 newduration = Duration(
225 years=self.years * other,
226 months=self.months * other)
227 newduration.tdelta = self.tdelta * other
228 return newduration
229 raise TypeError('unsupported operand type(s) for +: %s and %s' %
230 (other.__class__, self.__class__))
231
204232 def __sub__(self, other):
205233 '''
206234 It is possible to subtract Duration and timedelta objects from Duration
225253 '''
226254 # print '__rsub__:', self, other
227255 if isinstance(other, (date, datetime)):
228 if (not(float(self.years).is_integer()
229 and float(self.months).is_integer())):
256 if (not(float(self.years).is_integer() and
257 float(self.months).is_integer())):
230258 raise ValueError('fractional years or months not supported'
231259 ' for date calculations')
232260 newmonth = other.month - self.months
257285 if not isinstance(other, Duration):
258286 return NotImplemented
259287 if (((self.years * 12 + self.months) ==
260 (other.years * 12 + other.months)
261 and self.tdelta == other.tdelta)):
288 (other.years * 12 + other.months) and
289 self.tdelta == other.tdelta)):
262290 return True
263291 return False
264292
267295 If the years, month part or the timedelta part is not equal, then
268296 the two Durations are considered not equal.
269297 '''
270 if ((isinstance(other, timedelta)
271 and self.years == 0
272 and self.months == 0)):
298 if ((isinstance(other, timedelta) and
299 self.years == 0 and
300 self.months == 0)):
273301 return self.tdelta != other
274302 if not isinstance(other, Duration):
275303 return NotImplemented
276304 if (((self.years * 12 + self.months) !=
277 (other.years * 12 + other.months)
278 or self.tdelta != other.tdelta)):
305 (other.years * 12 + other.months) or
306 self.tdelta != other.tdelta)):
279307 return True
280308 return False
281309
4040
4141 ISO8601_PERIOD_REGEX = re.compile(
4242 r"^(?P<sign>[+-])?"
43 r"P(?P<years>[0-9]+([,.][0-9]+)?Y)?"
43 r"P(?!\b)"
44 r"(?P<years>[0-9]+([,.][0-9]+)?Y)?"
4445 r"(?P<months>[0-9]+([,.][0-9]+)?M)?"
4546 r"(?P<weeks>[0-9]+([,.][0-9]+)?W)?"
4647 r"(?P<days>[0-9]+([,.][0-9]+)?D)?"
135136 '''
136137 # TODO: implement better decision for negative Durations.
137138 # should be done in Duration class in consistent way with timedelta.
138 if (((isinstance(tduration, Duration)
139 and (tduration.years < 0 or tduration.months < 0
140 or tduration.tdelta < timedelta(0)))
141 or (isinstance(tduration, timedelta)
142 and (tduration < timedelta(0))))):
139 if (((isinstance(tduration, Duration) and
140 (tduration.years < 0 or tduration.months < 0 or
141 tduration.tdelta < timedelta(0))) or
142 (isinstance(tduration, timedelta) and
143 (tduration < timedelta(0))))):
143144 ret = '-'
144145 else:
145146 ret = ''
7070 # hh:mm:ss.ss ... extended format
7171 TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2}):"
7272 r"(?P<minute>[0-9]{2}):"
73 r"(?P<second>[0-9]{2}([,.][0-9]+)?)"
74 + TZ_REGEX))
73 r"(?P<second>[0-9]{2}"
74 r"([,.][0-9]+)?)" + TZ_REGEX))
7575 # hhmmss.ss ... basic format
7676 TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2})"
7777 r"(?P<minute>[0-9]{2})"
78 r"(?P<second>[0-9]{2}([,.][0-9]+)?)"
79 + TZ_REGEX))
78 r"(?P<second>[0-9]{2}"
79 r"([,.][0-9]+)?)" + TZ_REGEX))
8080 # 2. reduced accuracy:
8181 # hh:mm.mm ... extended format
8282 TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2}):"
83 r"(?P<minute>[0-9]{2}([,.][0-9]+)?)"
84 + TZ_REGEX))
83 r"(?P<minute>[0-9]{2}"
84 r"([,.][0-9]+)?)" + TZ_REGEX))
8585 # hhmm.mm ... basic format
8686 TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2})"
87 r"(?P<minute>[0-9]{2}([,.][0-9]+)?)"
88 + TZ_REGEX))
87 r"(?P<minute>[0-9]{2}"
88 r"([,.][0-9]+)?)" + TZ_REGEX))
8989 # hh.hh ... basic format
90 TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2}([,.][0-9]+)?)"
91 + TZ_REGEX))
90 TIME_REGEX_CACHE.append(re.compile(r"T?(?P<hour>[0-9]{2}"
91 r"([,.][0-9]+)?)" + TZ_REGEX))
9292 return TIME_REGEX_CACHE
9393
9494
230230 # date(2001, 2, 14)),
231231 )
232232
233 # A list of test cases of multiplications of durations
234 # are compared against a given expected result.
235 DATE_MUL_TEST_CASES = (
236 (Duration(years=1, months=1),
237 3,
238 Duration(years=3, months=3)),
239 (Duration(years=1, months=1),
240 -3,
241 Duration(years=-3, months=-3)),
242 (3,
243 Duration(years=1, months=1),
244 Duration(years=3, months=3)),
245 (-3,
246 Duration(years=1, months=1),
247 Duration(years=-3, months=-3)),
248 (5,
249 Duration(years=2, minutes=40),
250 Duration(years=10, hours=3, minutes=20)),
251 (-5,
252 Duration(years=2, minutes=40),
253 Duration(years=-10, hours=-3, minutes=-20)),
254 (7,
255 Duration(years=1, months=2, weeks=40),
256 Duration(years=8, months=2, weeks=280)))
257
233258
234259 class DurationTest(unittest.TestCase):
235260 '''
262287 'raise exception')
263288 self.assertRaises(TypeError, operator.add, 'raise exception',
264289 Duration(years=1, months=1, weeks=5))
290 self.assertRaises(TypeError, operator.mul,
291 Duration(years=1, months=1, weeks=5),
292 'raise exception')
293 self.assertRaises(TypeError, operator.mul, 'raise exception',
294 Duration(years=1, months=1, weeks=5))
295 self.assertRaises(TypeError, operator.mul,
296 Duration(years=1, months=1, weeks=5),
297 3.14)
298 self.assertRaises(TypeError, operator.mul, 3.14,
299 Duration(years=1, months=1, weeks=5))
265300
266301 def test_parseerror(self):
267302 '''
271306
272307 def test_repr(self):
273308 '''
274 Test __repr__ and __str__ for Duration obqects.
309 Test __repr__ and __str__ for Duration objects.
275310 '''
276311 dur = Duration(10, 10, years=10, months=10)
277312 self.assertEqual('10 years, 10 months, 10 days, 0:00:10', str(dur))
278313 self.assertEqual('isodate.duration.Duration(10, 10, 0,'
279314 ' years=10, months=10)', repr(dur))
315
316 def test_hash(self):
317 '''
318 Test __hash__ for Duration objects.
319 '''
320 dur1 = Duration(10, 10, years=10, months=10)
321 dur2 = Duration(9, 9, years=9, months=9)
322 dur3 = Duration(10, 10, years=10, months=10)
323 self.assertNotEqual(hash(dur1), hash(dur2))
324 self.assertNotEqual(id(dur1), id(dur2))
325 self.assertEqual(hash(dur1), hash(dur3))
326 self.assertNotEqual(id(dur1), id(dur3))
327 durSet = set()
328 durSet.add(dur1)
329 durSet.add(dur2)
330 durSet.add(dur3)
331 self.assertEqual(len(durSet), 2)
280332
281333 def test_neg(self):
282334 '''
497549 return unittest.TestLoader().loadTestsFromTestCase(TestDateCalc)
498550
499551
552 def create_datemultestcase(operand1, operand2, expectation):
553 """
554 Create a TestCase class for a specific test.
555
556 This allows having a separate TestCase for each test tuple from the
557 DATE_CALC_TEST_CASES list, so that a failed test won't stop other tests.
558 """
559
560 class TestDateMul(unittest.TestCase):
561 '''
562 A test case template test addition operators for Duration objects.
563 '''
564
565 def test_mul(self):
566 '''
567 Test operator *.
568 '''
569 self.assertEqual(operand1 * operand2, expectation)
570
571 return unittest.TestLoader().loadTestsFromTestCase(TestDateMul)
572
573
500574 def test_suite():
501575 '''
502576 Return a test suite containing all test defined above.
512586 suite.addTest(create_datetestcase(*testdata))
513587 for testdata in DATE_CALC_TEST_CASES:
514588 suite.addTest(create_datecalctestcase(*testdata))
589 for testdata in DATE_MUL_TEST_CASES:
590 suite.addTest(create_datemultestcase(*testdata))
515591 suite.addTest(unittest.TestLoader().loadTestsFromTestCase(DurationTest))
516592 return suite
517593
00 Metadata-Version: 1.1
11 Name: isodate
2 Version: 0.5.1
3 Summary: An ISO 8601 date/time/duration parser and formater
2 Version: 0.5.4
3 Summary: An ISO 8601 date/time/duration parser and formatter
44 Home-page: http://cheeseshop.python.org/pypi/isodate
55 Author: Gerhard Weis
66 Author-email: gerhard.weis@proclos.com
99 ISO 8601 date/time parser
1010 =========================
1111
12 .. image:: https://travis-ci.org/gweis/isodate.png?branch=master
12 .. image:: https://travis-ci.org/gweis/isodate.svg?branch=master
1313 :target: https://travis-ci.org/gweis/isodate
1414 :alt: Travis-CI
15 .. image:: https://coveralls.io/repos/gweis/isodate/badge.png?branch=master
15 .. image:: https://coveralls.io/repos/gweis/isodate/badge.svg?branch=master
1616 :target: https://coveralls.io/r/gweis/isodate?branch=master
1717 :alt: Coveralls
18 .. image:: https://pypip.in/v/isodate/badge.png
18 .. image:: https://pypip.in/version/isodate/badge.svg
1919 :target: https://pypi.python.org/pypi/isodate/
2020 :alt: Latest Version
21 .. image:: https://pypip.in/d/isodate/badge.png
22 :target: https://pypi.python.org/pypi//isodate/
21 .. image:: https://pypip.in/download/isodate/badge.svg
22 :target: https://pypi.python.org/pypi/isodate/
2323 :alt: Downloads
24 .. image:: https://pypip.in/license/isodate/badge.png
24 .. image:: https://pypip.in/license/isodate/badge.svg
2525 :target: https://pypi.python.org/pypi/isodate/
2626 :alt: License
2727
6767 which can be used almost like a *timedelta* object (with some limitations).
6868 However, a *Duration* object can be converted into a *timedelta* object.
6969
70 There are also ISO formating methods for all supported data types. Each
70 There are also ISO formatting methods for all supported data types. Each
7171 *xxx_isoformat* method accepts a format parameter. The default format is
7272 always the ISO 8601 expanded format. This is the same format used by
7373 *datetime.isoformat*:
128128 CHANGES
129129 =======
130130
131 0.5.4 (2015-08-06)
132 ------------------
133
134 - Fix parsing of Periods (Fabien Bochu)
135 - Make Duration objects hashable (Geoffrey Fairchild)
136 - Add multiplication to duration (Reinoud Elhorst)
137
138
131139 0.5.1 (2014-11-07)
132140 ------------------
133141