1

使用 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 组件说“

4

2 回答 2

1

几点观察:

  1. 如果您的Date对象在 UTC 时区,那么也将您的格式化程序设置timeZoneTimeZone(secondsFromGMT: 0)

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

  3. 最后,我不会指定dateFormat字符串,因为并非所有用户都期望日期MMMM dd, yyyy格式。例如,英国用户期望它的d MMMM yyyy格式。在 UI 中显示日期时,请指定 a 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)
    }

}
于 2018-01-02T20:13:48.473 回答
0

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

    formatter.timeZone = TimeZone(secondsFromGMT: 0)

它会解决你的目的!

于 2018-01-03T07:36:54.083 回答