几个观察:
-
你想要NSCalendarUnitWeekOfMonth,而不是NSCalendarUnitWeekOfYear。
-
为了区分“今天”和“昨天”,不能只获取两个NSDate 对象之间的日期分量。您应该先获取两个日期的日期分量(而不是时间分量),然后再获取这两组日期分量之间的差异。
事实上,如果现在是上午 9 点,而您正在查看昨晚 11 点的消息,它会计算出 day < 1,因此它会显示“今天晚上 11 点”(这是错误的)而不是“昨天晚上 11 点” ”。
-
如果您要包含“x 个月前”字符串,我建议您不要自己构建它。 Apple 有一个类可以为您执行此操作 (NSDateComponentsFormatter),并且已本地化。
所以,把所有这些放在一起,你会得到类似的东西:
- (NSString *)relativeDateStringForDate:(NSDate *)date {
// get the number of days differences
NSCalendarUnit units = NSCalendarUnitDay | NSCalendarUnitWeekOfMonth | NSCalendarUnitMonth | NSCalendarUnitYear;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [calendar components:units fromDate:date];
NSDateComponents *nowComponents2 = [calendar components:units fromDate:[NSDate date]];
NSDateComponents *components = [calendar components:units fromDateComponents:dateComponents toDateComponents:nowComponents2 options:0];
if (components.year > 0 || components.month > 0 || components.weekOfMonth > 0 || components.day > 1) {
NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
formatter.allowedUnits = units;
formatter.maximumUnitCount = 2; // set this to whatever you want, but 1 or 2 is often best
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleFull;
return [NSString stringWithFormat:@"%@ %@", [formatter stringFromDateComponents:components], NSLocalizedString(@"ago", @"x days _ago_")];
} else {
// build time string
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.timeStyle = NSDateFormatterShortStyle;
NSString *timeString = [formatter stringFromDate:date];
if (components.day == 1) {
return [NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"Yesterday", @"day before today"), timeString];
} else {
return [NSString stringWithFormat:@"%@ %@", NSLocalizedString(@"Today", @"well, er, today"), timeString];
}
}
}
现在,请注意,如果日期在昨天之前,我排除了时间。如果日期字符串以任何大于天的单位来衡量,则时间没有意义(例如,时间在此字符串中没有意义:“3 个月前,上午 11:20”)。如果要包含时间,则必须包含日期(这会使这些相对的“以前”字符串变得无用)。所以你可能会摆脱这个“之前”的部分:
- (NSString *)relativeDateStringForDate:(NSDate *)date {
// get the number of days differences
NSCalendarUnit units = NSCalendarUnitDay | NSCalendarUnitWeekOfMonth | NSCalendarUnitMonth | NSCalendarUnitYear;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [calendar components:units fromDate:date];
NSDateComponents *nowComponents2 = [calendar components:units fromDate:[NSDate date]];
NSDateComponents *components = [calendar components: NSCalendarUnitDay fromDateComponents:dateComponents toDateComponents:nowComponents2 options:0];
if (components.day > 1) {
// build date/time string
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.timeStyle = NSDateFormatterShortStyle;
formatter.dateStyle = NSDateFormatterShortStyle;
return [formatter stringFromDate:date];
} else {
// build time string
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.timeStyle = NSDateFormatterShortStyle;
NSString *timeString = [formatter stringFromDate:date];
if (components.day == 1) {
return [NSString stringWithFormat:@"%@, %@", NSLocalizedString(@"Yesterday", @"day before today"), timeString];
} else {
return [NSString stringWithFormat:@"%@, %@", NSLocalizedString(@"Today", @"well, er, today"), timeString];
}
}
}
这解决了奇怪的“3 个月前,上午 11:20”问题,但话又说回来,它不再是相对日期/时间字符串。
另一种选择是完全放弃绝对时间,只显示一个相对字符串:
- (NSString *)relativeDateStringForDate:(NSDate *)date {
NSCalendarUnit units = NSCalendarUnitSecond | NSCalendarUnitMinute | NSCalendarUnitHour | NSCalendarUnitDay | NSCalendarUnitWeekOfMonth | NSCalendarUnitMonth | NSCalendarUnitYear;
NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
formatter.allowedUnits = units;
formatter.maximumUnitCount = 2;
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleFull;
return [NSString stringWithFormat:@"%@ %@", [formatter stringFromDate:date toDate:[NSDate date]], NSLocalizedString(@"ago", @"x days _ago_")];
}
上述示例的细节不如基本概念重要,即:
- 在确定“今天”和“昨天”时要小心使用日期组件;
- 在尝试创建时间字符串或日期/时间字符串时使用日期格式化程序;和
- 在尝试构建表示已过去时间(或天数)的字符串时,请使用日期组件格式化程序。