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

Swift中能否结合doesRelativeDateFormatting使用自定义日期格式?

解决Swift中同时支持相对日期和自定义非相对日期格式的问题

我来帮你搞定这个需求!要实现既显示today/tomorrow这类友好的相对日期,又在非相对场景下使用Wed, Feb 10 '18这种自定义格式,我们可以通过组合DateFormatter的特性,再加上简单的判断逻辑来实现,具体方案如下:

核心思路

当开启doesRelativeDateFormatting后,DateFormatter会优先返回相对日期字符串(比如"Today"、"Tomorrow",具体取决于本地化设置)。我们可以先尝试用带相对格式化的formatter处理日期,如果返回的是相对字符串就直接用;如果不是,再切换到自定义格式的formatter来生成目标样式。

完整代码实现

你可以把这个逻辑封装成一个Date的扩展,方便在项目里随时调用:

extension Date {
    func formattedWithRelativeOrCustomStyle() -> String {
        // 1. 配置支持相对格式化的formatter
        let relativeFormatter = DateFormatter()
        relativeFormatter.doesRelativeDateFormatting = true
        // 设置基础dateStyle触发相对格式化判断
        relativeFormatter.dateStyle = .short
        relativeFormatter.locale = Locale(identifier: "en_US_POSIX") // 根据需求调整本地化
        
        // 2. 先尝试获取相对日期字符串
        let relativeString = relativeFormatter.string(from: self)
        
        // 3. 判断是否为相对日期:对比关闭相对格式化的结果
        let nonRelativeFormatter = DateFormatter()
        nonRelativeFormatter.dateStyle = .short
        nonRelativeFormatter.locale = relativeFormatter.locale
        let nonRelativeString = nonRelativeFormatter.string(from: self)
        
        if relativeString != nonRelativeString {
            // 返回相对日期字符串
            return relativeString
        } else {
            // 使用自定义格式生成非相对日期
            let customFormatter = DateFormatter()
            customFormatter.dateFormat = "EEE, MMM d ''yy"
            customFormatter.locale = relativeFormatter.locale
            return customFormatter.string(from: self)
        }
    }
}

关键细节说明

  • 相对日期判断逻辑:通过对比开启/关闭相对格式化的formatter输出结果,就能知道当前日期是否触发了相对格式化——两者结果不同,说明是相对日期场景。
  • 自定义格式字符串解析:"EEE, MMM d ''yy"完全匹配你想要的样式:
    • EEE:星期缩写(如Wed)
    • MMM:月份缩写(如Feb)
    • d:不带前导零的日期数字
    • ''yy:带单引号的两位年份(如'18)
  • 本地化适配:如果是中文环境,把locale改成Locale(identifier: "zh_CN"),相对日期会自动变成"今天"/"明天",完全符合用户的语言习惯。

用法示例

// 今天的日期
let today = Date()
print(today.formattedWithRelativeOrCustomStyle()) // 输出 "Today"

// 明天的日期
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: today)!
print(tomorrow.formattedWithRelativeOrCustomStyle()) // 输出 "Tomorrow"

// 一个非近期的日期
let pastDate = Calendar.current.date(byAdding: .day, value: -30, to: today)!
print(pastDate.formattedWithRelativeOrCustomStyle()) // 输出类似 "Wed, Feb 10 '18" 的结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:06:55