iPhone: Преобразуйте строку даты в относительную метку времени

Вы можете получить информацию о городе / штате в формате значений, разделенных табуляцией, из GeoNames.org . Данные являются бесплатными, всеобъемлющими и хорошо структурированными. Для данных в США возьмите файл US.txt на странице бесплатных данных почтового индекса . Файл readme.txt на этой странице описывает формат.

39
задан stefanB 28 May 2009 в 00:53
поделиться

5 ответов

-(NSString *)dateDiff:(NSString *)origDate {
    NSDateFormatter *df = [[NSDateFormatter alloc] init];
    [df setFormatterBehavior:NSDateFormatterBehavior10_4];
    [df setDateFormat:@"EEE, dd MMM yy HH:mm:ss VVVV"];
    NSDate *convertedDate = [df dateFromString:origDate];
    [df release];
    NSDate *todayDate = [NSDate date];
    double ti = [convertedDate timeIntervalSinceDate:todayDate];
    ti = ti * -1;
    if(ti < 1) {
        return @"never";
    } else  if (ti < 60) {
        return @"less than a minute ago";
    } else if (ti < 3600) {
        int diff = round(ti / 60);
        return [NSString stringWithFormat:@"%d minutes ago", diff];
    } else if (ti < 86400) {
        int diff = round(ti / 60 / 60);
        return[NSString stringWithFormat:@"%d hours ago", diff];
    } else if (ti < 2629743) {
        int diff = round(ti / 60 / 60 / 24);
        return[NSString stringWithFormat:@"%d days ago", diff];
    } else {
        return @"never";
    }   
}
72
ответ дан 27 November 2019 в 02:05
поделиться

Вот методы из Какао, которые помогут вам получить релевантную информацию (не уверен, все ли они доступны в coca-touch).

    NSDate * today = [NSDate date];
    NSLog(@"today: %@", today);

    NSString * str = @"Thu, 21 May 09 19:10:09 -0700";
    NSDate * past = [NSDate dateWithNaturalLanguageString:str
                            locale:[[NSUserDefaults 
                            standardUserDefaults] dictionaryRepresentation]];

    NSLog(@"str: %@", str);
    NSLog(@"past: %@", past);

    NSCalendar *gregorian = [[NSCalendar alloc]
                             initWithCalendarIdentifier:NSGregorianCalendar];
    unsigned int unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | 
                             NSDayCalendarUnit | 
                             NSHourCalendarUnit | NSMinuteCalendarUnit | 
                             NSSecondCalendarUnit;
    NSDateComponents *components = [gregorian components:unitFlags
                                                fromDate:past
                                                  toDate:today
                                                 options:0];

    NSLog(@"months: %d", [components month]);
    NSLog(@"days: %d", [components day]);
    NSLog(@"hours: %d", [components hour]);
    NSLog(@"seconds: %d", [components second]);

Кажется, что объект NSDateComponents содержит разницу в соответствующих единицах (как указано). Если вы укажете все единицы, вы можете использовать этот метод:

void dump(NSDateComponents * t)
{
    if ([t year]) NSLog(@"%d years ago", [t year]);
    else if ([t month]) NSLog(@"%d months ago", [t month]);
    else if ([t day]) NSLog(@"%d days ago", [t day]);
    else if ([t minute]) NSLog(@"%d minutes ago", [t minute]);
    else if ([t second]) NSLog(@"%d seconds ago", [t second]);
}

Если вы хотите вычислить самостоятельно, вы можете взглянуть на:

NSDate timeIntervalSinceDate

А затем использовать секунды в алгоритме.

Отказ от ответственности : Если этот интерфейс устаревает (я не проверял), предпочтительный способ Apple сделать это через NSDateFormatters , как предлагается в комментариях ниже, также выглядит довольно аккуратно - я сохраню свой ответ по историческим причинам, это может все же будет полезно для некоторых взглянуть на используемую логику.

22
ответ дан 27 November 2019 в 02:05
поделиться

Не уверен, почему этого нет в cocoa-touch, я хороший стандартный способ сделать это было бы здорово.

