使用 setDoesRelativeDateFormatting: YES 和 setDateFormat: 与 NSDateFormatter
Posted
技术标签:
【中文标题】使用 setDoesRelativeDateFormatting: YES 和 setDateFormat: 与 NSDateFormatter【英文标题】:Using setDoesRelativeDateFormatting: YES and setDateFormat: with NSDateFormatter 【发布时间】:2013-12-02 15:07:46 【问题描述】:当当前语言支持时,NSDateFormatter 对生成诸如“今天”、“明天”、“昨天”等相对日期有很好的支持。一个很大的优势是所有这些都已经为您本地化了——您不需要翻译字符串。
您可以通过以下方式打开此功能:
[dateFormatter setDoesRelativeDateFormatting: YES];
不利的一面是,这似乎只适用于使用其中一种预定义格式的实例,例如:
[dateFormatter setDateStyle: NSDateFormatterShortStyle];
如果您将日期格式化程序设置为使用自定义格式,如下所示:
[dateFormatter setDateStyle: @"EEEE"];
然后当你打电话时:
[dateFormatter stringFromDate: date];
…你只会得到一个空字符串。
我希望能够在可能的情况下获取相关字符串,并在没有时使用我自己的自定义格式。
【问题讨论】:
【参考方案1】:我在 NSDateFormatter 上设置了一个类别来为此提供解决方法。代码后面有解释。
在 NSDateFormatter+RelativeDateFormat.h 中:
@interface NSDateFormatter (RelativeDateFormat)
-(NSString*) relativeStringFromDateIfPossible:(NSDate *)date;
@end
在 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
这是如何工作的?
它使用(任意)标准格式维护两个日期格式化程序。它们的格式相同,只是一个提供相对日期字符串,另一个不提供。
通过使用两个格式化程序格式化给定日期,可以查看相对日期格式化程序是否给出了特殊的相对日期。当两个格式化程序给出不同的结果时,存在一个特殊的相对日期。
如果有一个特殊的相对日期字符串,则返回那个特殊的相对日期字符串。 如果没有一个特殊的相对日期字符串,原始格式化程序将用作后备,并使用您在其上定义的格式设置。您可以了解更多关于dispatch_once
here的信息。
一个限制……
该实现不处理您可能已放入格式字符串的时间组件。当相对日期字符串可用时,您的格式字符串将被忽略并获得相对日期字符串。
【讨论】:
干得好。我建议的一种解决方法是使用dispatch_once
创建静态格式化程序
改为使用 dispatch_once。谢谢@GreatWiz。【参考方案2】:
我认为@Benjohn 的代码的 swift 版本对其他人有用
extension NSDateFormatter
@nonobjc static let relativeFormatter : NSDateFormatter =
let formatter = NSDateFormatter()
formatter.dateStyle = .MediumStyle
formatter.timeStyle = .NoStyle
formatter.doesRelativeDateFormatting = true
return formatter
()
@nonobjc static let absoluteFormatter : NSDateFormatter =
let formatter = NSDateFormatter()
formatter.dateStyle = .MediumStyle
formatter.timeStyle = .NoStyle
formatter.doesRelativeDateFormatting = false
return formatter
()
func relativeStringFromDateIfPossible(date:NSDate) -> String
if NSDateFormatter.relativeFormatter.locale != locale
NSDateFormatter.relativeFormatter.locale = locale
NSDateFormatter.absoluteFormatter.locale = locale
if NSDateFormatter.absoluteFormatter.calendar != calendar
NSDateFormatter.relativeFormatter.calendar = calendar
NSDateFormatter.absoluteFormatter.calendar = calendar
let maybeRelativeString = NSDateFormatter.relativeFormatter.stringFromDate(date)
let absoluteString = NSDateFormatter.absoluteFormatter.stringFromDate(date)
return (maybeRelativeString != absoluteString ) ? maybeRelativeString : stringFromDate(date)
【讨论】:
以上是关于使用 setDoesRelativeDateFormatting: YES 和 setDateFormat: 与 NSDateFormatter的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?
Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)