Кто-нибудь знает библиотеку или что-то, что преобразует NSDate в строки, подобные примерам ниже?
1 hour ago
yesterday
last Thursday
2 days ago
last month
6 months ago
last year
Кто-нибудь знает библиотеку или что-то, что преобразует NSDate в строки, подобные примерам ниже?
1 hour ago
yesterday
last Thursday
2 days ago
last month
6 months ago
last year
NSDateFormatter будет делать многое из того, что упоминалось выше, используя setDoesRelativeDateFormatting: на экземпляре. Оттуда вы можете управлять форматированием, используя стиль даты и стиль времени, чтобы точно настроить его на свои нужды.
Если это не поможет вам, посмотрите SORelativeDateTransformer, это подкласс NSValueTransformer, который пытается предоставить такое же поведение вы видите с относительными датами на SO.
Наконец, если вы хотите перевернуть свои собственные или сделать больше исследований, это (вероятный) оригинальный вопрос по теме... да, это вопрос 11.
Дата математика отстой. Посмотрите библиотеку хронологии Дэйва Делонга (https://github.com/davedelong/Chronology) или, для iOS 13+, (NS) RelativeDateTimeFormatter
Я оставляю ниже для потомков, но это определенно неправильная вещь. Мой обновленный ответ выше.
Вот метод категории NSDate, который я создал вместе, который использует расчет относительности Qaru, связанный Дэвидом, а также другие советы, придуманные из других подобных вопросов SO:
- (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;
}
НЕ используйте собственный собственный перевод строк. Написание собственного перевода, которое делает что-то вроде "3 секунды назад", не только требует постоянной необходимости обновления, но также не локализует на другие языки.
Вместо этого используйте Apple, встроенную в NSDateFormatter:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.doesRelativeDateFormatting = YES;
formatter.locale = [NSLocale currentLocale];
formatter.dateStyle = NSDateFormatterShortStyle;
formatter.timeStyle = NSDateFormatterShortStyle;
NSString *timeString = [formatter stringFromDate:self.date];
Это выведет что-то вроде "Сегодня, 11:10 вечера" или "7/17/14, 5:44 AM".
Похоже, что TTTTimeIntervalFormatter в FormatterKit может также помочь в генерации относительных строк интервала времени.
DateTools - потрясающая всеобъемлющая структура для выполнения всех видов связанных с датой функций. https://github.com/MatthewYork/DateTools
Как категория NSDate, это проще в использовании, чем SORelativeDateTransformer.
Однако есть проблема с получением точных значений дня. (Например, если сегодня утром в понедельник, субботний вечер будет представлен как "вчера", должен быть "два дня назад" )
Это должно работать лучше (используя 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];
}
}