详解Go中处理时间数据的方法

 更新时间:2023年04月18日 10:13:15   作者:洛天枫  
在许多场合,你将不得不编写必须处理时间的代码。在Go中处理时间数据需要你从Go标准库中导入 time 包。这个包有很多方法和类型供你使用,但我选取了最常用的方法和类型,并在这篇文章中进行了描述,感兴趣的可以了解一下

在许多场合,你将不得不编写必须处理时间的代码。你可以写一个时钟程序,或者在你的代码中测量两点之间的时间差。无论是哪种方式,知道如何在Go中处理时间数据是很重要的。这很简单,了解一些有趣的函数可以帮助你节省时间。在Go中处理时间数据需要你从Go标准库中导入 time 包。这个包有很多方法和类型供你使用,但我选取了最常用的方法和类型,并在这篇文章中进行了描述。如果你想看更多关于这个主题的信息,请查看time包的文档页面。

获取时间

这可能是软件包中最常用的方法。我们如何知道当前的时间呢?像这样:

t := time.Now()
fmt.Println(t)

输出:

2023-04-16 23:54:45.924965 +0800 CST m=+0.000152293

这就是当前的时间。这是很麻烦的,所以我将把它分解成几个部分。

  • 2023-02-06:年月日。
  • 23:01:48.9983151:时、分、秒
  • 0800:与 GMT 的时差。
  • CST:您所在的当前时区。
  • m=+0.000152293: 单调时钟读数。

我们将在本文后面介绍单调时钟。 我们现在可以继续前进。

有没有更好的方法来格式化这个

你打赌。

t := time.Now()
fmt.Println(t.Year())
fmt.Println(t.Month())
fmt.Println(t.Day())
fmt.Println(t.Date())
fmt.Println(t.Hour())
fmt.Println(t.Minute())
fmt.Println(t.Second())

输出:

2023
April
17
2023 April 17
0
3
31

以下是如何提取时间的每个元素。 很简单,对吧?

我们如何以更漂亮的格式打印它?

fmt.Printf("%d %d %d\n", t.Year(), t.Month(), t.Day())

输出:

2023 4 17

您可以看到我们如何使用 fmt.Printf 函数来根据自己的喜好格式化时间。

但是如果我们想用名字显示月份,比如二月而不是 2 怎么办? 如果我们想以 12 小时制而不是 24 小时制显示时间怎么办? 你可以看到它是如何很快变得复杂的。

有一种更好的格式化时间的方法

幸运的是,我们有 time.Format 函数来帮助我们。 让我们看看它是如何工作的。

fmt.Println(t.Format("Mon Jan 2 15:04:05 2006 MST"))
fmt.Println(t.Format("Mon Jan 2 15:04:05"))
fmt.Println(t.Format("2006/01/02"))
fmt.Println(t.Format("3:04PM"))
fmt.Println(t.Format("15:04PM"))

输出:

Mon Apr 17 00:06:21 2023 CST
Mon Apr 17 00:06:21
2023/04/17
12:06AM
00:06AM

我认为这是我刚开始学习这个主题时最让我失望的部分。 这也是您可以看到语言设计者有多么厚颜无耻的部分。

我们可以看到 time.Format 接受一个字符串,该字符串表示我们希望时间采用的格式。这是奇怪的部分,因为 Go 对格式字符串的格式非常非常讲究。

Mon Apr 17 00:06:21 2023 CST

格式字符串必须是该字符串的变体,否则代码会打印出奇怪的时间。 有趣的是,如果排除 Mon,格式字符串的每个元素都代表一个整数。 Jan 是 1,2 是 2,15 是 3。

1 2 3 4 5 6 -7

不过,从上面的代码中,您可以看到我们如何按照我们想要的方式格式化我们的时间。 而且我们不必编写额外的函数来将小时转换为 12 或 24 小时制,或者将每个整数映射到月份。

您也可以使用预定义的格式,如下所示:

fmt.Println(time.UnixDate)
fmt.Println(time.RFC3339)

输出:

Mon Jan _2 15:04:05 MST 2006
2006-01-02T15:04:05Z07:00

查看文档以了解更多格式。

不同的时区呢

如上所示,系统会自动检测时区。 但是,在某些情况下,您可能需要显示不同时区的时间。

nt := time.Now()
lt := time.Now().Local()
ut := time.Now().UTC()
fmt.Println(nt)
fmt.Println(lt)
fmt.Println(ut)

输出:

2023-04-17 00:11:10.214751 +0800 CST m=+0.000135417
2023-04-17 00:11:10.214751 +0800 CST
2023-04-16 16:11:10.214751 +0000 UTC

Local() 获取本地时区,这与 time.Now() 会自动检测到的时间相同。 调用 UTC() 会将时区转换为 UTC。

但是,如果我们需要更强大的东西怎么办?

l, _ := time.LoadLocation("UTC")
fmt.Printf("%s\n", nt.In(l))

l, _ = time.LoadLocation("Europe/London")
fmt.Printf("%s\n", nt.In(l))

l, _ = time.LoadLocation("America/Los_Angeles")
fmt.Printf("%s\n", nt.In(l))

l, _ = time.LoadLocation("Asia/Seoul")
fmt.Printf("%s\n", nt.In(l))

