Ruby如何用strftime或I18n.l格式化日期为季度+年份?
首先直接回答你的问题:strftime本身没有内置的季度格式占位符,但可以通过扩展实现;而I18n.l是实现本地化季度格式的最佳方案,完全能解决你提到的白标合作伙伴自定义格式的需求。
先说说strftime的局限
你当前手动计算季度的方式是可行的,但确实没法直接通过strftime的原生参数生成季度格式——因为标准的strftime没有%q这类专门的季度占位符。如果只是单一格式需求,这个方案没问题,但要适配多场景的话,扩展性太差。
用I18n实现本地化的最优解
I18n本来就是为多语言、多格式场景设计的,我们可以通过配置+简单的类扩展来实现灵活的季度格式化:
1. 配置本地化格式
在项目的config/locales目录下,针对不同语言/合作伙伴需求添加配置文件:
比如英文基础配置(en.yml):
en: date: formats: quarter_short: "Q%q %Y"
如果有白标合作伙伴需要中文格式(zh.yml):
zh: date: formats: quarter_short: "第%q季度 %Y"
甚至可以给特定合作伙伴单独做配置(比如partner_a.yml):
partner_a: date: formats: quarter_short: "Q%q '%y"
2. 给Date/Time类添加季度计算方法
要让I18n能识别%q这个自定义占位符,我们需要给Date和Time类加一个返回季度数字的方法。在config/initializers/date_extensions.rb里添加:
class Date def quarter (month - 1) / 3 + 1 end end class Time def quarter (month - 1) / 3 + 1 end end
3. 调用I18n.l格式化日期
现在你就可以用统一的代码,根据当前locale自动适配格式:
# 默认英文locale下 I18n.l(datum.recorded_at, format: :quarter_short) # 输出:"Q1 2018" # 切换到中文locale I18n.with_locale(:zh) do I18n.l(datum.recorded_at, format: :quarter_short) end # 输出:"第1季度 2018" # 切换到特定合作伙伴的locale I18n.with_locale(:partner_a) do I18n.l(datum.recorded_at, format: :quarter_short) end # 输出:"Q1 '18"
进阶:支持完整季度名称
如果需要更正式的格式(比如英文"First Quarter 2018"),可以在本地化文件里定义季度名称:
en: date: quarters: 1: "First" 2: "Second" 3: "Third" 4: "Fourth" formats: quarter_long: "%{quarter} Quarter %Y"
调用时:
date = datum.recorded_at I18n.t('date.formats.quarter_long', quarter: I18n.t("date.quarters.#{date.quarter}"), year: date.year) # 输出:"First Quarter 2018"
替代方案:扩展strftime
如果你更习惯strftime的写法,也可以扩展它支持自定义占位符:
class Date def strftime_with_quarter(format) format.gsub('%q', quarter.to_s).gsub('%Q', I18n.t("date.quarters.#{quarter}")) end end # 使用示例 datum.recorded_at.strftime_with_quarter("Q%q %Y") # 输出 "Q1 2018"
不过这种方式的扩展性不如I18n,新增格式需要修改代码,而I18n只需要添加配置文件即可。
总结一下:用I18n的方案完全能满足你本地化的需求,后续新增格式只需要加配置,不用改业务代码,非常适合白标这类多场景的需求。
内容的提问来源于stack exchange,提问作者jeznag

