-
Notifications
You must be signed in to change notification settings - Fork 574
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The time value is wrong when outputting the log to console. #483
Comments
Ok, I think I understood the code base and how the behaviour above occurs. And I think it is an unfortunate case of "works as designed by Go". I have no idea if there is a need for a change; or how to fix this holistically. Inner workings of
|
var evt map[string]interface{} | |
p = decodeIfBinaryToBytes(p) | |
d := json.NewDecoder(bytes.NewReader(p)) | |
d.UseNumber() | |
err = d.Decode(&evt) | |
if err != nil { | |
return n, fmt.Errorf("cannot decode event: %s", err) | |
} |
It extracts the time
field as a string
in the format specified by zerolog.TimeFieldFormat
. For instance, this byte array is copied from a debug session (using the default time format).
{"level":"info","time":"2022-10-06T20:04:38+02:00","message":"wrong time default"}
Later, zerolog uses the closure as returned by consoleDefaultFormatTimestamp()
to parse & format the extracted time.
Lines 339 to 345 in 55aaf04
case string: | |
ts, err := time.Parse(TimeFieldFormat, tt) | |
if err != nil { | |
t = tt | |
} else { | |
t = ts.Local().Format(timeFormat) | |
} |
It uses zerolog.TimeFieldFormat
to parse the extracted time from string
to time.Time
. That is rightfully so because that is the exact time layout used to format the time in the first place.
Then it uses the time format layout given to the ConsoleWriter
on creation by TimeFormat
:
zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: "<here time format for console writer output>"}
So we take the parsed time.Time
, convert it into our local time zone and format it as specified by TimeFormat
:
ts.Local().Format(timeFormat)
The result is the time string, as we see it printed later.
Reason for the observed behaviour
The time.Parse()
method handles time layouts without a time zone indicator by assuming UTC.
Source: Go documentation for time package
In the absence of a time zone indicator,
time.Parse()
returns a time in UTC.
Remember above that we use zerolog.TimeFieldFormat
to format and then parse the time again?
In your example, the format is "2006-01-02 15:04:05"
... no time zone indicator.
Let's say ConsoleWriter
sees the following log:
{"level":"info","time":"2022-10-06 20:54:52","message":"wrong time default"}
Parsing it again leads to "2022-10-06 20:54:52 UTC" (due to the missing time zone indicator).
The formatting with ts.Local().Format(timeFormat)
then converts from UTC to your local time zone again.
Adding or subtracting the hours accordingly. Leading to the wrong output.
Solution
Add a time zone indicator to your layout so Go doesn't end up assuming UTC.
timeFormat := "2006-01-02 15:04:05 MST"
Maybe a diagram is more accessible than my kind of unstructured thoughts.
This happens when we use a time format without a time zone indicator. Go assumes UTC, and we falsely convert from UTC to our time zone again.
On the other hand: If we use a time format with a time zone indicator, Go can restore the time zone, doesn't convert, and the result is correct.
@pscheid92 Thanks for your detailed answer, it's very clear. I have a question: Is it possible to replace time.Parse() with time.ParseInLocation() to solve this problem? zerolog/console.go
|
🤔 Could be a solution I think.
But I still try to wrap my head around the second remark:
WDYT @rs? |
Playing around with it locally looked good to me 🤔 |
I'm fine with a local tz default on console writer. |
) Closes issue #483 Before: We use time.Parse which defaults to TZ UTC if there is no time zone indicator specified in the time layout string. During the reparsing in ConsoleWriter we therefore added the TZ difference to UTC twice. After: We use time.ParseInLocal where we need to provide a dedicated fallback TZ as a fallback. Since we now fallback to the local TZ, we don't add the TZ difference to UTC twice.
…s#497) Closes issue rs#483 Before: We use time.Parse which defaults to TZ UTC if there is no time zone indicator specified in the time layout string. During the reparsing in ConsoleWriter we therefore added the TZ difference to UTC twice. After: We use time.ParseInLocal where we need to provide a dedicated fallback TZ as a fallback. Since we now fallback to the local TZ, we don't add the TZ difference to UTC twice.
Code:
Output:
The local time is 2022-09-23 21:19:29 and the UTC time is 2022-09-23 13:19:29, but the console output time is 2022-09-24 05:19:29 .
This issue is caused by #415 .
The text was updated successfully, but these errors were encountered: