2011-02-08 11 views
13

¿Alguien sabe de una biblioteca o algo que convertirá un NSDate en cadenas como los ejemplos a continuación?Cadena relativa de NSDate

1 hour ago 
yesterday 
last Thursday 
2 days ago 
last month 
6 months ago 
last year 

Respuesta

16

NSDateFormatter va a hacer una gran cantidad de lo que se menciona anteriormente usando setDoesRelativeDateFormatting: en una instancia. Desde allí, puede controlar el formato utilizando el estilo de fecha y el estilo de tiempo para ajustarlo a sus necesidades.

Si eso no le proporciona lo que necesita, entonces echa un vistazo a SORelativeDateTransformer, es una subclase NSValueTransformer que intenta proporcionar el mismo comportamiento que usted ve con fechas relativas en SO.

Por último, si desea hacer su propia investigación o hacer más investigación aquí es la (probable) pregunta original sobre el tema ... yes it is question 11.

+1

Es curioso, nunca antes * he visto ese método en 'NSDateFormatter', y juro que lo he buscado ... –

+0

¡Respuesta impresionante y muy completa! SORelativeDateTransformer es exactamente lo que estoy buscando y conocer NSDateFormatter también es útil. – keegan3d

+4

Merece la pena señalar que 'NSDateFormatter' solo tiene un puñado de estas cadenas relativas. Es más o menos "Mañana", "Hoy" y "Ayer". –

16

Para la posteridad, que aquí es un método categoría NSDate Tiré juntos que utiliza el cálculo de la relatividad de desbordamiento de pila unidos por David, así como otros consejos de adoquines de otros SO preguntas similares:

- (NSString *)relativeDateString 
{ 
    const int SECOND = 1; 
    const int MINUTE = 60 * SECOND; 
    const int HOUR = 60 * MINUTE; 
    const int DAY = 24 * HOUR; 
    const int MONTH = 30 * DAY; 

    NSDate *now = [NSDate date]; 
    NSTimeInterval delta = [self timeIntervalSinceDate:now] * -1.0; 

    NSCalendar *calendar = [NSCalendar currentCalendar]; 
    NSUInteger units = (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit); 
    NSDateComponents *components = [calendar components:units fromDate:self toDate:now options:0]; 

    NSString *relativeString; 

    if (delta < 0) { 
     relativeString = @"!n the future!"; 

    } else if (delta < 1 * MINUTE) { 
     relativeString = (components.second == 1) ? @"One second ago" : [NSString stringWithFormat:@"%d seconds ago",components.second]; 

    } else if (delta < 2 * MINUTE) { 
     relativeString = @"a minute ago"; 

    } else if (delta < 45 * MINUTE) { 
     relativeString = [NSString stringWithFormat:@"%d minutes ago",components.minute]; 

    } else if (delta < 90 * MINUTE) { 
     relativeString = @"an hour ago"; 

    } else if (delta < 24 * HOUR) { 
     relativeString = [NSString stringWithFormat:@"%d hours ago",components.hour]; 

    } else if (delta < 48 * HOUR) { 
     relativeString = @"yesterday"; 

    } else if (delta < 30 * DAY) { 
     relativeString = [NSString stringWithFormat:@"%d days ago",components.day]; 

    } else if (delta < 12 * MONTH) { 
     relativeString = (components.month <= 1) ? @"one month ago" : [NSString stringWithFormat:@"%d months ago",components.month]; 

    } else { 
     relativeString = (components.year <= 1) ? @"one year ago" : [NSString stringWithFormat:@"%d years ago",components.year]; 

    } 

    return relativeString; 
} 
1

DateTools es un impresionante marco completo para hacer todo tipo de funciones relacionadas con la fecha. https://github.com/MatthewYork/DateTools

Como categoría NSDate, es más fácil de usar que SORelativeDateTransformer.

Sin embargo, hay un problema con la obtención de valores de día precisos. (Por ejemplo, si hoy es lunes por la mañana, la tarde del sábado se reportó como "Yesterday", debe ser "Hace dos días")

Esto debería funcionar mejor (utilizando DateTools):

- (NSString *)relativeDateStringForDate:(NSDate *)d 
{ 
    if ([d daysAgo] < 1) { 
     //Return as is 
     return [d timeAgoSinceNow]; 
    } 
    else { //More than 24 hours ago. The default implementation will underreport (round down) day durations. 
      //We should modify the reference date we're using to midnight on the current day. 

     NSDate *date = [NSDate date]; 
     date = [date dateByAddingDays:1]; 
     NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar]; 
     NSUInteger preservedComponents = (NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit); 
     NSDate *todayAtMidnight = [calendar dateFromComponents:[calendar components:preservedComponents fromDate:date]]; 

     return [d timeAgoSinceDate:todayAtMidnight]; 

    } 
} 
5

NO utilice su propia traducción de cadenas personalizada. Escribir su propia traducción que hace algo así como "hace 3 segundos" no solo tiene el problema de tener que actualizarse constantemente, sino que tampoco se localiza en otros idiomas.

su lugar, utilice Apple incorporado en NSDateFormatter: salida

Esta voluntad algo así como "hoy, 23:10", o "07/17/14, 05:44 AM".