17.2 Objektorientierte Datumsverwaltung – datetime
Das Modul datetime ist im Vergleich zum time-Modul abstrakter und durch seine eigenen Zeit- und Datumstypen auch angenehmer zu benutzen.
Es werden vier Datentypen zur Verfügung gestellt, die wir einzeln besprechen.
Die Datentypen von datetime | Abschnitt | |
---|---|---|
date | ein Datentyp zum Speichern von Datumsangaben | 17.2.1 |
time | Speichert Zeitpunkte an einem Tag. | 17.2.2 |
datetime |
Die Kombination aus datetime.date und datetime.time zum Speichern von Zeitpunkten, die sowohl ein Datum als auch eine Uhrzeit umfassen. Der Datentyp datetime.datetime ist der wichtigste des Moduls datetime. |
17.2.3 |
timedelta | Es ist möglich, Differenzen zwischen datetime.date- und auch datetime.datetime-Instanzen zu bilden. Die Ergebnisse solcher Subtraktionen sind datetime.timedelta-Objekte. | 17.2.4 |
17.2.1 datetime.date
Eine datetime.date-Instanz beschreibt einen Tag auf der Zeitachse, indem das Jahr, der Monat und der Tag im Monat in den Attributen year, month und day gespeichert werden.
Im einfachsten Fall erzeugt man eine datetime.date-Instanz durch die Angabe dieser drei Werte.
datetime.date(year, month, day)
>>> d = datetime.date(1995, 3, 28)
>>> d
datetime.date(1995, 3, 28)
Beim Monat entspricht die 3 dem März, sodass nur Werte ab 1 zulässig sind. Der Konstruktor prüft außerdem, ob das übergebene Datum gültig ist, und wirft bei ungültigen Daten einen ValueError. Beispielsweise war das Jahr 1996 im Gegensatz zum Jahr 1995 ein Schaltjahr.
>>> datetime.date(1996, 2, 29)
datetime.date(1996, 2, 29)
>>> datetime.date(1995, 2, 29)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: day is out of range for month
Mit datetime.date.today() wird eine datetime.date-Instanz erzeugt, die den aktuellen Tag repräsentiert, und um eine datetime.date-Instanz aus einem Unix-Timestamp zu erzeugen, dient die Klassenmethode datetime.date.fromtimestamp.
>>> datetime.date.today()
datetime.date(2017, 3, 9)
>>> datetime.date.fromtimestamp(0)
datetime.date(1970, 1, 1)
Tabelle 17.6 listet die wichtigsten Methoden für den Umgang mit datetime.date-Instanzen auf.
Methode | Beschreibung |
---|---|
ctime() | Erzeugt einen String, der den von der datetime. date-Instanz beschriebenen Tag im Format 'Tue Oct 23 00:00:00 1989' angibt. |
isoformat() | Wandelt die datetime.date-Instanz in einen String der Form "YYYY-MM-DD" um. |
replace({year, month, day}) | Erzeugt eine neue datetime.date-Instanz aus einer bestehenden, indem einzelne Elemente ersetzt werden. |
strftime(format) | Wandelt die datetime.date-Instanz gemäß einer Formatbeschreibung in einen String um (siehe time.strftime in Abschnitt 17.1.2). |
timetuple() | Erzeugt eine time.struct_time-Instanz, die dem Datum der datetime.date-Instanz entspricht. |
weekday() | Gibt den Tag innerhalb der Woche zurück. Dabei entspricht 0 dem Montag und 6 dem Sonntag. |
17.2.2 datetime.time
Objekte des Typs datetime.time dienen dazu, Tageszeiten anhand von Stunde, Minute, Sekunde und auch Mikrosekunde zu verwalten.
Eine datetime.time-Instanz besitzt die Attribute hour, minute, second und microsecond für die Stunde, Minute, Sekunde und Mikrosekunde seit Tagesbeginn. Jedes dieser Attribute kann dem Konstruktor übergeben werden, wobei der Standardwert jeweils 0 ist.
datetime.time([hour, minute, second, microsecond])
>>> datetime.time(2, 30, 25)
datetime.time(2, 30, 25)
>>> datetime.time(minute=10)
datetime.time(0, 10)
>>> datetime.time(hour=12, second=36, microsecond=123456)
datetime.time(12, 0, 36, 123456)
Tabelle 17.7 gibt Ihnen einen Überblick über die wichtigsten Methoden des Datentyps time.
Methode | Beschreibung |
---|---|
isoformat() | Erzeugt einen String im Format "HH:MM:SS.mmmmmm", der den Zeitpunkt beschreibt. Ist das Attribut microseconds 0, hat der String das Format "HH:MM:SS". |
replace([hour, minute, second, microsecond]) | Erzeugt eine neue time-Instanz aus einer vorhandenen, indem die übergebenen Angaben ersetzt werden. |
strftime(format) | Wandelt eine time-Instanz gemäß der übergebenen Formatbeschreibung in einen String um. Siehe time.strftime in Abschnitt 17.1.2. |
17.2.3 datetime.datetime
Um einen vollständigen Zeitpunkt zu beschreiben, reichen die Fähigkeiten der Datentypen datetime.date und datetime.time einzeln nicht aus, da Zeitangaben in der Regel aus einem Datum und der Uhrzeit an dem jeweiligen Tag bestehen.
Der Datentyp datetime.datetime ist genau das, was sein Name vermuten lässt: ein Typ zum Speichern einer Kombination aus Datum- und Uhrzeitangabe. Er vereint dazu die Fähigkeiten von datetime.date und datetime.time in einem Datentyp.
datetime(year, month, day, [hour, minute, second, microsecond])
Wie schon bei datetime.date und datetime.time werden neue datetime.datetime-Instanzen durch Angabe der jeweiligen Bestandteile des Zeitpunkts erzeugt. Die Parameter haben die gleiche Bedeutung wie die gleichnamigen Elemente der Konstruktoren von date und time in den Abschnitten 17.2.1 und 17.2.2, wobei die optionalen Parameter mit 0 vorbelegt sind.
>>> bescherung = datetime.datetime(1989, 12, 24, 18, 30)
>>> bescherung
datetime.datetime(1989, 12, 24, 18, 30)
Eine datetime-Instanz besitzt für jeden der oben genannten Parameter ein Attribut, sodass sich beispielsweise die Minute und der Monat folgendermaßen auslesen lassen:
>>> bescherung.minute
30
>>> bescherung.month
12
Es gibt noch weitere Klassenmethoden, um komfortabel bestimmte datetime. datetime-Instanzen zu erzeugen.
now() und utcnow()
Mit now() wird eine datetime-Instanz erzeugt, die die aktuelle Lokalzeit speichert, während utcnow() die aktuelle koordinierte Weltzeit zugrunde legt.
>>> datetime.datetime.now()
datetime.datetime(2017, 4, 6, 17, 54, 46, 638458)
>>> datetime.datetime.utcnow()
datetime.datetime(2017, 4, 6, 15, 54, 50, 309061)
fromtimestamp(timestamp) und utcfromtimestamp(timestamp)
Die Methode fromtimestamp erzeugt eine datetime.datetime -Instanz, die den gleichen Zeitpunkt wie der für timestamp übergebene Unix-Zeitstempel in der Lokalzeit des Systems repräsentiert. Bei utcfromtimestamp enthält das Resultat die koordinierte Weltzeit des Zeitstempels.
combine(date, time)
Hiermit wird ein datetime.datetime-Objekt erzeugt, das aus der Kombination von date und time hervorgeht. Der Parameter date muss eine datetime.date-Instanz enthalten, und der Parameter time muss auf ein datetime.time-Objekt verweisen.
Alternativ können Sie für date auch ein datetime.datetime-Objekt übergeben. In diesem Fall wird die in date enthaltene Uhrzeit ignoriert und nur das Datum betrachtet.
strptime(date_string, format)
Interpretiert den String, der als Parameter date_string übergeben wurde, gemäß der Formatbeschreibung aus format als Zeitinformation und gibt ein entsprechendes datetime-Objekt zurück.
Für die Formatbeschreibung gelten die gleichen Regeln wie bei time.strftime in Abschnitt 17.1.2.
Die wichtigsten Methoden einer datetime.datetime-Instanz sind in Tabelle 17.8 zusammengestellt.
Methode | Beschreibung |
---|---|
ctime() | Wandelt eine datetime-Instanz in einen String im Format 'Tue Oct 23 16:03:12 1989' um. |
date() | Gibt ein datetime.date-Objekt zurück, das dem Tag der datetime-Instanz entspricht. |
isoformat([sep]) | Wandelt die datetime-Instanz in einen String im Format "YYYY-MM-DDTHH:MM:SS.mmmmmm" um. |
replace([year, month, day, hour, minute, second, microsecond]) | Erzeugt eine neue datetime-Instanz, die aus der vorhandenen dadurch hervorgeht, dass die übergebenen Werte ersetzt werden. |
strftime(format) |
Wandelt ein datetime-Objekt gemäß einer Formatbeschreibung in einen String um. Das Format ist dabei identisch mit der Funktion time.strftime (siehe Abschnitt 17.1.2). |
time() | Gibt ein datetime.time-Objekt zurück, das der Tageszeit der datetime-Instanz entspricht. |
timetuple() | Erzeugt eine time.struct_time-Instanz, die denselben Zeitpunkt beschreibt wie die datetime-Instanz (siehe Abschnitt 17.1.2). |
weekday() | Gibt den Wochentag als Zahl zurück, wobei Montag den Wert 0 und Sonntag den Wert 6 ergibt. |
17.2.4 datetime.timedelta
Mit Instanzen des Datentyps datetime.timedelta können Zeitspannen beschrieben werden, wie sie beispielsweise entstehen, wenn Sie die Differenz zweier datetime.datetime-Instanzen bilden:
>>> d1 = datetime.datetime(1989, 1, 9, 12, 0, 0)
>>> d2 = datetime.datetime(1989, 2, 10, 20, 15, 0)
>>> delta1 = d2 - d1
>>> delta1
datetime.timedelta(32, 29700)
Dabei speichert eine datetime.timedelta-Instanz die Anzahl der Tage, Sekunden und Mikrosekunden der Zeitspanne getrennt ab. Im Beispiel liegen also 32 Tage und 29700 Sekunden zwischen den beiden Zeitpunkten. Mit den Attributen days, seconds und microseconds kann auf den jeweiligen Anteil der Zeitspanne zugegriffen werden.
>>> delta1.days, delta1.seconds, delta1.microseconds
(32, 29700, 0)
Eine Zeitspanne hat ein Vorzeichen, das angibt, ob die Zeitspanne in Richtung Zukunft oder Vergangenheit zeigt. Im oben genannten Beispiel muss 32 Tage und 29700 Sekunden vom Zeitpunkt d1 aus in die Zukunft gegangen werden, um bei d2 zu landen. Dreht man die Differenz um, ändert sich das Vorzeichen:
>>> delta2 = d1 - d2
>>> delta2
datetime.timedelta(-33, 56700)
Diese Angabe ist so zu verstehen, dass man, ausgehend von d2, erst 33 Tage in Richtung Vergangenheit und dann wieder 56700 Sekunden in Richtung Zukunft gehen muss, um bei d1 herauszukommen.
Auch wenn es auf den ersten Blick nicht offensichtlich ist, beschreiben delta1 und delta2 jeweils die gleiche Dauer, einmal mit negativem und einmal mit positivem Vorzeichen. Dies wird klar, wenn man die Summe der beiden bildet:
>>> delta1 + delta2
datetime.timedelta(0)
Dieses Verhalten ist dadurch begründet, dass die Sekunden- und Mikrosekundenangaben bei datetime.timedelta-Instanzen immer positiv sind. Einzig die Angabe des Tages kann ein negatives Vorzeichen haben.
Ein Tag hat 24*60*60 = 86400 Sekunden. Möchten Sie also 32 Tage und 29700 Sekunden in die Vergangenheit gehen, können Sie genauso gut erst 33 Tage Richtung Vergangenheit gehen und dann das, was Sie dadurch zu viel gegangen sind, wieder ausgleichen. Dieser Überschuss umfasst gerade 6400 - 29700 = 56700 Sekunden.
Damit Sie diese einfache, aber unpraktische Rechnung nicht selbst durchführen müssen, nimmt der Konstruktor von datetime.timedelta Ihnen diese Arbeit ab. Dabei wird die Zeitspanne, die sich als Summe der übergebenen Werte errechnet, in eine datetime.timedelta-Instanz umgerechnet.
timedelta([days, seconds, microseconds, milliseconds, minutes, hours, weeks])
Um beispielsweise wie oben eine datetime.timedelta-Instanz zu erzeugen, die 32 Tage und 29700 Sekunden in die Vergangenheit zeigt, können Sie folgenden Aufruf verwenden:
>>> datetime.timedelta(days=-32, seconds=-29700)
datetime.timedelta(-33, 56700)
Alle Parameter sind optional und haben den Standardwert 0, und es können neben ganzen Zahlen auch Gleitkommazahlen übergeben werden. In diesem Fall werden alle Nachkommateile von days zusammengefasst, und es wird zur nächsten timedelta-Instanz gerundet.
>>> datetime.timedelta(days=0.5)
datetime.timedelta(0, 43200)
Die einzige Methode einer timedelta.timedelta-Instanz ist total_seconds(), mit der eine Zeitspanne in eine Angabe in Sekunden umgerechnet wird. Der Rückgabewert ist eine Gleitkommazahl, sodass auch die Mikrosekundenanteile abgebildet werden können.
>>> delta1 = datetime.timedelta(days=32, seconds=29700)
>>> delta1.total_seconds()
2794500.0
>>> delta2 = datetime.timedelta(days=32, seconds=29700, milliseconds=123)
>>> delta2.total_seconds()
2794500.123
Diese Darstellung in Sekunden lässt sich umkehren, sodass wir aus 2794500.123 wieder die ursprüngliche datetime.timedelta-Instanz erhalten können.
>>> delta2
datetime.timedelta(32, 29700, 123000)
>>> delta3 = datetime.timedelta(seconds=2794500.123)
>>> delta3
datetime.timedelta(32, 29700, 123000)
Folglich kann eine datetime.timedelta-Instanz als einfache Zahl, nämlich als ihr Äquivalent in Sekunden, betrachtet werden. Daher ist es nicht verwunderlich, dass mit datetime.timedelta-Instanzen gerechnet werden kann wie mit Zahlen.
>>> woche = datetime.timedelta(days=7)
>>> tag = woche/7
>>> tag
datetime.timedelta(1)
>>> jahr = 52*woche + tag
>>> jahr
datetime.timedelta(365)
>>> jahr/woche
52.142857142857146
Tabelle 17.9 gibt Ihnen eine Übersicht über die verfügbaren Rechenoperationen für datetime.timedelta-Instanzen.
Operationen (t1,t2 timedelta-Instanzen, i int-Instanz, f float-Instanz) | |
---|---|
t1 + t2 | Bildet die Summe zweier timedelta-Instanzen. |
t1 - t2 | Bildet die Differenz zweier timedelta-Instanzen. |
t1 * i t1 * f |
Erzeugt eine timedelta-Instanz, die i- bzw. f-mal so lang ist wie t1. Ist das Vorzeichen von i bzw. f negativ, dreht sich außerdem die Richtung auf der Zeitachse um. |
t1 / t2 t1 / i t1 / f |
Bildet den Quotienten aus zwei timedelta-Instanzen oder einer timedelta-Instanz und einer Ganz- oder Gleitkommazahl. |
t1 // t2 t1 // i |
wie der Operator /, außer dass zusätzlich abgerundet wird |
t1 % t2 | Liefert den Divisionsrest bei der Division zweier timedelta-Instanzen. |
<, <=, >, >= | Vergleicht zwei timedelta-Instanzen. |
q,r = divmod(t1,t2) | Erzeugt ein Tupel aus q = t1//t2 und r = t1%t2, also dem abgerundeten Quotienten und dem Divisionsrest. |
abs(t1) | Erzeugt eine timedelta-Instanz, die die gleiche Dauer wie t1 beschreibt, aber in Richtung der positiven Zeitachse zeigt. |
17.2.5 Operationen für datetime.datetime und datetime.date
Wie bereits in vorangegangenen Beispielen gezeigt, kann auch mit datetime.date- und datetime.datetime-Instanzen gerechnet werden. Dabei sind Differenzen zwischen zwei datetime.date- bzw. zwei datetime.datetime-Instanzen möglich.
>>> p = datetime.date(1987, 1, 9)
>>> j = datetime.date(1987, 7, 26)
>>> delta1 = j-p
>>> delta1
datetime.timedelta(198)
>>> s = datetime.datetime(1995, 1, 1)
>>> o = datetime.datetime(1995, 5, 4, 12, 00)
>>> delta2 = o-s
>>> delta2
datetime.timedelta(123, 43200)
Das Ergebnis einer solchen Differenz ist eine datetime.timedelta-Instanz. Zeitspannen können wiederum zu Zeitpunkten und Datumsangaben addiert oder davon abgezogen werden.
>>> p + delta1
datetime.date(1987, 7, 26)
>>> o - 2*delta2
datetime.datetime(1994, 8, 30, 12, 0)
Wird eine datetime.timedelta-Instanz zu einer datetime.date-Instanz addiert oder davon abgezogen, wird nur das days-Attribut berücksichtigt.
>>> p + datetime.timedelta(days=5)
datetime.date(1987, 1, 14)
[»] Hinweis
Dadurch, dass das Vorzeichen einer datetime.timedelta-Instanz nur im days-Attribut gespeichert ist, spiegelt sich jeder angefangene Tag in Richtung Vergangenheit dort wider. Deshalb müssen Sie beim Rechnen mit negativen datetime.timedelta-Instanzen aufpassen, wenn Sie mit datetime.date arbeiten.
>>> datum = datetime.date(1995, 3, 15)
>>> dreivierteltag = datetime.timedelta(days=0.75)
>>> dreivierteltag
datetime.timedelta(0, 64800)
>>> m_dreivierteltag = -dreivierteltag
>>> m_dreivierteltag
datetime.timedelta(-1, 21600)
>>> datum - dreivierteltag
datetime.date(1995, 3, 15)
>>> datum + m_dreivierteltag
datetime.date(1995, 3, 14)
Obwohl dreivierteltag und m_dreivierteltag Zeitspannen mit gleicher Dauer beschreiben, wird nur bei Addition von m_dreivierteltag das Datum verändert. Dies liegt daran, dass m_dreivierteltag.days=-1 gilt, während dreivierteltag.days=0 ist.
Vergleichsoperationen für datetime.date und datetime.datetime
Außerdem können datetime.date-Instanzen bzw. datetime.datetime-Instanzen mit den Vergleichsoperatoren < und > sowie <= und >= verglichen werden. Dabei wird dasjenige Datum als »kleiner« betrachtet, das in der Zeit weiter in Richtung Vergangenheit liegt:
>>> datetime.date(1987, 7, 26) < datetime.date(1987, 11, 3)
True
17.2.6 Bemerkung zum Umgang mit Zeitzonen
Python bietet neben den hier beschriebenen Funktionen auch Unterstützung für den Umgang mit verschiedenen Zeitzonen. Dazu können Instanzen der Typen datetime.date, datetime.time und datetime.datetime mit Informationen über die Zeitzone versehen werden, auf die sie sich beziehen.
Nähere Informationen dazu finden Sie in der Onlinedokumentation von Python zum Modul datetime. Dabei spielt die Klasse tzinfo eine zentrale Rolle.