一文详解Go time包时间处理

蚀纹阈值
• 阅读 1151

前言

本文主要介绍使用标准库中的time包进行时间处理。快速掌握时区设置、时间戳获取,以及时间格式化等操作。

时区设置

1. 默认使用本地时区

本地指的是程序运行所属环境(物理机或容器等)。例如本地设置的是北京时间(Asia/Shanghai),则获取到的时间就是东八区的时间

func main() {
  fmt.Println(time.Now())
  fmt.Println(time.Now().Location())
}
输出:
2023-02-19 22:52:38.217136 +0800 CST m=+0.000072078
Local

2.使用os.Setenv()设置时区

使用os包设置环境变量TZ为对应时区。注意:1.该设置一定要在time包使用之前,否则无效;2.依赖当前系统的时区数据库,有则可以加载一个位置得到对应的时区,无则兜底使用UTC

func main() {
  os.Setenv("TZ", "Asia/Shanghai")
  fmt.Println(time.Now())
  fmt.Println(time.Now().Location())
}
输出:
2023-02-19 22:54:05.885626 +0800 CST m=+0.000077761
Asia/Shanghai

3.使用time.LoadLocation()设置时区

依赖当前系统的时区数据库,有则可以加载一个位置得到对应的时区,无则会返回一个error

func main() {
  loc, err := time.LoadLocation("Asia/Shanghai")
  if err != nil {
    fmt.Println("LoadLocation error: " + err.Error())
    return
  }
  fmt.Println(time.Now().In(loc))
  fmt.Println(time.Now().In(loc).Location())
}
正确输出:
2023-02-19 23:03:22.543069 +0800 CST
Asia/Shanghai

错误输出:LoadLocation error: unknown time zone Asia/ShanghaiA

4.使用内置的time.UTC和time.Local快速切换时区

time.UTC设置为UTC;time.Local设置为本地默认时区

func main() {
  fmt.Println(time.Now().In(time.UTC))
  fmt.Println(time.Now().In(time.UTC).Location())
  fmt.Println(time.Now().In(time.Local))
  fmt.Println(time.Now().In(time.Local).Location())
}
输出:
2023-02-19 15:22:41.626207 +0000 UTC
UTC
2023-02-19 23:22:41.626254 +0800 CST
Local

获取当前时间信息

通过time.Now获取当前的时间对象,然后从时间对象中可以获取到年、月、日、时、分、秒等信息

func main() {
  t := time.Now() // 获取当前时间
  fmt.Printf("当前时间:%v\n", t)

  year := t.Year()     // 年
  month := t.Month()   // 月
  day := t.Day()       // 日
  hour := t.Hour()     // 小时
  minute := t.Minute() // 分钟
  second := t.Second() // 秒
  fmt.Println(year, month, day, hour, minute, second)
}
输出:
当前时间:2023-02-19 23:36:46.75675 +0800 CST m=+0.000270495
2023 February 19 23 36 46

获取时间戳

1.当前时间的时间戳

通过time.Now获取当前的时间对象,然后使用时间对象调用相关方法获取时间戳。

注意:毫秒和微秒的方法,在Go1.17之后才能使用,之前的版本可以通过纳秒进行计算转换

func main() {
  t := time.Now()
  
  sec := t.Unix()              //秒
  mill := t.UnixNano() / 1e6   //毫秒
  //mill := t.UnixMilli()      //毫秒,要求Go1.17+
  micro := t.UnixNano() / 1e3  //微秒
  //micro := t.UnixMicro()     //微秒,要求Go1.17+
  nano := t.UnixNano()         //纳秒
  fmt.Println(sec, mill, micro, nano) 
}
输出:
1676821481 1676821481283 1676821481283263 1676821481283263000

2.指定时间的时间戳

使用time.ParseInLocation指定时区解析指定时间,并获取到时间对象,然后调用相关方法获取时间戳

