NSDateFormatter使用自定义格式的相对日期格式

时间:2013-08-28 21:29:55

标签: objective-c nsdateformatter relative-date

所以我的意图是推出如下所示的日期:

Today, August 28
Tomorrow, August 29
Friday, August 30
...etc

问题在于我似乎只能如此接近。

当我setDoesRelativeDateFormatting:YESsetDateStyleFullsetTimeStyleNone时,会产生如下结果:

Today
Tomorrow
Friday, August 30, 2013

这会产生一年,并且不会产生今天和明天的月份和日期。

我尝试的其他代码是:

[NSDateFormatter dateFormatFromTemplate:@"eeeedMMM" options:0
                                                     locale:[NSLocale currentLocale]];

,产生以下结果:

Wednesday, August 28
Thursday, August 29
Friday, August 30

看起来,dateStyle和timeStyle或相对日期格式会覆盖自定义格式。

有没有办法在不进入自定义实现的情况下完成此日期格式?

提前致谢!

3 个答案:

答案 0 :(得分:3)

基于有关NSDateFormatter的文档,我认为您的问题的唯一解决方案是为您希望相对显示的日期提供两个日期字符串。您应该记住,在不同的语言中,相对日期存在差异。来自文档:

  

如果日期格式化程序使用相对日期格式,则在可能的情况下,它会使用短语(例如“今天”或“明天”)替换其输出的日期组件 - 表示相对日期。可用的短语取决于日期格式化程序的区域设置;然而,对于将来的日期,英语可能只允许“明天”,法语可能允许“后天的日子”。

我相信如果你定义你将在昨天,今天和明天相对展示你可以使用2个NSDateFormatters。第一个显示相对值,第二个显示实际日期。对于非相对日期,您将仅显示非相对值。

答案 1 :(得分:3)

似乎没有办法在不进入自定义实现的情况下完成这种日期格式化。所以,对这个问题的简短回答是“不”。

然而,问题仍然存在,所以下面是我自己解决问题的方法。

创建NSDateFormatter的子类并实现自定义init并覆盖stringFromDate:方法。

- (instancetype)initWithDateFormat:(NSString *)dateFormat
{
    self = [super init];
    if (self) {
        NSLocale *locale = [NSLocale currentLocale];
        self.locale = locale;

        self.timeStyle = NSDateFormatterNoStyle;
        self.dateStyle = NSDateFormatterShortStyle;
        self.doesRelativeDateFormatting = YES;

        self.dateFormat = dateFormat;
    }
    return self;
}

- (NSString *)stringFromDate:(NSDate *)date
{
    NSString *dateFormat = self.dateFormat;
    self.dateFormat = nil;

    BOOL didRelativeDateFormatting = self.doesRelativeDateFormatting;
    self.doesRelativeDateFormatting = YES;

    NSString *result = [super stringFromDate:date];

    if ([result rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location != NSNotFound) {
        self.dateFormat = dateFormat;
        self.doesRelativeDateFormatting = NO;
        result = [super stringFromDate:date];
    }

    self.dateFormat = dateFormat;
    self.doesRelativeDateFormatting = didRelativeDateFormatting;

    return result;
}

由于doesRelativeDateFormattingdateFormat是互斥的,我们首先尝试使用相对格式。鉴于我们在init方法中设置self.dateStyle = NSDateFormatterShortStyle,我们知道日期将包含十进制数,除非它被替换为意味着“今天”,“明天”以及可能出现在其他语言中的任何内容。如果我们没有发现任何数字,我们会接受这个结果。

如果字符串中有数字数字,我们假设相关格式没有发生,所以我们应用自己的日期格式。

答案 2 :(得分:3)

我在Swift 3中使用这种方法:

struct SharedFormatters {
    private static let dateWithRelativeFormatting: DateFormatter = {
        let df = DateFormatter()
        df.dateStyle = .medium
        df.doesRelativeDateFormatting = true
        return df
    }()
    private static let dateWithoutRelativeFormatting: DateFormatter = {
        let df = DateFormatter()
        df.dateStyle = .medium
        df.doesRelativeDateFormatting = false
        return df
    }()
    private static let longDateWithoutYear: DateFormatter = {
        let df = DateFormatter()
        df.dateFormat = "MMMM d"
        df.doesRelativeDateFormatting = false
        return df
    }()
    static func string(from date: Date) -> String {
        let val = dateWithRelativeFormatting.string(from: date)
        let val2 = dateWithoutRelativeFormatting.string(from: date)
        return val == val2 ? longDateWithoutYear.string(from: date) : val
    }
}