问题:如何在Python中截断DateTime对象上的时间?

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

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

我希望输出也是日期时间对象,而不是字符串。

What is a classy way to way truncate a python datetime object?

In this particular case, to the day. So basically setting hour, minute, seconds, and microseconds to 0.

I would like the output to also be a datetime object, not a string.


回答 0

我认为这就是您要寻找的…

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

I think this is what you’re looking for…

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

But if you really don’t care about the time aspect of things, then you should really only be passing around date objects…

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

回答 1

如果您不在乎时间,请使用datenot 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)

Use a date not a datetime if you dont care about the time.

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

You can update a datetime like this:

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

回答 2

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

我知道四年前已经接受的答案有效,但是这似乎比使用replace以下要轻:

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

笔记

  • 当您在datetime不将时间属性传递给构造函数的情况下创建对象时,将出现午夜。
  • 正如其他人所指出的那样,这假设您想要一个datetime对象供以后与timedelta一起使用。
  • 当然,您可以将其替换为第一行: dt = datetime.datetime.now()

Four years later: another way, avoiding replace

I know the accepted answer from four years ago works, but this seems a tad lighter than using replace:

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

Notes

  • When you create a datetime object without passing time properties to the constructor, you get midnight.
  • As others have noted, this assumes you want a datetime object for later use with timedeltas.
  • You can, of course, substitute this for the first line: dt = datetime.datetime.now()

回答 3

您不能截断日期时间对象,因为它是不可变的

但是,这是一种使用0小时,分钟,秒和微秒字段构造新日期时间而不丢弃原始日期或tzinfo的方法:

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

You cannot truncate a datetime object because it is immutable.

However, here is one way to construct a new datetime with 0 hour, minute, second, and microsecond fields, without throwing away the original date or tzinfo:

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

回答 4

要获得对应于给定日期时间对象的午夜,可以使用datetime.combine()method

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

相比,优点是datetime.combine()即使datetime模块引入了纳秒级支持,基于解决方案的解决方案仍将继续有效。

tzinfo可以在必要时保留它,但是utc偏移量可能在午夜有所不同,例如由于DST转换,因此幼稚的解决方案(设置tzinfo时间属性)可能会失败。请参阅如何获取给定时区的UTC时间“午夜”?

To get a midnight corresponding to a given datetime object, you could use datetime.combine() method:

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

The advantage compared to is that datetime.combine()-based solution will continue to work even if datetime module introduces the nanoseconds support.

tzinfo can be preserved if necessary but the utc offset may be different at midnight e.g., due to a DST transition and therefore a naive solution (setting tzinfo time attribute) may fail. See How do I get the UTC time of “midnight” for a given timezone?


回答 5

您可以为此使用熊猫(尽管对于该任务可能是开销)。您可以像通常的数字一样使用roundfloorceil,也可以使用offset-aliases的任何熊猫频率:

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

You could use pandas for that (although it could be overhead for that task). You could use round, floor and ceil like for usual numbers and any pandas frequency from offset-aliases:

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

回答 6

您可以使用datetime.strftime提取日期,月份,年份…

范例:

from datetime import datetime
d = datetime.today()

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

输出(今天):

29-2011

如果只想获取日期,则可以使用day属性,例如:

from datetime import datetime
d = datetime.today()

# Retrieves the day
print d.day

Ouput(今天):

29

You can use datetime.strftime to extract the day, the month, the year…

Example :

from datetime import datetime
d = datetime.today()

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

Output (for today):

29-2011

If you just want to retrieve the day, you can use day attribute like :

from datetime import datetime
d = datetime.today()

# Retrieves the day
print d.day

Ouput (for today):

29

回答 7

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

There is a great library used to manipulate dates: 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')

and if you want to get datetime value back:

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

回答 8

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

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

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

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

It’s now 2019, I think the most efficient way to do it is:

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

回答 9

有一个模块datetime_truncate可以为您处理。它只是调用datetime.replace。

There is a module datetime_truncate which handlers this for you. It just calls datetime.replace.


回答 10

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

干杯

6 years later… I found this post and I liked more the numpy aproach:

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

cheers


回答 11

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

回答 12

你可以用

datetime.date.today()

轻巧,可精确返回您想要的东西。

You can just use

datetime.date.today()

It’s light and returns exactly what you want.


回答 13

截断是什么意思?

通过使用strftime()方法并使用适当的格式字符串,您可以完全控制格式。

http://docs.python.org/library/datetime.html#strftime-strptime-behavior

What does truncate mean?

You have full control over the formatting by using the strftime() method and using an appropriate format string.

http://docs.python.org/library/datetime.html#strftime-strptime-behavior


回答 14

如果要处理DateTime类型的Series,则有一种更有效的方法来截断它们,尤其是在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)

If you are dealing with a Series of type DateTime there is a more efficient way to truncate them, specially when the Series object has a lot of rows.

You can use the floor function

For example, if you want to truncate it to hours:

Generate a range of dates

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

We can check it comparing the running time between the replace and the floor functions.

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

回答 15

这是适合另一行但又不是特别优雅的另一种方式:

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

Here is yet another way which fits in one line but is not particularly elegant:

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

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。