你们好,我叫谢伟,是一名程序员。程序员
近期会更新内置库的学习笔记,主要参考文献来自于官方文档和源代码。数据库
本节的主题:timejson
时间的操做在项目中使用的很是频繁,好比说数据库中,常常有时间的操做,好比根据时间进行划分,统计之类的功能。后端
那么如何学会经常使用的操做呢?数组
大纲:bash
时间类型的数据,咱们在项目中都会进行哪些操做呢?服务器
要在思惟里掌握时间类型的数据的操做,又应该如何梳理呢?函数
暂时撇开代码层面,平常生活中关于时间的单位都有哪些呢?布局
通常到毫秒层面就够了,固然还能够继续划分:微秒、纳秒...学习
那时间的单位的转换是如何进行的呢?
为何要了解这些啊? 这不是常识吗?是的。常常有常识性的问题,转换成代码层面而出错。因此有必要进行了回顾。
了解了时间的基本单位,那就好办了。
func main(){
now := time.Now()
fmt.Println(now.Year())
fmt.Println(now.Month())
fmt.Println(now.Day())
fmt.Println(now.Hour())
fmt.Println(now.Minute())
fmt.Println(now.Second())
fmt.Println(now.Date())
}
>>
2018-11-13 22:30:03.500763 +0800 CST m=+0.000810351
2018
November
13
22
30
3
2018 November 13
复制代码
全部这些时间的单位底层都是 int
类型。既然是 int
类型,那 November 是如何获得的?
很简单,底层定义这样一个关于月份的数组,将对应的位置的值返回便可。
var months = [...]string{
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
}
复制代码
时间戳,这个概念,若是不是程序员,可能完成没有必要了解,有更好的阅读时间的显示方式,不必知道这么一串数字。
在 Go 中,如何将时间转换成时间戳?
func main(){
now := time.Now()
fmt.Println(now.UnixNano())
fmt.Println(now.Unix())
}
>>
1542119403501037000
1542119403
复制代码
上文一个转换为纳秒,一个是转换为秒。能够看到转换单位是 10^9
那如何将时间戳转换为 时间类型?
func main(){
fmt.Println(time.Unix(1542119403, 1542119403000000000))
fmt.Println(time.Unix(1542119403, 1542119403000000000).UTC())
}
>>
2067-09-26 13:00:06 +0800 CST
2067-09-26 05:00:06 +0000 UTC
复制代码
关于时间,还存在一个重要的概念,即:时区
因此常常会出现时间相差 8 小时的状况,好比,本地程序运行正常,推送到仓库中,自动构建够,程序得不到预期的值,有多是由于服务器的时间的时区和本地的不一致。
涉及时间的显示的布局有个默认值:2006-01-02 15:04:05
这个时间的速记:12345
func main(){
now := time.Now()
fmt.Println(now.Format("2006-01-02 15:04:05"))
}
timeString := "2019-01-02 15:03:00"
fmt.Println(time.Parse("2006-01-02 15:04:05", timeString))
fmt.Println(time.ParseInLocation("2006-01-02 15:04:05", timeString, time.Local))
>>
2018-11-13 22:59:08
2019-01-02 15:03:00 +0000 UTC <nil>
2019-01-02 15:03:00 +0800 CST <nil>
复制代码
还记得以前字符串和基本数据类型(整型、浮点型、布尔型)相互转化的章节。
咱们总结:
时间类型和字符串之间的转化和上文的总结一致。
启发:使用关键字:Format 、 Parse 对本身函数进行命名组织;没有错误类型的函数不返回错误类型
有时候咱们可能只须要时间的部分值,好比说,只须要整点的值,那关于这些操做,又应该如何操做呢?
func main(){
timeToString()
}
var timeToString = func() {
now := time.Now()
fmt.Println(now.Format("2006-01-02 15:00:00"))
fmt.Println(now.Format("2006-01-02 15:04:00"))
fmt.Println(now.Format("2006-01-02 00:00:00"))
fmt.Println(now.Round(time.Hour))
fmt.Println(now.Round(time.Minute))
fmt.Println(now.Round(time.Second))
fmt.Println(now.Truncate(time.Hour))
fmt.Println(now.Truncate(time.Minute))
fmt.Println(now.Truncate(time.Second))
}
>>
2018-11-13 23:00:00
2018-11-13 23:12:00
2018-11-13 00:00:00
2018-11-13 23:00:00 +0800 CST
2018-11-13 23:13:00 +0800 CST
2018-11-13 23:12:34 +0800 CST
2018-11-13 23:00:00 +0800 CST
2018-11-13 23:12:00 +0800 CST
2018-11-13 23:12:33 +0800 CST
复制代码
能够看出,存在两种方法,一种是操做 布局,即更改那个默认值 2006-01-02 15:04:05
; 一种是使用内置的 Round, Truncate 两种的区别是Round 向上取整,Truncate 向下取整
上面的例子绝大多数是单个时间的操做,好比取时间戳、时间和字符串之间转化、获取时间的年月日等。
平常操做中,两个时间的操做也是比较频繁的。
好比:
func main(){
timeOp()
}
var timeOp = func() {
now := time.Now()
fmt.Println(now.Add(1 * time.Hour))
fmt.Println(now.Add(24 * time.Hour))
fmt.Println(now.Add(-10 * time.Hour))
}
>>
2018-11-14 00:21:47.48055 +0800 CST m=+3600.000854277
2018-11-14 23:21:47.48055 +0800 CST m=+86400.000854277
2018-11-13 13:21:47.48055 +0800 CST m=-35999.999145723
复制代码
获得 1小时后、1天后、10小时前
好,那这些时间先后都有哪些值能够选择?
const (
Nanosecond Duration = 1
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute
)
复制代码
这些常量,辅以恰当的运算。
那 1年前咋搞?还运算吗?傻瓜。
func main(){
timeOpDate()
}
var timeOpDate = func() {
now := time.Now()
fmt.Println(now.AddDate(-1, 0, 0))
fmt.Println(now.AddDate(2, 0, 0))
fmt.Println(now.AddDate(0, 1, 0))
}
>>
2017-11-13 23:26:18.697797 +0800 CST
2020-11-13 23:26:18.697797 +0800 CST
2018-12-13 23:26:18.697797 +0800 CST
复制代码
完成啦。
基本上这两个函数就能够完成目的。
那如何计算两个时间之间的差呢?
func main(){
timeInterval()
}
var timeInterval = func() {
now := time.Now()
stringTime := "2018-11-14 20:00:00"
newTime, _ := time.ParseInLocation("2006-01-02 15:04:05", stringTime, time.Local)
if newTime.After(now) {
subTime := newTime.Sub(now)
fmt.Println("newTime after now")
fmt.Println(subTime.Hours())
fmt.Println(subTime.Minutes())
fmt.Println(subTime.Seconds())
fmt.Println(subTime.Nanoseconds())
}
if newTime.Before(now) {
subTime := now.Sub(newTime)
fmt.Println(subTime.String())
}
}
>>
newTime after now
20.463746377777777
1227.8247826666666
73669.48696
73669486960000
复制代码
func main(){
fmt.Println(time.Now().ISOWeek())
fmt.Println(time.Now().Weekday())
}
>>
2018 46
Tuesday
复制代码
大概咱们没讲有这些内容:
func (t Time) MarshalJSON() ([]byte, error)
MarshalJSON implements the json.Marshaler interface. The time is a quoted string in RFC 3339 format, with sub-second precision added if present.
复制代码
自定义了序列化的结构
枚举类型在 Go 里面的时候,用来表示连续的递增的值。
好比想表示颜色、好比想表示星期几
这种连续的值,通常都选择枚举类型来定义。
const (
Sunday Weekday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
const (
January Month = 1 + iota
February
March
April
May
June
July
August
September
October
November
December
)
复制代码
好比想自定义的颜色顺序:
const (
Red = iota
Orange
Yellow
Green
Cyan
Blue
Purple
)
func main(){
fmt.Println(Red,
Orange,
Yellow,
Green,
Cyan,
Blue,
Purple)
}
>>
0 1 2 3 4 5 6
复制代码
固然提到枚举,考点不会这样考你,而是以下面的操做:
const (
Red = iota
Orange
Yellow = iota + 10
Green = iota
Cyan
Blue = 10
Purple
)
复制代码
问你各个值得多少?
0 1 12 3 4 10 10
复制代码
<完>