42

これを iOS6 で実行してみてください (iOS6 より前のテストは行っていません):

NSDateFormatter *julianDayDateFormatter = nil;
julianDayDateFormatter = [[NSDateFormatter alloc] init];
[julianDayDateFormatter setDateFormat:@"g"];

for (NSString *timeZone in [NSTimeZone knownTimeZoneNames]) {
    julianDayDateFormatter.timeZone = [NSTimeZone timeZoneWithName: timeZone];
    NSDate *date = [julianDayDateFormatter dateFromString:[NSString stringWithFormat:@"%d", 2475213]];
    if (date == nil)
        NSLog(@"timeZone = %@", timeZone);
}

次の出力が得られます。

America/Bahia
America/Campo_Grande
America/Cuiaba
America/Sao_Paulo

NSDateFormatter をユリウス日番号に設定して、これら 4 つのタイム ゾーンがこのように動作する理由を説明できる人はいますか? 他のすべてのタイムゾーンでは、NSDateFormatter は実際の NSDates を返します。

4

2 に答える 2

61

疑いがあります。単なる疑いですが、かなり強いものです。

その値は 2064 年 10 月 19 日を表します。ブラジルのタイム ゾーンでは、現地の午前 0時から始まる夏時間が適用されます。この時間に時計が進むため、午前 0 時自体は存在しません。10 月 19 日はその移行の 1 つです。

これは、私の .NET 日付/時刻 API である Noda Time を使用したサンプル コードです。認識しているすべてのタイム ゾーンの 1 日の始まりが実際に真夜中かどうかをチェックします。

using System;
using NodaTime;

class Test
{
    static void Main()
    {
        var localDate = new LocalDate(2064, 10, 19);
        var provider = DateTimeZoneProviders.Tzdb;
        foreach (var id in provider.Ids)
        {
            var zone = provider[id];
            var startOfDay = zone.AtStartOfDay(localDate).LocalDateTime.TimeOfDay;
            if (startOfDay != LocalTime.Midnight)
            {
                Console.WriteLine(id);
            }
        }
    }
}

これにより、非常によく似たリストが生成されます。

America/Bahia
America/Campo_Grande
America/Cuiaba
America/Sao_Paulo
Brazil/East

Brazil/East は、America/Sao_Paolo のエイリアスである可能性があると思われます。そのため、リストに含まれていません。

とにかく、ユリウス日の問題に戻るために-フォーマッタは常にNSDate *ローカルの真夜中の を返したいと思っていると思います。これらのタイム ゾーンでは 2064 年 10 月 19 日には存在しません。したがって、nil を返します。個人的には、代わりに午前 1 時の値を返すことをお勧めしますが、ねえ...

于 2012-10-16T20:29:02.557 に答える
16

私を正しい道に導いてくれた Jon Skeet に感謝します。ただし、iOS のコンテキストで彼の答えを明確にしたいだけです。

NSDateFormatter にユリウス日を NSDate に変換するように依頼する場合、解析する文字列に整数のみを指定できます (通常は、1 日の時間/分/秒の小数部分を指定できます)。Apple はユリウス日を真夜中に区切るため (天文学の正午とは対照的に、ここで詳細をお読みください: http://www.unicode.org/reports/tr35/#Date_Field_Symbol_Table )、いくつかの真夜中は単に存在しません (指摘してくれてありがとう) @JonSkeet) NSDateFormatter は、その特定の時点がそのタイム ゾーンに存在しないことを識別し、nil を返します。

記録として、iOS5 はこのように動作しません。Jon Skeet に同意します。NSDateFormatter は、nil ではなく DST に合わせて調整された NSDate を返す必要があります。その特定のユリウス日が実際に存在するからです! Appleにバグを報告しました。

于 2012-10-17T09:01:31.440 に答える