问题
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