iPhone:计算距下​​一个生日天数的方法不准确--?

标签 iphone date calendar nsdatecomponents

这是一个益智游戏。我使用以下方法来计算今天的日期和即将到来的生日之间的天数:

-(int) daysTillBirthday: (NSDate*)aDate {

// check to see if valid date was passed in

//NSLog(@"aDate passed in is %@",aDate);

if (aDate == nil) {
    //NSLog(@"aDate is NULL");
    return -1;  // return a negative so won't be picked in table
}

//** HOW MANY DAYS TO BDAY

NSDate *birthDay = aDate; // [calendar dateFromComponents:myBirthDay];

//NSLog(@"birthDay: %@, today: %@",birthDay, [NSDate date]);

NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];

NSDateComponents *thisYearComponents = [calendar components:NSYearCalendarUnit fromDate:[NSDate date]];
NSDateComponents *birthDayComponents = [calendar components:NSMonthCalendarUnit|NSDayCalendarUnit fromDate:birthDay];
[birthDayComponents setYear:[thisYearComponents year]];

NSDate *birthDayThisYear = [calendar dateFromComponents:birthDayComponents];

//NSLog(@"birthDayThisYear: %@",birthDayThisYear);

NSDateComponents *differenceHours = [calendar components:NSHourCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
NSDateComponents *differenceDays = [calendar components:NSDayCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];

// NSLog(@"difference days: %i, hours %i",[differenceDays day],[differenceHours hour]);

//*** I added this to try and correct the "error" *** 

if ([differenceDays day] == 0) {  // is it today, or tomorrow?

    if (([differenceHours hour] <= 0) && ([differenceHours hour] >= -24)) {  // must be today

        //NSLog(@"TODAY");
        return (0);            
        [calendar release];

    }else if (([differenceHours hour] >= 0) && ([differenceHours hour] <= 24)) { 

        //NSLog(@"TOMORROW");
        return (1);
        [calendar release];

    }           
}

if ([differenceDays day] < 0) {
    // this years birthday is already over. calculate distance to next years birthday
    [birthDayComponents setYear:[thisYearComponents year]+1];
    birthDayThisYear = [calendar dateFromComponents:birthDayComponents];
    differenceDays = [calendar components:NSDayCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
}


return ([differenceDays day]);
[calendar release];

}

一切正常,但结果不准确!我经常发现生日与今天很接近,但相差一天,导致 [differenceDays day] 相同!即,如果今天是 2011 年 6 月 6 日,并且我有两个生日,一个是 6/7/2011,另一个是 6/8/2011,那么它们都显示为 1 天后!

谁有更好的方法来准确计算这个,或者可以找出问题所在?

非常感谢。

最佳答案

NSCalendar 提供了一种更简单的方法来执行此操作:

NSDate *birthday = ...; // the birthday
NSDate *today = [NSDate date];

NSCalendar *c = [NSCalendar currentCalendar];
NSInteger birthdayDayOfYear = [c ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:birthday];
NSInteger todayDayOfYear = [c ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:today];

NSInteger different = birthdayDayOfYear - todayDayOfYear;

基本上,我们计算出今天距离今年有多远(即今天 [6 月 5 日] 是一年中的第 156 天),然后将它们相减以计算出今年有多少天他们之间。

当然,此方法依赖于目标日期与当前日期在同一年的假设。不过,我认为解决这个问题相当容易。

<小时/>

另一种更简单的方法可以解决多年差异,如下所示:

NSDateComponents *d = [[NSCalendar currentCalendar] components:NSDayCalendarUnit fromDate:today toDate:birthday options:0];
NSInteger difference = [d day];
<小时/>

如果您需要确保生日是在未来,这也很容易完成:

NSDateComponents *year = [[[NSDateComponents alloc] init] autorelease];
NSInteger yearDiff = 1;
NSDate *newBirthday = birthday;
while([newBirthday earlierDate:today] == newBirthday) {
  [year setYear:yearDiff++];
  newBirthday = [[NSCalendar currentCalendar] dateByAddingComponents:year toDate:birthday options:0];
}
//continue on with the 2-line calculation above, using "newBirthday" instead.

更新我更新了上面的循环,始终从原始日期一次递增n年,而不是逐年递增。如果某人出生于 2 月 29 日,则增加一年将得到 3 月 1 日,一旦再次进入闰年,这将是错误的。通过每次从原始日期跳转,我们就不会遇到这个问题。

关于iPhone:计算距下​​一个生日天数的方法不准确--?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6246727/

相关文章:

ios - 如何限制应用程序仅在 iPhone 中下载而不在 iPad 中下载

iphone - 不同高度的UITableViewCell将它们的accessoryView放置在不同的X位置

iphone - 我的 iPad 应用程序会导致设备重启吗?

javascript - 为什么 Javascript 将第 3 个月变成了 4 月?

django - Django:在settings.py中使用DATE_FORMAT,DATETIME_FORMAT,TIME_FORMAT吗?

iphone - 屏幕动画未录制

java - 更改日期

java - 为什么 Calendar 使用正确的时区返回错误的时间?

php - 使用 Javascript/PHP/mySQL 的日历

javascript - 使用 javascript 动态创建文本框