質問

ご挨拶、

最近、私はnscalendarクラスで大きな問題に直面しました(私にはそう思われます)。

私のタスクでは、4000BCから2000AD(グレゴリオカレンダー)までの大規模な期間で作業する必要があります。ある場所では、100年間隔でNSDateを増やすことを余儀なくされました。広告タイムライン(0-> ...)で年を増やすと、すべてが正常に機能しましたが、BCで同じことを試したとき、私は少し混乱していました。

問題は、100年を3000年[編集]に追加しようとすると、何があっても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。

btw。:メソッド[nscalendarコンポーネント:fromdate:todate:options:] BC時代の年の違いを計算することはできません...追加「なぜ?」このパンドラの箱に。

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

なぜ私が何年しか反転しないのか疑問に思うなら、答えは単純で、年を除く他のすべてのコンポーネントは正しい方法で増加して減少しています(私はそれらすべてをテストしていませんが、数ヶ月と日は正常に働いているようです)。

編集: :誤ってAutoreleaseを誤って追加した、Johnに感謝します。

他のヒント

それはバグや機能です。 Apple Docは、それらが何を意味するかを決して言いません カレンダーの日付にコンポーネントを追加します. 。年間コンポーネントへの追加として、BCE日付に「コンポーネントの追加」を定義するのは完全に無料です。

はい、私はそれが直感に反するものであり、それがバグだと思います。

あなたはあなたを変換する必要があります NSDate どちらか

  • Unix Epoch(1.1.1970)からの2番目の -timeIntervalSince1970
  • OS X Epoch(1.1.2001)からの2番目の -timeIntervalSinceReferenceDate

その後、計算を実行し、それをに戻すことができます NSDate. 。常にグレゴリオカレンダーで作業するのは悪い考えだと思います... GUIに表示する直前にグレゴリオカレンダーに変換する方が良いでしょう。

あなたが私たちの時代の最初の瞬間とデートしていると想像してください - AD 0001-01-01 00:00:00。 前の瞬間は何でしたか? BC 0001-01-01 00:00:01. 。ココア開発者がこのタスクに基本的な算術を使用した場合、あなたは取得するでしょう AD 0000-12-31 23:59:59. 。それはグレゴリオカレンダーにとって合理的ですか?そうではないと思います。ですから、カレンダーを実装する最も便利な方法は、ERAフラグを使用し、変更することだったように思えます。」時間の方向「あらゆる場合に人間が読みやすい日付を取得するためにBC時代を扱うとき。

ところで: [NSCalendar dateByAddingComponents:toDate:options:] 本当に奇妙に振る舞い、BC日付間の時間間隔を数えることができないので、私もチェックしました。したがって、BCの日付では、たとえば、日付をADに翻訳してからDIFFを見つけることにより、回避策を使用できます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top