Merge pull request #1056 from stevenyoungs/dateparser_quarter

This commit is contained in:
Nick Hall 2022-02-19 21:14:43 +00:00
commit 3b15423032
2 changed files with 64 additions and 0 deletions

View File

@ -4,6 +4,7 @@
#
# Copyright (C) 2004-2006 Donald N. Allingham
# Copyright (C) 2017 Paul Franklin
# Copyright (c) 2020 Steve Youngs
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -445,6 +446,9 @@ class DateParser:
self._range = re.compile(
r"(bet|bet.|between)\s+(?P<start>.+)\s+and\s+(?P<stop>.+)",
re.IGNORECASE)
self._quarter = re.compile(
r"[qQ](?P<quarter>[1-4])\s+(?P<year>.+)",
re.IGNORECASE)
self._modifier = re.compile(r'%s\s+(.*)' % self._mod_str,
re.IGNORECASE)
self._modifier_after = re.compile(r'(.*)\s+%s' % self._mod_after_str,
@ -836,6 +840,31 @@ class DateParser:
return 1
return 0
def match_quarter(self, text, cal, ny, qual, date):
"""
Try matching calendar quarter date.
On success, set the date and return 1. On failure return 0.
"""
match = self._quarter.match(text)
if match:
quarter = self._get_int(match.group('quarter'))
text_parser = self.parser[cal]
(text, bc) = self.match_bce(match.group('year'))
start = self._parse_subdate(text, text_parser, cal)
if (start == Date.EMPTY and text != "") or (start[0] != 0) or (start[1] != 0): # reject dates where the day or month have been set
return 0
if bc:
start = self.invert_year(start)
stop_month = quarter * 3
stop_day = _max_days[stop_month - 1] # no need to worry about leap years since no quarter ends in February
date.set(qual, Date.MOD_RANGE, cal, (1, stop_month - 2, start[2], start[3]) + (stop_day, stop_month, start[2], start[3]), newyear=ny)
return 1
return 0
def match_bce(self, text):
"""
Try matching BCE qualifier.
@ -923,6 +952,8 @@ class DateParser:
return
if self.match_range(text, cal, newyear, qual, date):
return
if self.match_quarter(text, cal, newyear, qual, date):
return
(text, bc) = self.match_bce(text)
if self.match_modifier(text, cal, newyear, qual, bc, date):

View File

@ -77,6 +77,39 @@ class DateParserTest(unittest.TestCase):
self.assert_map_key_val(self.parser.calendar_to_int, 'юлианский', Date.CAL_JULIAN)
self.assert_map_key_val(self.parser.calendar_to_int, 'ю', Date.CAL_JULIAN)
def test_quarter_1(self):
date = self.parser.parse('q1 1900')
self.assertTrue(date.is_equal(self.parser.parse('Q1 1900')))
self.assertEqual(date.get_ymd(), (1900, 1, 1))
self.assertEqual(date.get_stop_ymd(), (1900, 3, 31))
self.assertEqual(date.get_modifier(), Date.MOD_RANGE)
def test_quarter_2(self):
date = self.parser.parse('q2 1900')
self.assertTrue(date.is_equal(self.parser.parse('Q2 1900')))
self.assertEqual(date.get_ymd(), (1900, 4, 1))
self.assertEqual(date.get_stop_ymd(), (1900, 6, 30))
self.assertEqual(date.get_modifier(), Date.MOD_RANGE)
def test_quarter_3(self):
date = self.parser.parse('q3 1900')
self.assertTrue(date.is_equal(self.parser.parse('Q3 1900')))
self.assertEqual(date.get_ymd(), (1900, 7, 1))
self.assertEqual(date.get_stop_ymd(), (1900, 9, 30))
self.assertEqual(date.get_modifier(), Date.MOD_RANGE)
def test_quarter_4(self):
date = self.parser.parse('q4 1900')
self.assertTrue(date.is_equal(self.parser.parse('Q4 1900')))
self.assertEqual(date.get_ymd(), (1900, 10, 1))
self.assertEqual(date.get_stop_ymd(), (1900, 12, 31))
self.assertEqual(date.get_modifier(), Date.MOD_RANGE)
def test_quarter_quality_calendar(self):
date = self.parser.parse('calc q1 1900 (julian)')
self.assertEqual(date.get_quality(), Date.QUAL_CALCULATED)
self.assertEqual(date.get_calendar(), Date.CAL_JULIAN)
class Test_generate_variants(unittest.TestCase):
def setUp(self):
from .. import _datestrings