Jaki jest elegancki sposób na obcięcie obiektu Python datetime?
W tym konkretnym przypadku do dnia. Więc w zasadzie ustaw godzinę, minutę, sekundy i mikrosekundy na 0.
Chciałbym, aby wynik był również obiektem typu data-godzina, a nie ciągiem.
Jaki jest elegancki sposób na obcięcie obiektu Python datetime?
W tym konkretnym przypadku do dnia. Więc w zasadzie ustaw godzinę, minutę, sekundy i mikrosekundy na 0.
Chciałbym, aby wynik był również obiektem typu data-godzina, a nie ciągiem.
Odpowiedzi:
Myślę, że tego właśnie szukasz ...
>>> 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)
Ale jeśli tak naprawdę nie zależy ci na aspekcie czasowym rzeczy, powinieneś naprawdę tylko omijać date
przedmioty ...
>>> d_truncated = datetime.date(dt.year, dt.month, dt.day)
>>> d_truncated
datetime.date(2011, 3, 29)
datetime
, a nie date
obiekt (że można uzyskać za pomocą dt.date()
wywołania (nie trzeba używać jawnego konstruktora)). .replace()
Metoda może zawieść jeśli datetime
dodaje wsparcie nanosekund . Możesz zamiast tego użyćdatetime.combine()
.
datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
?
Użyj date
nie, datetime
jeśli nie zależy ci na czasie.
>>> now = datetime.now()
>>> now.date()
datetime.date(2011, 3, 29)
Możesz zaktualizować datę / godzinę w ten sposób:
>>> now.replace(minute=0, hour=0, second=0, microsecond=0)
datetime.datetime(2011, 3, 29, 0, 0)
replace
Wiem, że przyjęta odpowiedź sprzed czterech lat działa, ale wydaje się to nieco lżejsze niż używanie replace
:
dt = datetime.date.today()
dt = datetime.datetime(dt.year, dt.month, dt.day)
Notatki
datetime
obiekt bez przekazywania właściwości konstruktora, dostajesz północ.dt = datetime.datetime.now()
Nie można obciąć obiektu datetime, ponieważ jest on niezmienny .
Jest jednak jeden sposób na zbudowanie nowej daty / godziny z polami 0 godzin, minut, sekund i mikrosekund, bez wyrzucania oryginalnej daty lub tzinfo:
newdatetime = now.replace(hour=0, minute=0, second=0, microsecond=0)
replace
opcję na pierwszym miejscu, ponieważ prawdopodobnie tego właśnie chcą.
tzinfo=now.tzinfo
. O tzinfo
północy może być inna, np. Przesunięcie utc o 2012-04-01 00:09:00
(9 rano) w strefie czasowej Australii / Melbourne jest, AEST+10:00
ale jest AEDT+11:00
o 2012-04-01 00:00:00
(północy) - w tym dniu następuje przejście na koniec DST. Możesz użyć pytz
modułu, aby to naprawić, zobacz moją odpowiedź.
Aby uzyskać północ odpowiadającą danemu obiektowi datetime, możesz użyć datetime.combine()
metody :
>>> 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)
Zaletą w porównaniu do tej .replace()
metody jest to datetime.combine()
, że oparte na rozwiązaniu rozwiązanie będzie nadal działać, nawet jeśli datetime
moduł wprowadzi obsługę nanosekund .
tzinfo
można zachować, jeśli to konieczne, ale przesunięcie utc może być inne o północy, np. z powodu przejścia DST, a zatem naiwne rozwiązanie (ustawienie tzinfo
atrybutu czasu) może się nie powieść. Zobacz Jak uzyskać czas UTC „północ” dla danej strefy czasowej?
Możesz do tego użyć pand (chociaż może to być narzut dla tego zadania). Możesz użyć okrągłego , podłogowego i sufitowego jak dla zwykłych liczb i dowolnej częstotliwości pand z przesuniętych aliasów :
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
"""
Możesz użyć datetime.strftime, aby wyodrębnić dzień, miesiąc, rok ...
Przykład:
from datetime import datetime
d = datetime.today()
# Retrieves the day and the year
print d.strftime("%d-%Y")
Wyjście (na dziś):
29-2011
Jeśli chcesz tylko pobrać dzień, możesz użyć atrybutu dnia, takiego jak:
from datetime import datetime
d = datetime.today()
# Retrieves the day
print d.day
Ouput (na dziś):
29
d.day
itp.
Istnieje wspaniała biblioteka używana do manipulowania datami: 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')
a jeśli chcesz odzyskać wartość daty / godziny:
>>> d.truncate('year').datetime
datetime.datetime(2015, 1, 1, 0, 0, tzinfo=<DstTzInfo 'US/Pacific' PDT-1 day, 17:00:00 DST>)
Zobacz więcej na https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.dt.floor.html
Jest teraz 2019, myślę, że najskuteczniejszym sposobem na to jest:
df['truncate_date'] = df['timestamp'].dt.floor('d')
6 lat później ... Znalazłem ten post i bardziej podobało mi się podejrzane podejście:
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]')
Twoje zdrowie
Możesz po prostu użyć
datetime.date.today()
Jest lekki i zwraca dokładnie to, czego chcesz.
Co oznacza obcinanie?
Masz pełną kontrolę nad formatowaniem za pomocą metody strftime () i odpowiedniego łańcucha formatu.
http://docs.python.org/library/datetime.html#strftime-strptime-behavior
Jeśli masz do czynienia z serią typu DateTime, istnieje bardziej skuteczny sposób na ich obcięcie, szczególnie gdy obiekt Series ma wiele wierszy.
Możesz użyć funkcji podłogi
Na przykład, jeśli chcesz go skrócić do godzin:
Wygeneruj zakres dat
times = pd.Series(pd.date_range(start='1/1/2018 04:00:00', end='1/1/2018 22:00:00', freq='s'))
Możemy to sprawdzić, porównując czas działania funkcji wymiany i podłogi.
%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)
Oto jeszcze jeden sposób, który pasuje do jednej linii, ale nie jest szczególnie elegancki:
dt = datetime.datetime.fromordinal(datetime.date.today().toordinal())