NSDate для того же местного времени, что и другой NSDate в разных часовых поясах.

У меня есть время для свиданий:

Friday, July 8, 2016 at 6:30:00 PM India Standard Time

Я хочу дату, как это:

Friday, July 8, 2016 at 6:30:00 PM Central Daylight Time

Я не хочу преобразовывать даты с помощью NSDateFormatter из одного часового пояса в другой, потому что это преобразование даст мне

Friday, July 8, 2016 at 8:00:00 AM Central Daylight Time

Я хочу ту же дату, но в другом часовом поясе. Как я могу это сделать?


person S.J    schedule 09.07.2016    source источник
comment
Я хочу ту же дату, но в другом часовом поясе. Нет, не нужно. Это две разные даты и времени.   -  person matt    schedule 09.07.2016
comment
@matt Да, безусловно, это разные даты, но как я могу создать новую или другую дату, выглядящую так же, как date1, но с другим часовым поясом?   -  person S.J    schedule 09.07.2016


Ответы (2)


Ответ dasblinkenlight абсолютно правильный, но я объясню немного подробнее и покажу шаги в ObjC вместо Swift. Вам не нужна та же дата в другом часовом поясе; вам нужно то же самое местное время (или время на стене): то, что человек увидит, когда посмотрит на часы.

Та же дата в другом поясе имеет другое местное время: пятница, 8 июля 2016 г., 18:30:00 Стандартное время Индии наступает пятница, 8 июля 2016 г., 8:00:00. Центральное летнее время. В тот момент, когда человек в Калькутте смотрит на часы и видит 18:30, человек в Омахе, смотрящий на свои часы, видит 8:00.

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

NSString * originalDateString = @"Friday, July 8, 2016 at 6:30:00 PM India Standard Time";

NSDateFormatter * parser = [NSDateFormatter new];
[parser setDateStyle:NSDateFormatterFullStyle];
[parser setTimeStyle:NSDateFormatterFullStyle];
NSDate * originalDate = [parser dateFromString:originalDateString];

Хотя исходная строка содержала информацию о часовом поясе, дата ее не содержит. Однако время на стене зависит от зоны, поэтому для следующего шага нам понадобится объект часовой зоны. Вы также получите это из своего объекта уведомления. Здесь мы просто создадим его из его идентификатора: NSTimeZone * originalTZ = [NSTimeZone timeZoneWithAbbreviation:@"IST"];

Нам нужно NSDateComponents для представления значений местного времени для даты в зоне. NSCalendar отвечает за разбиение даты на следующие компоненты:

NSCalendar * cal = [NSCalendar currentCalendar];
NSDateComponents * localComps;
localComps = [cal componentsInTimeZone:originalTZ
                              fromDate:originalDate];

Если вы проверите localComps сейчас, вы увидите, что значения инкапсулируют ожидаемое время стены: 2016-07-08 18:30:00. Теперь, когда мы разбили эти значения, мы можем поместить их в другую зону без перевода. То есть без переинтерпретации значений как абсолютного времени, что дало бы 2016-07-08 08:00:00, как обсуждалось выше. Просто измените часовой пояс (опять же, вы получите пояс из вашего уведомления, а не из его аббревиатуры):

NSTimeZone * destinationTZ = [NSTimeZone timeZoneWithAbbreviation:@"CDT"];
[localComps setTimeZone:destinationTZ];

Теперь календарь может создать новый объект даты из этих компонентов. NSDate * destinationDate = [cal dateFromComponents:localComps];*

Эта дата является моментом времени, не зависящим от часового пояса, который соответствует пятнице, 8 июля 2016 г., 18:30:00 по центральному летнему времени. Как и в случае с любым NSDate, если вы просто распечатаете его, он будет отформатирован по Гринвичу. Если вы хотите увидеть ожидаемые значения времени на стене, вам нужно использовать средство форматирования, установленное для часового пояса назначения.


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

person jscs    schedule 09.07.2016

Вы можете сделать это, разделив свою дату на компоненты в исходном часовом поясе, установив целевой часовой пояс на своих компонентах и ​​получив результирующую дату (она не будет той же датой/временем)

import Foundation

let calendar = NSCalendar.currentCalendar()
let date = NSDate()
let origTz = NSTimeZone(abbreviation: "IST")!
let destTz = NSTimeZone(abbreviation: "CDT")!
let components = calendar.componentsInTimeZone(origTz, fromDate: date)
components.timeZone = destTz
let res = components.date!
let fmt = NSDateFormatter()
fmt.timeZone = destTz
fmt.locale = NSLocale(localeIdentifier: "en_US_POSIX")
fmt.dateStyle = .FullStyle
fmt.timeStyle = .FullStyle
fmt.timeZone = origTz
print(fmt.stringFromDate(date)) // Sunday, July 10, 2016 at 2:14:21 AM India Standard Time
fmt.timeZone = destTz
print(fmt.stringFromDate(res))  // Sunday, July 10, 2016 at 2:14:21 AM Central Daylight Time
person Sergey Kalinichenko    schedule 09.07.2016
comment
Да демонстративно они оба разные даты. - person S.J; 09.07.2016
comment
myLocalNotification.firedate возвращает простую дату, она не содержит информации о часовом поясе, как я могу использовать ваш код. - person S.J; 09.07.2016
comment
это не работает, я получаю этот результат 2016, 09 июля, суббота, 03:20 - person S.J; 09.07.2016
comment
вот код NSTimeZone *origTz = [NSTimeZone timeZoneWithAbbreviation:@IST]; NSDateComponents *components = [cal componentInTimeZone: origTz fromDate: self.fireDate]; [компоненты setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@CDT]]; NSDate *dateNew = [дата компонентов]; NSString *sDate1 = [строка dateFormatterFromDate:dateNew]; - person S.J; 09.07.2016
comment
@ S.J Пожалуйста, ознакомьтесь с правкой, чтобы узнать, как правильно отформатировать время с соответствующим часовым поясом. Я не понимал, что вам нужно решение на Objective-C, но я вижу, что у вас нет проблем с преобразованием из Swift, поэтому я оставил язык демонстрации на месте. - person Sergey Kalinichenko; 09.07.2016