贝利信息

Go 中实现带序数词后缀(如 1st、2nd、3rd)的日期格式化教程

日期:2026-01-26 00:00 / 作者:碧海醫心

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
}

关键改进说明

? 使用示例

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 中稳定输出符合英语习惯的“Wednesday 4th March”这类自然日期格式,兼顾准确性与可维护性。