@@ -12,11 +12,18 @@ class DateDescriptionUtils:
1212 DATE_FORMAT_YYYY_MM_DD = "%Y-%m-%d"
1313 DATE_FORMAT_DD_MM_YYYY = "%d/%m/%Y"
1414
15+ # Enum name constants
16+ ENUM_VAL_NULL = "NULL"
17+ ENUM_VAL_NOT_NULL = "NOT_NULL"
18+
1519 @staticmethod
1620 def interpret_date (date_field_name : str , date_value : str ) -> str :
1721 """
1822 Interprets a date description and returns a formatted date string (dd/MM/yyyy).
1923 If the date cannot be interpreted, returns the original value.
24+ Args:
25+ date_field_name (str): The name of the date field (for logging purposes).
26+ date_value (str): The date description to interpret. E.g., "2 years ago", "NULL", "15/08/2020".
2027 """
2128 logging .debug (f"interpret_date: { date_field_name } , { date_value } " )
2229 try :
@@ -34,6 +41,9 @@ def convert_description_to_sql_date(
3441 """
3542 Converts a date description to an Oracle TO_DATE SQL string.
3643 Returns None if the date cannot be interpreted.
44+ Args:
45+ which_date (str): A label for the date being converted (for logging purposes). E.g., "start_date", "end_date".
46+ date_description (str): The date description to convert. E.g., "2 years ago", "NULL", "15/08/2020".
3747 """
3848 logging .debug (
3949 f"convert_description_to_sql_date: { which_date } , { date_description } "
@@ -64,10 +74,10 @@ def convert_description_to_sql_date(
6474 # If the date description is in the enum, use the suggested suitable date, plus allow for NULL and NOT NULL
6575 enum_val = DateDescription .by_description_case_insensitive (date_description )
6676 if enum_val is not None :
67- if enum_val .name == "NULL" :
68- return_date_string = "NULL"
69- elif enum_val .name == "NOT_NULL" :
70- return_date_string = "NOT NULL"
77+ if enum_val .name == DateDescriptionUtils . ENUM_VAL_NULL :
78+ return_date_string = DateDescriptionUtils . ENUM_VAL_NULL
79+ elif enum_val .name == DateDescriptionUtils . ENUM_VAL_NOT_NULL :
80+ return_date_string = DateDescriptionUtils . ENUM_VAL_NOT_NULL
7181 else :
7282 return_date = enum_val .suitable_date
7383
@@ -86,6 +96,9 @@ def convert_description_to_local_date(
8696 """
8797 Converts a date description to a Python date object.
8898 Raises ValueError if the description cannot be interpreted.
99+ Args:
100+ which_date (str): A label for the date being converted (for logging purposes). E.g., "start_date", "end_date".
101+ date_description (str): The date description to convert. E.g., "2 years ago", "NULL", "15/08/2020".
89102 """
90103 logging .debug (
91104 f"convert_description_to_local_date: { which_date } , { date_description } "
@@ -123,7 +136,10 @@ def convert_description_to_local_date(
123136 # Handle enum-based descriptions
124137 enum_val = DateDescription .by_description_case_insensitive (date_description )
125138 if enum_val is not None :
126- if enum_val .name in ["NULL" , "NOT_NULL" ]:
139+ if enum_val .name in [
140+ DateDescriptionUtils .ENUM_VAL_NULL ,
141+ DateDescriptionUtils .ENUM_VAL_NOT_NULL ,
142+ ]:
127143 raise ValueError (f"Cannot convert '{ date_description } ' to a date." )
128144 if enum_val .suitable_date is not None :
129145 return enum_val .suitable_date
@@ -132,10 +148,21 @@ def convert_description_to_local_date(
132148
133149 @staticmethod
134150 def _is_relative_date (date_description , words , suffix ):
151+ """Checks if the date description is a relative date ending with the specified suffix.
152+ Args:
153+ date_description (str): The full date description string.
154+ words (list): The split words of the date description.
155+ suffix (str): The suffix to check for ("ago" or "ahead").
156+ """
135157 return date_description .endswith (f" { suffix } " ) and len (words ) == 3
136158
137159 @staticmethod
138160 def _calculate_relative_date (words , is_ago ):
161+ """Calculates the date based on the relative description.
162+ Args:
163+ words (list): The split words of the date description. E.g., ["2", "years", "ago"].
164+ is_ago (bool): Whether the date is in the past (True) or future (False).
165+ """
139166 if not words [0 ].isdigit ():
140167 raise ValueError (f"Invalid period number in '{ ' ' .join (words )} '" )
141168 number_of_periods = int (words [0 ])
@@ -151,6 +178,11 @@ def _calculate_relative_date(words, is_ago):
151178
152179 @staticmethod
153180 def _get_delta_days (number_of_periods , period_type ):
181+ """Returns the number of days corresponding to the given period type and number.
182+ Args:
183+ number_of_periods (int): The number of periods (e.g., 2).
184+ period_type (str): The type of period (e.g., "years", "months", "weeks", "days").
185+ """
154186 if period_type in ["year" , "years" ]:
155187 return number_of_periods * 365
156188 if period_type in ["month" , "months" ]:
@@ -168,6 +200,12 @@ def convert_description_to_string_date(
168200 """
169201 Converts a date description to a formatted date string.
170202 Raises ValueError if the description cannot be interpreted.
203+ Args:
204+ which_date (str): A label for the date being converted (for logging purposes). E.g., "start_date", "end_date".
205+ date_description (str): The date description to convert. E.g., "2 years ago", "NULL", "15/08/2020".
206+ date_format (str): The desired output date format. E.g., "%d/%m/%Y".
207+ Returns:
208+ str: The formatted date string.
171209 """
172210 logging .debug (
173211 f"convert_description_to_string_date: { which_date } , { date_description } , { date_format } "
@@ -181,6 +219,11 @@ def convert_description_to_string_date(
181219 def is_valid_date (date_str : str , date_format : str ) -> bool :
182220 """
183221 Checks if the given string is a valid date in the specified format.
222+ Args:
223+ date_str (str): The date string to validate.
224+ date_format (str): The format to validate against. E.g., "%d/%m/%Y".
225+ Returns:
226+ bool: True if the string is a valid date, False otherwise.
184227 """
185228 try :
186229 datetime .strptime (date_str , date_format )
0 commit comments