Wie kann ich die Zeit für ein DateTime-Objekt in Python abschneiden?

251

Was ist eine klassische Methode, um ein Python-Datum / Uhrzeit-Objekt abzuschneiden?

In diesem speziellen Fall auf den Tag. Stellen Sie also im Grunde Stunde, Minute, Sekunden und Mikrosekunden auf 0 ein.

Ich möchte, dass die Ausgabe auch ein Datum / Uhrzeit-Objekt ist, keine Zeichenfolge.

Kyle Brandt
quelle

Antworten:

376

Ich denke, das ist was du suchst ...

>>> import datetime
>>> dt = datetime.datetime.now()
>>> dt = dt.replace(hour=0, minute=0, second=0, microsecond=0) # Returns a copy
>>> dt
datetime.datetime(2011, 3, 29, 0, 0)

Aber wenn Sie sich wirklich nicht für den zeitlichen Aspekt der Dinge interessieren, sollten Sie wirklich nur dateObjekte herumreichen ...

>>> d_truncated = datetime.date(dt.year, dt.month, dt.day)
>>> d_truncated
datetime.date(2011, 3, 29)
Chris W.
quelle
14
Mit einem zeitzonenabhängigen dt wirft datetime.datetime (dt.year, dt.month, dt.day) die tzinfo-Informationen weg.
ʇsәɹoɈ
1
Wenn Sie nur heute suchen, können Sie auch datetime.date.today ()
galarant
4
Beachten Sie, dass Python 2 und Python 3 docs beide Zustand , dass die replace()Methode zurückgibt ein Datetime - Objekt, so dass die korrekte Beschwörung wäre:dt = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
Brad M
3
OP will datetime, kein dateObjekt (das Sie mit dt.date()call bekommen könnten (kein expliziter Konstruktor nötig)). Die .replace()Methode kann fehlschlagen, wenn datetimeNanosekundenunterstützung hinzugefügt wird . Sie könnten verwenden datetime.combine()statt .
JFS
@chrisw Warum nicht einfach in eine Zeile schreiben datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)?
3kstc
66

Verwenden Sie ein dateNicht-A, datetimewenn Sie sich nicht um die Zeit kümmern.

>>> now = datetime.now()
>>> now.date()
datetime.date(2011, 3, 29)

Sie können eine Datums- und Uhrzeitangabe wie folgt aktualisieren:

>>> now.replace(minute=0, hour=0, second=0, microsecond=0)
datetime.datetime(2011, 3, 29, 0, 0)
Jochen Ritzel
quelle
9
Bei zeitzonenabhängigen Datumsangaben wirft now.date () die tzinfo-Informationen weg.
29sәɹoɈ
1
@ ʇsәɹoɈ: Hier ist, wie Sie die zeitzonenbewusste Mitternacht bekommen können
jfs
34

Vier Jahre später: ein anderer Weg, um zu vermeiden replace

Ich weiß, dass die akzeptierte Antwort von vor vier Jahren funktioniert, aber dies scheint ein bisschen leichter zu sein als die Verwendung von replace:

dt = datetime.date.today()
dt = datetime.datetime(dt.year, dt.month, dt.day)

Anmerkungen

  • Wenn Sie ein datetimeObjekt erstellen, ohne die Zeiteigenschaften an den Konstruktor zu übergeben, erhalten Sie Mitternacht.
  • Wie andere angemerkt haben, wird davon ausgegangen, dass Sie ein Datum / Uhrzeit-Objekt für die spätere Verwendung mit Zeitleisten benötigen.
  • Sie können dies natürlich durch die erste Zeile ersetzen: dt = datetime.datetime.now()
zx81
quelle
20

Sie können ein datetime-Objekt nicht abschneiden, da es unveränderlich ist .

Hier ist jedoch eine Möglichkeit, eine neue Datums- / Uhrzeitangabe mit Feldern von 0 Stunden, Minuten, Sekunden und Mikrosekunden zu erstellen, ohne das ursprüngliche Datum oder tzinfo wegzuwerfen:

newdatetime = now.replace(hour=0, minute=0, second=0, microsecond=0)
ʇSәɹoɈ
quelle
1
+1: Wenn Sie die replaceOption an die erste Stelle setzen, da dies wahrscheinlich das ist, was sie wollen.
S.Lott
Es ist falsch zu verwenden tzinfo=now.tzinfo. Die tzinfoMitternacht kann unterschiedlich sein, z. B. ist der UTC-Versatz um 2012-04-01 00:09:00(9 Uhr morgens ) in der Zeitzone Australien / Melbourne, AEST+10:00aber es ist AEDT+11:00um 2012-04-01 00:00:00(Mitternacht) - an diesem Tag gibt es einen Übergang zum Ende der Sommerzeit. Sie könnten das pytzModul verwenden, um es zu beheben, siehe meine Antwort.
JFS
13

Um eine Mitternacht zu erhalten, die einem bestimmten Datum / Uhrzeit-Objekt entspricht, können Sie die folgende datetime.combine()Methode verwenden :

>>> from datetime import datetime, time
>>> dt = datetime.utcnow()
>>> dt.date()
datetime.date(2015, 2, 3)
>>> datetime.combine(dt, time.min)
datetime.datetime(2015, 2, 3, 0, 0)

Der Vorteil gegenüber der .replace()Methode besteht darin, dass die datetime.combine()Lösung auf Basis auch dann weiter funktioniert, wenn das datetimeModul die Nanosekunden-Unterstützung einführt .

tzinfokann bei Bedarf beibehalten werden, aber der utc-Offset kann um Mitternacht unterschiedlich sein, z. B. aufgrund eines DST-Übergangs, und daher kann eine naive Lösung (Einstellen des Zeitattributs tzinfo) fehlschlagen. Siehe Wie erhalte ich die UTC-Zeit von „Mitternacht“ für eine bestimmte Zeitzone?

