From a92df402b4b3e796748cf25eeefea5e41617ee8b Mon Sep 17 00:00:00 2001 From: JarbasAI <33701864+JarbasAl@users.noreply.github.com> Date: Tue, 22 Jun 2021 14:43:32 -1000 Subject: [PATCH] timezone issues (#32) Co-authored-by: jarbasal --- lingua_nostra/lang/parse_fa.py | 7 +- lingua_nostra/lang/parse_fr.py | 3 +- lingua_nostra/time.py | 39 ++- setup.py | 2 +- test/test_format_ca.py | 40 ++- test/test_format_cs.py | 40 ++- test/test_format_da.py | 25 +- test/test_format_de.py | 25 +- test/test_format_en.py | 72 +++- test/test_format_es.py | 27 +- test/test_format_fr.py | 25 +- test/test_parse_en.py | 619 ++++++++++++++++++--------------- test/test_parse_fa.py | 28 +- 13 files changed, 544 insertions(+), 408 deletions(-) diff --git a/lingua_nostra/lang/parse_fa.py b/lingua_nostra/lang/parse_fa.py index cf2897aa..9a11091d 100644 --- a/lingua_nostra/lang/parse_fa.py +++ b/lingua_nostra/lang/parse_fa.py @@ -22,6 +22,7 @@ import json from lingua_nostra.internal import resolve_resource_file from lingua_nostra.parse import normalize_decimals +from lingua_nostra.time import now_local def _is_number(s): @@ -215,7 +216,7 @@ def extract_datetime_fa(text, anchorDate=None, default_time=None): .replace('بعد از ظهر', 'بعدازظهر') if not anchorDate: - anchorDate = datetime.now() + anchorDate = now_local() today = anchorDate.replace(hour=0, minute=0, second=0, microsecond=0) today_weekday = int(anchorDate.strftime("%w")) weekday_names = [ @@ -369,10 +370,10 @@ def extract_number_fa(text, short_scale=True, ordinals=False, decimal='.'): class FarsiNormalizer(Normalizer): # TODO - with open(resolve_resource_file("text/en-us/normalize.json")) as f: + with open(resolve_resource_file("text/fa-ir/normalize.json")) as f: _default_config = json.load(f) def normalize_fa(text, remove_articles=True): - """ English string normalization """ + """ Farsi string normalization """ return FarsiNormalizer().normalize(text, remove_articles) diff --git a/lingua_nostra/lang/parse_fr.py b/lingua_nostra/lang/parse_fr.py index 2ae0cf41..764552cd 100644 --- a/lingua_nostra/lang/parse_fr.py +++ b/lingua_nostra/lang/parse_fr.py @@ -960,8 +960,7 @@ def date_found(): if not hasYear: temp = datetime.strptime(datestr, "%B %d") if extractedDate.tzinfo: - temp = temp.replace(tzinfo=gettz("UTC")) - temp = temp.astimezone(extractedDate.tzinfo) + temp = temp.replace(tzinfo=extractedDate.tzinfo) temp = temp.replace(year=extractedDate.year) if extractedDate < temp: extractedDate = extractedDate.replace(year=int(currentYear), diff --git a/lingua_nostra/time.py b/lingua_nostra/time.py index a40a5f64..3b989dd5 100644 --- a/lingua_nostra/time.py +++ b/lingua_nostra/time.py @@ -46,7 +46,7 @@ def now_utc(): Returns: (datetime): The current time in Universal Time, aka GMT """ - return to_utc(datetime.utcnow()) + return datetime.now(gettz("UTC")) def now_local(tz=None): @@ -63,6 +63,18 @@ def now_local(tz=None): return datetime.now(tz) +def now_system(): + """ Retrieve the current time in system timezone + + Args: + tz (datetime.tzinfo, optional): Timezone, default to user's settings + + Returns: + (datetime): The current time + """ + return datetime.now(tzlocal()) + + def to_utc(dt): """ Convert a datetime with timezone info to a UTC datetime @@ -71,11 +83,16 @@ def to_utc(dt): Returns: (datetime): time converted to UTC """ - tzUTC = gettz("UTC") + tz = gettz("UTC") if dt.tzinfo: - return dt.astimezone(tzUTC) + return dt.astimezone(tz) else: - return dt.replace(tzinfo=gettz("UTC")).astimezone(tzUTC) + # naive datetimes assumed to be in default timezone already! + # in the case of datetime.now this corresponds to tzlocal() + # otherwise timezone is undefined and can not be guessed, we assume + # the user means "my timezone" and that LN was configured to use it + # beforehand, if unconfigured default == tzlocal() + return dt.replace(tzinfo=default_timezone()).astimezone(tz) def to_local(dt): @@ -90,7 +107,12 @@ def to_local(dt): if dt.tzinfo: return dt.astimezone(tz) else: - return dt.replace(tzinfo=gettz("UTC")).astimezone(tz) + # naive datetimes assumed to be in default timezone already! + # in the case of datetime.now this corresponds to tzlocal() + # otherwise timezone is undefined and can not be guessed, we assume + # the user means "my timezone" and that LN was configured to use it + # beforehand, if unconfigured default == tzlocal() + return dt.replace(tzinfo=tz) def to_system(dt): @@ -105,4 +127,9 @@ def to_system(dt): if dt.tzinfo: return dt.astimezone(tz) else: - return dt.replace(tzinfo=gettz("UTC")).astimezone(tz) + # naive datetimes assumed to be in default timezone already! + # in the case of datetime.now this corresponds to tzlocal() + # otherwise timezone is undefined and can not be guessed, we assume + # the user means "my timezone" and that LN was configured to use it + # beforehand, if unconfigured default == tzlocal() + return dt.replace(tzinfo=default_timezone()).astimezone(tz) diff --git a/setup.py b/setup.py index d36e799f..fa3ac6a1 100644 --- a/setup.py +++ b/setup.py @@ -27,7 +27,7 @@ def required(requirements_file): setup( name='lingua_nostra', - version='0.4.3', + version='0.4.4', packages=['lingua_nostra', 'lingua_nostra.lang'], url='https://github.com/HelloChatterbox/lingua-nostra', license='Apache2.0', diff --git a/test/test_format_ca.py b/test/test_format_ca.py index f3777dd0..4fc53123 100644 --- a/test/test_format_ca.py +++ b/test/test_format_ca.py @@ -21,6 +21,7 @@ from lingua_nostra.format import nice_time from lingua_nostra.format import pronounce_number from lingua_nostra.lang.format_ca import TimeVariantCA +from lingua_nostra.time import default_timezone def setUpModule(): @@ -134,7 +135,7 @@ def test_convert_decimals(self): class TestNiceDateFormat(unittest.TestCase): def test_pm(self): dt = datetime.datetime(2017, 1, 31, - 13, 22, 3) + 13, 22, 3, tzinfo=default_timezone()) # Verify defaults haven't changed self.assertEqual(nice_time(dt, lang="ca-es"), @@ -155,7 +156,7 @@ def test_pm(self): self.assertEqual(nice_time(dt, lang="ca", use_24hour=True, use_ampm=False), "les tretze i vint-i-dos") - dt = datetime.datetime(2017, 1, 31, 13, 0, 3) + dt = datetime.datetime(2017, 1, 31, 13, 0, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="ca"), "la una en punt") self.assertEqual(nice_time(dt, lang="ca", use_ampm=True), "la una en punt de la tarda") @@ -169,7 +170,8 @@ def test_pm(self): self.assertEqual(nice_time(dt, lang="ca", use_24hour=True, use_ampm=True), "les tretze") - dt = datetime.datetime(2017, 1, 31, 13, 2, 3) + dt = datetime.datetime(2017, 1, 31, 13, 2, 3, + tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="ca", use_24hour=True), "les tretze i dos") self.assertEqual(nice_time(dt, lang="ca", use_ampm=True), @@ -186,7 +188,8 @@ def test_pm(self): self.assertEqual(nice_time(dt, lang="ca", use_24hour=True, use_ampm=False), "les tretze i dos") - dt = datetime.datetime(2017, 1, 31, 12, 15, 0) + dt = datetime.datetime(2017, 1, 31, 12, 15, 0, + tzinfo=default_timezone()) # Default Watch system self.assertEqual(nice_time(dt, lang="ca", use_24hour=True, use_ampm=False), "les dotze i quinze") @@ -204,7 +207,8 @@ def test_pm(self): use_ampm=False, variant=TimeVariantCA.BELL), "un quart d'una de la tarda") - dt = datetime.datetime(2017, 1, 31, 00, 14, 0) + dt = datetime.datetime(2017, 1, 31, 00, 14, 0, + tzinfo=default_timezone()) # Default Watch system self.assertEqual(nice_time(dt, lang="ca", use_24hour=True, use_ampm=False), "les zero i catorze") @@ -225,7 +229,7 @@ def test_pm(self): def test_midnight(self): dt = datetime.datetime(2017, 1, 31, - 0, 2, 3) + 0, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="ca"), "les dotze i dos") self.assertEqual(nice_time(dt, lang="ca", use_ampm=True), @@ -248,7 +252,7 @@ def test_midnight(self): def test_midday(self): dt = datetime.datetime(2017, 1, 31, - 12, 15, 9) + 12, 15, 9, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="ca-es"), "les dotze i quinze") self.assertEqual(nice_time(dt, lang="ca-es", use_ampm=True), @@ -274,7 +278,7 @@ def test_midday(self): def test_minutes_to_hour(self): # "twenty minutes to midnight" dt = datetime.datetime(2017, 1, 31, - 19, 40, 49) + 19, 40, 49, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="ca-es"), "les set i quaranta") self.assertEqual(nice_time(dt, lang="ca-es", use_ampm=True), @@ -300,39 +304,39 @@ def test_minutes_to_hour(self): def test_minutes_past_hour(self): # "quarter past ten" dt = datetime.datetime(2017, 1, 31, - 1, 15, 00) + 1, 15, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="ca-es", use_24hour=True), "la una i quinze") self.assertEqual(nice_time(dt, lang="ca-es"), "la una i quinze") dt = datetime.datetime(2017, 1, 31, - 1, 35, 00) + 1, 35, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="ca-es"), "la una i trenta-cinc") dt = datetime.datetime(2017, 1, 31, - 1, 45, 00) + 1, 45, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="ca-es"), "la una i quaranta-cinc") dt = datetime.datetime(2017, 1, 31, - 4, 50, 00) + 4, 50, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="ca-es"), "les quatre i cinquanta") dt = datetime.datetime(2017, 1, 31, - 5, 55, 00) + 5, 55, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="ca-es"), "les cinc i cinquanta-cinc") dt = datetime.datetime(2017, 1, 31, - 5, 30, 00) + 5, 30, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="ca-es", use_ampm=True), "les cinc i trenta de la matinada") dt = datetime.datetime(2017, 1, 31, - 23, 15, 9) + 23, 15, 9, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="ca-es", use_24hour=True, use_ampm=True), "les vint-i-tres i quinze") @@ -341,7 +345,8 @@ def test_minutes_past_hour(self): "les onze i quinze de la nit") def test_variant_strings(self): - dt = datetime.datetime(2017, 1, 31, 12, 15, 0) + dt = datetime.datetime(2017, 1, 31, 12, 15, 0, + tzinfo=default_timezone()) # Default variant self.assertEqual(nice_time(dt, lang="ca", use_24hour=True, use_ampm=False, variant="default"), @@ -350,7 +355,8 @@ def test_variant_strings(self): use_ampm=False), "les dotze i quinze") - dt = datetime.datetime(2017, 1, 31, 00, 14, 0) + dt = datetime.datetime(2017, 1, 31, 00, 14, 0, + tzinfo=default_timezone()) # Spanish-like time system self.assertEqual(nice_time(dt, lang="ca", use_24hour=True, use_ampm=False, diff --git a/test/test_format_cs.py b/test/test_format_cs.py index 6996bb9f..fd37a56c 100644 --- a/test/test_format_cs.py +++ b/test/test_format_cs.py @@ -31,6 +31,7 @@ from lingua_nostra import get_default_lang, set_default_lang, \ load_language, unload_language +from lingua_nostra.time import default_timezone def setUpModule(): @@ -375,7 +376,7 @@ def setUpClass(cls): def test_convert_times(self): dt = datetime.datetime(2017, 1, 31, - 13, 22, 3) + 13, 22, 3, tzinfo=default_timezone()) # Verify defaults haven't changed self.assertEqual(nice_time(dt), @@ -400,7 +401,7 @@ def test_convert_times(self): "třináct dvacet dva") dt = datetime.datetime(2017, 1, 31, - 13, 0, 3) + 13, 0, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, use_24hour=False), "jedna hodin") self.assertEqual(nice_time(dt, use_24hour=False, use_ampm=True), @@ -420,7 +421,7 @@ def test_convert_times(self): "třináct sto") dt = datetime.datetime(2017, 1, 31, - 13, 2, 3) + 13, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, use_24hour=False), "jedna oh dva") self.assertEqual(nice_time(dt, use_24hour=False, use_ampm=True), @@ -440,7 +441,7 @@ def test_convert_times(self): "třináct nula dva") dt = datetime.datetime(2017, 1, 31, - 0, 2, 3) + 0, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, use_24hour=False), "dvanáct oh dva") self.assertEqual(nice_time(dt, use_24hour=False, use_ampm=True), @@ -460,7 +461,7 @@ def test_convert_times(self): "nula nula nula dva") dt = datetime.datetime(2018, 2, 8, - 1, 2, 33) + 1, 2, 33, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, use_24hour=False), "jedna oh dva") self.assertEqual(nice_time(dt, use_24hour=False, use_ampm=True), @@ -480,19 +481,19 @@ def test_convert_times(self): "nula jedna nula dva") dt = datetime.datetime(2017, 1, 31, - 12, 15, 9) + 12, 15, 9, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, use_24hour=False), "čtvrt po dvanáct") self.assertEqual(nice_time(dt, use_24hour=False, use_ampm=True), "čtvrt po dvanáct p.m.") dt = datetime.datetime(2017, 1, 31, - 5, 30, 00) + 5, 30, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, use_24hour=False, use_ampm=True), "půl po pět a.m.") dt = datetime.datetime(2017, 1, 31, - 1, 45, 00) + 1, 45, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, use_24hour=False), "třičtvrtě na dva") @@ -505,9 +506,11 @@ def test_nice_date(self): dp = ast.literal_eval(p['datetime_param']) np = ast.literal_eval(p['now']) dt = datetime.datetime( - dp[0], dp[1], dp[2], dp[3], dp[4], dp[5]) + dp[0], dp[1], dp[2], dp[3], dp[4], dp[5], + tzinfo=default_timezone()) now = None if not np else datetime.datetime( - np[0], np[1], np[2], np[3], np[4], np[5]) + np[0], np[1], np[2], np[3], np[4], np[5], + tzinfo=default_timezone()) print('Testing for ' + lang + ' that ' + str(dt) + ' is date ' + p['assertEqual']) self.assertEqual(p['assertEqual'], @@ -515,7 +518,7 @@ def test_nice_date(self): i = i + 1 # test fall back to english !!!Skiped - #dt = datetime.datetime(2018, 2, 4, 0, 2, 3) + #dt = datetime.datetime(2018, 2, 4, 0, 2, 3, tzinfo=default_timezone()) # self.assertEqual(nice_date( # dt, lang='invalid', now=datetime.datetime(2018, 2, 4, 0, 2, 3)), # 'today') @@ -523,7 +526,8 @@ def test_nice_date(self): # test all days in a year for all languages, # that some output is produced # for lang in self.test_config: - for dt in (datetime.datetime(2017, 12, 30, 0, 2, 3) + + for dt in (datetime.datetime(2017, 12, 30, 0, 2, 3, + tzinfo=default_timezone()) + datetime.timedelta(n) for n in range(368)): self.assertTrue(len(nice_date(dt, lang=lang)) > 0) @@ -536,9 +540,11 @@ def test_nice_date_time(self): dp = ast.literal_eval(p['datetime_param']) np = ast.literal_eval(p['now']) dt = datetime.datetime( - dp[0], dp[1], dp[2], dp[3], dp[4], dp[5]) + dp[0], dp[1], dp[2], dp[3], dp[4], dp[5], + tzinfo=default_timezone()) now = None if not np else datetime.datetime( - np[0], np[1], np[2], np[3], np[4], np[5]) + np[0], np[1], np[2], np[3], np[4], np[5], + tzinfo=default_timezone()) print('Testing for ' + lang + ' that ' + str(dt) + ' is date time ' + p['assertEqual']) self.assertEqual( @@ -557,7 +563,8 @@ def test_nice_year(self): p = self.test_config[lang]['test_nice_year'][str(i)] dp = ast.literal_eval(p['datetime_param']) dt = datetime.datetime( - dp[0], dp[1], dp[2], dp[3], dp[4], dp[5]) + dp[0], dp[1], dp[2], dp[3], dp[4], dp[5], + tzinfo=default_timezone()) print('Testing for ' + lang + ' that ' + str(dt) + ' is year ' + p['assertEqual']) self.assertEqual(p['assertEqual'], nice_year( @@ -568,7 +575,8 @@ def test_nice_year(self): # that some output is produced print("Test all years in " + lang) for i in range(1, 9999): - dt = datetime.datetime(i, 1, 31, 13, 2, 3) + dt = datetime.datetime(i, 1, 31, 13, 2, 3, + tzinfo=default_timezone()) self.assertTrue(len(nice_year(dt, lang=lang)) > 0) # Looking through the date sequence can be helpful diff --git a/test/test_format_da.py b/test/test_format_da.py index ddd4805b..2220f498 100644 --- a/test/test_format_da.py +++ b/test/test_format_da.py @@ -23,6 +23,7 @@ # from lingua_nostra.format import pronounce_number # # from mycroft_parsers.lang.format_da import nice_response from lingua_nostra.lang.format_da import pronounce_ordinal_da # internal to da +from lingua_nostra.time import default_timezone def setUpModule(): @@ -205,7 +206,7 @@ def test_convert_dacimals_da(self): # use_ampm=False): class TestNiceDateFormat_da(unittest.TestCase): def test_convert_times_da(self): - dt = datetime.datetime(2017, 1, 31, 13, 22, 3) + dt = datetime.datetime(2017, 1, 31, 13, 22, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="da-dk"), "et toogtyve") @@ -229,7 +230,7 @@ def test_convert_times_da(self): use_ampm=False), "tretten toogtyve") - dt = datetime.datetime(2017, 1, 31, 13, 0, 3) + dt = datetime.datetime(2017, 1, 31, 13, 0, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="da-dk"), "et") self.assertEqual(nice_time(dt, lang="da-dk", use_ampm=True), "et om eftermiddagen") @@ -251,7 +252,7 @@ def test_convert_times_da(self): use_ampm=False), "tretten") - dt = datetime.datetime(2017, 1, 31, 13, 2, 3) + dt = datetime.datetime(2017, 1, 31, 13, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="da-dk"), "et nul to") self.assertEqual(nice_time(dt, lang="da-dk", use_ampm=True), "et nul to om eftermiddagen") @@ -273,7 +274,7 @@ def test_convert_times_da(self): use_ampm=False), "tretten nul to") - dt = datetime.datetime(2017, 1, 31, 0, 2, 3) + dt = datetime.datetime(2017, 1, 31, 0, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="da-dk"), "tolv nul to") self.assertEqual(nice_time(dt, lang="da-dk", use_ampm=True), "tolv nul to om natten") @@ -295,7 +296,7 @@ def test_convert_times_da(self): use_ampm=False), "nul nul to") - dt = datetime.datetime(2017, 1, 31, 12, 15, 9) + dt = datetime.datetime(2017, 1, 31, 12, 15, 9, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="da-dk"), "tolv femten") self.assertEqual(nice_time(dt, lang="da-dk", use_ampm=True), "tolv femten om eftermiddagen") @@ -317,7 +318,7 @@ def test_convert_times_da(self): use_ampm=False), "tolv femten") - dt = datetime.datetime(2017, 1, 31, 19, 40, 49) + dt = datetime.datetime(2017, 1, 31, 19, 40, 49, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="da-dk"), "syv fyrre") self.assertEqual(nice_time(dt, lang="da-dk", use_ampm=True), "syv fyrre om aftenen") @@ -339,24 +340,24 @@ def test_convert_times_da(self): use_ampm=False), "nitten fyrre") - dt = datetime.datetime(2017, 1, 31, 1, 15, 00) + dt = datetime.datetime(2017, 1, 31, 1, 15, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="da-dk", use_24hour=True), "et femten") - dt = datetime.datetime(2017, 1, 31, 1, 35, 00) + dt = datetime.datetime(2017, 1, 31, 1, 35, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="da-dk"), "et femogtredive") - dt = datetime.datetime(2017, 1, 31, 1, 45, 00) + dt = datetime.datetime(2017, 1, 31, 1, 45, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="da-dk"), "et femogfyrre") - dt = datetime.datetime(2017, 1, 31, 4, 50, 00) + dt = datetime.datetime(2017, 1, 31, 4, 50, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="da-dk"), "fire halvtres") - dt = datetime.datetime(2017, 1, 31, 5, 55, 00) + dt = datetime.datetime(2017, 1, 31, 5, 55, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="da-dk"), "fem femoghalvtres") - dt = datetime.datetime(2017, 1, 31, 5, 30, 00) + dt = datetime.datetime(2017, 1, 31, 5, 30, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="da-dk", use_ampm=True), "fem tredive om morgenen") diff --git a/test/test_format_de.py b/test/test_format_de.py index 8fc6bc6a..28dfe33e 100644 --- a/test/test_format_de.py +++ b/test/test_format_de.py @@ -24,6 +24,7 @@ from lingua_nostra.lang.format_de import nice_response_de from lingua_nostra.lang.format_de import pronounce_ordinal_de from lingua_nostra.format import join_list +from lingua_nostra.time import default_timezone def setUpModule(): @@ -219,7 +220,7 @@ def tearDown(self): def test_convert_times_de(self): dt = datetime.datetime(2017, 1, 31, - 13, 22, 3) + 13, 22, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "ein Uhr zweiundzwanzig") @@ -244,7 +245,7 @@ def test_convert_times_de(self): "dreizehn Uhr zweiundzwanzig") dt = datetime.datetime(2017, 1, 31, - 13, 0, 3) + 13, 0, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "ein Uhr") self.assertEqual(nice_time(dt, use_ampm=True), @@ -268,7 +269,7 @@ def test_convert_times_de(self): "dreizehn Uhr") dt = datetime.datetime(2017, 1, 31, - 13, 2, 3) + 13, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "ein Uhr zwei") self.assertEqual(nice_time(dt, use_ampm=True), @@ -292,7 +293,7 @@ def test_convert_times_de(self): "dreizehn Uhr zwei") dt = datetime.datetime(2017, 1, 31, - 0, 2, 3) + 0, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "zwölf Uhr zwei") self.assertEqual(nice_time(dt, use_ampm=True), @@ -316,7 +317,7 @@ def test_convert_times_de(self): "null Uhr zwei") dt = datetime.datetime(2017, 1, 31, - 12, 15, 9) + 12, 15, 9, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "viertel eins") self.assertEqual(nice_time(dt, use_ampm=True), @@ -340,7 +341,7 @@ def test_convert_times_de(self): "zwölf Uhr fünfzehn") dt = datetime.datetime(2017, 1, 31, - 19, 40, 49) + 19, 40, 49, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "sieben Uhr vierzig") self.assertEqual(nice_time(dt, use_ampm=True), @@ -364,32 +365,32 @@ def test_convert_times_de(self): "neunzehn Uhr vierzig") dt = datetime.datetime(2017, 1, 31, - 1, 15, 00) + 1, 15, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, use_24hour=True), "ein Uhr fünfzehn") dt = datetime.datetime(2017, 1, 31, - 1, 35, 00) + 1, 35, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "ein Uhr fünfunddreißig") dt = datetime.datetime(2017, 1, 31, - 1, 45, 00) + 1, 45, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "dreiviertel zwei") dt = datetime.datetime(2017, 1, 31, - 4, 50, 00) + 4, 50, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "vier Uhr fünfzig") dt = datetime.datetime(2017, 1, 31, - 5, 55, 00) + 5, 55, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "fünf Uhr fünfundfünfzig") dt = datetime.datetime(2017, 1, 31, - 5, 30, 00) + 5, 30, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, use_ampm=True), "halb sechs morgens") diff --git a/test/test_format_en.py b/test/test_format_en.py index 0d8d4398..4dfd6629 100644 --- a/test/test_format_en.py +++ b/test/test_format_en.py @@ -16,6 +16,7 @@ import json import unittest import datetime +from dateutil import tz import ast import warnings import sys @@ -38,6 +39,8 @@ from lingua_nostra.format import nice_bytes from lingua_nostra.format import pronounce_digits from lingua_nostra.format import nice_units, expand_units +from lingua_nostra.time import default_timezone, set_default_tz, now_local, \ + to_local def setUpModule(): @@ -82,6 +85,36 @@ def tearDownModule(): } +class TestTimezones(unittest.TestCase): + def test_default_tz(self): + set_default_tz("America/Chicago") + + local_time = now_local() + local_tz = default_timezone() + us_time = datetime.datetime.now(tz=tz.gettz("America/Chicago")) + self.assertEqual(nice_date_time(local_time), + nice_date_time(us_time)) + self.assertEqual(local_time.tzinfo, local_tz) + + # naive datetimes assumed to be in default timezone already! + # in the case of datetime.now this corresponds to tzlocal() + # otherwise timezone is undefined and can not be guessed, we assume + # the user means "my timezone" and that LN was configured to use it + # beforehand, if unconfigured default == tzlocal() + dt = datetime.datetime(2021, 6, 23, 00, 43, 39) + dt_local = to_local(dt) + self.assertEqual(nice_time(dt), nice_time(dt_local)) + + def test_tz_conversion(self): + naive = datetime.datetime.now() + system_time = datetime.datetime.now(tz.tzlocal()) + # naive == datetime.now() == tzlocal() internally + # NOTE nice_date_time is not a localized function, it just formats + # the datetime object directly + self.assertEqual(nice_date_time(naive), + nice_date_time(system_time)) + + class TestNiceNumberFormat(unittest.TestCase): tmp_var = None @@ -437,10 +470,6 @@ def test_ordinals(self): "trillionth") -# def nice_time(dt, lang="en-us", speech=True, use_24hour=False, -# use_ampm=False): - - class TestNiceDateFormat(unittest.TestCase): @classmethod def setUpClass(cls): @@ -456,7 +485,7 @@ def setUpClass(cls): def test_convert_times(self): dt = datetime.datetime(2017, 1, 31, - 13, 22, 3) + 13, 22, 3, tzinfo=default_timezone()) # Verify defaults haven't changed self.assertEqual(nice_time(dt), @@ -481,7 +510,7 @@ def test_convert_times(self): "thirteen twenty two") dt = datetime.datetime(2017, 1, 31, - 13, 0, 3) + 13, 0, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "one o'clock") self.assertEqual(nice_time(dt, use_ampm=True), @@ -501,7 +530,7 @@ def test_convert_times(self): "thirteen hundred") dt = datetime.datetime(2017, 1, 31, - 13, 2, 3) + 13, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "one oh two") self.assertEqual(nice_time(dt, use_ampm=True), @@ -521,7 +550,7 @@ def test_convert_times(self): "thirteen zero two") dt = datetime.datetime(2017, 1, 31, - 0, 2, 3) + 0, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "twelve oh two") self.assertEqual(nice_time(dt, use_ampm=True), @@ -541,7 +570,7 @@ def test_convert_times(self): "zero zero zero two") dt = datetime.datetime(2018, 2, 8, - 1, 2, 33) + 1, 2, 33, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "one oh two") self.assertEqual(nice_time(dt, use_ampm=True), @@ -561,14 +590,14 @@ def test_convert_times(self): "zero one zero two") dt = datetime.datetime(2017, 1, 31, - 12, 15, 9) + 12, 15, 9, tzinfo=default_timezone()) self.assertEqual(nice_time(dt), "quarter past twelve") self.assertEqual(nice_time(dt, use_ampm=True), "quarter past twelve p.m.") dt = datetime.datetime(2017, 1, 31, - 5, 30, 00) + 5, 30, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, use_ampm=True), "half past five a.m.") @@ -586,9 +615,11 @@ def test_nice_date(self): dp = ast.literal_eval(p['datetime_param']) np = ast.literal_eval(p['now']) dt = datetime.datetime( - dp[0], dp[1], dp[2], dp[3], dp[4], dp[5]) + dp[0], dp[1], dp[2], dp[3], dp[4], dp[5], + tzinfo=default_timezone()) now = None if not np else datetime.datetime( - np[0], np[1], np[2], np[3], np[4], np[5]) + np[0], np[1], np[2], np[3], np[4], np[5], + tzinfo=default_timezone()) print('Testing for ' + lang + ' that ' + str(dt) + ' is date ' + p['assertEqual']) self.assertEqual(p['assertEqual'], @@ -598,7 +629,8 @@ def test_nice_date(self): # test all days in a year for all languages, # that some output is produced for lang in self.test_config: - for dt in (datetime.datetime(2017, 12, 30, 0, 2, 3) + + for dt in (datetime.datetime(2017, 12, 30, 0, 2, 3, + tzinfo=default_timezone()) + datetime.timedelta(n) for n in range(368)): self.assertTrue(len(nice_date(dt, lang=lang)) > 0) @@ -615,9 +647,11 @@ def test_nice_date_time(self): dp = ast.literal_eval(p['datetime_param']) np = ast.literal_eval(p['now']) dt = datetime.datetime( - dp[0], dp[1], dp[2], dp[3], dp[4], dp[5]) + dp[0], dp[1], dp[2], dp[3], dp[4], dp[5], + tzinfo=default_timezone()) now = None if not np else datetime.datetime( - np[0], np[1], np[2], np[3], np[4], np[5]) + np[0], np[1], np[2], np[3], np[4], np[5], + tzinfo=default_timezone()) print('Testing for ' + lang + ' that ' + str(dt) + ' is date time ' + p['assertEqual']) self.assertEqual( @@ -637,7 +671,8 @@ def test_nice_year(self): p = self.test_config[lang]['test_nice_year'][str(i)] dp = ast.literal_eval(p['datetime_param']) dt = datetime.datetime( - dp[0], dp[1], dp[2], dp[3], dp[4], dp[5]) + dp[0], dp[1], dp[2], dp[3], dp[4], dp[5], + tzinfo=default_timezone()) print('Testing for ' + lang + ' that ' + str(dt) + ' is year ' + p['assertEqual']) self.assertEqual(p['assertEqual'], nice_year( @@ -649,7 +684,8 @@ def test_nice_year(self): for lang in self.test_config: print("Test all years in " + lang) for i in range(1, 9999): - dt = datetime.datetime(i, 1, 31, 13, 2, 3) + dt = datetime.datetime(i, 1, 31, 13, 2, 3, + tzinfo=default_timezone()) self.assertTrue(len(nice_year(dt, lang=lang)) > 0) # Looking through the date sequence can be helpful diff --git a/test/test_format_es.py b/test/test_format_es.py index e11b06fa..cbe1f462 100644 --- a/test/test_format_es.py +++ b/test/test_format_es.py @@ -21,6 +21,7 @@ from lingua_nostra.format import nice_number from lingua_nostra.format import nice_time from lingua_nostra.format import pronounce_number +from lingua_nostra.time import default_timezone def setUpModule(): @@ -178,7 +179,7 @@ def test_convert_decimals(self): class TestNiceDateFormat(unittest.TestCase): def test_convert_times(self): dt = datetime.datetime(2017, 1, 31, - 13, 22, 3) + 13, 22, 3, tzinfo=default_timezone()) # Verify defaults haven't changed self.assertEqual(nice_time(dt, lang="es-es"), @@ -201,7 +202,7 @@ def test_convert_times(self): use_ampm=False), "las trece veintidós") dt = datetime.datetime(2017, 1, 31, - 13, 0, 3) + 13, 0, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="es"), "la una en punto") self.assertEqual(nice_time(dt, lang="es", use_ampm=True), @@ -217,7 +218,7 @@ def test_convert_times(self): self.assertEqual(nice_time(dt, lang="es", use_24hour=True, use_ampm=True), "las trece cero cero") dt = datetime.datetime(2017, 1, 31, - 13, 2, 3) + 13, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="es", use_24hour=True), "las trece cero dos") self.assertEqual(nice_time(dt, lang="es", use_ampm=True), @@ -236,7 +237,7 @@ def test_convert_times(self): use_ampm=False), "las trece cero dos") dt = datetime.datetime(2017, 1, 31, - 0, 2, 3) + 0, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="es"), "las doce y dos") self.assertEqual(nice_time(dt, lang="es", use_ampm=True), @@ -258,7 +259,7 @@ def test_convert_times(self): use_ampm=False), "las cero cero dos") dt = datetime.datetime(2017, 1, 31, - 12, 15, 9) + 12, 15, 9, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="es-es"), "las doce y cuarto") self.assertEqual(nice_time(dt, lang="es-es", use_ampm=True), @@ -282,7 +283,7 @@ def test_convert_times(self): "las doce quince") dt = datetime.datetime(2017, 1, 31, - 19, 40, 49) + 19, 40, 49, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="es-es"), "las ocho menos veinte") self.assertEqual(nice_time(dt, lang="es-es", use_ampm=True), @@ -306,37 +307,37 @@ def test_convert_times(self): "las diecinueve cuarenta") dt = datetime.datetime(2017, 1, 31, - 1, 15, 00) + 1, 15, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="es-es", use_24hour=True), "la una quince") dt = datetime.datetime(2017, 1, 31, - 1, 35, 00) + 1, 35, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="es-es"), "las dos menos veinticinco") dt = datetime.datetime(2017, 1, 31, - 1, 45, 00) + 1, 45, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="es-es"), "las dos menos cuarto") dt = datetime.datetime(2017, 1, 31, - 4, 50, 00) + 4, 50, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="es-es"), "las cinco menos diez") dt = datetime.datetime(2017, 1, 31, - 5, 55, 00) + 5, 55, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="es-es"), "las seis menos cinco") dt = datetime.datetime(2017, 1, 31, - 5, 30, 00) + 5, 30, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="es-es", use_ampm=True), "las cinco y media de la madrugada") dt = datetime.datetime(2017, 1, 31, - 23, 15, 9) + 23, 15, 9, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="es-es", use_24hour=True, use_ampm=True), "las veintitrés quince") diff --git a/test/test_format_fr.py b/test/test_format_fr.py index 94344922..afd758ad 100644 --- a/test/test_format_fr.py +++ b/test/test_format_fr.py @@ -20,6 +20,7 @@ from lingua_nostra.format import nice_number from lingua_nostra.format import nice_time from lingua_nostra.format import pronounce_number +from lingua_nostra.time import default_timezone def setUpModule(): @@ -184,7 +185,7 @@ def test_convert_decimals_fr(self): class TestNiceDateFormat_fr(unittest.TestCase): def test_convert_times_fr(self): dt = datetime.datetime(2017, 1, 31, - 13, 22, 3) + 13, 22, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="fr-fr"), "une heure vingt-deux") @@ -209,7 +210,7 @@ def test_convert_times_fr(self): "treize heures vingt-deux") dt = datetime.datetime(2017, 1, 31, - 13, 0, 3) + 13, 0, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="fr-fr"), "une heure") self.assertEqual(nice_time(dt, lang="fr-fr", use_ampm=True), @@ -233,7 +234,7 @@ def test_convert_times_fr(self): "treize heures") dt = datetime.datetime(2017, 1, 31, - 13, 2, 3) + 13, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="fr-fr"), "une heure deux") self.assertEqual(nice_time(dt, lang="fr-fr", use_ampm=True), @@ -257,7 +258,7 @@ def test_convert_times_fr(self): "treize heures deux") dt = datetime.datetime(2017, 1, 31, - 0, 2, 3) + 0, 2, 3, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="fr-fr"), "minuit deux") self.assertEqual(nice_time(dt, lang="fr-fr", use_ampm=True), @@ -281,7 +282,7 @@ def test_convert_times_fr(self): "minuit deux") dt = datetime.datetime(2017, 1, 31, - 12, 15, 9) + 12, 15, 9, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="fr-fr"), "midi et quart") self.assertEqual(nice_time(dt, lang="fr-fr", use_ampm=True), @@ -305,7 +306,7 @@ def test_convert_times_fr(self): "midi quinze") dt = datetime.datetime(2017, 1, 31, - 19, 40, 49) + 19, 40, 49, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="fr-fr"), "huit heures moins vingt") self.assertEqual(nice_time(dt, lang="fr-fr", use_ampm=True), @@ -329,32 +330,32 @@ def test_convert_times_fr(self): "dix-neuf heures quarante") dt = datetime.datetime(2017, 1, 31, - 1, 15, 00) + 1, 15, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="fr-fr", use_24hour=True), "une heure quinze") dt = datetime.datetime(2017, 1, 31, - 1, 35, 00) + 1, 35, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="fr-fr"), "deux heures moins vingt-cinq") dt = datetime.datetime(2017, 1, 31, - 1, 45, 00) + 1, 45, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="fr-fr"), "deux heures moins le quart") dt = datetime.datetime(2017, 1, 31, - 4, 50, 00) + 4, 50, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="fr-fr"), "cinq heures moins dix") dt = datetime.datetime(2017, 1, 31, - 5, 55, 00) + 5, 55, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="fr-fr"), "six heures moins cinq") dt = datetime.datetime(2017, 1, 31, - 5, 30, 00) + 5, 30, 00, tzinfo=default_timezone()) self.assertEqual(nice_time(dt, lang="fr-fr", use_ampm=True), "cinq heures et demi du matin") diff --git a/test/test_parse_en.py b/test/test_parse_en.py index b493cb58..70ee9579 100644 --- a/test/test_parse_en.py +++ b/test/test_parse_en.py @@ -15,18 +15,20 @@ # import unittest from datetime import datetime, timedelta +from dateutil import tz +from lingua_nostra.time import now_local, set_default_tz from lingua_nostra import load_language, unload_language, set_default_lang from lingua_nostra.internal import FunctionNotLocalizedError -from lingua_nostra.time import default_timezone from lingua_nostra.parse import extract_datetime from lingua_nostra.parse import extract_duration from lingua_nostra.parse import extract_number, extract_numbers +from lingua_nostra.parse import extract_quantities from lingua_nostra.parse import fuzzy_match from lingua_nostra.parse import get_gender from lingua_nostra.parse import match_one from lingua_nostra.parse import normalize -from lingua_nostra.parse import extract_quantities +from lingua_nostra.time import default_timezone def setUpModule(): @@ -61,6 +63,45 @@ def test_match_one(self): self.assertEqual(match_one('enry', choices)[0], 4) +class TestTimezones(unittest.TestCase): + def test_default_tz(self): + naive = datetime.now() + + # convert to default tz + set_default_tz("Europe/London") + dt = extract_datetime("tomorrow", anchorDate=naive)[0] + self.assertEqual(dt.tzinfo, tz.gettz("Europe/London")) + + set_default_tz("America/Chicago") + dt = extract_datetime("tomorrow", anchorDate=naive)[0] + self.assertEqual(dt.tzinfo, tz.gettz("America/Chicago")) + + def test_convert_to_anchorTZ(self): + naive = datetime.now() + local = now_local() + london_time = datetime.now(tz=tz.gettz("Europe/London")) + us_time = datetime.now(tz=tz.gettz("America/Chicago")) + + # convert to anchor date + dt = extract_datetime("tomorrow", anchorDate=naive)[0] + self.assertEqual(dt.tzinfo, default_timezone()) + dt = extract_datetime("tomorrow", anchorDate=local)[0] + self.assertEqual(dt.tzinfo, local.tzinfo) + dt = extract_datetime("tomorrow", anchorDate=london_time)[0] + self.assertEqual(dt.tzinfo, london_time.tzinfo) + dt = extract_datetime("tomorrow", anchorDate=us_time)[0] + self.assertEqual(dt.tzinfo, us_time.tzinfo) + + # test naive == default tz + set_default_tz("America/Chicago") + dt = extract_datetime("tomorrow", anchorDate=naive)[0] + self.assertEqual(dt.tzinfo, default_timezone()) + set_default_tz("Europe/London") + dt = extract_datetime("tomorrow", anchorDate=naive)[0] + self.assertEqual(dt.tzinfo, default_timezone()) + + + class TestNormalize(unittest.TestCase): def test_articles(self): self.assertEqual(normalize("this is a test", remove_articles=True), @@ -73,6 +114,240 @@ def test_articles(self): remove_articles=False), "this is an extra test") + def test_normalize_numbers(self): + self.assertEqual(normalize("remind me to do something at two to two"), + "remind me to do something at 2 to 2") + self.assertEqual(normalize('what time will it be in two minutes'), + 'what time will it be in 2 minutes') + self.assertEqual( + normalize('What time will it be in twenty two minutes'), + 'What time will it be in 22 minutes') + self.assertEqual( + normalize("remind me to do something at twenty to two"), + "remind me to do something at 20 to 2") + + # TODO imperfect test, maybe should return 'my favorite numbers are 20 2', + # let is pass for now since this is likely a STT issue if ever + # encountered in the wild and is somewhat ambiguous, if this was + # spoken by a human the result is what we expect, if in written form + # it is ambiguous but could mean separate numbers + self.assertEqual(normalize('my favorite numbers are twenty 2'), + 'my favorite numbers are 22') + # TODO imperfect test, same as above, fixing would impact + # extract_numbers quite a bit and require a non trivial ammount of + # refactoring + self.assertEqual(normalize('my favorite numbers are 20 2'), + 'my favorite numbers are 22') + + # test ordinals + self.assertEqual(normalize('this is the first'), + 'this is first') + self.assertEqual(normalize('this is the first second'), + 'this is first second') + self.assertEqual(normalize('this is the first second and third'), + 'this is first second and third') + + # test fractions + self.assertEqual(normalize('whole hour'), + 'whole hour') + self.assertEqual(normalize('quarter hour'), + 'quarter hour') + self.assertEqual(normalize('halve hour'), + 'halve hour') + self.assertEqual(normalize('half hour'), + 'half hour') + + def test_spaces(self): + self.assertEqual(normalize(" this is a test"), + "this is test") + self.assertEqual(normalize(" this is a test "), + "this is test") + self.assertEqual(normalize(" this is one test"), + "this is 1 test") + + def test_numbers(self): + self.assertEqual(normalize("this is a one two three test"), + "this is 1 2 3 test") + self.assertEqual(normalize(" it's a four five six test"), + "it is 4 5 6 test") + self.assertEqual(normalize("it's a seven eight nine test"), + "it is 7 8 9 test") + self.assertEqual(normalize("it's a seven eight nine test"), + "it is 7 8 9 test") + self.assertEqual(normalize("that's a ten eleven twelve test"), + "that is 10 11 12 test") + self.assertEqual(normalize("that's a thirteen fourteen test"), + "that is 13 14 test") + self.assertEqual(normalize("that's fifteen sixteen seventeen"), + "that is 15 16 17") + self.assertEqual(normalize("that's eighteen nineteen twenty"), + "that is 18 19 20") + self.assertEqual(normalize("that's one nineteen twenty two"), + "that is 1 19 22") + self.assertEqual(normalize("that's one hundred"), + "that is 100") + self.assertEqual(normalize("that's one two twenty two"), + "that is 1 2 22") + self.assertEqual(normalize("that's one and a half"), + "that is 1 and half") + self.assertEqual(normalize("that's one and a half and five six"), + "that is 1 and half and 5 6") + + def test_contractions(self): + self.assertEqual(normalize("ain't"), "is not") + self.assertEqual(normalize("aren't"), "are not") + self.assertEqual(normalize("can't"), "can not") + self.assertEqual(normalize("could've"), "could have") + self.assertEqual(normalize("couldn't"), "could not") + self.assertEqual(normalize("didn't"), "did not") + self.assertEqual(normalize("doesn't"), "does not") + self.assertEqual(normalize("don't"), "do not") + self.assertEqual(normalize("gonna"), "going to") + self.assertEqual(normalize("gotta"), "got to") + self.assertEqual(normalize("hadn't"), "had not") + self.assertEqual(normalize("hadn't have"), "had not have") + self.assertEqual(normalize("hasn't"), "has not") + self.assertEqual(normalize("haven't"), "have not") + # TODO: Ambiguous with "he had" + self.assertEqual(normalize("he'd"), "he would") + self.assertEqual(normalize("he'll"), "he will") + # TODO: Ambiguous with "he has" + self.assertEqual(normalize("he's"), "he is") + # TODO: Ambiguous with "how would" + self.assertEqual(normalize("how'd"), "how did") + self.assertEqual(normalize("how'll"), "how will") + # TODO: Ambiguous with "how has" and "how does" + self.assertEqual(normalize("how's"), "how is") + # TODO: Ambiguous with "I had" + self.assertEqual(normalize("I'd"), "I would") + self.assertEqual(normalize("I'll"), "I will") + self.assertEqual(normalize("I'm"), "I am") + self.assertEqual(normalize("I've"), "I have") + self.assertEqual(normalize("I haven't"), "I have not") + self.assertEqual(normalize("isn't"), "is not") + self.assertEqual(normalize("it'd"), "it would") + self.assertEqual(normalize("it'll"), "it will") + # TODO: Ambiguous with "it has" + self.assertEqual(normalize("it's"), "it is") + self.assertEqual(normalize("it isn't"), "it is not") + self.assertEqual(normalize("mightn't"), "might not") + self.assertEqual(normalize("might've"), "might have") + self.assertEqual(normalize("mustn't"), "must not") + self.assertEqual(normalize("mustn't have"), "must not have") + self.assertEqual(normalize("must've"), "must have") + self.assertEqual(normalize("needn't"), "need not") + self.assertEqual(normalize("oughtn't"), "ought not") + self.assertEqual(normalize("shan't"), "shall not") + # TODO: Ambiguous wiht "she had" + self.assertEqual(normalize("she'd"), "she would") + self.assertEqual(normalize("she hadn't"), "she had not") + self.assertEqual(normalize("she'll"), "she will") + self.assertEqual(normalize("she's"), "she is") + self.assertEqual(normalize("she isn't"), "she is not") + self.assertEqual(normalize("should've"), "should have") + self.assertEqual(normalize("shouldn't"), "should not") + self.assertEqual(normalize("shouldn't have"), "should not have") + self.assertEqual(normalize("somebody's"), "somebody is") + # TODO: Ambiguous with "someone had" + self.assertEqual(normalize("someone'd"), "someone would") + self.assertEqual(normalize("someone hadn't"), "someone had not") + self.assertEqual(normalize("someone'll"), "someone will") + # TODO: Ambiguous with "someone has" + self.assertEqual(normalize("someone's"), "someone is") + self.assertEqual(normalize("that'll"), "that will") + # TODO: Ambiguous with "that has" + self.assertEqual(normalize("that's"), "that is") + # TODO: Ambiguous with "that had" + self.assertEqual(normalize("that'd"), "that would") + # TODO: Ambiguous with "there had" + self.assertEqual(normalize("there'd"), "there would") + self.assertEqual(normalize("there're"), "there are") + # TODO: Ambiguous with "there has" + self.assertEqual(normalize("there's"), "there is") + # TODO: Ambiguous with "they had" + self.assertEqual(normalize("they'd"), "they would") + self.assertEqual(normalize("they'll"), "they will") + self.assertEqual(normalize("they won't have"), "they will not have") + self.assertEqual(normalize("they're"), "they are") + self.assertEqual(normalize("they've"), "they have") + self.assertEqual(normalize("they haven't"), "they have not") + self.assertEqual(normalize("wasn't"), "was not") + # TODO: Ambiguous wiht "we had" + self.assertEqual(normalize("we'd"), "we would") + self.assertEqual(normalize("we would've"), "we would have") + self.assertEqual(normalize("we wouldn't"), "we would not") + self.assertEqual(normalize("we wouldn't have"), "we would not have") + self.assertEqual(normalize("we'll"), "we will") + self.assertEqual(normalize("we won't have"), "we will not have") + self.assertEqual(normalize("we're"), "we are") + self.assertEqual(normalize("we've"), "we have") + self.assertEqual(normalize("weren't"), "were not") + self.assertEqual(normalize("what'd"), "what did") + self.assertEqual(normalize("what'll"), "what will") + self.assertEqual(normalize("what're"), "what are") + # TODO: Ambiguous with "what has" / "what does") + self.assertEqual(normalize("whats"), "what is") + self.assertEqual(normalize("what's"), "what is") + self.assertEqual(normalize("what've"), "what have") + # TODO: Ambiguous with "when has" + self.assertEqual(normalize("when's"), "when is") + self.assertEqual(normalize("where'd"), "where did") + # TODO: Ambiguous with "where has" / where does" + self.assertEqual(normalize("where's"), "where is") + self.assertEqual(normalize("where've"), "where have") + # TODO: Ambiguous with "who had" "who did") + self.assertEqual(normalize("who'd"), "who would") + self.assertEqual(normalize("who'd've"), "who would have") + self.assertEqual(normalize("who'll"), "who will") + self.assertEqual(normalize("who're"), "who are") + # TODO: Ambiguous with "who has" / "who does" + self.assertEqual(normalize("who's"), "who is") + self.assertEqual(normalize("who've"), "who have") + self.assertEqual(normalize("why'd"), "why did") + self.assertEqual(normalize("why're"), "why are") + # TODO: Ambiguous with "why has" / "why does" + self.assertEqual(normalize("why's"), "why is") + self.assertEqual(normalize("won't"), "will not") + self.assertEqual(normalize("won't've"), "will not have") + self.assertEqual(normalize("would've"), "would have") + self.assertEqual(normalize("wouldn't"), "would not") + self.assertEqual(normalize("wouldn't've"), "would not have") + self.assertEqual(normalize("ya'll"), "you all") + self.assertEqual(normalize("y'all"), "you all") + self.assertEqual(normalize("y'ain't"), "you are not") + # TODO: Ambiguous with "you had" + self.assertEqual(normalize("you'd"), "you would") + self.assertEqual(normalize("you'd've"), "you would have") + self.assertEqual(normalize("you'll"), "you will") + self.assertEqual(normalize("you're"), "you are") + self.assertEqual(normalize("you aren't"), "you are not") + self.assertEqual(normalize("you've"), "you have") + self.assertEqual(normalize("you haven't"), "you have not") + + def test_combinations(self): + self.assertEqual(normalize("I couldn't have guessed there'd be two"), + "I could not have guessed there would be 2") + self.assertEqual(normalize("I wouldn't have"), "I would not have") + self.assertEqual(normalize("I hadn't been there"), + "I had not been there") + self.assertEqual(normalize("I would've"), "I would have") + self.assertEqual(normalize("it hadn't"), "it had not") + self.assertEqual(normalize("it hadn't have"), "it had not have") + self.assertEqual(normalize("it would've"), "it would have") + self.assertEqual(normalize("she wouldn't have"), "she would not have") + self.assertEqual(normalize("she would've"), "she would have") + self.assertEqual(normalize("someone wouldn't have"), + "someone would not have") + self.assertEqual(normalize("someone would've"), "someone would have") + self.assertEqual(normalize("what's the weather like"), + "what is weather like") + self.assertEqual(normalize("that's what I told you"), + "that is what I told you") + + self.assertEqual(normalize("whats 8 + 4"), "what is 8 + 4") + + +class TestNumbers(unittest.TestCase): def test_extract_number_decimal_markers(self): # Test decimal normalization self.assertEqual(extract_number("4,4", decimal=','), 4.4) @@ -307,17 +582,60 @@ def test_extract_number(self): self.assertEqual(extract_number("a couple thousand beers"), 2000) self.assertEqual(extract_number("totally 100%"), 100) - def test_extract_duration_en(self): - self.assertEqual(extract_duration("10 seconds"), - (timedelta(seconds=10.0), "")) - self.assertEqual(extract_duration("5 minutes"), - (timedelta(minutes=5), "")) - self.assertEqual(extract_duration("2 hours"), - (timedelta(hours=2), "")) - self.assertEqual(extract_duration("3 days"), - (timedelta(days=3), "")) - self.assertEqual(extract_duration("25 weeks"), - (timedelta(weeks=25), "")) + def test_multiple_numbers(self): + self.assertEqual(extract_numbers("this is a one two three test"), + [1.0, 2.0, 3.0]) + self.assertEqual(extract_numbers("it's a four five six test"), + [4.0, 5.0, 6.0]) + self.assertEqual(extract_numbers("this is a ten eleven twelve test"), + [10.0, 11.0, 12.0]) + self.assertEqual(extract_numbers("this is a one twenty one test"), + [1.0, 21.0]) + self.assertEqual(extract_numbers("1 dog, seven pigs, macdonald had a " + "farm, 3 times 5 macarena"), + [1, 7, 3, 5]) + self.assertEqual(extract_numbers("two beers for two bears"), + [2.0, 2.0]) + self.assertEqual(extract_numbers("twenty 20 twenty"), + [20, 20, 20]) + self.assertEqual(extract_numbers("twenty 20 22"), + [20.0, 20.0, 22.0]) + self.assertEqual(extract_numbers("twenty twenty two twenty"), + [20, 22, 20]) + self.assertEqual(extract_numbers("twenty 2"), + [22.0]) + self.assertEqual(extract_numbers("twenty 20 twenty 2"), + [20, 20, 22]) + self.assertEqual(extract_numbers("third one"), + [1 / 3, 1]) + self.assertEqual(extract_numbers("third one", ordinals=True), [3]) + self.assertEqual(extract_numbers("six trillion", short_scale=True), + [6e12]) + self.assertEqual(extract_numbers("six trillion", short_scale=False), + [6e18]) + self.assertEqual(extract_numbers("two pigs and six trillion bacteria", + short_scale=True), [2, 6e12]) + self.assertEqual(extract_numbers("two pigs and six trillion bacteria", + short_scale=False), [2, 6e18]) + self.assertEqual(extract_numbers("thirty second or first", + ordinals=True), [32, 1]) + self.assertEqual(extract_numbers("this is a seven eight nine and a" + " half test"), + [7.0, 8.0, 9.5]) + + +class TestDuration(unittest.TestCase): + def test_extract_duration_en(self): + self.assertEqual(extract_duration("10 seconds"), + (timedelta(seconds=10.0), "")) + self.assertEqual(extract_duration("5 minutes"), + (timedelta(minutes=5), "")) + self.assertEqual(extract_duration("2 hours"), + (timedelta(hours=2), "")) + self.assertEqual(extract_duration("3 days"), + (timedelta(days=3), "")) + self.assertEqual(extract_duration("25 weeks"), + (timedelta(weeks=25), "")) self.assertEqual(extract_duration("seven hours"), (timedelta(hours=7), "")) self.assertEqual(extract_duration("7.5 seconds"), @@ -348,6 +666,8 @@ def test_extract_duration_case_en(self): self.assertEqual(extract_duration("Nineteen minutes past THE hour"), (timedelta(minutes=19), "past THE hour")) + +class TestDatetime(unittest.TestCase): def test_extractdatetime_fractions_en(self): def extractWithFormat(text): date = datetime(2017, 6, 27, 13, 4, @@ -792,49 +1112,6 @@ def testExtract(text, expected_date, expected_leftover): testExtract("lets meet in 5seconds", "2017-06-27 10:01:07", "lets meet") - def test_normalize_numbers(self): - self.assertEqual(normalize("remind me to do something at two to two"), - "remind me to do something at 2 to 2") - self.assertEqual(normalize('what time will it be in two minutes'), - 'what time will it be in 2 minutes') - self.assertEqual( - normalize('What time will it be in twenty two minutes'), - 'What time will it be in 22 minutes') - self.assertEqual( - normalize("remind me to do something at twenty to two"), - "remind me to do something at 20 to 2") - - # TODO imperfect test, maybe should return 'my favorite numbers are 20 2', - # let is pass for now since this is likely a STT issue if ever - # encountered in the wild and is somewhat ambiguous, if this was - # spoken by a human the result is what we expect, if in written form - # it is ambiguous but could mean separate numbers - self.assertEqual(normalize('my favorite numbers are twenty 2'), - 'my favorite numbers are 22') - # TODO imperfect test, same as above, fixing would impact - # extract_numbers quite a bit and require a non trivial ammount of - # refactoring - self.assertEqual(normalize('my favorite numbers are 20 2'), - 'my favorite numbers are 22') - - # test ordinals - self.assertEqual(normalize('this is the first'), - 'this is first') - self.assertEqual(normalize('this is the first second'), - 'this is first second') - self.assertEqual(normalize('this is the first second and third'), - 'this is first second and third') - - # test fractions - self.assertEqual(normalize('whole hour'), - 'whole hour') - self.assertEqual(normalize('quarter hour'), - 'quarter hour') - self.assertEqual(normalize('halve hour'), - 'halve hour') - self.assertEqual(normalize('half hour'), - 'half hour') - def test_extract_date_with_number_words(self): now = datetime(2019, 7, 4, 8, 1, 2, tzinfo=default_timezone()) self.assertEqual( @@ -848,236 +1125,8 @@ def test_extract_date_with_number_words(self): now)[0], datetime(2019, 7, 4, 11, 21, 2, tzinfo=default_timezone())) - def test_spaces(self): - self.assertEqual(normalize(" this is a test"), - "this is test") - self.assertEqual(normalize(" this is a test "), - "this is test") - self.assertEqual(normalize(" this is one test"), - "this is 1 test") - - def test_numbers(self): - self.assertEqual(normalize("this is a one two three test"), - "this is 1 2 3 test") - self.assertEqual(normalize(" it's a four five six test"), - "it is 4 5 6 test") - self.assertEqual(normalize("it's a seven eight nine test"), - "it is 7 8 9 test") - self.assertEqual(normalize("it's a seven eight nine test"), - "it is 7 8 9 test") - self.assertEqual(normalize("that's a ten eleven twelve test"), - "that is 10 11 12 test") - self.assertEqual(normalize("that's a thirteen fourteen test"), - "that is 13 14 test") - self.assertEqual(normalize("that's fifteen sixteen seventeen"), - "that is 15 16 17") - self.assertEqual(normalize("that's eighteen nineteen twenty"), - "that is 18 19 20") - self.assertEqual(normalize("that's one nineteen twenty two"), - "that is 1 19 22") - self.assertEqual(normalize("that's one hundred"), - "that is 100") - self.assertEqual(normalize("that's one two twenty two"), - "that is 1 2 22") - self.assertEqual(normalize("that's one and a half"), - "that is 1 and half") - self.assertEqual(normalize("that's one and a half and five six"), - "that is 1 and half and 5 6") - - def test_multiple_numbers(self): - self.assertEqual(extract_numbers("this is a one two three test"), - [1.0, 2.0, 3.0]) - self.assertEqual(extract_numbers("it's a four five six test"), - [4.0, 5.0, 6.0]) - self.assertEqual(extract_numbers("this is a ten eleven twelve test"), - [10.0, 11.0, 12.0]) - self.assertEqual(extract_numbers("this is a one twenty one test"), - [1.0, 21.0]) - self.assertEqual(extract_numbers("1 dog, seven pigs, macdonald had a " - "farm, 3 times 5 macarena"), - [1, 7, 3, 5]) - self.assertEqual(extract_numbers("two beers for two bears"), - [2.0, 2.0]) - self.assertEqual(extract_numbers("twenty 20 twenty"), - [20, 20, 20]) - self.assertEqual(extract_numbers("twenty 20 22"), - [20.0, 20.0, 22.0]) - self.assertEqual(extract_numbers("twenty twenty two twenty"), - [20, 22, 20]) - self.assertEqual(extract_numbers("twenty 2"), - [22.0]) - self.assertEqual(extract_numbers("twenty 20 twenty 2"), - [20, 20, 22]) - self.assertEqual(extract_numbers("third one"), - [1 / 3, 1]) - self.assertEqual(extract_numbers("third one", ordinals=True), [3]) - self.assertEqual(extract_numbers("six trillion", short_scale=True), - [6e12]) - self.assertEqual(extract_numbers("six trillion", short_scale=False), - [6e18]) - self.assertEqual(extract_numbers("two pigs and six trillion bacteria", - short_scale=True), [2, 6e12]) - self.assertEqual(extract_numbers("two pigs and six trillion bacteria", - short_scale=False), [2, 6e18]) - self.assertEqual(extract_numbers("thirty second or first", - ordinals=True), [32, 1]) - self.assertEqual(extract_numbers("this is a seven eight nine and a" - " half test"), - [7.0, 8.0, 9.5]) - - def test_contractions(self): - self.assertEqual(normalize("ain't"), "is not") - self.assertEqual(normalize("aren't"), "are not") - self.assertEqual(normalize("can't"), "can not") - self.assertEqual(normalize("could've"), "could have") - self.assertEqual(normalize("couldn't"), "could not") - self.assertEqual(normalize("didn't"), "did not") - self.assertEqual(normalize("doesn't"), "does not") - self.assertEqual(normalize("don't"), "do not") - self.assertEqual(normalize("gonna"), "going to") - self.assertEqual(normalize("gotta"), "got to") - self.assertEqual(normalize("hadn't"), "had not") - self.assertEqual(normalize("hadn't have"), "had not have") - self.assertEqual(normalize("hasn't"), "has not") - self.assertEqual(normalize("haven't"), "have not") - # TODO: Ambiguous with "he had" - self.assertEqual(normalize("he'd"), "he would") - self.assertEqual(normalize("he'll"), "he will") - # TODO: Ambiguous with "he has" - self.assertEqual(normalize("he's"), "he is") - # TODO: Ambiguous with "how would" - self.assertEqual(normalize("how'd"), "how did") - self.assertEqual(normalize("how'll"), "how will") - # TODO: Ambiguous with "how has" and "how does" - self.assertEqual(normalize("how's"), "how is") - # TODO: Ambiguous with "I had" - self.assertEqual(normalize("I'd"), "I would") - self.assertEqual(normalize("I'll"), "I will") - self.assertEqual(normalize("I'm"), "I am") - self.assertEqual(normalize("I've"), "I have") - self.assertEqual(normalize("I haven't"), "I have not") - self.assertEqual(normalize("isn't"), "is not") - self.assertEqual(normalize("it'd"), "it would") - self.assertEqual(normalize("it'll"), "it will") - # TODO: Ambiguous with "it has" - self.assertEqual(normalize("it's"), "it is") - self.assertEqual(normalize("it isn't"), "it is not") - self.assertEqual(normalize("mightn't"), "might not") - self.assertEqual(normalize("might've"), "might have") - self.assertEqual(normalize("mustn't"), "must not") - self.assertEqual(normalize("mustn't have"), "must not have") - self.assertEqual(normalize("must've"), "must have") - self.assertEqual(normalize("needn't"), "need not") - self.assertEqual(normalize("oughtn't"), "ought not") - self.assertEqual(normalize("shan't"), "shall not") - # TODO: Ambiguous wiht "she had" - self.assertEqual(normalize("she'd"), "she would") - self.assertEqual(normalize("she hadn't"), "she had not") - self.assertEqual(normalize("she'll"), "she will") - self.assertEqual(normalize("she's"), "she is") - self.assertEqual(normalize("she isn't"), "she is not") - self.assertEqual(normalize("should've"), "should have") - self.assertEqual(normalize("shouldn't"), "should not") - self.assertEqual(normalize("shouldn't have"), "should not have") - self.assertEqual(normalize("somebody's"), "somebody is") - # TODO: Ambiguous with "someone had" - self.assertEqual(normalize("someone'd"), "someone would") - self.assertEqual(normalize("someone hadn't"), "someone had not") - self.assertEqual(normalize("someone'll"), "someone will") - # TODO: Ambiguous with "someone has" - self.assertEqual(normalize("someone's"), "someone is") - self.assertEqual(normalize("that'll"), "that will") - # TODO: Ambiguous with "that has" - self.assertEqual(normalize("that's"), "that is") - # TODO: Ambiguous with "that had" - self.assertEqual(normalize("that'd"), "that would") - # TODO: Ambiguous with "there had" - self.assertEqual(normalize("there'd"), "there would") - self.assertEqual(normalize("there're"), "there are") - # TODO: Ambiguous with "there has" - self.assertEqual(normalize("there's"), "there is") - # TODO: Ambiguous with "they had" - self.assertEqual(normalize("they'd"), "they would") - self.assertEqual(normalize("they'll"), "they will") - self.assertEqual(normalize("they won't have"), "they will not have") - self.assertEqual(normalize("they're"), "they are") - self.assertEqual(normalize("they've"), "they have") - self.assertEqual(normalize("they haven't"), "they have not") - self.assertEqual(normalize("wasn't"), "was not") - # TODO: Ambiguous wiht "we had" - self.assertEqual(normalize("we'd"), "we would") - self.assertEqual(normalize("we would've"), "we would have") - self.assertEqual(normalize("we wouldn't"), "we would not") - self.assertEqual(normalize("we wouldn't have"), "we would not have") - self.assertEqual(normalize("we'll"), "we will") - self.assertEqual(normalize("we won't have"), "we will not have") - self.assertEqual(normalize("we're"), "we are") - self.assertEqual(normalize("we've"), "we have") - self.assertEqual(normalize("weren't"), "were not") - self.assertEqual(normalize("what'd"), "what did") - self.assertEqual(normalize("what'll"), "what will") - self.assertEqual(normalize("what're"), "what are") - # TODO: Ambiguous with "what has" / "what does") - self.assertEqual(normalize("whats"), "what is") - self.assertEqual(normalize("what's"), "what is") - self.assertEqual(normalize("what've"), "what have") - # TODO: Ambiguous with "when has" - self.assertEqual(normalize("when's"), "when is") - self.assertEqual(normalize("where'd"), "where did") - # TODO: Ambiguous with "where has" / where does" - self.assertEqual(normalize("where's"), "where is") - self.assertEqual(normalize("where've"), "where have") - # TODO: Ambiguous with "who had" "who did") - self.assertEqual(normalize("who'd"), "who would") - self.assertEqual(normalize("who'd've"), "who would have") - self.assertEqual(normalize("who'll"), "who will") - self.assertEqual(normalize("who're"), "who are") - # TODO: Ambiguous with "who has" / "who does" - self.assertEqual(normalize("who's"), "who is") - self.assertEqual(normalize("who've"), "who have") - self.assertEqual(normalize("why'd"), "why did") - self.assertEqual(normalize("why're"), "why are") - # TODO: Ambiguous with "why has" / "why does" - self.assertEqual(normalize("why's"), "why is") - self.assertEqual(normalize("won't"), "will not") - self.assertEqual(normalize("won't've"), "will not have") - self.assertEqual(normalize("would've"), "would have") - self.assertEqual(normalize("wouldn't"), "would not") - self.assertEqual(normalize("wouldn't've"), "would not have") - self.assertEqual(normalize("ya'll"), "you all") - self.assertEqual(normalize("y'all"), "you all") - self.assertEqual(normalize("y'ain't"), "you are not") - # TODO: Ambiguous with "you had" - self.assertEqual(normalize("you'd"), "you would") - self.assertEqual(normalize("you'd've"), "you would have") - self.assertEqual(normalize("you'll"), "you will") - self.assertEqual(normalize("you're"), "you are") - self.assertEqual(normalize("you aren't"), "you are not") - self.assertEqual(normalize("you've"), "you have") - self.assertEqual(normalize("you haven't"), "you have not") - - def test_combinations(self): - self.assertEqual(normalize("I couldn't have guessed there'd be two"), - "I could not have guessed there would be 2") - self.assertEqual(normalize("I wouldn't have"), "I would not have") - self.assertEqual(normalize("I hadn't been there"), - "I had not been there") - self.assertEqual(normalize("I would've"), "I would have") - self.assertEqual(normalize("it hadn't"), "it had not") - self.assertEqual(normalize("it hadn't have"), "it had not have") - self.assertEqual(normalize("it would've"), "it would have") - self.assertEqual(normalize("she wouldn't have"), "she would not have") - self.assertEqual(normalize("she would've"), "she would have") - self.assertEqual(normalize("someone wouldn't have"), - "someone would not have") - self.assertEqual(normalize("someone would've"), "someone would have") - self.assertEqual(normalize("what's the weather like"), - "what is weather like") - self.assertEqual(normalize("that's what I told you"), - "that is what I told you") - - self.assertEqual(normalize("whats 8 + 4"), "what is 8 + 4") +class TestGender(unittest.TestCase): # TODO not localized; needed in english? def test_gender(self): self.assertRaises((AttributeError, FunctionNotLocalizedError), diff --git a/test/test_parse_fa.py b/test/test_parse_fa.py index adaf6651..99a90ced 100644 --- a/test/test_parse_fa.py +++ b/test/test_parse_fa.py @@ -17,12 +17,11 @@ from datetime import datetime, timedelta from lingua_nostra import load_language, unload_language, set_default_lang -from lingua_nostra.internal import FunctionNotLocalizedError from lingua_nostra.parse import extract_datetime from lingua_nostra.parse import extract_duration from lingua_nostra.parse import extract_number, extract_numbers -from lingua_nostra.time import default_timezone from lingua_nostra.parse import normalize +from lingua_nostra.time import default_timezone def setUpModule(): @@ -35,7 +34,7 @@ def tearDownModule(): unload_language('fa') -class TestNormalize(unittest.TestCase): +class TestNumbers(unittest.TestCase): def test_extract_number(self): # self.assertEqual(extract_number("این تست اول است", @@ -73,6 +72,16 @@ def test_extract_number(self): self.assertEqual(extract_number("دو میلیون و پانصد هزار " "تن گوشت یخ زده"), 2500000) + def test_multiple_numbers(self): + self.assertEqual(extract_numbers("یک دو سه"), + [1.0, 2.0, 3.0]) + self.assertEqual( + extract_numbers("ده بیست سه پونزده هزار و شصت و شونزده"), + [10, 20, 3, 15060, 16]) + + +class TestDuration(unittest.TestCase): + def test_extract_duration_farsi(self): self.assertEqual(extract_duration("10 ثانیه"), (timedelta(seconds=10.0), "")) @@ -102,9 +111,13 @@ def test_extract_duration_farsi(self): (timedelta(hours=1, minutes=57.5), "این فیلم طول می کشد")) + +class TestDatetime(unittest.TestCase): + def test_extractdatetime_farsi(self): def extractWithFormat(text): - date = datetime(2017, 6, 27, 13, 4, tzinfo=default_timezone()) # Tue June 27, 2017 @ 1:04pm + date = datetime(2017, 6, 27, 13, 4, + tzinfo=default_timezone()) # Tue June 27, 2017 @ 1:04pm [extractedDate, leftover] = extract_datetime(text, date) extractedDate = extractedDate.strftime("%Y-%m-%d %H:%M:%S") return [extractedDate, leftover] @@ -159,13 +172,6 @@ def testExtract(text, expected_date, expected_leftover): # TODO: This test is imperfect due to the "at 7:00" still in the # remainder. But let it pass for now since time is correct - def test_multiple_numbers(self): - self.assertEqual(extract_numbers("یک دو سه"), - [1.0, 2.0, 3.0]) - self.assertEqual( - extract_numbers("ده بیست سه پونزده هزار و شصت و شونزده"), - [10, 20, 3, 15060, 16]) - if __name__ == "__main__": unittest.main()