
本文介绍如何使用 Go 的 time.Parse 函数正确解析形如 "November 05, 2016, 01:02:31 PM" 的英文月份、12 小时制带 AM/PM 的日期时间字符串。关键在于匹配 Go 独特的参考时间布局(layout),而非传统 POSIX 格式。
本文介绍如何使用 go 的 `time.parse` 函数正确解析形如 `"november 05, 2016, 01:02:31 pm"` 的英文月份、12 小时制带 am/pm 的日期时间字符串。关键在于匹配 go 独特的参考时间布局(layout),而非传统 posix 格式。
Go 语言的 time.Parse 函数不接受常见的格式化字符串(如 %Y-%m-%d),而是要求使用一个固定的“参考时间”作为 layout 模板:Mon Jan 2 15:04:05 MST 2006(即 Unix 时间戳 1136239445 对应的本地时间)。所有 layout 字符串都必须严格遵循该参考时间中各字段的位置与大小写。
对于输入字符串 "November 05, 2016, 01:02:31 PM",我们逐段对照参考时间推导 layout:
-
November→ 月份全名 →January(layout 中对应January,注意首字母大写,且必须为英文全称) -
05→ 日(带前导零)→02(参考时间中日期是2,但需用02表示两位数字格式) -
2016→ 四位年份 →2006 -
01:02:31→ 12 小时制小时、分钟、秒 →15:04:05中的15在 12 小时制下应替换为03?❌ 错!正确做法是:保留03仅用于表示 12 小时制的小时占位,但实际 layout 中必须写03,并配合PM使用。然而 Go 官方文档明确指出:03表示 12 小时制(1–12),而15表示 24 小时制(0–23);同时PM是独立布局元素,必须显式写出。
✅ 正确 layout 为:
"January 02, 2006, 03:04:05 PM"
⚠️ 注意:虽然参考时间中是
15:04:05,但解析01:02:31 PM时,小时部分必须用03(代表 12 小时制),而非15;否则解析将失败或产生意外结果(例如01被当作 24 小时制的凌晨 1 点,忽略PM)。
完整示例代码如下:
package main
import (
"fmt"
"time"
)
func main() {
layout := "January 02, 2006, 03:04:05 PM"
input := "November 05, 2016, 01:02:31 PM"
t, err := time.Parse(layout, input)
if err != nil {
panic(err)
}
fmt.Println("Parsed time:", t) // 2016-11-05 13:02:31 +0000 UTC
fmt.Println("In local timezone:", t.Local()) // 如本地为 CST,则显示对应本地时间
}? 关键注意事项:
- layout 中的月份名称(如
January)必须为英文全称且首字母大写;缩写(如Nov)需改用Jan。 -
03是 12 小时制小时的唯一合法 layout 符号;01或1均无效。 -
PM(或AM)必须原样出现在 layout 和输入字符串中,区分大小写。 - 解析结果默认为 UTC 时间;如需本地时区,请调用
.Local()方法(注意:time.Parse本身不读取系统时区,需显式处理)。 - 若输入含有时区信息(如
EST,PDT),需在 layout 中添加对应 zone 名称,并确保time.LoadLocation或使用time.Now().Location()配合解析。
掌握这一机制后,你可灵活应对各类英文日期格式,例如 "Dec 25, 2023, 11:59:59 PM" —— 对应 layout 即 "Jan 02, 2006, 03:04:05 PM"(Jan 可匹配任意英文月份缩写,前提是输入一致;但为严谨起见,建议 layout 中也使用 Jan 并确保输入为缩写,或统一用全称)。

















