@desmater: Das ist alles ein wenig widersprüchlich. Wenn Du es ohne zusätzliche Module machen möchtest, dann dürftest Du `datetime` auch nicht für den „grösser”-Vergleich verwenden. Probleme löst man in einer Programmiersprache dadurch, dass man sich die passenden Sprachmittel und Bibliotheken sucht, mit denen man das Problem möglichst einfach und verständlich lösen kann. Das wäre in diesem Fall — also in Python — das `datetime`-Modul aus der Standardbibliothek. Ohne dieses ist das Problem, zumindest wenn man es richtig und fehlerfrei lösen möchte, alles andere als trivial. Zum Thema, rechnen mit Datumswerten ist nicht so leicht wie es auf den ersten Blick scheint, wurde in den einzelnen Beiträgen ja schon einiges verlinkt.
Edit: Sonstige Anmerkungen zum Quelltext:
Die Kommentare über den Funktionen würden besser als DocStrings unter die ``def``-Anweisung geschrieben.
Funktionen die etwas prüfen und einen Wahrheitswert zurück geben haben oft ein Namen der mit `is_` oder `has_` beginnt. Also zum Beispiel `is_leap_year()`. Die Funktion liesse sich auch mit *einem* logischen Ausdruck formulieren, statt mit den ganzen ``if``/``elif`` und literalen Wahrheitswerten.
Bei `get_next_day()` ist der Name des letzten Arguments schlecht gewählt. Statt in einerm Kommentar zu erklären was der Wert bedeutet, hätte man ihn besser `last_day_of_month` oder so ähnlich genannt und sich die Erklärung gespart. Als Argument hätte ich diesen Wert auch nicht übergeben, denn man bekommt ja den Monat und das Jahr übergeben, kann diesen Wert also *in* dieser Funktion berechnen und muss das nicht dem Aufrufer überlassen.
In der `get_days_in_month()`-Funktion werden Daten fast 1:1 wiederholt. Die beiden Sequenzen unterscheiden sich nur in einem Wert und da auch nur um den Wert 1. Ich würde dort die Tage für den Normalfall ermitteln und im Sonderfall, dass es sich um den zweiten Monat in einem Schaltjahr handelt, 1 vom Ergebnis abziehen. Dabei kann man zusätzlich ausnutzen, dass Wahrheitswerte in Python ein Untertyp von ganzen Zahlen sind, und die `True` und `False` den Werten 1 und 0 entsprechen. Man kann also das Ergebnis der Bedingung einfach von der Monatsanzahl abziehen.
Die beiden Daten in `count_days()` als Einzelwerte zu behandeln obwohl immer alle drei zusammen verwendet werden, macht den Quelltext umfangreicher und unübersichtlicher als er sein müsste. Die Namen sind ausserdem schlecht gewählt, denn dass das zweite Datum das *heutige* Datum ist, stimmt ja nur wenn man diese Funktion auch tatsächlich mit dem heutigen Datum aufruft. Die Funktion würde aber auch mit jedem anderen funktionieren. Ebenso egal ist, ob das erste Datum vom Benutzer eingegeben wurde, oder irgendwie anders zustande kam. Die Funktion zählt die Tage von einem Start- zu einem Enddatum.
Der Kommentar bei `get_user_input()` wäre zumindest als Dokumentation für die Funktion nicht so gut, weil die Variablennamen *in* der Funktion für den Aufrufer egal sind.
Das Zerlegen der Komponenten des Datums ist umständlich. Die `split()`-Methode wäre hier viel einfacher.
Den aktuellen Tag in `age_in_days()` über eine Zeichenkettendarstellung der Einzelteile, die dann wieder in Zahlen umgewandelt werden, zu erstellen, ist auch wieder umständlich. Die `time.localtime()`-Funktion liefert diese Komponenten schon als Zahlen.
Eine lokale Variable genau so zu nennen wie die Funktion kann verwirrend werden.
``continue`` am Ende einer Schleife macht keinen Sinn, denn dort hat diese Anweisung keinen Effekt.
Das alles umgesetzt komme ich ungefähr auf so etwas (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf-8
import time
def is_leap_year(year):
"""Checks if the year is a leap year."""
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
def get_days_in_month(month, year):
"""Returns the number of days for the month."""
result = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1]
return result - (month == 2 and is_leap_year(year))
def get_next_day((day, month, year)):
"""Returns the next date after the date the function gets."""
last_day_of_month = get_days_in_month(month, year)
if day < last_day_of_month:
return day + 1, month, year
elif day == last_day_of_month:
if month < 12:
return 1, month + 1, year
else:
return 1, 1, year + 1
def count_days(start_date, end_date):
"""Counts the days from start date to target date."""
days = 0
while start_date != end_date:
start_date = get_next_day(start_date)
days += 1
return days
def get_user_input():
"""Gets the input from user and returns a sequence with day, month, year."""
print 'Enter your date of birth in this notation: dd.mm.yyyy'
user_input = raw_input('Please enter your date of birth: ')
return map(int, user_input.split('.'))
def age_in_days():
"""The main function -> bring all the other functions together."""
today = tuple(reversed(time.localtime()[:3]))
while True:
birth_date = get_user_input()
if today[::-1] > birth_date[::-1]:
return 'Your age in days is: {0} days'.format(
count_days(birth_date, today)
)
print "I'm sorry, but you didn't enter a valid date for your birth!"
print 'Please try again.'
def main():
print age_in_days()
if __name__ == '__main__':
main()