5

I have an NSDate which I want zero-out hour, minutes and seconds. The result I want is: 2014-02-19 00:00:00 +0000. I have tried the following:

NSUInteger flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents* components = [[NSCalendar currentCalendar] components:flags fromDate:self.birthDatePicker.date];
NSDate* birthDate = [[NSCalendar currentCalendar] dateFromComponents:components];

For some reason I get this: 2014-02-19 23:00:00 +0000. Hour isn't zeroed out. I have also tried to set [components setHour:0]. But I get the same result 23 for hours. Any ideas on what I'm doing wrong?

Anders
  • 2,903
  • 7
  • 58
  • 114
  • 9
    consider timezones... your local timezone is GMT+1 and when you log the date using NSLog it gives its time in GMT – Volker Feb 20 '14 at 09:00
  • Need of the time zone depends on the use case. If you hard code your time zone to the date you'll easily break it for the users on different time zones. What you need is a simple date formatter with a style or format. – Desdenova Feb 20 '14 at 09:52

3 Answers3

3

Take a look at this library: https://github.com/mysterioustrousers/MTDates

I had the similar problem I've decided to use it. It has a lot of date related functions. The one you need is:

- (NSDate *)mt_startOfCurrentDay;

About time zones. NSDate has independent from time zone format. Time zone you need you can specify in NSDateFormatter instance.

Update Full code example

NSDate *date = [NSDate date];
NSLog(@"%@", date); // 2014-02-20 11:11:40 +0000
[NSDate mt_setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
NSLog(@"%@", [[date mt_startOfCurrentDay] mt_stringFromDateWithISODateTime]); // 2014-02-20 00:00:00 +0000

For other date format, setup NSDateFormatter with time zone and your custom date format

One more solution This one without library:

NSDate *date = [NSDate date];
NSLog(@"%@", date); // 2014-02-20 11:36:20 +0000
NSUInteger flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:currentCalendar.calendarIdentifier];
calendar.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
NSDateComponents* components = [calendar components:flags fromDate:date];
date = [calendar dateFromComponents:components];
NSLog(@"%@", date); // 2014-02-20 00:00:00 +0000

P.S. Btw I have GMT+3 time zone

Ossir
  • 3,109
  • 1
  • 34
  • 52
3

Consider this category on NSDate:

@interface NSDate (Utilities)
- (NSDate *) dateAtStartOfDay;
@end

@implementation
- (NSDate *) dateAtStartOfDay
{

   NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekCalendarUnit |  NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekdayCalendarUnit | NSWeekdayOrdinalCalendarUnit) fromDate:self];
   [components setHour:0];
   [components setMinute:0];
   [components setSecond:0];
   return [[NSCalendar currentCalendar] dateFromComponents:components];
}
@end

Code taken from Erika Sadun NSDate Extension

Andrea
  • 26,120
  • 10
  • 85
  • 131
  • This is identical with the OP's way. His was a bit more clean. – Desdenova Feb 20 '14 at 09:43
  • Not identical... the OP way doesn't take into account hour, min, sec etc... and doesn't set them to zero. – Andrea Feb 20 '14 at 10:00
  • Not using those unit flags is the exact same thing as setting them to zero. Run his code and yours to see for yourself. – Desdenova Feb 20 '14 at 10:35
  • 1
    You are totally right, the have the same time. The code of the OP and mine shows 23, cause of the localeTimeZone that has an offset of 3600s. Log an NSDate give you the time in absolute reference. To have a start date time in my coutry it needs to subtract (or add) the offset. – Andrea Feb 20 '14 at 10:51
0

Always helpful:

WWDC Videos

2011 Session 117 - Performing Calendar Calculations

2013 Session 227 - Solutions to Common Date and Time Challenges


This contains the information you probably want:

Session 227 @ 13m25s, "Common Operations" / "Calculate Midnight".