2012-06-14 4 views
22

В настоящее время я лесозаготовки вещи, и я использую свой собственный форматера с настраиваемой FormatTime():питон Дата и время: Круглые/обрезки количество цифр в микросекундах

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

Моя проблема заключается в том, что микросекунд,% е, шесть цифр. В любом случае, чтобы выплескивать меньше цифр, например, первые три цифры микросекунд?

ответ

27

Самый простой способ будет использовать нарезку просто отрубить последние три цифры микросекунд:

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

Если вы хотите на самом деле круглые числа, а не только рубить, это немного больше работы, но не попало:

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

Ваш метод округления не работает для меня, она производит этот результат: '» 2015-04-12 17: 09: 020.588'', секунды недействительны. – NuclearPeon

+1

Я проверил ваш код в python 2.7.6 и python 3.4.0. Копировал и вставлял ваш код, одинаковый результат каждый раз. У вас есть 3 цифры в вашей области секунд. Я смотрю на код, и кажется, что ваш float (переменная 'f') накладывает на ведущее 0 перед десятичным (например:' 0.367'), которое добавляется в виде строки. То, что приводит к 0 в области секунд, начинается с отказа. – NuclearPeon

+2

@NuclearPeon Прошу прощения. Вы определили реальную ошибку, которая доказывает, что я фактически не тестировал ее, прежде чем публиковать ее. Я отредактировал код, чтобы исправить ошибку, и теперь он должен работать для вас. Спасибо, что привлек это к моему вниманию. – steveha

1

Этот метод позволяет гибко точность и будет потреблять всю величину микросекунд, если вы укажете слишком большую точность.

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

Этот метод реализует округление до 3 знаков после запятой:

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

я избегал использовать метод strftime намеренно, потому что я предпочел бы не изменить полностью сериализованный объект DATETIME без повторного съема его. Этот способ также показывает внутреннюю дату, если вы хотите изменить ее дальше.

В примере округления обратите внимание, что точность основана на строках для модуля Decimal.

2

В моем случае я пытался отформатировать datestamp с миллисекундами, отформатированными как «ddd». Решение, которое я использовал для получения миллисекунд, должно было использовать атрибут объекта datetime, разделите его на 1000,0, поместите его нулями, если необходимо, и округлите его с помощью формата. Это выглядит следующим образом:

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

микросекунда составляет 0 <= микросекунды <1000000. Так что точно за миллион будет производиться «1000». Это именно то, что случилось со мной. Https://www.devrant.io/rants/466105 – alkuzad

+1

@alkuzad: Как вы уже упоминали, это не может быть ровно миллион, но «формат» будет округлять его до 1000, когда микросекунда составляет не менее 999500 Вместо округления вы можете добавить 500 мкс к дате времени и усечь, чтобы получить тот же эффект, при этом автоматически заботясь о округлении до минут, часов, дней, месяцев или лет. Или просто усечь, если вам не хватает половины миллисекунды: '' {: 03} '. Format (datetime.now(). Microsecond // 1000) ' – Kundor

1

Этот метод всегда должен возвращать временную метку, которая выглядит точно так же, как это (с или без временной зоны, в зависимости от того объекта ввода dt содержит один):

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

В качестве входных данных требуется объект datetime (который вы можете произвести с помощью datetime.datetime.now()). Чтобы получить часовой пояс, как в моем примере вывода, вам нужно будет import pytz и пройти 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') 
    ) 

я заметил, что некоторые из других методов выше будет опускать заднюю ноль, если был один (например, 0.870 стал 0.87), и это было причиной проблем для синтаксического анализа я кормил эти временные метки в. Этот метод не имеет этой проблемы.

0

Вот мое решение, используя регулярное выражение:

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

Другой подход, основанный на элегантное решение от 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)