diff --git a/reminder/locale_util.py b/reminder/locale_util.py index 1d93dcc097f1b49af6e4b9a897f3385bc6b700bf..dd5462faff80df2c304bad5b124d67d5b0f3b862 100644 --- a/reminder/locale_util.py +++ b/reminder/locale_util.py @@ -13,7 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. -from typing import NamedTuple, Union, Pattern, Dict, Type, Optional, TYPE_CHECKING +from typing import NamedTuple, Union, Pattern, Match, Dict, Type, Optional, TYPE_CHECKING from datetime import datetime from abc import ABC, abstractmethod import re @@ -73,11 +73,31 @@ class RegexMatcher(Matcher): def match(self, val: str, start: int = 0) -> Optional[MatcherReturn]: match = self.regex.match(val, pos=start) if match and match.end() > 0: - return MatcherReturn(params={key: self.value_type(value) - for key, value in match.groupdict().items() if value}, - end=match.end()) + return self._convert_match(match) return None + def _convert_match(self, match: Match) -> MatcherReturn: + return MatcherReturn(params=self._convert_groups(match.groupdict()), + end=match.end()) + + def _convert_groups(self, groups: Dict[str, str]) -> 'RelativeDeltaParams': + return {key: self.value_type(value) for key, value in groups.items() if value} + + +class TimeMatcher(RegexMatcher): + def _convert_match(self, match: Match) -> MatcherReturn: + groups = match.groupdict() + try: + meridiem = groups.pop("meridiem").lower() + except KeyError: + meridiem = None + params = self._convert_groups(groups) + if meridiem == "pm": + params["hour"] += 12 + elif meridiem == "am" and params["hour"] == 12: + params["hour"] = 0 + return MatcherReturn(params=params, end=match.end()) + class WeekdayMatcher(Matcher): regex: Pattern diff --git a/reminder/locales.py b/reminder/locales.py index 989abda08efc89e49c038783c1394a885ec4ff14..1e2cac4f34138c5881e7d374cf776f148b5804fe 100644 --- a/reminder/locales.py +++ b/reminder/locales.py @@ -15,7 +15,7 @@ # along with this program. If not, see <https://www.gnu.org/licenses/>. from dateutil.relativedelta import MO, TU, WE, TH, FR, SA, SU -from .locale_util import Locales, Locale, RegexMatcher, WeekdayMatcher +from .locale_util import Locales, Locale, RegexMatcher, WeekdayMatcher, TimeMatcher locales: Locales = {} @@ -47,15 +47,21 @@ locales["en_iso"] = Locale( time=RegexMatcher(r"\s?(?:at\s)?" r"(?P<hour>\d{2})" r"[:.](?P<minute>\d{2})" - r"(?:[:.](?P<second>\d{2}))?") + r"(?:[:.](?P<second>\d{2}))?"), ) +time_12_en = TimeMatcher(r"\s?(?:at\s)?" + r"(?P<hour>\d{2})" + r"(?:[:.](?P<minute>\d{2}))?" + r"(?:[:.](?P<second>\d{2}))?" + r"(?:\s(?P<meridiem>a\.?m|p\.?m)\.?)?") + locales["en_us"] = locales["en_iso"].replace( - name="English (US)", + name="English (US)", time=time_12_en, date=RegexMatcher(r"(?P<month>\d{1,2})/(?P<day>\d{1,2})(?:/(?P<year>\d{4}))?")) locales["en_uk"] = locales["en_iso"].replace( - name="English (UK)", + name="English (UK)", time=time_12_en, date=RegexMatcher(r"(?P<day>\d{1,2})/(?P<month>\d{1,2})(?:/(?P<year>\d{4}))?")) td_sep_fi = r"(?:[\s,]{1,3}(?:ja\s)?)"