关于java:如何在JVM上解析时区字符串“Pacific Time(US&Canada)”?

How to parse time zone string “Pacific Time (US & Canada)” on JVM?

我正在编写与Yammer的集成,它返回一个如下所示的时区字符串:

1
Pacific Time (US & Canada)

如何将其解析为JVM上的TimeZone或DateTimeZone? 我已经尝试过TimeZone.getTimeZone和DateTimeZone.forID,但无济于事。


看起来Yammer在其REST API中返回timezone字段作为user对象的一部分。可以将示例视为响应正文中标记为"C.App Authentication"的部分中的授权文档的一部分,如下所示:

1
2
3
4
5
6
7
8
{
 "user":
  {
   "timezone":"Hawaii",
   "interests": null,
   "type":"user",

...

这也是从任何GET /users/... API返回的。通过实验,我可以看到API返回的值对应于用户帐户设置屏幕(位于https://yammer.com//account/display_options)中显示的下拉列表的键:

screenshot

查看此网页的来源时,您可以看到包含所有键和值的下拉列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<select id="meta_user_timezone" name="meta_user[timezone]"><option value="Hawaii">(GMT-10:00) Hawaii</option>
<option value="Alaska">(GMT-09:00) Alaska</option>
<option value="Pacific Time (US &amp; Canada)" selected="selected">(GMT-08:00) Pacific Time (US &amp; Canada)</option>
<option value="Arizona">(GMT-07:00) Arizona</option>
<option value="Mountain Time (US &amp; Canada)">(GMT-07:00) Mountain Time (US &amp; Canada)</option>
<option value="Central Time (US &amp; Canada)">(GMT-06:00) Central Time (US &amp; Canada)</option>
<option value="Eastern Time (US &amp; Canada)">(GMT-05:00) Eastern Time (US &amp; Canada)</option>
<option value="Indiana (East)">(GMT-05:00) Indiana (East)</option><option value="" disabled="disabled">-------------</option>
<option value="American Samoa">(GMT-11:00) American Samoa</option>
<option value="International Date Line West">(GMT-11:00) International Date Line West</option>
<option value="Midway Island">(GMT-11:00) Midway Island</option>
<option value="Tijuana">(GMT-08:00) Tijuana</option>
<option value="Chihuahua">(GMT-07:00) Chihuahua</option>
<option value="Mazatlan">(GMT-07:00) Mazatlan</option>
<option value="Central America">(GMT-06:00) Central America</option>
<option value="Guadalajara">(GMT-06:00) Guadalajara</option>
<option value="Mexico City">(GMT-06:00) Mexico City</option>
<option value="Monterrey">(GMT-06:00) Monterrey</option>
<option value="Saskatchewan">(GMT-06:00) Saskatchewan</option>
<option value="Bogota">(GMT-05:00) Bogota</option>
<option value="Lima">(GMT-05:00) Lima</option>
<option value="Quito">(GMT-05:00) Quito</option>
<option value="Caracas">(GMT-04:30) Caracas</option>
<option value="Atlantic Time (Canada)">(GMT-04:00) Atlantic Time (Canada)</option>
<option value="Georgetown">(GMT-04:00) Georgetown</option>
<option value="La Paz">(GMT-04:00) La Paz</option>
<option value="Newfoundland">(GMT-03:30) Newfoundland</option>
<option value="Brasilia">(GMT-03:00) Brasilia</option>
<option value="Buenos Aires">(GMT-03:00) Buenos Aires</option>
<option value="Greenland">(GMT-03:00) Greenland</option>
<option value="Santiago">(GMT-03:00) Santiago</option>
<option value="Mid-Atlantic">(GMT-02:00) Mid-Atlantic</option>
<option value="Azores">(GMT-01:00) Azores</option>
<option value="Cape Verde Is.">(GMT-01:00) Cape Verde Is.</option>
<option value="Casablanca">(GMT+00:00) Casablanca</option>
<option value="Dublin">(GMT+00:00) Dublin</option>
<option value="Edinburgh">(GMT+00:00) Edinburgh</option>
<option value="Lisbon">(GMT+00:00) Lisbon</option>
<option value="London">(GMT+00:00) London</option>
<option value="Monrovia">(GMT+00:00) Monrovia</option>
<option value="UTC">(GMT+00:00) UTC</option>
<option value="Amsterdam">(GMT+01:00) Amsterdam</option>
<option value="Belgrade">(GMT+01:00) Belgrade</option>
<option value="Berlin">(GMT+01:00) Berlin</option>
<option value="Bern">(GMT+01:00) Bern</option>
<option value="Bratislava">(GMT+01:00) Bratislava</option>
<option value="Brussels">(GMT+01:00) Brussels</option>
<option value="Budapest">(GMT+01:00) Budapest</option>
<option value="Copenhagen">(GMT+01:00) Copenhagen</option>
<option value="Ljubljana">(GMT+01:00) Ljubljana</option>
<option value="Madrid">(GMT+01:00) Madrid</option>
<option value="Paris">(GMT+01:00) Paris</option>
<option value="Prague">(GMT+01:00) Prague</option>
<option value="Rome">(GMT+01:00) Rome</option>
<option value="Sarajevo">(GMT+01:00) Sarajevo</option>
<option value="Skopje">(GMT+01:00) Skopje</option>
<option value="Stockholm">(GMT+01:00) Stockholm</option>
<option value="Vienna">(GMT+01:00) Vienna</option>
<option value="Warsaw">(GMT+01:00) Warsaw</option>
<option value="West Central Africa">(GMT+01:00) West Central Africa</option>
<option value="Zagreb">(GMT+01:00) Zagreb</option>
<option value="Athens">(GMT+02:00) Athens</option>
<option value="Bucharest">(GMT+02:00) Bucharest</option>
<option value="Cairo">(GMT+02:00) Cairo</option>
<option value="Harare">(GMT+02:00) Harare</option>
<option value="Helsinki">(GMT+02:00) Helsinki</option>
<option value="Istanbul">(GMT+02:00) Istanbul</option>
<option value="Jerusalem">(GMT+02:00) Jerusalem</option>
<option value="Kyiv">(GMT+02:00) Kyiv</option>
<option value="Pretoria">(GMT+02:00) Pretoria</option>
<option value="Riga">(GMT+02:00) Riga</option>
<option value="Sofia">(GMT+02:00) Sofia</option>
<option value="Tallinn">(GMT+02:00) Tallinn</option>
<option value="Vilnius">(GMT+02:00) Vilnius</option>
<option value="Baghdad">(GMT+03:00) Baghdad</option>
<option value="Kuwait">(GMT+03:00) Kuwait</option>
<option value="Minsk">(GMT+03:00) Minsk</option>
<option value="Moscow">(GMT+03:00) Moscow</option>
<option value="Nairobi">(GMT+03:00) Nairobi</option>
<option value="Riyadh">(GMT+03:00) Riyadh</option>
<option value="St. Petersburg">(GMT+03:00) St. Petersburg</option>
<option value="Volgograd">(GMT+03:00) Volgograd</option>
<option value="Tehran">(GMT+03:30) Tehran</option>
<option value="Abu Dhabi">(GMT+04:00) Abu Dhabi</option>
<option value="Baku">(GMT+04:00) Baku</option>
<option value="Muscat">(GMT+04:00) Muscat</option>
<option value="Tbilisi">(GMT+04:00) Tbilisi</option>
<option value="Yerevan">(GMT+04:00) Yerevan</option>
<option value="Kabul">(GMT+04:30) Kabul</option>
<option value="Ekaterinburg">(GMT+05:00) Ekaterinburg</option>
<option value="Islamabad">(GMT+05:00) Islamabad</option>
<option value="Karachi">(GMT+05:00) Karachi</option>
<option value="Tashkent">(GMT+05:00) Tashkent</option>
<option value="Chennai">(GMT+05:30) Chennai</option>
<option value="Kolkata">(GMT+05:30) Kolkata</option>
<option value="Mumbai">(GMT+05:30) Mumbai</option>
<option value="New Delhi">(GMT+05:30) New Delhi</option>
<option value="Sri Jayawardenepura">(GMT+05:30) Sri Jayawardenepura</option>
<option value="Kathmandu">(GMT+05:45) Kathmandu</option>
<option value="Almaty">(GMT+06:00) Almaty</option>
<option value="Astana">(GMT+06:00) Astana</option>
<option value="Dhaka">(GMT+06:00) Dhaka</option>
<option value="Novosibirsk">(GMT+06:00) Novosibirsk</option>
<option value="Urumqi">(GMT+06:00) Urumqi</option>
<option value="Rangoon">(GMT+06:30) Rangoon</option>
<option value="Bangkok">(GMT+07:00) Bangkok</option>
<option value="Hanoi">(GMT+07:00) Hanoi</option>
<option value="Jakarta">(GMT+07:00) Jakarta</option>
<option value="Krasnoyarsk">(GMT+07:00) Krasnoyarsk</option>
<option value="Beijing">(GMT+08:00) Beijing</option>
<option value="Chongqing">(GMT+08:00) Chongqing</option>
<option value="Hong Kong">(GMT+08:00) Hong Kong</option>
<option value="Irkutsk">(GMT+08:00) Irkutsk</option>
<option value="Kuala Lumpur">(GMT+08:00) Kuala Lumpur</option>
<option value="Perth">(GMT+08:00) Perth</option>
<option value="Singapore">(GMT+08:00) Singapore</option>
<option value="Taipei">(GMT+08:00) Taipei</option>
<option value="Ulaan Bataar">(GMT+08:00) Ulaan Bataar</option>
<option value="Osaka">(GMT+09:00) Osaka</option>
<option value="Sapporo">(GMT+09:00) Sapporo</option>
<option value="Seoul">(GMT+09:00) Seoul</option>
<option value="Tokyo">(GMT+09:00) Tokyo</option>
<option value="Yakutsk">(GMT+09:00) Yakutsk</option>
<option value="Adelaide">(GMT+09:30) Adelaide</option>
<option value="Darwin">(GMT+09:30) Darwin</option>
<option value="Brisbane">(GMT+10:00) Brisbane</option>
<option value="Canberra">(GMT+10:00) Canberra</option>
<option value="Guam">(GMT+10:00) Guam</option>
<option value="Hobart">(GMT+10:00) Hobart</option>
<option value="Magadan">(GMT+10:00) Magadan</option>
<option value="Melbourne">(GMT+10:00) Melbourne</option>
<option value="Port Moresby">(GMT+10:00) Port Moresby</option>
<option value="Solomon Is.">(GMT+10:00) Solomon Is.</option>
<option value="Sydney">(GMT+10:00) Sydney</option>
<option value="Vladivostok">(GMT+10:00) Vladivostok</option>
<option value="New Caledonia">(GMT+11:00) New Caledonia</option>
<option value="Auckland">(GMT+12:00) Auckland</option>
<option value="Fiji">(GMT+12:00) Fiji</option>
<option value="Kamchatka">(GMT+12:00) Kamchatka</option>
<option value="Marshall Is.">(GMT+12:00) Marshall Is.</option>
<option value="Wellington">(GMT+12:00) Wellington</option>
<option value="Nuku&#x27;alofa">(GMT+13:00) Nuku&#x27;alofa</option>
<option value="Samoa">(GMT+13:00) Samoa</option>
<option value="Tokelau Is.">(GMT+13:00) Tokelau Is.</option></select>

问题是如何翻译这些?好吧,我没有任何硬性证据,但看起来这些时区键都是Windows时区显示名称的部分位。它们不是Windows或任何Microsoft技术中的不同标识符。我很困惑为什么Yammer会选择这些作为时区ID。但你的方式如下:

  • 查看CLDR Windows Zone映射文件。你会看到如下条目:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!--  (UTC-08:00) Pacific Time (US & Canada)  -->
    <mapZone other="Pacific Standard Time" territory="001" type="America/Los_Angeles"/>
    <mapZone other="Pacific Standard Time" territory="CA" type="America/Vancouver America/Dawson America/Whitehorse"/>
    <mapZone other="Pacific Standard Time" territory="MX" type="America/Tijuana"/>
    <mapZone other="Pacific Standard Time" territory="US" type="America/Los_Angeles"/>
    <mapZone other="Pacific Standard Time" territory="ZZ" type="PST8PDT"/>
    <!--  (UTC-07:00) Arizona  -->
    <mapZone other="US Mountain Standard Time" territory="001" type="America/Phoenix"/>
    <mapZone other="US Mountain Standard Time" territory="CA" type="America/Dawson_Creek America/Creston"/>
    <mapZone other="US Mountain Standard Time" territory="MX" type="America/Hermosillo"/>
    <mapZone other="US Mountain Standard Time" territory="US" type="America/Phoenix"/>
    <mapZone other="US Mountain Standard Time" territory="ZZ" type="Etc/GMT+7"/>
    <!--  (UTC-07:00) Chihuahua, La Paz, Mazatlan  -->
    <mapZone other="Mountain Standard Time (Mexico)" territory="001" type="America/Chihuahua"/>
    <mapZone other="Mountain Standard Time (Mexico)" territory="MX" type="America/Chihuahua America/Mazatlan"/>
  • 在注释行中搜索Yammer时区键,作为部分子字符串匹配。例如,如果Yammer时区"La Paz",它将与注释的条目匹配

  • 从评论后的下一行获取IANA时区ID。它将是标有territory="001"的那个。你想要type字段。对于前面的示例,这将是"America/Chihuahua"

  • 您可以在Java中使用任何标准Java 7或Java 8 API(或使用Joda Time)。

最后一点。我检查了(通过用户API)我自己的Yammer网络中许多人的timezone设置,我知道他在其他时区,并且只有少数人从"Pacific Time (US & Canada)"默认设置更改了他们的时区。因此,我怀疑这些价值观是否准确。据我所知,没有什么可以迫使Yammer用户从默认设置更改此设置,他们必须尽力去做。


这看起来很熟悉Ruby on Rails时间API,它使用"友好"的时区名称而不是标准的"America / Los_Angeles"。正如另一个答案中所建议的那样,实际上可能是Windows名称。

这使我开始讨论Java中的TimeZones,并从那里开始讨论为Java程序提供这些Windows名称的Github存储库。

看起来您将不得不将日期时间内的东西包装在您自己借用或编写的翻译层中。


如果Yammer为您提供一个时区偏移,您可能会更好。据我所知,Yammer给你的时区字符串不正确(或者至少是微软特有的)。如果您执行此Java代码:

1
System.out.println(Arrays.toString(TimeZone.getAvailableIDs()));

你会发现字符串Pacific Time (US & Canada)没有出现在其中,因为它(我认为)是一个微软风格的时区名称,并且由于只有他们自己知道的原因,微软决定以不同的方式命名它们。