如何截断日期时间对象上的时间?

问题描述 投票:0回答:18

截断 python

datetime
对象的经典方法是什么?

在这种特殊情况下,直到今天。所以基本上将小时、分钟、秒和微秒设置为 0。

我希望输出也是一个

datetime
对象,而不是字符串。

python datetime
18个回答
542
投票

我想这就是你正在寻找的......

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

97
投票

如果您不关心时间,请使用

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)

52
投票

四年后:另一种方式,避免
replace

我知道四年前接受的答案是有效的,但这似乎比使用

replace
轻一点:

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

注释

  • 当您创建一个
    datetime
    对象而不将时间属性传递给构造函数时,您将得到午夜。
  • 正如其他人所指出的,这假设您需要一个日期时间对象以便稍后与时间增量一起使用。
  • 当然,您可以将其替换为第一行:
    dt = datetime.datetime.now()

27
投票

要获取与给定日期时间对象对应的午夜,您可以使用

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 偏移量在午夜可能会有所不同,例如,由于 DST 转换,因此简单的解决方案(设置 
tzinfo
 时间属性)可能会失败。请参阅
如何获取给定时区的“午夜”的 UTC 时间?


26
投票
您无法截断日期时间对象,因为

它是不可变的

但是,这里有一种方法可以构造具有 0 小时、分钟、秒和微秒字段的新日期时间,而无需丢弃原始日期或 tzinfo:

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

16
投票
查看更多信息

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.dt.floor.html

现在已经2019年了,我认为最有效的方法是:

df['truncate_date'] = df['timestamp'].dt.floor('d')
    

11
投票
您可以使用

pandas 来实现这一点(尽管这可能会增加该任务的开销)。您可以使用 roundfloorceil 来表示通常的数字以及来自 offset-aliases 的任何 pandas 频率:

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
投票
有一个很棒的库用于操作日期:

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

如果您想取回日期时间值:

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

3
投票
您可以使用 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

输出(今天):

29
    

3
投票
如果您正在处理 DateTime 类型的 Series,有一种更有效的方法来截断它们,特别是当 Series 对象有很多行时。

您可以使用

floor功能

例如,如果您想将其截断为小时:

生成日期范围

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)
    

3
投票
>>> import datetime >>> dt = datetime.datetime.now() >>> datetime.datetime.date(dt) datetime.date(2019, 4, 2)
    

3
投票
这是另一种适合一行的方式,但不是特别优雅:

dt = datetime.datetime.fromordinal(datetime.date.today().toordinal())
    

3
投票
如果您想截断为任意时间增量:

from datetime import datetime, timedelta truncate = lambda t, d: t + (datetime.min - t) % - d # 2022-05-04 15:54:19.979349 now = datetime.now() # truncates to the last 15 secondes print(truncate(now, timedelta(seconds=15))) # truncates to the last minute print(truncate(now, timedelta(minutes=1))) # truncates to the last 2 hours print(truncate(now, timedelta(hours=2))) # ... """ 2022-05-04 15:54:15 2022-05-04 15:54:00 2022-05-04 14:00:00 """
PS:这是针对python3的


1
投票
有一个模块 datetime_truncate 可以为您处理这个问题。它只是调用 datetime.replace 。


1
投票
6 年后...我发现了这篇文章,我更喜欢 numpy 方法:

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
投票
您可以通过指定来做到这一点

isoformat


>>> import datetime >>> datetime.datetime.now().isoformat(timespec='seconds', sep=' ') 2022-11-24 12:42:05
该文档提供了有关 

isoformat()

 用法的更多详细信息。

https://docs.python.org/3/library/datetime.html#datetime.datetime.isoformat


0
投票
你可以直接使用

datetime.date.today()
它很轻,并且返回的正是您想要的。


0
投票
我看到的其他答案可能会引入错误,因为它们可能会删除

tzinfo

,或者不使用 
time.min
,这确保将来添加到 Python 的任何额外精度也被考虑在内。以干净可靠的方式开始新的一天的方法是:

from datetime import datetime, time, timezone def start_of_day(dt: datetime) -> datetime: return datetime.combine(dt, time.min, tzinfo=dt.tzinfo) print(start_of_day(datetime.now())) print(start_of_day(datetime.now(tz=timezone.utc)))
今天输出:

2024-04-03 00:00:00 2024-04-03 00:00:00+00:00
    
© www.soinside.com 2019 - 2024. All rights reserved.