slashmili / python-jalali

Jalali calendar binding for Python based on Python's datetime module
http://pypi.python.org/pypi/jdatetime/
Other
335 stars 46 forks source link

feat(strptime):handle %b and %B directive. #121

Closed Mojtaba-saf closed 2 years ago

Mojtaba-saf commented 2 years ago

in response to this issue as I discussed there If patterns are changed to use '\d' instead of [0-9] regex patterns for python 3 can detect Unicode numbers.

to detect month names in the string we can use these patterns.

    '%B': '(?P<B>[a-zA-Z\u0600-\u06EF\uFB8A\u067E\u0686\u06AF]{3,12})'
    '%b': '(?P<b>[a-zA-Z]{3})',

these patterns detect month names. I tested it against these examples and it works fine.

jdatetime.datetime.strptime('14 Ordibehesht 1400', '%d %B %Y')
jdatetime.datetime.strptime('14 ordibehesht 1400', '%d %B %Y')
jdatetime.datetime.strptime('۱۴ Ordibehesht ۱۴۰۰', '%d %B %Y')
jdatetime.datetime.strptime('۱۴ ordibehesht ۱۴۰۰', '%d %B %Y')
jdatetime.datetime.strptime('1۴ Ordibehesht 14۰۰', '%d %B %Y')
jdatetime.datetime.strptime('۱4 ordibehesht 14۰0', '%d %B %Y')
jdatetime.datetime.strptime('۱۴ اردیبهشت ۱۴۰۰', '%d %B %Y')
jdatetime.datetime.strptime('14 اردیبهشت 1400', '%d %B %Y')
jdatetime.datetime.strptime('1۴ اردیبهشت ۱4۰0', '%d %B %Y')
jdatetime.datetime.strptime('14 Ord 1400', '%d %b %Y')
jdatetime.datetime.strptime('۱۴ Ord ۱۴۰۰', '%d %b %Y')
jdatetime.datetime.strptime('۱4 Ord 14۰0', '%d %b %Y')
hramezani commented 2 years ago

Thanks @Mojtaba-saf, Please add some tests for this path. You can add your tested example as test cases

hramezani commented 2 years ago

Let's add another test for invalid month name:

    def test_strptime_invalid_date_string_b_B_directive(self):
        with self.assertRaises(
            ValueError,
            msg="time data '14 foo 1400' does not match format '%d %b %Y'"
        ):
            jdatetime.datetime.strptime('14 foo 1400', '%d %b %Y')
Mojtaba-saf commented 2 years ago

sorry I'm not familiar with writing test cases. should this test for invalid month name be exactly like what you said or should it be like the last one and contain multiple subtests? I ask that because I think it should at least be 2 test cases one for B and one for b directive.

hramezani commented 2 years ago

sorry I'm not familiar with writing test cases. should this test for invalid month name be exactly like what you said or should it be like the last one and contain multiple subtests?

I would add it to a separate test function.

I ask that because I think it should at least be 2 test cases one for B and one for b directive.

Yes, you can another test case for B as well. like:

    def test_strptime_b_B_directive_invalid_month(self):
        tests = (
            ('۱4 foo 14۰0', '%d %B %Y'),
            ('۱4 bar 14۰0', '%d %b %Y'),
        )
        for date_string, date_format in tests:
            with self.subTest(date_string=date_string, date_format=date_format):
                with self.assertRaises(
                    ValueError,
                    msg=f"time data '{date_string}' does not match format '{date_format}'"
                ):
                    jdatetime.datetime.strptime(date_string, date_format)
slashmili commented 2 years ago

Thanks @Mojtaba-saf ❤️