from dateutil.relativedelta import FR, MO, SA, SU, TH, TU, WE
import maha.parsers.rules.numeral.values as numvalues
from maha.constants import ARABIC_COMMA, COMMA, LAM, WAW, arabic, english
from maha.expressions import EXPRESSION_SPACE, EXPRESSION_SPACE_OR_NONE
from maha.parsers.rules.duration.values import (
ONE_DAY,
ONE_HOUR,
ONE_MINUTE,
ONE_MONTH,
ONE_WEEK,
ONE_YEAR,
SEVERAL_DAYS,
SEVERAL_HOURS,
SEVERAL_MINUTES,
SEVERAL_MONTHS,
SEVERAL_WEEKS,
SEVERAL_YEARS,
TWO_DAYS,
TWO_HOURS,
TWO_MINUTES,
TWO_MONTHS,
TWO_WEEKS,
TWO_YEARS,
)
from maha.parsers.rules.numeral.rule import (
RULE_NUMERAL_INTEGERS,
RULE_NUMERAL_ONES,
RULE_NUMERAL_TENS,
RULE_NUMERAL_THOUSANDS,
TEN,
eleven_to_nineteen,
)
from maha.parsers.rules.ordinal.rule import (
RULE_ORDINAL_ONES,
RULE_ORDINAL_TENS,
RULE_ORDINAL_THOUSANDS,
)
from maha.parsers.rules.ordinal.values import ALEF_LAM, ONE_PREFIX
from maha.parsers.templates import FunctionValue, Value
from maha.parsers.templates.value_expressions import MatchedValue
from maha.rexy import (
Expression,
ExpressionGroup,
named_group,
non_capturing_group,
optional_non_capturing_group,
)
from ..common import (
AFTER,
AFTER_NEXT,
ALL_ALEF,
BEFORE,
BEFORE_PREVIOUS,
ELLA,
FRACTIONS,
IN_FROM_AT,
NEXT,
PREVIOUS,
get_fractions_of_pattern,
spaced_patterns,
)
from .template import TimeValue
[docs]def value_group(value):
return named_group("value", value)
[docs]def parse_value(value: dict) -> TimeValue:
return TimeValue(**value)
[docs]lam_lam_group = named_group("to_time", LAM + LAM)
[docs]ALEF_LAM_OR_DOUBLE_LAM = non_capturing_group(ALEF_LAM, lam_lam_group)
[docs]ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL = optional_non_capturing_group(ALEF_LAM_OR_DOUBLE_LAM)
[docs]START_OF = Value(1, "بداي[ةه]")
[docs]AFTER = optional_non_capturing_group("[إا]لل?ي" + EXPRESSION_SPACE) + "بعد"
[docs]BEFORE = optional_non_capturing_group("[إا]لل?ي" + EXPRESSION_SPACE) + "[أاق]بل"
[docs]PREVIOUS = (
non_capturing_group("الماضي?", "السابق", "المنصرم", "الفا[يئ]ت")
+ numvalues.TEH_OPTIONAL_SUFFIX
)
[docs]NEXT = (
non_capturing_group("الجاي", "القادم", "التالي?", "ال[اآ]تي?", "المقبل")
+ numvalues.TEH_OPTIONAL_SUFFIX
)
[docs]AFTER_NEXT = spaced_patterns(AFTER, NEXT)
[docs]BEFORE_PREVIOUS = spaced_patterns(BEFORE, PREVIOUS)
[docs]IN_FROM_AT = non_capturing_group(
"في", "من", "خلال", "الموافق", "عند", "قراب[ةه]", "على"
)
[docs]FROM = Expression(non_capturing_group("من"))
[docs]TO = Expression(
optional_non_capturing_group(WAW)
+ EXPRESSION_SPACE_OR_NONE
+ non_capturing_group(
"[اإ]لى",
"حتى",
"لل?",
)
)
[docs]THIS = optional_non_capturing_group(
IN_FROM_AT + EXPRESSION_SPACE
) + non_capturing_group("ها?ذ[ياه]", "ه[اذ]ي", "هاد")
[docs]CURRENT = ALEF_LAM + non_capturing_group("حالي?", "حالي[ةه]?")
[docs]LAST = non_capturing_group("[آأا]خر", "ال[أا]خير")
[docs]HIJRIAH = Expression("هجري[ةه]?")
[docs]HIJRIATAN = Expression("هجريت?[اي]ن")
[docs]TIME_WORD_SEPARATOR = Expression(
non_capturing_group(
f"{EXPRESSION_SPACE_OR_NONE}{non_capturing_group(COMMA, ARABIC_COMMA)}",
EXPRESSION_SPACE + "ب?و?ع?",
EXPRESSION_SPACE + IN_FROM_AT + EXPRESSION_SPACE,
)
+ non_capturing_group(r"\b", EXPRESSION_SPACE_OR_NONE)
)
[docs]ordinal_ones_tens = ExpressionGroup(
RULE_ORDINAL_TENS, RULE_ORDINAL_ONES, ONE_PREFIX, START_OF
)
[docs]numeral_ones_tens = ExpressionGroup(
RULE_NUMERAL_TENS, RULE_NUMERAL_ONES, RULE_NUMERAL_INTEGERS
)
[docs]numeral_hours = ExpressionGroup(
eleven_to_nineteen,
TEN,
RULE_NUMERAL_ONES,
RULE_NUMERAL_INTEGERS,
)
# region NOW
[docs]AT_THE_MOMENT = Value(
TimeValue(years=0, months=0, days=0, hours=0, minutes=0, seconds=0),
non_capturing_group(
"ال[أآا]ن",
spaced_patterns(THIS, non_capturing_group("الوقت", "اللح[زضظ][ةه]")),
"هس[اةه]",
"في الحال",
"حالا",
spaced_patterns(non_capturing_group("الوقت", "اللح[زضظ][ةه]"), CURRENT),
),
)
# endregion
# region YEARS
# ----------------------------------------------------
# YEARS
# ----------------------------------------------------
[docs]numeral_thousands = ExpressionGroup(
RULE_NUMERAL_THOUSANDS,
FunctionValue(lambda match: int(match.group()), r"\d{4}"),
)
[docs]ordinal_thousands = ExpressionGroup(RULE_ORDINAL_THOUSANDS)
[docs]alhijri_group = named_group("hijri", ALEF_LAM + HIJRIAH)
[docs]alhijri_optional_group = optional_non_capturing_group(alhijri_group + EXPRESSION_SPACE)
[docs]hijri_group = named_group("hijri", HIJRIAH)
[docs]hijriatan_group = named_group("hijri", HIJRIATAN)
[docs]NUMERAL_YEAR = FunctionValue(
lambda match: parse_value(
{
"year": list(numeral_thousands.parse(match.group("value")))[0].value,
"hijri": True if match.group("hijri") else None,
}
),
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_YEAR,
value_group(numeral_thousands.join())
+ optional_non_capturing_group(
EXPRESSION_SPACE
+ non_capturing_group(hijriatan_group, hijri_group, alhijri_group)
),
),
)
[docs]ORDINAL_YEAR = FunctionValue(
lambda match: parse_value(
{
"year": list(ordinal_thousands.parse(match.group("value")))[0].value,
"hijri": True if match.group("hijri") else None,
}
),
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_YEAR,
value_group(ordinal_thousands.join())
+ optional_non_capturing_group(
EXPRESSION_SPACE
+ non_capturing_group(hijriatan_group, hijri_group, alhijri_group)
),
),
)
[docs]def years_with_hijri(match, years):
return TimeValue(years=years, hijri=True if match.group("hijri") else None)
[docs]THIS_YEAR = FunctionValue(
lambda match: years_with_hijri(match, 0),
optional_non_capturing_group(THIS + EXPRESSION_SPACE)
+ ALEF_LAM_OR_DOUBLE_LAM
+ ONE_YEAR
+ alhijri_optional_group
+ optional_non_capturing_group(EXPRESSION_SPACE + CURRENT),
)
[docs]LAST_YEAR = FunctionValue(
lambda match: years_with_hijri(match, -1),
non_capturing_group(
spaced_patterns(
BEFORE,
ONE_YEAR + optional_non_capturing_group(EXPRESSION_SPACE + hijri_group),
),
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM + ONE_YEAR,
alhijri_optional_group + PREVIOUS,
),
),
)
[docs]LAST_TWO_YEARS = FunctionValue(
lambda match: years_with_hijri(match, -2),
non_capturing_group(
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM + ONE_YEAR,
alhijri_optional_group + BEFORE_PREVIOUS,
),
spaced_patterns(
BEFORE,
TWO_YEARS
+ optional_non_capturing_group(EXPRESSION_SPACE + hijriatan_group),
),
),
)
[docs]NEXT_YEAR = FunctionValue(
lambda match: years_with_hijri(match, 1),
non_capturing_group(
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM + ONE_YEAR,
alhijri_optional_group + NEXT,
),
spaced_patterns(
AFTER,
ONE_YEAR + optional_non_capturing_group(EXPRESSION_SPACE + hijri_group),
),
),
)
[docs]NEXT_TWO_YEARS = FunctionValue(
lambda match: years_with_hijri(match, 2),
non_capturing_group(
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM + ONE_YEAR,
alhijri_optional_group + AFTER_NEXT,
),
spaced_patterns(
AFTER,
TWO_YEARS
+ optional_non_capturing_group(EXPRESSION_SPACE + hijriatan_group),
),
),
)
[docs]AFTER_N_YEARS = FunctionValue(
lambda match: parse_value(
{
"years": list(numeral_ones_tens.parse(match.group("value")))[0].value,
"hijri": True if match.group("hijri") else None,
}
),
spaced_patterns(
AFTER,
value_group(numeral_ones_tens.join()),
non_capturing_group(ONE_YEAR, SEVERAL_YEARS),
)
+ optional_non_capturing_group(EXPRESSION_SPACE + hijri_group),
)
[docs]BEFORE_N_YEARS = FunctionValue(
lambda match: parse_value(
{
"years": -1 * list(numeral_ones_tens.parse(match.group("value")))[0].value,
"hijri": True if match.group("hijri") else None,
}
),
spaced_patterns(
BEFORE,
value_group(numeral_ones_tens.join()),
non_capturing_group(ONE_YEAR, SEVERAL_YEARS)
+ optional_non_capturing_group(EXPRESSION_SPACE + hijri_group),
),
)
# endregion
# region MONTHS
# -----------------------------------------------------------
# MONTHS
# -----------------------------------------------------------
[docs]JANUARY = Value(
TimeValue(month=1),
non_capturing_group(
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "يناير",
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "كانون الثاني",
spaced_patterns(
ONE_MONTH,
non_capturing_group(numvalues.ONE, arabic.ARABIC_ONE, english.ONE),
),
),
)
[docs]FEBRUARY = Value(
TimeValue(month=2),
non_capturing_group(
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "فبراير",
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "شباط",
spaced_patterns(
ONE_MONTH,
non_capturing_group(numvalues.TWO, arabic.ARABIC_TWO, english.TWO),
),
),
)
[docs]MARCH = Value(
TimeValue(month=3),
non_capturing_group(
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "مارس",
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "[اأآ]ذار",
spaced_patterns(
ONE_MONTH,
non_capturing_group(numvalues.THREE, arabic.ARABIC_THREE, english.THREE),
),
),
)
[docs]APRIL = Value(
TimeValue(month=4),
non_capturing_group(
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "نيسان",
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + f"{ALL_ALEF}بريل",
spaced_patterns(
ONE_MONTH,
non_capturing_group(numvalues.FOUR, arabic.ARABIC_FOUR, english.FOUR),
),
),
)
[docs]MAY = Value(
TimeValue(month=5),
non_capturing_group(
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "مايو",
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "[أا]يار",
spaced_patterns(
ONE_MONTH,
non_capturing_group(numvalues.FIVE, arabic.ARABIC_FIVE, english.FIVE),
),
),
)
[docs]JUNE = Value(
TimeValue(month=6),
non_capturing_group(
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "يونيو",
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "حزيران",
spaced_patterns(
ONE_MONTH,
non_capturing_group(numvalues.SIX, arabic.ARABIC_SIX, english.SIX),
),
),
)
[docs]JULY = Value(
TimeValue(month=7),
non_capturing_group(
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "يوليو",
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "تموز",
spaced_patterns(
ONE_MONTH,
non_capturing_group(numvalues.SEVEN, arabic.ARABIC_SEVEN, english.SEVEN),
),
),
)
[docs]AUGUST = Value(
TimeValue(month=8),
non_capturing_group(
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "[اأآ]غسطس",
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "[أاآ]ب",
spaced_patterns(
ONE_MONTH,
non_capturing_group(numvalues.EIGHT, arabic.ARABIC_EIGHT, english.EIGHT),
),
),
)
[docs]SEPTEMBER = Value(
TimeValue(month=9),
non_capturing_group(
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "سبتمبر",
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "[اأ]يلول",
spaced_patterns(
ONE_MONTH,
non_capturing_group(numvalues.NINE, arabic.ARABIC_NINE, english.NINE),
),
),
)
[docs]OCTOBER = Value(
TimeValue(month=10),
non_capturing_group(
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "[اأ]كتوبر",
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "تشرين ال[اأ]ول",
spaced_patterns(
ONE_MONTH,
non_capturing_group(
numvalues.TEN,
arabic.ARABIC_ONE + arabic.ARABIC_ZERO,
english.ONE + english.ZERO,
),
),
),
)
[docs]NOVEMBER = Value(
TimeValue(month=11),
non_capturing_group(
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "نوفمبر",
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "تشرين ال[تث]اني",
spaced_patterns(
ONE_MONTH,
non_capturing_group(
numvalues.ELEVEN,
arabic.ARABIC_ONE + arabic.ARABIC_ONE,
english.ONE + english.ONE,
),
),
),
)
[docs]DECEMBER = Value(
TimeValue(month=12),
non_capturing_group(
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "ديسمبر",
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "كانون ال[اأ]ول",
spaced_patterns(
ONE_MONTH,
non_capturing_group(
numvalues.TWELVE,
arabic.ARABIC_ONE + arabic.ARABIC_TWO,
english.ONE + english.TWO,
),
),
),
)
# -----------------------------------------------------------
# HIJRI MONTHS
# -----------------------------------------------------------
[docs]MUHARRAM = Value(
TimeValue(month=1, hijri=True),
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "محرم",
)
[docs]SAFAR = Value(
TimeValue(month=2, hijri=True),
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "صفر",
)
[docs]RABI_AL_AWWAL = Value(
TimeValue(month=3, hijri=True),
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "ربيع ال[اآأ]ول",
)
[docs]RABI_AL_ATHANI = Value(
TimeValue(month=4, hijri=True),
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE)
+ "ربيع "
+ non_capturing_group("ال[اآأ]خر", "الثاني")
+ "[ةه]?",
)
[docs]JUMADA_AL_AWWAL = Value(
TimeValue(month=5, hijri=True),
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE)
+ "جماد[ىي] ال[اآأ]ول[ىي]?",
)
[docs]JUMADA_AL_ATHANI = Value(
TimeValue(month=6, hijri=True),
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE)
+ "جماد[ىي] "
+ non_capturing_group("ال[اآأ]خر", "الثاني")
+ "[ةه]?",
)
[docs]RAJAB = Value(
TimeValue(month=7, hijri=True),
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "رجب",
)
[docs]SHABAN = Value(
TimeValue(month=8, hijri=True),
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "شعبان",
)
[docs]RAMADAN = Value(
TimeValue(month=9, hijri=True),
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "رمضان",
)
[docs]SHAWWAL = Value(
TimeValue(month=10, hijri=True),
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "شوال",
)
[docs]DHU_AL_QIDAH = Value(
TimeValue(month=11, hijri=True),
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "ذو القعد[ةه]",
)
[docs]DHU_AL_HIJJAH = Value(
TimeValue(month=12, hijri=True),
optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE) + "ذو الحج[ةه]",
)
_months = ExpressionGroup(
OCTOBER,
NOVEMBER,
DECEMBER,
JANUARY,
FEBRUARY,
MARCH,
APRIL,
MAY,
JUNE,
JULY,
AUGUST,
SEPTEMBER,
MUHARRAM,
SAFAR,
RABI_AL_AWWAL,
RABI_AL_ATHANI,
JUMADA_AL_AWWAL,
JUMADA_AL_ATHANI,
RAJAB,
SHABAN,
RAMADAN,
SHAWWAL,
DHU_AL_QIDAH,
DHU_AL_HIJJAH,
)
[docs]THIS_MONTH = Value(
TimeValue(months=0),
optional_non_capturing_group(THIS + EXPRESSION_SPACE)
+ ALEF_LAM_OR_DOUBLE_LAM
+ ONE_MONTH
+ optional_non_capturing_group(EXPRESSION_SPACE + CURRENT),
)
[docs]LAST_MONTH = Value(
TimeValue(months=-1),
non_capturing_group(
spaced_patterns(BEFORE, ONE_MONTH),
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_MONTH, PREVIOUS),
),
)
[docs]LAST_TWO_MONTHS = Value(
TimeValue(months=-2),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_MONTH, BEFORE_PREVIOUS),
spaced_patterns(BEFORE, TWO_MONTHS),
),
)
[docs]NEXT_MONTH = Value(
TimeValue(months=1),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_MONTH, NEXT),
spaced_patterns(AFTER, ONE_MONTH),
),
)
[docs]NEXT_TWO_MONTHS = Value(
TimeValue(months=2),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_MONTH, AFTER_NEXT),
spaced_patterns(AFTER, TWO_MONTHS),
),
)
[docs]AFTER_N_MONTHS = FunctionValue(
lambda match: parse_value(
{"months": list(numeral_ones_tens.parse(match.group("value")))[0].value}
),
spaced_patterns(
AFTER,
value_group(numeral_ones_tens.join()),
non_capturing_group(ONE_MONTH, SEVERAL_MONTHS),
),
)
[docs]BEFORE_N_MONTHS = FunctionValue(
lambda match: parse_value(
{"months": -1 * list(numeral_ones_tens.parse(match.group("value")))[0].value}
),
spaced_patterns(
BEFORE,
value_group(numeral_ones_tens.join()),
non_capturing_group(ONE_MONTH, SEVERAL_MONTHS),
),
)
[docs]def get_matched_month(text):
return _months.get_matched_expression(text).value # type: ignore
[docs]SPECIFIC_MONTH = MatchedValue(_months, _months.join())
[docs]NEXT_SPECIFIC_MONTH = FunctionValue(
lambda match: parse_value(
{
"next_month": get_matched_month(match.group("value")).month,
"hijri": get_matched_month(match.group("value")).hijri,
}
),
non_capturing_group(
spaced_patterns(ONE_MONTH, value_group(_months.join()), NEXT),
spaced_patterns(value_group(_months.join()), NEXT),
),
)
[docs]PREVIOUS_SPECIFIC_MONTH = FunctionValue(
lambda match: parse_value(
{
"prev_month": get_matched_month(match.group("value")).month,
"hijri": get_matched_month(match.group("value")).hijri,
}
),
non_capturing_group(
spaced_patterns(ONE_MONTH, value_group(_months.join()), PREVIOUS),
spaced_patterns(value_group(_months.join()), PREVIOUS),
),
)
[docs]AFTER_SPECIFIC_NEXT_MONTH = FunctionValue(
lambda match: parse_value(
{
"next_month": get_matched_month(match.group("value")).month,
"hijri": get_matched_month(match.group("value")).hijri,
"years": 1,
}
),
non_capturing_group(
spaced_patterns(ONE_MONTH, value_group(_months.join()), AFTER_NEXT),
spaced_patterns(value_group(_months.join()), AFTER_NEXT),
),
)
[docs]BEFORE_SPECIFIC_PREVIOUS_MONTH = FunctionValue(
lambda match: parse_value(
{
"prev_month": get_matched_month(match.group("value")).month,
"hijri": get_matched_month(match.group("value")).hijri,
"years": -1,
}
),
non_capturing_group(
spaced_patterns(ONE_MONTH, value_group(_months.join()), BEFORE_PREVIOUS),
spaced_patterns(value_group(_months.join()), BEFORE_PREVIOUS),
),
)
# endregion
# region WEEKS
# ----------------------------------------------------
# WEEKS
# ----------------------------------------------------
[docs]THIS_WEEK = Value(
TimeValue(weeks=0),
optional_non_capturing_group(THIS + EXPRESSION_SPACE)
+ ALEF_LAM_OR_DOUBLE_LAM
+ ONE_WEEK
+ optional_non_capturing_group(EXPRESSION_SPACE + CURRENT),
)
[docs]LAST_WEEK = Value(
TimeValue(weeks=-1),
non_capturing_group(
spaced_patterns(BEFORE, ONE_WEEK),
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_WEEK, PREVIOUS),
),
)
[docs]LAST_TWO_WEEKS = Value(
TimeValue(weeks=-2),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_WEEK, BEFORE_PREVIOUS),
spaced_patterns(BEFORE, TWO_WEEKS),
),
)
[docs]NEXT_WEEK = Value(
TimeValue(weeks=1),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_WEEK, NEXT),
spaced_patterns(AFTER, ONE_WEEK),
),
)
[docs]NEXT_TWO_WEEKS = Value(
TimeValue(weeks=2),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_WEEK, AFTER_NEXT),
spaced_patterns(AFTER, TWO_WEEKS),
),
)
[docs]AFTER_N_WEEKS = FunctionValue(
lambda match: parse_value(
{"weeks": list(numeral_ones_tens.parse(match.group("value")))[0].value}
),
spaced_patterns(
AFTER,
value_group(numeral_ones_tens.join()),
non_capturing_group(ONE_WEEK, SEVERAL_WEEKS),
),
)
[docs]BEFORE_N_WEEKS = FunctionValue(
lambda match: parse_value(
{"weeks": -1 * list(numeral_ones_tens.parse(match.group("value")))[0].value}
),
spaced_patterns(
BEFORE,
value_group(numeral_ones_tens.join()),
non_capturing_group(ONE_WEEK, SEVERAL_WEEKS),
),
)
# endregion
# region DAYS
# ----------------------------------------------------
# DAYS
# ----------------------------------------------------
[docs]SUNDAY = Value(SU, ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + "[أا]حد")
[docs]MONDAY = Value(MO, ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + "[إا][تث]نين")
[docs]TUESDAY = Value(TU, ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + "[ثت]لا[ثت]اء?")
[docs]WEDNESDAY = Value(WE, ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + "[أا]ربعاء?")
[docs]THURSDAY = Value(TH, ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + "خميس")
[docs]FRIDAY = Value(FR, ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + "جمع[ةه]")
[docs]SATURDAY = Value(SA, ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + "سبت")
_days = ExpressionGroup(SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY)
[docs]WEEKDAY = FunctionValue(
lambda match: TimeValue(
weekday=_days.get_matched_expression(match.group("value")).value # type: ignore
),
optional_non_capturing_group(ONE_DAY + EXPRESSION_SPACE)
+ non_capturing_group(
ALEF_LAM_OR_DOUBLE_LAM + value_group(_days[:2].join()),
value_group(_days[2:].join()),
),
)
[docs]THIS_DAY = Value(
TimeValue(days=0),
optional_non_capturing_group(THIS + EXPRESSION_SPACE)
+ ALEF_LAM_OR_DOUBLE_LAM
+ ONE_DAY
+ optional_non_capturing_group(EXPRESSION_SPACE + CURRENT),
)
[docs]YESTERDAY = Value(
TimeValue(days=-1),
non_capturing_group(
"[اإ]?مبارح",
ALEF_LAM_OR_DOUBLE_LAM + "بارح[ةه]",
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + "[أا]مس",
spaced_patterns(BEFORE, ONE_DAY),
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_DAY, PREVIOUS),
),
)
[docs]BEFORE_YESTERDAY = Value(
TimeValue(days=-2),
non_capturing_group(
spaced_patterns(non_capturing_group("[أا]ول", str(BEFORE)), YESTERDAY),
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_DAY, BEFORE_PREVIOUS),
spaced_patterns(BEFORE, TWO_DAYS),
),
)
[docs]TOMORROW = Value(
TimeValue(days=1),
non_capturing_group(
optional_non_capturing_group(ONE_DAY + EXPRESSION_SPACE)
+ ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL
+ "غدا?",
"بكر[ةه]",
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_DAY, NEXT),
spaced_patterns(AFTER, ONE_DAY),
),
)
[docs]AFTER_TOMORROW = Value(
TimeValue(days=2),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_DAY, AFTER_NEXT),
spaced_patterns(AFTER, TOMORROW),
spaced_patterns(AFTER, TWO_DAYS),
),
)
[docs]AFTER_N_DAYS = FunctionValue(
lambda match: parse_value(
{"days": list(numeral_ones_tens.parse(match.group("value")))[0].value}
),
spaced_patterns(
AFTER,
value_group(numeral_ones_tens.join()),
non_capturing_group(ONE_DAY, SEVERAL_DAYS),
),
)
[docs]BEFORE_N_DAYS = FunctionValue(
lambda match: parse_value(
{"days": -1 * list(numeral_ones_tens.parse(match.group("value")))[0].value}
),
spaced_patterns(
BEFORE,
value_group(numeral_ones_tens.join()),
non_capturing_group(ONE_DAY, SEVERAL_DAYS),
),
)
[docs]NEXT_WEEKDAY = FunctionValue(
lambda match: parse_value(
{
"days": 1,
"weekday": _days.get_matched_expression(match.group("value")).value(1), # type: ignore
}
),
non_capturing_group(
spaced_patterns(ONE_DAY, value_group(_days.join()), NEXT),
spaced_patterns(value_group(_days.join()), NEXT),
),
)
[docs]PREVIOUS_WEEKDAY = FunctionValue(
lambda match: parse_value(
{
"days": -1,
"weekday": _days.get_matched_expression(match.group("value")).value(-1), # type: ignore
}
),
non_capturing_group(
spaced_patterns(ONE_DAY, value_group(_days.join()), PREVIOUS),
spaced_patterns(value_group(_days.join()), PREVIOUS),
),
)
[docs]AFTER_NEXT_WEEKDAY = FunctionValue(
lambda match: parse_value(
{
"days": 1,
"weekday": _days.get_matched_expression(match.group("value")).value(2), # type: ignore
}
),
non_capturing_group(
spaced_patterns(ONE_DAY, value_group(_days.join()), AFTER_NEXT),
spaced_patterns(value_group(_days.join()), AFTER_NEXT),
),
)
[docs]BEFORE_PREVIOUS_WEEKDAY = FunctionValue(
lambda match: parse_value(
{
"days": -1,
"weekday": _days.get_matched_expression(match.group("value")).value(-2), # type: ignore
}
),
non_capturing_group(
spaced_patterns(ONE_DAY, value_group(_days.join()), BEFORE_PREVIOUS),
spaced_patterns(value_group(_days.join()), BEFORE_PREVIOUS),
),
)
[docs]LAST_DAY = Value(
parse_value({"day": 31}),
non_capturing_group(
spaced_patterns(LAST, ONE_DAY),
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_DAY, LAST),
),
)
[docs]LAST_SPECIFIC_DAY = FunctionValue(
lambda match: parse_value(
{
"day": 31,
"weekday": _days.get_matched_expression(match.group("day")).value(-1), # type: ignore
}
),
non_capturing_group(
LAST
+ EXPRESSION_SPACE
+ optional_non_capturing_group(ONE_DAY + EXPRESSION_SPACE)
+ named_group("day", _days.join()),
optional_non_capturing_group(ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_DAY)
+ EXPRESSION_SPACE
+ named_group("day", _days.join())
+ LAST,
),
)
[docs]ORDINAL_SPECIFIC_DAY = FunctionValue(
lambda match: parse_value(
{
"day": 1,
"weekday": _days.get_matched_expression(match.group("day")).value( # type: ignore
list(ordinal_ones_tens.parse(match.group("ordinal")))[0].value
),
}
),
non_capturing_group(
spaced_patterns(
named_group("ordinal", ordinal_ones_tens.join()),
optional_non_capturing_group(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_DAY + EXPRESSION_SPACE
)
+ named_group("day", _days.join()),
),
spaced_patterns(
optional_non_capturing_group(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_DAY + EXPRESSION_SPACE
)
+ named_group("day", _days.join()),
named_group("ordinal", ordinal_ones_tens.join()),
),
),
)
# endregion
# region LAST DAY OF MONTH
# ----------------------------------------------------
# LAST DAY OF MONTH
# ----------------------------------------------------
_optional_month_start = optional_non_capturing_group(
EXPRESSION_SPACE + ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_MONTH
)
_start_of_last_day = (
non_capturing_group(
LAST
+ EXPRESSION_SPACE
+ optional_non_capturing_group(ONE_DAY + EXPRESSION_SPACE)
+ named_group("day", _days.join())
+ EXPRESSION_SPACE
+ IN_FROM_AT,
optional_non_capturing_group(ONE_DAY + EXPRESSION_SPACE)
+ named_group("day", _days.join())
+ EXPRESSION_SPACE
+ LAST
+ EXPRESSION_SPACE
+ IN_FROM_AT,
)
+ _optional_month_start
)
[docs]LAST_SPECIFIC_DAY_OF_SPECIFIC_MONTH = FunctionValue(
lambda match: parse_value(
{
"weekday": _days.get_matched_expression(match.group("day")).value(-1), # type: ignore
"day": 31,
}
)
+ get_matched_month(match.group("month")),
spaced_patterns(_start_of_last_day, named_group("month", _months.join())),
)
# endregion
# region HOURS
# -----------------------------------------------
# HOURS
# -----------------------------------------------
[docs]NUMERAL_HOUR = FunctionValue(
lambda match: parse_value(
{
"microsecond": 0,
"second": 0,
"minute": 0,
"hour": list(numeral_hours.parse(match.group("value")))[0].value,
}
),
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_HOUR,
value_group(numeral_hours.join()),
),
)
[docs]ORDINAL_HOUR = FunctionValue(
lambda match: parse_value(
{
"microsecond": 0,
"second": 0,
"minute": 0,
"hour": list(ordinal_ones_tens.parse(match.group("value")))[0].value,
}
),
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_HOUR,
value_group(ordinal_ones_tens.join()),
),
)
[docs]THIS_HOUR = Value(
TimeValue(hours=0),
optional_non_capturing_group(THIS + EXPRESSION_SPACE)
+ ALEF_LAM_OR_DOUBLE_LAM
+ ONE_HOUR
+ optional_non_capturing_group(EXPRESSION_SPACE + CURRENT),
)
[docs]LAST_HOUR = Value(
TimeValue(hours=-1),
non_capturing_group(
spaced_patterns(BEFORE, ONE_HOUR),
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_HOUR, PREVIOUS),
),
)
[docs]LAST_TWO_HOURS = Value(
TimeValue(hours=-2),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_HOUR, BEFORE_PREVIOUS),
spaced_patterns(BEFORE, TWO_HOURS),
),
)
[docs]NEXT_HOUR = Value(
TimeValue(hours=1),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_HOUR, NEXT),
spaced_patterns(AFTER, ONE_HOUR),
),
)
[docs]NEXT_TWO_HOURS = Value(
TimeValue(hours=2),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_HOUR, AFTER_NEXT),
spaced_patterns(AFTER, TWO_HOURS),
),
)
[docs]AFTER_N_HOURS = FunctionValue(
lambda match: parse_value(
{"hours": list(numeral_hours.parse(match.group("value")))[0].value}
),
spaced_patterns(
AFTER,
value_group(numeral_hours.join()),
non_capturing_group(ONE_HOUR, SEVERAL_HOURS),
),
)
[docs]BEFORE_N_HOURS = FunctionValue(
lambda match: parse_value(
{"hours": -1 * list(numeral_hours.parse(match.group("value")))[0].value}
),
spaced_patterns(
BEFORE,
value_group(numeral_hours.join()),
non_capturing_group(ONE_HOUR, SEVERAL_HOURS),
),
)
# endregion
# region MINUTES
# ----------------------------------------------------
# MINUTES
# ----------------------------------------------------
[docs]NUMERAL_MINUTE = FunctionValue(
lambda match: parse_value(
{
"microsecond": 0,
"second": 0,
"minute": list(numeral_ones_tens.parse(match.group("value")))[0].value,
}
),
non_capturing_group(
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_MINUTE,
value_group(numeral_ones_tens.join()),
),
spaced_patterns(
value_group(numeral_ones_tens.join()),
non_capturing_group(ONE_MINUTE, SEVERAL_MINUTES),
),
),
)
[docs]ORDINAL_MINUTE = FunctionValue(
lambda match: parse_value(
{
"microsecond": 0,
"second": 0,
"minute": list(ordinal_ones_tens.parse(match.group("value")))[0].value,
}
),
non_capturing_group(
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_MINUTE,
value_group(ordinal_ones_tens.join()),
),
spaced_patterns(
value_group(ordinal_ones_tens.join()),
non_capturing_group(ONE_MINUTE, SEVERAL_MINUTES),
),
),
)
[docs]THIS_MINUTE = Value(
TimeValue(minutes=0),
optional_non_capturing_group(THIS + EXPRESSION_SPACE)
+ ALEF_LAM_OR_DOUBLE_LAM
+ ONE_MINUTE
+ optional_non_capturing_group(EXPRESSION_SPACE + CURRENT),
)
[docs]LAST_MINUTE = Value(
TimeValue(minutes=-1),
non_capturing_group(
spaced_patterns(BEFORE, ONE_MINUTE),
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_MINUTE, PREVIOUS),
),
)
[docs]LAST_TWO_MINUTES = Value(
TimeValue(minutes=-2),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_MINUTE, BEFORE_PREVIOUS),
spaced_patterns(BEFORE, TWO_MINUTES),
),
)
[docs]NEXT_MINUTE = Value(
TimeValue(minutes=1),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_MINUTE, NEXT),
spaced_patterns(AFTER, ONE_MINUTE),
),
)
[docs]NEXT_TWO_MINUTES = Value(
TimeValue(minutes=2),
non_capturing_group(
spaced_patterns(ALEF_LAM_OR_DOUBLE_LAM + ONE_MINUTE, AFTER_NEXT),
spaced_patterns(AFTER, TWO_MINUTES),
),
)
[docs]AFTER_N_MINUTES = FunctionValue(
lambda match: parse_value(
{"minutes": list(numeral_ones_tens.parse(match.group("value")))[0].value}
),
spaced_patterns(
AFTER,
value_group(numeral_ones_tens.join()),
non_capturing_group(ONE_MINUTE, SEVERAL_MINUTES),
),
)
[docs]BEFORE_N_MINUTES = FunctionValue(
lambda match: parse_value(
{"minutes": -1 * list(numeral_ones_tens.parse(match.group("value")))[0].value}
),
spaced_patterns(
BEFORE,
value_group(numeral_ones_tens.join()),
non_capturing_group(ONE_MINUTE, SEVERAL_MINUTES),
),
)
# endregion
# region AM PM
# ----------------------------------------------------
# AM PM
# ----------------------------------------------------
[docs]PM = Value(
TimeValue(am_pm="PM"),
non_capturing_group(
optional_non_capturing_group(
AFTER + EXPRESSION_SPACE,
THIS + EXPRESSION_SPACE,
BEFORE + EXPRESSION_SPACE,
)
+ ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL
+ non_capturing_group(
"مساء?ا?",
"مغرب",
"عشاء?ا?",
"عصرا?",
"ليل[اةه]?",
),
spaced_patterns(AFTER, ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + "ظهرا?"),
),
)
[docs]AM = Value(
TimeValue(am_pm="AM"),
non_capturing_group(
optional_non_capturing_group(
BEFORE + EXPRESSION_SPACE, THIS + EXPRESSION_SPACE, AFTER + EXPRESSION_SPACE
)
+ ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL
+ non_capturing_group(
"صبا?حا?",
"فجرا?",
),
optional_non_capturing_group(BEFORE + EXPRESSION_SPACE, THIS + EXPRESSION_SPACE)
+ ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL
+ "ظهرا?",
),
)
# endregion
# region YEARS + MONTHS
# ----------------------------------------------------
# YEARS + MONTHS
# ----------------------------------------------------
[docs]YEAR_WITH_MONTH = FunctionValue(
lambda match: parse_value(
{"year": list(numeral_thousands.parse(match.group("value")))[0].value}
)
+ get_matched_month(match.group("month")),
spaced_patterns(
named_group("month", _months.join()), value_group(numeral_thousands.join())
),
)
# endregion
# region DAY + MONTH
# ----------------------------------------------------
# DAY WITH MONTH
# ----------------------------------------------------
_optional_middle = optional_non_capturing_group(
IN_FROM_AT + EXPRESSION_SPACE
) + optional_non_capturing_group(ONE_MONTH + EXPRESSION_SPACE)
_optional_start = (
optional_non_capturing_group(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_DAY + EXPRESSION_SPACE
)
+ optional_non_capturing_group(_days.join() + EXPRESSION_SPACE)
+ optional_non_capturing_group(IN_FROM_AT + EXPRESSION_SPACE)
)
[docs]months_expressions = ExpressionGroup(
AFTER_N_MONTHS,
BEFORE_N_MONTHS,
AFTER_SPECIFIC_NEXT_MONTH,
LAST_TWO_MONTHS,
NEXT_TWO_MONTHS,
LAST_MONTH,
NEXT_MONTH,
NEXT_SPECIFIC_MONTH,
PREVIOUS_SPECIFIC_MONTH,
BEFORE_SPECIFIC_PREVIOUS_MONTH,
THIS_MONTH,
SPECIFIC_MONTH,
)
[docs]ORDINAL_AND_MONTH = FunctionValue(
lambda match: parse_value(
{
"day": (list(ordinal_ones_tens.parse(match.group("ordinal")))[0].value),
}
)
+ list(months_expressions.parse(match.group("value")))[0].value,
non_capturing_group(
spaced_patterns(
_optional_start + named_group("ordinal", ordinal_ones_tens.join()),
_optional_middle + value_group(months_expressions.join()),
),
spaced_patterns(
named_group("ordinal", ordinal_ones_tens.join()),
ONE_DAY,
_optional_middle + value_group(months_expressions.join()),
),
spaced_patterns(
_optional_middle + value_group(_months.join()),
named_group("ordinal", ordinal_ones_tens.join()),
),
),
)
[docs]NUMERAL_AND_MONTH = FunctionValue(
lambda match: parse_value(
{
"day": (list(numeral_ones_tens.parse(match.group("numeral")))[0].value),
}
)
+ list(months_expressions.parse(match.group("value")))[0].value,
non_capturing_group(
spaced_patterns(
_optional_start + named_group("numeral", numeral_ones_tens.join()),
_optional_middle + value_group(months_expressions.join()),
),
spaced_patterns(
_optional_middle + value_group(months_expressions.join()),
named_group("numeral", numeral_ones_tens.join()),
),
),
)
# endregion
# region DAY + MONTH + YEAR
# ----------------------------------------------------
# DAY + MONTH + YEAR
# ----------------------------------------------------
# endregion
# region HOURS + MINUTES
# ----------------------------------------------------
# HOURS AND MINUTES
# ----------------------------------------------------
[docs]def parse_time_fraction(match, expression, am_pm=None):
ella = ELLA.search(match.group("value"))
splits = match.group("value").split(" ")
if ella:
hour_text, fraction_text = " ".join(splits[:-2]), " ".join(splits[-2:])
else:
hour_text, fraction_text = " ".join(splits[:-1]), splits[-1]
fraction = list(FRACTIONS.parse(fraction_text))[0].value
minute = int(60 * fraction)
hour = list(expression.parse(hour_text))[0].value
if ella:
hour = hour - 1 if hour > 0 else 23
time = {"microsecond": 0, "second": 0, "minute": minute, "hour": hour}
if am_pm:
time["am_pm"] = am_pm
return parse_value(time)
[docs]NUMERAL_FRACTION_HOUR_MINUTE = FunctionValue(
lambda match: parse_time_fraction(match, numeral_ones_tens),
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_HOUR,
value_group(get_fractions_of_pattern(numeral_ones_tens.join())),
),
)
[docs]ORDINAL_FRACTION_HOUR_MINUTE = FunctionValue(
lambda match: parse_time_fraction(match, ordinal_ones_tens),
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + ONE_HOUR,
value_group(get_fractions_of_pattern(ordinal_ones_tens.join())),
),
)
# endregion
# region HOUR + MINUTES + SECONDS
# ----------------------------------------------------
# HOUR + MINUTES + SECONDS
# ----------------------------------------------------
# endregion
# region HOUR + AM/PM
# ----------------------------------------------------
# HOUR + AM/PM
# ----------------------------------------------------
[docs]NUMERAL_HOUR_PM = FunctionValue(
lambda match: parse_value(
{
"microsecond": 0,
"second": 0,
"minute": 0,
"am_pm": "PM",
"hour": list(numeral_hours.parse(match.group("value")))[0].value,
}
),
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + value_group(numeral_hours.join()),
PM,
),
)
[docs]NUMERAL_HOUR_AM = FunctionValue(
lambda match: parse_value(
{
"microsecond": 0,
"second": 0,
"minute": 0,
"am_pm": "AM",
"hour": list(numeral_hours.parse(match.group("value")))[0].value,
}
),
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL + value_group(numeral_hours.join()),
AM,
),
)
[docs]NUMERAL_FRACTION_HOUR_AM = FunctionValue(
lambda match: parse_time_fraction(match, numeral_hours, "AM"),
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL
+ value_group(get_fractions_of_pattern(numeral_hours.join())),
AM,
),
)
[docs]NUMERAL_FRACTION_HOUR_PM = FunctionValue(
lambda match: parse_time_fraction(match, numeral_hours, "PM"),
spaced_patterns(
ALEF_LAM_OR_DOUBLE_LAM_OPTIONAL
+ value_group(get_fractions_of_pattern(numeral_hours.join())),
PM,
),
)
[docs]ORDINAL_HOUR_PM = FunctionValue(
lambda match: parse_value(
{
"microsecond": 0,
"second": 0,
"minute": 0,
"am_pm": "PM",
"hour": list(ordinal_ones_tens.parse(match.group("value")))[0].value,
}
),
spaced_patterns(value_group(ordinal_ones_tens.join()), PM),
)
[docs]ORDINAL_HOUR_AM = FunctionValue(
lambda match: parse_value(
{
"microsecond": 0,
"second": 0,
"minute": 0,
"am_pm": "AM",
"hour": list(ordinal_ones_tens.parse(match.group("value")))[0].value,
}
),
spaced_patterns(value_group(ordinal_ones_tens.join()), AM),
)
[docs]ORDINAL_FRACTION_HOUR_AM = FunctionValue(
lambda match: parse_time_fraction(match, ordinal_ones_tens, "AM"),
spaced_patterns(
value_group(get_fractions_of_pattern(ordinal_ones_tens.join())), AM
),
)
[docs]ORDINAL_FRACTION_HOUR_PM = FunctionValue(
lambda match: parse_time_fraction(match, ordinal_ones_tens, "PM"),
spaced_patterns(
value_group(get_fractions_of_pattern(ordinal_ones_tens.join())), PM
),
)
# endregion