I've implemented a date class, which calculates the next day's date and the previous day's date. eg. if today is 3/26/2022 (MM/DD/YYYY) then my method nextday gives 3/27/2022. However, instead of returning a string, I am trying to return an instance but it's not working properly. It's calculating the day correctly but changes the original instance. This is my class:
class Date:
"""
Assigning class arguments
"""
min_year = 1800
dow_jan1 = "Wednesday"
def __init__(self,month=1,day=1,year=min_year):
"""
Assigning instance arguments and checking the validity of dates.
If Not valid then an Exception is raised.
"""
self.c_month = month
self.c_day = day
self.c_year = year
if self.c_year < self.min_year:
raise Exception("Invalid Year")
elif self.c_month <1 or self.c_month > 12:
raise Exception("Invalid Month")
elif self.c_day<1 or self.c_day > 31:
raise Exception("Invalid Day")
else:
if self.c_month == 2:
if self.year_is_leap(self.c_year):
if self.c_day<1 or self.c_day > 29:
raise Exception("Invalid Day")
else:
if self.c_day<1 or self.c_day > 28:
raise Exception("Invalid Day")
else:
months_31_days = [1,3,5,7,8,10,12]
if self.c_month in months_31_days:
if self.c_day<1 or self.c_day > 31:
raise Exception("Invalid Day")
else:
if self.c_day<1 or self.c_day > 30:
raise Exception("Invalid Day")
def year_is_leap(self,year=None):
"""
Finds if a year is Leap or not
Parameters:
year : takes a year which is to be checked
however if a year is not provided then the instance argument year (self.c_year)
is set as default value
"""
if year is None:
year = self.c_year
if (year % 4) == 0:
if (year % 100) == 0:
if (year % 400) == 0:
return True
else:
return False
else:
return True
else:
return False
def __str__(self):
"""
returns the date in suitable format
eg. 2/14/1900 => February 14, 1900
"""
months = {1:"January",2:"February",3:"March",4:"April",
5:"May",6:"June",7:"July",8:"August",9:"September",
10:"October",11:"November",12:"December"}
return "{} {}, {}".format(months[self.c_month],self.c_day,self.c_year)
def nextday(self):
"""
Returns next date in date object
"""
leap_year = self.year_is_leap(self.c_year)
#print(leap_year)
if self.c_month in (1, 3, 5, 7, 8, 10, 12):
month_length = 31
elif self.c_month == 2:
if leap_year:
month_length = 29
else:
month_length = 28
else:
month_length = 30
if self.c_day < month_length:
self.c_day = 1
else:
self.c_day = 1
if self.c_month == 12:
self.c_month = 1
self.c_year = 1
else:
self.c_month = 1
print("The next date is [mm-dd-yyyy] %d-%d-%d." % (self.c_month, self.c_day,self.c_year))
return self #Date(self.c_month,self.c_day,self.c_year) #Date #self.__class__()
```
I've tried to return `self`, `Date()`, `Date(self.c_month,self.c_day,self.c_year)` and `self.__class__()`, however none of it worked.
When I run:
firstdate = Date(1,1,Date.min_year) print(firstdate) print("The date after ", firstdate, "is", firstdate.nextday())
I am getting the output:
January 1, 1800 The next date is [mm-dd-yyyy] 1-2-1800. The date after January 2, 1800 is January 2, 1800
CodePudding user response:
The most straightforward solution will be creating a new instance of Date
with same values as self
(basically copy it) and work with it, not changing self
:
class Date:
# other methods here
def nextday(self):
"""
Returns next date in date object
"""
new_date = Date(self.c_month, self.c_day, self.c_year)
is_leap_year = new_date.year_is_leap(new_date.c_year)
if new_date.c_month in {1, 3, 5, 7, 8, 10, 12}:
month_length = 31
elif new_date.c_month == 2:
month_length = 28 is_leap_year
else:
month_length = 30
if new_date.c_day < month_length:
new_date.c_day = 1
else:
new_date.c_day = 1
if new_date.c_month == 12:
new_date.c_month = 1
new_date.c_year = 1
else:
new_date.c_month = 1
print("The next date is [mm-dd-yyyy] %d-%d-%d." % (new_date.c_month, new_date.c_day,new_date.c_year))
return new_date
You could also implement some convenience methods (e.g. .copy
to copy the date or __format__
to print the date, but that's out of question scope)
CodePudding user response:
The problem is that you change the object attributes. For example on nextday
method, you write self.c_day = 1
, you are changing the object itself.
Instead, if you want to return a new Date, you need to write c_day = 1
then return Date(c_month, c_day, c_year)