func main() {
  t, err := time.ParseInLocation("2006-01-02 15:04:05", "2023-02-19 21:00:00", time.Local)
  if err != nil {
    fmt.Println("ParseInLocation error:" + err.Error())
  }
  fmt.Println(t)

  sec := t.Unix()             //秒
  mill := t.UnixNano() / 1e6  //毫秒
  micro := t.UnixNano() / 1e3 //微秒
  nano := t.UnixNano()        //纳秒
  fmt.Println(sec, mill, micro, nano)
}
输出:
2023-02-19 21:00:00 +0800 CST
1676811600 1676811600000 1676811600000000 1676811600000000000

时间格式化

Go语言的格式化布局规则,比较特殊,不是使用常规的“Y-m-d H:M:S”,而是使用“2006-01-02 15:04:05.000”

含义说明

  • 2006:年(Y)
  • 01:月(m)
  • 02:日(d)
  • 15:时(H)。若想表示12小时制则写为03,并且后面加上PM
  • 04:分(M)
  • 05:秒(S)
  • 特殊:小数部分想保留指定位数就写0,如果想省略末尾可能的0就写 9

使用示例

func main() {
  t := time.Now()
  //24小时制
  fmt.Println(t.Format("2006-01-02 15:04:05"))
  //12小时制(时占位03并且后面加上PM)
  fmt.Println(t.Format("2006-01-02 03:04:05 PM"))

  //小数点0或9
  fmt.Println(t.Format("2006-01-02 15:04:05.000"))
  fmt.Println(t.Format("2006-01-02 15:04:05.999"))

  //只要日期
  fmt.Println(t.Format("2006-01-02"))
  //只要时间
  fmt.Println(t.Format("15:04:05"))
}
输出:
2023-02-20 00:48:12
2023-02-20 12:48:12 AM
2023-02-20 00:48:12.223
2023-02-20 00:48:12.223
2023-02-20
00:48:12

时间间隔

time.Duration代表两个时间点之间经过的时间,以纳秒为单位。可表示的最长时间段大约290年

time 包定义的时间间隔常量:

const (
  Nanosecond  Duration = 1
  Microsecond          = 1000 * Nanosecond
  Millisecond          = 1000 * Microsecond
  Second               = 1000 * Millisecond
  Minute               = 60 * Second
  Hour                 = 60 * Minute
)

常用方法

  • Add:func (t Time) Add(d Duration) Time,指定时间间隔(t+d),得到一个新的时间对象
  • Sub:func (t Time) Sub(u Time) Duration,求两个时间之间的差值(t-d)

使用示例

func main() {
  t := time.Now()
  t2 := t.Add(1 * time.Hour)  //一个小时之后的时间
  t3 := t.Add(-1 * time.Hour) //一个小时之前的时间
  fmt.Println(t)              //2023-02-20 01:18:00.204169 +0800 CST m=+0.000410087
  fmt.Println(t2)             //2023-02-20 02:18:00.204169 +0800 CST m=+3600.000410087
  fmt.Println(t3)             //2023-02-20 00:18:00.204169 +0800 CST m=-3599.999589913

  time.Sleep(2 * time.Second)
  fmt.Println(t.Sub(time.Now())) //-2.005207034s
  fmt.Println(time.Now().Sub(t)) //2.00532078s
}

定时器

使用time.Tick(时间间隔)来设置定时器,定时器的本质上是一个通道(channel)。可用于处理定时执行的任务

func timeTick() {
  ticker := time.Tick(time.Second) //定义一个1秒间隔的定时器
  for i := range ticker {
    fmt.Println(i) //每秒都会执行的任务
  }
}
输出:
2023-02-20 01:25:18.310543 +0800 CST m=+3.010979096
2023-02-20 01:25:19.31052 +0800 CST m=+4.010955881
2023-02-20 01:25:20.31051 +0800 CST m=+5.010945974

总结

对时区设置、时间戳获取,以及时间格式化等操作,做了详细的讲解。记住所有的操作,都得基于时间对象,来展开的,时间对象是时间处理的基石。

如果本文对你有帮助,欢迎点赞收藏加关注,如果本文有错误的地方,欢迎指出!
本文参与了SegmentFault 思否写作挑战赛,欢迎正在阅读的你也加入。
点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Wesley13 Wesley13
4年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Karen110 Karen110
4年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Wesley13 Wesley13
4年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
4年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Wesley13 Wesley13
4年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
4年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Wesley13 Wesley13
4年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Stella981 Stella981
4年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable