1

対処する必要がある 1600 年 1 月 1 日からの日数として保存されている日付があります。これは、アプリケーションで何度も読み取る必要がある従来の日付形式です。

以前は、カレンダー、空の日付コンポーネント、ルート日付を次のように作成していました。

self.gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar
                    ] autorelease];
id rootComponents = [[[NSDateComponents alloc] init] autorelease];
[rootComponents setYear: 1600];
[rootComponents setMonth: 1];
[rootComponents setDay: 1];
self.rootDate = [gregorian dateFromComponents: rootComponents];
self.offset = [[[NSDateComponents alloc] init] autorelease];

次に、後で整数を日付に変換するために、これを使用します。

[offset setDay: theLegacyDate];
id eventDate = [gregorian dateByAddingComponents: offset
                                          toDate: rootDate
                                         options: 0];

(オフセットの値を他の場所で変更することはありません。)

rootDate問題は、iOS と Mac OS X で異なる時刻を取得していることです。Mac OS X では、午前 0 時を取得しています。iOS では、8:12:28 を取得しています。(今のところ、これについては一貫しているようです。) 後で日数を追加すると、変な時間が残ります。

OS | OS | レガシー日付 | rootDate | 開催日
======== | ========== | ==========================|====================== ===
マック OS X | 143671 | 1600-01-01 00:00:00 -0800 | 1993-05-11 00:00:00 -0700
iOS | iOS | 143671 | 1600-01-01 08:12:28 +0000 | 1993-05-11 07:12:28 +0000

私の製品の以前のリリースでは、時間は気にしませんでした。今私がやります。iOS の奇妙な時間はなぜですか?どうすればよいですか? (時差はDSTだと思います。)

rootComponents の時、分、秒を 0 に設定しようとしましたが、影響はありません。0 以外に設定すると、8:12:28 に追加されます。これがうるう秒やその他の累積的な時計の変更と関係があるのか​​ どうか疑問に思っていました.

それとも、これは iOS で使用する完全に間違ったアプローチですか?

4

3 に答える 3

3

時間の問題を説明するうるう秒/累積クロックの変更については、あなたが正しいと思います。あなたが扱っている日付は実際には過去のものですか、それとも純粋に恣意的なエポックですか?

どちらの場合でも、現在にかなり近い新しいエポック (Cocoa エポックなど) を定義してみることができます。新しいエポックと古いエポックの間の日の差分を計算し、定数として保存します。日付を処理する必要がある場合は、このデルタを日付に適用し、既存の NSCalendar 手法を使用しますが、古いエポックではなく新しいエポックを使用します。これにより、発生しているクロック ドリフトの問題が回避されることを願っています。

于 2011-01-12T01:36:47.330 に答える
1

正しい答えは物事を単純化することのようです。rootDateを作成する代わりに、毎回コンポーネントから日付を作成します。これは遅くなることはなく、それでもコードをアイデアに非常に近づけることができます。

初期設定:

self.gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar
                    ] autorelease];
self.components = [[[NSDateComponents alloc] init] autorelease];
[components setYear: 1600];
[components setMonth: 1];

(明らかに、プロパティとivarは調整されます。)

後で、実際にレガシー日付をNSDate:に変換します。

[components setDay: 1 + theLegacyDate];
id eventDate = [gregorian dateFromComponents: components];

これには、次のような利点があります。

  1. ユーザー数が少なくなります。
  2. それはより少ないコードです。
  3. DSTが有効であるかどうかに関係なく、その日の午前0時に常に戻ります。
于 2011-01-12T01:49:21.687 に答える
0

iOS では、さまざまなタイム ゾーンの非常にあいまいなルールが考慮されることに注意してください。可能性が最も高いのは、1 月 1 日の真夜中です。あなたのタイムゾーンの 1600 は、実際には 7:12:28 UTC でした。人々が日付変換のバグについて不平を言った後、何年も前に奇妙なカレンダーの変更を行ったタイムゾーンに実際にいることに誰かが気づいたという多くのケースがありました.

最初に、データが表す正確な NSDate を確認する必要があります。タイムゾーンが必要なため、「1600 年 1 月 1 日からの日数」はナンセンスです。何をすべきか: 何日を表すことになっているかがわかっている「従来の」番号を見つけます。たとえば、143671 があなたのタイム ゾーンで 1993 年 5 月 11 日であることを「知っている」場合、その日付をルート日付として開始し、それに (x - 143671) 日を追加します。

于 2015-01-22T11:56:46.783 に答える