NSDate for the same local time as another NSDate in different time zones

我的梦境 提交于 2019-12-11 13:53:48

问题


I have a date time:

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

I want a date time like this:

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

I do not want to convert the dates using NSDateFormatter from one timezone to another, because this conversion will give me

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

I want the same date time, but in a different timezone. How can I do that?


回答1:


dasblinkenlight's answer is absolutely correct, but I'll explain a little more fully, and show the steps in ObjC instead of Swift. You don't want the same date in a different time zone; you want the same local time (or wall time): what a person would see when they look at the clock.

The same date in a different zone has a different local time: Friday, July 8, 2016 at 6:30:00 PM India Standard Time is Friday, July 8, 2016 at 8:00:00 AM Central Daylight Time. At the moment that a person in Kolkata looks at the clock and sees 6:30 PM, a person in Omaha looking at her clock would see 8:00 AM.

First, solely for the purpose of the demonstration, we'll create the original date from the string you've given, using a date parser. You would just get the date from your notification object.

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];

Although the original string contained time zone information, the date does not. The wall time, however, is dependent on the zone, so we will need a time zone object for the next step. You would get this too from your notification object. Here, we'll just create one from its identifier: NSTimeZone * originalTZ = [NSTimeZone timeZoneWithAbbreviation:@"IST"];

We need an NSDateComponents to represent the local time values for the date in the zone. NSCalendar is responsible for breaking the date into those components:

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

If you inspect localComps now, you'll see the values encapsulate the wall time you expect: 2016-07-08 18:30:00. Now that we have these values broken out, we can essentially put them into another zone without translation. That is, without reinterpreting the values as an absolute time, which would give 2016-07-08 08:00:00, as discussed above. Simply change the time zone (again, you would get the zone from your notification rather than from its abbreviation):

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

Now the calendar can construct a new date object from those components. NSDate * destinationDate = [cal dateFromComponents:localComps];*

This date is the time-zone-independent moment in time that represents Friday, July 8, 2016 at 6:30:00 PM Central Daylight Time. As with any NSDate, if you simply print it out, it will be formatted in GMT. If you want to see the wall time values you expect, you need to use a formatter set to the destination time zone.


*As dasblinkenlight's answer shows, localComps has an associated calendar, so it's capable of creating a date itself, too. I thought this would be a bit clearer.




回答2:


You can do this by splitting your date into components in the original time zone, setting the target time zone on your components, and retrieving the resultant date (it is not going to be the same date/time)

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


来源:https://stackoverflow.com/questions/38282732/nsdate-for-the-same-local-time-as-another-nsdate-in-different-time-zones

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!