时间处理看似简单,实则不然。关于时间的错误假设通常包括以下几点:

  • 一分钟有 60 秒
  • 一小时有 60 分钟
  • 一天有 24 小时
  • 一周有 7 天
  • 一年 365 天

还有更多,具体可参考 Falsehoods programmers believe about time

例如,在一个时间点上加上 24 小时并不总是产生一个新的日历日。

为什么常识性的认知是错误的呢?因为地球自转的不均匀性和长期变慢性,会存在时间修正的情况,比如闰秒,闰年等。

因此,在处理时间时始终使用 "time" 包,因为它有助于以更安全、更准确的方式处理这些不正确的假设。

  • 使用 time.Time 表达瞬时时间

在处理时间的瞬间时使用 time.Time,在比较、添加或减去时间时使用 time.Time 中的方法。

// Bad
func isActive(now, start, stop int) bool {
  return start <= now && now < stop
}

// God
func isActive(now, start, stop time.Time) bool {
  return (start.Before(now) || start.Equal(now)) && now.Before(stop)
}
  • 使用 time.Duration 表达时间段 ```go // Bad func poll(delay int) { for { // ... time.Sleep(time.Duration(delay) * time.Millisecond) } } poll(10) // 是几秒钟还是几毫秒?

// Good func poll(delay time.Duration) { for { // ... time.Sleep(delay) } } poll(10*time.Second) // 代码即注释

回到第一个例子,在一个时间时刻加上 24 小时,我们用于添加时间的方法取决于意图。如果我们想要下一个日历日(当前天的下一天)的同一个时间点,我们应该使用 `Time.AddDate`。但是,如果我们想保证某一时刻比前一时刻晚 24 小时,我们应该使用`Time.Add`。
```go
newDay := t.AddDate(0 /* years */, 0 /* months */, 1 /* days */)
maybeNewDay := t.Add(24 * time.Hour)
  • 对外部系统使用 time.Time 和 time.Duration

尽可能在与外部系统交互中使用 time.Timetime.Duration

(1)Command-line 标志:flag 通过 time.ParseDuration 支持 time.Duration

(2)JSON:encoding/json 通过其 Time.UnmarshalJSON 方法支持将 time.Time 编码为 RFC 3339 字符串;

(3)SQL:database/sql 支持将 DATETIMETIMESTAMP 列转换为 time.Time,如果底层驱动程序支持则返回;

(4)YAML:gopkg.in/yaml.v2 支持将 time.Time 作为 RFC 3339 字符串,并通过 time.ParseDuration 支持 time.Duration

当不能在这些交互中使用 time.Duration 时,请使用 intfloat64,并在字段名称中包含单位。

例如,由于 encoding/json 不支持 time.Duration,因此该单位包含在字段的名称中。

// Bad
// {"interval": 2}
type Config struct {
  Interval int `json:"interval"`
}

// Good
// {"intervalMillis": 2000}
type Config struct {
  IntervalMillis int `json:"intervalMillis"`
}

当在这些交互中不能使用 time.Time 时,除非达成一致,否则使用 string 和 RFC 3339 中定义的格式时间戳。默认情况下,Time.UnmarshalText 使用此格式,并可通过 time.RFC3339 在 Time.Format 和 time.Parse 中使用。

尽管这在实践中并不成问题,但请记住,time 包不支持解析闰秒时间戳(issue 8728),也不在计算中考虑闰秒(issue 15190)。如果您比较两个时刻,则差异将不包括这两个时刻之间可能发生的闰秒。

powered by Gitbook该文章修订时间: 2024-03-22 15:30:00

results matching ""

    No results matching ""