Как перевести время по Гринвичу в местное время в Swift 4? - PullRequest
0 голосов
/ 02 октября 2019

Я пробовал несколько похожих вопросов и ответов, но все еще не работает. Я пытаюсь конвертировать 2019-09-30T09:10:32.537244Z

func serverToLocal(date:String) -> Date? {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-ddTHH:mm:ss.SSSSSSZ"
    dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
    let localDate = dateFormatter.date(from: date)

    return localDate
}

Выше метода всегда возвращать ноль. Что не так с моим форматом даты?

enter image description here

1 Ответ

3 голосов
/ 02 октября 2019

Очевидно, что ключевой вопрос заключается в отсутствии кавычек вокруг T.

Но вы, вероятно, не хотите создавать новый форматер даты каждый раз, когда вызываете эту подпрограмму (потому что этообщеизвестно вычислительно дорогой процесс). Таким образом, вы должны сохранить свой форматировщик даты как свойство. Таким образом, вам не нужно создавать новый форматер для каждой строки, которую вы хотите преобразовать в Date. Также этот форматтер можно использовать для преобразования дат обратно в строки в формате 2019-09-30T09:10:32.537244Z.

. Таким образом, вопреки рекомендациям, приведенным в другом месте, я предложил бы установить timeZone от форматера. Это не требуется при преобразовании строк в даты (потому что строка даты содержит спецификатор часового пояса), но при переходе от даты к строкам вам действительно нужен форматер даты, чтобы указать часовой пояс, или же строковое представлениедата будет в местном часовом поясе устройства. Таким образом, ваш форматтер по-прежнему работает как для преобразования строк в даты, так и обратно в строки.

Аналогично, я бы предложил заменить Z либо ZZZZZ, либо просто X. Опять же, это важно, только если форматер даты также используется для преобразования дат обратно в строки (в противном случае результирующая строка будет иметь +0000, а не Z). В итоге, я обнаружил, что использование X / ZZZZZ означает, что мне просто не нужно об этом беспокоиться, это работает, когда средство форматирования преобразует 2019-09-30T09:10:32.537244Z в Date объект или наоборот.

Таким образом:

let iso8601DateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSX"
    formatter.timeZone = TimeZone(secondsFromGMT: 0)
    formatter.locale = Locale(identifier: "en_US_POSIX")
    return formatter
}()

func serverToLocal(string: String) -> Date? {
    return iso8601DateFormatter.date(from: string)
}

func localToServer(date: Date) -> String {
    return iso8601DateFormatter.string(from: date)
}

Кстати, вы говорите о «серверных» строках даты. Вы обмениваетесь данными через JSON? Если вы анализируете строки в JSON с JSONEncoder и JSONDecoder, вы можете использовать свой форматер в кодировщике dateEncodingStrategy или декодере dateDecodingStrategy. Таким образом, ваши базовые объекты модели могут быть просто Date свойствами, а кодер / декодер JSON позаботится о преобразовании строк даты в JSON в Date объекты (и обратно). И тогда вам не нужны эти методы serverToLocal и localToServer.


FWIW, для получения дополнительной информации о цитировании T, настройке языкового стандарта и т. Д., Пожалуйста, смотрите Apple Технические вопросы и ответы 1480 . Это старый документ, ориентированный на Objective-C, но в нем говорится о концепциях, изложенных здесь.

...