英文:
Zone method from time package doesn't return updated timezone if timezone is changed during process execution
问题
我已经为您翻译了以下的Go代码,用于获取系统时区。它可以正常工作并返回系统的当前时区。问题在于,如果在进程执行期间更改时区,则不会返回更新后的时区,而只会返回旧的时区。
package main
import (
"fmt"
"time"
)
func main() {
for i := 0; i < 10; i++ {
t := time.Now()
zone, offset := t.Zone()
fmt.Println(zone, offset)
z, _ := t.Zone()
fmt.Println("时区", z)
}
}
希望对您有所帮助!
英文:
I have written below a simple Go code to get the system timezone. It works fine and returns the system's current timezone. The issue is if I change the timezone in-between process execution then it doesn't return the updated timezone. It returns only the old timezone.
package main
import (
"fmt"
"time"
)
func main() {
for i := 0; i < 10; i++ {
t := time.Now()
zone, offset := t.Zone()
fmt.Println(zone, offset)
z, _ := t.Zone()
fmt.Println("timezone", z)
}
}
答案1
得分: 3
如果你查看一下time包的源代码,你会发现本地位置(local Location)在应用程序启动时只设置一次,通过sync.Once
来实现(更准确地说,是在第一次调用.get()
获取时区信息时):
// localLoc is separate so that initLocal can initialize
// it even if a client has changed Local.
var localLoc Location
var localOnce sync.Once
func (l *Location) get() *Location {
if l == nil {
return &utcLoc
}
if l == &localLoc {
localOnce.Do(initLocal)
}
return l
}
现在,initLocal
是与平台相关的,因为不同的平台处理时区的方式不同;例如,在Windows平台上,你可以这样实现:
func initLocal() {
var i syscall.Timezoneinformation
if _, err := syscall.GetTimeZoneInformation(&i); err != nil {
localLoc.name = "UTC"
return
}
initLocalFromTZI(&i)
}
从这里开始,你可以通过查看源代码来了解如何在你的应用程序中实现这一功能。例如,在Windows上,你可以通过调用syscall.Timezoneinformation
结构体的Bias
和DaylightBias
字段来获取以分钟为单位的UTC偏移量。
英文:
if you have a look at the source code of the time package, you can find that the local Location is set once at the start of the application, by a sync.Once
(or more precisely: when the tz information is obtained by a call to .get()
for the first time):
// localLoc is separate so that initLocal can initialize
// it even if a client has changed Local.
var localLoc Location
var localOnce sync.Once
func (l *Location) get() *Location {
if l == nil {
return &utcLoc
}
if l == &localLoc {
localOnce.Do(initLocal)
}
return l
}
Now, initLocal
is platform-dependent since different platforms handle time zones differently; for example for Windows you have:
func initLocal() {
var i syscall.Timezoneinformation
if _, err := syscall.GetTimeZoneInformation(&i); err != nil {
localLoc.name = "UTC"
return
}
initLocalFromTZI(&i)
}
From here on, you could work your way through the source code to get an idea how you can implement this for your application. For example on Windows, you could get the UTC offset in minutes by calling the Bias
and DaylightBias
fields of the syscall.Timezoneinformation
struct.
答案2
得分: 0
感谢,@MrFuppes
通过从Golang调用Win32 API,问题得到解决。以下是代码片段。
package main
import (
"fmt"
"time"
"syscall"
"strconv"
"unicode/utf16"
)
func main() {
for index := 0; index < 10; index++ {
now := time.Now()
timeZone, _ := now.Zone()
fmt.Println("timezone", timeZone)
var itz syscall.Timezoneinformation
if _, err := syscall.GetTimeZoneInformation(&itz); err != nil {
fmt.Println("GetTimeZoneInformation failed")
}
fmt.Println(strconv.Itoa(int(itz.Bias)))
var newBytes []uint16
const intBits = 4 + 4*(^uint(0)>>63)
if intBits == 4 {
//For 32 bit
bytes := itz.StandardName
for i := 0; i < len(bytes); i++ {
c := bytes[i]
if c == 0 {
break
}
newBytes = append(newBytes, c)
}
} else if intBits == 8 {
//For 64 bit
bytes := itz.StandardName
for i := 0; ; i++ {
c := bytes[i]
if c == 0 || i == 2048 {
break
}
newBytes = append(newBytes, c)
}
}
tzName := string(utf16.Decode(newBytes))
fmt.Println("Timezone StandardName: ", tzName)
}
}
希望对你有帮助!
英文:
Thanks, @MrFuppes
The issue got resolved by calling Win32 API from Golang. Below is the code snippet.
package main
import (
"fmt"
"time"
"syscall"
"strconv"
"unicode/utf16"
)
func main() {
for index := 0; index < 10; index++ {
now := time.Now()
timeZone, _ := now.Zone()
fmt.Println("timezone", timeZone)
var itz syscall.Timezoneinformation
if _, err := syscall.GetTimeZoneInformation(&itz); err != nil {
fmt.Println("GetTimeZoneInformation failed")
}
fmt.Println(strconv.Itoa(int(itz.Bias)))
var newBytes []uint16
const intBits = 4 + 4*(^uint(0)>>63)
if intBits == 4 {
//For 32 bit
bytes := itz.StandardName
for i := 0; i < len(bytes); i++ {
c := bytes[i]
if c == 0 {
break
}
newBytes = append(newBytes, c)
}
} else if intBits == 8 {
//For 64 bit
bytes := itz.StandardName
for i := 0; ; i++ {
c := bytes[i]
if c == 0 || i == 2048 {
break
}
newBytes = append(newBytes, c)
}
}
tzName := string(utf16.Decode(newBytes))
fmt.Println("Timezone StandardName: ", tzName)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论