
go 的 `time.format()` 不支持自动添加英文日期序数词后缀(如 "1st"、"2nd"),需手动拼接;本文提供简洁可靠的自定义格式化函数,并涵盖边界处理与本地化扩展建议。
Go 标准库的 time.Time.Format() 方法基于固定布局字符串(如 "2006-01-02")进行格式化,其占位符(如 "2" 表示日)仅输出纯数字,不支持语言学意义上的序数词(ordinal suffixes)——即不会将 1 转为 1st、2 转为 2nd 等。因此,直接使用 "Monday 2nd January" 会导致字面量 "2nd" 被原样保留,而 2 占位符仍输出实际日期数字(如 4),最终变成 "4nd",显然不符合预期。
要实现正确效果,核心思路是:分离格式化逻辑——先用 t.Format() 生成不含日序数词的骨架字符串,再动态插入带后缀的日期数字。以下是一个生产就绪的实现:
func formatDate(t time.Time) string {
day := t.Day()
var suffix string
switch {
case day%100 >= 11 && day%100 <= 13:
suffix = "th" // 11th, 12th, 13th are special cases
case day%10 == 1:
suffix = "st"
case day%10 == 2:
suffix = "nd"
case day%10 == 3:
suffix = "rd"
default:
suffix = "th"
}
// 使用 Format() 拼接:替换掉原始布局中的 "2" 占位符,注入 "Xth" 形式
base := t.Format("Monday ") + fmt.Sprintf("%d%s", day, suffix) + t.Format(" January")
return base
}✅ 关键改进说明:
- 正确处理英语序数词规则:11, 12, 13 恒为 th(避免 11st 错误);
- 使用 day%100 和 day%10 组合判断,覆盖所有日期(1–31);
- 利用 t.Format("Monday ") 和 t.Format(" January") 分段获取星期与月份,确保本地化兼容(若 time.Time 已设置对应 Location,且系统支持,Monday/January 会自动本地化);
- 避免硬编码 "2" 占位符,提升可读性与健壮性。
? 使用示例:
t := time.Date(2025, 3, 1, 0, 0, 0, 0, time.UTC) fmt.Println(formatDate(t)) // 输出:Sunday 1st March t = time.Date(2025, 3, 11, 0, 0, 0, 0, time.UTC) fmt.Println(formatDate(t)) // 输出:Tuesday 11th March
⚠️ 注意事项:
- Go 原生不内置多语言序数词支持(如法语 "1er"、西班牙语 "1º"),如需国际化,应结合 golang.org/x/text 包与区域规则实现;
- 若需高频调用,可预编译 suffix 映射表(map[int]string)以减少分支开销;
- 该方案保持了 time.Format() 对时区、语言环境的原有能力,仅增强日部分的表达力。
通过这一轻量封装,你就能在 Go 中稳定输出符合英语习惯的“Wednesday 4th March”这类自然日期格式,兼顾准确性与可维护性。










