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

11次阅读

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

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”这类自然日期格式,兼顾准确性与可维护性。

text=ZqhQzanResources