Как укоротить время на объекте DateTime в Python?


251

Что такое классный способ обрезать объект даты и времени Python?

В данном конкретном случае до дня. Таким образом, в общем случае установка часов, минут, секунд и микросекунд на 0.

Я хотел бы, чтобы выходные данные также были объектом datetime, а не строкой.

Ответы:


376

Я думаю, это то, что вы ищете ...

>>> 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)

Но если вы действительно не заботитесь о временном аспекте вещей, тогда вам действительно нужно только обойти dateобъекты ...

>>> d_truncated = datetime.date(dt.year, dt.month, dt.day)
>>> d_truncated
datetime.date(2011, 3, 29)

14
С dt с учетом часового пояса datetime.datetime (dt.year, dt.month, dt.day) выбрасывает информацию tzinfo.
— ʇsәɹoɈ

1
если вы ищете только сегодня, вы также можете сделать datetime.date.today ()
— galarant

4
Обратите внимание , что Python 2 и Python 3 документы и состояние , что replace()метод возвращает объект DateTime, поэтому правильное заклинание будет:dt = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
— Брэд M

3
OP хочет datetime, а не dateобъект (который вы можете получить с помощью dt.date()call (нет необходимости использовать явный конструктор)). .replace()Метод может потерпеть неудачу , если datetimeдобавляет поддержку наносекунд . Вы могли бы использовать datetime.combine()вместо этого .
— Jfs

@ chrisw Почему бы просто не написать это в одну строку datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)?
— 3

66

Используйте dateне, datetimeесли вы не заботитесь о времени.

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

Вы можете обновить дату и время следующим образом:

>>> now.replace(minute=0, hour=0, second=0, microsecond=0)
datetime.datetime(2011, 3, 29, 0, 0)

9
С учетом timezone с учетом timezone now.date () отбрасывает информацию tzinfo.
— ɈsәɹoɈ


35

Четыре года спустя: другой путь, избегая replace

Я знаю, что принятый ответ от четырехлетней давности работает, но это кажется немного легче, чем при использовании replace:

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

Ноты

  • Когда вы создаете datetime объект без передачи свойств времени конструктору, вы получаете полночь.
  • Как уже отмечали другие, это предполагает, что вам нужен объект datetime для последующего использования с timedeltas.
  • Конечно, вы можете заменить это на первую строку: dt = datetime.datetime.now()

20

Вы не можете усечь объект datetime, потому что он неизменен .

Тем не менее, вот один из способов создать новое время даты с полями 0 час, минута, секунда и микросекунды, не выбрасывая исходную дату или tzinfo:

newdatetime = now.replace(hour=0, minute=0, second=0, microsecond=0)

1
+1: если вы поставите replaceопцию первым, так как это, вероятно, то, что они хотят.
— S.Lott

Это неправильно использовать tzinfo=now.tzinfo. В tzinfoполночь может отличаться, например, смещение utc в 2012-04-01 00:09:00(9:00) в часовом поясе Австралия / Мельбурн, AEST+10:00но это AEDT+11:00в 2012-04-01 00:00:00(полночь) - в этот день происходит переход на конец летнего времени. Вы можете использовать pytzмодуль, чтобы исправить это, смотрите мой ответ.
— Jfs

13

Чтобы получить полночь, соответствующую данному объекту datetime, вы можете использовать datetime.combine()метод :

>>> 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)

Преимущество по сравнению с по .replace()методу является то , что datetime.combine()основанное решение будет продолжать работать , даже если datetimeмодуль вводит поддержку наносекунд .

tzinfoможет быть сохранено при необходимости, но смещение utc может быть другим в полночь, например, из-за перехода на летнее время, и поэтому простое решение (установка tzinfoатрибута времени) может потерпеть неудачу. См. Как я могу получить время UTC «полуночи» для данного часового пояса?


7

Вы можете использовать панды для этого (хотя это может быть накладные расходы для этой задачи). Вы можете использовать round , floor и ceil, как для обычных чисел и любой частоты панд из смещенных псевдонимов :

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
"""

4

Вы можете использовать datetime.strftime, чтобы извлечь день, месяц, год ...

Пример :

from datetime import datetime
d = datetime.today()

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

Выход (на сегодня):

29-2011

Если вы просто хотите получить день, вы можете использовать атрибут дня, например:

from datetime import datetime
d = datetime.today()

# Retrieves the day
print d.day

Ouput (на сегодня):

29

Ну, дело в том, что я уже делаю это один раз, так что это может потребовать больше времени, чем просто установка поля min и т. Д. В объекте datetime.
— Кайл Брандт

Хех, это странный способ сделать это, вы можете просто сделать d.day и т. Д.
— Йохен Ритцель,

3

Для манипулирования датами есть большая библиотека: 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')

и если вы хотите вернуть значение datetime:

>>> d.truncate('year').datetime
datetime.datetime(2015, 1, 1, 0, 0, tzinfo=<DstTzInfo 'US/Pacific' PDT-1 day, 17:00:00 DST>)

он возвращает неправильное время (неправильное смещение utc), если время результата имеет другое смещение utc, например, из-за перехода DST. См. Как я могу получить время UTC «полуночи» для данного часового пояса?
— Jfs


1

Есть модуль datetime_truncate, который обрабатывает это для вас. Он просто вызывает datetime.replace.


1

6 лет спустя ... Я нашел этот пост, и мне больше понравился этот тупой подход:

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]')

ура


1
>>> import datetime
>>> dt = datetime.datetime.now()
>>> datetime.datetime.date(dt)
datetime.date(2019, 4, 2)

1

Вы можете просто использовать

datetime.date.today()

Это свет и возвращает именно то, что вы хотите.


Такой же ответ был дан раньше, ничего нового.
— slfan

Извините @slfan, но я не увидел ни одного поста с вашим именем, даже используя "поиск" из браузера.
— Бордотти

1
Не мной, zx81 3 года назад. поиск datetime.date.today (). Если ответ правильный, вы должны проголосовать, а не отвечать снова.
— slfan


0

Если вы имеете дело с Series типа DateTime, существует более эффективный способ их усекать, особенно если в объекте Series много строк.

Вы можете использовать функцию пола

Например, если вы хотите сократить его до часов:

Генерация диапазона дат

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

Мы можем проверить это, сравнивая время выполнения функций замены и пола.

%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)

0

Вот еще один способ, который умещается в одну строку, но не особенно элегантен:

dt = datetime.datetime.fromordinal(datetime.date.today().toordinal())
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.