Browse Source

feat: add timezone support (#2064)

* feat: add timezone support

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

* docs: add timezone example doc

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

* docs: add IANA db links

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

---------

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>
Jason Lyu 1 year ago
parent
commit
9b3d6a2790

+ 9 - 0
docs/en_US/configuration/global_configurations.md

@@ -46,6 +46,15 @@ basic:
 
 When the user sets the value of the environment variable named KuiperSyslogKey to true, the log will be printed to the syslog.
 
+## Timezone
+
+```yaml
+# The global time zone from the IANA time zone database, or UTC if not set.
+timezone: UTC
+```
+
+The global time zone configuration based on the [IANA time zone database](https://www.iana.org/time-zones), if it is left blank, `UTC` will be used as the default time zone, and if it is set to `Local`, the system time zone will be used.
+
 ## Cli Addr
 
 ```yaml

+ 9 - 0
docs/zh_CN/configuration/global_configurations.md

@@ -44,6 +44,15 @@ basic:
 
 用户将名为 KuiperSyslogKey 的环境变量的值设置为 true 时,日志将打印到系统日志中。
 
+## 时区配置
+
+```yaml
+# The global time zone from the IANA time zone database, or UTC if not set.
+timezone: UTC
+```
+
+基于 [IANA 时区数据库](https://www.iana.org/time-zones)的全局时区配置,如果留空则使用 `UTC` 作为默认时区,设置为 `Local` 时则使用系统时区。
+
 ## Cli 地址
 
 ```yaml

+ 2 - 0
etc/kuiper.yaml

@@ -17,6 +17,8 @@ basic:
   restIp: 0.0.0.0
   # REST service port
   restPort: 9081
+  # The global time zone from the IANA time zone database, or UTC if not set.
+  timezone: UTC
   # true|false, when true, will check the RSA jwt token for rest api
   authentication: false
   #  restTls:

+ 8 - 0
internal/conf/conf.go

@@ -27,6 +27,7 @@ import (
 	"github.com/sirupsen/logrus"
 
 	"github.com/lf-edge/ekuiper/pkg/api"
+	"github.com/lf-edge/ekuiper/pkg/cast"
 )
 
 const ConfFileName = "kuiper.yaml"
@@ -126,6 +127,7 @@ type KuiperConf struct {
 		FileLog        bool     `yaml:"fileLog"`
 		RotateTime     int      `yaml:"rotateTime"`
 		MaxAge         int      `yaml:"maxAge"`
+		TimeZone       string   `yaml:"timezone"`
 		Ip             string   `yaml:"ip"`
 		Port           int      `yaml:"port"`
 		RestIp         string   `yaml:"restIp"`
@@ -228,6 +230,12 @@ func InitConf() {
 		Log.SetOutput(os.Stdout)
 	}
 
+	if Config.Basic.TimeZone != "" {
+		if err := cast.SetTimeZone(Config.Basic.TimeZone); err != nil {
+			Log.Fatal(err)
+		}
+	}
+
 	if Config.Store.Type == "redis" && Config.Store.Redis.ConnectionSelector != "" {
 		if err := RedisStorageConSelectorApply(Config.Store.Redis.ConnectionSelector, Config); err != nil {
 			Log.Fatal(err)

+ 13 - 2
pkg/cast/time.go

@@ -70,6 +70,17 @@ func init() {
 	now.TimeFormats = append(now.TimeFormats, JSISO, ISO8601)
 }
 
+var localTimeZone = time.UTC
+
+func SetTimeZone(name string) error {
+	loc, err := time.LoadLocation(name)
+	if err != nil {
+		return err
+	}
+	localTimeZone = loc
+	return nil
+}
+
 func TimeToUnixMilli(time time.Time) int64 {
 	return time.UnixNano() / 1e6
 }
@@ -110,7 +121,7 @@ func InterfaceToTime(i interface{}, format string) (time.Time, error) {
 }
 
 func TimeFromUnixMilli(t int64) time.Time {
-	return time.Unix(t/1000, (t%1000)*1e6).UTC()
+	return time.Unix(t/1000, (t%1000)*1e6).In(localTimeZone)
 }
 
 func ParseTime(t string, f string) (_ time.Time, err error) {
@@ -118,7 +129,7 @@ func ParseTime(t string, f string) (_ time.Time, err error) {
 		return time.Time{}, err
 	}
 	c := &now.Config{
-		TimeLocation: time.UTC,
+		TimeLocation: localTimeZone,
 		TimeFormats:  now.TimeFormats,
 	}
 	if f != "" {