I was having a ValueError
every time I tried to pass a date whose years are not 4 digits to some function of the datetime
module, in this case the operation to be performed is to add or subtract days
import datetime
def add_or_subtract_days(datestr, days, operation):
if operation == "add" : input_text = (datetime.datetime.strptime(datestr, "%Y-%m-%d") datetime.timedelta(days=int(days))).strftime('%Y-%m-%d')
elif operation == "subtract" : input_text = (datetime.datetime.strptime(datestr, "%Y-%m-%d") - datetime.timedelta(days=int(days))).strftime('%Y-%m-%d')
return input_text
input_text = add_or_subtract_days("2023-01-20", "5", "add")
print(repr(input_text)) # ---> '2023-01-25'
input_text = add_or_subtract_days("999-12-27", "5", "add")
print(repr(input_text)) # ---> ValueError: time data '999-12-27' does not match format '%Y-%m-%d'
input_text = add_or_subtract_days("12023-01-20", "5", "add")
print(repr(input_text)) # ---> ValueError: time data '12023-01-20' does not match format '%Y-%m-%d'
Something that occurred to me is to identify these problem cases with an exception, and I managed to extract the number of years. Perhaps it will help me to operate with it in some way, so that it does not generate problems when adding or subtracting days with datetime. You also have to take into account that when adding or subtracting days, you can also change the number of the month and the number of the year, which is a very important factor to consider and is giving me a lot of problems since I don't have much idea how to solve it.
import datetime, re
def add_or_subtract_days(datestr, days, operation):
try:
if operation == "add" : input_text = (datetime.datetime.strptime(datestr, "%Y-%m-%d") datetime.timedelta(days=int(days))).strftime('%Y-%m-%d')
elif operation == "subtract" : input_text = (datetime.datetime.strptime(datestr, "%Y-%m-%d") - datetime.timedelta(days=int(days))).strftime('%Y-%m-%d')
except ValueError:
m1 = re.search( r"(?P<year>\d*)-(?P<month>\d{2})-(?P<startDay>\d{2})", datestr, re.IGNORECASE, )
if m1:
ref_year = str(m1.groups()[0])
print(ref_year)
return input_text
I've already managed to extract the year number, however I can't think of what kind of algorithm I should use to truncate the year to a value with the amount that supports the datetime and then join it (keeping logic) to get the correct date though does not have a 4-digit year
for example...
"212023-12-30"
2 days
--> 21
2023-12-30
2 days
--> 21 2024-01-01
--> 212024-01-01
"12023-12-30"
2 days
--> 1
2023-12-30
2 days
--> 1 2024-01-01
--> 12024-01-01
"999-12-30"
2 days
--> 0
999-12-30
2 days
--> 0 1000-01-01
--> 1000-01-01
"999-11-30"
5 days
--> 0
999-11-30
5 days
--> 0 999-11-05
--> 999-11-05
"99-12-31"
5 days
--> 00
99-12-31
5 days
--> 00 100-01-05
--> 100-01-05
CodePudding user response:
Having a '99' as a year is problematic since Python wont know what date you actually want (2099 or 1999 or 3099 etc).
The %Y is telling python that you want to parse a date that is 4 characters. you can use %y for just 2:
>>> datetime.datetime.strptime('99-12-29', '%y-%m-%d')
datetime.datetime(1999, 12, 29, 0, 0)
>>>
if you want the year 0099
then you need 4 characters:
>>> datetime.datetime.strptime('0099-12-29', '%Y-%m-%d')
datetime.datetime(99, 12, 29, 0, 0)
>>>
From Comments: Its easier to take all the dates and move them to 4 characters and then parse the time:
def add_or_subtract_days(datestr, days, operation):
to_add = 4 - len(datestr[:datestr.find('-')])
datestr = ('0' * to_add) datestr
if operation == "add":
input_text = (datetime.datetime.strptime(datestr, "%Y-%m-%d") datetime.timedelta(days=int(days))).strftime('%Y-%m-%d')
elif operation == "subtract":
input_text = (datetime.datetime.strptime(datestr, "%Y-%m-%d") - datetime.timedelta(days=int(days))).strftime('%Y-%m-%d')
return input_text
first two lines we calculate how many 0 we need to add to the start of the date. second line is a little known python hackery where we can multiply a string with an int to get a string of repeating characters of n. This obviously doesnt work for dates that are larger than 9999 since python MAXYEAR is 9999.
input_text = add_or_subtract_days("2023-01-20", "5", "add")
print(repr(input_text)) # ---> '2023-01-25'
input_text = add_or_subtract_days("999-12-27", "5", "add")
print(repr(input_text)) # ---> '1000-01-01'
input_text = add_or_subtract_days("99-01-20", "5", "add")
print(repr(input_text)) # ---> '0099-01-25'