Skip to content

Commit 70a0d3e

Browse files
committed
ISO 8601 parser for the examples
1 parent e58c0c6 commit 70a0d3e

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

examples/iso8601.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import datetime
2+
import pytz
3+
4+
from parsley import makeGrammar
5+
6+
# See www.ietf.org/rfc/rfc3339.txt
7+
8+
_iso_8601_definition = r"""
9+
year = <digit{4}>:Y -> int(Y)
10+
month = <digit{2}>:m -> int(m)
11+
day = <digit{2}>:d -> int(d)
12+
13+
hour = <digit{2}>:H -> int(H)
14+
minute = <digit{2}>:M -> int(M)
15+
second = <digit{2}>:S -> int(S)
16+
fraction = '.' <digit+>:frac -> int(float('0.' + frac) * 10 ** 6)
17+
18+
sign = ('-' -> -1) | ('+' -> 1)
19+
numeric_offset = sign:s hour:h ':' minute:m -> FixedOffset(s * (h * 60 + m))
20+
utc = 'Z' -> UTC
21+
offset = utc | numeric_offset
22+
23+
naive_time = hour:h ':' minute:m ':' second:s (fraction | -> 0):ms
24+
-> time(h, m, s, ms)
25+
time = naive_time:t offset:o -> t.replace(tzinfo=o)
26+
date = year:y '-' month:m '-' day:d -> date(y, m, d)
27+
28+
datetime = date:d 'T' time:t -> datetime.combine(d, t)
29+
"""
30+
31+
32+
DateTimeParser = makeGrammar(
33+
_iso_8601_definition,
34+
{
35+
'FixedOffset': pytz.FixedOffset,
36+
'date': datetime.date,
37+
'time': datetime.time,
38+
'datetime': datetime.datetime,
39+
'UTC': pytz.UTC,
40+
},
41+
)

examples/test_iso8601.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import datetime
2+
import unittest
3+
4+
import pytz
5+
6+
from iso8601 import DateTimeParser
7+
8+
9+
class TestDatetimeParsing(unittest.TestCase):
10+
11+
def test_date(self):
12+
self.assertEqual(
13+
datetime.date(2001, 12, 25),
14+
DateTimeParser('2001-12-25').date())
15+
16+
def test_naive_time(self):
17+
self.assertEqual(
18+
datetime.time(13, 59, 43),
19+
DateTimeParser('13:59:43').naive_time())
20+
21+
def test_fractional_naive_time(self):
22+
self.assertEqual(
23+
datetime.time(13, 59, 43, 880000),
24+
DateTimeParser('13:59:43.88').naive_time())
25+
26+
def test_utc_time(self):
27+
self.assertEqual(
28+
datetime.time(13, 59, 43, tzinfo=pytz.UTC),
29+
DateTimeParser('13:59:43Z').time())
30+
31+
def test_fractional_utc_time(self):
32+
self.assertEqual(
33+
datetime.time(13, 59, 43, 880000, tzinfo=pytz.UTC),
34+
DateTimeParser('13:59:43.88Z').time())
35+
36+
def test_timezone_time(self):
37+
self.assertEqual(
38+
datetime.time(13, 59, 43, tzinfo=pytz.FixedOffset(60)),
39+
DateTimeParser('13:59:43+01:00').time())
40+
41+
def test_fractional_timezone_time(self):
42+
self.assertEqual(
43+
datetime.time(13, 59, 43, 770000, tzinfo=pytz.FixedOffset(60)),
44+
DateTimeParser('13:59:43.77+01:00').time())
45+
46+
def test_numeric_offset(self):
47+
get_offset = lambda x: DateTimeParser(x).numeric_offset()
48+
self.assertEqual(pytz.FixedOffset(0), get_offset('+00:00'))
49+
self.assertEqual(pytz.FixedOffset(90), get_offset('+01:30'))
50+
self.assertEqual(pytz.FixedOffset(-150), get_offset('-02:30'))
51+
52+
def test_datetime(self):
53+
self.assertEqual(
54+
datetime.datetime(
55+
2001, 12, 25, 13, 59, 43, 770000, tzinfo=pytz.UTC),
56+
DateTimeParser('2001-12-25T13:59:43.77Z').datetime())

0 commit comments

Comments
 (0)