Настройте некоторые типы для хранения данных, это упростит, если вам когда-либо требовалось немного его локализовать. (очевидно, расширьте, если вам нужно больше периодов времени)

typedef struct DayHours {
    int Days;
    double Hours;
} DayHours;


+ (DayHours) getHourBasedTimeInterval:(double) hourBased withHoursPerDay:(double) hpd
{
    int NumberOfDays = (int)(fabs(hourBased) / hpd);
    float hoursegment = fabs(hourBased) - (NumberOfDays * hpd);
    DayHours dh;
    dh.Days = NumberOfDays;
    dh.Hours = hoursegment;
    return dh;
}

ПРИМЕЧАНИЕ: Я использую расчет на основе часов, так как это то, в чем мои данные. NSTimeInterval основан на секундах. Мне также пришлось конвертировать между ними.

0
ответ дан 27 November 2019 в 02:05
поделиться

Используйте класс NSDate:

timeIntervalSinceDate

возвращает интервал в секундах.

Быстрое упражнение для реализации этого в objective-c:

  1. Получить время «сейчас» NSDate
  2. Получить NSDate, который вы хотите сравнить с
  3. . Получите интервал в секундах, используя timeIntervalSinceDate

Затем реализуйте этот псевдокод:

if (x < 60) // x seconds ago

else if( x/60 < 60) // floor(x/60) minutes ago

else if (x/(60*60) < 24) // floor(x/(60*60) hours ago

else if (x/(24*60*60) < 7) // floor(x(24*60*60) days ago

и так далее ...

, тогда вам нужно решить, равен ли месяц 30,31 или 28 дней. Будьте проще - выберите 30.

Может быть и лучший способ, но сейчас 2 часа ночи, и это первое, что пришло в голову ...

1
ответ дан 27 November 2019 в 02:05
поделиться

Я пока не могу редактировать, но я взял Gilean и сделал пару настроек и сделал его категорией NSDateFormatter.

Он принимает строку формата, поэтому он будет работать с произвольными строками, и я добавил, что предложения if, содержащие единичные события, должны быть грамматически правильными.

Ура,

Карл CM

@interface NSDateFormatter (Extras)
+ (NSString *)dateDifferenceStringFromString:(NSString *)dateString
                                  withFormat:(NSString *)dateFormat;

@end

@implementation NSDateFormatter (Extras)

+ (NSString *)dateDifferenceStringFromString:(NSString *)dateString
                                  withFormat:(NSString *)dateFormat
{
  NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
  [dateFormatter setDateFormat:dateFormat];
  NSDate *date = [dateFormatter dateFromString:dateString];
  [dateFormatter release];
  NSDate *now = [NSDate date];
  double time = [date timeIntervalSinceDate:now];
  time *= -1;
  if(time < 1) {
    return dateString;
  } else if (time < 60) {
    return @"less than a minute ago";
  } else if (time < 3600) {
    int diff = round(time / 60);
    if (diff == 1) 
      return [NSString stringWithFormat:@"1 minute ago", diff];
    return [NSString stringWithFormat:@"%d minutes ago", diff];
  } else if (time < 86400) {
    int diff = round(time / 60 / 60);
    if (diff == 1)
      return [NSString stringWithFormat:@"1 hour ago", diff];
    return [NSString stringWithFormat:@"%d hours ago", diff];
  } else if (time < 604800) {
    int diff = round(time / 60 / 60 / 24);
    if (diff == 1) 
      return [NSString stringWithFormat:@"yesterday", diff];
    if (diff == 7) 
      return [NSString stringWithFormat:@"last week", diff];
    return[NSString stringWithFormat:@"%d days ago", diff];
  } else {
    int diff = round(time / 60 / 60 / 24 / 7);
    if (diff == 1)
      return [NSString stringWithFormat:@"last week", diff];
    return [NSString stringWithFormat:@"%d weeks ago", diff];
  }   
}

@end
14
ответ дан 27 November 2019 в 02:05
поделиться