Мне нужна возможность конвертировать значение NSDate
в дату по Гринвичу.
Как я могу преобразовать значение NSDate
в значение NSDate
в формате GMT, независимо от того, какие настройки локали даты использует устройство iPhone?
Мне нужна возможность конвертировать значение NSDate
в дату по Гринвичу.
Как я могу преобразовать значение NSDate
в значение NSDate
в формате GMT, независимо от того, какие настройки локали даты использует устройство iPhone?
Работа со временем в Cocoa может быть сложной. Когда вы получаете объект NSDate
, он находится в местном часовом поясе. [[NSTimeZone defaultTimeZone] secondsFromGMT]
дает вам смещение текущего часового пояса от GMT. Тогда вы можете сделать это:
NSDate *localDate = // get the date
NSTimeInterval timeZoneOffset = [[NSTimeZone defaultTimeZone] secondsFromGMT]; // You could also use the systemTimeZone method
NSTimeInterval gmtTimeInterval = [localDate timeIntervalSinceReferenceDate] - timeZoneOffset;
NSDate *gmtDate = [NSDate dateWithTimeIntervalSinceReferenceDate:gmtTimeInterval];
Теперь gmtDate
должна иметь для вас правильную дату по Гринвичу. Чтобы отобразить его, посмотрите на NSDateFormatter
, особенно на методы setDateStyle
и setTimeStyle
. Вы создаете NSDateFormatter
, настраиваете его так, как хотите, а затем вызываете stringFromDate:
, чтобы получить хорошо отформатированную строку.
Ответ Говарда правильный, проголосуйте за него и примите это.
Для справки, я думаю, полезно объяснить разницу между объектами даты и локализованными представлениями даты.
Во многих языках программирования объекты даты используются для представления уникальных моментов времени. Игнорируя релятивистские аргументы, можно предположить, что в любой момент мы можем определить момент времени, который одинаковы для всех, независимо от того, как мы измеряем время.
Если бы для каждого момента времени мы могли создать уникальную метку, эту метку можно было бы передавать и ссылаться на нее однозначно. Объекты даты предназначены для использования в качестве уникальной универсальной метки для заданного момента времени.
Можно придумать любое количество методов для создания такой схемы маркировки, и то, как каждый объект даты выбирает это, не имеет значения для любого, кто их использует.
Например, можно использовать числовое смещение от универсального события (X секунд с момента взрыва солнца).
Только когда мы хотим взять момент времени и сериализовать его в удобочитаемую строку, мы должны иметь дело со сложностями часовых поясов, локалей и т. д.
(Локальная строка даты) + (Формат даты) => Момент времени
Момент времени + (Формат даты) => (Локальная строка даты)
Каждая временная точка универсальна... не существует таких вещей, как временная точка Нью-Йорка или временная точка по Гринвичу, только если вы преобразуете временную точку в локальную строку. (с использованием средства форматирования даты) появляется какая-либо связь с часовым поясом.
Примечание: я уверен, что есть много блогов/статей по этому вопросу, но мой google foo не работает в этот час. Если у кого-то есть желание расширить эту тему, пожалуйста, сделайте это.
Свифт 4:
//UTC or GMT ⟺ Local
extension Date {
// Convert local time to UTC (or GMT)
func toGlobalTime() -> Date {
let timezone = TimeZone.current
let seconds = -TimeInterval(timezone.secondsFromGMT(for: self))
return Date(timeInterval: seconds, since: self)
}
// Convert UTC (or GMT) to local time
func toLocalTime() -> Date {
let timezone = TimeZone.current
let seconds = TimeInterval(timezone.secondsFromGMT(for: self))
return Date(timeInterval: seconds, since: self)
}
}
Хотя ответ Алекса был хорошим началом, он не касался летнего времени (летнего времени) и добавлял ненужное преобразование в/из исходной даты. Для меня работает следующее:
Чтобы преобразовать из localDate в GMT с учетом летнего времени:
NSDate *localDate = <<your local date>>
NSTimeInterval timeZoneOffset = [[NSTimeZone systemTimeZone] secondsFromGMTForDate:localDate];
NSDate *gmtDate = [localDate dateByAddingTimeInterval:-timeZoneOffset]; // NOTE the "-" sign!
Чтобы преобразовать дату по Гринвичу в локальную дату с учетом летнего времени:
NSDate *gmtDate = <<your gmt date>>
NSTimeInterval timeZoneOffset = [[NSTimeZone systemTimeZone] secondsFromGMTForDate:gmtDate];
NSDate *localDate = [gmtDate dateByAddingTimeInterval:timeZoneOffset];
Одно небольшое замечание: я использовал dateByAddingTimeInterval, который есть только в iOS 4. Если вы используете OS 3 или более раннюю версию, используйте addTimerInterval.
Вы пробовали смотреть документацию для NSDateFormatter?
NSDateFormatter, похоже, имеет некоторые методы для игры с часовыми поясами, в частности
-setTimeZone:
Я не проверял это сам, но я предполагаю, что если вы установите GMT в качестве часового пояса на дату, которая изначально представлена в другом часовом поясе, он будет отображать дату с правильными настройками, чтобы соответствовать новому часовому поясу.