12
votes

I need to get an NSDate object for 00:00(beginning of the day) from [NSDate date], let's say if currently it is 11:30am(returned by [NSDate date]), on 01/06/2012, now I need to have an NSDate for 00:00am on 01/06/2012.

I haven't tried this, but what is in my mind is:

NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:now];
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
NSDate *morningStart = [calendar dateFromComponents:components];

So I first get current date(say it is 01/06/2012), and construct a NSDateComponent for the date, then I set hour/minute/second to 0 and the year/month/day should not be changed(ie. 01/06/2012) then I create an NSDate for this component setting and can I get a date of 00:00:00 01/06/2012?

3
Check the answer from poozolax. It is much better and 100% correct!iWheelBuy

3 Answers

10
votes

What you doing is correct, but when you NSLog morningStart the date will be displayed in GMT time zone

If you wanna make sure that the date is correct, convert it to NSString

 NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
 [formatter setDateFormat:@"yyyy-MMM-dd HH:mm:ss"];
 NSString *strFromDate = [formatter stringFromDate:morningStart]; // this will return 2012-Jun-21 00:00:00
5
votes

Converting NSDate to NSString can be helpful but if you need to keep a NSDate object for further processing, here is your solution to have your real morningStart NSDate object set at 00:00:00 time, with care of the timezone as well... As you will see you were not so far from the solution :

NSDate *now = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:now];
NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone];
int timeZoneOffset = [destinationTimeZone secondsFromGMTForDate:now] / 3600;
[components setHour:timeZoneOffset];
[components setMinute:0];
[components setSecond:0];
NSDate *morningStart = [calendar dateFromComponents:components];
2
votes

It's very easy to do this in iOS8 using startOfDayForDate:

let date = NSDate() 
let calendar = NSCalendar.currentCalendar(calendarIdentifier: NSGregorianCalendar)
let dateAtStartOfDay = calendar.startOfDayForDate(date)

OR you may do it in the traditional way in Swift as follows:

let date = NSDate()
let calendar = NSCalendar.currentCalendar(calendarIdentifier: NSGregorianCalendar)
// Use a mask to extract the required components from today's date
let components = calendar.components(.CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay, fromDate: date)
let dateAtStartOfDay = calendar.dateFromComponents(components)!
print(dateAtStartOfDay) 

(Note: NSDates are stored relative to GMT. So print will display the relative local time. A clear understanding of TimeZone's is essential to using NSDates properly.)