Golang中time.Format方法的使用问题解析
Golang中time.Format方法的使用问题解析
我正在绞尽脑汁,试图理解 time.Format 中一个非常简单的单字符更改。
我查看了这个网站以查看一些格式化示例。如果我使用他们的格式化示例,它可以正常工作;但如果我更改一个地方,它就不行了,我不明白其中的区别。
完整代码:
package main
import (
"log"
"time"
)
func main() {
t := time.Now()
log.Println(t)
log.Println("Correct:", t.Format("2006-01-02 15:04:05"))
log.Println("Weird:", t.Format("2007-01-02 15:04:05"))
}
输出: 2021/07/23 23:44:24 2021-07-23 23:44:24.569482 +0100 BST m=+0.000072078 2021/07/23 23:44:24 Correct: 2021-07-23 23:44:24 2021/07/23 23:44:24 Weird: 23007-07-23 23:44:24
为什么年份差异如此之大?如果我更改年、月、日、小时等,也会发生类似的情况。
非常感谢。
更多关于Golang中time.Format方法的使用问题解析的实战教程也可以访问 https://www.itying.com/category-94-b0.html
同意。这可能是我在标准库中最不喜欢的函数!
更多关于Golang中time.Format方法的使用问题解析的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你可以尝试使用 carbon,这是一个简单、语义化且对开发者友好的 Go 语言日期时间处理包。
好的,非常感谢。我已经点击链接,现在明白它的来源了。这不是首先会想到的事情——需要知道那些“魔法数字”才能知道如何格式化日期。
J.
啊哈!非常感谢您的及时回复。但我仍然有些困惑。
以年份为例,2006和2007之间有什么区别?它们都是四位数,所以我期望得到的结果是四位数的年份。为什么我得到了五位数?我不明白为什么使用2006作为格式得到的是2021,而使用2007却得到23007。难道2006是那个神奇的数字(而不仅仅是代表4位数字)?
再次感谢。
因为2007不是魔法数字之一。2是表示日期的魔法数字,所以你在“2”的位置得到了“23”,然后,我猜格式化程序不知道如何处理“007”,所以就原样保留了。
编辑: 列出具体数字的Go文档链接:https://pkg.go.dev/time#Parse
日期组件都是魔数。与大多数编程语言使用诸如“yy”、“yyyy”、“MM”、“MMM”等表示方式不同,Go 决定使用魔数来表示日期格式。要在 Go 中获得两位数的年份格式,请使用“06”;要获得四位数的年份,请使用“2006”。要获得12小时制的小时,请使用“03”或“3”。要使其成为24小时制,请使用“15”,等等。
我怀疑这原本是为了比记住“mm 是月份而 MM 是分钟,还是反过来?”更容易。然而,似乎每个人(包括我自己!)都会感到困惑,所以我认为他们并没有完全做对。
感谢您的提示。我可能会尝试一下。在必要时我会使用第三方包。
我打算在这里写一些可能具有争议性的内容,您自己也提到了:如果我需要使用第三方包来获得“对开发者友好”的日期和时间函数,那么根据定义,内置函数就是“对开发者不友好”的。我认真考虑了 skillian 关于 MM 和 mm 混淆的论述——我自己这些年来也犯过好几次这样的错误,事后才意识到我用了月份而不是分钟,或者反之,然后改正了。这很容易出错,也同样容易纠正。如果不了解所使用的那些“魔法数字”,我绝不会想到 2007 和 2006 有如此大的不同。
我算不上你们所说的那种严肃的开发者,我只是随便玩玩。我发现 Go 语言非常容易上手,没有遇到任何严重问题,只有学习新事物时常见的那些典型困难。这是我第一次遇到一些我会描述为“奇怪”和“他们为什么要那样做?”的事情。
非常感谢, J.
在Go语言的time.Format方法中,格式化字符串使用固定的参考时间2006-01-02 15:04:05来定义格式。这个时间点不是任意的,而是Go语言设计者选择的特定时间,用于表示格式化的各个部分:
2006代表年份01代表月份02代表日期15代表小时(24小时制)04代表分钟05代表秒
当您将年份部分从2006改为2007时,解析器会将2007识别为不同的格式代码,导致年份解析错误。实际上,2007中的每个数字都被单独解析:
2被解析为年份的最后一位0被解析为年份的十位0被解析为年份的百位7被解析为年份的千位
这导致了年份显示为23007的奇怪结果。下面是一个更清晰的示例:
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
// 正确的格式化
fmt.Println("正确格式:", t.Format("2006-01-02 15:04:05"))
// 修改年份部分会导致解析错误
fmt.Println("错误格式1:", t.Format("2007-01-02 15:04:05"))
fmt.Println("错误格式2:", t.Format("2005-01-02 15:04:05"))
// 其他部分的修改也会导致问题
fmt.Println("错误月份:", t.Format("2006-13-02 15:04:05"))
fmt.Println("错误分钟:", t.Format("2006-01-02 15:14:05"))
}
输出示例:
正确格式: 2024-07-23 10:30:45
错误格式1: 42007-07-23 10:30:45
错误格式2: 52005-07-23 10:30:45
错误月份: 2024-13-02 10:30:45
错误分钟: 2024-01-02 10:14:45
关键点:必须严格使用2006-01-02 15:04:05这个参考时间的各个部分作为格式字符串的占位符。任何修改都会改变解析规则,导致意外的输出结果。


