2011-12-06 34 views
19

Xin chào, tôi cần một số trợ giúp để hiểu tại sao điều này xảy ra. Tôi có một phương pháp để theo dõi 'thời gian còn lại trong một chương trình sự kiện:Vấn đề thời gian Python bằng các giá trị âm

def get_program_time_budget(self): 
    return self.estimated_duration-self.get_program_duration() 

Tất cả tốt khi ESTIMATED_DURATION> self.get_program_duration() nhưng khi điều này đi theo cách khác mọi thứ trở nên buồn cười.

Kết quả được hiển thị cho người dùng:

Estimated 11 hours Allocated  10 hours 55 minutes  Remaining  5 minutes 

Khi kết quả đi tiêu cực nó thực hiện điều này:

Estimated 11 hours Allocated  11 hours 5 minutes Remaining  -1 day 23 hours 55 minutes 

Bất kỳ ý tưởng làm thế nào để có được kết quả -5 phút?

EDIT: Đây là định dạng timedelta (Lưu ý đây là một bộ lọc Django, vì vậy nhận được giá trị timedelta như một str - nhưng nó được lưu giữ như một timedelta):

def format_duration(value): 
    try: 
    delim = ':' 
    toks = value.split(',') 
    hour = minute = '' 
    d_string = value.count('day') and toks[0] or '' 
    h, m, s = d_string and toks[-1].strip().split(delim) or value.split(delim) 
    try: 
     hour = int(h) 
    except: 
     pass 
    try: 
     minute = int(m) 
    except: 
     pass 
    h_string = "%s%s%s" % (hour and hour or '', (hour and ' hour' or ''),(hour and hour > 1 and 's' or '') ) 
    m_string = "%s%s%s" % (minute and minute or '', (minute and ' minute' or ''),(minute and minute > 1 and 's' or '')) 
    return "%s %s %s" % (d_string, h_string, m_string) 
    except Exception, e: 
    logging.error("Error in format_duration -> %s. Duration value=%s" % (e, value)) 
    return ''v 
+1

Đây là cách 'timedelta' hoạt động cho các giá trị âm. Kết quả luôn được chuẩn hóa để chỉ giá trị 'ngày' là âm. Bạn có muốn phủ nhận các trường khác nếu giá trị ngày, ví dụ, -5? –

+3

Chúng ta biết cách trừ hai timedeltas. Những gì chúng tôi không biết là mã bạn sử dụng để hiển thị kết quả. Để được tư vấn tốt hơn, hãy tiết lộ. –

+1

Nếu bạn muốn làm việc với các giá trị timedelta âm theo cách thông minh ("-1 phút" chỉ là "-1 phút" và ** không ** "-1 ngày cộng với 23h59"), bạn có thể sử dụng mô-đun 'relativetimedelta' có mặt trong [dateutil] (http://labix.org/python-dateutil). – florisla

Trả lời

35

Nếu bạn đang sử dụng Python 2.7 hoặc cao hơn, bạn có thể sử dụng timedelta.total_seconds() để có được một số float đại diện của timedelta dưới dạng số giây dương hoặc âm.

>>> datetime.timedelta(-1, 86100).total_seconds() 
-300.0 

Bạn sẽ có thể sử dụng tính năng này để tính toán số phút khá dễ dàng.

Nếu bạn không sử dụng Python 2.7, bạn có thể sử dụng công thức tương đương sau đây từ các tài liệu:

(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6)/10.0**6 

Edit: Dường như bạn có lẽ bằng cách sử dụng chuỗi đại diện mặc định cho timedelta để hiển thị kết quả , vì vậy câu trả lời ban đầu của tôi có thể không hữu ích. Tôi sẽ đề nghị một cái gì đó như thế này để hiển thị kết quả:

def get_program_time_budget(self): 
    td = self.estimated_duration-self.get_program_duration() 
    if td.days < 0: 
     return '-' + str(datetime.timedelta() - td) 
    return str(td) 

này bây giờ sẽ trả về một chuỗi thay vì một timedelta, và cho timedeltas tiêu cực nó sẽ thêm vào trước một '-' để một timedelta tích cực.

+0

Cảm ơn. Câu trả lời tuyệt vời nhưng tôi không sử dụng định dạng str mặc định. Tôi có định dạng riêng của tôi (để dải giây vv) vì vậy cần một timedelta, không phải là một str. Sẽ thử công thức từ các tài liệu để làm total_seconds. –

+0

Trong trường hợp đó, bạn nên thay đổi trình định dạng của mình để chuyển thành một dấu thời gian dương và chỉ ở dấu '-' ở phía trước nó. –

+0

Thật không may là mã định dạng là một bộ lọc Django, do đó, lấy timedelta .__ str__ (hoặc __unicode__) làm giá trị - xem câu hỏi cho mã. –

11

Tại sao?

Có thể là tác dụng phụ không mong muốn của cách //% được xác định.

Có thể vì việc này giúp dễ dàng triển khai lớp datetime. Năm phút trước kỷ nguyên là 23:55, không phải là 0: -5.

Nó không thực sự quan trọng. Chỉ cần biết rằng đó là cách days, secondsmicroseconds được chuẩn hóa. Và nó có thể dễ dàng được làm việc xung quanh.

def format_timedelta(td): 
    if td < timedelta(0): 
     return '-' + format_timedelta(-td) 
    else: 
     # Change this to format positive timedeltas the way you want 
     return str(td) 

>>> format_timedelta(timedelta(minutes=-5)) 
'-0:05:00' 
+2

Điều này thật đơn giản nhưng thiên tài. Cảm ơn bạn! –

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