2011-06-23 68 views
7

Tôi đang tìm cách chuyển đổi đối tượng ngày giờ thành năm thập phân. Dưới đây là ví dụpython cách chuyển đổi ngày giờ thành số thập phân

>>> obj = SomeObjet() 
>>> obj.DATE_OBS 
datetime.datetime(2007, 4, 14, 11, 42, 50) 

Làm cách nào để chuyển đổi datetime.datetime (2007, 4, 14, 11, 42, 50) sang thập phân? Từ định dạng dd/mm/yyyy này sang định dạng yyyy.yyyy

+0

Bạn có thể đưa ra một số ví dụ không? Bạn có ý nghĩa gì bởi "năm thập phân"? –

+0

Từ định dạng này dd/mm/yyyy sang loại định dạng yyyy.yyyy – user739807

+0

Ý của bạn là, để chuyển đổi nó thành một số số dấu phẩy động? Giống như - chuyển đổi ngày/tháng/giờ/etc thành một số? Nếu có, thì bạn cần tính toán nó một mình. –

Trả lời

18
from datetime import datetime as dt 
import time 

def toYearFraction(date): 
    def sinceEpoch(date): # returns seconds since epoch 
     return time.mktime(date.timetuple()) 
    s = sinceEpoch 

    year = date.year 
    startOfThisYear = dt(year=year, month=1, day=1) 
    startOfNextYear = dt(year=year+1, month=1, day=1) 

    yearElapsed = s(date) - s(startOfThisYear) 
    yearDuration = s(startOfNextYear) - s(startOfThisYear) 
    fraction = yearElapsed/yearDuration 

    return date.year + fraction 

Demo:

>>> toYearFraction(dt.today()) 
2011.47447514 

Phương pháp này có lẽ là chính xác để trong vòng thứ hai (hoặc giờ nếu tiết kiệm ánh sáng ban ngày hoặc những thứ trong khu vực kỳ lạ khác đang có hiệu lực). Nó cũng hoạt động chính xác trong thời gian nhảy vọt. Nếu bạn cần độ phân giải quyết liệt (chẳng hạn như do thay đổi trong xoay vòng của Trái đất), bạn nên truy vấn dịch vụ mạng tốt hơn.

+0

Câu trả lời của tôi là đơn giản hơn nhiều và cung cấp cho một float tương đương so sánh. Cả hai giải pháp của chúng tôi đều không chính xác, nhưng không có cách nào tiêu chuẩn có thể chấp nhận được để chuyển đổi một thời điểm nhất định theo thời gian sang biểu diễn thập phân của một năm, có phải không? – Kimvais

+0

@Kimvais có, có; nó là một số lượng được xác định rõ. Điều này chính xác trong vòng một giờ, nhiều hơn nếu các thư viện chăm sóc tiết kiệm ánh sáng ban ngày (mà tôi không nghĩ rằng chúng làm). – ninjagecko

+0

Xin lỗi, có nghĩa là 'thường được chấp nhận tiêu chuẩn' không 'thường chấp nhận được ...' – Kimvais

2

Tôi giả định rằng bạn đang sử dụng điều này để so sánh giá trị ngày giờ. Để làm điều đó, vui lòng sử dụng các đối tượng timedelta thay vì reiniventing bánh xe.

Ví dụ:

>>> from datetime import timedelta 
>>> from datetime import datetime as dt 
>>> d = dt.now() 
>>> year = timedelta(days=365) 
>>> tomorrow = d + timedelta(days=1) 
>>> tomorrow + year > d + year 
True 

Nếu vì một lý do nào bạn thực sự cần năm chữ số thập phân, datetime đối tượng phương pháp strftime() có thể cung cấp cho bạn một đại diện nguyên của ngày của năm nếu được yêu cầu cho %j - nếu điều này là những gì bạn đang tìm kiếm, xem bên dưới cho một mẫu đơn giản (chỉ trên độ phân giải 1 ngày):

>>> from datetime import datetime 
>>> d = datetime(2007, 4, 14, 11, 42, 50) 
>>> (float(d.strftime("%j"))-1)/366 + float(d.strftime("%Y")) 
2007.2814207650274 
+0

Phương pháp này không chính xác trong khoảng 1-2 ngày tùy theo năm và không hoạt động những năm nhuận. Tôi cũng nhầm lẫn lý do tại sao bạn đang giả định 367 ngày mỗi năm. – ninjagecko

+0

367 để ngày cuối cùng của năm nhuận không trở thành chính xác trong năm tới. – Kimvais

+1

đó không phải là điều đúng đắn để làm. Hơn nữa, bạn có một lỗi khác: bạn luôn bỏ qua '2010.0' và' 2011.0' và tất cả các số khác, bởi vì datetime (năm = 2011, tháng = 1, ngày = 1) .ndftime ("% j") là 1 không 0. Việc sửa chữa là trừ 1, nhưng điều đó vẫn không chính xác bởi một ngày trong thời gian nhảy vọt. – ninjagecko

0

Đây là một cách đơn giản hơn chút so với các giải pháp khác:

import datetime 
def year_fraction(date): 
    start = datetime.date(date.year, 1, 1).toordinal() 
    year_length = datetime.date(date.year+1, 1, 1).toordinal() - start 
    return date.year + float(date.toordinal() - start)/year_length 

>>> print year_fraction(datetime.datetime.today()) 
2016.32513661 

Lưu ý rằng điều này sẽ tính toán phần dựa trên sự bắt đầu của ngày, vì vậy ngày 31 tháng 12 sẽ là 0,997, không 1.0.

0

Ngạc nhiên không ai đề cập đến điều này ... nhưng đối tượng datetime.timedelta là kết quả của việc trừ các đối tượng datetime.datetime có phương pháp phân chia. Vì vậy, bạn có thể sử dụng hàm đơn giản

from datetime import datetime 
def datetime2year(dt): 
    year_part = dt - datetime(year=dt.year, month=1, day=1) 
    year_length = datetime(year=dt.year+1, month=1, day=1) - datetime(year=dt.year, month=1, day=1) 
    return dt.year + year_part/year_length 

nơi phân chia nằm giữa các đối tượng datetime.timedelta.

0

Có thể tính ngày thập phân bằng cách sử dụng ngày tháng julian của Pandas và các công thức sau đây.

Trong trường hợp dataframe gấu trúc của bạn có một chỉ số đó là ngày thời gian:

JD=dat.index.to_julian_date() #create julian date 
L= JD+68569 
N= 4*L/146097 
L= L-(146097*N+3)/4 
I= 4000*(L+1)/1461001 
L= L-1461*I/4+31 
J= 80*L/2447 
K= L-2447*J/80 
L= J/11 
J= J+2-12*L 
decimal_date= 100*(N-49)+I+L 

decimal_date là một loạt các ngày của bạn (trong TZ giống như chỉ số dataframe) dưới hình thức một cái gì đó giống như 2007,123452 .

Adapted from this post.

0

Sau khi thực hiện các giải pháp chấp nhận, tôi đã có sự mặc khải rằng phiên bản gấu trúc hiện đại này là giống hệt nhau, và đơn giản hơn nhiều:

dat['decimal_date']=dat.index.year+ (dat.index.dayofyear -1)/365 

Phải được sử dụng trên một số ngày thời gian Pandas dataframe.Thêm khi bài đăng giải pháp này xuất hiện ở đầu tìm kiếm google của tôi cho vấn đề này.

Các vấn đề liên quan