Ver código fonte

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 ano atrás
pai
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.
 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
 ## Cli Addr
 
 
 ```yaml
 ```yaml

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

@@ -44,6 +44,15 @@ basic:
 
 
 用户将名为 KuiperSyslogKey 的环境变量的值设置为 true 时,日志将打印到系统日志中。
 用户将名为 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 地址
 ## Cli 地址
 
 
 ```yaml
 ```yaml

+ 2 - 0
etc/kuiper.yaml

@@ -17,6 +17,8 @@ basic:
   restIp: 0.0.0.0
   restIp: 0.0.0.0
   # REST service port
   # REST service port
   restPort: 9081
   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
   # true|false, when true, will check the RSA jwt token for rest api
   authentication: false
   authentication: false
   #  restTls:
   #  restTls:

+ 8 - 0
internal/conf/conf.go

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

+ 13 - 2
pkg/cast/time.go

@@ -70,6 +70,17 @@ func init() {
 	now.TimeFormats = append(now.TimeFormats, JSISO, ISO8601)
 	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 {
 func TimeToUnixMilli(time time.Time) int64 {
 	return time.UnixNano() / 1e6
 	return time.UnixNano() / 1e6
 }
 }
@@ -110,7 +121,7 @@ func InterfaceToTime(i interface{}, format string) (time.Time, error) {
 }
 }
 
 
 func TimeFromUnixMilli(t int64) time.Time {
 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) {
 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
 		return time.Time{}, err
 	}
 	}
 	c := &now.Config{
 	c := &now.Config{
-		TimeLocation: time.UTC,
+		TimeLocation: localTimeZone,
 		TimeFormats:  now.TimeFormats,
 		TimeFormats:  now.TimeFormats,
 	}
 	}
 	if f != "" {
 	if f != "" {