Nächstes Kapitel: Python, Pandas and Timeseries
# invisible
import numpy as np
np.core.arrayprint._line_width = 65
Python, Datum und Zeit
Python Standard-Module für Zeit-Daten
Python bietet reichlich Funktionalität, um mit Datums- und Zeit-Daten umzugehen. Die Standard-Bibliotheken enthalten folgende Module:
time
calendar
datetime
Diese Module bieten Klassen zur Manipulation von simplen und komplexen Datums- und Zeit-Daten.
Speziell die datetime
-Klasse ist sehr wichtig für die Timeseries in Pandas.
Die wichtigsten Module in Python, um mit Zeiten zu arbeiten, sind time
,
calendar
und datetime
.
Das datetime
-Modul bietet diverse Klassen, Methoden und Funktionen für die Arbeit mit Daten, Zeiten und Zeit-Intervallen. Dafür stehen folgende Klassen zur Verfügung:
- Die Instanzen der
date
-Klasse können Daten innerhalb der Jahre zwischen 1 und 9999 abbilden. - Eine Instanz der
datetime
-Klasse besteht sowohl aus dem Datum, als auch aus der Zeit. - Die
time
-Klasse implementiert Zeit-Objekte. - Die
timedelta
-Klasse wird verwendet zur Differenzbildung zwischen zwei Zeit- oder Datums-Objekten. - Die
tzinfo
-Klasse dient der Implementierung von Zeitzonen für Zeit- und Datums-Objekten.
Wir starten mit dem date-Objekt.
Die date-Klasse
from datetime import date
x = date(1993, 12, 14)
print(x)
Wir können Datums-Objekte zwischen dem 01. Januar 0001 und dem 31. Dezember 9999 instanziieren. Über die Attribute min
und max
kann dies ermittelt werden:
from datetime import date
print(date.min)
print(date.max)
Wir können diverse Methoden auf das obige date
-Objekt anwenden. Das proleptische Gregorianische Ordinal liefert die Methode toordinal
. Der proleptische gregorianische Kalender besteht aus der Erweiterung des gregorianischen Kalenders rückwärts über seine Einführung im Jahre 1582 hinaus. In der Ordinalen Numerierung entspricht somit dem Tag 1 der 1. Januar des Jahres 1:
x = date(1, 1, 1) # 1. Januar 1
print(x.toordinal())
x = date(1, 1, 2) # 2. Januar 1
print(x.toordinal())
print(x.today())
print(x.today().toordinal())
Aus einem Ordinal kann das Datum mit der Klassen-Methode fromordinal
wieder herausgerechnet werden:
print(date.fromordinal(726952))
Wenn Sie den Wochentag eines bestimmten Tages wissen möchten, kann dies mit der Methode weekday
berechnet werden. weekday
liefert Zahlen zwischen 0
(Montag) und 6
(Sonntag) zurück.
print(x.weekday())
print(date.today())
Über die Attribute können wir auf den Tag, den Monat und das Jahr eines Date-Objektes zugreifen:
print(x.day)
print(x.month)
print(x.year)
from datetime import time
t = time(15, 6, 23)
print(t)
Die möglichen Zeiten liegen zwischen:
print(time.min)
print(time.max)
Der Zugriff auf Stunde, Minute und Sekunde:
print(t.hour, t.minute, t.second)
Jede Komponente eines Zeit-Objektes kann durch replace()
geändert werden:
t = t.replace(hour=11, minute=59)
print(t)
Wir können einen Datums-String in C-Style generieren, entsprechend der ctime
-Funktion in C:
print(x.ctime())
Die datetime-Klasse
Das datetime
-Modul bietet uns Funktionen und Methoden zur Manipulation von Datums- und Zeit-Objekten. Weiterhin stellt es Funktionalitäten zur Verfügung für arithmetische Operationen für Datums- und Zeit-Objekte, z.B. Addition und Subtraktion. Ein weiterer Fokus der Implementierung liegt auf der Extrahierung von Attributen.
Es gibt zwei Arten von Datums- und Zeit-Objekten:
- naive
- aware
Wenn ein Zeit-Objekt 'naive' ist, enthält es keine Informationen für den Vergleich oder die Lokalisation gegenüber anderen Datums- oder Zeit-Objekten. Die Semantik, falls das 'naive'-Objekt einer bestimmten Zeitzone entspricht (wie beispielsweise UTC, lokale Zeit, etc.), ist in der Logik des Programs verankert.
Auf der anderen Seite hat ein 'aware'-Objekt Informationen über die Zeitzone. Somit kann es gegenüber anderen 'aware'-Objekten lokalisiert werden.
Wie können Sie herausfinden, ob ein datetime-Objekt t
'aware' ist?
t
ist 'aware', wenn t.tzinfo
nicht None ist und t.tzinfo.utcoffset(t)
nicht None ist.
Beide Bedingungen müssen erfüllt sein.
Demgegenüber ist das Objekt t
'naive', wenn t.tzinfo
oder t.tzinfo.utcoffset(t)
None ist.
Erstellen wir ein datetime-Objekt:
from datetime import datetime
t = datetime(2017, 4, 19, 16, 31, 0)
print(t)
t
ist naive, weil folgender Ausdruck True
ist:
print(t.tzinfo == None)
Wir erstellen ein 'aware' datetime-Objekt vom aktuellen Datum. Dafür benötigen wir das Modul pytz
. pytz
ist ein Modul, welches die 'Olsen-Zeitzonen-Datenbank' in Python bereitstellt. Die Olsen-Zeitzonen werden nahezu komplett durch dieses Modul unterstützt.
from datetime import datetime
import pytz
t = datetime.now(pytz.utc)
Wir sehen, dass sowohl t.tzinfo
als auch t.tzinfo.utcoffset(t)
nicht None
sind und t
somit ein 'aware'-Objekt ist:
print(t.tzinfo, t.tzinfo.utcoffset(t))
from datetime import datetime, timedelta as delta
ndays = 15
start = datetime(1991, 4, 30)
dates = [start - delta(days=x) for x in range(0, ndays)]
dates
from datetime import datetime
delta = datetime(1993, 12, 14) - datetime(1991, 4, 30)
print(delta, type(delta))
Das Ergebnis der Subtraktion der beiden datetime
-Objekte ist ein timedelta
-Objekt.
Über das Attribut days
können wir die Tage der Differenz auslesen:
print(delta.days)
t1 = datetime(2017, 1, 31, 14, 17)
t2 = datetime(2015, 12, 15, 16, 59)
delta = t1 - t2
print(delta.days, delta.seconds)
Es ist möglich, ein timedelta
-Objekt von einem anderen datetime
-Objekt zu subtrahieren oder es zu addieren (in Tagen), um ein neues datetime
-Objekt zu berechnen:
from datetime import datetime, timedelta
d1 = datetime(1991, 4, 30)
d2 = d1 + timedelta(10)
print(d2)
print(d2 - d1)
d3 = d1 - timedelta(100)
print(d3)
d4 = d1 - 2 * timedelta(50)
print(d4)
Ebenso können timedelta
-Objekte auch in Tagen und Minuten zu datetime
-Objekten addiert oder voneinander subtrahiert werden:
from datetime import datetime, timedelta
d1 = datetime(1991, 4, 30)
d2 = d1 + timedelta(10,100)
print(d2)
print(d2 - d1)
s = str(d1)
print(s)
Wandlung mit strftime
Der Methodenaufruf datetime.strftime(format)
liefert einen String zurück, welcher die Zeit und das Datum repräsentiert, jedoch durch ein explizites Format bestimmt wird.
Ein komplette Liste von möglichen Formatierungen kann hier (strftime) eingesehen werden:
print(d1.strftime('%Y-%m-%d'))
print("Wochentag: " + d1.strftime('%a'))
print("Wochentag ausgeschrieben: " + d1.strftime('%A'))
# Weekday as a decimal number, where 0 is Sunday
# and 6 is Saturday
print("Wochentag als Dezimalzahl: " + d1.strftime('%w'))
Formatierung von Monaten:
# Day of the month as a zero-padded decimal number.
# 01, 02, ..., 31
print(d1.strftime('%d'))
# Month as locale’s abbreviated name.
# Jan, Feb, ..., Dec (en_US);
# Jan, Feb, ..., Dez (de_DE)
print(d1.strftime('%b'))
# Month as locale’s full name.
# January, February, ..., December (en_US);
# Januar, Februar, ..., Dezember (de_DE)
print(d1.strftime('%B'))
# Month as a zero-padded decimal number.
# 01, 02, ..., 12
print(d1.strftime('%m'))
from datetime import datetime, timedelta
d1 = datetime(1993, 12, 14)
print(d1.strftime('%d %B %Y'))
print("Nur in Zahlen:")
print(d1.strftime('%d/%m/%Y'))
print("Auf US Art:")
print(d1.strftime('%m/%d/%Y'))
print(f"It was a {d1.strftime('%A'):s}!")
Eine häufig gestellte Frage lautet, wie man diese Ausgaben in Landessprache ausgeben kann. Zunächst ist es wichtig, das locale
-Modul zu importieren:
from datetime import datetime, timedelta
import locale
# Umstellung auf Deutsch:
locale.setlocale(locale.LC_ALL, 'de_DE.utf8')
d1 = datetime(1993, 12, 14)
print(d1.strftime('%d. %B %Y'))
print("Nur in Zahlen:")
print(d1.strftime('%d.%m.%Y'))
print(f"Der {d1.strftime('%d.%m.%Y'):s} war ein {d1.strftime('%A'):s}!")
# und nun in Französisch:
locale.setlocale(locale.LC_ALL, 'fr_FR.utf8')
d1 = datetime(1993, 12, 14)
print(d1.strftime('%d %B %Y'))
print("Seulement en nombre:")
print(d1.strftime('%d.%m.%Y'))
print(f"Le {d1.strftime('%d %m %Y'):s} était un {d1.strftime('%A'):s}!")
Anmerkung:
Die länderspezifischen Ausgaben der obigen Beispiele funktionieren nur, falls 'de_DE.utf8' und 'fr_FR.utf8' im Betriebssystem installiert sind. Unter Ubuntu kann man diese wie folgt installieren:
sudo locale-gen fr_FR.UTF-8
und
sudo locale-gen de_DE.UTF-8
from datetime import datetime
t = datetime.strptime("30 12 1999", "%d %m %Y")
print(t)
dt = "2007-03-04T21:08:12"
datetime.strptime( dt, "%Y-%m-%dT%H:%M:%S" )
import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
dt = '12/24/1957 4:03:29 AM'
dt = datetime.strptime(dt, '%m/%d/%Y %I:%M:%S %p')
dt
Auf einer Linux-Maschine können wir einen englischen Datumsstring generieren mit dem Kommando
LC_ALL=en_EN.utf8 date
.
dt = 'Wed Apr 12 20:29:53 CEST 2017'
dt = datetime.strptime(dt, '%a %b %d %H:%M:%S %Z %Y')
print(dt)
Obwohl datetime.strptime()
eine einfache Möglichkeit ist, ein Datum mit einem bekannten Format zu parsen, kann es doch kompliziert sein, für neue Datumsformate jedes Mal eine neue Spezifikation zu erstellen.
Für das Parsen ist die Nutzung der Methode dateutil.parser
besser:
from dateutil.parser import parse
parse('2011-01-03')
parse('Wed Apr 12 20:29:53 CEST 2017')
Nächstes Kapitel: Python, Pandas and Timeseries