golang time 格式详解

银冰雪千载 · · 18648 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

神奇时刻:2006-01-02 15:04:05

1 官方文档

time package(需科学上网查看):https://golang.org/pkg/time/

2 自定义时间格式

在看代码之前,先问一个关键问题:你懂 2006-01-02 15:04:05 么?不懂还是看代码吧!

package main

import (
    "fmt"
    "time"
)

func main() {
    // 使用系统默认格式打印当前时间
    t1 := time.Now();
    fmt.Println("t1:", t1)

    // 自定义格式,相当于Java中的时间格式:yyyy-MM-dd HH:mm:ss
    t2 := t1.Format("2006-01-02 15:04:05")
    fmt.Println("t2:", t2)

    // 换个时间定义格式不行么?答案:不行
    t3 := t1.Format("2018-10-01 15:18:00")
    fmt.Println("t3:", t3)

    // 自定义解析时间字符串格式
    t4, _ := time.Parse("2006-01-02 15:04:05", "2018-10-01 14:51:00")
    fmt.Println("t4:", t4)
}

示例输出:

t1: 2018-10-01 15:35:54.7057525 +0800 CST m=+0.006020701
t2: 2018-10-01 15:35:54
t3: 1108-100-10 15:108:00
t4: 2018-10-01 14:51:00 +0000 UTC

简而言之,其他常规语言使用字母 “ymd” 编写时间格式,而 golang 使用固定的时刻 "2006-01-02 15:04:05" 编写时间格式。 优点就是所见即所得,立刻看到效果,缺点就是,你要记住这个时刻,这是目前为止遇到的第一个挑战。至于为什么是这个时时刻?它有什么意义?我不知道。

标准库内置定义的时间格式常量如下:

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"
)

看了之后,叹了口气,为啥常用的 "2006-01-02 15:04:05" 时间格式都没有,看来以后还得自食其力。

3 时区

由于世界各国家与地区经度不同,地方时也有所不同,因此会划分为不同的时区。正式的时区划分,其中包括24个时区,每一时区由一个英文字母表示。每隔经度15°划分一个时区。

3.1 如何计算区时?

计算的区时=已知区时-(已知区时的时区-要计算区时的时区),(注:东时区为正,西时区为负)。

下面举例加以说明:

例1:已知东京(东九区)时间为5月1日12:00,求北京(东八区)的区时?

北京时间=12:00-(9-8)=11:00(即北京时间为5月1日11:00)。

3.2 UTC

UTC 不属于任意时区 。协调世界时,又称世界统一时间,世界标准时间,国际协调时间,简称 UTC。

3.3 时区解析

下面是几个解析时区的例子,这个问题困了我一周。代码如下:

// 考虑时区:下面对么?答案:不对
t5, _ := time.Parse("2006-01-02T15:04:05Z07:00", "2018-10-01T16:27:00Z08:00")
fmt.Println("t5:", t5) // 输出:t5: 0001-01-01 00:00:00 +0000 UTC

// 考虑时区:上面正确的格式是把 "Z" 替换成 "+" 或者 "-",分别代表正负时区。
t6, _ := time.Parse("2006-01-02T15:04:05Z07:00", "2018-10-01T16:27:00+08:00")
fmt.Println("t6:", t6) // 输出:t6: 2018-10-01 16:27:00 +0800 CST

// 考虑时区:如果解析的格式不带时区,将由 time.ParseInLocation 第三个参数决定
t7, _ := time.ParseInLocation("2006-01-02T15:04:05", "2018-10-01T16:27:00", time.Local)
fmt.Println("t7:", t7) // 输出:t7: 2018-10-01 16:27:00 +0800 CST

// 考虑时区:使用 UTC
t8, _ := time.ParseInLocation("2006-01-02T15:04:05", "2018-10-01T16:27:00", time.UTC)
fmt.Println("t8:", t8) // 输出:t8: 2018-10-01 16:27:00 +0000 UTC

官方例子代码如下:

// See the example for Time.Format for a thorough description of how
// to define the layout string to parse a time.Time value; Parse and
// Format use the same model to describe their input and output.

// longForm shows by example how the reference time would be represented in
// the desired layout.
const longForm = "Jan 2, 2006 at 3:04pm (MST)"
t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
fmt.Println(t)

// shortForm is another way the reference time would be represented
// in the desired layout; it has no time zone present.
// Note: without explicit zone, returns time in UTC.
const shortForm = "2006-Jan-02"
t, _ = time.Parse(shortForm, "2013-Feb-03")
fmt.Println(t)

// Some valid layouts are invalid time values, due to format specifiers
// such as _ for space padding and Z for zone information.
// For example the RFC3339 layout 2006-01-02T15:04:05Z07:00
// contains both Z and a time zone offset in order to handle both valid options:
// 2006-01-02T15:04:05Z
// 2006-01-02T15:04:05+07:00
t, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
fmt.Println(t)
t, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05+07:00")
fmt.Println(t)
_, err := time.Parse(time.RFC3339, time.RFC3339)
fmt.Println("error", err) // Returns an error as the layout is not a valid time value

输出如下:

2013-02-03 19:54:00 -0800 PST
2013-02-03 00:00:00 +0000 UTC
2006-01-02 15:04:05 +0000 UTC
2006-01-02 15:04:05 +0700 +0700
error parsing time "2006-01-02T15:04:05Z07:00": extra text: 07:00

官方解释很清楚,对于 time.RFC3339 (2006-01-02T15:04:05Z07:00) 中的 Z , 包含单独的 "Z" 或者是包含正负号的时区偏移都是有效格式,例如:

  • 2006-01-02T15:04:05Z
  • 2006-01-02T15:04:05+07:00

更多关于 time.Parse 函数的详情可参考:官方文档 time.Parse 说明


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:银冰雪千载

查看原文:golang time 格式详解

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

18648 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传