内容简介:大家好,我叫谢伟,是一名程序员。近期会更新内置库的学习笔记,主要参考文献来自于官方文档和源代码。本节的主题:time
大家好,我叫谢伟,是一名程序员。
近期会更新内置库的学习笔记,主要参考文献来自于官方文档和源代码。
本节的主题:time
时间的操作在项目中使用的非常频繁,比如说数据库中,经常有时间的操作,比如根据时间进行划分,统计之类的功能。
那么如何学会常用的操作呢?
大纲:
- 自己总结的常用操作
- 官方的 API
- 学习总结
自己总结的常用操作
时间类型的数据,我们在项目中都会进行哪些操作呢?
要在思维里掌握时间类型的数据的操作,又应该如何梳理呢?
1. 时间的单位
暂时撇开代码层面,日常生活中关于时间的单位都有哪些呢?
- 年
- 月
- 周
- 日
- 时
- 分
- 秒
- 毫秒
一般到毫秒层面就够了,当然还可以继续划分:微秒、纳秒...
那时间的单位的转换是如何进行的呢?
- 1 y = 12 m
- 1 m = 4 w
- 1 w = 7 d
- 1 d = 24 h
- 1 h = 60 min
- 1 min = 60 s
- 1 s = 1000 ms
- 1 ms = 1000 us
- 1 us = 1000 ns
为什么要了解这些啊? 这不是常识吗?是的。经常有常识性的问题,转换成代码层面而出错。所以有必要进行了回顾。
2. 时间操作
了解了时间的基本单位,那就好办了。
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", } 复制代码
3. 时间戳
- 时间戳的使用也非常广泛,比如为了表示唯一性
- 时间戳的概念:1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数
时间戳,这个概念,如果不是程序员,可能完成没有必要了解,有更好的阅读时间的显示方式,没必要知道这么一串数字。
在 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 复制代码
关于时间,还存在一个重要的概念,即:时区
- UTC 校准的全球时间
- CST China Standard Time UT 8:00
所以经常会出现时间相差 8 小时的情况,比如,本地程序运行正常,推送到仓库中,自动构建够,程序得不到预期的值,有可能是因为服务器的时间的时区和本地的不一致。
4. 时间和字符串的相互转化
涉及时间的显示的布局有个默认值: 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 , 且存在错误返回
时间类型和字符串之间的转化和上文的总结一致。
启发:使用关键字: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 向下取整
5. 两个时间之间的操作
上面的例子绝大多数是单个时间的操作,比如取时间戳、时间和字符串之间转化、获取时间的年月日等。
日常操作中,两个时间的操作也是比较频繁的。
比如:
- 判断一个时间是否是在该时间之前、之后
- 给出给定时间的某个时间节点的值:比如 1小时前、1天前、1年前、1年后、1天后、1小时后等
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 复制代码
6. 其他
- 得出时间是本周的周几
- 得出时间是该年的第几周
func main(){ fmt.Println(time.Now().ISOWeek()) fmt.Println(time.Now().Weekday()) } >> 2018 46 Tuesday 复制代码
官方API
大概我们没讲有这些内容:
- 定时器?
- 底层是如何获取时间的?
- 序列化和反序列化(还记得 json 那节 Marshler 吗)
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 复制代码
<完>
以上所述就是小编给大家介绍的《『Go 内置库第一季:time』》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
算法设计与分析基础
Anany Levitin / 潘彦 / 清华大学出版社 / 2015-2-1 / 69.00元
作者基于丰富的教学经验,开发了一套全新的算法分类方法。该分类法站在通用问题求解策略的高度,对现有大多数算法准确分类,从而引领读者沿着一条清晰、一致、连贯的思路来探索算法设计与分析这一迷人领域。《算法设计与分析基础(第3版)》作为第3版,相对前版调整了多个章节的内容和顺序,同时增加了一些算法,并扩展了算法的应用,使得具体算法和通用算法设计技术的对应更加清晰有序;各章累计增加了70道习题,其中包括一些......一起来看看 《算法设计与分析基础》 这本书的介绍吧!