【问题标题】:Using DateFormatter produces a result which is off by a day使用 DateFormatter 产生的结果相差一天
【发布时间】:2018-01-02 19:41:20
【问题描述】:

使用 DateFormatter 会产生相差一天(实际上是 12 小时)的结果。使用以下代码始终生成显示为前一天的日期。一段时间以来,我在许多应用程序中都遇到了这个问题,但终于有时间深入研究它。

extension Date
{
    func display() -> String
    {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MMMM dd, yyyy"
        print(dateFormatter.locale)
        dateFormatter.locale = Locale(identifier: "en_US_POSIX")
        let txt = dateFormatter.string(from: self)
        print(txt)
        return txt
    }
}

类似的其他问题建议更改语言环境,因此添加了代码,但我检查了语言环境和实际日期。如果我在日期上加上 8 小时,我会得到正确的显示结果,但添加的时间少于这个时间不会有任何作用。一些日期是从联系人应用程序中的生日字段中检索出来的,这会产生时间为 00:00:00 UTC 的日期。看来我需要将日期转换为当地时间?设备上的时区设置为本地时区(太平洋)。这看起来还不错,但是从日期选择器中检索到的日期不是 UTC 时间,而是当地时间。自从使用日历类并尝试提取 .timezone 组件说“此方法无法获取 NSCalendarUnitTimeZone”以来,我一直无法弄清楚如何判断日期所在的时区。有关如何创建适用于所有情况的通用日期格式化程序的任何建议?

【问题讨论】:

    标签: date swift3 dateformatter


    【解决方案1】:

    几个观察:

    1. 如果您的 Date 对象位于 UTC 时区,则也将格式化程序的 timeZone 设置为 TimeZone(secondsFromGMT: 0)

    2. 如果您在 UI 中显示 Date 对象的字符串表示,您确实想要使用 en_US_POSIXlocale。您想在设备的默认位置显示它(即,根本不要更改格式化程序的 locale)。您仅在处理内部使用的 ISO 8601 和 RFC 3339 日期字符串时使用 en_US_POSIX,例如,用于与 Web 服务交换日期字符串。

    3. 最后,我不会指定dateFormat 字符串,因为并非所有用户都希望日期采用MMMM dd, yyyy 格式。例如,英国用户期望它采用d MMMM yyyy 格式。在 UI 中显示日期时,请指定 dateStyle。或者,如果这些样式都不起作用,请继续指定dateFormat,但使用setLocalizedDateFormatFromTemplate(_:) 而不是固定字符串进行设置。

    因此,为了你的目的,你会这样做:

    extension Date {
        var dateString: String {
            let formatter = DateFormatter()
            formatter.dateStyle = .long
            formatter.timeZone = TimeZone(secondsFromGMT: 0)
            return formatter.string(from: self)
        }
    }
    

    或者,如果您经常调用它,您可能希望重用格式化程序:

    extension Date {
    
        private static let formatterForDateString: DateFormatter = {
            let formatter = DateFormatter()
            formatter.dateStyle = .long
            formatter.timeZone = TimeZone(secondsFromGMT: 0)
    
            return formatter
        }()
    
        var dateString: String {
            return Date.formatterForDateString.string(from: self)
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      使用timeZone属性,获取准确的日期,如下图:

          formatter.timeZone = TimeZone(secondsFromGMT: 0)
      

      它会解决你的目的!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-26
        • 2013-08-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-08
        相关资源
        最近更新 更多