You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何通过JSONEncoder/Codable将Date转为无小数Unix秒数

解决Codable序列化Date为无小数Unix秒数的问题

嘿,这个场景我太熟悉了!默认的.secondsSince1970确实会输出带毫秒的浮点数,而DateFormatter又没法直接输出数值型的Unix秒数,完全重写Codable又太麻烦。给你几个简单高效的方案:

方案一:直接自定义dateEncodingStrategy闭包

这是最直接的方法,不用改动你的模型代码,只需要给JSONEncoder设置自定义的日期编码策略就行:

let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .custom { date, encoder in
    // 把Date的时间戳转成整数秒(自动舍去小数部分)
    let unixSeconds = Int(date.timeIntervalSince1970)
    var container = encoder.singleValueContainer()
    try container.encode(unixSeconds)
}

// 测试示例
struct Event: Codable {
    let name: String
    let timestamp: Date
}

let event = Event(name: "Test", timestamp: Date())
if let data = try? encoder.encode(event),
   let jsonString = String(data: data, encoding: .utf8) {
    print(jsonString)
    // 输出会是 {"name":"Test","timestamp":1699999999} 这类纯整数格式
}

这个闭包逻辑很直白:把Date的timeIntervalSince1970转成Int类型(自动丢弃小数部分),再编码成数值类型,这样序列化后的JSON里就是无小数的Unix秒数了。

方案二:封装复用的编码器

如果项目里很多地方都需要这个逻辑,建议封装成扩展,方便随时调用:

extension JSONEncoder {
    static var unixSecondsEncoder: JSONEncoder {
        let encoder = JSONEncoder()
        encoder.dateEncodingStrategy = .custom { date, encoder in
            try encoder.encode(Int(date.timeIntervalSince1970))
        }
        return encoder
    }
}

// 使用时直接调用
let data = try JSONEncoder.unixSecondsEncoder.encode(event)

配套的解码策略(可选)

如果需要反序列化对应的JSON,记得给JSONDecoder设置对应的解码逻辑:

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom { decoder in
    let timestamp = try decoder.singleValueContainer().decode(Int.self)
    return Date(timeIntervalSince1970: TimeInterval(timestamp))
}

为什么不用DateFormatter?

你说得没错,DateFormatter的dateFormat确实没有直接输出Unix秒数的格式——它主要负责字符串格式的日期转换,而Unix秒数是数值类型,所以用自定义闭包是最适配的方案,比绕弯子用DateFormatter高效多了。

内容的提问来源于stack exchange,提问作者mm282

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:27:11