输出:

2023-04-16 16:12:00.918525 +0000 UTC
2023-04-16 17:12:00.918525 +0100 BST
2023-04-16 09:12:00.918525 -0700 PDT
2023-04-17 01:12:00.918525 +0900 KST

time.LoadLocation 将加载您选择的语言环境。 您可以使用此结果通过传入你的 time.In 来转换您的时间。

您还可以从字符串中读取时间

在许多情况下,您将不得不读入一个字符串。 通常,这些将是时间戳。 在这些时间戳字符串上使用时间库的函数不是很好吗?

默认情况下,时间库适用于 time.Time 类型。 但是,我们可以使用 time.Parse 来解析这些时间戳字符串。

timestamp := "2023-02-06 23:49:01"
ts, err := time.Parse("2006-01-02 15:04:05", timestamp)
if err != nil {
    fmt.Println(err)
}
fmt.Println(ts)

输出:

2023-02-06 23:49:01 +0000 UTC

您还可以使用上述 Format 方法格式化 ts。

等等,什么是单调时钟

让我们回到这个话题。 这听起来比实际情况要可怕得多。

您的计算机有一个计时时钟。 很有可能这次相当不稳定。 有没有过在去另一个国家旅行后你的时钟慢了几个小时的经历? 是否曾经需要重新设置您的时钟以使其与您的手表相匹配? 这个时钟叫做挂钟,很容易改变。

虽然挂钟擅长报时,但不适合测量时间。 例如,看看这段代码。

t1 := time.Now()
fmt.Println(t1)
time.Sleep(time.Second)
t2 := time.Now()
fmt.Println(time.Now())
fmt.Println(t2.Sub(t1))

输出:

2023-04-17 00:15:32.65858 +0800 CST m=+0.000109168
2023-04-17 00:15:33.660121 +0800 CST m=+1.001672543
1.001563166s

上面的代码测量了 t1 和 t2 之间经过的时间。 这看起来很明显,因为我们在声明 t2 之前等待了一秒钟。 但是,如果我们以某种方式设法在该跨度内切换我们的操作系统时间设置呢? 如果我们将系统时钟增加 4 小时,是否意味着 t1 和 t2 之间经过的时间为 4 小时 1 秒? 这是荒谬的!

这就是 Go 使用单调时钟来测量时间的原因。 从打印出来的时间里的m值可以看出,时间差大约是一秒。 单调时钟允许准确测量时间。

结论

我们对时间的概念如此熟悉,以至于我们倾向于认为我们对它的理解是理所当然的。 然而,时间往往是在计算机中表示的更令人沮丧的事物之一。 幸运的是,Go 开发人员已经从我们这里抽象出了大部分原始转换,这样我们就可以使用 time 包的简单易懂的功能。 这篇文章涵盖了很多必要的功能,但如果您需要细节,您可以随时参考官方文档。

到此这篇关于详解Go中处理时间数据的方法的文章就介绍到这了,更多相关Go处理时间数据内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go语言tunny的workerWrapper使用教程示例

    Go语言tunny的workerWrapper使用教程示例

    这篇文章主要为大家介绍了Go语言tunny的workerWrapper使用教程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • Go语言包管理工具Godep的用法

    Go语言包管理工具Godep的用法

    这篇文章介绍了Go语言包管理工具Godep的用法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Go利用反射reflect实现获取接口变量信息

    Go利用反射reflect实现获取接口变量信息

    反射是通过实体对象获取反射对象(Value、Type),然后可以操作相应的方法。本文将利用Go语言中的反射reflect实现获取接口变量信息,需要的可以参考一下
    2022-05-05
  • Go语言学习之链表的使用详解

    Go语言学习之链表的使用详解

    链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。本文将详细为大家介绍Go语言中链表的使用,感兴趣的可以了解一下
    2022-04-04
  • 一文详解Golang中new和make的区别

    一文详解Golang中new和make的区别

    在Go语言中,new和make是两个用于创建对象的内建函数。本文将详细介绍new和make的区别,并通过多个方面的分析和代码示例,帮助大家理解它们的使用场景
    2023-05-05
  • go zero微服务框架logx日志组件剖析

    go zero微服务框架logx日志组件剖析

    这篇文章主要为大家介绍了go zero微服务框架logx日志组件剖析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • 关于Go 是传值还是传引用?

    关于Go 是传值还是传引用?

    这篇文章主要讨论Go语言 是传值还是传引用?文章先从Go 官方的定义展开,随后是传值和传引用得介绍到map 和 slice得区别,需要的小伙伴可以参考一下文章得具体内容
    2021-10-10
  • Golang 使用gorm添加数据库排他锁,for update

    Golang 使用gorm添加数据库排他锁,for update

    这篇文章主要介绍了Golang 使用gorm添加数据库排他锁,for update,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 详解Golang实现http重定向https的方式

    详解Golang实现http重定向https的方式

    这篇文章主要介绍了详解Golang实现http重定向https的方式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • GoLang string类型深入分析

    GoLang string类型深入分析

    string 作为 go 语言中的基础类型,其实有一些需要反复揣摩的,可能是我们使用的场景太简单,也可能是我们不需要那可怜的一点优化来提高性能,对它也就没那么上心了
    2023-01-01

最新评论