Repository: caddyserver/caddy (language: go)

Issue:
logfile can not output localtime
hi guys, I can not output the localtime in the caddy log file.
the TS alway display UTC.
the server timezone is set,
```
               Local time: Tue 2022-09-06 15:45:55 CST
           Universal time: Tue 2022-09-06 07:45:55 UTC
                 RTC time: Tue 2022-09-06 07:45:56
                Time zone: Asia/Shanghai (CST, +0800)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
```
the log content
```
{"level":"info","ts":"2022/09/06 07:51:40","logger":"http.log.access.log0","msg":"handled request","request":{"remote_addr":"127.0.0.1:55063","uri":"/reflesh/"},"status":204}
```



Discussion / hints:
(I'm not sure why the docs aren't rendering for this property, but) you can customize the time format: https://caddyserver.com/docs/json/logging/logs/encoder/json/time_format/
See https://caddyserver.com/docs/caddyfile/directives/log#format-modules for the supported time format options. I'm not sure if any of those actually use the timezone though, it might just always be UTC.
Those are just presets. You can use any Go-supported time format, which lets you choose the time zone: https://pkg.go.dev/time#pkg-constants
I don't study Golang.
I checked the source code, find this in "encoders.go" 
```
	// time format
	var timeFormatter zapcore.TimeEncoder
	switch lec.TimeFormat {
	case "", "unix_seconds_float":
		timeFormatter = zapcore.EpochTimeEncoder
	case "unix_milli_float":
		timeFormatter = zapcore.EpochMillisTimeEncoder
	case "unix_nano":
		timeFormatter = zapcore.EpochNanosTimeEncoder
	case "iso8601":
		timeFormatter = zapcore.ISO8601TimeEncoder
	default:
		timeFormat := lec.TimeFormat
		switch lec.TimeFormat {
		case "rfc3339":
			timeFormat = time.RFC3339
		case "rfc3339_nano":
			timeFormat = time.RFC3339Nano
		case "wall":
			timeFormat = "2006/01/02 15:04:05"
		case "wall_milli":
			timeFormat = "2006/01/02 15:04:05.000"
		case "wall_nano":
			timeFormat = "2006/01/02 15:04:05.000000000"
		case "common_log":
			timeFormat = "02/Jan/2006:15:04:05 -0700"
		}
		timeFormatter = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) {
			encoder.AppendString(ts.UTC().Format(timeFormat))
		}
	}
	cfg.EncodeTime = timeFormatter
```

Yep, so it's what we told you :+1: Just put in a format that works for you. (Link above describes the format.)
sorry, I mean that the time is UTC in logfile, I want Local.
```
func (Time) Local
func (t Time) Local() Time
Local returns t with the location set to local time.
```
```
func (Time) UTC
func (t Time) UTC() Time
UTC returns t with the location set to UTC.
```

I can't set the time is Local in log file,
I guess maybe in this
```
encoder.AppendString(ts.UTC().Format(timeFormat))
```

Fix patch:
diff --git a/modules/logging/encoders.go b/modules/logging/encoders.go
index d8825d351c6..1cfab8ea607 100644
--- a/modules/logging/encoders.go
+++ b/modules/logging/encoders.go
@@ -127,6 +127,7 @@ type LogEncoderConfig struct {
 	StacktraceKey  *string `json:"stacktrace_key,omitempty"`
 	LineEnding     *string `json:"line_ending,omitempty"`
 	TimeFormat     string  `json:"time_format,omitempty"`
+	TimeLocal      bool    `json:"time_local,omitempty"`
 	DurationFormat string  `json:"duration_format,omitempty"`
 	LevelFormat    string  `json:"level_format,omitempty"`
 }
@@ -142,12 +143,21 @@ type LogEncoderConfig struct {
 //	    stacktrace_key  <key>
 //	    line_ending     <char>
 //	    time_format     <format>
+//	    time_local
 //	    duration_format <format>
 //	    level_format    <format>
 //	}
 func (lec *LogEncoderConfig) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
 	for nesting := d.Nesting(); d.NextBlock(nesting); {
 		subdir := d.Val()
+		switch subdir {
+		case "time_local":
+			lec.TimeLocal = true
+			if d.NextArg() {
+				return d.ArgErr()
+			}
+			continue
+		}
 		var arg string
 		if !d.AllArgs(&arg) {
 			return d.ArgErr()
@@ -237,7 +247,13 @@ func (lec *LogEncoderConfig) ZapcoreEncoderConfig() zapcore.EncoderConfig {
 			timeFormat = "02/Jan/2006:15:04:05 -0700"
 		}
 		timeFormatter = func(ts time.Time, encoder zapcore.PrimitiveArrayEncoder) {
-			encoder.AppendString(ts.UTC().Format(timeFormat))
+			var time time.Time
+			if lec.TimeLocal {
+				time = ts.Local()
+			} else {
+				time = ts.UTC()
+			}
+			encoder.AppendString(time.Format(timeFormat))
 		}
 	}
 	cfg.EncodeTime = timeFormatter


Test patch: