来自NSDate的相对字符串

时间:2011-02-08 19:11:07

标签: cocoa nsstring nsdate

是否有人知道将某个NSDate转换为字符串的库或其他内容,如下例所示?

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

5 个答案:

答案 0 :(得分:17)

NSDateFormatter将通过在实例上使用setDoesRelativeDateFormatting:来完成上面提到的大量操作。从那里,您可以使用日期样式和时间样式控制格式,以根据您的需要进行微调。

如果这不能满足您的需求,那么请查看SORelativeDateTransformer,它是一个NSValueTransformer子类,它试图提供您在SO上看到的相对日期相同的行为。

最后,如果你想自己动手或在这里做更多的研究,那么关于这个话题的{可能的}原始问题是...... yes it is question 11

答案 1 :(得分:16)

对于后代,这里是一个NSDate类别方法,我使用由David链接的Stack Overflow相关性计算以及其他类似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;
}

答案 2 :(得分:5)

请勿使用自己的自定义字符串翻译。编写自己的翻译,其中包含&#34; 3秒前&#34;不仅需要不断更新的问题,而且它也不会本地化为其他语言。

相反,请使用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];

这将输出类似&#34;今天,晚上11:10和#34;或&#34; 7/17 / 14,5:44 AM&#34;。

答案 3 :(得分:3)

TTTTimeIntervalFormatter中的FormatterKit似乎也可以帮助生成相对时间间隔字符串。

答案 4 :(得分:1)

DateTools是一个非常棒的综合框架,用于执行各种与日期相关的功能。 https://github.com/MatthewYork/DateTools

作为NSDate类别,它比SORelativeDateTransformer更容易使用。

然而,获得准确的日期值存在问题。 (例如,如果今天是星期一早上,星期六晚上将报告为&#34;昨天&#34 ;;应该是&#34;两天前&#34;)

这应该更好(使用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];

    }
}