NSDateComponents 因 2 个日期的差异而缺少 1 秒
遇到一个似乎没有任何意义的真正令人沮丧的问题。我正在尝试获取两个日期之间的年数。这是我的代码。
// Initialize variable to store calendar
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
// Break out date to year component
NSDateComponents *Components = [gregorian components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit
fromDate:startDate
toDate:endDate
options:0];
// Debugging code
NSLog(@"Debug start date = %@",startDate);
NSLog(@"Debug end date = %@", endDate);
NSLog(@"Debug year = %d",[Components year]);
NSLog(@"Debug month = %d",[Components month]);
NSLog(@"Debug day = %d", [Components day]);
NSLog(@"Debug hours = %d",[Components hour]);
NSLog(@"Debug minutes = %d", [Components minute]);
NSLog(@"Debug seconds = %d", [Components second]);
[gregorian release];
// Check which component to extract and return value accordingly
// Defaults to month for now
if ([datecomponent isEqualToString:@"year"]) {
return [Components year];
}
else {
return [Components month];
}
开始和结束日期由 UIDatePickers 在其他地方设置。他们默认相差10岁。一旦我返回到控制结束日期的 UIDatePicker 并将其提前 1 年。问题将开始出现。这是将结束日期移回原始日期后我将看到的 NSLog 示例。我应该在其他地方看到 10 年和 0,但我错过了 1 秒。
Debug start date = 2011-08-15 15:55:07 +0000
Debug end date = 2021-08-15 15:55:07 +0000
Debug year = 9
Debug month = 11
Debug day = 30
Debug hours = 23
Debug minutes = 59
Debug seconds = 59
对我来说,开始日期和结束日期在 10 年之间看起来是相同的,但由于某种原因,我错过了 1 秒的时间。有谁知道为什么?
提前致谢!
添加
这是我初始化和存储两个日期的方式。
开始日期位于 viewWillAppear 方法中。
- (void)viewWillAppear:(BOOL)animated {
if ([managedObject valueForKeyPath:self.keypath] != nil)
[self.datePicker setDate:[managedObject
valueForKeyPath:keypath] animated:YES];
else
[self.datePicker setDate:[NSDate date] animated:YES];
[self.tableView reloadData];
[super viewWillAppear:animated];
相同的类
也用于我的结束日期,但是我还在 NSManagedObject 的自定义子类中添加了以下代码:-
- (void)awakeFromInsert {
[super awakeFromInsert];
// Set default date of registration to be today's date
self.startdate = [NSDate date];
NSDate *today = [[NSDate alloc] init]; // I also tried to equate this to self.startdate but there is no difference
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setYear:10];
self.enddate = [gregorian dateByAddingComponents:offsetComponents toDate:today options:0];
}
这会导致任何问题吗?如果是,为什么调试会显示开始和结束日期(包括它们的时间)完全相同?
Got a really frustrating problem that doesn't seem to make any sense. I'm trying to get the number of years between 2 dates. Here is my code.
// Initialize variable to store calendar
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
// Break out date to year component
NSDateComponents *Components = [gregorian components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit
fromDate:startDate
toDate:endDate
options:0];
// Debugging code
NSLog(@"Debug start date = %@",startDate);
NSLog(@"Debug end date = %@", endDate);
NSLog(@"Debug year = %d",[Components year]);
NSLog(@"Debug month = %d",[Components month]);
NSLog(@"Debug day = %d", [Components day]);
NSLog(@"Debug hours = %d",[Components hour]);
NSLog(@"Debug minutes = %d", [Components minute]);
NSLog(@"Debug seconds = %d", [Components second]);
[gregorian release];
// Check which component to extract and return value accordingly
// Defaults to month for now
if ([datecomponent isEqualToString:@"year"]) {
return [Components year];
}
else {
return [Components month];
}
The start and end dates are set by UIDatePickers elsewhere. They would default to being 10 years apart. Once I go back to the UIDatePicker that controls the end date and move that up to 1 year earlier. The problem will start appearing. This is an example of the NSLog I will see after I move the end date back to the original date. I should see 10 years and 0 everywhere else but I'm missing 1 second in time.
Debug start date = 2011-08-15 15:55:07 +0000
Debug end date = 2021-08-15 15:55:07 +0000
Debug year = 9
Debug month = 11
Debug day = 30
Debug hours = 23
Debug minutes = 59
Debug seconds = 59
The start and end dates look identical saved for the 10 years between them to me but for some reason, I'm missing 1 second of time. Does anyone know why?
Thanks in advance!
ADDED
Here is the way I have initialized and stored the 2 dates.
The start date is in the viewWillAppear method.
- (void)viewWillAppear:(BOOL)animated {
if ([managedObject valueForKeyPath:self.keypath] != nil)
[self.datePicker setDate:[managedObject
valueForKeyPath:keypath] animated:YES];
else
[self.datePicker setDate:[NSDate date] animated:YES];
[self.tableView reloadData];
[super viewWillAppear:animated];
}
The same class is also used for my end date however I have also added the following code in my custom subclass of NSManagedObject:-
- (void)awakeFromInsert {
[super awakeFromInsert];
// Set default date of registration to be today's date
self.startdate = [NSDate date];
NSDate *today = [[NSDate alloc] init]; // I also tried to equate this to self.startdate but there is no difference
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *offsetComponents = [[NSDateComponents alloc] init];
[offsetComponents setYear:10];
self.enddate = [gregorian dateByAddingComponents:offsetComponents toDate:today options:0];
}
Would this have caused any problems? If yes, why would the debug show the start and end dates including their times as exactly the same?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我创建了一个简单的项目,在单个 ViewController 中包含两个 UIDatePicker。我将每个 UIDatePicker 初始化为参考日期,并设置一个操作方法来计算两个 UIDatePicker 每次更改时的日期之间的差异。我将你的代码插入到该方法中,然后在 iPhone 模拟器中对其进行了测试。结果是您的代码输出正好 10 年:
您在使用 UIDatePickers 之前是否将它们初始化为相同的时间?默认情况下,UIDatePickers 被初始化为它们创建时的日期(这包括小时、分钟、秒等,即使您仅在选择器中显示年、月和日)。
您是否有可能以其他方式引入这种差异?也许您正在对日期进行一些其他计算或操作?
编辑:
在您添加的代码中,您应该从开始日期引用结束日期,而不是从另一个日期对象引用结束日期。我知道您说过这没有什么区别,但使用 startdate 是更好的形式,而不是假设今天和 startdate 将具有相同的值。
另一件需要考虑的事情是您的
setStartDate:
和setEndDate:
方法。在这些 setter 方法中,我建议将不需要的任何精度舍入到 0。如果您不允许用户设置比日期更精确的任何内容,则将任何更高的精度设置为 0。这样,任何两个日期之间就不会剩下任何小时、分钟或秒。I created a simple project with two UIDatePickers in a single ViewController. I initialized each UIDatePicker to the reference date and set an action method to calculate the difference between the dates of the two UIDatePickers each time either one of them changed. I inserted your code into that method and then tested it out in the iPhone Simulator. The result is that your code outputs exactly 10 years:
Have you initialized the UIDatePickers to the same time before using them? By default, the UIDatePickers are initialized to the date when they were created (this includes hours, minutes, seconds, etc, even if you are only showing year, month, and day in the picker).
Is it possible that you are introducing this discrepancy some other way? Perhaps you are doing some other calculations or manipulations on the date?
EDIT:
In the code that you added, you should reference enddate from startdate, rather than from another date object. I know that you said it didn't make a difference, but it is better form to use startdate rather than assume that today and startdate are going to have the same value.
Another thing to consider would be your
setStartDate:
andsetEndDate:
methods. In those setter methods, I would recommend rounding to 0 any precision that you don't need. If you don't allow the user to set anything more precise than the day, then set anything higher precision to 0. This way you won't have any left over hours, minutes, or seconds between any two dates.我无法在 10.7 上重现此问题。您正在构建什么 SDK?
请注意,没有理由在此处提取日、小时、分钟和秒。另外,如果
datecomponent
不是year
,则在您的情况下将返回 0。我想你实际上的意思是让它返回 120 ?或者您以不同的方式使用它?这是我的完整程序(对于 10.7,命令行模板):
I can't reproduce this on 10.7. What SDK are you building against?
Note that there's no reason to extract day, hour, minute and second here. Also, if
datecomponent
isn'tyear
, this is going to return 0 in your case. I assume you actually mean for it to return 120? Or are you using this a different way?Here is my full program (for 10.7, command-line template):
经过对各种场景的大量修改后,这就是我解决问题的方法。
1)由于查找日期之间差异的代码经多个独立方检查正常,因此我已将其作为问题根源消除。
2)我已经删除了任何试图修改我的应用程序中的日期的代码,这些代码本来就不应该存在。
3)现在,当我创建开始日期和结束日期时,我也会初始化时间,以确保它们不是基于我在数据库中创建条目时的任意时间。
这是初始化开始日期的代码片段。
这样,我从 NSLog 中看到时间现在设置为 16:00 +0000(转换为我的时区后对我来说是午夜)。现在问题已经消失了,我不再浪费一秒钟了。
感谢所有帮助引导我走上正确道路的人!
After quite a bit of tinkering with various scenarios, this is the way which I solved the issue.
1) Since the code to find the difference between the dates checks out ok by several independent parties, I have eliminated it as a source of problem.
2) I have removed any code that attempts to modify the dates in my app which should not have been there in the first place.
3) I now initialize the time as well when I create the start and end dates so as to ensure that they are not some arbitrary time based on when I create the entry in database.
Here's the code snippet to initialize the start date.
With this, I see from the NSLog that the time is now set as 16:00 +0000 (which is midnight for me after converting to my timezone). The problem has now gone away and I'm no longer losing my 1 second.
Thanks to all who have helped guide me on the right path!