GO 中的时间操作(time & dateparse)【GO 基础】

〇、前言

日常开发过程中,对于时间的操作可谓是无处不在,但是想实现时间自由还是不简单的,多种时间格式容易混淆,那么本文将进行梳理,一起学习下。

官方提供的库是 time,功能很全面,本文也会详细介绍。

还有另外一个开源库 dateparse,使用起来比较方便,本文也会将加入示例测试出结果,以展示其优点。

一、time 库

1.1 Time 类型的结构

go 通过time.Now()来取当前时间,打印出来如下:

2023-09-15 17:59:14.2642387 +0800 CST m=+0.010202701

这里存在两个疑点:1)表示秒级的数值为什么默认为 7 位?  2)最后边的 m=... 代表什么?

1)对于时间戳来说,一般采用秒级或毫秒级。采用浮点数或定点数来表示小数部分,需要一定的字节数来存储,而为了在大多数应用场景下满足足够的精度,一般会选择使用7位数字来表示毫秒级的小数部分,从而达到既满足绝大多数需求又占用尽量上的存储。

2)m 就是 Monotonic Clocks,意思是单调时间的,所谓单调,就是只会不停的往前增长,不受校时操作的影响,这个时间是自进程启动以来的秒数。

在 go1.9 之后,结构更新为:

type Time struct { 	wall uint64 	ext  int64 	loc *Location }

Time 结构体中由三部分组成,loc 比较明了,表示时区,wall 和 ext 所存储的信息规则相对复杂,根据文档的介绍总结成了下图:

 GO 中的时间操作(time & dateparse)【GO 基础】

golang 中的 Time 结构,不像很多语言保存 Unix 时间戳(也就是最早只能表示到 1970 年 1 月 1 日),而是至少可以安全的表示 1885 年以来的时间。

下面来取当前时间测试下:

