Go 标准库 time 包之 Time 结构 ( 下 )

5 点 30 就起床开工了...

上一章节,我们从宏观的角度介绍了下 Time 结构,如果你英文很厉害,其实就会发现我只是把官方文档翻译了一遍。本章节,我们继续把剩余的 Time 结构的内部文档再翻译一遍。介绍下 Time 结构的那些成员属性:wallext 还有 loc 。其实,最重要的还会上一章节中要讲但没讲的 Time 如何区分 wall clock 和 monotonic clocks 两种时钟。

我们再次熟悉下 Time 结构的源码 ( 删除了注释 )

type Time struct {

    wall uint64
    ext  int64

    loc *Location
}

可以看到有三个属性

属性 类型 说明
wall uint64 wall clock 的总秒数,其实就是时间戳,1970 年 1 月 1 日 0 时 0 分 0 秒以来的总秒数
ext int64 纳秒数
loc *Location 时区 ,默认为 nil ,也就是 UTC ,或者说格林威治时间

如果你熟悉其它语言的日期时间处理模块,就会有一个担忧,因为它们中有很多存储时间戳使用的是 int 的数据类型,在 32 位机器上,能表示的日期是 范围是1970 年 1 月 1 日到 2038 年 1 月 19 日。( 现在的电脑基本上是 64 位,能表示一个非常非常大的时刻 )

Go 语言 ,在出生那刹那开始,使用的就是 uint64,如果全部用来表示时间,那将会是一个非常大非常大的时间。甚至超过 9999-12-31 23:59:59

我们看一下以下代码的输出结果就知道了

package main

import "time"

const UINT64_MIN uint64 = 0
const UINT64_MAX uint64 = ^uint64(0)
const form = "2006-01-02 15:04:05"

func main() {

    t, _ := time.Parse(form, "9999-12-31 23:59:59")

    println("unint64 的最大值为:", UINT64_MAX)
    println("9999-12-31 23:59:59 的时间戳为:", t.Unix())
}

输出结果为

unint64 的最大值为: 18446744073709551615
9999-12-31 23:59:59 的时间戳为: 253402300799

可以看到,253402300799 远远小于 18446744073709551615,所以,wall 中有些位 ( 总共 64 位 ) 可以拿来做其它事情。比如标识是否包含了 monotonic clocks 等。

实际上,Time 结构也是这么做的,我们可以看看官方文档对 wallext 的注释。

// wall and ext encode the wall time seconds, wall time nanoseconds,
// and optional monotonic clock reading in nanoseconds.
//
// From high to low bit position, wall encodes a 1-bit flag (hasMonotonic),
// a 33-bit seconds field, and a 30-bit wall time nanoseconds field.
// The nanoseconds field is in the range [0, 999999999].
// If the hasMonotonic bit is 0, then the 33-bit field must be zero
// and the full signed 64-bit wall seconds since Jan 1 year 1 is stored in ext.
// If the hasMonotonic bit is 1, then the 33-bit field holds a 33-bit
// unsigned wall seconds since Jan 1 year 1885, and ext holds a
// signed 64-bit monotonic clock reading, nanoseconds since process start.

注释上说

  1. wallext 两个属性分别用于编码 wall time 中的总秒数和 wall time 中的纳秒数,还可能包含了可选的 monotonic clock 的纳秒格式的读数

  2. 从高位到低位, wall 编码时,第一个位 ( 1-bit ) 是一个标识符位,用于标识是否包含了 monotonic clock 。 可以将 wall 与 hasMonotonic 做位与 ( & ) 操作来检查。

    hasMonotonic 的定义如下

    hasMonotonic = 1 << 63
    

    我们简称这个最高位为 hasMonotonic

  3. 然后接下来的 33 位和最后的 30 位,分别用于编码编码 wall time 中的总秒数和 wall time 中的纳秒数,纳秒的取值范围是 [0, 999999999]

  4. 如果 hasMonotonic 位的取值为 0 ,那么中间的 33 位会被设置为且必须为 0 ,然后会将自 1 年 1 月 1 日 0 时 0 分 0 纳秒的有符号的 wall clock 总秒数都存储在 ext 中。但是,纳秒数还是存储在原来的位置,也就是 wall 的剩余的 30 位

  5. 如果 hasMonotonic 位的取值为 1 ,那么中间的 33 位存储了自 1885 1 年 1 月 1 日 0 时 0 分 0 纳秒的以来的无符号的 wall clock 的总秒数,而 ext 则存储了有符号的 64 位的 monotonic clock 读数,也就是,进程创建以来的总纳秒数

而对于 loc 这个属性,官方文档的解释为

// loc specifies the Location that should be used to
// determine the minute, hour, month, day, and year
// that correspond to this Time.
// The nil location means UTC.
// All UTC times are represented with loc==nil, never loc==&utcLoc.

意思就是说

loc 用于指定了用于确定与此时间对应的分钟,小时,月,日和年的时区。

如果 loc 的值为 nil ,则表示 UTC 。 所有的 UTC 时间都用 loc == nil 表示,而不是 loc ==&utcLoc

结束语

就先这样了,Time 结构的介绍到此完毕,我要出门了...

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.