3

遇到了一个非常令人沮丧的问题,似乎没有任何意义。我正在尝试获取两个日期之间的年数。这是我的代码。

// 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 并将其移至一年前。问题将开始出现。这是我将结束日期移回原始日期后将看到的 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 秒的时间。有谁知道为什么?

提前致谢!

添加

这是我初始化和存储 2 个日期的方式。

开始日期在 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];

}

这会引起任何问题吗?如果是,为什么调试会显示开始和结束日期,包括它们的时间完全相同?

4

3 回答 3

1

我在一个 ViewController 中创建了一个包含两个 UIDatePicker 的简单项目。我将每个 UIDatePicker 初始化为参考日期,并设置一个操作方法来计算两个 UIDatePicker 中的任何一个更改时的日期之间的差异。我将您的代码插入到该方法中,然后在 iPhone 模拟器中对其进行了测试。结果是您的代码正好输出 10 年:

2011-08-15 11:18:44.225 test[1004:b303] Debug start date = 2001-01-01 00:00:00 +0000
2011-08-15 11:18:44.225 test[1004:b303] Debug end date = 2011-01-01 00:00:00 +0000
2011-08-15 11:18:44.226 test[1004:b303] Debug year = 10
2011-08-15 11:18:44.226 test[1004:b303] Debug month = 0
2011-08-15 11:18:44.227 test[1004:b303] Debug day = 0
2011-08-15 11:18:44.227 test[1004:b303] Debug hours = 0
2011-08-15 11:18:44.227 test[1004:b303] Debug minutes = 0
2011-08-15 11:18:44.228 test[1004:b303] Debug seconds = 0

您是否在使用 UIDatePickers 之前将它们初始化为同一时间?默认情况下,UIDatePickers 被初始化为它们创建的日期(这包括小时、分钟、秒等,即使您在选择器中只显示年、月和日)。

您是否有可能以其他方式引入这种差异?也许您正在对日期进行其他计算或操作?

编辑:

在您添加的代码中,您应该从 startdate 引用 enddate,而不是从另一个日期对象。我知道您说它没有任何区别,但是使用 startdate 比假设今天和 startdate 将具有相同的值更好。

要考虑的另一件事是您的setStartDate:setEndDate:方法。在这些 setter 方法中,我建议将不需要的任何精度四舍五入为 0。如果您不允许用户设置比日期更精确的值,则将精度更高的值设置为 0。这样您就不会在任何两个日期之间留出小时、分钟或秒数。

于 2011-08-15T17:57:03.397 回答
0

我无法在 10.7 上重现此内容。您正在构建什么 SDK?

2011-08-15 13:51:44.262 test[9420:707] Debug start date = 2011-08-15 15:55:07 +0000
2011-08-15 13:51:44.263 test[9420:707] Debug end date = 2021-08-15 15:55:07 +0000
2011-08-15 13:51:44.263 test[9420:707] Debug year = 10
2011-08-15 13:51:44.264 test[9420:707] Debug month = 0
2011-08-15 13:51:44.264 test[9420:707] Debug day = 0
2011-08-15 13:51:44.265 test[9420:707] Debug hours = 0
2011-08-15 13:51:44.265 test[9420:707] Debug minutes = 0
2011-08-15 13:51:44.266 test[9420:707] Debug seconds = 0

请注意,这里没有理由提取日、时、分和秒。此外,如果datecomponentis not year,这将在您的情况下返回 0 。我假设您实际上是想让它返回 120?还是您以不同的方式使用它?

这是我的完整程序(对于 10.7,命令行模板):

int main (int argc, const char * argv[]) {
  @autoreleasepool {
    // Initialize variable to store calendar
    NSDate *startDate = [NSDate dateWithString:@"2011-08-15 15:55:07 +0000"];
    NSDate *endDate = [NSDate dateWithString:@"2021-08-15 15:55:07 +0000"];

    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 = %ld",[components year]);
    NSLog(@"Debug month = %ld",[components month]);
    NSLog(@"Debug day = %ld", [components day]);
    NSLog(@"Debug hours = %ld",[components hour]);
    NSLog(@"Debug minutes = %ld", [components minute]);
    NSLog(@"Debug seconds = %ld", [components second]);

//    [gregorian release];
    return 0;
  }
}
于 2011-08-15T17:55:42.590 回答
0

在对各种场景进行了相当多的修改之后,这就是我解决问题的方式。

1)由于查找日期之间差异的代码由几个独立方检查确定,因此我已将其作为问题根源消除。

2)我已经删除了任何试图修改我的应用程序中的日期的代码,这些代码原本不应该存在。

3)我现在在创建开始日期和结束日期时也初始化时间,以确保它们不是基于我在数据库中创建条目的任意时间。

这是初始化开始日期的代码片段。

NSDate *now = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *settomidnight = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:now];
[settomidnight setHour:0];
[settomidnight setMinute:0];
[settomidnight setSecond:0];
startdate = [calendar dateFromComponents:settomidnight];

有了这个,我从 NSLog 中看到时间现在设置为 16:00 +0000(转换为我的时区后对我来说是午夜)。问题现在已经消失,我不再失去我的 1 秒。

感谢所有帮助我走上正确道路的人!

于 2011-08-19T06:33:18.620 回答