objective c - ¿Cómo establezco un tiempo de NSDate existente?
objective-c nscalendar (6)
¿Cómo establezco una NSDate
de NSDate
existente?
Es decir, tengo una fecha (diga la fecha / hora actual), pero luego quiero configurar esto en una hora específica (p. Ej., 11.23 am). ¿Cuál es la forma más rápida de hacer esto en el objetivo C?
Estoy mirando NSCalendar
y veo métodos como dateByAddingComponents:toDate:options:
y dateFromComponents:
pero estos no parecen ser suficientes para lo que necesito aquí. Por ejemplo:
-
dateFromComponents:
- Tendría que trabajar todos los componentes para que esto funcione, lo que parece una exageración. -
dateByAddingComponents:toDate:options:
- No quiero AGREGAR en mi caso, sino más bien "establecer" la hora.
Aquí hay una extensión Swift (v2.1.1) más genérica que se basa en la útil respuesta de Andrew Schreiber.
extension NSDate {
func dateWithTime(hour: Int, minute: Int, second: Int) -> NSDate? {
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let components = calendar.components(([.Day, .Month, .Year]), fromDate: self)
components.hour = hour
components.minute = minute
components.second = second
let newDate = calendar.dateFromComponents(components)
return newDate
}
}
Un ejemplo rápido. Para mis propósitos, quería obtener la fecha para alrededor de las 12 del mediodía de mañana.
var tomorrow:NSDate = NSDate().dateByAddingTimeInterval(60*60*24); //60seconds*60minutes*12hours
var gregorian:NSCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!;
var unit : NSCalendarUnit = (NSCalendarUnit.YearCalendarUnit|NSCalendarUnit.MonthCalendarUnit|NSCalendarUnit.DayCalendarUnit|NSCalendarUnit.HourCalendarUnit|NSCalendarUnit.MinuteCalendarUnit);
var comps:NSDateComponents = gregorian.components(unit, fromDate: tomorrow);
comps.setValue(12, forComponent: NSCalendarUnit.HourCalendarUnit);
comps.setValue(0, forComponent: NSCalendarUnit.MinuteCalendarUnit);
var noon_tomorrow : NSDate = gregorian.dateFromComponents(comps)!;
Versión Swift 2.0 de cómo establecería una fecha determinada a las 8 am
extension NSDate {
func setTo8AM() -> NSDate {
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let components = calendar.components(([.Day, .Month, .Year]), fromDate: self)
components.hour = 8
return calendar.dateFromComponents(components)!
}
}
Aplique esto para establecer la hora desde otra fecha a una fecha existente
NSDate *today = [NSDate date]; // from which i need only "Year" "Month" "Date"
NSCalendar *calendar = [NSCalendar currentCalendar]
NSDateComponents *dateComponents = [calendar components:( NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit ) fromDate:today];
NSDate *timeDate = datePicker.date; // from which i need only "Hours" "Minutes" and "Seconds"
NSDateComponents *timeComponents = [calendar components:( NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:timeDate];
[dateComponents setHour:[timeComponents hour]];
[dateComponents setMinute:[timeComponents minute]];
[dateComponents setSecond:[timeComponents second]];
NSDate *newDate = [calendar dateFromComponents:dateComponents]; // New Date with My "Year" "Month" "Date" "Hours" "Minutes" and "Seconds"
NSLog(@"New Date: %@",newDate);
Nota de iOS 7: Estoy poniendo esto en algunas de estas preguntas porque el uso de NSUIntegerMax ya no parece funcionar en iOS7, y al usarlo me obligó a perseguir mi cola durante aproximadamente 3 horas. Acabo de descubrir que cuando uso NSUIntegerMax
, NSDateComponents
ignora el año establecido. Entonces, por ejemplo, esto NO cambia el año:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [gregorian components:NSUIntegerMax fromDate:date];
[comps setYear:year];
return [gregorian dateFromComponents:comps];
Considerando que esto hace:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger timeComps = (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSTimeZoneCalendarUnit);
NSDateComponents *comps = [gregorian components:timeComps fromDate:date];
[comps setYear:year];
return [gregorian dateFromComponents:comps];
Puede ser un error de iOS7 o puede ser que el uso de NSUIntegerMax fuera una casualidad que ya no funciona. Presentaré un informe de error y obtendré una respuesta definitiva.
En cualquier caso, si desea evitar consecuencias inesperadas, especifique TODOS los componentes, ¡de lo contrario, podría estar persiguiendo su cola!
NSDate *date = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents *components = [gregorian components: NSUIntegerMax fromDate: date];
[components setHour: 7];
[components setMinute: 59];
[components setSecond: 17];
NSDate *newDate = [gregorian dateFromComponents: components];
Uso NSUIntegerMax
lugar de máscaras de bits combinadas OR O porque es más fácil, pero si desea especificar qué componentes de datos recibir, sea mi invitado.