Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem combining a date and a time into a single NSDate

I am trying to combine the time value (hours, minutes, seconds) of one NSDate with the date value (day, month, year) of a second NSDate with this method:

+ (NSDate *)combineDate:(NSDate *)date withTime:(NSDate *)time {

    NSCalendar *gregorian = [[NSCalendar alloc]
        initWithCalendarIdentifier:NSGregorianCalendar];

    NSDateComponents *dateComponents = [gregorian components:(NSDayCalendarUnit | 
        NSWeekdayCalendarUnit) fromDate:date];
    NSDateComponents *timeComponents = [gregorian components:(NSDayCalendarUnit | 
        NSWeekdayCalendarUnit) fromDate:time];

    NSDateComponents *comp = [NSDateComponents alloc];
    [comp setSecond:[timeComponents second]];
    [comp setHour:[timeComponents hour]];
    [comp setMinute:[timeComponents minute]];
    [comp setYear:[dateComponents year]];
    [comp setMonth:[dateComponents month]];
    [comp setDay:[dateComponents day]];

    NSDate *combDate = [gregorian dateFromComponents:comp]; 

    [gregorian release];
    [comp release];

    return combDate;
}

... but what it's returning is effectively gibberish (the year comes out as "1", for example). Anybody see what's wrong with this method?

like image 412
MusiGenesis Avatar asked May 12 '11 14:05

MusiGenesis


2 Answers

I was using the wrong calendar components. Here's the corrected function (now for ARC):

+ (NSDate *)combineDate:(NSDate *)date withTime:(NSDate *)time {

    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:
        NSGregorianCalendar];

    unsigned unitFlagsDate = NSYearCalendarUnit | NSMonthCalendarUnit 
        |  NSDayCalendarUnit;
    NSDateComponents *dateComponents = [gregorian components:unitFlagsDate 
        fromDate:date];
    unsigned unitFlagsTime = NSHourCalendarUnit | NSMinuteCalendarUnit 
        |  NSSecondCalendarUnit;
    NSDateComponents *timeComponents = [gregorian components:unitFlagsTime 
        fromDate:time];

    [dateComponents setSecond:[timeComponents second]];
    [dateComponents setHour:[timeComponents hour]];
    [dateComponents setMinute:[timeComponents minute]];

    NSDate *combDate = [gregorian dateFromComponents:dateComponents];   

    return combDate;
}
like image 64
MusiGenesis Avatar answered Sep 22 '22 06:09

MusiGenesis


Swift 3 extension:

func combineDateAndTime(date: Date, time: Date) -> Date {

    let calendar = NSCalendar.current

    let dateComponents = calendar.dateComponents([.year, .month, .day], from: date)
    let timeComponents = calendar.dateComponents([.hour, .minute, .second], from: time)

    var components = DateComponents()
    components.year = dateComponents.year
    components.month = dateComponents.month
    components.day = dateComponents.day
    components.hour = timeComponents.hour
    components.minute = timeComponents.minute
    components.second = timeComponents.second

    return calendar.date(from: components)!
}
like image 20
Jasper Alblas Avatar answered Sep 21 '22 06:09

Jasper Alblas