-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add an undate converter to wire in hijri date parsing capability
- Loading branch information
Showing
4 changed files
with
86 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from undate.converters.calendars.hijri import HijriDateConverter | ||
|
||
__all__ = ["HijriDateConverter"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from undate.converters.calendars.hijri.converter import HijriDateConverter | ||
|
||
__all__ = ["HijriDateConverter"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
from typing import Union | ||
|
||
from lark.exceptions import UnexpectedCharacters | ||
|
||
from undate.converters.base import BaseDateConverter | ||
from undate.converters.calendars.hijri.parser import hijri_parser | ||
from undate.converters.calendars.hijri.transformer import HijriDateTransformer | ||
from undate.undate import Undate, UndateInterval | ||
|
||
|
||
class HijriDateConverter(BaseDateConverter): | ||
""" | ||
Converter for Hijri / Islamic calendar. | ||
Support for parsing Hijri dates and converting to Undate and UndateInterval | ||
objects in the Gregorian calendar. | ||
""" | ||
|
||
#: converter name: Hijri | ||
name: str = "Hijri" | ||
calendar_name: str = "Hijrī" | ||
|
||
def __init__(self): | ||
self.transformer = HijriDateTransformer() | ||
|
||
def parse(self, value: str) -> Union[Undate, UndateInterval]: | ||
""" | ||
Parse a Hijri date string and return an :class:`~undate.undate.Undate` or | ||
:class:`~undate.undate.UndateInterval` in Gregorian calendar. | ||
The Hijri date string is preserved in the undate label | ||
""" | ||
if not value: | ||
raise ValueError("Parsing empty string is not supported") | ||
|
||
# parse the input string, then transform to undate object | ||
try: | ||
# parse the string with our Hijri date parser | ||
parsetree = hijri_parser.parse(value) | ||
# transform the parse tree into an undate or undate interval | ||
undate_obj = self.transformer.transform(parsetree) | ||
# set the original date as a label, with the calendar name | ||
undate_obj.label = f"{value} {self.calendar_name}" | ||
return undate_obj | ||
except UnexpectedCharacters: | ||
raise ValueError("Could not parse '%s' as a Hijri date" % value) | ||
|
||
# do we need to support conversion the other direction? | ||
# i.e., generate a Hijri date from an abitrary undate or undate interval? |
32 changes: 32 additions & 0 deletions
32
tests/test_converters/test_calendars/test_hijri/test_hijri_converter.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import pytest | ||
from undate.converters.calendars import HijriDateConverter | ||
from undate.undate import Undate, UndateInterval | ||
|
||
|
||
class TestHijriDateConverter: | ||
def test_parse_(self): | ||
# day | ||
date_str = "7 Jumādā I 1243" | ||
date = HijriDateConverter().parse(date_str) | ||
assert date == Undate(1827, 11, 26) | ||
assert date.label == f"{date_str} {HijriDateConverter.calendar_name}" | ||
|
||
# month | ||
date_str = "Rajab 495" | ||
date = HijriDateConverter().parse(date_str) | ||
assert date == UndateInterval(Undate(1102, 4, 28), Undate(1102, 5, 27)) | ||
assert date.label == f"{date_str} {HijriDateConverter.calendar_name}" | ||
|
||
# year | ||
date_str = "441" | ||
date = HijriDateConverter().parse(date_str) | ||
assert date == UndateInterval(Undate(1049, 6, 11), Undate(1050, 5, 31)) | ||
assert date.label == f"{date_str} {HijriDateConverter.calendar_name}" | ||
|
||
def test_parse_error(self): | ||
# a string we can't parse should raise an error | ||
with pytest.raises(ValueError): | ||
HijriDateConverter().parse("January 2, 1991") | ||
# empty string should also error | ||
with pytest.raises(ValueError): | ||
HijriDateConverter().parse("") |