package main  import ( 	"encoding/json" 	"fmt" 	"time" )  func main() { 	now := time.Now() // 取当前时间 	time_now := now 	fmt.Println(time_now) 	for i := 0; i < 5; i++ { // 循环 0~4 共 5 此 		time_now = time_now.Add(1 * time.Second) // 每次加 1 秒 		fmt.Println(time_now) 	} 	encodeNow, _ := json.Marshal(now) // 转 json 编码 	decodeNow := time.Time{} 	json.Unmarshal(encodeNow, &decodeNow) // 将 json 编码转回 Time 	fmt.Println(decodeNow)  	equal_r := now.Equal(decodeNow) 	fmt.Println(equal_r) }

 结果如下,可见循环了五次,每次 m 的值都加 1,json 编码转换后的时间中 m 参数消失:

 GO 中的时间操作(time &amp; dateparse)【GO 基础】

1.2 获取当前时间与格式化

1.2.1 取当前时间

回去当前时间的方法很简单:

now := time.Now() fmt.Println(now) // 2023-09-18 13:51:40.8480546 +0800 CST m=+0.008992401 fmt.Println(now.String()) // 2023-09-18 13:51:40.8480546 +0800 CST m=+0.008992401

1.2.2 时间格式化

Go 语言提供了时间类型格式化函数 Format(),需要注意的是 Go 语言格式化时间模板不是常见的 Y-m-d H:i:s,而是 2006-01-02 15:04:05,也很好记忆(2006 1 2 3 4 5)。

func (t Time) Format(layout string) string {   }

time 库中,定义了年、月、日、时、分、秒、周、时区的多种表现形式,如下:

  • 年:   06/2006
  • 月:   1/01/Jan/January
  • 日:   2/02/_2
  • 时:   3/03/15/PM/pm/AM/am
  • 分:   4/04
  • 秒:   5/05
  • 周:   Mon/Monday
  • 时区:-07/-0700/Z0700/Z07:00/-07:00/MST

这些格式的形式配置,可以根据自己的需求自由组合,一下是部分组合的测试:

package main  import ( 	"fmt" 	"time" )  func main() { 	now := time.Now() 	fmt.Println(now) 	fmt.Println("2006-01-02 15:04:05             output:", now.Format("2006-01-02 15:04:05")) 	fmt.Println("2006-01-02                      output:", now.Format("2006-01-02")) 	fmt.Println("01-02-2006                      output:", now.Format("01-02-2006")) 	fmt.Println("15:03:04                        output:", now.Format("15:03:04")) 	fmt.Println("2006/01/02 15:04                output:", now.Format("2006/01/02 15:04")) 	fmt.Println("15:04 2006/01/02                output:", now.Format("15:04 2006/01/02")) 	fmt.Println("2006#01#02                      output:", now.Format("2006#01#02")) 	fmt.Println("2006$01$02                      output:", now.Format("2006$01$02")) 	fmt.Println("2006-01-02 15:04:05.000         output:", now.Format("2006-01-02 15:04:05.000")) 	fmt.Println("2006-01-02 15:04:05.000000000   output:", now.Format("2006-01-02 15:04:05.000000000")) 	fmt.Println("2006-January-02 15:04:05 Monday output:", now.Format("2006-January-02 15:04:05 Monday")) 	fmt.Println("2006-Jan-02 15:04:05 Mon        output:", now.Format("2006-Jan-02 15:04:05 Mon")) 	fmt.Println("2006-1-2 3:4:5 PM               output:", now.Format("2006-1-2 3:4:5 PM")) }

GO 中的时间操作(time &amp; dateparse)【GO 基础】

字符串类型的日期转 Time:

package main  import ( 	"fmt" 	"time" )  func main() { 	t, _ := time.ParseInLocation("2006-01-02", "2023-09-18", time.Local) // time.Local 指定本地时间 	fmt.Println(t) 	t, _ = time.ParseInLocation("2006-01-02 15:04:05", "2023-09-18 17:46:13", time.Local) 	fmt.Println(t) 	t, _ = time.ParseInLocation("2006-01-02 15:04:05", "2023-09-18", time.Local) 	fmt.Println(t) // 当时间字符串和标准字符串不统一时,转化失败 }

GO 中的时间操作(time &amp; dateparse)【GO 基础】

1.2.3 取日期的单个值

日期的组成部分比较多,下面来尝试取出各个部分的值: 

package main  import ( 	"fmt" 	"time" )  func main() { 	now := time.Now() 	// 返回日期 	year, month, day := now.Date() 	fmt.Printf("日期:%d年%d月%d日n", year, month, day) 	fmt.Println("年:", now.Year()) // int 	fmt.Println("月:", now.Month()) // time.Month 	fmt.Println("月:", now.Month().String()) 	fmt.Println("月:", int(now.Month())) 	fmt.Println("日:", now.Day()) // int  	// 时分秒 	hour, minute, second := now.Clock() 	fmt.Printf("时间:%d:%d:%dn", hour, minute, second) 	fmt.Println("时:", now.Hour()) // int 	fmt.Println("分:", now.Minute()) // int 	fmt.Println("秒:", now.Second()) // int  	fmt.Println("星期:", now.Weekday()) // time.Weekday 	fmt.Println("星期:", now.Weekday().String()) // 不能得到 一、二。。。 	fmt.Println("星期:", int(now.Weekday()))     // 可以通过取得的 1、2。。。来计算是周几 	fmt.Println("天数:", now.YearDay()) // int 	fmt.Println("时区:", now.Location()) }

GO 中的时间操作(time &amp; dateparse)【GO 基础】

1.3 日期的计算

计算之前或之后一段时间:

package main  import ( 	"fmt" 	"time" )  func main() { 	now := time.Now() 	fmt.Println(now, "(当前时间)") 	// func (t Time) AddDate(years int, months int, days int) Time 	m0 := now.AddDate(1, 1, 1) 	fmt.Println(m0, "(now.AddDate(1,1,1))") 	m00 := now.AddDate(0, 1, 1) 	fmt.Println(m00, "(now.AddDate(0,1,1))") 	// func ParseDuration(s string) (Duration, error) 	// s string:"ns", "us" (or "µs"), "ms", "s", "m", "h" 	t1, _ := time.ParseDuration("1h1m1s") // 亦可:48h1m1s 	m1 := now.Add(t1) 	fmt.Println(m1, "(1小时1分1s之后)") 	t2, _ := time.ParseDuration("-1h1m1s") 	m2 := now.Add(t2) 	fmt.Println(m2, "(1小时1分1s之前)") 	t3, _ := time.ParseDuration("-1h") 	m3 := now.Add(t3 * 3) 	fmt.Println(m3, "(3小时之前)") }

GO 中的时间操作(time &amp; dateparse)【GO 基础】

时间差和比较时间大小:

package main  import ( 	"fmt" 	"time" )  func main() { 	now := time.Now() 	fmt.Println(now, "(当前时间)") 	// func (t Time) Sub(u Time) Duration // 取时间差对象 	sub1 := now.Sub(m1) 	fmt.Println(sub1.Hours(), "(相差小时数)") 	fmt.Println(sub1.Minutes(), "(相差分钟数)") 	// time.Since(t Time) Duration // 返回当前时间与 t 的时间差,返回值是 Duration 	// time.Until(t Time) Duration // 返回 t 与当前时间的时间差,返回值是 Duration 	t1s, _ := time.ParseDuration("-1h") 	m1s := now.Add(t1s) 	fmt.Println(time.Since(m1s), "(Since)") 	fmt.Println(time.Until(m1s), "(Until)") 	// func (t Time) Before(u Time) bool // 如果 t 代表的时间点在 u 之前,返回真;否则返回假 	// func (t Time) After(u Time) bool // 如果 t 代表的时间点在 u 之后,返回真;否则返回假 	// func (t Time) Equal(u Time) bool // 比较时间是否相等,相等返回真;否则返回假 	t1m, _ := time.ParseDuration("1h") 	m1m := now.Add(t1m) 	fmt.Println(m1m) 	fmt.Println(m1m.After(now), "(After(now))") 	fmt.Println(m1m.Before(now), "(Before(now))") 	fmt.Println(now.Equal(m1m), "(Equal(m1m))") }

GO 中的时间操作(time &amp; dateparse)【GO 基础】

1.4 时间戳

如何取时间戳:

package main  import ( 	"fmt" 	"time" )  func main() { 	now := time.Now() 	fmt.Println(now, "(当前时间)") 	// 取时间戳 	fmt.Println(now.Unix())       // 当前时间戳 	fmt.Println(now.UnixMilli())  // 毫秒级时间戳 	fmt.Println(now.UnixMicro())  // 微秒级时间戳 	fmt.Println(now.UnixNano())   // 纳秒级时间戳 	fmt.Println(now.Nanosecond()) // 时间戳小数部分 单位:纳秒 }

GO 中的时间操作(time &amp; dateparse)【GO 基础】

时间戳与时间的简单转换:

package main  import ( 	"fmt" 	"time" )  func main() { 	now := time.Now() 	fmt.Println(now, "(当前时间)")  	unix := now.Unix() 	fmt.Println(unix, "(秒级时间戳)") 	t := time.Unix(unix, 0) 	fmt.Println(t, "(原时间)") 	t = time.Unix(unix, 1) // 在时间戳的基础上,加 1 纳秒 	fmt.Println(t, "(加 1 纳秒)")  	micro_unix := now.UnixMicro() 	fmt.Println(micro_unix, "(微秒级时间戳)") 	t1 := time.UnixMicro(micro_unix) 	fmt.Println(t1) }

GO 中的时间操作(time &amp; dateparse)【GO 基础】

参考:https://zhuanlan.zhihu.com/p/362936088   https://zhuanlan.zhihu.com/p/145009400  https://zhuanlan.zhihu.com/p/47754783

二、dateparse 库

dateparse 库的作用主要就是将不同格式的字符串类型的时间,转为 Time 时间类型源码地址:https://github.com/araddon/dateparse

根据本文 1.2.2 章节中第二部分 的转换方法,并不能用于全部字符串日期的转换,容易出现转换失败的情况。另外需要根据源日期的格式组织标准日期的格式,也会增加工作量。但是,当用上 dateparse 库后,这一切将变的非常简单。

dateparse 库,就是将各种类型的日期格式字符串,转换成同样的格式,参考:2006-01-02 15:04:05 +0000 UTC

具体引用的方法是func ParseLocal(datestr string, opts ...ParserOption) (time.Time, error){ },调用示例为Time_date_output := dateparse.ParseLocal(str_date_input)

以下代码是 github 上源码中的示例,供参考:

package main  import ( 	"flag" 	"fmt" 	"time"  	"github.com/scylladb/termtables" 	"github.com/araddon/dateparse" )  var examples = []string{ 	"May 8, 2009 5:57:51 PM", 	"oct 7, 1970", 	"oct 7, '70",     ... }  var ( 	timezone = "" )  func main() { 	flag.StringVar(&timezone, "timezone", "UTC", "Timezone aka `America/Los_Angeles` formatted time-zone") 	flag.Parse() // 取命令行参数 timezone  	if timezone != "" { 		loc, err := time.LoadLocation(timezone) 		if err != nil { 			panic(err.Error()) 		} 		time.Local = loc // 将默认的本地值修改为输入的本地参数 	}  	table := termtables.CreateTable()  	table.AddHeaders("Input", "Parsed, and Output as %v") 	for _, dateExample := range examples { // 循环全部日期格式字符串,并输出转换后的格式 		t, err := dateparse.ParseLocal(dateExample) 		if err != nil { 			panic(err.Error()) 		} 		table.AddRow(dateExample, fmt.Sprintf("%v", t)) 	} 	fmt.Println(table.Render()) }  /* +-------------------------------------------------------+-----------------------------------------+ | Input                                                 | Parsed, and Output as %v                | +-------------------------------------------------------+-----------------------------------------+ | May 8, 2009 5:57:51 PM                                | 2009-05-08 17:57:51 +0000 UTC           | | oct 7, 1970                                           | 1970-10-07 00:00:00 +0000 UTC           | | oct 7, '70                                            | 1970-10-07 00:00:00 +0000 UTC           | | oct. 7, 1970                                          | 1970-10-07 00:00:00 +0000 UTC           | | oct. 7, 70                                            | 1970-10-07 00:00:00 +0000 UTC           | | Mon Jan  2 15:04:05 2006                              | 2006-01-02 15:04:05 +0000 UTC           | | Mon Jan  2 15:04:05 MST 2006                          | 2006-01-02 15:04:05 +0000 MST           | | Mon Jan 02 15:04:05 -0700 2006                        | 2006-01-02 15:04:05 -0700 -0700         | | Monday, 02-Jan-06 15:04:05 MST                        | 2006-01-02 15:04:05 +0000 MST           | | Mon, 02 Jan 2006 15:04:05 MST                         | 2006-01-02 15:04:05 +0000 MST           | | Tue, 11 Jul 2017 16:28:13 +0200 (CEST)                | 2017-07-11 16:28:13 +0200 +0200         | | Mon, 02 Jan 2006 15:04:05 -0700                       | 2006-01-02 15:04:05 -0700 -0700         | | Mon 30 Sep 2018 09:09:09 PM UTC                       | 2018-09-30 21:09:09 +0000 UTC           | | Mon Aug 10 15:44:11 UTC+0100 2015                     | 2015-08-10 15:44:11 +0000 UTC           | | Thu, 4 Jan 2018 17:53:36 +0000                        | 2018-01-04 17:53:36 +0000 UTC           | | Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time) | 2015-07-03 18:04:07 +0100 GMT           | | Sun, 3 Jan 2021 00:12:23 +0800 (GMT+08:00)            | 2021-01-03 00:12:23 +0800 +0800         | | September 17, 2012 10:09am                            | 2012-09-17 10:09:00 +0000 UTC           | | September 17, 2012 at 10:09am PST-08                  | 2012-09-17 10:09:00 -0800 PST           | | September 17, 2012, 10:10:09                          | 2012-09-17 10:10:09 +0000 UTC           | | October 7, 1970                                       | 1970-10-07 00:00:00 +0000 UTC           | | October 7th, 1970                                     | 1970-10-07 00:00:00 +0000 UTC           | | 12 Feb 2006, 19:17                                    | 2006-02-12 19:17:00 +0000 UTC           | | 12 Feb 2006 19:17                                     | 2006-02-12 19:17:00 +0000 UTC           | | 14 May 2019 19:11:40.164                              | 2019-05-14 19:11:40.164 +0000 UTC       | | 7 oct 70                                              | 1970-10-07 00:00:00 +0000 UTC           | | 7 oct 1970                                            | 1970-10-07 00:00:00 +0000 UTC           | | 03 February 2013                                      | 2013-02-03 00:00:00 +0000 UTC           | | 1 July 2013                                           | 2013-07-01 00:00:00 +0000 UTC           | | 2013-Feb-03                                           | 2013-02-03 00:00:00 +0000 UTC           | | 06/Jan/2008:15:04:05 -0700                            | 2008-01-06 15:04:05 -0700 -0700         | | 06/Jan/2008 15:04:05 -0700                            | 2008-01-06 15:04:05 -0700 -0700         | | 3/31/2014                                             | 2014-03-31 00:00:00 +0000 UTC           | | 03/31/2014                                            | 2014-03-31 00:00:00 +0000 UTC           | | 08/21/71                                              | 1971-08-21 00:00:00 +0000 UTC           | | 8/1/71                                                | 1971-08-01 00:00:00 +0000 UTC           | | 4/8/2014 22:05                                        | 2014-04-08 22:05:00 +0000 UTC           | | 04/08/2014 22:05                                      | 2014-04-08 22:05:00 +0000 UTC           | | 4/8/14 22:05                                          | 2014-04-08 22:05:00 +0000 UTC           | | 04/2/2014 03:00:51                                    | 2014-04-02 03:00:51 +0000 UTC           | | 8/8/1965 12:00:00 AM                                  | 1965-08-08 00:00:00 +0000 UTC           | | 8/8/1965 01:00:01 PM                                  | 1965-08-08 13:00:01 +0000 UTC           | | 8/8/1965 01:00 PM                                     | 1965-08-08 13:00:00 +0000 UTC           | | 8/8/1965 1:00 PM                                      | 1965-08-08 13:00:00 +0000 UTC           | | 8/8/1965 12:00 AM                                     | 1965-08-08 00:00:00 +0000 UTC           | | 4/02/2014 03:00:51                                    | 2014-04-02 03:00:51 +0000 UTC           | | 03/19/2012 10:11:59                                   | 2012-03-19 10:11:59 +0000 UTC           | | 03/19/2012 10:11:59.3186369                           | 2012-03-19 10:11:59.3186369 +0000 UTC   | | 2014/3/31                                             | 2014-03-31 00:00:00 +0000 UTC           | | 2014/03/31                                            | 2014-03-31 00:00:00 +0000 UTC           | | 2014/4/8 22:05                                        | 2014-04-08 22:05:00 +0000 UTC           | | 2014/04/08 22:05                                      | 2014-04-08 22:05:00 +0000 UTC           | | 2014/04/2 03:00:51                                    | 2014-04-02 03:00:51 +0000 UTC           | | 2014/4/02 03:00:51                                    | 2014-04-02 03:00:51 +0000 UTC           | | 2012/03/19 10:11:59                                   | 2012-03-19 10:11:59 +0000 UTC           | | 2012/03/19 10:11:59.3186369                           | 2012-03-19 10:11:59.3186369 +0000 UTC   | | 2014:3:31                                             | 2014-03-31 00:00:00 +0000 UTC           | | 2014:03:31                                            | 2014-03-31 00:00:00 +0000 UTC           | | 2014:4:8 22:05                                        | 2014-04-08 22:05:00 +0000 UTC           | | 2014:04:08 22:05                                      | 2014-04-08 22:05:00 +0000 UTC           | | 2014:04:2 03:00:51                                    | 2014-04-02 03:00:51 +0000 UTC           | | 2014:4:02 03:00:51                                    | 2014-04-02 03:00:51 +0000 UTC           | | 2012:03:19 10:11:59                                   | 2012-03-19 10:11:59 +0000 UTC           | | 2012:03:19 10:11:59.3186369                           | 2012-03-19 10:11:59.3186369 +0000 UTC   | | 2014年04月08日                                        | 2014-04-08 00:00:00 +0000 UTC           | | 2006-01-02T15:04:05+0000                              | 2006-01-02 15:04:05 +0000 UTC           | | 2009-08-12T22:15:09-07:00                             | 2009-08-12 22:15:09 -0700 -0700         | | 2009-08-12T22:15:09                                   | 2009-08-12 22:15:09 +0000 UTC           | | 2009-08-12T22:15:09.988                               | 2009-08-12 22:15:09.988 +0000 UTC       | | 2009-08-12T22:15:09Z                                  | 2009-08-12 22:15:09 +0000 UTC           | | 2017-07-19T03:21:51:897+0100                          | 2017-07-19 03:21:51.897 +0100 +0100     | | 2019-05-29T08:41-04                                   | 2019-05-29 08:41:00 -0400 -0400         | | 2014-04-26 17:24:37.3186369                           | 2014-04-26 17:24:37.3186369 +0000 UTC   | | 2012-08-03 18:31:59.257000000                         | 2012-08-03 18:31:59.257 +0000 UTC       | | 2014-04-26 17:24:37.123                               | 2014-04-26 17:24:37.123 +0000 UTC       | | 2013-04-01 22:43                                      | 2013-04-01 22:43:00 +0000 UTC           | | 2013-04-01 22:43:22                                   | 2013-04-01 22:43:22 +0000 UTC           | | 2014-12-16 06:20:00 UTC                               | 2014-12-16 06:20:00 +0000 UTC           | | 2014-12-16 06:20:00 GMT                               | 2014-12-16 06:20:00 +0000 UTC           | | 2014-04-26 05:24:37 PM                                | 2014-04-26 17:24:37 +0000 UTC           | | 2014-04-26 13:13:43 +0800                             | 2014-04-26 13:13:43 +0800 +0800         | | 2014-04-26 13:13:43 +0800 +08                         | 2014-04-26 13:13:43 +0800 +0800         | | 2014-04-26 13:13:44 +09:00                            | 2014-04-26 13:13:44 +0900 +0900         | | 2012-08-03 18:31:59.257000000 +0000 UTC               | 2012-08-03 18:31:59.257 +0000 UTC       | | 2015-09-30 18:48:56.35272715 +0000 UTC                | 2015-09-30 18:48:56.35272715 +0000 UTC  | | 2015-02-18 00:12:00 +0000 GMT                         | 2015-02-18 00:12:00 +0000 UTC           | | 2015-02-18 00:12:00 +0000 UTC                         | 2015-02-18 00:12:00 +0000 UTC           | | 2015-02-08 03:02:00 +0300 MSK m=+0.000000001          | 2015-02-08 03:02:00 +0300 +0300         | | 2015-02-08 03:02:00.001 +0300 MSK m=+0.000000001      | 2015-02-08 03:02:00.001 +0300 +0300     | | 2017-07-19 03:21:51+00:00                             | 2017-07-19 03:21:51 +0000 UTC           | | 2014-04-26                                            | 2014-04-26 00:00:00 +0000 UTC           | | 2014-04                                               | 2014-04-01 00:00:00 +0000 UTC           | | 2014                                                  | 2014-01-01 00:00:00 +0000 UTC           | | 2014-05-11 08:20:13,787                               | 2014-05-11 08:20:13.787 +0000 UTC       | | 2020-07-20+08:00                                      | 2020-07-20 00:00:00 +0800 +0800         | | 3.31.2014                                             | 2014-03-31 00:00:00 +0000 UTC           | | 03.31.2014                                            | 2014-03-31 00:00:00 +0000 UTC           | | 08.21.71                                              | 1971-08-21 00:00:00 +0000 UTC           | | 2014.03                                               | 2014-03-01 00:00:00 +0000 UTC           | | 2014.03.30                                            | 2014-03-30 00:00:00 +0000 UTC           | | 20140601                                              | 2014-06-01 00:00:00 +0000 UTC           | | 20140722105203                                        | 2014-07-22 10:52:03 +0000 UTC           | | 171113 14:14:20                                       | 2017-11-13 14:14:20 +0000 UTC           | | 1332151919                                            | 2012-03-19 10:11:59 +0000 UTC           | | 1384216367189                                         | 2013-11-12 00:32:47.189 +0000 UTC       | | 1384216367111222                                      | 2013-11-12 00:32:47.111222 +0000 UTC    | | 1384216367111222333                                   | 2013-11-12 00:32:47.111222333 +0000 UTC | +-------------------------------------------------------+-----------------------------------------+ */

发表评论

评论已关闭。

相关文章