Golang 时间戳格式化的一个技巧

Golang 时间戳格式化的一个技巧

这是写Go时候 踩的一个坑经验分享(中间省去了一些波折)。

工程里面需要将一个时间戳(毫秒)转为 “2012-01-01T12:00:00.000+0800”的UTC时间格式。查阅文档(https://golang.org/pkg/time/)有Time.Format(layout) 函数可以转换。
layout 参数可以有:

const (
        ANSIC       = "Mon Jan _2 15:04:05 2006"
        UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
        RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
        RFC822      = "02 Jan 06 15:04 MST"
        RFC822Z     = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
        RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
        RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
        RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
        RFC3339     = "2006-01-02T15:04:05Z07:00"
        RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
        Kitchen     = "3:04PM"
        // Handy time stamps.
        Stamp      = "Jan _2 15:04:05"
        StampMilli = "Jan _2 15:04:05.000"
        StampMicro = "Jan _2 15:04:05.000000"
        StampNano  = "Jan _2 15:04:05.000000000"
)

对比参数RFC3339Nano 最为接近。之后~bibibaba~ 写代码,打日志输出结果查看。

func TimestampToUtcIso8601(timestamp int64) {
    t := time.Unix(0, timestamp * 1000000)
    s := t.Format(time.RFC3339Nano)

    fmt.Println(s)
}

上面代码读解:原来的输入是毫秒的,Time.Unix() 函数可以在参数1输入一个秒为单位的参数,也可参数2 输入为纳秒的参数。由于我们的原来参数是毫秒,而且格式化后需要格式也是精确到毫秒,所以上面timestamp * 1000000 来转化为纳秒,在参数2 输入。

使用时间戳1558076828941 测试,结果:2019-05-17T15:07:08.941+08:00,
测试了好几组数据都OK,虽然这个格式不是我要的,不过没问题,对这个字符串做下截取就可以了。

但当把时间戳改为1558076828000 时候(也就是说毫秒部分如果为0),傻眼了,
结果是:2019-05-17T15:07:08+08:00,毫秒部分如果为0 的时间戳,格式化结果会少了毫秒的尾部。

为解决输出格式不一,首先想到的是,针对这两个格式,做个分支的情况的判断截取,针对后面的没有毫秒的情况格式,需要拼凑补上毫秒部分,使得函数输出格式统一。

有没有办法,使得Time.format 输出格式是统一的?这样在截取时候,更为方便。思考了若干分钟后,想到了一个办法:
我们在转化为纳秒后,在加1。
也就是上面的t这样创建: t := time.Unix(0, timestamp * 1000000+1),这样的format 后的结果,就是2019-05-17T15:07:08.941000001+08:00 这样的精确到纳秒的、长长的、统一结果了,我们在对其进行字符串截取,就方便多了。

最终代码:

func TimestampToUtcIso8601(timestamp int64) string {
    t := time.Unix(0, timestamp * 1000000 + 1)
    s := t.Format(time.RFC3339Nano)

    if len(s) != 35 { // 2019-05-17T15:07:08.941000001+08:00   
        return "1970-01-01T00:00:00.000+0800"
    }

    return s[:23] + s[29:32] + s[33:]
}

这次的技巧,在于毫秒转纳秒时候,再加上1 ,使得毫秒之下部分肯定不为0,使得格式化输出统一了,省去了Time.Format 输出格式可能不一致,而需要的分支判断截取。

(全文完)

(欢迎转载本站文章,但请注明作者和出处 云域 – Yuccn

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注