Skip to content

Commit 5bb3302

Browse files
author
Aaron Gallagher
committed
Merge branch 'iso8601'
2 parents 2e9639b + 5c6ec66 commit 5bb3302

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ python:
44
- "2.7"
55

66
install:
7-
- "pip install pytest Twisted coveralls . --use-mirrors"
7+
- "pip install pytest Twisted coveralls pytz . --use-mirrors"
88
script:
99
- "coverage run $(which trial) test_parsley"
1010
- "coverage run -a $(which trial) ometa"

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

0 commit comments

Comments
 (0)