Go 语言 `time.Format` 格式化指南
Go 语言 time.Format() 方法用于将 time.Time 对象格式化为字符串,其独特之处在于使用固定参考时间作模板,而非传统符号。
核心概念:魔法时间 2006-01-02 15:04:05
Go 语言时间格式化基于特定参考时间:2006年1月2日 下午3点4分5秒。此时间为模板,在格式字符串中用其对应数字表示所需时间部分。
2006/06: 年份 (四位2006/ 两位06)01/1: 月份 (带前导零01/ 不带前导零1)Jan/January: 月份缩写Jan/ 全称January02/2: 日期 (带前导零02/ 不带前导零2)15/3: 小时 (24 小时制15/ 12 小时制3)04/4: 分钟 (带前导零04/ 不带前导零4)05/5: 秒 (带前导零05/ 不带前导零5).000/.999: 毫秒 (三位000/ 最高精度999)PM/pm: 上午/下午标记 (大写PM/ 小写pm)MST: 时区缩写 (如CST,PST,EST)-0700/Z0700: 时区偏移 (如+0800,Z代表 UTC)
记忆小技巧: 这个参考时间可看作 1 2 3 4 5 6 的变体(月份 1,日期 2,小时 3,分钟 4,秒 5,年份后两位 06)。
常见用法示例
以下是 time.Format 的常见用法示例:
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now() // 获取当前本地时间
// 1. 常见日期格式 (YYYY-MM-DD)
fmt.Println("日期 (YYYY-MM-DD):", now.Format("2006-01-02")) // 示例: 2025-05-29
// 2. 常见时间格式 (HH:MM:SS)
fmt.Println("时间 (HH:MM:SS):", now.Format("15:04:05")) // 示例: 00:30:00 (24小时制)
// 3. 日期和时间 (完整)
fmt.Println("完整格式:", now.Format("2006-01-02 15:04:05")) // 示例: 2025-05-29 00:30:00
// 4. 包含中文或其他字符
fmt.Println("中文格式:", now.Format("2006年01月02日 15时04分05秒")) // 示例: 2025年05月29日 00时30分00秒
// 5. 12小时制和AM/PM
fmt.Println("12小时制 (带AM/PM):", now.Format("2006-01-02 03:04:05 PM")) // 示例: 2025-05-29 12:30:00 AM
// 6. 包含毫秒、微秒、纳秒
fmt.Println("带毫秒 (.000):", now.Format("2006-01-02 15:04:05.000")) // 示例: 2025-05-29 00:30:00.123
fmt.Println("带微秒 (.000000):", now.Format("2006-01-02 15:04:05.000000")) // 示例: 2025-05-29 00:30:00.123456
fmt.Println("带纳秒 (.999999999):", now.Format("2006-01-02 15:04:05.999999999")) // 示例: 2025-05-29 00:30:00.123456789
// 7. 文件名常用格式 (下划线连接,无特殊字符)
fmt.Println("文件名格式 (无分隔符):", now.Format("20060102150405")) // 示例: 20250529003000
fmt.Println("文件名格式 (下划线分隔):", now.Format("20060102_150405")) // 示例: 20250529_003000
fmt.Println("文件名格式 (短横线分隔):", now.Format("2006-01-02_15-04-05")) // 示例: 2025-05-29_00-30-00
// 8. 只获取年份和月份
fmt.Println("年月 (不带前导零):", now.Format("2006年1月")) // 示例: 2025年5月
fmt.Println("年月 (带前导零):", now.Format("2006年01月")) // 示例: 2025年05月
// 9. 星期几
fmt.Println("星期几 (全称):", now.Format("Monday")) // 示例: Thursday
fmt.Println("星期几 (缩写):", now.Format("Mon")) // 示例: Thu
// 10. ISO 8601 格式
fmt.Println("ISO 8601 (UTC):", now.In(time.UTC).Format("2006-01-02T15:04:05Z")) // 示例: 2025-05-28T15:30:00Z (UTC时间)
fmt.Println("ISO 8601 (带时区偏移):", now.Format("2006-01-02T15:04:05-07:00")) // 示例: 2025-05-29T00:30:00+09:00 (本地时区)
}
避坑指南
-
仅用参考时间数字作占位符,勿随意替换:
- 核心要点:
time.Format()方法的参数不是一个“模式字符串”,而是一个具体的日期时间示例。你必须使用2006、01、02、15、04、05这些固定数字来代表对应的年、月、日、时、分、秒。 - 错误示例: 如果你写
now.Format("2024-01-02"),你可能期望它输出当前年份,但实际上2024会被 Go 语言视为一个普通字符串,而不是年份的占位符。它会原样输出 "2024",而日期部分则会根据01-02格式化。 - 正确做法: 始终使用
2006来表示年份,01表示月份,02表示日期,以此类推。其他非数字字符(如-,,:,年,月等)则会被原样输出。
- 核心要点:
-
文件名特殊字符:
- 问题: 在不同的操作系统和文件系统中,某些字符(如
/,\,:,*,?,",<,>,|)在文件名中是非法的或有特殊含义。直接使用这些字符会导致文件创建失败或行为异常。 - 建议: 当将格式化后的时间字符串用作文件名时,应避免使用上述特殊字符。
- 安全字符: 推荐使用
_(下划线) 或-(短横线) 作为分隔符。例如20060102_150405.log或2006-01-02-15-04-05.txt。 - 中文文件名: 尽管现代文件系统(如 NTFS, ext4)通常支持 UTF-8 编码的中文文件名,但在跨平台或旧系统环境下,仍可能遇到兼容性问题。为确保最佳兼容性,文件名最好限制在 ASCII 字符集内。
- 问题: 在不同的操作系统和文件系统中,某些字符(如
-
前导零区分 (
01vs1,02vs2等):- 区别: Go 的格式化占位符中,带前导零的数字(如
01,02,03,04,05)和不带前导零的数字(如1,2,3,4,5)代表不同的格式化行为。01:输出带前导零的月份(例如 1 月输出01,12 月输出12)。1:输出不带前导零的月份(例如 1 月输出1,12 月输出12)。02:输出带前导零的日期(例如 9 日输出09,25 日输出25)。2:输出不带前导零的日期(例如 9 日输出9,25 日输出25)。15:24 小时制,带前导零(例如凌晨 3 点输出03,下午 3 点输出15)。03:12 小时制,带前导零(例如凌晨 3 点输出03,下午 3 点输出03)。3:12 小时制,不带前导零(例如凌晨 3 点输出3,下午 3 点输出3)。
- 选择: 根据你的具体需求(例如是否需要固定长度的输出,或是否需要与特定系统对接),选择合适的占位符。
- 区别: Go 的格式化占位符中,带前导零的数字(如
-
时区问题:
time.Now()默认行为:time.Now()返回的是当前系统的本地时间,并附带了本地时区信息。- 跨时区应用: 在分布式系统或需要处理全球用户时间的场景中,直接使用本地时间可能导致混乱。
- 推荐做法:
- 统一使用 UTC 时间: 在存储、传输和内部处理时间时,强烈建议将所有时间转换为 UTC(协调世界时)。你可以使用
time.Now().UTC()获取当前 UTC 时间。 - 转换为特定时区: 如果需要将时间显示为特定时区,可以使用
time.LoadLocation()加载时区,然后用time.In()方法转换。loc, err := time.LoadLocation("America/New_York") // 加载纽约时区 if err != nil { fmt.Println("加载时区失败:", err) return } nyTime := now.In(loc) // 将当前时间转换为纽约时间 fmt.Println("纽约时间:", nyTime.Format("2006-01-02 15:04:05 MST")) - 格式化时区偏移: 使用
-0700或Z0700可以将时区偏移包含在格式化字符串中,这对于调试和跨系统时间同步非常有用。Z在Z0700中表示 UTC 时间。fmt.Println("带时区偏移:", now.Format("2006-01-02 15:04:05 -0700")) // 示例: 2025-05-29 00:30:00 +0900 fmt.Println("UTC时间 (带Z):", now.In(time.UTC).Format("2006-01-02T15:04:05Z")) // 示例: 2025-05-28T15:30:00Z
- 统一使用 UTC 时间: 在存储、传输和内部处理时间时,强烈建议将所有时间转换为 UTC(协调世界时)。你可以使用
- 避免隐式转换: 避免在不同时区的时间之间直接进行比较或计算,这可能导致错误。始终确保时间对象处于相同的时区后再进行操作。

浙公网安备 33010602011771号