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];
NSDateCom开发者_运维知识库ponents *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?
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;
}
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)!
}
Here it is in Swift 2
func combineDateAndTime(date: NSDate, time: NSDate) -> NSDate {
let calendar = NSCalendar.currentCalendar()
let dateComponents = calendar.components([.Year, .Month, .Day], fromDate: date)
let timeComponents = calendar.components([.Hour, .Minute, .Second], fromDate: time)
let components = NSDateComponents()
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.dateFromComponents(components)!
}
(Swift + extension) are your friend:
// MARK: - NSDate extension -
extension NSDate {
static func combineDate(date date: NSDate, withTime time: NSDate) -> NSDate? {
let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)
let dateComponents = gregorian?.components([.Year, .Month, .Day], fromDate: date)
let timeComponents = gregorian?.components([.Hour, .Minute, .Second], fromDate: date)
dateComponents?.second = timeComponents?.second ?? 0
dateComponents?.minute = timeComponents?.minute ?? 0
dateComponents?.hour = timeComponents?.hour ?? 0
if let _ = dateComponents {
return gregorian?.dateFromComponents(dateComponents!)
}
return nil
}
}
精彩评论