侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

golang时间、时区、格式的使用方法

Go  /  管理员 发布于 7年前   188

前几天,因为需要实现海外服务端定时停机,涉及到时区的概念。网上搜索了一下,大部分都是谈time.Format中的Layout,非常不成体系,这里就简单总结一下其中的时间初始化、时区转化及格式转换。

开发中,我们对时间的使用是比较多的,其应用场景,按照使用概率,从大到小,通常是:

  1. 获取当前或数据库中存储的时间
  2. 比较两个时间点的先后
  3. 显示打印时间
  4. 时区转换

对应到go,也就是几个基本定义:

  1. 时间点与时间段:Time,Duration。好比MVC中的M。
  2. 时 区:Location,在时间转换上,好比是MVC中的C。
  3. 格式化:Format的layout定义,好比MVC中的V。

单独就Duration没什么好谈的,使用非常简单。Time实例中的Add、Sub与其相关,非常容易上手,就不再多说。

时区

时区是时间运算非常重要的概念,特别强调与layout是两个完全不同的概念。go语言通过Location来作为时区的运行实例,同一时刻转换成为不同的时区,就需要通过不同的Location来进行。默认情况下,采用UTC(unix标准时间),而不是过去式的GMT(格林尼治标准时间)。

以下代码展示了UTC标准、北京、美国洛杉矶在同一时刻的转换:

  now := time.Now()  local1, err1 := time.LoadLocation("") //等同于"UTC"  if err1 != nil {    fmt.Println(err1)  }  local2, err2 := time.LoadLocation("Local")//服务器设置的时区  if err2 != nil {    fmt.Println(err2)  }  local3, err3 := time.LoadLocation("America/Los_Angeles")  if err3 != nil {    fmt.Println(err3)  }  fmt.Println(now.In(local1))  fmt.Println(now.In(local2))  fmt.Println(now.In(local3))  //output:  //2016-12-04 07:39:06.270473069 +0000 UTC  //2016-12-04 15:39:06.270473069 +0800 CST  //2016-12-03 23:39:06.270473069 -0800 PST

代码中,LoadLocation的输入参数的取值,除了该函数的源代码中可看到的”UTC”、”Local”,其余的值其实是遵照“IANA Time Zone”的规则,可以解压$GOROOT/lib/time/zoneinfo.zip 这个文件打开查看。在Asia这个目录,我看到了Chongqing,Hong_Kong,但没Beijing。在国外获取中国北京时间,要用”PRC”,当然”Asia/Chongqing”也是个方法:

loc, _:= time.LoadLocation("Asia/Chongqing")  //参数就是解压文件的“目录”+“/”+“文件名”。fmt.Println(time.Now().In(loc))

值得强调的是,Location仅用于时区转化,而不对time内部的数据产生影响(内部其实是unix标准时),因此,当几个time实例进行Add、Sub的时候,不用关注Location是否相同。

时间格式化

前面例子中,打印结果非常丑陋,通常没人关心秒之后的ns;明确时区后,很少需要与UTC的时差。这时候,就需要定义我们的layout了。

网上好多都说,“2006-01-02 15:04:05是go的诞生时间,所以这么设计Format的Layout”,应该不是真的。请看下表:

01/Jan 02 03/15 04 05 06 -07[00][:00] PM Mon
月 日 时 分 秒 年 时差 上下午 星期几

也就是1234567,分别对应:月日时分秒年 时差,很好记忆。只是稍微注意一下:

  • 月:01或Jan都可以
  • 小时:03表示12小时制,15表示24小时制。
  • 时差:是 -07 ,不是 07,后边可以增加“00”或“:00”,表示更进一步的分秒时差。
  • 上下午:使用PM,不是AM。
  • 摆放顺序:随意,甚至重复都可以。源代码包也有定义的常用格式供使用。

也许是因为06对应的“年”与go的项目启动时间差不多,也就有了网上的误传。在源代码time/time.go中,有非常明确的描述,粘贴一下,就不翻译了:

// These are predefined layouts for use in Time.Format and Time.Parse.
// The reference time used in the layouts is the specific time:
// Mon Jan 2 15:04:05 MST 2006
// which is Unix time 1136239445. Since MST is GMT-0700,
// the reference time can be thought of as
// 01/02 03:04:05PM ‘06 -0700

虽然go已经提供了10多个常用格式:

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 Mon”,之前代码稍加修改,就是这样:

  formate:="2006-01-02 15:04:05 Mon"  now := time.Now()  local1, err1 := time.LoadLocation("UTC") //输入参数"UTC",等同于""  if err1 != nil {    fmt.Println(err1)  }  local2, err2 := time.LoadLocation("Local")  if err2 != nil {    fmt.Println(err2)  }  local3, err3 := time.LoadLocation("America/Los_Angeles")  if err3 != nil {    fmt.Println(err3)  }  fmt.Println(now.In(local1).Format(formate))  fmt.Println(now.In(local2).Format(formate))  fmt.Println(now.In(local3).Format(formate))  //output:  //2016-12-04 08:06:39 Sun  //2016-12-04 16:06:39 Sun  //2016-12-04 00:06:39 Sun

时间初始化

除了最常用的time.Now,go还提供了通过unix标准时间、字符串两种方式来初始化:

//通过字符串,默认UTC时区初始化Timefunc Parse(layout, value string) (Time, error) //通过字符串,指定时区来初始化Timefunc ParseInLocation(layout, value string, loc *Location) (Time, error) //通过unix 标准时间初始化Timefunc Unix(sec int64, nsec int64) Time 

时间初始化的时候,一定要注意原始输入值的时区。正好手里有一个变量,洛杉矶当地时间“2016-11-28 19:36:25”,unix时间精确到秒为1480390585。将其解析出来的代码如下:

  local, _ := time.LoadLocation("America/Los_Angeles")  timeFormat := "2006-01-02 15:04:05"  //func Unix(sec int64, nsec int64) Time {  time1 := time.Unix(1480390585, 0)   //通过unix标准时间的秒,纳秒设置时间  time2, _ := time.ParseInLocation(timeFormat, "2016-11-28 19:36:25", local) //洛杉矶时间  fmt.Println(time1.In(local).Format(timeFormat))  fmt.Println(time2.In(local).Format(timeFormat))  chinaLocal, _ := time.LoadLocation("Local")//运行时,该服务器必须设置为中国时区,否则最好是采用"Asia/Chongqing"之类具体的参数。  fmt.Println(time2.In(chinaLocal).Format(timeFormat))  //output:  //2016-11-28 19:36:25  //2016-11-28 19:36:25  //2016-11-29 11:36:25

当然,如果输入值是字符串,且带有时区

“2016-12-04 15:39:06 +0800 CST”

则不需要采用ParseInLocation方法,直接使用Parse即可。

当然,其他time包中的函数还有很多,但网上已经有很多描述,就不再隆

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


  • 上一条:
    golang读取文件的常用方法总结
    下一条:
    简单谈谈Golang中的字符串与字节数组
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2017-09
    • 2020-03
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-12
    • 2021-01
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-10
    • 2021-11
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    • 2024-05
    • 2024-06
    • 2024-07
    • 2024-08
    • 2024-11
    • 2025-02
    • 2025-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客