为什么Excel序列日期时间为NSDate转换两天,提前一小时40分钟?

时间:2014-06-19 12:55:04

标签: objective-c nsdate

我正在将日期从Excel电子表格转换为NSDate,但出于某种原因,它们总是提前两天出现:星期天出现在星期二等等。

我的转化方法基于cpearson.com的以下信息:

  

Excel将日期和时间存储为表示数字的数字   自1900年1月1日以来的几天,加上24小时工作日的一小部分:
  ddddd.tttttt。这称为序列日期或序列日期时间。   (...)数字的整数部分ddddd表示数字   自1900年1月1日以来的几天。 (...)数字的小数部分,   ttttt,表示24小时工作日的小数部分。对于   例如,上午6:00存储为0.25,或24小时工作日的25%。   同样,6PM存储在0.75,或24小时工作日的75%。

- (NSDate *)dateFromExcelSerialDate:(double)serialdate
{
    if (serialdate == 0)
        return nil;

    NSTimeInterval theTimeInterval;
    NSInteger numberOfSecondsInOneDay = 86400;

    double integral;
    double fractional = modf(serialdate, &integral);

    NSLog(@"%@ %@ \r serialdate = %f, integral = %f, fractional = %f",
          [self class], NSStringFromSelector(_cmd),
          serialdate, integral, fractional);

    theTimeInterval = integral * numberOfSecondsInOneDay; //number of days
    if (fractional > 0) {
        theTimeInterval += numberOfSecondsInOneDay / fractional; //portion of one day
    }

    NSCalendar *nl_gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    NSTimeZone *nl_timezone = [[NSTimeZone alloc] initWithName:@"Europe/Amsterdam"];
    [nl_gregorianCalendar setTimeZone:nl_timezone];

    NSDateComponents *excelBaseDateComps = [[NSDateComponents alloc] init];
    [excelBaseDateComps setMonth:1];
    [excelBaseDateComps setDay:1];
    [excelBaseDateComps setHour:00];
    [excelBaseDateComps setMinute:00];
    [excelBaseDateComps setTimeZone:nl_timezone];
    [excelBaseDateComps setYear:1900];
    NSDate *excelBaseDate = [nl_gregorianCalendar dateFromComponents:excelBaseDateComps];

    NSDate *inputDate = [NSDate dateWithTimeInterval:theTimeInterval sinceDate:excelBaseDate];

    NSLog(@"%@ %@ \r serialdate %f, theTimeInterval = %f \r inputDate = %@",
          [self class], NSStringFromSelector(_cmd),
          serialdate, theTimeInterval,
          [self.nl_dateFormatter stringFromDate:inputDate]);

    return inputDate;
}

该电子表格是在荷兰制作的,大概是荷兰语版的Microsoft Excel。 电子表格日期2014年7月6日星期日00:00产生以下结果: dateFromExcelSerialDate:

  

serialdate = 41826.000000,integral = 41826.000000,fractional =   0.000000 theTimeInterval = 3613766400.000000 inputDate = 08 jul。 2014 01:40

同样,2014年7月13日星期日00:00收益率:

  

serialdate = 41833.000000,integral = 41833.000000,fractional =   0.000000 theTimeInterval = 3614371200.000000 inputDate = 15 jul。 2014 01:40

我可以通过减去2天,1小时40分钟来纠正输出:

theTimeInterval -= ((60 * 60 * 24 * 2) + (60*60) + (60*40));

但我不知道那是多么强大。

这两天的差异让我觉得它与闰年修正有关,所以我试图让日历通过在excelBaseDate中添加NSTimeInterval秒来进行计算,如下所示:

NSDateComponents *comps = [[NSDateComponents alloc] init];
         [comps setSecond:theInterval];
         NSDate *inputDate = [nl_gregorianCalendar dateByAddingComponents:comps
         toDate:excelBaseDate
         options:0];

奇怪的是,这给了我1870年代的某个日期。谁知道发生了什么?

1 个答案:

答案 0 :(得分:-1)

这里有两件事:

  1. 您的开始日期为1900-Jan-1,但您的推荐说明明确指出:引用为1900-Jan-0 - 您可以在此处添加额外的一天;

  2. 1900年不是闰年 - 你可以在这里额外增加一天;

  3. 我想,这就是为什么你每次都要多加两天的原因。


    Microsoft在此处了解see more有关此主题的信息。