Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix parsing of localized meridians (refers #228) #244

Merged
Merged
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
20 changes: 15 additions & 5 deletions arrow/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ class DateTimeParser(object):
'm': _ONE_OR_TWO_DIGIT_RE,
'ss': _TWO_DIGIT_RE,
's': _ONE_OR_TWO_DIGIT_RE,
'a': re.compile('(a|A|p|P)'),
'A': re.compile('(am|AM|pm|PM)'),
'X': re.compile('\d+'),
'ZZ': _TZ_RE,
'Z': _TZ_RE,
Expand All @@ -64,7 +62,13 @@ def __init__(self, locale='en_us'):
'MMMM': self._choice_re(self.locale.month_names[1:], re.IGNORECASE),
'MMM': self._choice_re(self.locale.month_abbreviations[1:],
re.IGNORECASE),
'Do': re.compile(self.locale.ordinal_day_re)
'Do': re.compile(self.locale.ordinal_day_re),
'a': self._choice_re(
(self.locale.meridians['am'], self.locale.meridians['pm'])
),
# note: 'A' token accepts both 'am/pm' and 'AM/PM' formats to
# ensure backwards compatibility of this token
'A': self._choice_re(self.locale.meridians.values())
})

def parse_iso(self, string):
Expand Down Expand Up @@ -210,9 +214,15 @@ def _parse_token(self, token, value, parts):
parts['tzinfo'] = TzinfoParser.parse(value)

elif token in ['a', 'A']:
if value in ['a', 'A', 'am', 'AM']:
if value in (
self.locale.meridians['am'],
self.locale.meridians['AM']
):
parts['am_pm'] = 'am'
elif value in ['p', 'P', 'pm', 'PM']:
elif value in (
self.locale.meridians['pm'],
self.locale.meridians['PM']
):
parts['am_pm'] = 'pm'

@classmethod
Expand Down
16 changes: 10 additions & 6 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -377,9 +377,9 @@ Use the following tokens in parsing and formatting:
+--------------------------------+--------------+-------------------------------------------+
| |YY |00, 01, 02 ... 12, 13 |
+--------------------------------+--------------+-------------------------------------------+
|**Month** |MMMM |January, February, March ... |
|**Month** |MMMM |January, February, March ... [#t1]_ |
+--------------------------------+--------------+-------------------------------------------+
| |MMM |Jan, Feb, Mar ... |
| |MMM |Jan, Feb, Mar ... [#t1]_ |
+--------------------------------+--------------+-------------------------------------------+
| |MM |01, 02, 03 ... 11, 12 |
+--------------------------------+--------------+-------------------------------------------+
Expand All @@ -395,9 +395,9 @@ Use the following tokens in parsing and formatting:
+--------------------------------+--------------+-------------------------------------------+
| |Do |1st, 2nd, 3rd ... 30th, 31st |
+--------------------------------+--------------+-------------------------------------------+
|**Day of Week** |dddd |Monday, Tuesday, Wednesday ... |
|**Day of Week** |dddd |Monday, Tuesday, Wednesday ... [#t2]_ |
+--------------------------------+--------------+-------------------------------------------+
| |ddd |Mon, Tue, Wed ... |
| |ddd |Mon, Tue, Wed ... [#t2]_ |
+--------------------------------+--------------+-------------------------------------------+
| |d |1, 2, 3 ... 6, 7 |
+--------------------------------+--------------+-------------------------------------------+
Expand All @@ -409,9 +409,9 @@ Use the following tokens in parsing and formatting:
+--------------------------------+--------------+-------------------------------------------+
| |h |1, 2, 3 ... 11, 12 |
+--------------------------------+--------------+-------------------------------------------+
|**AM / PM** |A |AM, PM |
|**AM / PM** |A |AM, PM, am, pm [#t1]_ |
+--------------------------------+--------------+-------------------------------------------+
| |a |am, pm |
| |a |am, pm [#t1]_ |
+--------------------------------+--------------+-------------------------------------------+
|**Minute** |mm |00, 01, 02 ... 58, 59 |
+--------------------------------+--------------+-------------------------------------------+
Expand All @@ -434,6 +434,10 @@ Use the following tokens in parsing and formatting:
|**Timestamp** |X |1381685817 |
+--------------------------------+--------------+-------------------------------------------+

.. rubric:: Footnotes

.. [#t1] localization support for parsing and formatting
.. [#t2] localization support only for formatting

---------
API Guide
Expand Down
55 changes: 55 additions & 0 deletions tests/parser_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,61 @@ def test_localized_month_abbreviation(self):
datetime(2013, 1, 1)
)


class DateTimeParserMeridiansTests(Chai):

def setUp(self):
super(DateTimeParserMeridiansTests, self).setUp()

self.parser = parser.DateTimeParser('en_us')

def test_meridians_lowercase(self):
assertEqual(
self.parser.parse('2013-01-01 5am', 'YYYY-MM-DD ha'),
datetime(2013, 1, 1, 5)
)

assertEqual(
self.parser.parse('2013-01-01 5pm', 'YYYY-MM-DD ha'),
datetime(2013, 1, 1, 17)
)

def test_meridians_capitalized(self):
assertEqual(
self.parser.parse('2013-01-01 5AM', 'YYYY-MM-DD hA'),
datetime(2013, 1, 1, 5)
)

assertEqual(
self.parser.parse('2013-01-01 5PM', 'YYYY-MM-DD hA'),
datetime(2013, 1, 1, 17)
)

def test_localized_meridians_lowercase(self):
parser_ = parser.DateTimeParser('hu_hu')
assertEqual(
parser_.parse('2013-01-01 5 de', 'YYYY-MM-DD h a'),
datetime(2013, 1, 1, 5)
)

assertEqual(
parser_.parse('2013-01-01 5 du', 'YYYY-MM-DD h a'),
datetime(2013, 1, 1, 17)
)

def test_localized_meridians_capitalized(self):
parser_ = parser.DateTimeParser('hu_hu')
assertEqual(
parser_.parse('2013-01-01 5 DE', 'YYYY-MM-DD h A'),
datetime(2013, 1, 1, 5)
)

assertEqual(
parser_.parse('2013-01-01 5 DU', 'YYYY-MM-DD h A'),
datetime(2013, 1, 1, 17)
)


class DateTimeParserMonthOrdinalDayTests(Chai):

def setUp(self):
Expand Down