2012-06-14 55 views
22

Hiện nay tôi đang đăng nhập công cụ và tôi đang sử dụng định dạng riêng của tôi với một formatTime tùy chỉnh():python datetime: Vòng/số cắt các chữ số trong micro

def formatTime(self, _record, _datefmt): 
     t = datetime.datetime.now() 
     return t.strftime('%Y-%m-%d %H:%M:%S.%f') 

Vấn đề của tôi là micro,% f, có sáu chữ số. Có anyway để nhổ ra chữ số ít hơn, giống như ba chữ số đầu tiên của micro giây?

Trả lời

27

Cách đơn giản nhất là nên sử dụng cắt để chỉ chặt ba chữ số cuối cùng của micro:

def format_time(): 
    t = datetime.datetime.now() 
    s = t.strftime('%Y-%m-%d %H:%M:%S.%f') 
    return s[:-3] 

Nếu bạn muốn thực sự tròn số chứ không chỉ chặt, đó là một công việc ít hơn nhưng không kinh khủng:

def format_time(): 
    t = datetime.datetime.now() 
    s = t.strftime('%Y-%m-%d %H:%M:%S.%f') 
    tail = s[-7:] 
    f = round(float(tail), 3) 
    temp = "%.3f" % f 
    return "%s%s" % (s[:-7], temp[1:]) 
+0

phương pháp làm tròn của bạn không làm việc cho tôi, nó tạo ra kết quả này: '' 2015-04-12 17: 09: 020.588'', giây không hợp lệ. – NuclearPeon

+1

Tôi đã thử nghiệm mã của bạn trong python 2.7.6 và python 3.4.0. Sao chép và dán mã của bạn, cùng một kết quả mỗi lần. Bạn có 3 chữ số trong vùng giây của bạn. Tôi đang nhìn vào mã và có vẻ như phao ('f' variable) của bạn có đuôi 0 hàng đầu trước dấu thập phân (ví dụ:' 0.367') được nối thêm dưới dạng một chuỗi. Điều đó dẫn đầu 0 trong khu vực giây là nơi nó bắt đầu thất bại. – NuclearPeon

+2

@NuclearPeon Tôi xin lỗi. Bạn đã xác định một lỗi thực sự, điều này chứng minh rằng tôi đã không thực sự kiểm tra điều này trước khi đăng nó. Tôi đã chỉnh sửa mã để sửa lỗi và nó sẽ làm việc cho bạn ngay bây giờ. Cảm ơn bạn đã mang đến sự chú ý của tôi. – steveha

1

Phương pháp này cho phép độ chính xác linh hoạt và sẽ tiêu thụ toàn bộ giá trị micro giây nếu bạn chỉ định độ chính xác quá lớn.

def formatTime(self, _record, _datefmt, precision=3): 
    dt = datetime.datetime.now() 
    us = str(dt.microsecond) 
    f = us[:precision] if len(us) > precision else us 
    return "%d-%d-%d %d:%d:%d.%d" % (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, int(f)) 

Phương pháp này thực hiện làm tròn đến 3 chữ số thập phân:

import datetime 
from decimal import * 

def formatTime(self, _record, _datefmt, precision='0.001'): 
    dt = datetime.datetime.now() 
    seconds = float("%d.%d" % (dt.second, dt.microsecond)) 
    return "%d-%d-%d %d:%d:%s" % (dt.year, dt.month, dt.day, dt.hour, dt.minute, 
          float(Decimal(seconds).quantize(Decimal(precision), rounding=ROUND_HALF_UP))) 

Tôi tránh sử dụng phương pháp strftime cố vì Tôi không muốn sửa đổi một đối tượng datetime đầy đủ serialized mà không revalidating nó. Cách này cũng hiển thị ngày tháng trong trường hợp bạn muốn sửa đổi thêm.

Trong ví dụ làm tròn, lưu ý rằng độ chính xác dựa trên chuỗi cho mô-đun Decimal.

2

Trong trường hợp của tôi, tôi đã cố gắng định dạng một dấu thời gian bằng mili giây được định dạng là 'ddd'. Các giải pháp tôi đã kết thúc bằng cách sử dụng để có được mili giây là sử dụng các thuộc tính microsecond của đối tượng datetime, chia cho 1000.0, pad nó với số không nếu cần thiết, và làm tròn nó với định dạng. Nó trông giống như thế này:

'{:03.0f}'.format(datetime.now().microsecond/1000.0) 
# Produces: '033', '499', etc. 
+0

micro giây là 0 <= micro giây <1000000. Vì vậy, chính xác cho triệu nó sẽ sản xuất "1000". Đây chính xác là những gì đã xảy ra với tôi https://www.devrant.io/rants/466105 – alkuzad

+1

@alkuzad: Như bạn đề cập, nó không thể chính xác là một triệu, nhưng 'định dạng' sẽ làm tròn đến 1000 khi micro giây ít nhất 999500 Thay vì làm tròn, bạn có thể thêm 500 micro giây vào datetime và cắt ngắn để có được hiệu ứng tương tự, trong khi tự động chăm sóc vòng tròn lên đến phút, giờ, ngày, tháng hoặc năm. Hoặc chỉ cắt ngắn, nếu là một nửa phần nghìn giây không quan trọng đối với bạn: ''{: 03}' định dạng (datetime.now(). Microecond // 1000)' – Kundor

1

Phương pháp này nên luôn luôn trả về một dấu thời gian mà trông giống hệt như thế này (có hoặc không có múi giờ tùy thuộc vào việc các đối tượng đầu vào dt chứa một):

2016-08- 05T18: 18: 54.776 + 0000

Cần có một đối tượng datetime làm đầu vào (bạn có thể sản xuất với datetime.datetime.now()). Để có múi giờ như trong ví dụ đầu ra của tôi, bạn cần phải import pytz và vượt qua datetime.datetime.now(pytz.utc).

import pytz, datetime 


time_format(datetime.datetime.now(pytz.utc)) 

def time_format(dt): 
    return "%s:%.3f%s" % (
     dt.strftime('%Y-%m-%dT%H:%M'), 
     float("%.3f" % (dt.second + dt.microsecond/1e6)), 
     dt.strftime('%z') 
    ) 

tôi nhận thấy rằng một số phương pháp khác trên sẽ bỏ qua các dấu zero nếu có một (ví dụ 0.870 trở thành 0.87) và điều này đã gây khó khăn cho phân tích cú pháp tôi đã ăn những timestamps vào. Phương pháp này không có vấn đề đó.

0

Đây là giải pháp của tôi sử dụng regexp:

import re 

# Capture 6 digits after dot in a group. 
regexp = re.compile(r'\.(\d{6})') 
def to_splunk_iso(dt): 
    """Converts the datetime object to Splunk isoformat string.""" 
    # 6-digits string. 
    microseconds = regexp.search(dt.isoformat()).group(1) 
    return regexp.sub('.%d' % round(float(microseconds)/1000), dt.isoformat()) 
0

Một cách tiếp cận dựa trên một giải pháp thanh lịch từ John La Rooy

import math 

dt_round_sec = round(dt.microsecond/10**int(math.log10(dt.microsecond))+1)) 
dt = dt.replace(second=dt.second + dt_round_sec, microsecond=0) 
Các vấn đề liên quan