NSDate - Offsetting the Time Zone
I must be missing something small her but can't figure it out. Trying to create a开发者_Go百科 date for comparison, but I can't seem to offset currentDate from GMT to EST:
// current date (gmt) //
NSDate *currentDate = [NSDate date];
NSTimeZone *currentDateTimeZone = [NSTimeZone timeZoneWithAbbreviation:@"EST"];
NSDateFormatter *currentDateFormat = [[NSDateFormatter alloc]init];
[currentDateFormat setTimeZone:currentDateTimeZone];
[currentDateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss zzz"];
NSString *currentDateString = [currentDateFormat stringFromDate:currentDate];
NSLog(@"currentDateString: %@", currentDateString); // returns 2011-01-05 13:30:30 EST
NSDate *currentDateWithOffset = [currentDateFormat dateFromString:currentDateString];
NSLog(@"currentDateWithOffset: %@", currentDateWithOffset); // returns 2011-01-05 18:30:30 +0000
Thanks!
Edit:
I'm calling a method in a separate class (trying to make this portable) using the following line:
[Expiration expires:[[NSDate alloc] initWithString:@"2011-01-07 12:00:00 +0000"] within:1.0]
in the expires method, I have these lines:
NSComparisonResult comparison = [currentDateWithOffset compare:expires]; // check for a fixed date to disable the demo
double withinRange = [installDate timeIntervalSinceDate:currentDateWithOffset]; // check for number of seconds between "within" and the install date
I'm then comparing these two values like so:
if(withinRange >= within && withinRange > 0.0) {
// app is expired //
}
else {
// app is still enabled (so far...) //
if(comparison == NSOrderedDescending || comparison == NSOrderedSame) {
// app is expired //
}
else {
// app is still enabled //
}
}
Does this help? Thanks for your patience!
Edit:
Here's the entire expires:within method as it currently stands...
+(BOOL)expire:(NSDate*)expires within:(double)within {
// default expired value //
BOOL expired = NO;
// convert within value from days to seconds //
within *= 24.0 * 60.0 * 60.0;
// current date (gmt) //
NSDate *currentDate = [NSDate date];
// install date //
NSDate *installDate = [[NSUserDefaults standardUserDefaults]objectForKey:@"installDate"];
// check for a value in installDate //
if (nil == installDate) {
// app is running for the first time //
[[NSUserDefaults standardUserDefaults]setObject:currentDate forKey:@"installDate"];
[[NSUserDefaults standardUserDefaults]synchronize];
installDate = currentDate;
}
if([installDate timeIntervalSinceNow] < (-within)) {
expired = YES;
}
else {
if([expires timeIntervalSinceNow] < 0) {
expired = YES;
}
}
NSLog(@"installDate:%@", installDate);
NSLog(@"expires:%@", expires);
NSLog(@"currentDate:%@", currentDate);
return expired;
}
I'm then calling it from another class with
message.text = (YES == [Expiration expire:[[NSDate alloc] initWithString:@"2011-01-07 12:00:00 -0500"] within:(0.015625/2)]) ? @"This App is Expired" : @"This App is Active";
When running in the simulator (fresh app install), NSLog displayed this...
[Session started at 2011-01-06 10:43:46 -0500.]
2011-01-06 10:43:48.146 TimeBasedDemo[14717:207] installDate:2011-01-06 15:43:48 +0000
2011-01-06 10:43:48.147 TimeBasedDemo[14717:207] expires:2011-01-07 17:00:00 +0000
2011-01-06 10:43:48.147 TimeBasedDemo[14717:207] currentDate:2011-01-06 15:43:48 +0000
None of these answers gave me an NSDate
object with the current, local date. So here's how I did it:
NSDate *currentDateWithOffset = [NSDate dateWithTimeIntervalSinceNow:[[NSTimeZone localTimeZone] secondsFromGMT]];
An NSDate
object represents an instant in time irrespective of time zone and calendar considerations. Time zone info is relevant when you print or parse a date, but it is not stored within the NSDate
.
Say you are creating your expiration date like this:
NSDate *exp=[[NSDate alloc] initWithString:@"2011-01-07 12:00:00 +0000"]
That says you want the expiration to occur at noon GMT, on the 7th Jan. If you want it to expire at noon EST, create it with -0500 instead. What you should not have to do is mess with the current time when you do a comparison.
An easy way just to see if the time has passed is then
if ([exp timeIntervalSinceNow]<0) { /* it's expired */ }
and you can see if within
seconds have passed since the install date like this:
if ([installDate timeIntervalSinceNow]<(-within)]) { /* it's expired */}
In Cocoa, NSDate
is an abstract representation of a date with no time zone information applied. Note that currentDateWithOffset
is the same date as the date string, just in a different time zone (five hours ahead). This is expected behavior, as NSDate
does not persist the time zone used to create it.
I tinkered around a bit more and found a way to 'cheat' the offset to suit my needs. From other reading, I'm guessing that NSCalendar might be a better long term-solution, but for now I ended up changing
NSDate *currentDateWithOffset = [currentDateFormat dateFromString:currentDateString];
to
NSDate *currentDateWithOffset = [[NSDate alloc] initWithString:[NSString stringWithFormat:@"%@ +0000", currentDateString]];
That got me the results I needed and works in the later comparisons I'm using. Thanks for the background info all!
精彩评论