对于许多人(包括我)来说,这似乎是一个反复出现的 问题 ,并且在将头发拉得太长之后,我终于解决了这个问题。
此代码所依赖的假设是:
- 你对日期感兴趣,而不是时间
- 您希望您的日期计算忽略任何夏令时
- 您想要一个足够简单的日期字符串表示,以便您可以保留它。
为了实现 1。我使用了唯一的 NSCalendar 实例,该实例初始化为 Gregorian,GMT 这也适用于 2。
对于 3. NSDateFormatter 使用唯一的日历及其时区进行初始化。将格式化程序的时区设置为用于计算的日历的时区是我遇到的所有问题的关键!
这应该总是正确的(假设下面的代码是DateModel
类的一部分):
NSDate * today = [DateModel normalize: [NSDate date]] ;
NSString*todayS= [DateModel dateToString: today] ;
BOOL alwaysTrue=[[DateModel normalize: [NSDate date]] isEqual: [DateModel stringToDate: todayS]] ;
这是代码:
+ (NSDate *) normalize: (NSDate *) date {
NSDateComponents * comps = [[DateModel calendar] components:NSYearCalendarUnit
| NSMonthCalendarUnit
| NSDayCalendarUnit
| NSHourCalendarUnit
| NSMinuteCalendarUnit
| NSSecondCalendarUnit
fromDate:date] ;
[comps setHour:0] ;
[comps setMinute:0] ;
[comps setSecond:0] ;
NSDate * dateOnly = [[DateModel calendar] dateFromComponents:comps] ;
return dateOnly ;
}
+ (NSCalendar *) calendar {
static NSCalendar * calendar = nil ;
if (calendar == nil) {
calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] ;
calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation: @"GMT"] ;
}
return calendar ;
}
+ (NSDateFormatter *) dateFormatter {
static NSDateFormatter * formatter = nil ;
if (formatter == nil) {
formatter = [[NSDateFormatter alloc] init] ;
[formatter setCalendar:[self calendar]] ; // <- This is
[formatter setTimeZone:[self calendar].timeZone] ; // <- critical
[formatter setDateFormat:@"yyyyMMdd"] ;
}
return formatter ;
}
+ (NSDate *) dateFromString: (NSString *) stringDate {
return [DateModel normalize: [[DateModel dateFormatter] dateFromString:stringDate]] ;
}
+ (NSString *) stringFromDate: (NSDate *) date {
return [[DateModel dateFormatter] stringFromDate:[DateModel normalize: date]] ;
}
希望这对某人有帮助!