-
博文分类专栏
- Jquery基础教程
-
- 文章:(15)篇
- 阅读:47263
- shell命令
-
- 文章:(42)篇
- 阅读:156703
- Git教程
-
- 文章:(36)篇
- 阅读:237799
- leetCode刷题
-
- 文章:(76)篇
- 阅读:137255
-
go里面时间time包使用2018-02-27 14:35 阅读(11898) 评论(1)
一、简介
时间一般包含时间值和时区,可以从go中time包里面对Time定义看出:
type Time struct { // wall and ext encode the wall time seconds, wall time nanoseconds, // and optional monotonic clock reading in nanoseconds. // // From high to low bit position, wall encodes a 1-bit flag (hasMonotonic), // a 33-bit seconds field, and a 30-bit wall time nanoseconds field. // The nanoseconds field is in the range [0, 999999999]. // If the hasMonotonic bit is 0, then the 33-bit field must be zero // and the full signed 64-bit wall seconds since Jan 1 year 1 is stored in ext. // If the hasMonotonic bit is 1, then the 33-bit field holds a 33-bit // unsigned wall seconds since Jan 1 year 1885, and ext holds a // signed 64-bit monotonic clock reading, nanoseconds since process start. wall uint64 ext int64 // loc specifies the Location that should be used to // determine the minute, hour, month, day, and year // that correspond to this Time. // The nil location means UTC. // All UTC times are represented with loc==nil, never loc==&utcLoc. loc *Location }
其中:
wall表示距离公元1年1月1日00:00:00UTC的秒数;
ext表示纳秒
loc代表时区,主要处理偏移量。因为不同的时区,对应的时间不一样。
如何正确表示时间呢?
人们认为最准确的计算应该是使用‘原子震荡周期’所计算的物理时钟了 (Atomic Clock, 也被称为原子钟),这也被定义为标准时间 (International Atomic Time)。而我们常常看见的UTC(Universal Time Coordinated,世界协调时间)就是利用这种 Atomic Clock 为基准所定义出来的正确时间。UTC 标准时间是以 GMT(Greenwich Mean Time,格林威治时间) 这个时区为主,所以本地时间与 UTC 时间的时差就是本地时间与 GMT 时间的时差。
UTC + 时区差 = 本地时间
国内一般使用的是北京时间,与UTC的时间关系如下:
UTC + 8个小时 = 北京时间
关于时区更多内容,可以查看鸟哥私房菜里面的“NTP 时间伺服器”。
在Go语言的time包里面有两个时区变量,如下:
time.UTC UTC时间
time.Local 本地时间
同时,go语言还提供了LoadLocation方法和FixedZone方法来获取时区变量,如下:
FixedZone(name string, offset int) *Location
name为时区名称,offset是与UTC 之前的时差。
LoadLocation(name string) (*Location, error)
name为时区的名字。
二、时间的使用
1、如何创建时间对象
所谓的时间对象,即一个结构体类型的时间类型变量而已。有如下方法创建
//1.以当前时间去创建 time.Now() //2.通过秒和纳秒去创建 time.Unix(sec int64, nsec int64) //3.通过时间字符串去创建 Parse(layout, value string) //4.通过指定年月日时分秒纳秒时区来创建 Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location)
2、获取时间字符串
//获取当前时间 time.Now().Format("2006-01-02 15:04:05") //获取时间戳的对应的时间字符串 var str int64 = 1523432131 //时间戳 var strTime = time.Unix(str, 0) //获取时间对象 strTime.Format("2006-01-02 15:04:05")//格式化后获取时间字符串
思路:获取时间对象,然后调用format方法,获取时间字符串。
备注:在Formate方法中是以"Mon Jan 2 15:04:05 -0700 MST 2006"为参考,来格式化时间的。
3、获取时间戳
//获取当前时间戳 time.Now().Unix() //获取时间字符串对应的时间戳 var strTime = "2018-03-11 15:35:03" timeObj ,_ := time.Parse("2006-01-02 15:04:05", strTime)//获取时间对象,获取的时间对应的时区是UTC //timeObj2, _ := time.ParseInLocation("2006-01-02 15:04:05", strTime, time.Local) //获取时间对象,获取的时间对应的时区是本地时间 timeObj.Unix() //获取对应的时间戳 int64类型
思路:获取时间对象,然后调用unix方法,获取时间戳。
3.1 如何解决时区不同导致的时间戳不同的问题?
要理解为什么不同的时区,同样的时间时间字符串,对应的时间戳不一样,我们首先要理解什么是时区,时间戳是怎么计算出来的?
时间戳是,通过距离UTC时区1970-01-01 00:00:00的秒数(since January 1, 1970 UTC. The result is undefined if the Unix time),即我们先把时间换算成,UTC时间,然后计算两个时间相差的秒数。
我国一般使用的是北京时间,假设时间为T,那么对应的时间戳为:
时间戳 =(T + 8个小时 - 1970-01-01 00:00:00 ) 秒
在go里面,通过time.Now()拿到的时间,默认的时区为本地时区;通过time.Parse(layout, value string) (Time, error)方法拿到的时间,时区为UTC对应的时区。通过time.ParseInLocation(layout, value string, loc *Location) (Time, error)方法拿到的时间,是调用该方法传递的loc对应的时区。
我们可以通过时间对象对应的Location()方法获取时区,如下:
curTime := time.Now() fmt.Println(curTime.Location()) // 输出local
当然,也可以通过Zone()方法来获取,这个方法还会返回与UTC的时差,如下:
timeObj ,_ := time.Parse("2006-01-02 15:04:05", "2018-03-11 15:35:03")//获取时间对象 fmt.Println(timeObj .Zone()) //输出UTC 0
在go里面,通过Unix()方法来获取秒的时候,程序会自动依据当前时间对应的时区,计算出距离UTC时区1970-01-01 00:00:00的秒数。
所以,当我们通过time.Parsel方法来获取同一个时间字符串对应的时间戳,比我们通过time.ParseInLocation方法限定loc为time.Local(为北京时间)早了8个小时对应的秒数28800,因为北京时间换算成UTC时间,需要减去8个小时。如下:
var layout string = "2006-01-02 15:04:05" var timeStr string = "2018-03-11 15:35:03" timeObj1, _ := time.Parse(layout, timeStr) fmt.Println(timeObj1.Unix()) timeObj2, _ := time.ParseInLocation(layout, timeStr, time.Local) fmt.Println(timeObj2.Unix())
3.2 go里面有没有类似PHP那样通过一个函数(date_default_timezone_set)来设置时区呢?
答案是有的。如下:
time.LoadLocation("Asia/Shanghai")
我们可以在程序的开头,先设定好时区。然后取出来的当前时间,就是设定时区的当前时间。如下:
time.LoadLocation("Asia/Shanghai") fmt.Println("当前时间戳:", time.Now().Unix()) var strTime = time.Unix(time.Now().Unix(), 0) fmt.Println("当前时间戳:", strTime.Format("2006-01-02 15:04:05"))
4、如何获取年月日时分秒
timeObj := time.Now() //获取时间对象 fmt.Println(timeObj.Year())//年 fmt.Println(timeObj.Month())//月 fmt.Println(timeObj.Day())//日 fmt.Println(timeObj.Hour())//时 fmt.Println(timeObj.Minute())//分 fmt.Println(timeObj.Second())//秒