views:

2401

answers:

2

In the iPhone docset for NSDate, in the discussion area they discuss -dateWithNaturalLanguageString:locale:, however they don't document the method elsewhere on the page.

I've used the method before for iPhone and it worked just fine, although I got warnings. Now that I'm building with -Werror (which I should have been doing all along ^_^) I've run into a warning with this.

How would I replace the following lines of code?

NSDate *today = [NSDate dateWithNaturalLanguageString:@"today at 23:59:59"];
NSDate *tomorrow = [NSDate dateWithNaturalLanguageString:@"tomorrow at 23:59:59"];
+1  A: 

Let's assume:

static const unsigned long seconds_per_day = 60 * 60 * 24;

You can get now and now+24 hours with:

NSDate* today = [NSDate date]; // set for today
NSDate* tomorrow = [today addTimeInterval:seconds_per_day];

In order to get midnight for the given day, it's important to remember that NSDate* is toll-free bridged to CFDateRef, which provides some additional APIs you'll want to use. In particular, you can convert an NSDate to a CFAbsoluteTime with CFDateGetAbsoluteTime:

CFAbsoluteTime abstime = CFDateGetAbsoluteTime(reinterpret_cast<CFDateRef>(myNSDate));
long long      inttime = static_cast<long long>(abstime);

inttime = (inttime / seconds_per_day) * seconds_per_day; // clips the time to midnight

NSDate* myNSDateAtMidnight = reinterpret_cast<NSDate*>(CFDateCreate(NULL,
                                                       static_cast<CFAbsoluteTime>(inttime)));

... which you can wrap into a function to round both today and tomorrow to midnight.

fbrereto
Where is CFAbsoluteTime declared? I've imported `<CoreFoundation/CoreFoundation.h> but still no dice. Also, what is myUint64Type? What should I be using for that?If it matters, I'm writing an NSDate category, although I don't think it matters.
jbrennan
Ah, there's a typo in your code, `CFAbosoluteTime` ;) Anyway I've got the code running now, but it's still not quite right. The time for today and tomorrow is still off...
jbrennan
What do the dates print when you say `NSLog(@"%@", myNSDate)`?
fbrereto
Also I changed `myUint64Type` to be `long long`
fbrereto
I've pasted my code here http://paste.lisp.org/display/86144 Thanks for your help so far :) We're getting there.
jbrennan
I think it's actually correct -- you have to take into account the UTC offset, which is -3 hours; so you add 3 hours to 21:00:00 and you get 24:00:00, which is midnight, today.
fbrereto
Hmmm, well 21:00 is off by 3 hours, but 16:41 is not. I'm trying to get "the end of today", instead of "the start of today". What a peculiar problem...
jbrennan
Hmm... I guess then what you'll want to do is add the amount of UTC time to compute midnight for your particular time zone, then add to that value seconds_per_day - 1. That should give you the last second for today in your specific time zone.
fbrereto
+1  A: 

One way to do this is with NSCalendar and NSDateComponents.

To get today at 23:59:59:

NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];

NSDateComponents *comps = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit 
           fromDate:date];

[comps setHour:23];
[comps setMinute:59];
[comps setSecond:59];

NSDate *today = [calendar dateFromComponents:comps];

To get tomorrow at 23:59:59:

NSDate *now = [NSDate dateWithTimeIntervalSinceNow:24 * 60 * 60]; // 24h from now
NSCalendar *calendar = [NSCalendar currentCalendar];

NSDateComponents *comps = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit 
           fromDate:date];

[comps setHour:23];
[comps setMinute:59];
[comps setSecond:59];

NSDate *tomorrow = [calendar dateFromComponents:comps];
iKenndac
Bingo. Thanks to everyone for their help.
jbrennan
I will certainly not be forgetting NSDateComponents any time soon!
jbrennan