防止日期本地化

时间:2018-04-17 21:39:04

标签: ios swift date

我有以下字符串:

let dateString = "2018-04-18T04:54:00-04:00"

我通过Date通过执行以下操作初始化ISO8601DateForamtter

let formatter = ISO8601DateFormatter()
let date = formatter.date(from: dateString)

如果我打印日期,我会得到以下内容:

Apr 18, 2018 at 1:54am

格式化程序会自动将时间转换为我当地时间。如何防止占用我的时区?例如,我希望Date对象显示以下内容:

Apr 18, 2018 at 4:54am 

5 个答案:

答案 0 :(得分:1)

使用ISO86012018-04-18T04:54:00-04:00表示2018-04-18 04:54:00中的GMT -4h。要打印原始字符串中的时间,您需要创建一个具有-4特定时区的日期格式化程序。

let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(secondsFromGMT: -4 * 60 * 60)
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
print(dateFormatter.string(from: date))

你会得到

2018-04-17 04:54:00

仅供参考,我正在添加ISO8601

的链接

答案 1 :(得分:1)

您需要从日期字符串中解析时区并使用它来设置日期格式化程序的时区:

func secondsFromGMT(from string: String) -> Int {
    guard !string.hasSuffix("Z") else { return 0 }
    let timeZone = string.suffix(6)
    let comps = timeZone.components(separatedBy: ":")
    guard let hours = comps.first,
        let minutes = comps.last,
        let hr = Int(hours),
        let min = Int(minutes) else { return 0 }
    return hr * 3600 + min * 60
}
let dateString = "2018-04-18T04:54:00-04:00"

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssxxxxx"
formatter.locale = Locale(identifier: "en_US_POSIX")
if let dateFromString = formatter.date(from: dateString) {
    formatter.timeZone = TimeZone(secondsFromGMT: secondsFromGMT(from: dateString))
    formatter.dateFormat = "MMM dd, yyyy 'at' h:mma"
    formatter.amSymbol = "am"
    formatter.pmSymbol = "pm"
    print(formatter.string(from: dateFromString))  // Apr 18, 2018 at 4:54am
}

答案 2 :(得分:0)

不要直接记录Date,而是查看string(from:timeZone:formatOptions:)上的ISO8601DateFormatter方法。有了这个,您应该能够获得所需时区的日期字符串。

答案 3 :(得分:0)

您应该将格式化程序设置为适当的时区,例如(UTC示例如下):

formatter.timeZone = TimeZone(identifier: "UTC")

或者指定GMT:

formatter.timeZone = TimeZone(secondsFromGMT: 0)

答案 4 :(得分:0)

您从当前格式化程序收到的日期在技术上是正确的。不建议按照当前接受的答案中的描述向后设置日期,因为您实际上是对预期时区进行硬编码。只要您的设备进入其他时区(或者用户在当前时区之外下载您的应用),您的信息就会不正确。

如果您在UTC时区尝试显示,则需要使用其他格式化程序正确格式化目标时区的输出。

为什么是你原来的日期正确吗?

let utcFormatter = DateFormatter() utcFormatter.timeZone = TimeZone(secondsFromGMT: 0) // Perform any other transformations you'd like let output = utcFormatter.string(from: date) API具有令人难以置信的强大功能,可以在很多方面做很多事情,但是使用简单的Date可以有效地实现。它向您显示的自动时区信息是一种抽象,可以更容易推理。日期在技术上不知道它所在的时区 - 但将其转换为字符串会隐含地在日期应用推断日期格式化程序并返回它认为对您最有用的信息。

如果您正在对某个日期进行操作,则可能会使用Double API。您通常会使用Calendar获取新实例,该实例将使用您当前的时区信息创建新日历。您可以更改日历的表示时区,如下所示:

Calendar.current

这将为您提供适用于任何时区的相对日期,而无需修改您正在使用的基础var calendar = Calendar.current calendar.timeZone = TimeZone(secondsFromGMT: 0) 对象。