NSDate from NSDateComponents

Sam picture Sam · Jul 10, 2011 · Viewed 25k times · Source

I am trying to alter the hh, mm, ss component of an NSDate to that of another NSDate - but for some reason, the time gets set to midnight for some reason. I can't figure out why!

Here is the code;

+ (NSDate *) fixTime:(NSDate*)fromDate  toDate:(NSDate *) toDate {
    NSCalendar *cal = [NSCalendar currentCalendar];
    [cal setTimeZone:[NSTimeZone localTimeZone]];
    [cal setLocale:[NSLocale currentLocale]];
    NSLog(@"fromDate=<%@>", [fromDate descriptionWithLocale:[NSLocale currentLocale]]);
    NSLog(@"toDate=  <%@>", [toDate descriptionWithLocale:[NSLocale currentLocale]]);

    NSDateComponents *fromTimeComponents = [cal components:( NSHourCalendarUnit   | 
                                                             NSMinuteCalendarUnit | 
                                                             NSSecondCalendarUnit   ) fromDate:fromDate];                               
    NSDateComponents *toDateComponents = [cal components:( NSYearCalendarUnit   | 
                                                           NSMonthCalendarUnit  |  
                                                           NSDayCalendarUnit      ) fromDate:toDate];
    NSDateComponents *toTimeComponents = [cal components:( NSHourCalendarUnit   | 
                                                           NSMinuteCalendarUnit | 
                                                           NSSecondCalendarUnit   ) fromDate:toDate];
    [toTimeComponents setHour:[fromTimeComponents hour]];
    [toTimeComponents setMinute:[fromTimeComponents minute]];
    [toTimeComponents setSecond:[fromTimeComponents second]];
    NSLog(@"toDateComponents year = %d", [toDateComponents year]);                                                     
    NSLog(@"toDateComponents mon  = %d", [toDateComponents month]);                                                    
    NSLog(@"toDateComponents day  = %d", [toDateComponents day]);
    NSLog(@"toTimeComponents hour = %d", [toTimeComponents hour]);                                                     
    NSLog(@"toTimeComponents min  = %d", [toTimeComponents minute]);                                                       
    NSLog(@"toTimeComponents sec  = %d", [toTimeComponents second]);

    NSDate *newDate = [cal dateFromComponents:toDateComponents];
    NSLogDebug(@"newDate=<%@>", [newDate descriptionWithLocale:[NSLocale currentLocale]]);
    return [[newDate retain] autorelease];
}

and here is the debug output on the console. Note the values of hour, min, sec components and the final value of newDate:

    <Util.m:229> fromDate=<Monday, July 11, 2011 10:35:00 PM Pacific Daylight Time>
    <Util.m:230> toDate=  <Saturday, July 23, 2011 9:35:00 PM Pacific Daylight Time>

    <Util.m:255> toDateComponents year = 2011
    <Util.m:256> toDateComponents mon  = 7
    <Util.m:257> toDateComponents day  = 23
    <Util.m:258> toTimeComponents hour = 22
    <Util.m:259> toTimeComponents min  = 35
    <Util.m:260> toTimeComponents sec  = 0
    <Util.m:266> newDate=<Saturday, July 23, 2011 12:00:00 AM Pacific Daylight Time>

Thanks in advance.

Answer

Deepak Danduprolu picture Deepak Danduprolu · Jul 10, 2011

You are generating the date off toDateComponents here,

NSDate *newDate = [cal dateFromComponents:toDateComponents];

The information in toDateComponents is only the date, month and the year. It doesn't have the time details. So you get 12:00:00 AM. You have stored the time info in toTimeComponents but it isn't used. If you want this to work, you will have to add the time info to toDateComponents and probably remove the toTimeComponents variable completely.

[toDateComponents setHour:[fromTimeComponents hour]];
[toDateComponents setMinute:[fromTimeComponents minute]];
[toDateComponents setSecond:[fromTimeComponents second]];