mirror of
https://gitee.com/johng/gf.git
synced 2024-11-29 18:57:44 +08:00
improve function SetTimeZone for package gtime (#2389)
* improve logging feature, add LevelPrint configuration for glog.Logger; add package internal/instance * improve command build * add default logger for panic message printing if no logger set * up * fix scheduler when timer triggers in less than one second for package gcron * up * improve function SetTimeZone for package gtime * improve function SetTimeZone for package gtime * improve function SetTimeZone for package gtime * up
This commit is contained in:
parent
ae4f14c2e2
commit
4bb88027d8
@ -12,7 +12,6 @@ package gtime
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -102,28 +101,6 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// SetTimeZone sets the time zone for current whole process.
|
||||
// The parameter `zone` is an area string specifying corresponding time zone,
|
||||
// eg: Asia/Shanghai.
|
||||
//
|
||||
// This should be called before package "time" import.
|
||||
// Please refer to issue: https://github.com/golang/go/issues/34814
|
||||
func SetTimeZone(zone string) (err error) {
|
||||
location, err := time.LoadLocation(zone)
|
||||
if err != nil {
|
||||
err = gerror.Wrapf(err, `time.LoadLocation failed for zone "%s"`, zone)
|
||||
return err
|
||||
}
|
||||
var (
|
||||
envKey = "TZ"
|
||||
envValue = location.String()
|
||||
)
|
||||
if err = os.Setenv(envKey, envValue); err != nil {
|
||||
err = gerror.Wrapf(err, `set environment failed with key "%s", value "%s"`, envKey, envValue)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Timestamp retrieves and returns the timestamp in seconds.
|
||||
func Timestamp() int64 {
|
||||
return Now().Timestamp()
|
||||
|
@ -7,21 +7,72 @@
|
||||
package gtime
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
)
|
||||
|
||||
var (
|
||||
// locationMap is time zone name to its location object.
|
||||
// Time zone name is like: Asia/Shanghai.
|
||||
locationMap = make(map[string]*time.Location)
|
||||
|
||||
// locationMu is used for concurrent safety for `locationMap`.
|
||||
locationMu = sync.RWMutex{}
|
||||
setTimeZoneMu sync.Mutex
|
||||
setTimeZoneName string
|
||||
zoneMap = make(map[string]*time.Location)
|
||||
zoneMu sync.RWMutex
|
||||
)
|
||||
|
||||
// SetTimeZone sets the time zone for current whole process.
|
||||
// The parameter `zone` is an area string specifying corresponding time zone,
|
||||
// eg: Asia/Shanghai.
|
||||
//
|
||||
// PLEASE VERY NOTE THAT:
|
||||
// 1. This should be called before package "time" import.
|
||||
// 2. This function should be called once.
|
||||
// 3. Please refer to issue: https://github.com/golang/go/issues/34814
|
||||
func SetTimeZone(zone string) (err error) {
|
||||
setTimeZoneMu.Lock()
|
||||
defer setTimeZoneMu.Unlock()
|
||||
if setTimeZoneName != "" && !strings.EqualFold(zone, setTimeZoneName) {
|
||||
return gerror.NewCodef(
|
||||
gcode.CodeInvalidOperation,
|
||||
`process timezone already set using "%s"`,
|
||||
setTimeZoneName,
|
||||
)
|
||||
}
|
||||
defer func() {
|
||||
if err == nil {
|
||||
setTimeZoneName = zone
|
||||
}
|
||||
}()
|
||||
|
||||
// Load zone info from specified name.
|
||||
location, err := time.LoadLocation(zone)
|
||||
if err != nil {
|
||||
err = gerror.WrapCodef(gcode.CodeInvalidParameter, err, `time.LoadLocation failed for zone "%s"`, zone)
|
||||
return err
|
||||
}
|
||||
|
||||
// Update the time.Local for once.
|
||||
time.Local = location
|
||||
|
||||
// Update the timezone environment for *nix systems.
|
||||
var (
|
||||
envKey = "TZ"
|
||||
envValue = location.String()
|
||||
)
|
||||
if err = os.Setenv(envKey, envValue); err != nil {
|
||||
err = gerror.WrapCodef(
|
||||
gcode.CodeUnknown,
|
||||
err,
|
||||
`set environment failed with key "%s", value "%s"`,
|
||||
envKey, envValue,
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ToLocation converts current time to specified location.
|
||||
func (t *Time) ToLocation(location *time.Location) *Time {
|
||||
newTime := t.Clone()
|
||||
@ -39,18 +90,18 @@ func (t *Time) ToZone(zone string) (*Time, error) {
|
||||
}
|
||||
|
||||
func (t *Time) getLocationByZoneName(name string) (location *time.Location, err error) {
|
||||
locationMu.RLock()
|
||||
location = locationMap[name]
|
||||
locationMu.RUnlock()
|
||||
zoneMu.RLock()
|
||||
location = zoneMap[name]
|
||||
zoneMu.RUnlock()
|
||||
if location == nil {
|
||||
location, err = time.LoadLocation(name)
|
||||
if err != nil {
|
||||
err = gerror.Wrapf(err, `time.LoadLocation failed for name "%s"`, name)
|
||||
}
|
||||
if location != nil {
|
||||
locationMu.Lock()
|
||||
locationMap[name] = location
|
||||
locationMu.Unlock()
|
||||
zoneMu.Lock()
|
||||
zoneMap[name] = location
|
||||
zoneMu.Unlock()
|
||||
}
|
||||
}
|
||||
return
|
||||
|
@ -78,9 +78,3 @@ func Benchmark_Datetime(b *testing.B) {
|
||||
gtime.Datetime()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_SetTimeZone(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
gtime.SetTimeZone("Asia/Shanghai")
|
||||
}
|
||||
}
|
||||
|
@ -17,12 +17,8 @@ import (
|
||||
func ExampleSetTimeZone() {
|
||||
gtime.SetTimeZone("Asia/Shanghai")
|
||||
fmt.Println(gtime.Datetime())
|
||||
|
||||
gtime.SetTimeZone("Asia/Tokyo")
|
||||
fmt.Println(gtime.Datetime())
|
||||
// May Output:
|
||||
// 2018-08-08 08:08:08
|
||||
// 2018-08-08 09:08:08
|
||||
}
|
||||
|
||||
func ExampleTimestamp() {
|
||||
|
@ -15,14 +15,6 @@ import (
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
)
|
||||
|
||||
func Test_SetTimeZone(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
t.Assert(gtime.SetTimeZone("Asia/Shanghai"), nil)
|
||||
t.AssertNE(gtime.SetTimeZone("testzone"), nil)
|
||||
// t.Assert(time.Local.String(), "Asia/Shanghai")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_TimestampStr(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
t.AssertGT(len(gtime.TimestampMilliStr()), 0)
|
||||
|
Loading…
Reference in New Issue
Block a user