Replaced the PeriodSpecification object-based utility with the get_spec function-based utility, for simplicity.

This commit is contained in:
依瑪貓 2023-03-09 19:30:36 +08:00
parent 7ad3f9e0cb
commit 4432484acd
2 changed files with 86 additions and 84 deletions

View File

@ -27,7 +27,7 @@ from datetime import date, timedelta
from accounting.locale import gettext from accounting.locale import gettext
from .description import get_desc from .description import get_desc
from .parser import parse_spec from .parser import parse_spec
from .specification import PeriodSpecification from .specification import get_spec
class Period: class Period:
@ -90,7 +90,7 @@ class Period:
:return: None. :return: None.
""" """
self.spec = PeriodSpecification(self.start, self.end).spec self.spec = get_spec(self.start, self.end)
self.desc = get_desc(self.start, self.end) self.desc = get_desc(self.start, self.end)
if self.start is None or self.end is None: if self.start is None or self.end is None:
return return

View File

@ -20,99 +20,101 @@
from datetime import date, timedelta from datetime import date, timedelta
class PeriodSpecification: def get_spec(start: date | None, end: date | None) -> str:
"""The period specification composer.""" """Returns the period specification.
def __init__(self, start: date | None, end: date | None):
"""Constructs the period specification composer.
:param start: The start of the period. :param start: The start of the period.
:param end: The end of the period. :param end: The end of the period.
"""
self.__start: date | None = start
self.__end: date | None = end
self.spec: str = self.__get_spec()
def __get_spec(self) -> str:
"""Returns the period specification.
:return: The period specification. :return: The period specification.
""" """
if self.__start is None and self.__end is None: if start is None and end is None:
return "-" return "-"
if self.__end is None: if end is None:
return self.__get_since_spec() return __get_since_spec(start)
if self.__start is None: if start is None:
return self.__get_until_spec() return __get_until_spec(end)
try: try:
return self.__get_year_spec() return __get_year_spec(start, end)
except ValueError: except ValueError:
pass pass
try: try:
return self.__get_month_spec() return __get_month_spec(start, end)
except ValueError: except ValueError:
pass pass
return self.__get_day_spec() return __get_day_spec(start, end)
def __get_since_spec(self) -> str:
def __get_since_spec(start: date) -> str:
"""Returns the period specification without the end day. """Returns the period specification without the end day.
:param start: The start of the period.
:return: The period specification without the end day :return: The period specification without the end day
""" """
if self.__start.month == 1 and self.__start.day == 1: if start.month == 1 and start.day == 1:
return self.__start.strftime("%Y-") return start.strftime("%Y-")
if self.__start.day == 1: if start.day == 1:
return self.__start.strftime("%Y-%m-") return start.strftime("%Y-%m-")
return self.__start.strftime("%Y-%m-%d-") return start.strftime("%Y-%m-%d-")
def __get_until_spec(self) -> str:
def __get_until_spec(end: date) -> str:
"""Returns the period specification without the start day. """Returns the period specification without the start day.
:param end: The end of the period.
:return: The period specification without the start day :return: The period specification without the start day
""" """
if self.__end.month == 12 and self.__end.day == 31: if end.month == 12 and end.day == 31:
return self.__end.strftime("-%Y") return end.strftime("-%Y")
if (self.__end + timedelta(days=1)).day == 1: if (end + timedelta(days=1)).day == 1:
return self.__end.strftime("-%Y-%m") return end.strftime("-%Y-%m")
return self.__end.strftime("-%Y-%m-%d") return end.strftime("-%Y-%m-%d")
def __get_year_spec(self) -> str:
def __get_year_spec(start: date, end: date) -> str:
"""Returns the period specification as a year range. """Returns the period specification as a year range.
:param start: The start of the period.
:param end: The end of the period.
:return: The period specification as a year range. :return: The period specification as a year range.
:raise ValueError: The period is not a year range. :raise ValueError: The period is not a year range.
""" """
if self.__start.month != 1 or self.__start.day != 1 \ if start.month != 1 or start.day != 1 \
or self.__end.month != 12 or self.__end.day != 31: or end.month != 12 or end.day != 31:
raise ValueError raise ValueError
if self.__start.year == self.__end.year: start_spec: str = start.strftime("%Y")
return "%04d" % self.__start.year if start.year == end.year:
return "%04d-%04d" % (self.__start.year, self.__end.year) return start_spec
end_spec: str = end.strftime("%Y")
return f"{start_spec}-{end_spec}"
def __get_month_spec(self) -> str:
def __get_month_spec(start: date, end: date) -> str:
"""Returns the period specification as a month range. """Returns the period specification as a month range.
:param start: The start of the period.
:param end: The end of the period.
:return: The period specification as a month range. :return: The period specification as a month range.
:raise ValueError: The period is not a month range. :raise ValueError: The period is not a month range.
""" """
if self.__start.day != 1 or (self.__end + timedelta(days=1)).day != 1: if start.day != 1 or (end + timedelta(days=1)).day != 1:
raise ValueError raise ValueError
if self.__start.year == self.__end.year \ start_spec: str = start.strftime("%Y-%m")
and self.__start.month == self.__end.month: if start.year == end.year and start.month == end.month:
return "%04d-%02d" % (self.__start.year, self.__start.month) return start_spec
return "%04d-%02d-%04d-%02d" % ( end_spec: str = end.strftime("%Y-%m")
self.__start.year, self.__start.month, return f"{start_spec}-{end_spec}"
self.__end.year, self.__end.month)
def __get_day_spec(self) -> str:
def __get_day_spec(start: date, end: date) -> str:
"""Returns the period specification as a day range. """Returns the period specification as a day range.
:param start: The start of the period.
:param end: The end of the period.
:return: The period specification as a day range. :return: The period specification as a day range.
:raise ValueError: The period is a month or year range. :raise ValueError: The period is a month or year range.
""" """
if self.__start == self.__end: start_spec: str = start.strftime("%Y-%m-%d")
return "%04d-%02d-%02d" % ( if start == end:
self.__start.year, self.__start.month, self.__start.day) return start_spec
return "%04d-%02d-%02d-%04d-%02d-%02d" % ( end_spec: str = end.strftime("%Y-%m-%d")
self.__start.year, self.__start.month, self.__start.day, return f"{start_spec}-{end_spec}"
self.__end.year, self.__end.month, self.__end.day)