BC时代的NScalendar问题
-
03-10-2019 - |
题
问候,
最近,我在Nscalendar课程中遇到了一个大问题(看来)。
在我的任务中,我需要使用从公元前4000年至2000AD(Gregorian日历)开始的较大时间。在某个地方,我被迫将一些NSDATE增加100年间隔。当在AD时间轴(0-> ...)中增加年份时,一切都很好,但是当我与BC一起尝试同一件事时,我有些困惑。
问题是,当您尝试将100年增加到3000 BC [编辑]年时,无论如何您都将获得3100BC [编辑] [编辑] ...我个人觉得这很奇怪和不合逻辑。正确的结果应为2900BC。
这是您看到这种“不正确”行为的代码样本:
NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
// initing
NSDateComponents *comps = [[[NSDateComponents alloc] init] autorelease];
[comps setYear:-1000];
NSDate *date = [gregorian dateFromComponents:comps];
// math
NSDateComponents *deltaComps = [[[NSDateComponents alloc] init] autorelease];
[deltaComps setYear:100];
date = [gregorian dateByAddingComponents:deltaComps toDate:date options:0];
// output
NSString *dateFormat = @"yyyy GG";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:dateFormat];
NSLog(@"%@", [formatter stringFromDate:date]);
您对这种行为能说些什么?这是应该如何工作还是这是一个错误?我很困惑:S。
顺便说一句:该方法[NSCALENDAR组件:FromDate:Todate:option:]不允许我们计算BC ERA年份之间的差异...附加“为什么?”在这个潘多拉的盒子里。
PS:我正在挖掘官方文档和其他资源,但没有发现这个问题(或者它打算这样做,我是个白痴?)。
解决方案
我找到了这个错误的简单解决方法。这里是:
@interface NSCalendar (EraFixes)
- (NSDate *)dateByAddingComponentsRegardingEra:(NSDateComponents *)comps toDate:(NSDate *)date options:(NSUInteger)opts;
@end
@implementation NSCalendar (EraFixes)
- (NSDate *)dateByAddingComponentsRegardingEra:(NSDateComponents *)comps toDate:(NSDate *)date options:(NSUInteger)opts
{
NSDateComponents *toDateComps = [self components:NSEraCalendarUnit fromDate:date];
NSDateComponents *compsCopy = [[comps copy] autorelease];
if ([toDateComps era] == 0) //B.C. era
{
if ([comps year] != NSUndefinedDateComponent) [compsCopy setYear:-[comps year]];
}
return [self dateByAddingComponents:compsCopy toDate:date options:opts];
}
@end
如果您想知道为什么我只倒转几年,答案很简单,除多年以外的其他组件以正确的方式增加和减少(我还没有对它们进行所有测试,但是几个月和几天似乎正常工作)。
编辑: :删除错误地添加了自动发行,谢谢约翰。
其他提示
这是一个错误和或功能。 Apple Doc从未说过他们的意思 将组件添加到日历日期. 。对于他们来说,将“添加一个组件”定义为公元前日期是年度组件的补充是完全免费的。
是的,我同意您的观点,这是违反直觉的,我认为这是一个错误。
您需要转换您的 NSDate
要点
- 使用Unix时期的第二个(1.1.1970)使用
-timeIntervalSince1970
- 第二个来自OS X Epoch(1.1.2001)的第二个
-timeIntervalSinceReferenceDate
然后您可以执行计算,然后将其转换回一个 NSDate
. 。我认为一直在Gregorian日历上工作是一个坏主意...最好在您在GUI上展示之前转换为Gregorian日历。
想象一下您与我们时代的第一时刻约会 - 广告0001-01-01 00:00:00。 以前是什么? BC 0001-01-01 00:00:01. 。如果可可开发人员将基本算术用于此任务,您将获得 广告0000-12-31 23:59:59. 。这对于格里高利日历合理吗?我猜不会。因此,在我看来,实施日历的最方便方法是使用ERA标志,并更改”时间方向“在与卑诗省时代打交道时,在每种情况下都能获得可读的日期。
顺便提一句。: [NSCalendar dateByAddingComponents:toDate:options:]
我的举止确实很奇怪,无法计算卑诗省日期之间的时间间隔,我也检查了。因此,对于卑诗省的日期,您可以使用解决方法,例如将日期转换为AD然后找到差异。