Как получить NSDate из строки без преобразования в UTC

У меня следующая проблема. Предположим, что я получаю от сервера строку, содержащую дату и время в следующем формате:

yyyy-MM-dd'T'HH:mm:ssxxxx

Это время даты сервера, и я хотел бы отобразить его в приложении как есть. Итак, если я получаю дату и время:

2017-04-07T10:29:23+ 02:00

значит на сервере есть 10:29:23 (08:29:23 UTC)

и я хотел бы отобразить его в приложении как:

04.07.2017 10:29:23

но всякий раз, когда я пытаюсь преобразовать строку в NSDate, я получаю дату, преобразованную в UTC, что нежелательно, потому что я теряю информацию о часовом поясе сервера. Я использую следующий код прямо сейчас:

let formatter = NSDateFormatter()
formatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssxxxx"

let date = formatter.dateFromString(dateString)

Как я могу добиться этого в Swift (2.3)?

Заранее спасибо.


person smq93    schedule 07.04.2017    source источник
comment
Ваш код правильный. Если вы print дату, вы получите UTC. Попробуйте на детской площадке. Два примечания: xxxx можно заменить на Z, а в строке даты не должно быть пробела между знаком плюс/минус и значением часового пояса.   -  person vadian    schedule 07.04.2017
comment
Спасибо за ответ. Да, я знаю, что это даст мне UTC, но, как я писал выше, я этого не хочу. Я хочу отображать дату и время сервера, как я это получил. Так, например. если на сервере 10:00 (8:00 UTC), я хотел бы отображать в приложении также 10:00 (независимо от часового пояса приложения).   -  person smq93    schedule 07.04.2017
comment
Если вы хотите игнорировать часовой пояс, вы должны удалить информацию о часовом поясе из строки даты (например, с параметрами replaceOccurrencesOfString и RegularExpression).   -  person vadian    schedule 07.04.2017
comment
Честно говоря, я принимал это во внимание, но подумал, что для этого может быть какое-то красивое решение. Любые другие идеи?   -  person smq93    schedule 07.04.2017


Ответы (2)


NSDate не имеет встроенного часового пояса. Если вы print и NSDate, то он будет печатать по Гринвичу, потому что он должен печатать что-то. Но сама дата не содержит часового пояса и не может. Они не зависят от часового пояса.

Чтобы напечатать дату в определенном часовом поясе, настройте NSDateFormatter с нужным форматом и часовым поясом, а затем используйте .stringFromDate. Или не устанавливайте часовой пояс, и он будет напечатан в часовом поясе и локали вашего устройства, что, вероятно, ожидает ваш пользователь (например, ваш сервер говорит «событие произошло в 00:23 + 02:00», поэтому для вашего пользователя CET вы отобразит «событие произошло в 23:23», а вашему пользователю EST вы отобразите «событие произошло в 18:23»).

К сожалению, у вас осталась только одна проблема: средство форматирования даты понимает часовой пояс в вашей исходной строке (+02:00), но никак не может сообщить его вам. Поэтому, если вы хотите взять NSDate и распечатать его в том же часовом поясе, что и ваш сервер, вам придется самостоятельно определить часовой пояс, передать его по другому каналу или жестко закодировать.

person Tommy    schedule 07.04.2017

Итак, наконец-то мне удалось решить проблему с помощью ваших подсказок.

Следующий код соответствует моим ожиданиям:

let formatter = NSDateFormatter()
formatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssxxxx"

let timeZonePattern = "([+-]([01][0-9]):[0-5][0-9])$" // e.g. "+02:00"
let regex = try! NSRegularExpression(pattern: pattern, options: [])
let dateStringWithoutTimeZone = regex.stringByReplacingMatchesInString(dateString, options: [], range: NSMakeRange(0, dateString.characters.count), withTemplate: "Z")

let date = formatter.dateFromString(dateStringWithoutTimeZone)

Спасибо вам всем!

person smq93    schedule 10.04.2017