使用setDoesRelativeDateFormatting:YES和setDateFormat:with NSDateFormatter

Ben*_*ohn 4 cocoa-touch nsdate nsdateformatter nscalendar ios

NSDateFormatter对生成相关日期有很好的支持,例如"今天","明天","昨天",这些都是当前语言支持的.一个很大的优点是所有这些都已经为您本地化 - 您不需要翻译字符串.

您可以使用以下命令打开此功能:

[dateFormatter setDoesRelativeDateFormatting: YES];
Run Code Online (Sandbox Code Playgroud)

不利的一面是,这似乎只适用于使用其中一种预定义格式的实例,例如:

[dateFormatter setDateStyle: NSDateFormatterShortStyle];
Run Code Online (Sandbox Code Playgroud)

如果您设置日期格式化程序以使用自定义格式,如下所示:

[dateFormatter setDateStyle: @"EEEE"];
Run Code Online (Sandbox Code Playgroud)

然后当你打电话:

[dateFormatter stringFromDate: date];
Run Code Online (Sandbox Code Playgroud)

......你会回来一个空字符串.

我希望能够在可能的情况下获得相关字符串,并在不支持时使用我自己的自定义格式.

Ben*_*ohn 9

我在NSDateFormatter上设置了一个类别,为此提供了一种解决方法.代码后面有一个解释.

在NSDateFormatter + RelativeDateFormat.h中:

@interface NSDateFormatter (RelativeDateFormat)
-(NSString*) relativeStringFromDateIfPossible:(NSDate *)date;
@end
Run Code Online (Sandbox Code Playgroud)

在NSDateFormatter + RelativeDateFormat.m中:

@implementation NSDateFormatter (RelativeDateFormat)
-(NSString*) relativeStringFromDateIfPossible:(NSDate *)date
{
  static NSDateFormatter *relativeFormatter;
  static NSDateFormatter *absoluteFormatter;

  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    const NSDateFormatterStyle arbitraryStyle = NSDateFormatterShortStyle;

    relativeFormatter = [[NSDateFormatter alloc] init];
    [relativeFormatter setDateStyle: arbitraryStyle];
    [relativeFormatter setTimeStyle: NSDateFormatterNoStyle];
    [relativeFormatter setDoesRelativeDateFormatting: YES];

    absoluteFormatter = [[NSDateFormatter alloc] init];
    [absoluteFormatter setDateStyle: arbitraryStyle];
    [absoluteFormatter setTimeStyle: NSDateFormatterNoStyle];
    [absoluteFormatter setDoesRelativeDateFormatting: NO];
  });

  NSLocale *const locale = [self locale];
  if([relativeFormatter locale] != locale)
  {
    [relativeFormatter setLocale: locale];
    [absoluteFormatter setLocale: locale];
  }

  NSCalendar *const calendar = [self calendar];
  if([relativeFormatter calendar] != calendar)
  {
    [relativeFormatter setCalendar: calendar];
    [absoluteFormatter setCalendar: calendar];
  }

  NSString *const maybeRelativeDateString = [relativeFormatter stringFromDate: date];
  const BOOL isRelativeDateString = ![maybeRelativeDateString isEqualToString: [absoluteFormatter stringFromDate: date]];

  if(isRelativeDateString)
  {
    return maybeRelativeDateString;
  }
  else
  {
    return [self stringFromDate: date];
  }
}
@end
Run Code Online (Sandbox Code Playgroud)

这是如何运作的?

它使用(任意)标准格式维护两个日期格式化程序.它们格式相同,除了一个将提供相对日期字符串而另一个不提供.

通过使用两种格式化器格式化给定日期,可以查看相对日期格式化程序是否给出特殊的相对日期.当两个格式化程序给出不同的结果时,有一个特殊的相对日期.

  • 如果一个相对特殊的日期字符串,返回相对特殊的日期字符串.
  • 如果没有特殊的相对日期字符串,则原始格式化程序将用作后备,并使用您在其上定义的格式设置.

你可以dispatch_once在这里找到更多相关信息.

限制......

该实现不处理您可能已放入格式字符串的时间组件.当相对日期字符串可用时,将忽略您的格式标记,并获得相对日期字符串.