@@ -62,7 +62,7 @@ def __init__(
62
62
json_deserializer : Optional [Callable [[Union [Dict , str , bool , int , float ]], str ]] = None ,
63
63
json_default : Optional [Callable [[Any ], Any ]] = None ,
64
64
datefmt : Optional [str ] = None ,
65
- datetime_fmt : Optional [ str ] = None ,
65
+ use_datetime : bool = False ,
66
66
log_record_order : Optional [List [str ]] = None ,
67
67
utc : bool = False ,
68
68
** kwargs ,
@@ -88,13 +88,12 @@ def __init__(
88
88
Only used when no custom JSON encoder is set
89
89
90
90
datefmt : str, optional
91
- String directives (strftime) to format log timestamp using `time`. Only one of `datefmt`
92
- and `datetime_fmt` should be specified.
91
+ String directives (strftime) to format log timestamp.
93
92
94
- See https://docs.python.org/3/library/time.html#time.strftime
95
- datetime_fmt : str, optional
96
- String directives (strftime) to format log timestamp using `datetime`. Only one of
97
- `datefmt` and `datetime_fmt` should be specified .
93
+ See https://docs.python.org/3/library/time.html#time.strftime or
94
+ use_datetime : str, optional
95
+ Interpret `datefmt` as a format string for `datetime.datetime.strftime`, rather than
96
+ `time.strftime` .
98
97
99
98
See https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior . This
100
99
also supports a custom %F directive for milliseconds.
@@ -110,10 +109,8 @@ def __init__(
110
109
self .json_default = json_default or str
111
110
self .json_serializer = json_serializer or partial (json .dumps , default = self .json_default , separators = ("," , ":" ))
112
111
113
- if datefmt and datetime_fmt :
114
- raise ValueError (f"at most one of datefmt { datefmt !r} and datetime_fmt { datetime_fmt !r} can be specified" )
115
112
self .datefmt = datefmt
116
- self .datetime_fmt = datetime_fmt
113
+ self .use_datetime = use_datetime
117
114
118
115
self .utc = utc
119
116
self .log_record_order = log_record_order or ["level" , "location" , "message" , "timestamp" ]
@@ -145,25 +142,28 @@ def format(self, record: logging.LogRecord) -> str: # noqa: A003
145
142
def formatTime (self , record : logging .LogRecord , datefmt : Optional [str ] = None ) -> str :
146
143
record_ts = self .converter (record .created ) # type: ignore
147
144
145
+ if datefmt is None :
146
+ datefmt = self .datefmt
147
+
148
148
# NOTE: Python `time.strftime` doesn't provide msec directives
149
149
# so we create a custom one (%F) and replace logging record ts
150
150
# Reason 2 is that std logging doesn't support msec after TZ
151
151
msecs = "%03d" % record .msecs
152
152
153
- if datefmt or self .datefmt :
154
- return time .strftime (datefmt or self .datefmt , record_ts )
155
-
156
- elif self .datetime_fmt :
153
+ if self .use_datetime :
157
154
timestamp = record .created + record .msecs / 1000
158
155
159
156
dt = datetime .fromtimestamp (timestamp , tz = timezone .utc )
160
157
if not self .utc :
161
158
# convert back to local time
162
159
dt = dt .astimezone ()
163
160
164
- custom_fmt = self .datetime_fmt .replace (self .custom_ms_time_directive , msecs )
161
+ custom_fmt = ( datefmt or self .default_time_format ) .replace (self .custom_ms_time_directive , msecs )
165
162
return dt .strftime (custom_fmt )
166
163
164
+ elif datefmt :
165
+ return time .strftime (datefmt , record_ts )
166
+
167
167
custom_fmt = self .default_time_format .replace (self .custom_ms_time_directive , msecs )
168
168
return time .strftime (custom_fmt , record_ts )
169
169
0 commit comments