Hello
I want to try to calculate the age in years but in de output i get 1 day instead of 1 year
from datetime import datetime, date
class persoon:
def __init__(self, naam, sekse, geboortedatum):
self.naam = naam
self.sekse = sekse
self.geboortedatum = datetime.strptime(geboortedatum, '%d-%m-%Y').date()
def getNaam(self):
return self.naam
def getGebDatum(self):
return self.geboortedatum
def isVrouw(self):
if self.sekse == "V":
return True
else:
return False
def isMan(self):
if self.sekse == "M":
return True
else:
return False
def leeftijd(self):
today = date.today()
age = (today - self.geboortedatum) // 365
return age
p1 = persoon("John", "M", "24-04-2022")
print(p1.getNaam(), p1.leeftijd())
Output
John 1 day, 0:00:00
What I want is
John 1 Year
You can't do this. A normal year has
364
days and a leap year has
365
days.
Calculate instead the years and not the timedelta.
import datetime
import calendar
# today = datetime.date.today()
today = datetime.date(2000, 2, 29)
bday = datetime.date(1984, 2, 29)
years = today.year - bday.year
# correct the bday, if it's the 29th february and today is not a leap yaar
if bday.month == 2 and bday.day == 29 and not calendar.isleap(today.year):
bday = datetime.date(bday.year, 3, 1)
# check if today earlier than birthday
if (today.month, today.day) < (bday.month, bday.day):
years -= 1
# today it's not the birthday, so one year lesser
print(years)
Improvement of your class:
class Persoon:
def __init__(self, naam, sekse, geboortedatum):
self._naam = naam
self._sekse = sekse
self._geboortedatum = datetime.strptime(geboortedatum, "%d-%m-%Y").date()
@property
def naam(self):
return self._naam
@property
def geb_datum(self):
return self._geboortedatum
@property
def vrouw(self):
return self._sekse == "V"
@property
def man(self):
return self._sekse == "M"
def leeftijd(self, today=None):
today = today or date.today()
years = today.year - self.geb_datum.year
geboortedatum = self.geb_datum
# leap fix 29 feb.
if (
geboortedatum.month == 2
and geboortedatum.day == 29
and not isleap(today.year)
):
geboortedatum = date(geboortedatum.year, 3, 1)
if (today.month, today.day) < (self.geb_datum.month, self.geb_datum.day):
years -= 1
return years
p1 = Persoon("John", "M", "29-2-1980")
# 2023 is not a leap year
print(p1.naam, p1.leeftijd(date(2023, 3, 1)))
The properties are read-only.
leeftijd()
is still a method, but now you can also set today (better for testing).
When i try the Improvement of your class then I get the following erors
3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 20:20:57) [MSC v.1600 64 bit (AMD64)]
Python Type "help", "copyright", "credits" or "license" for more information.
[evaluate Objectgeoriënteerd programmeren_FeedackVraag4a.py]
Traceback (most recent call last):
File "C:\Python\Objectgeoriënteerd programmeren_FeedackVraag4a.py", line 42, in <module>
p1 = Persoon("John", "M", "29-2-1980")
File "C:\Python\Objectgeoriënteerd programmeren_FeedackVraag4a.py", line 5, in <module>
self._geboortedatum = datetime.strptime(geboortedatum, "%d-%m-%Y").date()
builtins.NameError: name 'datetime' is not defined
You still need to import the classes
datetime
and
date
.
Also
calendar.isleap
.
from calendar import isleap
from datetime import datetime, date
class Persoon:
def __init__(self, naam, sekse, geboortedatum):
self._naam = naam
self._sekse = sekse
self._geboortedatum = datetime.strptime(geboortedatum, "%d-%m-%Y").date()
@property
def naam(self):
return self._naam
@property
def geb_datum(self):
return self._geboortedatum
@property
def vrouw(self):
return self._sekse == "V"
@property
def man(self):
return self._sekse == "M"
def leeftijd(self, today=None):
today = today or date.today()
years = today.year - self.geb_datum.year
geboortedatum = self.geb_datum
# leap fix 29 feb.
if (
geboortedatum.month == 2
and geboortedatum.day == 29
and not isleap(today.year)
):
geboortedatum = date(geboortedatum.year, 3, 1)
if (today.month, today.day) < (self.geb_datum.month, self.geb_datum.day):
years -= 1
return years
p1 = Persoon("John", "M", "29-2-1980")
# 2023 is not a leap year
print(p1.naam, p1.leeftijd(date(2023, 3, 1)))
Other question, I try to make a sub classes and when there is no argument then value 0
But get the following error
from datetime import datetime, date
class persoon:
def __init__(self, naam, sekse, geboortedatum):
self.naam = naam
self.sekse = sekse
self.geboortedatum = datetime.strptime(geboortedatum, '%d-%m-%Y').date()
def getNaam(self):
return self.naam
def getGebDatum(self):
return self.geboortedatum
def isVrouw(self):
if self.sekse == "V":
return True
else:
return False
def isMan(self):
if self.sekse == "M":
return True
else:
return False
def leeftijd(self):
today = date.today()
age = (today.year - self.geboortedatum.year)
return age
class Docent(persoon):
def __init__(self, naam, sekse, geboortedatum,*Salaris):
if(Salaris==None):
self.Salaris = "0"
else:
self.Salaris = Salaris
d1 = Docent("John", "M", "24-04-2000")
print(d1.naam)
Error:
3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 20:20:57) [MSC v.1600 64 bit (AMD64)]
Python Type "help", "copyright", "credits" or "license" for more information.
[evaluate Objectgeoriënteerd programmeren_FeedackVraag4.py]
Traceback (most recent call last):
File "C:\Python\Objectgeoriënteerd programmeren_FeedackVraag4.py", line 43, in <module>
print(d1.naam)
builtins.AttributeError: 'Docent' object has no attribute 'naam'
When you subclass and the superclass has an __init__ method, the subclass needs to call the __init__ method for the superclass. The best way to do that is use super().
class Docent(persoon):
def __init__(self, naam, sekse, geboortedatum,*Salaris):
super().__init__(naam, seksa, geboortedatum)
if(Salaris==None):
self.Salaris = "0"
else:
self.Salaris = Salaris
You are not handling the optional Salaris argument correctly.
class Docent(persoon):
def __init__(self, naam, sekse, geboortedatum, Salaris=0):
super().__init__(naam, seksa, geboortedatum)
self.Salaris = Salaris
Your __init__() method made Python think Solaris was a list of positional arguments following geboortedatum when what you really want is an argument where the user has to option of providing an argument value, or using the default value.
Great Thanks for your help !!!
Now I get the following error , can you please help me !!
from datetime import datetime, date
class persoon:
def __init__(self, naam, sekse, geboortedatum):
self.naam = naam
self.sekse = sekse
self.geboortedatum = datetime.strptime(geboortedatum, '%d-%m-%Y').date()
def getNaam(self):
return self.naam
def getGebDatum(self):
return self.geboortedatum
def isVrouw(self):
if self.sekse == "V":
return True
else:
return False
def isMan(self):
if self.sekse == "M":
return True
else:
return False
def leeftijd(self):
today = date.today()
age = (today.year - self.geboortedatum.year)
return age
class Docent(persoon):
def __init__(self, naam, sekse, geboortedatum, Salaris=0):
super().__init__(naam, sekse, geboortedatum)
self.Salaris = Salaris
def setSalaris(self, SalarisInput):
self.Salaris = SalarisInput
def getSalaris(self):
return self.Salaris
def VerhoogSalaris(self, percentage):
return self.Salaris * percentage
d1 = Docent("Marcella", "V", "24-04-2000")
print(d1.getNaam(), d1.leeftijd(), d1.isVrouw(),d1.getSalaris())
d1.setSalaris(2500)
print(d1.getSalaris)
d1.verhoogSalaris(5)
print(d1.getSalaris())
Error:
3.4.4 (v3.4.4:737efcadf5a6, Dec 20 2015, 20:20:57) [MSC v.1600 64 bit (AMD64)]
Python Type "help", "copyright", "credits" or "license" for more information.
[evaluate Objectgeoriënteerd programmeren_FeedackVraag5.py]
Marcella 23 True 0
<bound method Docent.getSalaris of <__main__.Docent object at 0x00000000036CA390>>
Traceback (most recent call last):
File "C:\Python\Objectgeoriënteerd programmeren_FeedackVraag5.py", line 52, in <module>
d1.verhoogSalaris(5)
builtins.AttributeError: 'Docent' object has no attribute 'verhoogSalaris'
Read the error message carefully. There is no Docent.verhoogSalaris() method.
Don't do this:
def isMan(self):
if self.sekse == "M":
return True
else:
return False
Do this:
def isMan(self):
return self.sekse == "M"
Think about how to solve the problem. Think about how to translate the solution to code. When the code is written, review and think about your code. In this case, you have a comparison that returns True or False. Does it make sense to check if the comparison is True and then return True? The if-else is extra code. Don't write extra code.
I don't like this either:
def setSalaris(self, SalarisInput):
self.Salaris = SalarisInput
Why did you write this? The user can access the attribute directly. What is added by writing this extra code?
Your age calculation is wrong. If I was born July 6, 2000, am I 23 years old today (April 24, 2023)? Your code says I am. I don't agree. Look at DeaD_EyE's year calculation that takes month and day into account.
Thanks I see it, type error VerhoogSalaris
(Apr-24-2023, 09:46 AM)DeaD_EyE Wrote: [ -> ]A normal year has 364 days and a leap year has 365 days.
Obvious mistake, but nevertheless 365 days in "normal" year and 366 days in leap year.