現在、私はものをログに記録しており、カスタムformatTime()
で独自のフォーマッタを使用しています:
def formatTime(self, _record, _datefmt):
t = datetime.datetime.now()
return t.strftime('%Y-%m-%d %H:%M:%S.%f')
私の問題は、マイクロ秒、%f
は、6桁です。とにかく、マイクロ秒の最初の3桁のように、より少ない桁を吐き出す必要はありますか?
最も簡単な方法は、スライスを使用して、マイクロ秒の最後の3桁を切り捨てることです。
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:])
このメソッドは、常に次のようなタイムスタンプを返す必要があります(入力dt
オブジェクトにタイムゾーンが含まれているかどうかによって、タイムゾーンの有無は異なります)。
2016-08-05T18:18:54.776 + 00
入力として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')
)
_
上記の他のメソッドのいくつかは、末尾のゼロが1つあれば省略されることに気づきました(例えば、_0.870
_が_0.87
_になり、これがこれらのタイムスタンプを供給しているパーサーに問題を引き起こしていました)。この方法にはその問題はありません。
編集:以下のコメントで指摘されているように、999.5は1000(オーバーフロー)に丸められるため、このソリューション(および上記のソリューション)の丸めでは、マイクロ秒値が999500に達すると問題が発生します。
必要な形式をサポートするためにstrftimeを再実装するのではなく(丸めによって発生する可能性のあるオーバーフローを数秒、数分などに伝播する必要があります)、最初の3桁に切り捨てる方がはるかに簡単です受け入れられた答え、または次のようなものを使用して:
'{:03}'.format(int(999999/1000))
-以下に元の回答を保存-
私の場合、ミリ秒を「ddd」としてフォーマットした日付スタンプをフォーマットしようとしました。最終的にミリ秒を取得するために使用した解決策は、microsecond
オブジェクトのdatetime
属性を使用し、1000.0で除算し、必要に応じてゼロを埋め込み、フォーマットで丸めることでした。次のようになります。
'{:03.0f}'.format(datetime.now().microsecond / 1000.0)
# Produces: '033', '499', etc.
すべての場合に機能する簡単なソリューション:
def format_time():
t = datetime.datetime.now()
if t.microsecond % 1000 >= 500: # check if there will be rounding up
t = t + datetime.timedelta(milliseconds=1) # manually round up
return t.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
基本的に、最初に日付オブジェクト自体を手動で丸めてから、マイクロ秒を安全にトリミングできます。
正規表現を使用した私のソリューションは次のとおりです。
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())
この方法により、柔軟な精度が可能になり、あまりにも高い精度を指定すると、マイクロ秒値全体が消費されます。
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)))
完全にシリアル化されたdatetimeオブジェクトを変更したくない再検証せずに、strftime
メソッドを意図的に使用することを避けました。この方法では、さらに変更する場合に備えて、日付の内部も表示されます。
丸めの例では、Decimal
モジュールの精度は文字列ベースであることに注意してください。
Pablojim コメントに基づいて提案されたソリューションを修正します。
from datetime import datetime
dt = datetime.now()
dt_round_microsec = round(dt.microsecond/1000) #number of zeroes to round
dt = dt.replace(microsecond=dt_round_microsec)
結果とともに曜日(つまり、「日曜日」)を取得したい場合、「[:-3]」をスライスしても機能しません。そのとき、あなたは一緒に行くかもしれません、
dt = datetime.datetime.now()
print("{}.{:03d} {}".format(dt.strftime('%Y-%m-%d %I:%M:%S'), dt.microsecond//1000, dt.strftime("%A")))
#Output: '2019-05-05 03:11:22.211 Sunday'
%H-24時間形式の場合
%I-12時間形式の場合
おかげで、