我有一个UITableViewController
的简单应用程序,用户填写并在另一个视图中选择UIDatePicker
的日期来填充。 cells
的{{1}}填充了UITableView
中的字词,UITextField
UITableView
标题代表section
中的所选日期。
当用户保存在UIDatePicker
时,它会保存到Add Entry View Controller,
,Core Data
负责更新NSFetchedResultsController
。
在我的应用程序的早期版本(版本2.0)中,我遇到了一个错误,即美国时区总是会在UITableView
所选日期之前的一天显示该部分标题。对其他国家来说没问题。 NSDate使用UTC时区存储。
我通过将UIDatePicker
设置为不使用版本2.1.1的任何时区来实现修复。我认为修复它,但进一步测试让我发现其他错误。
我现在正试图解决这个问题。
我有以下部分标题的UIDatePicker
属性:
Transient
我的模型是:-(NSString *)sectionDateFormatter
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"d MMMM yyyy"];
dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
NSDate *thisDate = self.dates.dateOfEvent;
NSString *stringDate = [dateFormatter stringFromDate:self.dates.dateOfEvent];
NSLog(@"[Transaction] The NSDate of self.dates.dateOfEvent = %@", thisDate);
NSLog(@"[Transaction] The NSDate converted into a string = %@", stringDate);
return [dateFormatter stringFromDate:self.dates.dateOfEvent];
}
与Transaction Entity
有关系,而Dates Entity
是datesOfEvent
。我将其转换为字符串,因此可以使用NSDate
标题以我想要的格式轻松显示。
问题
如果我从我的应用程序的新安装开始,这非常有效,在section
中,我已将Add Entry View Controller
设置为使用GMT时区。
但是,如果我从版本2.1.1更新,我的所有EXISTING *条目的日期都会在UIDatePicker
的{{1}}标题中向后移动一个。我的意思是:
如果我在9月17日有一个条目,在2.1.1版本中有一个第15个条目和第10个条目(仅仅是一个日期示例),当我更新到我正在工作的这个新版本时所有章节标题都可以追溯到9月16日,9月14日和9月。如果我点击该条目,section
将显示它应该是的日期(而不是UITableView
标题中显示的日期)。因此,如果我点击第一个条目,UIDatePicker
会向我显示第17个,但section
标题会显示第16个。
这与时区无关。
我不确定我需要做些什么来确保更新的用户具有相同的日期,新用户也不会遇到问题。为什么一切都要追溯到一个日期?
更新后运行应用程序时,NSLogs输出显示: [交易] self.dates.dateOfEvent = 2014-09-16 23:00:00 +0000的NSDate [交易] NSDate转换为字符串= 2014年9月16日
我不明白为什么UIDatePicker
在23:00时排名第16,字符串显示为第16位。我不明白为什么日期会追溯到一个日期。
*现有:我清楚地标记了这一点,因为更新版本中的新条目工作正常,但现有条目是其日期在章节标题中移回的条目。
请注意,对于版本2.1.1,我没有代码在section
标题的dateOfEvent
属性中使用GMT。这是我在开发过程中引入的一些东西,这是由于时区的一些奇怪行为造成的。
更新:显示日期的存储方式
在Add Entry的保存方法中,在2.1.1版中,我这样做:
Transient
所以,我已经为日历和NSDateComponents添加了localTimeZone,但是我在2.1.1的发布版本中注释了代码。
在2.0版中,我有:
section
我将NSDateComponents的时区设置为UTC。
在2.2版本(我正在处理的版本)中,我设置了这个:
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
//cal.timeZone = [NSTimeZone localTimeZone];
NSDateComponents *components = [cal components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:self.datePicker.date];
//[components setTimeZone:[NSTimeZone localTimeZone]];
NSDate *selectedDate = [cal dateFromComponents:components];
// Call the date category and check whether the value exists; if it does return, etc.
Date *date = (Date *)[Date occasionWithDate:selectedDate inManagedObjectContext:context];
我将此设置为GMT时区。
对此有任何帮助真的很感激。
答案 0 :(得分:1)
NSDate包含UTC的时间点(大致是格林威治标准时间,没有夏令时)。它没有时区信息。如果我们同时看看我们的手表,我们可能会看到不同的时间,因为我们在不同的位置。但是如果我们的应用程序同时调用[NSDate日期],我们会看到相同的结果。
您应始终将NSDate保存为未修改的,并使用NSTimeZone和NSDateFormatter方法向用户显示时间。如果NSLog(@"%@",[NSDate date]))显示对您来说意外的事情,这是绝对正常的,因为它以UTC显示时间。通过NSDateFormatter向用户显示的文本应该不同。
我说你需要退出你正在做的事情,并找出你现在存储的确切日期。您是否存储了正确的NSDate,或者您是否以某种方式调整了时区?如果你的新代码同时存储不同的NSDates,那么显然有些东西是行不通的。