Làm cách nào để rút ngắn thời gian trên một đối tượng DateTime trong Python?


251

Một cách sang trọng để cắt ngắn một đối tượng datetime python là gì?

Trong trường hợp cụ thể này, đến ngày. Vì vậy, về cơ bản thiết lập giờ, phút, giây và micro giây thành 0.

Tôi muốn đầu ra cũng là một đối tượng datetime, không phải là một chuỗi.

Câu trả lời:


376

Tôi nghĩ rằng đây là những gì bạn đang tìm kiếm ...

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

Nhưng nếu bạn thực sự không quan tâm đến khía cạnh thời gian của mọi thứ, thì bạn thực sự chỉ nên đi xung quanh datecác vật thể ...

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

14
Với dt nhận biết múi giờ, datetime.datetime (dt.year, dt.month, dt.day) sẽ loại bỏ thông tin tzinfo.
ʇsәɹoɈ

1
nếu bạn đang tìm kiếm ngay hôm nay, bạn cũng có thể thực hiện datetime.date.today ()
galarant

4
Lưu ý rằng tài liệu python 2 và python 3 đều nói rằng replace()phương thức trả về một đối tượng datetime, vì vậy câu thần chú chính xác sẽ là:dt = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
Brad M

3
OP muốn datetime, không phải dateđối tượng (mà bạn có thể nhận được bằng cách sử dụng dt.date()cuộc gọi (không cần sử dụng hàm tạo rõ ràng)). Các .replace()phương pháp có thể thất bại nếu datetimebổ sung hỗ trợ nano giây . Bạn có thể sử dụng datetime.combine()thay thế .
JFS

@chrisw Tại sao không viết nó thành một dòng datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)?
3kstc

66

Sử dụng datekhông datetimenếu bạn không quan tâm đến thời gian.

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

Bạn có thể cập nhật một datetime như thế này:

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

9
Với các mốc thời gian nhận biết múi giờ, now.date () sẽ loại bỏ thông tin tzinfo.
ʇsәɹoɈ

1
@ sәɹoɈ: đây là cách bạn có thể nhận được nửa đêm nhận biết múi giờ
jfs

34

Bốn năm sau: một cách khác, tránh replace

Tôi biết câu trả lời được chấp nhận từ bốn năm trước hoạt động, nhưng điều này có vẻ nhẹ hơn so với sử dụng replace:

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

Ghi chú

  • Khi bạn tạo một datetimeđối tượng mà không chuyển các thuộc tính thời gian cho hàm tạo, bạn sẽ nhận được nửa đêm.
  • Như những người khác đã lưu ý, điều này giả định rằng bạn muốn một đối tượng datetime để sử dụng sau này với timedeltas.
  • Tất nhiên, bạn có thể thay thế điều này cho dòng đầu tiên: dt = datetime.datetime.now()

20

Bạn không thể cắt một đối tượng datetime vì nó là bất biến .

Tuy nhiên, đây là một cách để xây dựng một datetime mới với các trường 0 giờ, phút, giây và micro giây, mà không cần bỏ đi ngày ban đầu hoặc tzinfo:

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

1
+1: nếu bạn đặt replacetùy chọn lên hàng đầu, vì đó có thể là những gì họ muốn.
S.Lott

Nó là không chính xác để sử dụng tzinfo=now.tzinfo. Vào tzinfolúc nửa đêm có thể khác nhau, ví dụ, bù utc vào lúc 2012-04-01 00:09:00(9 giờ sáng) ở múi giờ Úc / Melbourne AEST+10:00nhưng AEDT+11:00vào lúc 2012-04-01 00:00:00(nửa đêm) - có sự chuyển tiếp cuối DST vào ngày đó. Bạn có thể sử dụng pytzmô-đun để sửa nó, xem câu trả lời của tôi.
JFS

13

Để có được một nửa đêm tương ứng với một đối tượng datetime nhất định, bạn có thể sử dụng datetime.combine()phương thức :

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

Ưu điểm so với các .replace()phương phápdatetime.combine()giải pháp dựa trên sẽ tiếp tục làm việc ngay cả khi datetimemô-đun giới thiệu nano giây hỗ trợ .

tzinfocó thể được bảo toàn nếu cần thiết nhưng phần bù utc có thể khác vào nửa đêm, ví dụ, do quá trình chuyển đổi DST và do đó, một giải pháp ngây thơ (cài đặt tzinfothuộc tính thời gian) có thể thất bại. Xem Làm thế nào để tôi có được thời gian UTC của nửa đêm nửa đêm cho một múi giờ nhất định?


7

Bạn có thể sử dụng gấu trúc cho điều đó (mặc dù nó có thể là chi phí cho nhiệm vụ đó). Bạn có thể sử dụng hình tròn , sàntrần như đối với các số thông thường và bất kỳ tần số gấu trúc nào từ các bí danh bù :

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

Bạn có thể sử dụng datetime.strftime để trích xuất ngày, tháng, năm ...

Thí dụ :

from datetime import datetime
d = datetime.today()

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

Đầu ra (cho ngày hôm nay):

29-2011

Nếu bạn chỉ muốn lấy lại ngày, bạn có thể sử dụng thuộc tính day như:

from datetime import datetime
d = datetime.today()

# Retrieves the day
print d.day

Ouput (cho ngày hôm nay):

29

Vâng, điều là tôi đã làm điều này một lần rồi, vì vậy có thể có nhiều chi phí hơn sau đó chỉ cần đặt các trường giờ min vv trong đối tượng datetime.
Kyle Brandt

Heh, đó là một cách kỳ lạ để làm điều đó, bạn thực sự có thể làm, d.dayv.v.
Jochen Ritzel

3

Có một thư viện tuyệt vời được sử dụng để thao túng ngày: 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')

và nếu bạn muốn lấy lại giá trị datetime:

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

nó trả về thời gian sai (bù sai utc) nếu thời gian kết quả có bù utc khác, ví dụ, do chuyển đổi DST. Xem Làm thế nào để tôi có được thời gian UTC của nửa đêm nửa đêm cho một múi giờ nhất định?
JFS


1

Có một mô-đun datetime_truncate xử lý cái này cho bạn. Nó chỉ gọi datetime.replace.


1

6 năm sau ... Tôi đã tìm thấy bài đăng này và tôi thích nhiều hơn những lời quảng cáo khó chịu:

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

chúc mừng


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

1

Bạn chỉ có thể sử dụng

datetime.date.today()

Đó là ánh sáng và trả lại chính xác những gì bạn muốn.


Câu trả lời tương tự đã được đưa ra trước đây, không có gì mới.
slfan

Xin lỗi @slfan nhưng tôi không thấy bất kỳ bài đăng nào có tên của bạn, thậm chí sử dụng "tìm kiếm" từ trình duyệt.
Bordotti

1
Không phải bởi tôi, bởi zx81 3 năm trước. tìm kiếm datetime.date.today (). Nếu một câu trả lời là chính xác, bạn nên upvote, không trả lời lại.
slfan


0

Nếu bạn đang xử lý một Series loại DateTime, có một cách hiệu quả hơn để cắt bớt chúng, đặc biệt khi đối tượng Sê-ri có nhiều hàng.

Bạn có thể sử dụng chức năng sàn

Ví dụ: nếu bạn muốn cắt ngắn nó thành giờ:

Tạo một phạm vi ngày

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

Chúng ta có thể kiểm tra nó so sánh thời gian chạy giữa các chức năng thay thế và sàn.

%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

Đây là một cách khác phù hợp với một dòng nhưng không đặc biệt thanh lịch:

dt = datetime.datetime.fromordinal(datetime.date.today().toordinal())
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.