NSDate - конвертировать дату в GMT - PullRequest
50 голосов
/ 08 декабря 2009

Мне нужна возможность конвертировать значение NSDate в дату по Гринвичу.

Как можно преобразовать значение NSDate в значение NSDate, отформатированное в GMT, независимо от того, какие настройки локали даты используются на устройстве iPhone?

Ответы [ 6 ]

132 голосов
/ 13 января 2010
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    dateFormatter.dateFormat = @"yyyy-MM-dd'T'HH:mm";

    NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
    [dateFormatter setTimeZone:gmt];
    NSString *timeStamp = [dateFormatter stringFromDate:[NSDate date]];
    [dateFormatter release];
42 голосов
/ 08 декабря 2009

Работа со временем в Какао может быть сложной. Когда вы получаете объект 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 должна иметь правильную дату в GMT для вас. Чтобы отобразить его, посмотрите на NSDateFormatter, в частности методы setDateStyle и setTimeStyle. Вы создаете NSDateFormatter, настраиваете его так, как хотите, а затем вызываете stringFromDate:, чтобы получить красиво отформатированную строку.

16 голосов
/ 10 августа 2010

Ответ Говарда правильный, и, пожалуйста, проголосуйте и примите его.

Для справки, мне кажется, полезно объяснить разницу между объектами даты и локализованными представлениями даты.

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

Если бы для каждого момента времени мы могли создать уникальный ярлык, этот ярлык можно было бы передавать и ссылаться на него однозначно. Цель объектов даты - выступать в качестве уникальной универсальной метки для данного момента времени .

Можно придумать любое количество методов для построения такой схемы маркировки, и то, как каждый объект даты выбирает это, несущественно для любого, кто их использует.

Примером может быть использование числового смещения от универсального события ( X секунд с момента взрыва солнца ).

Только когда мы хотим взять момент времени и сериализовать его в удобочитаемую строку, мы должны иметь дело со сложностями часовых поясов, локалей и т. Д. *

( Локальная строка даты ) + ( Форматер даты ) => Точка времени

Точка времени + ( Форматер даты ) => ( Локальная строка даты )

Каждый момент времени универсален ... не существует такого понятия, как нью-йоркский момент времени или момент времени gmt , только после преобразования временной точки в местный строка (с использованием средства форматирования даты) отображает любую связь с часовым поясом.

Примечание: я уверен, что есть много блогов / статей по этой самой проблеме, но мой Google Foo подводит меня в этот час. Если у кого-то есть энтузиазм по поводу этой проблемы, пожалуйста, не стесняйтесь.

5 голосов
/ 10 августа 2010

Хотя ответ Алекса был хорошим началом, он не имел отношения к летнему времени (летнее время) и добавил ненужное преобразование в / из контрольной даты. У меня работает следующее:

Чтобы преобразовать localDate в GMT, принимая во внимание DST:

NSDate *localDate = <<your local date>>
NSTimeInterval timeZoneOffset = [[NSTimeZone systemTimeZone] secondsFromGMTForDate:localDate];
NSDate *gmtDate = [localDate dateByAddingTimeInterval:-timeZoneOffset]; // NOTE the "-" sign!

Чтобы преобразовать дату из GMT в localDate, принимая во внимание DST:

NSDate *gmtDate  = <<your gmt date>>
NSTimeInterval timeZoneOffset = [[NSTimeZone systemTimeZone] secondsFromGMTForDate:gmtDate];
NSDate *localDate = [gmtDate dateByAddingTimeInterval:timeZoneOffset];

Одна небольшая заметка: я использовал dateByAddingTimeInterval, который является только iOS 4. Если вы используете OS 3 или более раннюю версию, используйте addTimerInterval.

4 голосов
/ 09 января 2018

Swift 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)
    }

}
3 голосов
/ 08 декабря 2009

Вы пытались просмотреть документацию по NSDateFormatter?

NSDateFormatter

В NSDateFormatter, похоже, есть несколько методов для игры с часовыми поясами, в частности

-setTimeZone:

Я не проверял это сам, но я представляю, что если вы установите GMT ​​в качестве часового пояса для даты, которая изначально представлена ​​в другом часовом поясе, она будет отображать дату с правильными настройками в соответствии с новым часовым поясом.

...