Domanda

I am setting up an NSPredicate for a fetch to Core Data which is set up like so:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(date >= %@) AND (date <= %@)", todaysDate, tomorrowsDate];

I need todaysDate to be today at 00:00:00, and I need tomorrowsDate to be today at 23:59:59.

I can't set todaysDate equal to [NSDate date] and then manipulate the hours, minutes, and seconds with NSDateComponents because [NSDate date] gives me a date which is 5 hours ahead of my local actual time (so if it's 11:00 pm here on May 6th, then [NSDate date] would give me "2014-05-07 04:00:00 +0000", but I still need it to think that it is May 6th, not 7th!).

How can I manipulate the tools I have in Xcode to consistently get my variable todaysDate to be today at midnight, and tomorrowsDate to be a second before midnight strikes tomorrow?

È stato utile?

Soluzione

The rangeOfUnit:... method of NSCalendar is a convenient method to compute the start of the current day and the start of tomorrow in your local time zone:

NSDate *now = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *todaysDate;
NSDate *tomorrowsDate;
NSTimeInterval interval;
[cal rangeOfUnit:NSDayCalendarUnit startDate:&todaysDate interval:&interval forDate:now];
tomorrowsDate = [todaysDate dateByAddingTimeInterval:interval];

so that you can use it in the predicate with >= and <:

[NSPredicate predicateWithFormat:@"(date >= %@) AND (date < %@)", todaysDate, tomorrowsDate]

to fetch all objects of the current day.


Remark: Don't let the NSLog() output of NSDate objects confuse you. NSDate represents an absolute point in time and knows nothing about time zones. NSLog(@"%@", todaysDate) prints the date according to the GMT time zone and not in your local time zone.

To print the dates according to your time zone, use p todaysDate in the debugger console (instead of po), or print

[todaysDate descriptionWithLocale:[NSLocale currentLocale]]

Altri suggerimenti

The following works for me:

- (NSDate *)dateWithDate:(NSDate *)date Hour:(NSInteger)hour Minute:(NSInteger)minute Second:(NSInteger)second {
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [calendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:date];
    components.hour = hour;
    components.minute = minute;
    components.second = second;
    return [calendar dateFromComponents:components];
}

Example:

NSDate *beginningOfDay = [self dateWithDate:[NSDate date] Hour:0 Minute:0 Second:0];
NSDate *endOfDay = [self dateWithDate:[NSDate date] Hour:23 Minute:59 Second:59];

Swift:

let cal = NSCalendar.currentCalendar()

//tip:NSCalendarUnit can be omitted, but with the presence of it, you can take advantage of Xcode's auto-completion
var comps = cal.components(NSCalendarUnit.YearCalendarUnit | .MonthCalendarUnit | .DayCalendarUnit | .HourCalendarUnit | .MinuteCalendarUnit | .SecondCalendarUnit, fromDate: NSDate()) 
comps.hour = 0
comps.minute = 0
comps.second = 0

let todaysDate = cal.dateFromComponents(comps)!
let tomorrowsDate = NSDate(timeInterval: 86399, sinceDate: todaysDate)

Objective-C:

NSCalendar *cal = [NSCalendar currentCalendar]; 

NSDateComponents *comps = [cal components: (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate: [NSDate date]];    
[comps setHour:0]; 
[comps setMinute:0]; 
[comps setSecond:0];

NSDate *todaysDate = [cal dateFromComponents:comps];
NSDate *tomorrowsDate = [NSDate dateWithTimeInterval: 86399 sinceDate:todaysDate];
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top