8

I want to set the NSDate time with my desired hours:minutes:seconds currently im working with NSDate component but it is not giving the desired result

[comps setHour: -hours];
[comps setMinute:0];
[comps setSecond:0];
NSDate *minDate = [calendar_c dateFromComponents:comps];
memmons
  • 40,222
  • 21
  • 149
  • 183

6 Answers6

22

This works great as an NSDate category.

/** Returns a new NSDate object with the time set to the indicated hour, 
  * minute, and second.
  * @param hour The hour to use in the new date.
  * @param minute The number of minutes to use in the new date.
  * @param second The number of seconds to use in the new date.
  */
-(NSDate *) dateWithHour:(NSInteger)hour 
                  minute:(NSInteger)minute 
                  second:(NSInteger)second 
{
   NSCalendar *calendar = [NSCalendar currentCalendar];
   NSDateComponents *components = [calendar components: NSYearCalendarUnit|
                                                         NSMonthCalendarUnit|
                                                         NSDayCalendarUnit
                                               fromDate:self];
    [components setHour:hour];
    [components setMinute:minute];
    [components setSecond:second];
    NSDate *newDate = [calendar dateFromComponents:components];
    return newDate;
}

With the above category, if you have an existing date you want to change the time on, you do so like this:

NSDate *newDate = [someDate dateWithHour:10 minute:30 second:00];

If, however, you are trying to add or subtract hours from an existing date, a category method to do that is also straightforward:

/** Returns a new date with the given number of hours added or subtracted.
  * @param hours The number of hours to add or subtract from the date.
  */
-(NSDate*)dateByAddingHours:(NSInteger)hours
{
    NSDateComponents *components = [[NSDateComponents alloc] init];
    [components setHour:hours];

    return [[NSCalendar currentCalendar] 
               dateByAddingComponents:components toDate:self options:0];
}
memmons
  • 40,222
  • 21
  • 149
  • 183
  • 1
    in your category `dateWithHour:minute:second` where the `calendar` comes from? – Lukasz 'Severiaan' Grela Jun 19 '14 at 09:06
  • @Lukasz'Severiaan'Grela It was a `[NSCalendar currentCalendar]` variable that was left out of the code. Added. – memmons Jun 19 '14 at 14:27
  • 1
    Is this right both for 24h format and AM/PM format? For instance, if I call the function this way: NSDate *newDate = [someDate dateWithHour:6 minute:30 second:00]; that "6" is 6AM or 6PM? Clearly, if I'm in the 24h format that 6 is 6AM. – superpuccio Jan 04 '16 at 14:16
18

Your approach should work fine. I needed a solution for this type problem (setting the individual date components) and the following code works as expected for me. My situation: I wanted to create a date object that used the current date but had the time set to a value that was passed in as a string.

NSString *string = @"7:00";
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
NSDateFormatter *timeOnlyFormatter = [[NSDateFormatter alloc] init];
[timeOnlyFormatter setLocale:locale];
[timeOnlyFormatter setDateFormat:@"h:mm"];

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *today = [NSDate date];
NSDateComponents *todayComps = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:today];

NSDateComponents *comps = [calendar components:(NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:[timeOnlyFormatter dateFromString:string]];
comps.day = todayComps.day;
comps.month = todayComps.month;
comps.year = todayComps.year;
NSDate *date = [calendar dateFromComponents:comps];
[calendar release];
[timeOnlyFormatter release];
[locale release];

One thing to note is that you really have to pay attention to time zones when you are judging whether a time appears to be accurate. For example, in my app, when you stop at a breakpoint, you will see the time in GMT (so it looks different than the input time, which is in my local time), but when the time is actually displayed on screen in the app, it is being formatted to display in the local timezone. You may need to take this into consideration to determine whether the result is actually different from what you would expect.

If this does not help, can you elaborate on "not giving the desired result"? What result is it giving and how does that compare to what you expected?

J.R. Armstrong
  • 1,264
  • 12
  • 12
  • I'm just getting this error: 2015-01-16 12:14:05.864 TesInsta[26792:4444831] *** -[__NSCFCalendar components:fromDate:]: date cannot be nil Future exception. A few of these errors are going to be reported with this complaint, then further violations will simply be ignored. Here is the backtrace where this occurred this time (some frames may be missing due to compiler optimizations): ( – Jack Solomon Jan 16 '15 at 01:15
  • Downvote seems a little harsh given that this answer worked great three and a half years ago when it was published. Did you get this exception from the answer above or from your code? Based on what you reported, look here: http://stackoverflow.com/questions/16094063/sending-nscfcalendar-nil-nsdate-sarcastic-error – J.R. Armstrong Jan 16 '15 at 18:59
2

is Swift2

extension NSDate {
    func dateWithHour (hour: Int, minute:Int, second:Int) ->NSDate?{

        let calendar = NSCalendar.currentCalendar(),
            components = calendar.components([.Day,.Month,.Year], fromDate: self)
        components.hour = hour;
        components.minute = minute;
        components.second = second;

        return calendar.dateFromComponents(components)
    }
}
dattk
  • 146
  • 1
  • 5
1

You can set 0 to hour, min, and second.

NSDateFormatter *tFmt = [[NSDateFormatter alloc] init];

tFmt.dateFormat = @"yyyy-MM-dd";

NSString *strNowDate = [NSString stringWithFormat:@"%@ 00:00:00",[tFmt stringFromDate:[NSDate date]]];

NSDate *nowDate = [NSDate dateWithString:strNowDate formatString:@"yyyy-MM-dd HH:mm:ss"];
Harikesh
  • 311
  • 4
  • 6
1

Swift 5 solution (based on @dattk answer) for those who fear Deprecation warnings :)

func date(withHour hour: Int, withMinute minute: Int, withSeconds second: Int) -> Date? { 
   let now = Date() 
   let calendar = NSCalendar.current 
   var components = calendar.dateComponents([.day,.month,.year], from: now)   
   components.hour = hour 
   components.minute = minute 
   components.second = second 
   return calendar.date(from: components) 
}
Nathaniel
  • 836
  • 9
  • 19
0
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *comps = [calendar components:(NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:[NSDate date]];
comps.hour = 0;
comps.minute = 15;
NSDate *date = [calendar dateFromComponents:comps];

iOS 8