两个不同的位置对象使用相同的时间进行比较失败?

huangapple go评论98阅读模式
英文:

time comparison fails for identical times using two different location objects?

问题

我期望time.Now().In(location)返回的对象在相同的时刻进行比较时是相同的,即使location对象是不同的,只要这些location对象是使用相同的name字符串创建的。

为什么这个期望没有成立?

package main

import (
	"fmt"
	"time"

	"log"
)

func main() {
	const USPacificTimeZone = "US/Pacific"

	location, err := time.LoadLocation(USPacificTimeZone)
	if err != nil {
		log.Fatal(fmt.Sprintf("Couldn't load timezone: %v", err))
	}
	// 与上面的location完全相同,只是一个新的实例
	location2, err := time.LoadLocation(USPacificTimeZone)
	if err != nil {
		log.Fatal(fmt.Sprintf("Couldn't load timezone: %v", err))
	}

	now := time.Now()
	fmt.Printf("使用相同的location对象的时间:%v\n",
		now.In(location) == now.In(location))
	// 输出:使用相同的location对象的时间:true

	// 使用(相同的)location2 导致时间不同???
	fmt.Printf("使用不同的location对象的时间:%v\n",
		now.In(location) == now.In(location2))
	// 输出:使用不同的location对象的时间:false
}
英文:

I am expecting time.Now().In(location) objects to compare as identical if they are for the same moment, even though the location objects are different, as long as the location objects are created using the same name string.

Why doesn't that expectation hold?

package main

import (
	"fmt"
	"time"

	"log"
)

func main() {
	const USPacificTimeZone = "US/Pacific"

	location, err := time.LoadLocation(USPacificTimeZone)
	if err != nil {
		log.Fatal(fmt.Sprintf("Couldn't load timezone: %v", err))
	}
	// Exactly the same as location above, just a new instance
	location2, err := time.LoadLocation(USPacificTimeZone)
	if err != nil {
		log.Fatal(fmt.Sprintf("Couldn't load timezone: %v", err))
	}

	now := time.Now()
	fmt.Printf("Times using same location object: %v\n",
		now.In(location) == now.In(location))
	// prints:  Times using same location object: true

	// Using (the identical) location2 causes the times to be different???
	fmt.Printf("Times using different location objects: %v\n",
		now.In(location) == now.In(location2))
	// prints:  Times using different location objects: false
}

答案1

得分: 4

使用Equal方法来比较时间点:

fmt.Printf("Times using different location objects: %v\n",
    now.In(location).Equal(now.In(location2)))   // 输出 true

Time类型文档描述了使用==比较Time值的陷阱:

注意,Go的==运算符不仅比较时间点,还比较时区和单调时钟读数。因此,Time值在用作映射或数据库键之前,应确保所有值都设置了相同的时区,可以通过使用UTC或Local方法来实现,并通过设置t = t.Round(0)来去除单调时钟读数。一般来说,优先使用t.Equal(u)而不是t == u,因为t.Equal使用了最准确的比较方法,并正确处理了只有一个参数具有单调时钟读数的情况。

英文:

Use the Equal method to compare instants in time:

fmt.Printf("Times using different location objects: %v\n",
	now.In(location).Equal(now.In(location2)))   // prints true

The Time type documentation describes the pitfalls of comparing Time values with ==:

> Note that the Go == operator compares not just the time instant but also the Location and the monotonic clock reading. Therefore, Time values should not be used as map or database keys without first guaranteeing that the identical Location has been set for all values, which can be achieved through use of the UTC or Local method, and that the monotonic clock reading has been stripped by setting t = t.Round(0). In general, prefer t.Equal(u) to t == u, since t.Equal uses the most accurate comparison available and correctly handles the case when only one of its arguments has a monotonic clock reading.

huangapple
  • 本文由 发表于 2022年6月9日 06:01:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/72552693.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定