我想将nsdate转换为相对格式"Today","Yesterday","a week ago","a month ago","a year ago","date as it is"
.
我已经为它写了以下方法..但有些如何只是打印,因为它是日期..你能告诉我应该是什么问题吗?
//以下是我的函数,它将日期转换为相对字符串
+(NSString *)getDateDiffrence:(NSDate *)strDate{ NSDateFormatter *df = [[NSDateFormatter alloc] init]; df.timeStyle = NSDateFormatterMediumStyle; df.dateStyle = NSDateFormatterShortStyle; df.doesRelativeDateFormatting = YES; NSLog(@"STRING DATEEE : %@ REAL DATE TODAY %@",[df stringFromDate:strDate],[NSDate date]); return [df stringFromDate:strDate]; }
我有以下格式的日期字符串 "2013-10-29T09:38:00"
当我试图给出NSDate对象时,它总是返回我的null日期.
所以我试图将该日期转换为yyyy-MM-dd HH:mm:ssZZZZ
然后我将此日期传递给函数然后它只是打印整个日期..
如何解决这个问题呢?
//以下是我调用上述函数的代码
NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"]; NSDate *date = [formatter dateFromString:[threadDict objectForKey:@"lastMessageDate"]]; [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ssZZZZ"]; NSString *date1 = [formatter stringFromDate:date]; NSDate *date_d = [formatter dateFromString:date1]; NSString *resultstr=[UserManager getDateDiffrence:date]; self.dateLabel.text=resultstr;
David Rönnqv.. 56
为简单起见,我假设你格式化的日期都是过去的(没有"明天"或"下周").并不是说它不能完成,而是处理更多的情况并返回更多的字符串.
您可以使用所需components:fromDate:toDate:options:
的任何日期组件组合来获取两个日期之间的年数,月数,周数,天数,小时数等.然后,按照从最重要(例如年份)到最不重要(例如日)的顺序浏览它们,您可以仅基于最重要的组件格式化字符串.
例如:1周,2天和7小时前的日期将被格式化为"1周".
如果要为特定数量的单元创建特殊字符串,例如"明天"为"1天前",则可以在确定该组件是最重要的组件后检查该组件的值.
代码看起来像这样:
- (NSString *)relativeDateStringForDate:(NSDate *)date { NSCalendarUnit units = NSCalendarUnitDay | NSCalendarUnitWeekOfYear | NSCalendarUnitMonth | NSCalendarUnitYear; // if `date` is before "now" (i.e. in the past) then the components will be positive NSDateComponents *components = [[NSCalendar currentCalendar] components:units fromDate:date toDate:[NSDate date] options:0]; if (components.year > 0) { return [NSString stringWithFormat:@"%ld years ago", (long)components.year]; } else if (components.month > 0) { return [NSString stringWithFormat:@"%ld months ago", (long)components.month]; } else if (components.weekOfYear > 0) { return [NSString stringWithFormat:@"%ld weeks ago", (long)components.weekOfYear]; } else if (components.day > 0) { if (components.day > 1) { return [NSString stringWithFormat:@"%ld days ago", (long)components.day]; } else { return @"Yesterday"; } } else { return @"Today"; } }
如果您的日期也可以在将来,那么您可以按相同的顺序检查组件的绝对值,然后检查它是正还是负,以返回相应的字符串.我只展示下面的一年:
if ( abs(components.year > 0) ) { // year is most significant component if (components.year > 0) { // in the past return [NSString stringWithFormat:@"%ld years ago", (long)components.year]; } else { // in the future return [NSString stringWithFormat:@"In %ld years", (long)components.year]; } }
对于时差只是好处但今天/昨天不起作用,因为如果它在过去24小时内被认为是今天:/ (6认同)
您不应该将`%zd`用于`NSDateComponents`的各种属性,因为`NSDateComponents`的属性使用`NSInteger`,而不是`size_t`.[字符串编程指南](https://developer.apple.com/library/ios/documentation/cocoa/conceptual/Strings/Articles/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265-SW5)建议使用` %ld`并转换为`long`.在64位平台上,演员将成为无操作. (3认同)
ChrisJF.. 13
这是我的回答(在Swift 3中!)以及为什么它更好.
func datePhraseRelativeToToday(from date: Date) -> String { // Don't use the current date/time. Use the end of the current day // (technically 0h00 the next day). Apple's calculation of // doesRelativeDateFormatting niavely depends on this start date. guard let todayEnd = dateEndOfToday() else { return "" } let calendar = Calendar.autoupdatingCurrent let units = Set([Calendar.Component.year, Calendar.Component.month, Calendar.Component.weekOfMonth, Calendar.Component.day]) let difference = calendar.dateComponents(units, from: date, to: todayEnd) guard let year = difference.year, let month = difference.month, let week = difference.weekOfMonth, let day = difference.day else { return "" } let timeAgo = NSLocalizedString("%@ ago", comment: "x days ago") let dateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.locale = Locale.autoupdatingCurrent formatter.dateStyle = .medium formatter.doesRelativeDateFormatting = true return formatter }() if year > 0 { // sample output: "Jan 23, 2014" return dateFormatter.string(from: date) } else if month > 0 { let formatter = DateComponentsFormatter() formatter.unitsStyle = .brief // sample output: "1mth" formatter.allowedUnits = .month guard let timePhrase = formatter.string(from: difference) else { return "" } return String(format: timeAgo, timePhrase) } else if week > 0 { let formatter = DateComponentsFormatter() formatter.unitsStyle = .brief; // sample output: "2wks" formatter.allowedUnits = .weekOfMonth guard let timePhrase = formatter.string(from: difference) else { return "" } return String(format: timeAgo, timePhrase) } else if day > 1 { let formatter = DateComponentsFormatter() formatter.unitsStyle = .abbreviated; // sample output: "3d" formatter.allowedUnits = .day guard let timePhrase = formatter.string(from: difference) else { return "" } return String(format: timeAgo, timePhrase) } else { // sample output: "Yesterday" or "Today" return dateFormatter.string(from: date) } } func dateEndOfToday() -> Date? { let calendar = Calendar.autoupdatingCurrent let now = Date() let todayStart = calendar.startOfDay(for: now) var components = DateComponents() components.day = 1 let todayEnd = calendar.date(byAdding: components, to: todayStart) return todayEnd }
请记住重复使用格式化程序以避免任何性能损失!提示:DateFormatter和DateComponentsFormatter上的扩展是好主意.
利用DateFormatter的"昨天"和"今天".这已经由Apple翻译,可以为您节省工作!
使用DateComponentsFormatter已翻译的"1周"字符串.(再次为你工作,Apple的礼貌.)你所要做的就是翻译"%@ ago"字符串.
其他答案错误地计算了当天从"今天"切换到"昨天"等的时间.固定常数是一个很大的NO-NO,因为原因.此外,其他答案使用当前日期/时间,他们应该使用当天日期/时间的结束.
使用autoupdatingCurrent进行日历和区域设置,确保您的应用程序立即与Settings.app中的用户日历和语言首选项保持同步
这个答案的灵感来自于GitHub上的DateTools.