Merge pull request #1056 from stevenyoungs/dateparser_quarter
This commit is contained in:
		@@ -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):
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user