ios - framework - cocoa touch español
Cocoa-Touch: ¿Cómo veo si dos NSDates están en el mismo día? (12)
¿Hay una forma más fácil / mejor de hacerlo que obtener NSDateComponents y comparar día / mes / año?
Sí, hay una manera más fácil
-[NSCalendar rangeForUnit:startDate:interval:forDate:]
Este método hace que sea fácil establecer una fecha para el comienzo de una unidad (día, hora, mes, año, ...) y obtener la duración (intervalo) de esa unidad.
Como categoría, podría usarse como
@interface NSDate (Comparison)
-(BOOL) isSameDay:(NSDate *)rhs;
@end
@implementation NSDate (Comparison)
-(BOOL)isSameDay:(NSDate *)rhs
{
NSDate *lhs = self;
NSDate *lhsStart;
NSDate *rhsStart;
NSCalendar *cal = [NSCalendar currentCalendar];
[cal rangeOfUnit:NSCalendarUnitDay startDate:&lhsStart interval:NULL forDate:lhs];
[cal rangeOfUnit:NSCalendarUnitDay startDate:&rhsStart interval:NULL forDate:rhs];
return [lhsStart compare:rhsStart] == NSOrderedSame;
}
@end
Esta categoría debería funcionar para todas las versiones de iOS y Mac OS X 10.5+.
para iOS 8+ y Mac OS X 10.9+, puede usar NSCalendars
- (BOOL)isDate:(NSDate *)date1 equalToDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit;
Necesito saber si dos instancias NSDate son ambas del mismo día.
¿Hay una forma más fácil / mejor de hacerlo que obtener NSDateComponents y comparar día / mes / año?
(Nota: Mire la respuesta de Joe para una buena manera de hacer esto en iOS 8+)
Solo uso un formateador de fecha:
NSDateFormatter *dateComparisonFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateComparisonFormatter setDateFormat:@"yyyy-MM-dd"];
if( [[dateComparisonFormatter stringFromDate:firstDate] isEqualToString:[dateComparisonFormatter stringFromDate:secondDate]] ) {
…
}
HTH.
A continuación, se probará si dos fechas representan el mismo día en una época determinada (que en muchos casos es suficiente):
- (BOOL)isDate:(NSDate *)date1 sameDayAsDate:(NSDate *)date2 {
NSCalendar *calendar = [NSCalendar currentCalendar];
int diff = [calendar ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSEraCalendarUnit
forDate:date1] -
[calendar ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSEraCalendarUnit
forDate:date2];
return 0 == diff;
}
Creo mis propias clases de utilidad.
ZYUtility.h
@interface ZYUtility : NSObject
+ (NSDate *)yesterday;
+ (NSDate *)tomorrow;
+ (NSDate *)endOfDay:(NSDate *)date;
+ (NSDate *)beginningOfDay:(NSDate *)date;
@end
ZYUtility.m
+ (NSDate *)yesterday;
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *componets = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
fromDate:[NSDate date]];
componets.day -= 1;
componets.hour = 24;
componets.minute = 0;
componets.second = 0;
return [calendar dateFromComponents:componets];
}
+ (NSDate *)tomorrow;
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *componets = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit
fromDate:[NSDate date]];
componets.day += 1;
componets.hour = 0;
componets.minute = 0;
componets.second = 0;
return [calendar dateFromComponents:componets];
}
+ (NSDate *)beginningOfDay:(NSDate *)date {
NSCalendar *calendar = [NSCalendar currentCalendar];
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *comp = [calendar components:unitFlags fromDate:date];
return [calendar dateFromComponents:comp];
}
+ (NSDate *)endOfDay:(NSDate *)date {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [NSDateComponents new];
components.day = 1;
NSDate *theDate = [calendar dateByAddingComponents:components
toDate:[ZYUtility beginningOfDay:date]
options:0];
theDate = [theDate dateByAddingTimeInterval:-1];
return theDate;
}
En Swift:
NSCalendar.currentCalendar().isDate(yourDate, equalToDate: yourOtherDate, toUnitGranularity: .Day)
Volverá verdadero si están en el mismo día.
Me gusta la solución del programador, pero iría más allá y NSDate
una categoría de NSDate
que proporciona este método. Hará que tu código sea un poco más legible, y no necesitarás copiar y pegar el método en cada nueva clase que pueda necesitarlo, solo importa el archivo de encabezado.
NSDate + SameDay.h
@interface NSDate (SameDay)
- (BOOL)isSameDayAsDate:(NSDate*)otherDate;
@end
NSDate + SameDay.m
#import "NSDate+SameDay.h"
@implementation NSDate (SameDay)
- (BOOL)isSameDayAsDate:(NSDate*)otherDate {
// From progrmr''s answer...
NSCalendar* calendar = [NSCalendar currentCalendar];
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents* comp1 = [calendar components:unitFlags fromDate:self];
NSDateComponents* comp2 = [calendar components:unitFlags fromDate:otherDate];
return [comp1 day] == [comp2 day] &&
[comp1 month] == [comp2 month] &&
[comp1 year] == [comp2 year];
}
@end
Luego, después de importar NSDate+SameDay.h
en su clase, puede usarlo de la siguiente manera:
if ([myFirstDate isSameDayAsDate:mySecondDate]) {
// The two dates are on the same day...
}
NSDateComponents parece la mejor apuesta para mí. Otra táctica para probar es la de peaje sin costo, tendiéndolo en un CFDate, luego usando CFDateGetAbsoluteTime y haciendo una resta para obtener la cantidad de tiempo entre las dos fechas. Tendrás que hacer algunos cálculos adicionales para averiguar si la diferencia de tiempo aterriza las fechas en el mismo día, sin embargo.
Si está trabajando con iOS 8, puede usar -isDate:inSameDayAsDate:
De NSCalendar.h
:
/*
This API compares the Days of the given dates, reporting them equal if they are in the same Day.
*/
- (BOOL)isDate:(NSDate *)date1 inSameDayAsDate:(NSDate *)date2 NS_AVAILABLE(10_9, 8_0);
Tenga en cuenta que, por alguna razón, esto no llegó a la documentación oficial en el sitio para desarrolladores de Apple. Pero definitivamente es parte de la API pública.
Si tiene como objetivo iOS 8 (y OS X 10.9) o posterior , entonces la respuesta de Joe es una mejor solución utilizando un nuevo método en NSCalendar solo para este propósito:
-[NSCalendar isDate:inSameDayAsDate:]
Para iOS 7 o anterior : NSDateComponents es mi preferencia. Qué tal algo como esto:
- (BOOL)isSameDayWithDate1:(NSDate*)date1 date2:(NSDate*)date2 {
NSCalendar* calendar = [NSCalendar currentCalendar];
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents* comp1 = [calendar components:unitFlags fromDate:date1];
NSDateComponents* comp2 = [calendar components:unitFlags fromDate:date2];
return [comp1 day] == [comp2 day] &&
[comp1 month] == [comp2 month] &&
[comp1 year] == [comp2 year];
}
Yo uso NSDateComponents para quitar el aspecto del tiempo y luego comparar. Algo como:
if ([[self beginningOfDay:date1] isEqualToDate:[self beginningOfDay:date2]])
{
...
}
- (NSDate *)beginningOfDay:(NSDate *)date {
NSCalendar *calendar = [NSCalendar currentCalendar];
unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *comp = [calendar components:unitFlags fromDate:date];
return [calendar dateFromComponents:comp];
}
en Swift 3.0, iOS8 +
if NSCalendar.current.isDate(Date(), equalTo: date, toGranularity: .day) {
}
o
if NSCalendar.current.isDateInToday(date) {
}
NSCalendar.currentCalendar().isDateInToday(yourNSDate)
Disponible en iOS 8.0 y posterior y OS X v10.9 y posterior.