如何使用Elixir DateTime实现RFC2616格式日期转换
实现思路
- 时区归一化:RFC2616 标准要求 HTTP 头所用日期必须为 GMT(即 UTC+0)时区,首先将输入的任意时区 DateTime 对象通过
DateTime.shift_zone/3转为 UTC 时区,从根源避免时区偏差,兼容非 UTC 输入场景。 - 静态映射替代内置格式化:不依赖
Calendar.DateTime.Format.httpdate方法,提前定义两个固定映射表即可完成星期、月份的缩写转换:- 星期缩写映射按周一到周日顺序配置为
["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],通过Date.day_of_week/1返回的1-7值减1后直接取对应索引值 - 月份缩写映射按1-12月顺序配置为
["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],通过DateTime.month/1返回的1-12值减1后直接取对应索引值
- 星期缩写映射按周一到周日顺序配置为
- 字段格式处理:按照 RFC2616 规则处理字段格式:日期字段不补前导零,时、分、秒字段统一补前导零到2位长度,直接丢弃微秒字段(标准格式不支持微秒位)。
- 固定格式拼接:按照
周缩写, 日期 月缩写 年 时:分:秒 GMT的固定结构拼接字符串即可。
可直接复用的代码实现
@week_abbr ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] @month_abbr ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] @spec to_rfc2616(DateTime.t()) :: String.t() def to_rfc2616(%DateTime{} = dt) do # 统一转换为UTC时区,对应末尾GMT标识 utc_dt = DateTime.shift_zone!(dt, "Etc/UTC") week_name = Enum.at(@week_abbr, Date.day_of_week(utc_dt) - 1) month_name = Enum.at(@month_abbr, utc_dt.month - 1) # 时分秒统一补前导零到两位 hour = utc_dt.hour |> Integer.to_string() |> String.pad_leading(2, "0") minute = utc_dt.minute |> Integer.to_string() |> String.pad_leading(2, "0") second = utc_dt.second |> Integer.to_string() |> String.pad_leading(2, "0") "#{week_name}, #{utc_dt.day} #{month_name} #{utc_dt.year} #{hour}:#{minute}:#{second} GMT" end
效果验证
用你提供的样例输入调用方法:
to_rfc2616(~U[2022-06-07 18:37:16.842920Z])
输出结果为Tue, 7 Jun 2022 18:37:16 GMT,完全符合格式要求。
注意:实现全程仅使用 DateTime、Date 模块的基础原生方法,没有引入额外依赖,也未调用被禁用的 httpdate 格式化接口,适配现有代码库的技术约束。
内容的提问来源于stack exchange,提问作者give_me_ur_btcns
相关产品推荐
相关产品推荐

