2017-01-10 14 views
2

私は次の好奇心に出くわしました: -米国のタイムゾーンの3文字の略語が夏時間に矛盾するのはなぜですか?

  • TimeZone.getTimeZoneは("Pacific Standard Time")夏時間を観察America/Los_Angeles、と等価としてみなし;
  • となりますが、夏時間の影響を受けないUTC-7と同等であると考えられます(("Mountain Standard Time"))。

これは、次のスニペットを証明することができる。

System.out.println(
    TimeZone.getTimeZone("MST").hasSameRules(TimeZone.getTimeZone("GMT-7"))); 
System.out.println(
    TimeZone.getTimeZone("PST").hasSameRules(TimeZone.getTimeZone("America/Los_Angeles"))); 

出力:

true 
true 

Ideone demo

そして、私たちは3文字の略称を使用してタイムゾーンを取得したことを証明することができます米国の4つの主要なタイムゾーンは夏時間の使用に矛盾しています:

for (String id : Arrays.asList("EST", "CST", "MST", "PST")) { 
    TimeZone tz = TimeZone.getTimeZone(id); 
    System.out.printf("%s is %s; observes DST: %s%n", 
     id, tz.getDisplayName(false, TimeZone.LONG), tz.useDaylightTime()); 
} 

出力:

EST is Eastern Standard Time; observes DST: false 
CST is Central Standard Time; observes DST: true 
MST is Mountain Standard Time; observes DST: false 
PST is Pacific Standard Time; observes DST: true 

Ideone demo

ほかに3文字の略語が最高とにかく回避されているという事実から、(Javadocは言う、 "しかし、その使用は推奨されていません...")これは非常に混乱しているようで、複数のタイムゾーンで夏時間の節約が期待されているかどうかは不明です。

この動作の違いには理由がありますか?この動作が予想されることを意味する米国のタイムゾーンの微妙な特性はありますか?

+0

私は、[Jon Skeet](http://stackoverflow.com/users/22656/jon-skeet)の質問と思います。 – Azodious

答えて

2

最初に言っておきたいことは:タイムゾーン識別子とタイムゾーン名の違いはです。通常、「MST」または「PST」はゾーン名を表しており、夏時間の状態ではないと解釈する必要があります(サフィックスST =標準時)

しかし、古いJavaバージョンでは、名前も識別子として、つまり、TimeZone.getTimeZone(...)のようなファクトリメソッドにパラメータとしてこれらの文字列を使用することができます。これは質問に私たちをリード:。有効な識別子は何である

ゾーンデータ(ルールの基本となるソース?このファイルの次のエントリは、MSTは識別子であるが、PST(PST8PDTではなく)であることを示しています。このファイルには次の項目が含まれています:

Zone EST  -5:00 - EST 
Zone MST  -7:00 - MST 
Zone HST  -10:00 - HST 
Zone EST5EDT  -5:00 US E%sT 
Zone CST6CDT  -6:00 US C%sT 
Zone MST7MDT  -7:00 US M%sT 
Zone PST8PDT  -8:00 US P%sT 

しかし、Javaはまだあまりにも、識別子として "PST" を使用しています - ハードワイヤード古いマッピング経由:

private static String[][] oldMappings = 
    { 
     { "ACT", "Australia/Darwin" }, 
     { "AET", "Australia/Sydney" }, 
     { "AGT", "America/Argentina/Buenos_Aires" }, 
     { "ART", "Africa/Cairo" }, 
     { "AST", "America/Anchorage" }, 
     { "BET", "America/Sao_Paulo" }, 
     { "BST", "Asia/Dhaka" }, 
     { "CAT", "Africa/Harare" }, 
     { "CNT", "America/St_Johns" }, 
     { "CST", "America/Chicago" }, 
     { "CTT", "Asia/Shanghai" }, 
     { "EAT", "Africa/Addis_Ababa" }, 
     { "ECT", "Europe/Paris" }, 
     { "IET", "America/Indiana/Indianapolis" }, 
     { "IST", "Asia/Kolkata" }, 
     { "JST", "Asia/Tokyo" }, 
     { "MIT", "Pacific/Apia" }, 
     { "NET", "Asia/Yerevan" }, 
     { "NST", "Pacific/Auckland" }, 
     { "PLT", "Asia/Karachi" }, 
     { "PNT", "America/Phoenix" }, 
     { "PRT", "America/Puerto_Rico" }, 
     { "PST", "America/Los_Angeles" }, 
     { "SST", "Pacific/Guadalcanal" }, 
     { "VST", "Asia/Ho_Chi_Minh" } 
    }; 

ただ、JDK-ファイルsun.util.calendar.ZoneInfoFileを調べます。したがって、「PST」はAmerica/Los_Angelesにマップされます。 "PST8PDT"はTZDBから追い越され、固定オフセットにマッピングされます。 "MST"はどうですか?ここでは、プロパティをどのように解釈するかを設定することができます。つまり、ブール値のシステムプロパティ "sun.timezone.ids.oldmapping"です。デフォルト値は "false"です。同じ上記のファイルZoneInfoFileは、システムプロパティの値に応じて、次のスイッチが含まれています

private static void addOldMapping() { 
     for (String[] arrayOfString1 : oldMappings) { 
     aliases.put(arrayOfString1[0], arrayOfString1[1]); 
     } 
     if (USE_OLDMAPPING) { 
     aliases.put("EST", "America/New_York"); 
     aliases.put("MST", "America/Denver"); 
     aliases.put("HST", "Pacific/Honolulu"); 
     } else { 
     zones.put("EST", new ZoneInfo("EST", -18000000)); 
     zones.put("MST", new ZoneInfo("MST", -25200000)); 
     zones.put("HST", new ZoneInfo("HST", -36000000)); 
     } 
} 

IBMもこのテーマについてan articleを書いています。これらの奇妙なことは、下位互換性のためだけであり、ユーザーは避けるべきです。

+0

ありがとう@メノ、それは本当に徹底的な答えです。 –

関連する問題