jfs
quelle
7

Sie könnten dafür Pandas verwenden (obwohl es für diese Aufgabe Overhead sein könnte). Sie können Rund- , Boden- und Deckenwerte wie für übliche Zahlen und jede Pandas-Frequenz aus Offset-Aliasen verwenden :

import pandas as pd
import datetime as dt

now = dt.datetime.now()
pd_now = pd.Timestamp(now)

freq = '1d'
pd_round = pd_now.round(freq)
dt_round = pd_round.to_pydatetime()

print(now)
print(dt_round)

"""
2018-06-15 09:33:44.102292
2018-06-15 00:00:00
"""
Anton Protopopov
quelle
4

Mit datetime.strftime können Sie den Tag, den Monat, das Jahr ...

Beispiel:

from datetime import datetime
d = datetime.today()

# Retrieves the day and the year
print d.strftime("%d-%Y")

Ausgabe (für heute):

29-2011

Wenn Sie nur den Tag abrufen möchten, können Sie das Tagesattribut wie folgt verwenden:

from datetime import datetime
d = datetime.today()

# Retrieves the day
print d.day

Ausgabe (für heute):

29
Sandro Munda
quelle
Nun, die Sache ist, dass ich dies bereits einmal mache, so dass möglicherweise mehr Overhead entsteht, als nur die Felder für die Stunde min usw. im Datum / Uhrzeit-Objekt festzulegen.
Kyle Brandt
Heh, das ist eine seltsame Art, es zu tun, man kann es tatsächlich einfach tun d.dayusw.
Jochen Ritzel
3

Es gibt eine großartige Bibliothek, mit der Datumsangaben bearbeitet werden können : Delorean

import datetime
from delorean import Delorean
now = datetime.datetime.now()
d = Delorean(now, timezone='US/Pacific')

>>> now    
datetime.datetime(2015, 3, 26, 19, 46, 40, 525703)

>>> d.truncate('second')
Delorean(datetime=2015-03-26 19:46:40-07:00, timezone='US/Pacific')

>>> d.truncate('minute')
Delorean(datetime=2015-03-26 19:46:00-07:00, timezone='US/Pacific')

>>> d.truncate('hour')
Delorean(datetime=2015-03-26 19:00:00-07:00, timezone='US/Pacific')

>>> d.truncate('day')
Delorean(datetime=2015-03-26 00:00:00-07:00, timezone='US/Pacific')

>>> d.truncate('month')
Delorean(datetime=2015-03-01 00:00:00-07:00, timezone='US/Pacific')

>>> d.truncate('year')
Delorean(datetime=2015-01-01 00:00:00-07:00, timezone='US/Pacific')

und wenn Sie den Datum / Uhrzeit-Wert zurückerhalten möchten:

>>> d.truncate('year').datetime
datetime.datetime(2015, 1, 1, 0, 0, tzinfo=<DstTzInfo 'US/Pacific' PDT-1 day, 17:00:00 DST>)
DmitrySemenov
quelle
es gibt die falsche Zeit zurück (falscher utc-Offset), wenn die Ergebniszeit einen anderen utc-Offset hat, z. B. aufgrund eines DST-Übergangs. Siehe Wie erhalte ich die UTC-Zeit von „Mitternacht“ für eine bestimmte Zeitzone?
JFS
1

Es gibt ein Modul datetime_truncate, das dies für Sie handhabt. Es wird nur datetime.replace aufgerufen.

kyrre
quelle
1

6 Jahre später ... Ich fand diesen Beitrag und ich mochte mehr den numpy Ansatz:

import numpy as np
dates_array = np.array(['2013-01-01', '2013-01-15', '2013-01-30']).astype('datetime64[ns]')
truncated_dates = dates_array.astype('datetime64[D]')

Prost

Matias Thayer
quelle
1
>>> import datetime
>>> dt = datetime.datetime.now()
>>> datetime.datetime.date(dt)
datetime.date(2019, 4, 2)
Markierung
quelle
1

Sie können einfach verwenden

datetime.date.today()

Es ist leicht und gibt genau das zurück, was Sie wollen.

Bordotti
quelle
Die gleiche Antwort wurde schon einmal gegeben, es gibt nichts Neues.
Slfan
Sorry @slfan, aber ich habe keinen Beitrag mit deinem Namen gesehen, auch nicht mit "Suche" im Browser.
Bordotti
1
Nicht von mir, von zx81 vor 3 Jahren. Suche nach datetime.date.today (). Wenn eine Antwort richtig ist, sollten Sie abstimmen und nicht erneut antworten.
Slfan
0

Wenn Sie mit einer Serie vom Typ DateTime arbeiten, gibt es eine effizientere Möglichkeit, diese abzuschneiden, insbesondere wenn das Series-Objekt viele Zeilen enthält.

Sie können die Bodenfunktion verwenden

Wenn Sie es beispielsweise auf Stunden kürzen möchten:

Generieren Sie eine Reihe von Daten

times = pd.Series(pd.date_range(start='1/1/2018 04:00:00', end='1/1/2018 22:00:00', freq='s'))

Wir können es überprüfen, indem wir die Laufzeit zwischen der Ersetzungs- und der Bodenfunktion vergleichen.

%timeit times.apply(lambda x : x.replace(minute=0, second=0, microsecond=0))
>>> 341 ms ± 18.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit times.dt.floor('h')
>>>>2.26 ms ± 451 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Abraham Simpson
quelle
0

Hier ist noch ein anderer Weg, der in eine Zeile passt, aber nicht besonders elegant ist:

dt = datetime.datetime.fromordinal(datetime.date.today().toordinal())
Valentin B.
quelle