Swift DateIntervalFormatter:即使间隔跨越多天,也将日期保留在字符串之外

Posted

技术标签:

【中文标题】Swift DateIntervalFormatter:即使间隔跨越多天,也将日期保留在字符串之外【英文标题】:Swift DateIntervalFormatter: keep dates out of the string even if interval spans multiple days 【发布时间】:2020-07-24 16:29:17 【问题描述】:

我正在尝试格式化时间间隔。我想要一个看起来像这样的结果:

10:45 - 12:00 AM

我可以使用DateInvervalFormatter 非常接近这一点:

let cal = Calendar.current
let formatter = DateIntervalFormatter()
formatter.dateStyle = .none
formatter.timeStyle = .short
let start = Date()
let end = cal.date(byAdding: .hour, value: 1, to: start)
formatter.string(from: DateInterval(start: start, end: end!))

上述(在 en_US 语言环境中)将产生如下输出:

5:27 – 6:27 PM

看起来不错吧?但是,如果间隔中的两个日期在不同的日期,则此方法不起作用。例如:

let formatter = DateIntervalFormatter()
formatter.dateStyle = .none
formatter.timeStyle = .short
let startComponents = DateComponents(year: 2020, month: 1, day: 1, hour: 23, minute: 45)
let start = cal.date(from: startComponents)
let end = cal.date(byAdding: .hour, value: 1, to: start!)
formatter.string(from: DateInterval(start: start!, end: end!))

尽管将dateStyle 设置为.none,但上述示例中生成的字符串(在 en_US 语言环境中)是:

1/1/2020, 11:45 PM – 1/2/2020, 12:45 AM

我想要的是:

11:45 PM – 12:45 AM

我怎样才能得到这个?我知道我可以使用DateFormatter 将每个日期(开始和结束)格式化为一个时间,然后在中间附加两个字符串和一个连字符(-),但这不一定对本地化友好.

【问题讨论】:

在使用日期格式化程序方法时,我不明白本地化有什么问题。 @LeoDabus 也许使用 DateFormatter 并没有什么问题,但我当然不是所有语言环境的专家,并假设可能有些语言不会使用连字符。 Apple 在 DateIntervalFormatter 中完成了所有艰苦的本地化工作,我想利用它。 好吧,我认为他们不会只显示两个不同日期的日期间隔和时间 也许吧!但也许有办法 - 因此我的问题。奇怪的是,在给定 dateStyle.none 的情况下,它们仍然显示日期......这似乎是实现我想要的合乎逻辑的方式。 我认为你现在得到的是这样做的逻辑方式,因为没有日期就不可能正确解释信息 【参考方案1】:

我最终得到的是:

extension Date 
    
    func formatTimeInterval(
        to: Date,
        timeZone: TimeZone = .autoupdatingCurrent
    ) -> String 
        
        let formatter = DateIntervalFormatter()
        formatter.timeZone = timeZone
        formatter.timeStyle = .short
        formatter.dateStyle = .none
        
        // we need to manually strip any "date" metadata, because for some locales,
        // even if we set `formatter.dateStyle = .none`, if the dates are in two different days
        // we will still get the date information in the end result (e.g. for the US locale)
        
        let calendar = Calendar.current
        let fromComponents = calendar.dateComponents([.hour, .minute, .second], from: self)
        let toComponents = calendar.dateComponents([.hour, .minute, .second], from: to)
        let fromDate = calendar.date(from: fromComponents)!
        let toDate = calendar.date(from: toComponents)!
        return formatter.string(from: fromDate, to: toDate)
    

但是,如果间隔日期在不同的月份(比如 8 月 31 日 - 9 月 1 日),它会添加一个从第 1 年开始的日期,类似于

1/1/1, 11:45 PM – 1/2/1, 12:45 AM

这仍然没有干净的解决方案......

【讨论】:

以上是关于Swift DateIntervalFormatter:即使间隔跨越多天,也将日期保留在字符串之外的主要内容,如果未能解决你的问题,请参考以下文章

Swift入门系列--Swift官方文档(2.2)--中文翻译--About Swift 关于Swift

swift 示例BS swift.swift

swift swift_bug.swift

ios 整理(一)swift和oc的区别

swift swift_extension5.swift

swift swift_optional4.swift