【问题标题】:NSDateFormatter relative date formatting with custom formatNSDateFormatter 具有自定义格式的相对日期格式
【发布时间】:2013-09-01 03:44:29
【问题描述】:

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

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,或相对日期格式会覆盖自定义格式。

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

提前致谢!

【问题讨论】:

    标签: objective-c nsdateformatter relative-date


    【解决方案1】:

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

    如果日期格式化程序使用相对日期格式化,它会在可能的情况下用表示相对日期的短语(例如“今天”或“明天”)替换其输出的日期部分。可用的短语取决于日期格式化程序的语言环境;而对于未来的日期,英语可能只允许“明天”,法语可能允许“后天后天”。

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

    【讨论】:

    • rmaddy 没有问这个问题。
    • 诀窍是找出相对格式实际发生的时间。你不能只依赖前一天和后一天。在其他语言中,例如法语和俄语,您将有“昨天之前”和“明天之后”的相对格式。
    【解决方案2】:

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

    但是问题依旧存在,下面是我自己的解决方法。

    创建 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,我们知道日期将包含十进制数字,除非它被替换为表示“今天”、“明天”以及其他语言中可能出现的任何内容。如果我们没有发现任何数字,我们会接受这个结果。

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

    【讨论】:

      【解决方案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
          }
      }
      

      【讨论】:

      • 这实际上是一个聪明的主意。如果您有很多日期要格式化(例如在表格中),请小心,因为这会使正在进行的格式化数量增加三倍。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-05
      • 2017-07-28
      • 2014-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多