时间处理很复杂。关于时间的错误假设通常包括以下几点。
- 一天有 24 小时
- 一小时有 60 分钟
- 一周有七天
- 一年 365 天
- 还有更多
例如,1 表示在一个时间点上加上 24 小时并不总是产生一个新的日历日。
因此,在处理时间时始终使用 "time" 包,因为它有助于以更安全、更准确的方式处理这些不正确的假设。
使用 time.Time 表达瞬时时间
在处理时间的瞬间时使用 time.Time,在比较、添加或减去时间时使用 time.Time 中的方法。
| Bad | Good |
|---|---|
|
|
使用 time.Duration 表达时间段
在处理时间段时使用 time.Duration .
| Bad | Good |
|---|---|
|
|
回到第一个例子,在一个时间瞬间加上 24 小时,我们用于添加时间的方法取决于意图。如果我们想要下一个日历日(当前天的下一天)的同一个时间点,我们应该使用 Time.AddDate。但是,如果我们想保证某一时刻比前一时刻晚 24 小时,我们应该使用 Time.Add。
newDay := t.AddDate(0 /* years */, 0 /* months */, 1 /* days */)
maybeNewDay := t.Add(24 * time.Hour)
对外部系统使用 time.Time 和 time.Duration
尽可能在与外部系统的交互中使用 time.Duration 和 time.Time 例如 :
- Command-line 标志:
flag通过time.ParseDuration支持time.Duration - JSON:
encoding/json通过其UnmarshalJSONmethod 方法支持将time.Time编码为 RFC 3339 字符串 - SQL:
database/sql支持将DATETIME或TIMESTAMP列转换为time.Time,如果底层驱动程序支持则返回 - YAML:
gopkg.in/yaml.v2支持将time.Time作为 RFC 3339 字符串,并通过time.ParseDuration支持time.Duration。
当不能在这些交互中使用 time.Duration 时,请使用 int 或 float64,并在字段名称中包含单位。
例如,由于 encoding/json 不支持 time.Duration,因此该单位包含在字段的名称中。
| Bad | Good |
|---|---|
|
|
当在这些交互中不能使用 time.Time 时,除非达成一致,否则使用 string 和 RFC 3339 中定义的格式时间戳。默认情况下,Time.UnmarshalText 使用此格式,并可通过 time.RFC3339 在 Time.Format 和 time.Parse 中使用。
尽管这在实践中并不成问题,但请记住,"time" 包不支持解析闰秒时间戳(8728),也不在计算中考虑闰秒(15190)。如果您比较两个时间瞬间,则差异将不包括这两个瞬间之间可能发生的闰秒。