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ć dateprzedmioty ...
>>> d_truncated = datetime.date(dt.year, dt.month, dt.day)
>>> d_truncated
datetime.date(2011, 3, 29)
datetime, a nie dateobiekt (że można uzyskać za pomocą dt.date()wywołania (nie trzeba używać jawnego konstruktora)). .replace()Metoda może zawieść jeśli datetimedodaje wsparcie nanosekund . Możesz zamiast tego użyćdatetime.combine() .
datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)?
Użyj datenie, datetimejeś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)
replaceWiem, ż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
datetimeobiekt 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)
replaceopcję na pierwszym miejscu, ponieważ prawdopodobnie tego właśnie chcą.
tzinfo=now.tzinfo. O tzinfopół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:00ale jest AEDT+11:00o 2012-04-01 00:00:00(północy) - w tym dniu następuje przejście na koniec DST. Możesz użyć pytzmoduł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 datetimemoduł wprowadzi obsługę nanosekund .
tzinfomoż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 tzinfoatrybutu 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.dayitp.
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())