libgweather r300 - in trunk: . data libgweather
- From: danw svn gnome org
- To: svn-commits-list gnome org
- Subject: libgweather r300 - in trunk: . data libgweather
- Date: Mon, 4 Aug 2008 12:04:12 +0000 (UTC)
Author: danw
Date: Mon Aug 4 12:04:12 2008
New Revision: 300
URL: http://svn.gnome.org/viewvc/libgweather?rev=300&view=rev
Log:
* data/Locations.xml.in:
* data/locations.dtd: add information about timezones
* libgweather/parser.c: new Locations.xml.in parser
* libgweather/gweather-location.c: opaque replacement for
WeatherLocation, based on the new parser
* libgweather/location-entry.c: Autocompleting location-selecting
entry
* libgweather/gweather-timezone.c: type representing a timezone
* libgweather/timezone-menu.c: New widget for selecting
a (localized) timezone.
* libgweather/gweather-xml.c: use the new parser internally (but
convert to WeatherLocation externally)
Added:
trunk/libgweather/gweather-location.c
trunk/libgweather/gweather-location.h
trunk/libgweather/gweather-timezone.c
trunk/libgweather/gweather-timezone.h
trunk/libgweather/location-entry.c
trunk/libgweather/location-entry.h
trunk/libgweather/parser.c
trunk/libgweather/parser.h
trunk/libgweather/test_locations.c
trunk/libgweather/timezone-menu.c
trunk/libgweather/timezone-menu.h
Modified:
trunk/ChangeLog
trunk/data/Locations.xml.in
trunk/data/locations.dtd
trunk/libgweather/ (props changed)
trunk/libgweather/Makefile.am
trunk/libgweather/gweather-xml.c
trunk/libgweather/weather-priv.h
trunk/libgweather/weather.h
Modified: trunk/data/Locations.xml.in
==============================================================================
--- trunk/data/Locations.xml.in (original)
+++ trunk/data/Locations.xml.in Mon Aug 4 12:04:12 2008
@@ -12,6 +12,9 @@
-->
<iso-code>DZ</iso-code>
<fips-code>AG</fips-code>
+ <timezones>
+ <timezone id="Africa/Algiers" />
+ </timezones>
<tz-hint>Africa/Algiers</tz-hint>
<city>
<!-- Translators: this is a city in Algeria -->
@@ -373,6 +376,9 @@
-->
<iso-code>AO</iso-code>
<fips-code>AO</fips-code>
+ <timezones>
+ <timezone id="Africa/Luanda" />
+ </timezones>
<tz-hint>Africa/Luanda</tz-hint>
<city>
<!-- Translators: this is the capital of Angola -->
@@ -395,6 +401,9 @@
-->
<iso-code>BJ</iso-code>
<fips-code>BN</fips-code>
+ <timezones>
+ <timezone id="Africa/Porto-Novo" />
+ </timezones>
<tz-hint>Africa/Porto-Novo</tz-hint>
<city>
<!-- Translators: this is a city in Benin -->
@@ -436,6 +445,9 @@
-->
<iso-code>BW</iso-code>
<fips-code>BC</fips-code>
+ <timezones>
+ <timezone id="Africa/Gaborone" />
+ </timezones>
<tz-hint>Africa/Gaborone</tz-hint>
<city>
<!-- Translators: this is a city in Botswana -->
@@ -562,6 +574,9 @@
-->
<iso-code>BF</iso-code>
<fips-code>UV</fips-code>
+ <timezones>
+ <timezone id="Africa/Ouagadougou" />
+ </timezones>
<tz-hint>Africa/Ouagadougou</tz-hint>
<city>
<!-- Translators: this is a city in Burkina Faso -->
@@ -614,6 +629,9 @@
-->
<iso-code>BI</iso-code>
<fips-code>BY</fips-code>
+ <timezones>
+ <timezone id="Africa/Bujumbura" />
+ </timezones>
<tz-hint>Africa/Bujumbura</tz-hint>
<city>
<!-- Translators: this is a city in Burundi -->
@@ -659,6 +677,9 @@
-->
<iso-code>CM</iso-code>
<fips-code>CM</fips-code>
+ <timezones>
+ <timezone id="Africa/Douala" />
+ </timezones>
<tz-hint>Africa/Douala</tz-hint>
<city>
<!-- Translators: this is a city in Cameroon -->
@@ -714,6 +735,9 @@
-->
<iso-code>CV</iso-code>
<fips-code>CV</fips-code>
+ <timezones>
+ <timezone id="Atlantic/Cape_Verde" />
+ </timezones>
<tz-hint>Atlantic/Cape_Verde</tz-hint>
<city>
<!-- Translators: this is a city in Cape Verde -->
@@ -736,6 +760,9 @@
-->
<iso-code>CF</iso-code>
<fips-code>CT</fips-code>
+ <timezones>
+ <timezone id="Africa/Bangui" />
+ </timezones>
<tz-hint>Africa/Bangui</tz-hint>
<city>
<!-- Translators: this is a city in Central African Republic -->
@@ -790,6 +817,9 @@
-->
<iso-code>TD</iso-code>
<fips-code>CD</fips-code>
+ <timezones>
+ <timezone id="Africa/Ndjamena" />
+ </timezones>
<tz-hint>Africa/Ndjamena</tz-hint>
<city>
<!-- Translators: this is a city in Chad -->
@@ -827,6 +857,9 @@
<_name>Comoros</_name>
<iso-code>KM</iso-code>
<fips-code>CN</fips-code>
+ <timezones>
+ <timezone id="Indian/Comoro" />
+ </timezones>
<tz-hint>Indian/Comoro</tz-hint>
<city>
<!-- Translators: this is a city in Comoros -->
@@ -859,6 +892,26 @@
-->
<iso-code>CD</iso-code>
<fips-code>CG</fips-code>
+ <timezones>
+ <timezone id="Africa/Kinshasa">
+ <!-- Translators: This is the time zone used in the western
+ half of the Democratic Republic of the Congo. The
+ string is only used in places where "Democratic
+ Republic of the Congo" is already clear from context.
+ FIXME: is there an official name for this zone?
+ -->
+ <_name>Western Congo</_name>
+ </timezone>
+ <timezone id="Africa/Lubumbashi">
+ <!-- Translators: This is the time zone used in the eastern
+ half of the Democratic Republic of the Congo. The
+ string is only used in places where "Democratic
+ Republic of the Congo" is already clear from context.
+ FIXME: is there an official name for this zone?
+ -->
+ <_name>Eastern Congo</_name>
+ </timezone>
+ </timezones>
<city>
<!-- Translators: this is the capital of Congo, Democratic
Republic of the
@@ -899,6 +952,9 @@
-->
<iso-code>CG</iso-code>
<fips-code>CF</fips-code>
+ <timezones>
+ <timezone id="Africa/Brazzaville" />
+ </timezones>
<tz-hint>Africa/Brazzaville</tz-hint>
<city>
<!-- Translators: this is the capital of Congo, Republic of the -->
@@ -932,6 +988,9 @@
-->
<iso-code>CI</iso-code>
<fips-code>IV</fips-code>
+ <timezones>
+ <timezone id="Africa/Abidjan" />
+ </timezones>
<tz-hint>Africa/Abidjan</tz-hint>
<city>
<!-- Translators: this is a city in CÃte d'Ivoire -->
@@ -953,6 +1012,9 @@
-->
<iso-code>DJ</iso-code>
<fips-code>DJ</fips-code>
+ <timezones>
+ <timezone id="Africa/Djibouti" />
+ </timezones>
<tz-hint>Africa/Djibouti</tz-hint>
<city>
<!-- Translators: this is a city in Djibouti -->
@@ -1014,6 +1076,9 @@
-->
<iso-code>EG</iso-code>
<fips-code>EG</fips-code>
+ <timezones>
+ <timezone id="Africa/Cairo" />
+ </timezones>
<tz-hint>Africa/Cairo</tz-hint>
<city>
<!-- Translators: this is a city in Egypt -->
@@ -1153,6 +1218,9 @@
-->
<iso-code>GQ</iso-code>
<fips-code>EK</fips-code>
+ <timezones>
+ <timezone id="Africa/Malabo" />
+ </timezones>
<tz-hint>Africa/Malabo</tz-hint>
<city>
<!-- Translators: this is a city in Equatorial Guinea -->
@@ -1184,6 +1252,9 @@
-->
<iso-code>ER</iso-code>
<fips-code>ER</fips-code>
+ <timezones>
+ <timezone id="Africa/Asmara" />
+ </timezones>
<tz-hint>Africa/Asmara</tz-hint>
</country>
<country>
@@ -1195,6 +1266,9 @@
-->
<iso-code>ET</iso-code>
<fips-code>ET</fips-code>
+ <timezones>
+ <timezone id="Africa/Addis_Ababa" />
+ </timezones>
<tz-hint>Africa/Addis_Ababa</tz-hint>
</country>
<country>
@@ -1206,6 +1280,9 @@
<_name>French Southern Territories</_name>
<iso-code>TF</iso-code>
<fips-code>FS</fips-code>
+ <timezones>
+ <timezone id="Indian/Kerguelen" />
+ </timezones>
<tz-hint>Indian/Kerguelen</tz-hint>
</country>
<country>
@@ -1217,6 +1294,9 @@
-->
<iso-code>GA</iso-code>
<fips-code>GB</fips-code>
+ <timezones>
+ <timezone id="Africa/Libreville" />
+ </timezones>
<tz-hint>Africa/Libreville</tz-hint>
<city>
<!-- Translators: this is a city in Gabon -->
@@ -1258,6 +1338,9 @@
-->
<iso-code>GM</iso-code>
<fips-code>GA</fips-code>
+ <timezones>
+ <timezone id="Africa/Banjul" />
+ </timezones>
<tz-hint>Africa/Banjul</tz-hint>
<city>
<!-- Translators: this is the capital of Gambia -->
@@ -1300,6 +1383,9 @@
-->
<iso-code>GH</iso-code>
<fips-code>GH</fips-code>
+ <timezones>
+ <timezone id="Africa/Accra" />
+ </timezones>
<tz-hint>Africa/Accra</tz-hint>
<city>
<!-- Translators: this is the capital of Ghana -->
@@ -1325,6 +1411,9 @@
-->
<iso-code>GN</iso-code>
<fips-code>GV</fips-code>
+ <timezones>
+ <timezone id="Africa/Conakry" />
+ </timezones>
<tz-hint>Africa/Conakry</tz-hint>
<city>
<!-- Translators: this is the capital of Guinea -->
@@ -1366,6 +1455,9 @@
-->
<iso-code>GW</iso-code>
<fips-code>PU</fips-code>
+ <timezones>
+ <timezone id="Africa/Bissau" />
+ </timezones>
<tz-hint>Africa/Bissau</tz-hint>
<city>
<!-- Translators: this is a city in Guinea-Bissau -->
@@ -1387,6 +1479,9 @@
-->
<iso-code>KE</iso-code>
<fips-code>KE</fips-code>
+ <timezones>
+ <timezone id="Africa/Nairobi" />
+ </timezones>
<tz-hint>Africa/Nairobi</tz-hint>
<city>
<!-- Translators: this is a city in Kenya -->
@@ -1449,6 +1544,9 @@
-->
<iso-code>LS</iso-code>
<fips-code>LT</fips-code>
+ <timezones>
+ <timezone id="Africa/Maseru" />
+ </timezones>
<tz-hint>Africa/Maseru</tz-hint>
</country>
<country>
@@ -1462,6 +1560,9 @@
-->
<iso-code>LR</iso-code>
<fips-code>LI</fips-code>
+ <timezones>
+ <timezone id="Africa/Monrovia" />
+ </timezones>
<tz-hint>Africa/Monrovia</tz-hint>
</country>
<country>
@@ -1473,6 +1574,9 @@
-->
<iso-code>LY</iso-code>
<fips-code>LY</fips-code>
+ <timezones>
+ <timezone id="Africa/Tripoli" />
+ </timezones>
<tz-hint>Africa/Tripoli</tz-hint>
<city>
<!-- Translators: this is a city in Libya -->
@@ -1517,6 +1621,9 @@
-->
<iso-code>MG</iso-code>
<fips-code>MA</fips-code>
+ <timezones>
+ <timezone id="Indian/Antananarivo" />
+ </timezones>
<tz-hint>Indian/Antananarivo</tz-hint>
<city>
<!-- Translators: this is a city in Madagascar -->
@@ -1602,6 +1709,9 @@
-->
<iso-code>MW</iso-code>
<fips-code>MI</fips-code>
+ <timezones>
+ <timezone id="Africa/Blantyre" />
+ </timezones>
<tz-hint>Africa/Blantyre</tz-hint>
</country>
<country>
@@ -1614,6 +1724,9 @@
-->
<iso-code>ML</iso-code>
<fips-code>ML</fips-code>
+ <timezones>
+ <timezone id="Africa/Bamako" />
+ </timezones>
<tz-hint>Africa/Bamako</tz-hint>
</country>
<country>
@@ -1626,6 +1739,9 @@
-->
<iso-code>MR</iso-code>
<fips-code>MR</fips-code>
+ <timezones>
+ <timezone id="Africa/Nouakchott" />
+ </timezones>
<tz-hint>Africa/Nouakchott</tz-hint>
<city>
<!-- Translators: this is a city in Mauritania -->
@@ -1653,6 +1769,9 @@
<_name>Mauritius</_name>
<iso-code>MU</iso-code>
<fips-code>MP</fips-code>
+ <timezones>
+ <timezone id="Indian/Mauritius" />
+ </timezones>
<tz-hint>Indian/Mauritius</tz-hint>
<city>
<!-- Translators: this is a city in Mauritius -->
@@ -1690,6 +1809,9 @@
<_name>Mayotte</_name>
<iso-code>YT</iso-code>
<fips-code>MF</fips-code>
+ <timezones>
+ <timezone id="Indian/Mayotte" />
+ </timezones>
<tz-hint>Indian/Mayotte</tz-hint>
<city>
<!-- Translators: this is a city in Mayotte -->
@@ -1720,6 +1842,9 @@
-->
<iso-code>MA</iso-code>
<fips-code>MO</fips-code>
+ <timezones>
+ <timezone id="Africa/Casablanca" />
+ </timezones>
<tz-hint>Africa/Casablanca</tz-hint>
<city>
<!-- Translators: this is a city in Morocco -->
@@ -1864,6 +1989,9 @@
-->
<iso-code>MZ</iso-code>
<fips-code>MZ</fips-code>
+ <timezones>
+ <timezone id="Africa/Maputo" />
+ </timezones>
<tz-hint>Africa/Maputo</tz-hint>
<city>
<!-- Translators: this is a city in Mozambique -->
@@ -1975,6 +2103,9 @@
-->
<iso-code>NA</iso-code>
<fips-code>WA</fips-code>
+ <timezones>
+ <timezone id="Africa/Windhoek" />
+ </timezones>
<tz-hint>Africa/Windhoek</tz-hint>
<city>
<!-- Translators: this is a city in Namibia -->
@@ -2006,6 +2137,9 @@
-->
<iso-code>NE</iso-code>
<fips-code>NG</fips-code>
+ <timezones>
+ <timezone id="Africa/Niamey" />
+ </timezones>
<tz-hint>Africa/Niamey</tz-hint>
<city>
<!-- Translators: this is a city in Niger -->
@@ -2055,6 +2189,9 @@
-->
<iso-code>NG</iso-code>
<fips-code>NI</fips-code>
+ <timezones>
+ <timezone id="Africa/Lagos" />
+ </timezones>
<tz-hint>Africa/Lagos</tz-hint>
<city>
<!-- Translators: this is a city in Nigeria -->
@@ -2137,6 +2274,9 @@
-->
<iso-code>RW</iso-code>
<fips-code>RW</fips-code>
+ <timezones>
+ <timezone id="Africa/Kigali" />
+ </timezones>
<tz-hint>Africa/Kigali</tz-hint>
<city>
<!-- Translators: this is a city in Rwanda -->
@@ -2166,6 +2306,9 @@
<_name>RÃunion</_name>
<iso-code>RE</iso-code>
<fips-code>RE</fips-code>
+ <timezones>
+ <timezone id="Indian/Reunion" />
+ </timezones>
<tz-hint>Indian/Reunion</tz-hint>
<city>
<!-- Translators: this is a city in RÃunion -->
@@ -2210,6 +2353,9 @@
-->
<iso-code>ST</iso-code>
<fips-code>TP</fips-code>
+ <timezones>
+ <timezone id="Africa/Sao_Tome" />
+ </timezones>
<tz-hint>Africa/Sao_Tome</tz-hint>
</country>
<country>
@@ -2221,6 +2367,9 @@
-->
<iso-code>SN</iso-code>
<fips-code>SG</fips-code>
+ <timezones>
+ <timezone id="Africa/Dakar" />
+ </timezones>
<tz-hint>Africa/Dakar</tz-hint>
<city>
<!-- Translators: this is a city in Senegal -->
@@ -2298,6 +2447,9 @@
<_name>Seychelles</_name>
<iso-code>SC</iso-code>
<fips-code>SE</fips-code>
+ <timezones>
+ <timezone id="Indian/Mahe" />
+ </timezones>
<tz-hint>Indian/Mahe</tz-hint>
<city>
<!-- Translators: this is a city in Seychelles -->
@@ -2329,6 +2481,9 @@
-->
<iso-code>SL</iso-code>
<fips-code>SL</fips-code>
+ <timezones>
+ <timezone id="Africa/Freetown" />
+ </timezones>
<tz-hint>Africa/Freetown</tz-hint>
<city>
<!-- Translators: this is the capital of Sierra Leone -->
@@ -2361,6 +2516,9 @@
-->
<iso-code>SO</iso-code>
<fips-code>SO</fips-code>
+ <timezones>
+ <timezone id="Africa/Mogadishu" />
+ </timezones>
<tz-hint>Africa/Mogadishu</tz-hint>
</country>
<country>
@@ -2377,6 +2535,9 @@
-->
<iso-code>ZA</iso-code>
<fips-code>SF</fips-code>
+ <timezones>
+ <timezone id="Africa/Johannesburg" />
+ </timezones>
<tz-hint>Africa/Johannesburg</tz-hint>
<city>
<!-- Translators: this is a city in South Africa -->
@@ -2526,6 +2687,9 @@
-->
<iso-code>SD</iso-code>
<fips-code>SU</fips-code>
+ <timezones>
+ <timezone id="Africa/Khartoum" />
+ </timezones>
<tz-hint>Africa/Khartoum</tz-hint>
<city>
<!-- Translators: this is the capital of Sudan.
@@ -2554,6 +2718,9 @@
-->
<iso-code>SZ</iso-code>
<fips-code>WZ</fips-code>
+ <timezones>
+ <timezone id="Africa/Mbabane" />
+ </timezones>
<tz-hint>Africa/Mbabane</tz-hint>
<city>
<!-- Translators: this is a city in Swaziland -->
@@ -2610,6 +2777,9 @@
-->
<iso-code>TZ</iso-code>
<fips-code>TZ</fips-code>
+ <timezones>
+ <timezone id="Africa/Dar_es_Salaam" />
+ </timezones>
<tz-hint>Africa/Dar_es_Salaam</tz-hint>
<city>
<!-- Translators: this is a city in Tanzania -->
@@ -2801,6 +2971,9 @@
-->
<iso-code>TG</iso-code>
<fips-code>TO</fips-code>
+ <timezones>
+ <timezone id="Africa/Lome" />
+ </timezones>
<tz-hint>Africa/Lome</tz-hint>
<city>
<!-- Translators: this is a city in Togo -->
@@ -2838,6 +3011,9 @@
<_name>Tunisia</_name>
<iso-code>TN</iso-code>
<fips-code>TS</fips-code>
+ <timezones>
+ <timezone id="Africa/Tunis" />
+ </timezones>
<tz-hint>Africa/Tunis</tz-hint>
<city>
<!-- Translators: this is a city in Tunisia -->
@@ -2993,6 +3169,9 @@
-->
<iso-code>UG</iso-code>
<fips-code>UG</fips-code>
+ <timezones>
+ <timezone id="Africa/Kampala" />
+ </timezones>
<tz-hint>Africa/Kampala</tz-hint>
<city>
<!-- Translators: this is a city in Uganda -->
@@ -3280,6 +3459,9 @@
<_name>Western Sahara</_name>
<iso-code>EH</iso-code>
<fips-code>WI</fips-code>
+ <timezones>
+ <timezone id="Africa/El_Aaiun" />
+ </timezones>
<tz-hint>Africa/El_Aaiun</tz-hint>
</country>
<country>
@@ -3292,6 +3474,9 @@
-->
<iso-code>ZM</iso-code>
<fips-code>ZA</fips-code>
+ <timezones>
+ <timezone id="Africa/Lusaka" />
+ </timezones>
<tz-hint>Africa/Lusaka</tz-hint>
<city>
<!-- Translators: this is the capital of Zambia -->
@@ -3309,6 +3494,9 @@
<_name>Zimbabwe</_name>
<iso-code>ZW</iso-code>
<fips-code>ZI</fips-code>
+ <timezones>
+ <timezone id="Africa/Harare" />
+ </timezones>
<tz-hint>Africa/Harare</tz-hint>
<city>
<!-- Translators: this is the capital of Zimbabwe -->
@@ -3329,6 +3517,82 @@
<_name>Antarctica</_name>
<iso-code>AQ</iso-code>
<fips-code>AY</fips-code>
+ <timezones>
+ <timezone id="Antarctica/Palmer">
+ <!-- Translators: This is an American research station in
+ Antarctica, which keeps the same time as mainland Chile.
+ The string is only used in places where "Antarctica" is
+ already clear from context.
+ -->
+ <_name>Palmer Station (Chile Time)</_name>
+ </timezone>
+ <timezone id="Antarctica/Rothera">
+ <!-- Translators: This is a British research station in
+ Antarctica. The string is only used in places where
+ "Antarctica" is already clear from context.
+ -->
+ <_name>Rothera Research Station</_name>
+ </timezone>
+ <timezone id="Antarctica/Syowa">
+ <!-- Translators: This is a Japanese research station in
+ Antarctica. The string is only used in places where
+ "Antarctica" is already clear from context.
+ -->
+ <_name>Showa Station</_name>
+ </timezone>
+ <timezone id="Antarctica/Mawson">
+ <!-- Translators: This is an Australian research station in
+ Antarctica. The string is only used in places where
+ "Antarctica" is already clear from context.
+ -->
+ <_name>Mawson Station</_name>
+ </timezone>
+ <timezone id="Antarctica/Vostok">
+ <!-- Translators: This is a Russian research station in
+ Antarctica. The string is only used in places where
+ "Antarctica" is already clear from context.
+ -->
+ <_name>Vostok Station</_name>
+ </timezone>
+ <timezone id="Antarctica/Davis">
+ <!-- Translators: This is an Australian research station in
+ Antarctica. The string is only used in places where
+ "Antarctica" is already clear from context.
+ -->
+ <_name>Davis Station</_name>
+ </timezone>
+ <timezone id="Antarctica/Casey">
+ <!-- Translators: This is an Australian research station in
+ Antarctica, which keeps the same time as Western
+ Australia. The string is only used in places where
+ "Antarctica" is already clear from context.
+ -->
+ <_name>Casey Station (Western Australia Time)</_name>
+ </timezone>
+ <timezone id="Antarctica/DumontDUrville">
+ <!-- Translators: This is a French research station in
+ Antarctica. The string is only used in places where
+ "Antarctica" is already clear from context.
+ -->
+ <_name>Dumont d'Urville Station</_name>
+ </timezone>
+ <timezone id="Antarctica/McMurdo">
+ <!-- Translators: This is an American research station in
+ Antarctica, which keeps the same time as New Zealand. The
+ string is only used in places where "Antarctica" is
+ already clear from context.
+ -->
+ <_name>McMurdo Station (New Zealand Time)</_name>
+ </timezone>
+ <timezone id="Antarctica/South_Pole">
+ <!-- Translators: This is an American research station in
+ Antarctica, which keeps the same time as New Zealand. The
+ string is only used in places where "Antarctica" is
+ already clear from context.
+ -->
+ <_name>Amundsen-Scott South Pole Station (New Zealand Time)</_name>
+ </timezone>
+ </timezones>
<tz-hint>Antarctica/McMurdo</tz-hint>
</country>
</region>
@@ -3343,6 +3607,9 @@
-->
<iso-code>AF</iso-code>
<fips-code>AF</fips-code>
+ <timezones>
+ <timezone id="Asia/Kabul" />
+ </timezones>
<tz-hint>Asia/Kabul</tz-hint>
<city>
<!-- Translators: this is a city in Afghanistan -->
@@ -3381,6 +3648,9 @@
-->
<iso-code>AM</iso-code>
<fips-code>AM</fips-code>
+ <timezones>
+ <timezone id="Asia/Yerevan" />
+ </timezones>
<tz-hint>Asia/Yerevan</tz-hint>
<city>
<!-- Translators: this is a city in Armenia -->
@@ -3448,6 +3718,9 @@
-->
<iso-code>AZ</iso-code>
<fips-code>AJ</fips-code>
+ <timezones>
+ <timezone id="Asia/Baku" />
+ </timezones>
<tz-hint>Asia/Baku</tz-hint>
<city>
<!-- Translators: this is the capital of Azerbaijan.
@@ -3522,6 +3795,9 @@
-->
<iso-code>BD</iso-code>
<fips-code>BG</fips-code>
+ <timezones>
+ <timezone id="Asia/Dhaka" />
+ </timezones>
<tz-hint>Asia/Dhaka</tz-hint>
<city>
<!-- Translators: this is a city in Bangladesh.
@@ -3567,6 +3843,9 @@
-->
<iso-code>BT</iso-code>
<fips-code>BT</fips-code>
+ <timezones>
+ <timezone id="Asia/Thimphu" />
+ </timezones>
<tz-hint>Asia/Thimphu</tz-hint>
</country>
<country>
@@ -3574,6 +3853,9 @@
<_name>Brunei</_name>
<iso-code>BN</iso-code>
<fips-code>BX</fips-code>
+ <timezones>
+ <timezone id="Asia/Brunei" />
+ </timezones>
<tz-hint>Asia/Brunei</tz-hint>
<city>
<!-- Translators: this is the capital of Brunei -->
@@ -3591,6 +3873,9 @@
<_name>Cambodia</_name>
<iso-code>KH</iso-code>
<fips-code>CB</fips-code>
+ <timezones>
+ <timezone id="Asia/Phnom_Penh" />
+ </timezones>
<tz-hint>Asia/Phnom_Penh</tz-hint>
<city>
<!-- Translators: this is the capital of Cambodia.
@@ -3642,6 +3927,14 @@
-->
<iso-code>CN</iso-code>
<fips-code>CH</fips-code>
+ <timezones>
+ <timezone id="Asia/Shanghai">
+ <obsoletes>Asia/Chongqing</obsoletes>
+ <obsoletes>Asia/Harbin</obsoletes>
+ <obsoletes>Asia/Kashgar</obsoletes>
+ <obsoletes>Asia/Urumqi</obsoletes>
+ </timezone>
+ </timezones>
<tz-hint>Asia/Shanghai</tz-hint>
<state>
<!-- Translators: this is a state/province/territory in China -->
@@ -4133,6 +4426,9 @@
-->
<iso-code>GE</iso-code>
<fips-code>GG</fips-code>
+ <timezones>
+ <timezone id="Asia/Tbilisi" />
+ </timezones>
<tz-hint>Asia/Tbilisi</tz-hint>
</country>
<country>
@@ -4142,6 +4438,9 @@
<_name>Hong Kong</_name>
<iso-code>HK</iso-code>
<fips-code>HK</fips-code>
+ <timezones>
+ <timezone id="Asia/Hong_Kong" />
+ </timezones>
<tz-hint>Asia/Hong_Kong</tz-hint>
<city>
<!-- Translators: this is a city in Hong Kong -->
@@ -4174,6 +4473,9 @@
-->
<iso-code>IN</iso-code>
<fips-code>IN</fips-code>
+ <timezones>
+ <timezone id="Asia/Kolkata" />
+ </timezones>
<tz-hint>Asia/Kolkata</tz-hint>
<city>
<!-- Translators: this is a city in India -->
@@ -4402,6 +4704,9 @@
-->
<iso-code>JP</iso-code>
<fips-code>JA</fips-code>
+ <timezones>
+ <timezone id="Asia/Tokyo" />
+ </timezones>
<tz-hint>Asia/Tokyo</tz-hint>
<city>
<!-- Translators: this is a city in Japan -->
@@ -5450,6 +5755,25 @@
<iso-code>KZ</iso-code>
<fips-code>KZ</fips-code>
<pref-lang>kaz</pref-lang>
+ <timezones>
+ <timezone id="Asia/Almaty">
+ <!-- Translators: This is the time zone used in the eastern
+ half of Kazakhstan. FIXME: is there an official name for
+ this zone?
+ -->
+ <_name>Eastern Kazakhstan</_name>
+ <obsoletes>Asia/Qyzylorda</obsoletes>
+ </timezone>
+ <timezone id="Asia/Aqtobe">
+ <!-- Translators: This is the time zone used in the western
+ half of Kazakhstan. FIXME: is there an official name for
+ this zone?
+ -->
+ <_name>Western Kazakhstan</_name>
+ <obsoletes>Asia/Aqtau</obsoletes>
+ <obsoletes>Asia/Oral</obsoletes>
+ </timezone>
+ </timezones>
<tz-hint>Asia/Almaty</tz-hint>
<city>
<!-- Translators: this is a city in Kazakhstan -->
@@ -5574,6 +5898,9 @@
-->
<iso-code>KG</iso-code>
<fips-code>KG</fips-code>
+ <timezones>
+ <timezone id="Asia/Bishkek" />
+ </timezones>
<tz-hint>Asia/Bishkek</tz-hint>
<city>
<!-- Translators: this is the capital of Kyrgyzstan -->
@@ -5598,6 +5925,9 @@
-->
<iso-code>LA</iso-code>
<fips-code>LA</fips-code>
+ <timezones>
+ <timezone id="Asia/Vientiane" />
+ </timezones>
<tz-hint>Asia/Vientiane</tz-hint>
<city>
<!-- Translators: this is the capital of Laos.
@@ -5622,6 +5952,9 @@
<_name>Macau</_name>
<iso-code>MO</iso-code>
<fips-code>MC</fips-code>
+ <timezones>
+ <timezone id="Asia/Macau" />
+ </timezones>
<tz-hint>Asia/Macau</tz-hint>
<city>
<!-- Translators: this is the capital of Macau.
@@ -5662,6 +5995,11 @@
-->
<iso-code>MY</iso-code>
<fips-code>MY</fips-code>
+ <timezones>
+ <timezone id="Asia/Kuala_Lumpur">
+ <obsoletes>Asia/Kuching</obsoletes>
+ </timezone>
+ </timezones>
<tz-hint>Asia/Kuala_Lumpur</tz-hint>
<city>
<!-- Translators: this is a city in Malaysia -->
@@ -5869,6 +6207,9 @@
<_name>Maldives</_name>
<iso-code>MV</iso-code>
<fips-code>MV</fips-code>
+ <timezones>
+ <timezone id="Indian/Maldives" />
+ </timezones>
<tz-hint>Indian/Maldives</tz-hint>
<city>
<!-- Translators: this is the capital of Maldives.
@@ -5896,6 +6237,29 @@
-->
<iso-code>MN</iso-code>
<fips-code>MG</fips-code>
+ <timezones>
+ <timezone id="Asia/Choibalsan">
+ <!-- Translators: This is the time zone used in the eastern part
+ of Mongolia. FIXME: Is there an official name for this
+ zone?
+ -->
+ <_name>Eastern Mongolia</_name>
+ </timezone>
+ <timezone id="Asia/Hovd">
+ <!-- Translators: This is the time zone used in the western part
+ of Mongolia. FIXME: Is there an official name for this
+ zone?
+ -->
+ <_name>Western Mongolia</_name>
+ </timezone>
+ <timezone id="Asia/Ulaanbaatar">
+ <!-- Translators: This is the time zone used in the central part
+ of Mongolia. FIXME: Is there an official name for this
+ zone?
+ -->
+ <_name>Central Mongolia</_name>
+ </timezone>
+ </timezones>
<tz-hint>Asia/Ulaanbaatar</tz-hint>
<city>
<!-- Translators: this is a city in Mongolia.
@@ -5939,6 +6303,9 @@
-->
<iso-code>MM</iso-code>
<fips-code>BM</fips-code>
+ <timezones>
+ <timezone id="Asia/Rangoon" />
+ </timezones>
<tz-hint>Asia/Rangoon</tz-hint>
<city>
<!-- Translators: this is the capital of Myanmar.
@@ -5959,6 +6326,9 @@
<_name>Nepal</_name>
<iso-code>NP</iso-code>
<fips-code>NP</fips-code>
+ <timezones>
+ <timezone id="Asia/Katmandu" />
+ </timezones>
<tz-hint>Asia/Katmandu</tz-hint>
<city>
<!-- Translators: this is the capital of Nepal.
@@ -5985,6 +6355,9 @@
-->
<iso-code>KP</iso-code>
<fips-code>KN</fips-code>
+ <timezones>
+ <timezone id="Asia/Pyongyang" />
+ </timezones>
<tz-hint>Asia/Pyongyang</tz-hint>
</country>
<country>
@@ -5996,6 +6369,9 @@
-->
<iso-code>PK</iso-code>
<fips-code>PK</fips-code>
+ <timezones>
+ <timezone id="Asia/Karachi" />
+ </timezones>
<tz-hint>Asia/Karachi</tz-hint>
<city>
<!-- Translators: this is the capital of Pakistan -->
@@ -6053,6 +6429,9 @@
<_name>Philippines</_name>
<iso-code>PH</iso-code>
<fips-code>RP</fips-code>
+ <timezones>
+ <timezone id="Asia/Manila" />
+ </timezones>
<tz-hint>Asia/Manila</tz-hint>
<city>
<!-- Translators: this is a city in Philippines -->
@@ -6144,6 +6523,9 @@
-->
<iso-code>SG</iso-code>
<fips-code>SN</fips-code>
+ <timezones>
+ <timezone id="Asia/Singapore" />
+ </timezones>
<tz-hint>Asia/Singapore</tz-hint>
<city>
<!-- Translators: this is the capital of Singapore -->
@@ -6174,6 +6556,9 @@
-->
<iso-code>KR</iso-code>
<fips-code>KS</fips-code>
+ <timezones>
+ <timezone id="Asia/Seoul" />
+ </timezones>
<tz-hint>Asia/Seoul</tz-hint>
<city>
<!-- Translators: this is a city in South Korea -->
@@ -6338,6 +6723,9 @@
<_name>Sri Lanka</_name>
<iso-code>LK</iso-code>
<fips-code>CE</fips-code>
+ <timezones>
+ <timezone id="Asia/Colombo" />
+ </timezones>
<tz-hint>Asia/Colombo</tz-hint>
<city>
<!-- Translators: this is the capital of Sri Lanka -->
@@ -6377,6 +6765,9 @@
<_name>Taiwan</_name>
<iso-code>TW</iso-code>
<fips-code>TW</fips-code>
+ <timezones>
+ <timezone id="Asia/Taipei" />
+ </timezones>
<tz-hint>Asia/Taipei</tz-hint>
<city>
<!-- Translators: this is a city in Taiwan.
@@ -6436,6 +6827,9 @@
-->
<iso-code>TJ</iso-code>
<fips-code>TI</fips-code>
+ <timezones>
+ <timezone id="Asia/Dushanbe" />
+ </timezones>
<tz-hint>Asia/Dushanbe</tz-hint>
<city>
<!-- Translators: this is the capital of Tajikistan -->
@@ -6471,6 +6865,9 @@
-->
<iso-code>TH</iso-code>
<fips-code>TH</fips-code>
+ <timezones>
+ <timezone id="Asia/Bangkok" />
+ </timezones>
<tz-hint>Asia/Bangkok</tz-hint>
<city>
<!-- Translators: this is a city in Thailand.
@@ -6790,6 +7187,9 @@
-->
<iso-code>TM</iso-code>
<fips-code>TX</fips-code>
+ <timezones>
+ <timezone id="Asia/Ashgabat" />
+ </timezones>
<tz-hint>Asia/Ashgabat</tz-hint>
<city>
<!-- Translators: this is the capital of Turkmenistan.
@@ -6819,6 +7219,11 @@
-->
<iso-code>UZ</iso-code>
<fips-code>UZ</fips-code>
+ <timezones>
+ <timezone id="Asia/Tashkent">
+ <obsoletes>Asia/Samarkand</obsoletes>
+ </timezone>
+ </timezones>
<tz-hint>Asia/Tashkent</tz-hint>
<city>
<!-- Translators: this is a city in Uzbekistan -->
@@ -6894,6 +7299,9 @@
-->
<iso-code>VN</iso-code>
<fips-code>VM</fips-code>
+ <timezones>
+ <timezone id="Asia/Ho_Chi_Minh" />
+ </timezones>
<tz-hint>Asia/Ho_Chi_Minh</tz-hint>
<city>
<!-- Translators: this is a city in Viet Nam -->
@@ -7031,6 +7439,9 @@
<_name>Anguilla</_name>
<iso-code>AI</iso-code>
<fips-code>AV</fips-code>
+ <timezones>
+ <timezone id="America/Anguilla" />
+ </timezones>
<tz-hint>America/Anguilla</tz-hint>
<city>
<!-- Translators: this is the capital of Anguilla -->
@@ -7048,6 +7459,9 @@
<_name>Antigua and Barbuda</_name>
<iso-code>AG</iso-code>
<fips-code>AC</fips-code>
+ <timezones>
+ <timezone id="America/Antigua" />
+ </timezones>
<tz-hint>America/Antigua</tz-hint>
<city>
<!-- Translators: this is a city in Antigua and Barbuda -->
@@ -7075,6 +7489,9 @@
<_name>Barbados</_name>
<iso-code>BB</iso-code>
<fips-code>BB</fips-code>
+ <timezones>
+ <timezone id="America/Barbados" />
+ </timezones>
<tz-hint>America/Barbados</tz-hint>
<city>
<!-- Translators: this is the capital of Barbados -->
@@ -7104,6 +7521,9 @@
<_name>Bermuda</_name>
<iso-code>BM</iso-code>
<fips-code>BD</fips-code>
+ <timezones>
+ <timezone id="Atlantic/Bermuda" />
+ </timezones>
<tz-hint>Atlantic/Bermuda</tz-hint>
<city>
<!-- Translators: this is the capital of Bermuda -->
@@ -7133,6 +7553,9 @@
<_name>Dominica</_name>
<iso-code>DM</iso-code>
<fips-code>DO</fips-code>
+ <timezones>
+ <timezone id="America/Dominica" />
+ </timezones>
<tz-hint>America/Dominica</tz-hint>
<city>
<!-- Translators: this is a city in Dominica -->
@@ -7181,6 +7604,34 @@
<iso-code>GL</iso-code>
<fips-code>GL</fips-code>
<pref-lang>dan</pref-lang>
+ <timezones>
+ <timezone id="America/Danmarkshavn">
+ <!-- Translators: This is the timezone around Danmarkshavn
+ station in Greenland. The string is only used in places
+ where "Greenland" is already clear from context.
+ -->
+ <_name>Danmarkshavn</_name>
+ </timezone>
+ <timezone id="America/Godthab">
+ <!-- Translators: This is the primary timezone for Greenland,
+ although sources seem to point towards calling the area
+ "Western Greenland" rathern than just "Greenland".
+ -->
+ <_name>Western Greenland</_name>
+ </timezone>
+ <timezone id="America/Scoresbysund">
+ <!-- Translators: This is the timezone around Scoresbysund /
+ Ittoqqortoormiit on the east coast of Greenland.
+ -->
+ <_name>Eastern Greenland</_name>
+ </timezone>
+ <timezone id="America/Thule">
+ <!-- Translators: This is the timezone at the Thule US Air Force
+ Base on the west coast of Greenland.
+ -->
+ <_name>Thule AFB</_name>
+ </timezone>
+ </timezones>
<tz-hint>America/Godthab</tz-hint>
<city>
<!-- Translators: this is a city in Greenland.
@@ -7277,6 +7728,11 @@
<_name>Puerto Rico</_name>
<iso-code>PR</iso-code>
<fips-code>US72</fips-code>
+ <timezones>
+ <timezone id="America/Puerto_Rico">
+ <_name>Atlantic Time</_name>
+ </timezone>
+ </timezones>
<tz-hint>America/Puerto_Rico</tz-hint>
<city>
<!-- Translators: this is a city in Puerto Rico -->
@@ -7330,6 +7786,9 @@
<_name>Saint BarthÃlemy</_name>
<iso-code>BL</iso-code>
<fips-code>TB</fips-code>
+ <timezones>
+ <timezone id="America/St_Barthelemy" />
+ </timezones>
<tz-hint>America/St_Barthelemy</tz-hint>
</country>
<country>
@@ -7341,6 +7800,9 @@
-->
<iso-code>SH</iso-code>
<fips-code>SH</fips-code>
+ <timezones>
+ <timezone id="Atlantic/St_Helena" />
+ </timezones>
<tz-hint>Atlantic/St_Helena</tz-hint>
<city>
<!-- Translators: this is a city in Saint Helena -->
@@ -7358,6 +7820,9 @@
<_name>Saint Kitts and Nevis</_name>
<iso-code>KN</iso-code>
<fips-code>SC</fips-code>
+ <timezones>
+ <timezone id="America/St_Kitts" />
+ </timezones>
<tz-hint>America/St_Kitts</tz-hint>
<city>
<!-- Translators: this is the capital of Saint Kitts and Nevis -->
@@ -7407,6 +7872,11 @@
<_name>United States Virgin Islands</_name>
<iso-code>VI</iso-code>
<fips-code>US78</fips-code>
+ <timezones>
+ <timezone id="America/St_Thomas">
+ <_name>Atlantic Time</_name>
+ </timezone>
+ </timezones>
<tz-hint>America/St_Thomas</tz-hint>
<city>
<!-- Translators: this is a city in United States Virgin Islands
@@ -7442,6 +7912,9 @@
<_name>American Samoa</_name>
<iso-code>AS</iso-code>
<fips-code>US60</fips-code>
+ <timezones>
+ <timezone id="Pacific/Pago_Pago" />
+ </timezones>
<tz-hint>Pacific/Pago_Pago</tz-hint>
<city>
<!-- Translators: this is a city in American Samoa -->
@@ -7463,6 +7936,98 @@
-->
<iso-code>AU</iso-code>
<fips-code>AS</fips-code>
+ <timezones>
+ <timezone id="Australia/Perth">
+ <!-- Translators: This is the time zone used in Western
+ Australia. The string is only used in places where
+ "Australia" is already clear from context.
+ -->
+ <_name>Western Time</_name>
+ </timezone>
+ <timezone id="Australia/Eucla">
+ <!-- Translators: This is the commonly-used name for an
+ unofficial time zone used in part of southwestern
+ Australia. The string is only used in places where
+ "Australia" is already clear from context.
+ -->
+ <_name>Central Western Time</_name>
+ </timezone>
+ <timezone id="Australia/Adelaide">
+ <!-- Translators: This is the time zone used in Central
+ Australia. This string is specifically for the time zone
+ as implemented in the state of South Australia, and is
+ only used in places where "Australia" is already clear
+ from context.
+ -->
+ <_name>Central Time (South Australia)</_name>
+ </timezone>
+ <timezone id="Australia/Broken_Hill">
+ <!-- Translators: This is the time zone used in Central
+ Australia. This string is specifically for the time zone
+ as implemented in Yancowinna county in the state of New
+ South Wales (NSW), which uses Central Time even though
+ the rest of the state uses Eastern Time. This string is
+ only used in places where "Australia" is already clear
+ from context.
+ -->
+ <_name>Central Time (Yancowinna, NSW)</_name>
+ </timezone>
+ <timezone id="Australia/Darwin">
+ <!-- Translators: This is the time zone used in Central
+ Australia. This string is specifically for the time zone
+ as implemented in the Northern Territory, which does not
+ use Summer Time. This string is only used in places where
+ "Australia" is already clear from context.
+ -->
+ <_name>Central Time (Northern Territory)</_name>
+ </timezone>
+ <timezone id="Australia/Hobart">
+ <!-- Translators: This is the time zone used in Eastern
+ Australia. This string is specifically for the time zone
+ as implemented in the state of Tasmania, and is only used
+ in places where "Australia" is already clear from
+ context.
+ -->
+ <_name>Eastern Time (Tasmania)</_name>
+ <obsoletes>Australia/Currie</obsoletes>
+ </timezone>
+ <timezone id="Australia/Melbourne">
+ <!-- Translators: This is the time zone used in Eastern
+ Australia. This string is specifically for the time zone
+ as implemented in the state of Victoria, and is only used
+ in places where "Australia" is already clear from
+ context.
+ -->
+ <_name>Eastern Time (Victoria)</_name>
+ </timezone>
+ <timezone id="Australia/Sydney">
+ <!-- Translators: This is the time zone used in Eastern
+ Australia. This string is specifically for the time zone
+ as implemented in the state of New South Wales, and is
+ only used in places where "Australia" is already clear
+ from context.
+ -->
+ <_name>Eastern Time (New South Wales)</_name>
+ </timezone>
+ <timezone id="Australia/Brisbane">
+ <!-- Translators: This is the time zone used in Eastern
+ Australia. This string is specifically for the time zone
+ as implemented in the state of Queensland, which does not
+ use Summer Time. This string is only used in places where
+ "Australia" is already clear from context.
+ -->
+ <_name>Eastern Time (Queensland)</_name>
+ <obsoletes>Australia/Lindeman</obsoletes>
+ </timezone>
+ <timezone id="Australia/Lord_Howe">
+ <!-- Translators: This is the time zone used on Lord Howe
+ Island, off the east coast of Australia. This string is
+ only used in places where "Australia" is already clear
+ from context.
+ -->
+ <_name>Lord Howe Island</_name>
+ </timezone>
+ </timezones>
<state>
<!-- Translators: this is a state/province/territory in
Australia
@@ -7861,6 +8426,9 @@
-->
<iso-code>IO</iso-code>
<fips-code>IO</fips-code>
+ <timezones>
+ <timezone id="Indian/Chagos" />
+ </timezones>
<tz-hint>Indian/Chagos</tz-hint>
</country>
<country>
@@ -7875,6 +8443,9 @@
-->
<iso-code>CX</iso-code>
<fips-code>KT</fips-code>
+ <timezones>
+ <timezone id="Indian/Christmas" />
+ </timezones>
<tz-hint>Indian/Christmas</tz-hint>
<city>
<!-- Translators: this is a city in Christmas Island -->
@@ -7905,6 +8476,9 @@
<_name>Cocos (Keeling) Islands</_name>
<iso-code>CC</iso-code>
<fips-code>CK</fips-code>
+ <timezones>
+ <timezone id="Indian/Cocos" />
+ </timezones>
<tz-hint>Indian/Cocos</tz-hint>
<city>
<!-- Translators: this is a city in Cocos (Keeling) Islands -->
@@ -7923,6 +8497,9 @@
<_name>Cook Islands</_name>
<iso-code>CK</iso-code>
<fips-code>CW</fips-code>
+ <timezones>
+ <timezone id="Pacific/Rarotonga" />
+ </timezones>
<tz-hint>Pacific/Rarotonga</tz-hint>
<city>
<!-- Translators: this is the capital of Cook Islands -->
@@ -7940,6 +8517,9 @@
<_name>Fiji</_name>
<iso-code>FJ</iso-code>
<fips-code>FJ</fips-code>
+ <timezones>
+ <timezone id="Pacific/Fiji" />
+ </timezones>
<tz-hint>Pacific/Fiji</tz-hint>
<city>
<!-- Translators: this is a city in Fiji -->
@@ -7969,6 +8549,32 @@
<_name>French Polynesia</_name>
<iso-code>PF</iso-code>
<fips-code>FP</fips-code>
+ <timezones>
+ <timezone id="Pacific/Tahiti">
+ <!-- Translators: This refers to the time zone in the Society
+ Islands of French Polynesia (including in particular the
+ island of Tahiti). This string is only used in places where
+ "French Polynesia" is already clear from context.
+ -->
+ <_name>Tahiti / Society Islands</_name>
+ </timezone>
+ <timezone id="Pacific/Marquesas">
+ <!-- Translators: This refers to the time zone in the
+ Marquesas Islands of French Polynesia. This string is
+ only used in places where "French Polynesia" is already
+ clear from context.
+ -->
+ <_name>Marquesas Islands</_name>
+ </timezone>
+ <timezone id="Pacific/Gambier">
+ <!-- Translators: This refers to the time zone in the Gambier
+ Islands of French Polynesia. This string is only used in
+ places where "French Polynesia" is already clear from
+ context.
+ -->
+ <_name>Gambier Islands</_name>
+ </timezone>
+ </timezones>
<tz-hint>Pacific/Tahiti</tz-hint>
<city>
<!-- Translators: this is the capital of French Polynesia -->
@@ -7992,6 +8598,9 @@
-->
<iso-code>GU</iso-code>
<fips-code>US66</fips-code>
+ <timezones>
+ <timezone id="Pacific/Guam" />
+ </timezones>
<tz-hint>Pacific/Guam</tz-hint>
<city>
<!-- Translators: this is a city in Guam -->
@@ -8030,6 +8639,30 @@
-->
<iso-code>ID</iso-code>
<fips-code>ID</fips-code>
+ <timezones>
+ <timezone id="Asia/Jakarta">
+ <!-- Translators: this is the timezone on the western islands of
+ Indonesia. The name in Indonesian is "Waktu Indonesia
+ Bagian Barat".
+ -->
+ <_name>Western Indonesia Time</_name>
+ <obsoletes>Asia/Pontianak</obsoletes>
+ </timezone>
+ <timezone id="Asia/Makassar">
+ <!-- Translators: this is the timezone on the central islands of
+ Indonesia. The name in Indonesian is "Waktu Indonesia
+ Bagian Tengah".
+ -->
+ <_name>Central Indonesia Time</_name>
+ </timezone>
+ <timezone id="Asia/Jayapura">
+ <!-- Translators: this is the timezone on the eastern islands of
+ Indonesia. The name in Indonesian is "Waktu Indonesia
+ Bagian Timur".
+ -->
+ <_name>Eastern Indonesia Time</_name>
+ </timezone>
+ </timezones>
<tz-hint>Asia/Jakarta</tz-hint>
<city>
<!-- Translators: this is the capital of Indonesia -->
@@ -8092,6 +8725,32 @@
-->
<iso-code>KI</iso-code>
<fips-code>KR</fips-code>
+ <timezones>
+ <timezone id="Pacific/Tarawa">
+ <!-- Translators: This is the time zone in the Gilbert
+ Islands, one of the three main island groups of Kiribati.
+ This string is only used in places where "Kiribati" is
+ already clear from context.
+ -->
+ <_name>Gilbert Islands</_name>
+ </timezone>
+ <timezone id="Pacific/Enderbury">
+ <!-- Translators: This is the time zone in the Phoenix
+ Islands, one of the three main island groups of Kiribati.
+ This string is only used in places where "Kiribati" is
+ already clear from context.
+ -->
+ <_name>Phoenix Islands</_name>
+ </timezone>
+ <timezone id="Pacific/Kiritimati">
+ <!-- Translators: This is the time zone in the Line Islands,
+ one of the three main island groups of Kiribati. This
+ string is only used in places where "Kiribati" is already
+ clear from context.
+ -->
+ <_name>Line Islands</_name>
+ </timezone>
+ </timezones>
<tz-hint>Pacific/Tarawa</tz-hint>
<city>
<!-- Translators: this is a city in Kiribati -->
@@ -8114,6 +8773,11 @@
<iso-code>MH</iso-code>
<fips-code>RM</fips-code>
<fips-code>US68</fips-code>
+ <timezones>
+ <timezone id="Pacific/Majuro">
+ <obsoletes>Pacific/Kwajalein</obsoletes>
+ </timezone>
+ </timezones>
<tz-hint>Pacific/Majuro</tz-hint>
<city>
<!-- Translators: this is the capital of Marshall Islands -->
@@ -8141,6 +8805,25 @@
<iso-code>FM</iso-code>
<fips-code>FM</fips-code>
<fips-code>US64</fips-code>
+ <timezones>
+ <timezone id="Pacific/Ponape">
+ <!-- Translators: This is one of two time zones in the
+ Federated States of Micronesia, including the islands of
+ Pohnpei and Kosrae. The string is only used in places
+ where "Micronesia" is already clear from context.
+ -->
+ <_name>Pohnpei / Kosrae</_name>
+ <obsoletes>Pacific/Kosrae</obsoletes>
+ </timezone>
+ <timezone id="Pacific/Truk">
+ <!-- Translators: This is one of two time zones in the Federated
+ States of Micronesia, including the islands of Yap and
+ Chuuk. The string is only used in places where "Micronesia"
+ is already clear from context.
+ -->
+ <_name>Yap / Chuuk</_name>
+ </timezone>
+ </timezones>
<city>
<!-- Translators: this is a city in Micronesia, Federated
States of
@@ -8212,6 +8895,9 @@
<_name>Nauru</_name>
<iso-code>NR</iso-code>
<fips-code>NR</fips-code>
+ <timezones>
+ <timezone id="Pacific/Nauru" />
+ </timezones>
<tz-hint>Pacific/Nauru</tz-hint>
</country>
<country>
@@ -8221,6 +8907,9 @@
<_name>New Caledonia</_name>
<iso-code>NC</iso-code>
<fips-code>NC</fips-code>
+ <timezones>
+ <timezone id="Pacific/Noumea" />
+ </timezones>
<tz-hint>Pacific/Noumea</tz-hint>
<city>
<!-- Translators: this is a city in New Caledonia -->
@@ -8248,6 +8937,24 @@
<_name>New Zealand</_name>
<iso-code>NZ</iso-code>
<fips-code>NZ</fips-code>
+ <timezones>
+ <timezone id="Pacific/Auckland">
+ <!-- Translators: This refers to the "mainland" of New Zealand
+ (ie, North Island and South Island), to distinguish it from
+ the Chatham Islands. The string is only used in places
+ where "New Zealand" is already clear from context. FIXME:
+ is there a better name for this? "Mainland" seems odd in
+ reference to an island nation...
+ -->
+ <_name>Mainland New Zealand</_name>
+ </timezone>
+ <timezone id="Pacific/Chatham">
+ <!-- Translators: This refers to the time zone in the Chatham
+ Islands of New Zealand.
+ -->
+ <_name>Chatham Islands</_name>
+ </timezone>
+ </timezones>
<tz-hint>Pacific/Auckland</tz-hint>
<city>
<!-- Translators: this is a city in New Zealand -->
@@ -8285,6 +8992,9 @@
<_name>Niue</_name>
<iso-code>NU</iso-code>
<fips-code>NE</fips-code>
+ <timezones>
+ <timezone id="Pacific/Niue" />
+ </timezones>
<tz-hint>Pacific/Niue</tz-hint>
<city>
<!-- Translators: this is the capital of Niue -->
@@ -8302,6 +9012,9 @@
<_name>Norfolk Island</_name>
<iso-code>NF</iso-code>
<fips-code>NF</fips-code>
+ <timezones>
+ <timezone id="Pacific/Norfolk" />
+ </timezones>
<tz-hint>Pacific/Norfolk</tz-hint>
<city>
<!-- Translators: this is a city in Norfolk Island -->
@@ -8322,6 +9035,9 @@
<_name>Northern Mariana Islands</_name>
<iso-code>MP</iso-code>
<fips-code>US69</fips-code>
+ <timezones>
+ <timezone id="Pacific/Saipan" />
+ </timezones>
<tz-hint>Pacific/Saipan</tz-hint>
<city>
<!-- Translators: this is a city in Northern Mariana Islands -->
@@ -8344,6 +9060,9 @@
<_name>Palau</_name>
<iso-code>PW</iso-code>
<fips-code>PS|US70</fips-code>
+ <timezones>
+ <timezone id="Pacific/Palau" />
+ </timezones>
<tz-hint>Pacific/Palau</tz-hint>
<city>
<!-- Translators: this is the capital of Palau -->
@@ -8380,6 +9099,9 @@
-->
<iso-code>PG</iso-code>
<fips-code>PP</fips-code>
+ <timezones>
+ <timezone id="Pacific/Port_Moresby" />
+ </timezones>
<tz-hint>Pacific/Port_Moresby</tz-hint>
<city>
<!-- Translators: this is a city in Papua New Guinea -->
@@ -8421,6 +9143,9 @@
-->
<iso-code>PN</iso-code>
<fips-code>PC</fips-code>
+ <timezones>
+ <timezone id="Pacific/Pitcairn" />
+ </timezones>
<tz-hint>Pacific/Pitcairn</tz-hint>
</country>
<country>
@@ -8430,6 +9155,9 @@
<_name>Samoa</_name>
<iso-code>WS</iso-code>
<fips-code>WS</fips-code>
+ <timezones>
+ <timezone id="Pacific/Apia" />
+ </timezones>
<tz-hint>Pacific/Apia</tz-hint>
<city>
<!-- Translators: this is the capital of Samoa -->
@@ -8457,6 +9185,9 @@
<_name>Solomon Islands</_name>
<iso-code>SB</iso-code>
<fips-code>BP</fips-code>
+ <timezones>
+ <timezone id="Pacific/Guadalcanal" />
+ </timezones>
<tz-hint>Pacific/Guadalcanal</tz-hint>
<city>
<!-- Translators: this is the capital of Solomon Islands -->
@@ -8478,6 +9209,9 @@
-->
<iso-code>TL</iso-code>
<fips-code>TT</fips-code>
+ <timezones>
+ <timezone id="Asia/Dili" />
+ </timezones>
<tz-hint>Asia/Dili</tz-hint>
</country>
<country>
@@ -8485,6 +9219,9 @@
<_name>Tokelau</_name>
<iso-code>TK</iso-code>
<fips-code>TL</fips-code>
+ <timezones>
+ <timezone id="Pacific/Fakaofo" />
+ </timezones>
<tz-hint>Pacific/Fakaofo</tz-hint>
</country>
<country>
@@ -8492,6 +9229,9 @@
<_name>Tonga</_name>
<iso-code>TO</iso-code>
<fips-code>TN</fips-code>
+ <timezones>
+ <timezone id="Pacific/Tongatapu" />
+ </timezones>
<tz-hint>Pacific/Tongatapu</tz-hint>
<city>
<!-- Translators: this is a city in Tonga -->
@@ -8519,6 +9259,9 @@
<_name>Tuvalu</_name>
<iso-code>TV</iso-code>
<fips-code>TV</fips-code>
+ <timezones>
+ <timezone id="Pacific/Funafuti" />
+ </timezones>
<tz-hint>Pacific/Funafuti</tz-hint>
<city>
<!-- Translators: this is the capital of Tuvalu -->
@@ -8539,6 +9282,35 @@
<_name>United States Minor Outlying Islands</_name>
<iso-code>UM</iso-code>
<fips-code>US74</fips-code>
+ <timezones>
+ <timezone id="Pacific/Johnston">
+ <!-- Translators: This is the time zone for the Johnston Atoll
+ in the United States Minor Outlying Islands, which keeps
+ the same time as the US state of Hawaii. The string is only
+ used in places where "US Minor Outlying Islands" is already
+ clear from context.
+ -->
+ <_name>Johnston Atoll (Hawaii Time)</_name>
+ </timezone>
+ <timezone id="Pacific/Midway">
+ <!-- Translators: This is the time zone for the Midway Atoll in
+ the United States Minor Outlying Islands, which uses the
+ same time as American Samoa (which is in fact also the same
+ time zone as (non-American) Samoa). The string is only used
+ in places where "US Minor Outlying Islands" is already
+ clear from context.
+ -->
+ <_name>Midway Atoll (Samoa Time)</_name>
+ </timezone>
+ <timezone id="Pacific/Wake">
+ <!-- Translators: This is the time zone for Wake Island in the
+ United States Minor Outlying Islands. The string is only
+ used in places where "US Minor Outlying Islands" is already
+ clear from context.
+ -->
+ <_name>Wake Island</_name>
+ </timezone>
+ </timezones>
<city>
<!-- Translators: this is a city in United States Minor
Outlying Islands
@@ -8557,6 +9329,9 @@
<_name>Vanuatu</_name>
<iso-code>VU</iso-code>
<fips-code>NH</fips-code>
+ <timezones>
+ <timezone id="Pacific/Efate" />
+ </timezones>
<tz-hint>Pacific/Efate</tz-hint>
<city>
<!-- Translators: this is the capital of Vanuatu -->
@@ -8580,6 +9355,9 @@
-->
<iso-code>WF</iso-code>
<fips-code>WF</fips-code>
+ <timezones>
+ <timezone id="Pacific/Wallis" />
+ </timezones>
<tz-hint>Pacific/Wallis</tz-hint>
</country>
</region>
@@ -8600,6 +9378,20 @@
-->
<iso-code>AR</iso-code>
<fips-code>AR</fips-code>
+ <timezones>
+ <timezone id="America/Argentina/Buenos_Aires">
+ <obsoletes>America/Argentina/Catamarca</obsoletes>
+ <obsoletes>America/Argentina/Cordoba</obsoletes>
+ <obsoletes>America/Argentina/Jujuy</obsoletes>
+ <obsoletes>America/Argentina/La_Rioja</obsoletes>
+ <obsoletes>America/Argentina/Mendoza</obsoletes>
+ <obsoletes>America/Argentina/Rio_Gallegos</obsoletes>
+ <obsoletes>America/Argentina/San_Juan</obsoletes>
+ <obsoletes>America/Argentina/San_Luis</obsoletes>
+ <obsoletes>America/Argentina/Tucuman</obsoletes>
+ <obsoletes>America/Argentina/Ushuaia</obsoletes>
+ </timezone>
+ </timezones>
<tz-hint>America/Argentina/Buenos_Aires</tz-hint>
<city>
<!-- Translators: this is the capital of Argentina -->
@@ -8819,6 +9611,9 @@
<_name>Aruba</_name>
<iso-code>AW</iso-code>
<fips-code>AA</fips-code>
+ <timezones>
+ <timezone id="America/Aruba" />
+ </timezones>
<tz-hint>America/Aruba</tz-hint>
<city>
<!-- Translators: this is a city in Aruba -->
@@ -8846,6 +9641,9 @@
<_name>Bahamas</_name>
<iso-code>BS</iso-code>
<fips-code>BF</fips-code>
+ <timezones>
+ <timezone id="America/Nassau" />
+ </timezones>
<tz-hint>America/Nassau</tz-hint>
<city>
<!-- Translators: this is a city in Bahamas -->
@@ -8887,6 +9685,9 @@
-->
<iso-code>BZ</iso-code>
<fips-code>BH</fips-code>
+ <timezones>
+ <timezone id="America/Belize" />
+ </timezones>
<tz-hint>America/Belize</tz-hint>
<city>
<!-- Translators: this is a city in Belize -->
@@ -8904,6 +9705,9 @@
<_name>Bolivia</_name>
<iso-code>BO</iso-code>
<fips-code>BL</fips-code>
+ <timezones>
+ <timezone id="America/La_Paz" />
+ </timezones>
<tz-hint>America/La_Paz</tz-hint>
<city>
<!-- Translators: this is a city in Bolivia -->
@@ -9164,6 +9968,145 @@
-->
<iso-code>BR</iso-code>
<fips-code>BR</fips-code>
+ <timezones>
+ <timezone id="America/Araguaina">
+ <!-- Translators: This represents the time zone in the Brazilian
+ state of Tocantins. See the comment on "BrasÃlia Time" for
+ more details. This string is only used in places where
+ "Brazil" is already clear from context.
+ -->
+ <_name>Tocantins</_name>
+ </timezone>
+ <timezone id="America/Bahia">
+ <!-- Translators: This represents the time zone in the Brazilian
+ state of Bahia. See the comment on "BrasÃlia Time" for more
+ details. This string is only used in places where "Brazil"
+ is already clear from context.
+ -->
+ <_name>Bahia</_name>
+ </timezone>
+ <timezone id="America/Belem">
+ <!-- Translators: This represents the time zone in the Brazilian
+ state of Amapà and the eastern part of ParÃ. See the
+ comment on "BrasÃlia Time" for more details. This string is
+ only used in places where "Brazil" is already clear from
+ context.
+ -->
+ <_name>Amapà / East ParÃ</_name>
+ </timezone>
+ <timezone id="America/Boa_Vista">
+ <!-- Translators: This represents the time zone in the Brazilian
+ state of Roraima. See the comment on "BrasÃlia Time" for
+ more details. This string is only used in places where
+ "Brazil" is already clear from context.
+ -->
+ <_name>Roraima</_name>
+ </timezone>
+ <timezone id="America/Campo_Grande">
+ <!-- Translators: This represents the time zone in the Brazilian
+ state of Mato Grosso do Sul. See the comment on "BrasÃlia
+ Time" for more details. This string is only used in places
+ where "Brazil" is already clear from context.
+ -->
+ <_name>Mato Grosso do Sul</_name>
+ </timezone>
+ <timezone id="America/Cuiaba">
+ <!-- Translators: This represents the time zone in the Brazilian
+ state of Mato Grosso. See the comment on "BrasÃlia Time"
+ for more details. This string is only used in places where
+ "Brazil" is already clear from context.
+ -->
+ <_name>Mato Grosso</_name>
+ </timezone>
+ <timezone id="America/Eirunepe">
+ <!-- Translators: This represents the time zone in the western
+ part of the Brazilian state of Amazonas. See the comment on
+ "BrasÃlia Time" for more details. This string is only used
+ in places where "Brazil" is already clear from context.
+ -->
+ <_name>West Amazonas</_name>
+ </timezone>
+ <timezone id="America/Fortaleza">
+ <!-- Translators: This represents the time zone in the Brazilian
+ states of CearÃ, MaranhÃo, ParaÃba, PiauÃ, and Rio Grande
+ do Norte. See the comment on "BrasÃlia Time" for more
+ details. This string is only used in places where "Brazil"
+ is already clear from context.
+ -->
+ <_name>CearÃ, MaranhÃo, ParaÃba, PiauÃ, Rio Grande do Norte</_name>
+ </timezone>
+ <timezone id="America/Maceio">
+ <!-- Translators: This represents the time zone in the Brazilian
+ states of Alagoas and Sergipe. See the comment on "BrasÃlia
+ Time" for more details. This string is only used in places
+ where "Brazil" is already clear from context.
+ -->
+ <_name>Alagoas, Sergipe</_name>
+ </timezone>
+ <timezone id="America/Manaus">
+ <!-- Translators: This represents the time zone in the eastern
+ part of the Brazilian state of Amazonas. See the comment on
+ "BrasÃlia Time" for more details. This string is only used
+ in places where "Brazil" is already clear from context.
+ -->
+ <_name>East Amazonas</_name>
+ </timezone>
+ <timezone id="America/Noronha">
+ <!-- Translators: This represents the time zone on the Brazilian
+ island of Fernando de Noronha. See the comment on "BrasÃlia
+ Time" for more details. This string is only used in places
+ where "Brazil" is already clear from context.
+ -->
+ <_name>Fernando de Noronha</_name>
+ </timezone>
+ <timezone id="America/Porto_Velho">
+ <!-- Translators: This represents the time zone in the Brazilian
+ state of RondÃnia and the western part of ParÃ. See the
+ comment on "BrasÃlia Time" for more details. This string is
+ only used in places where "Brazil" is already clear from
+ context.
+ -->
+ <_name>West ParÃ, RondÃnia</_name>
+ </timezone>
+ <timezone id="America/Recife">
+ <!-- Translators: This represents the time zone in the Brazilian
+ state of Pernambuco. See the comment on "BrasÃlia Time" for
+ more details. This string is only used in places where
+ "Brazil" is already clear from context.
+ -->
+ <_name>Pernambuco</_name>
+ </timezone>
+ <timezone id="America/Rio_Branco">
+ <!-- Translators: This represents the time zone in the Brazilian
+ state of Acre. See the comment on "BrasÃlia Time" for more
+ details. This string is only used in places where "Brazil"
+ is already clear from context.
+ -->
+ <_name>Acre</_name>
+ </timezone>
+ <timezone id="America/Sao_Paulo">
+ <!-- Translators: This represents the official "base" time zone
+ in Brazil, covering the capital city of BrasÃlia, and those
+ states that choose to follow it. Each Brazilian state
+ decides on its own each year whether or not to observe
+ Daylight Saving Time. The tzdata database breaks the states
+ up into groups of states that generally make the same
+ decision in a given year. Thus, in any given year, several
+ of the time zones will appear to be redundant, but exactly
+ which ones seem redundant may differ from year to year, and
+ there's no good way to identify the zones other than by
+ listing states.
+
+ Anyway, "BrasÃlia Time" is the most common timezone,
+ being used by about a third of the states in Brazil
+ (Distrito Federal, EspÃrito Santo, GoiÃs, Minas Gerais,
+ ParanÃ, Rio de Janeiro, Rio Grande do Sul, Santa
+ Catarina, and SÃo Paulo). This string is only used in
+ places where "Brazil" is already clear from context.
+ -->
+ <_name>BrasÃlia Time</_name>
+ </timezone>
+ </timezones>
<tz-hint>America/Sao_Paulo</tz-hint>
<state>
<!-- Translators: this is a state/province/territory in Brazil -->
@@ -10289,6 +11232,9 @@
<_name>British Virgin Islands</_name>
<iso-code>VG</iso-code>
<fips-code>VI</fips-code>
+ <timezones>
+ <timezone id="America/Tortola" />
+ </timezones>
<tz-hint>America/Tortola</tz-hint>
<city>
<!-- Translators: this is the capital of British Virgin Islands -->
@@ -10316,6 +11262,9 @@
<_name>Cayman Islands</_name>
<iso-code>KY</iso-code>
<fips-code>CJ</fips-code>
+ <timezones>
+ <timezone id="America/Cayman" />
+ </timezones>
<tz-hint>America/Cayman</tz-hint>
<city>
<!-- Translators: this is the capital of Cayman Islands -->
@@ -10357,6 +11306,17 @@
-->
<iso-code>CL</iso-code>
<fips-code>CI</fips-code>
+ <timezones>
+ <timezone id="America/Santiago">
+ <!-- Translators: This refers to the time zone for mainland
+ Chile (as opposed to the time zone for Easter Island).
+ -->
+ <_name>Mainland Chile</_name>
+ </timezone>
+ <timezone id="Pacific/Easter">
+ <_name>Easter Island</_name>
+ </timezone>
+ </timezones>
<tz-hint>America/Santiago</tz-hint>
<city>
<!-- Translators: this is a city in Chile -->
@@ -10491,6 +11451,9 @@
-->
<iso-code>CO</iso-code>
<fips-code>CO</fips-code>
+ <timezones>
+ <timezone id="America/Bogota" />
+ </timezones>
<tz-hint>America/Bogota</tz-hint>
<city>
<!-- Translators: this is a city in Colombia -->
@@ -10642,6 +11605,9 @@
-->
<iso-code>CR</iso-code>
<fips-code>CS</fips-code>
+ <timezones>
+ <timezone id="America/Costa_Rica" />
+ </timezones>
<tz-hint>America/Costa_Rica</tz-hint>
<city>
<!-- Translators: this is a city in Costa Rica -->
@@ -10702,6 +11668,9 @@
-->
<iso-code>CU</iso-code>
<fips-code>CU</fips-code>
+ <timezones>
+ <timezone id="America/Havana" />
+ </timezones>
<tz-hint>America/Havana</tz-hint>
<city>
<!-- Translators: this is a city in Cuba -->
@@ -10816,6 +11785,9 @@
-->
<iso-code>DO</iso-code>
<fips-code>DR</fips-code>
+ <timezones>
+ <timezone id="America/Santo_Domingo" />
+ </timezones>
<tz-hint>America/Santo_Domingo</tz-hint>
<city>
<!-- Translators: this is a city in Dominican Republic -->
@@ -10897,6 +11869,19 @@
-->
<iso-code>EC</iso-code>
<fips-code>EC</fips-code>
+ <timezones>
+ <timezone id="America/Guayaquil">
+ <!-- Translators: This refers to the time zone for mainland
+ Ecuador (as opposed to the time zone for the Galapagos
+ Islands).
+ -->
+ <_name>Mainland Ecuador</_name>
+ </timezone>
+ <timezone id="Pacific/Galapagos">
+ <!-- Translators: This is the time zone for the Galapagos Islands. -->
+ <_name>Galapagos Islands</_name>
+ </timezone>
+ </timezones>
<tz-hint>America/Guayaquil</tz-hint>
<city>
<!-- Translators: this is a city in Ecuador -->
@@ -10944,6 +11929,9 @@
<_name>El Salvador</_name>
<iso-code>SV</iso-code>
<fips-code>ES</fips-code>
+ <timezones>
+ <timezone id="America/El_Salvador" />
+ </timezones>
<tz-hint>America/El_Salvador</tz-hint>
<city>
<!-- Translators: this is a city in El Salvador -->
@@ -10986,6 +11974,9 @@
<_name>Falkland Islands (Malvinas)</_name>
<iso-code>FK</iso-code>
<fips-code>FK</fips-code>
+ <timezones>
+ <timezone id="Atlantic/Stanley" />
+ </timezones>
<tz-hint>Atlantic/Stanley</tz-hint>
<city>
<!-- Translators: this is the capital of Falkland Islands
@@ -11007,6 +11998,9 @@
<_name>French Guiana</_name>
<iso-code>GF</iso-code>
<fips-code>FG</fips-code>
+ <timezones>
+ <timezone id="America/Cayenne" />
+ </timezones>
<tz-hint>America/Cayenne</tz-hint>
<city>
<!-- Translators: this is the capital of French Guiana -->
@@ -11024,6 +12018,9 @@
<_name>Grenada</_name>
<iso-code>GD</iso-code>
<fips-code>GJ</fips-code>
+ <timezones>
+ <timezone id="America/Grenada" />
+ </timezones>
<tz-hint>America/Grenada</tz-hint>
<city>
<!-- Translators: this is a city in Grenada -->
@@ -11053,6 +12050,9 @@
<_name>Guadeloupe</_name>
<iso-code>GP</iso-code>
<fips-code>GP</fips-code>
+ <timezones>
+ <timezone id="America/Guadeloupe" />
+ </timezones>
<tz-hint>America/Guadeloupe</tz-hint>
<city>
<!-- Translators: this is the capital of Guadeloupe -->
@@ -11080,6 +12080,9 @@
<_name>Guatemala</_name>
<iso-code>GT</iso-code>
<fips-code>GT</fips-code>
+ <timezones>
+ <timezone id="America/Guatemala" />
+ </timezones>
<tz-hint>America/Guatemala</tz-hint>
<city>
<!-- Translators: this is the capital of Guatemala -->
@@ -11147,6 +12150,9 @@
<_name>Guyana</_name>
<iso-code>GY</iso-code>
<fips-code>GY</fips-code>
+ <timezones>
+ <timezone id="America/Guyana" />
+ </timezones>
<tz-hint>America/Guyana</tz-hint>
<city>
<!-- Translators: this is the capital of Guyana -->
@@ -11168,6 +12174,9 @@
-->
<iso-code>HT</iso-code>
<fips-code>HA</fips-code>
+ <timezones>
+ <timezone id="America/Port-au-Prince" />
+ </timezones>
<tz-hint>America/Port-au-Prince</tz-hint>
</country>
<country>
@@ -11179,6 +12188,9 @@
-->
<iso-code>HN</iso-code>
<fips-code>HO</fips-code>
+ <timezones>
+ <timezone id="America/Tegucigalpa" />
+ </timezones>
<tz-hint>America/Tegucigalpa</tz-hint>
<city>
<!-- Translators: this is a city in Honduras -->
@@ -11326,6 +12338,9 @@
<_name>Jamaica</_name>
<iso-code>JM</iso-code>
<fips-code>JM</fips-code>
+ <timezones>
+ <timezone id="America/Jamaica" />
+ </timezones>
<tz-hint>America/Jamaica</tz-hint>
<city>
<!-- Translators: this is the capital of Jamaica -->
@@ -11355,6 +12370,9 @@
<_name>Martinique</_name>
<iso-code>MQ</iso-code>
<fips-code>MB</fips-code>
+ <timezones>
+ <timezone id="America/Martinique" />
+ </timezones>
<tz-hint>America/Martinique</tz-hint>
<city>
<!-- Translators: this is the capital of Martinique -->
@@ -11386,6 +12404,9 @@
-->
<iso-code>MS</iso-code>
<fips-code>MH</fips-code>
+ <timezones>
+ <timezone id="America/Montserrat" />
+ </timezones>
<tz-hint>America/Montserrat</tz-hint>
</country>
<country>
@@ -11396,6 +12417,9 @@
<_name>Netherlands Antilles</_name>
<iso-code>AN</iso-code>
<fips-code>NT</fips-code>
+ <timezones>
+ <timezone id="America/Curacao" />
+ </timezones>
<tz-hint>America/Curacao</tz-hint>
<city>
<!-- Translators: this is a city in Netherlands Antilles -->
@@ -11443,6 +12467,9 @@
<_name>Nicaragua</_name>
<iso-code>NI</iso-code>
<fips-code>NU</fips-code>
+ <timezones>
+ <timezone id="America/Managua" />
+ </timezones>
<tz-hint>America/Managua</tz-hint>
<city>
<!-- Translators: this is a city in Nicaragua -->
@@ -11527,6 +12554,9 @@
-->
<iso-code>PA</iso-code>
<fips-code>PM</fips-code>
+ <timezones>
+ <timezone id="America/Panama" />
+ </timezones>
<tz-hint>America/Panama</tz-hint>
<city>
<!-- Translators: this is a city in Panama -->
@@ -11574,6 +12604,9 @@
<_name>Paraguay</_name>
<iso-code>PY</iso-code>
<fips-code>PA</fips-code>
+ <timezones>
+ <timezone id="America/Asuncion" />
+ </timezones>
<tz-hint>America/Asuncion</tz-hint>
<city>
<!-- Translators: this is the capital of Paraguay -->
@@ -11610,6 +12643,9 @@
-->
<iso-code>PE</iso-code>
<fips-code>PE</fips-code>
+ <timezones>
+ <timezone id="America/Lima" />
+ </timezones>
<tz-hint>America/Lima</tz-hint>
<city>
<!-- Translators: this is a city in Peru -->
@@ -11837,6 +12873,9 @@
<_name>Saint Lucia</_name>
<iso-code>LC</iso-code>
<fips-code>ST</fips-code>
+ <timezones>
+ <timezone id="America/St_Lucia" />
+ </timezones>
<tz-hint>America/St_Lucia</tz-hint>
<city>
<!-- Translators: this is the capital of Saint Lucia -->
@@ -11877,6 +12916,9 @@
<_name>Saint Martin</_name>
<iso-code>MF</iso-code>
<fips-code>RN</fips-code>
+ <timezones>
+ <timezone id="America/Marigot" />
+ </timezones>
<tz-hint>America/Marigot</tz-hint>
</country>
<country>
@@ -11884,6 +12926,9 @@
<_name>Saint Vincent and the Grenadines</_name>
<iso-code>VC</iso-code>
<fips-code>VC</fips-code>
+ <timezones>
+ <timezone id="America/St_Vincent" />
+ </timezones>
<tz-hint>America/St_Vincent</tz-hint>
<city>
<!-- Translators: this is a city in Saint Vincent and the
@@ -11917,6 +12962,9 @@
<_name>South Georgia and the South Sandwich Islands</_name>
<iso-code>GS</iso-code>
<fips-code>SX</fips-code>
+ <timezones>
+ <timezone id="Atlantic/South_Georgia" />
+ </timezones>
<tz-hint>Atlantic/South_Georgia</tz-hint>
</country>
<country>
@@ -11928,6 +12976,9 @@
-->
<iso-code>SR</iso-code>
<fips-code>NS</fips-code>
+ <timezones>
+ <timezone id="America/Paramaribo" />
+ </timezones>
<tz-hint>America/Paramaribo</tz-hint>
<city>
<!-- Translators: this is the capital of Suriname -->
@@ -11955,6 +13006,9 @@
<_name>Trinidad and Tobago</_name>
<iso-code>TT</iso-code>
<fips-code>TD</fips-code>
+ <timezones>
+ <timezone id="America/Port_of_Spain" />
+ </timezones>
<tz-hint>America/Port_of_Spain</tz-hint>
<city>
<!-- Translators: this is a city in Trinidad and Tobago -->
@@ -11998,6 +13052,9 @@
-->
<iso-code>TC</iso-code>
<fips-code>TK</fips-code>
+ <timezones>
+ <timezone id="America/Grand_Turk" />
+ </timezones>
<tz-hint>America/Grand_Turk</tz-hint>
</country>
<country>
@@ -12005,6 +13062,9 @@
<_name>Uruguay</_name>
<iso-code>UY</iso-code>
<fips-code>UY</fips-code>
+ <timezones>
+ <timezone id="America/Montevideo" />
+ </timezones>
<tz-hint>America/Montevideo</tz-hint>
<city>
<!-- Translators: this is a city in Uruguay -->
@@ -12062,6 +13122,9 @@
<_name>Venezuela</_name>
<iso-code>VE</iso-code>
<fips-code>VE</fips-code>
+ <timezones>
+ <timezone id="America/Caracas" />
+ </timezones>
<tz-hint>America/Caracas</tz-hint>
<city>
<!-- Translators: this is a city in Venezuela -->
@@ -12417,6 +13480,9 @@
-->
<iso-code>AL</iso-code>
<fips-code>AL</fips-code>
+ <timezones>
+ <timezone id="Europe/Tirane" />
+ </timezones>
<tz-hint>Europe/Tirane</tz-hint>
<city>
<!-- Translators: this is a city in Albania -->
@@ -12472,6 +13538,9 @@
-->
<iso-code>AD</iso-code>
<fips-code>AN</fips-code>
+ <timezones>
+ <timezone id="Europe/Andorra" />
+ </timezones>
<tz-hint>Europe/Andorra</tz-hint>
</country>
<country>
@@ -12479,6 +13548,9 @@
<_name>Austria</_name>
<iso-code>AT</iso-code>
<fips-code>AU</fips-code>
+ <timezones>
+ <timezone id="Europe/Vienna" />
+ </timezones>
<tz-hint>Europe/Vienna</tz-hint>
<city>
<!-- Translators: this is a city in Austria.
@@ -12665,6 +13737,9 @@
-->
<iso-code>BY</iso-code>
<fips-code>BO</fips-code>
+ <timezones>
+ <timezone id="Europe/Minsk" />
+ </timezones>
<tz-hint>Europe/Minsk</tz-hint>
<city>
<!-- Translators: this is a city in Belarus -->
@@ -12747,6 +13822,9 @@
-->
<iso-code>BE</iso-code>
<fips-code>BE</fips-code>
+ <timezones>
+ <timezone id="Europe/Brussels" />
+ </timezones>
<tz-hint>Europe/Brussels</tz-hint>
<state>
<!-- Translators: This is a state in Belgium. local name (nl):
@@ -13086,6 +14164,9 @@
<_name>Bosnia and Herzegovina</_name>
<iso-code>BA</iso-code>
<fips-code>BK</fips-code>
+ <timezones>
+ <timezone id="Europe/Sarajevo" />
+ </timezones>
<tz-hint>Europe/Sarajevo</tz-hint>
<city>
<!-- Translators: this is a city in Bosnia and Herzegovina -->
@@ -13139,6 +14220,9 @@
-->
<iso-code>BG</iso-code>
<fips-code>BU</fips-code>
+ <timezones>
+ <timezone id="Europe/Sofia" />
+ </timezones>
<tz-hint>Europe/Sofia</tz-hint>
<city>
<!-- Translators: this is a city in Bulgaria -->
@@ -13254,6 +14338,9 @@
-->
<iso-code>HR</iso-code>
<fips-code>HR</fips-code>
+ <timezones>
+ <timezone id="Europe/Zagreb" />
+ </timezones>
<tz-hint>Europe/Zagreb</tz-hint>
<city>
<!-- Translators: this is a city in Croatia -->
@@ -13471,6 +14558,9 @@
<_name>Cyprus</_name>
<iso-code>CY</iso-code>
<fips-code>CY</fips-code>
+ <timezones>
+ <timezone id="Asia/Nicosia" />
+ </timezones>
<tz-hint>Asia/Nicosia</tz-hint>
<city>
<!-- Translators: this is a city in Cyprus -->
@@ -13537,6 +14627,9 @@
-->
<iso-code>CZ</iso-code>
<fips-code>EZ</fips-code>
+ <timezones>
+ <timezone id="Europe/Prague" />
+ </timezones>
<tz-hint>Europe/Prague</tz-hint>
<city>
<!-- Translators: this is a city in Czech Republic -->
@@ -13621,6 +14714,9 @@
-->
<iso-code>DK</iso-code>
<fips-code>DA</fips-code>
+ <timezones>
+ <timezone id="Europe/Copenhagen" />
+ </timezones>
<tz-hint>Europe/Copenhagen</tz-hint>
<city>
<!-- Translators: this is a city in Denmark -->
@@ -13875,6 +14971,9 @@
-->
<iso-code>EE</iso-code>
<fips-code>EN</fips-code>
+ <timezones>
+ <timezone id="Europe/Tallinn" />
+ </timezones>
<tz-hint>Europe/Tallinn</tz-hint>
<city>
<!-- Translators: this is a city in Estonia -->
@@ -13978,6 +15077,9 @@
-->
<iso-code>FO</iso-code>
<fips-code>FO</fips-code>
+ <timezones>
+ <timezone id="Atlantic/Faroe" />
+ </timezones>
<tz-hint>Atlantic/Faroe</tz-hint>
<city>
<!-- Translators: this is a city in Faroe Islands -->
@@ -14010,6 +15112,9 @@
<iso-code>FI</iso-code>
<fips-code>FI</fips-code>
<pref-lang>fin</pref-lang>
+ <timezones>
+ <timezone id="Europe/Helsinki" />
+ </timezones>
<tz-hint>Europe/Helsinki</tz-hint>
<city>
<!-- Translators: this is a city in Finland -->
@@ -14294,6 +15399,9 @@
-->
<iso-code>FR</iso-code>
<fips-code>FR</fips-code>
+ <timezones>
+ <timezone id="Europe/Paris" />
+ </timezones>
<tz-hint>Europe/Paris</tz-hint>
<city>
<!-- Translators: this is a city in France -->
@@ -15323,6 +16431,9 @@
-->
<iso-code>DE</iso-code>
<fips-code>GM</fips-code>
+ <timezones>
+ <timezone id="Europe/Berlin" />
+ </timezones>
<tz-hint>Europe/Berlin</tz-hint>
<state>
<!-- Translators: this is a state/province/territory in Germany -->
@@ -16479,6 +17590,9 @@
<_name>Gibraltar</_name>
<iso-code>GI</iso-code>
<fips-code>GI</fips-code>
+ <timezones>
+ <timezone id="Europe/Gibraltar" />
+ </timezones>
<tz-hint>Europe/Gibraltar</tz-hint>
<city>
<!-- Translators: this is the capital of Gibraltar -->
@@ -16506,6 +17620,9 @@
-->
<iso-code>GR</iso-code>
<fips-code>GR</fips-code>
+ <timezones>
+ <timezone id="Europe/Athens" />
+ </timezones>
<tz-hint>Europe/Athens</tz-hint>
<city>
<!-- Translators: this is a city in Greece -->
@@ -17081,6 +18198,11 @@
-->
<iso-code>GG</iso-code>
<fips-code>GK</fips-code>
+ <timezones>
+ <timezone id="Europe/Guernsey">
+ <_name>GMT/BST</_name>
+ </timezone>
+ </timezones>
<tz-hint>Europe/Guernsey</tz-hint>
<city>
<!-- Translators: this is a city in Guernsey -->
@@ -17120,6 +18242,9 @@
-->
<iso-code>HU</iso-code>
<fips-code>HU</fips-code>
+ <timezones>
+ <timezone id="Europe/Budapest" />
+ </timezones>
<tz-hint>Europe/Budapest</tz-hint>
<city>
<!-- Translators: this is the capital of Hungary -->
@@ -17257,6 +18382,9 @@
<_name>Iceland</_name>
<iso-code>IS</iso-code>
<fips-code>IC</fips-code>
+ <timezones>
+ <timezone id="Atlantic/Reykjavik" />
+ </timezones>
<tz-hint>Atlantic/Reykjavik</tz-hint>
<city>
<!-- Translators: this is a city in Iceland -->
@@ -17310,6 +18438,14 @@
-->
<iso-code>IE</iso-code>
<fips-code>EI</fips-code>
+ <timezones>
+ <timezone id="Europe/Dublin">
+ <!-- Translators: This is the time zone in Ireland (GMT in the
+ winter, and Irish Summer Time in the summer.)
+ -->
+ <_name>GMT/IST</_name>
+ </timezone>
+ </timezones>
<tz-hint>Europe/Dublin</tz-hint>
<city>
<!-- Translators: this is a city in Ireland.
@@ -17459,6 +18595,11 @@
<_name>Isle of Man</_name>
<iso-code>IM</iso-code>
<fips-code>IM</fips-code>
+ <timezones>
+ <timezone id="Europe/Isle_of_Man">
+ <_name>GMT/BST</_name>
+ </timezone>
+ </timezones>
<tz-hint>Europe/Isle_of_Man</tz-hint>
<city>
<!-- Translators: this is the capital of Isle of Man -->
@@ -17492,6 +18633,9 @@
-->
<iso-code>IT</iso-code>
<fips-code>IT</fips-code>
+ <timezones>
+ <timezone id="Europe/Rome" />
+ </timezones>
<tz-hint>Europe/Rome</tz-hint>
<city>
<!-- Translators: this is a city in Italy -->
@@ -18375,6 +19519,11 @@
<_name>Jersey</_name>
<iso-code>JE</iso-code>
<fips-code>JE</fips-code>
+ <timezones>
+ <timezone id="Europe/Jersey">
+ <_name>GMT/BST</_name>
+ </timezone>
+ </timezones>
<tz-hint>Europe/Jersey</tz-hint>
<city>
<!-- Translators: this is a city in Jersey -->
@@ -18412,6 +19561,9 @@
-->
<iso-code>LV</iso-code>
<fips-code>LG</fips-code>
+ <timezones>
+ <timezone id="Europe/Riga" />
+ </timezones>
<tz-hint>Europe/Riga</tz-hint>
<city>
<!-- Translators: this is a city in Latvia -->
@@ -18443,6 +19595,9 @@
-->
<iso-code>LI</iso-code>
<fips-code>LS</fips-code>
+ <timezones>
+ <timezone id="Europe/Vaduz" />
+ </timezones>
<tz-hint>Europe/Vaduz</tz-hint>
<city>
<!-- Translators: this is a city in Liechtenstein -->
@@ -18564,6 +19719,9 @@
-->
<iso-code>LT</iso-code>
<fips-code>LH</fips-code>
+ <timezones>
+ <timezone id="Europe/Vilnius" />
+ </timezones>
<tz-hint>Europe/Vilnius</tz-hint>
<city>
<!-- Translators: this is a city in Lithuania -->
@@ -18621,6 +19779,9 @@
<_name>Luxembourg</_name>
<iso-code>LU</iso-code>
<fips-code>LU</fips-code>
+ <timezones>
+ <timezone id="Europe/Luxembourg" />
+ </timezones>
<tz-hint>Europe/Luxembourg</tz-hint>
</country>
<country>
@@ -18643,6 +19804,9 @@
-->
<iso-code>MK</iso-code>
<fips-code>MK</fips-code>
+ <timezones>
+ <timezone id="Europe/Skopje" />
+ </timezones>
<tz-hint>Europe/Skopje</tz-hint>
<city>
<!-- Translators: this is a city in Macedonia -->
@@ -19190,6 +20354,9 @@
<_name>Malta</_name>
<iso-code>MT</iso-code>
<fips-code>MT</fips-code>
+ <timezones>
+ <timezone id="Europe/Malta" />
+ </timezones>
<tz-hint>Europe/Malta</tz-hint>
<city>
<!-- Translators: this is a city in Malta -->
@@ -19221,6 +20388,9 @@
-->
<iso-code>MD</iso-code>
<fips-code>MD</fips-code>
+ <timezones>
+ <timezone id="Europe/Chisinau" />
+ </timezones>
<tz-hint>Europe/Chisinau</tz-hint>
<city>
<!-- Translators: this is the capital of Moldova -->
@@ -19282,6 +20452,9 @@
-->
<iso-code>MC</iso-code>
<fips-code>MN</fips-code>
+ <timezones>
+ <timezone id="Europe/Monaco" />
+ </timezones>
<tz-hint>Europe/Monaco</tz-hint>
<city>
<!-- Translators: this is the capital of Monaco -->
@@ -19303,6 +20476,9 @@
-->
<iso-code>ME</iso-code>
<fips-code>MJ</fips-code>
+ <timezones>
+ <timezone id="Europe/Podgorica" />
+ </timezones>
<tz-hint>Europe/Podgorica</tz-hint>
<city>
<!-- Translators: this is a city in Montenegro -->
@@ -19338,6 +20514,9 @@
-->
<iso-code>NL</iso-code>
<fips-code>NL</fips-code>
+ <timezones>
+ <timezone id="Europe/Amsterdam" />
+ </timezones>
<tz-hint>Europe/Amsterdam</tz-hint>
<city>
<!-- Translators: this is a city in Netherlands -->
@@ -19576,6 +20755,9 @@
-->
<iso-code>NO</iso-code>
<fips-code>NO</fips-code>
+ <timezones>
+ <timezone id="Europe/Oslo" />
+ </timezones>
<tz-hint>Europe/Oslo</tz-hint>
<city>
<!-- Translators: this is a city in Norway -->
@@ -20192,6 +21374,9 @@
-->
<iso-code>PL</iso-code>
<fips-code>PL</fips-code>
+ <timezones>
+ <timezone id="Europe/Warsaw" />
+ </timezones>
<tz-hint>Europe/Warsaw</tz-hint>
<city>
<!-- Translators: this is a city in Poland -->
@@ -20301,6 +21486,28 @@
-->
<iso-code>PT</iso-code>
<fips-code>PO</fips-code>
+ <timezones>
+ <timezone id="Atlantic/Azores">
+ <!-- Translators: This refers to the time zone for the Azores.
+ The string is only used in places where "Portugal" is
+ already understood from context.
+ -->
+ <_name>Azores</_name>
+ </timezone>
+ <timezone id="Atlantic/Madeira">
+ <!-- Translators: This refers to the time zone for the
+ Portuguese island of Madeira. The string is only used in
+ places where "Portugal" is already understood from context.
+ -->
+ <_name>Madeira</_name>
+ </timezone>
+ <timezone id="Europe/Lisbon">
+ <!-- Translators: This refers to the time zone for mainland
+ Portugal (as opposed to the time zone for the Azores).
+ -->
+ <_name>Mainland Portugal</_name>
+ </timezone>
+ </timezones>
<tz-hint>Europe/Lisbon</tz-hint>
<city>
<!-- Translators: this is a city in Portugal -->
@@ -20580,6 +21787,9 @@
-->
<iso-code>RO</iso-code>
<fips-code>RO</fips-code>
+ <timezones>
+ <timezone id="Europe/Bucharest" />
+ </timezones>
<tz-hint>Europe/Bucharest</tz-hint>
<city>
<!-- Translators: this is a city in Romania -->
@@ -20822,6 +22032,109 @@
-->
<iso-code>RU</iso-code>
<fips-code>RS</fips-code>
+ <timezones>
+ <timezone id="Europe/Kaliningrad">
+ <!-- Translators: This is a Russian time zone, used in the city
+ and oblast of Kaliningrad on the Baltic sea. The Russian
+ name is "ÐÐÐÐÐÐÐÐÑÐÐÑÐÐÐ ÐÑÐÐÑ". This string is only used
+ in places where "Russia" is already clear from context.
+ -->
+ <_name>Kaliningrad Time</_name>
+ </timezone>
+ <timezone id="Europe/Moscow">
+ <!-- Translators: This is a Russian time zone, used in most of
+ the European part of Russia, including Moscow. The Russian
+ name is "ÐÐÑÐÐÐÑÐÐÐ ÐÑÐÐÑ". This string is only used in
+ places where "Russia" is already clear from context.
+ -->
+ <_name>Moscow Time</_name>
+ <obsoletes>Europe/Volgograd</obsoletes>
+ </timezone>
+ <timezone id="Europe/Samara">
+ <!-- Translators: This is a Russian time zone, used in the
+ Samara oblast and Udmurtia, on the eastern edge of European
+ Russia. The Russian name is "ÐÐÐÐÑÑÐÐÐ ÐÑÐÐÑ". This string
+ is only used in places where "Russia" is already clear from
+ context.
+ -->
+ <_name>Samara Time</_name>
+ </timezone>
+ <timezone id="Asia/Yekaterinburg">
+ <!-- Translators: This is a Russian time zone, used along the
+ Ural mountains, including the city of Yekaterinburg. The
+ Russian name is "ÐÐÐÑÐÑÐÐÐÑÑÐÑÐÐÐ ÐÑÐÐÑ". This string is
+ only used in places where "Russia" is already clear from
+ context.
+ -->
+ <_name>Yekaterinburg Time</_name>
+ </timezone>
+ <timezone id="Asia/Omsk">
+ <!-- Translators: This is a Russian time zone, used in the Omsk
+ and Novosibirsk oblasts and surrounding areas of
+ south-central Russia. The Russian name is "ÐÐÑÐÐÐ ÐÑÐÐÑ".
+ This string is only used in places where "Russia" is
+ already clear from context.
+ -->
+ <_name>Omsk Time</_name>
+ <obsoletes>Asia/Novosibirsk</obsoletes>
+ </timezone>
+ <timezone id="Asia/Krasnoyarsk">
+ <!-- Translators: This is a Russian time zone, used in the
+ Krasnoyarsk krai and surrounding areas of central Russia.
+ The Russian name is "ÐÑÐÑÐÐÑÑÑÐÐÐ ÐÑÐÐÑ". This string is
+ only used in places where "Russia" is already clear from
+ context.
+ -->
+ <_name>Krasnoyarsk Time</_name>
+ </timezone>
+ <timezone id="Asia/Irkutsk">
+ <!-- Translators: This is a Russian time zone, used in the
+ Irkutsk oblast and surrounding areas of south-central
+ Russia. The Russian name is "ÐÑÐÑÑÑÐÐÐ ÐÑÐÐÑ". This string
+ is only used in places where "Russia" is already clear from
+ context.
+ -->
+ <_name>Irkutsk Time</_name>
+ </timezone>
+ <timezone id="Asia/Yakutsk">
+ <!-- Translators: This is a Russian time zone, used in the city
+ of Yakutsk and surrounding areas of east-central Russia.
+ The Russian name is "ÐÐÑÑÑÐÐÐ ÐÑÐÐÑ". This string is only
+ used in places where "Russia" is already clear from
+ context.
+ -->
+ <_name>Yakutsk Time</_name>
+ </timezone>
+ <timezone id="Asia/Vladivostok">
+ <!-- Translators: This is a Russian time zone, used in the city
+ of Vladivostok and surrounding areas of eastern Russia. The
+ Russian name is "ÐÐÐÐÐÐÐÑÑÐÐÑÐÐÐ ÐÑÐÐÑ". This string is
+ only used in places where "Russia" is already clear from
+ context.
+ -->
+ <_name>Vladivostok Time</_name>
+ <obsoletes>Asia/Sakhalin</obsoletes>
+ </timezone>
+ <timezone id="Asia/Magadan">
+ <!-- Translators: This is a Russian time zone, used in the
+ Magadan oblast and surrounding areas of eastern Russia. The
+ Russian name is "ÐÐÐÐÐÐÐÑÐÐÐ ÐÑÐÐÑ". This string is only
+ used in places where "Russia" is already clear from
+ context.
+ -->
+ <_name>Magadan Time</_name>
+ </timezone>
+ <timezone id="Asia/Kamchatka">
+ <!-- Translators: This is a Russian time zone, used in the
+ Kamchatka krai and Chukotka okrug of far-eastern Russia.
+ The Russian name is "ÐÐÐÑÐÑÑÐÐÐ ÐÑÐÐÑ". This string is only
+ used in places where "Russia" is already clear from
+ context.
+ -->
+ <_name>Kamchatka Time</_name>
+ <obsoletes>Asia/Anadyr</obsoletes>
+ </timezone>
+ </timezones>
<city>
<!-- Translators: this is a city in Russia.
The local name in Russian is "ÐÐÐÐÐÐ".
@@ -21556,6 +22869,9 @@
-->
<iso-code>SM</iso-code>
<fips-code>SM</fips-code>
+ <timezones>
+ <timezone id="Europe/San_Marino" />
+ </timezones>
<tz-hint>Europe/San_Marino</tz-hint>
<city>
<!-- Translators: this is a city in San Marino -->
@@ -21603,6 +22919,9 @@
<_name>Serbia</_name>
<iso-code>RS</iso-code>
<fips-code>RB</fips-code>
+ <timezones>
+ <timezone id="Europe/Belgrade" />
+ </timezones>
<tz-hint>Europe/Belgrade</tz-hint>
<city>
<!-- Translators: this is the capital of Serbia.
@@ -21663,6 +22982,9 @@
<_name>Slovakia</_name>
<iso-code>SK</iso-code>
<fips-code>LO</fips-code>
+ <timezones>
+ <timezone id="Europe/Bratislava" />
+ </timezones>
<tz-hint>Europe/Bratislava</tz-hint>
<city>
<!-- Translators: this is a city in Slovakia -->
@@ -21834,6 +23156,9 @@
-->
<iso-code>SI</iso-code>
<fips-code>SI</fips-code>
+ <timezones>
+ <timezone id="Europe/Ljubljana" />
+ </timezones>
<tz-hint>Europe/Ljubljana</tz-hint>
<city>
<!-- Translators: this is the capital of Slovenia -->
@@ -21879,6 +23204,26 @@
-->
<iso-code>ES</iso-code>
<fips-code>SP</fips-code>
+ <timezones>
+ <timezone id="Atlantic/Canary">
+ <_name>Canary Islands</_name>
+ </timezone>
+ <timezone id="Europe/Madrid">
+ <!-- Translators: This refers to the time zone for mainland
+ Spain (as opposed to the time zone for the Canary
+ Islands).
+ -->
+ <_name>Mainland Spain</_name>
+ </timezone>
+ <timezone id="Africa/Ceuta">
+ <!-- Translators: This is the time zone for the Spanish cities
+ of Ceuta and Melilla, on the coast of Africa. The string is
+ only used in places where "Spain" is already clear from
+ context.
+ -->
+ <_name>Ceuta and Melilla</_name>
+ </timezone>
+ </timezones>
<tz-hint>Europe/Madrid</tz-hint>
<city>
<!-- Translators: this is a city in Spain -->
@@ -22494,6 +23839,9 @@
-->
<iso-code>SJ</iso-code>
<fips-code>SV|JN</fips-code>
+ <timezones>
+ <timezone id="Arctic/Longyearbyen" />
+ </timezones>
<tz-hint>Arctic/Longyearbyen</tz-hint>
<city>
<!-- Translators: this is the capital of Svalbard and Jan Mayen -->
@@ -22519,6 +23867,9 @@
-->
<iso-code>SE</iso-code>
<fips-code>SW</fips-code>
+ <timezones>
+ <timezone id="Europe/Stockholm" />
+ </timezones>
<tz-hint>Europe/Stockholm</tz-hint>
<city>
<!-- Translators: this is a city in Sweden -->
@@ -22894,6 +24245,9 @@
-->
<iso-code>CH</iso-code>
<fips-code>SZ</fips-code>
+ <timezones>
+ <timezone id="Europe/Zurich" />
+ </timezones>
<tz-hint>Europe/Zurich</tz-hint>
<city>
<!-- Translators: this is a city in Switzerland -->
@@ -23122,6 +24476,9 @@
-->
<iso-code>TR</iso-code>
<fips-code>TU</fips-code>
+ <timezones>
+ <timezone id="Europe/Istanbul" />
+ </timezones>
<tz-hint>Europe/Istanbul</tz-hint>
<city>
<!-- Translators: this is a city in Turkey -->
@@ -23463,6 +24820,13 @@
-->
<iso-code>UA</iso-code>
<fips-code>UP</fips-code>
+ <timezones>
+ <timezone id="Europe/Kiev">
+ <obsoletes>Europe/Simferopol</obsoletes>
+ <obsoletes>Europe/Uzhgorod</obsoletes>
+ <obsoletes>Europe/Zaporozhye</obsoletes>
+ </timezone>
+ </timezones>
<tz-hint>Europe/Kiev</tz-hint>
<city>
<!-- Translators: this is a city in Ukraine -->
@@ -23658,6 +25022,14 @@
-->
<iso-code>GB</iso-code>
<fips-code>UK</fips-code>
+ <timezones>
+ <timezone id="Europe/London">
+ <!-- Translators: This is the time zone in the UK (GMT in the
+ winter, and British Summer Time in the summer.)
+ -->
+ <_name>GMT/BST</_name>
+ </timezone>
+ </timezones>
<tz-hint>Europe/London</tz-hint>
<city>
<!-- Translators: this is a city in United Kingdom -->
@@ -27230,6 +28602,9 @@
<_name>Vatican City</_name>
<iso-code>VA</iso-code>
<fips-code>VT</fips-code>
+ <timezones>
+ <timezone id="Europe/Vatican" />
+ </timezones>
<tz-hint>Europe/Vatican</tz-hint>
</country>
<country>
@@ -27238,6 +28613,9 @@
<iso-code>AX</iso-code>
<fips-code>FI01</fips-code>
<pref-lang>swe</pref-lang>
+ <timezones>
+ <timezone id="Europe/Mariehamn" />
+ </timezones>
<tz-hint>Europe/Mariehamn</tz-hint>
<city>
<!-- Translators: this is a city in Ãland Islands.
@@ -27260,6 +28638,9 @@
<_name>Bahrain</_name>
<iso-code>BH</iso-code>
<fips-code>BA</fips-code>
+ <timezones>
+ <timezone id="Asia/Bahrain" />
+ </timezones>
<tz-hint>Asia/Bahrain</tz-hint>
<city>
<!-- Translators: this is a city in Bahrain.
@@ -27296,6 +28677,9 @@
-->
<iso-code>IR</iso-code>
<fips-code>IR</fips-code>
+ <timezones>
+ <timezone id="Asia/Tehran" />
+ </timezones>
<tz-hint>Asia/Tehran</tz-hint>
<city>
<!-- Translators: this is a city in Iran.
@@ -27848,6 +29232,9 @@
-->
<iso-code>IQ</iso-code>
<fips-code>IZ</fips-code>
+ <timezones>
+ <timezone id="Asia/Baghdad" />
+ </timezones>
<tz-hint>Asia/Baghdad</tz-hint>
</country>
<country>
@@ -27855,6 +29242,9 @@
<_name>Israel</_name>
<iso-code>IL</iso-code>
<fips-code>IS</fips-code>
+ <timezones>
+ <timezone id="Asia/Jerusalem" />
+ </timezones>
<tz-hint>Asia/Jerusalem</tz-hint>
<city>
<!-- Translators: this is a city in Israel -->
@@ -27922,6 +29312,9 @@
<_name>Jordan</_name>
<iso-code>JO</iso-code>
<fips-code>JO</fips-code>
+ <timezones>
+ <timezone id="Asia/Amman" />
+ </timezones>
<tz-hint>Asia/Amman</tz-hint>
<city>
<!-- Translators: this is a city in Jordan -->
@@ -27962,6 +29355,9 @@
<_name>Kuwait</_name>
<iso-code>KW</iso-code>
<fips-code>KU</fips-code>
+ <timezones>
+ <timezone id="Asia/Kuwait" />
+ </timezones>
<tz-hint>Asia/Kuwait</tz-hint>
<city>
<!-- Translators: this is the capital of Kuwait.
@@ -27982,6 +29378,9 @@
<_name>Lebanon</_name>
<iso-code>LB</iso-code>
<fips-code>LE</fips-code>
+ <timezones>
+ <timezone id="Asia/Beirut" />
+ </timezones>
<tz-hint>Asia/Beirut</tz-hint>
<city>
<!-- Translators: this is the capital of Lebanon.
@@ -28002,6 +29401,9 @@
<_name>Oman</_name>
<iso-code>OM</iso-code>
<fips-code>MU</fips-code>
+ <timezones>
+ <timezone id="Asia/Muscat" />
+ </timezones>
<tz-hint>Asia/Muscat</tz-hint>
<city>
<!-- Translators: this is a city in Oman -->
@@ -28042,6 +29444,9 @@
<_name>Palestinian Territory</_name>
<iso-code>PS</iso-code>
<fips-code>GZ|WE</fips-code>
+ <timezones>
+ <timezone id="Asia/Gaza" />
+ </timezones>
<tz-hint>Asia/Gaza</tz-hint>
</country>
<country>
@@ -28058,6 +29463,9 @@
-->
<iso-code>QA</iso-code>
<fips-code>QA</fips-code>
+ <timezones>
+ <timezone id="Asia/Qatar" />
+ </timezones>
<tz-hint>Asia/Qatar</tz-hint>
<city>
<!-- Translators: this is the capital of Qatar.
@@ -28087,6 +29495,9 @@
-->
<iso-code>SA</iso-code>
<fips-code>SA</fips-code>
+ <timezones>
+ <timezone id="Asia/Riyadh" />
+ </timezones>
<tz-hint>Asia/Riyadh</tz-hint>
<city>
<!-- Translators: this is a city in Saudi Arabia -->
@@ -28391,6 +29802,9 @@
<_name>Syria</_name>
<iso-code>SY</iso-code>
<fips-code>SY</fips-code>
+ <timezones>
+ <timezone id="Asia/Damascus" />
+ </timezones>
<tz-hint>Asia/Damascus</tz-hint>
<city>
<!-- Translators: this is a city in Syria -->
@@ -28461,6 +29875,9 @@
-->
<iso-code>AE</iso-code>
<fips-code>AE</fips-code>
+ <timezones>
+ <timezone id="Asia/Dubai" />
+ </timezones>
<tz-hint>Asia/Dubai</tz-hint>
<city>
<!-- Translators: this is the capital of United Arab Emirates.
@@ -28546,6 +29963,9 @@
-->
<iso-code>YE</iso-code>
<fips-code>YM</fips-code>
+ <timezones>
+ <timezone id="Asia/Aden" />
+ </timezones>
<tz-hint>Asia/Aden</tz-hint>
<city>
<!-- Translators: this is a city in Yemen -->
@@ -28705,6 +30125,114 @@
-->
<iso-code>CA</iso-code>
<fips-code>CA</fips-code>
+ <timezones>
+ <timezone id="America/Vancouver">
+ <!-- Translators: This is the time zone used on most of the west
+ coast of North America. In Mexico it is called "Tiempo del
+ PacÃfico" and in French-speaking parts of Canada it is
+ called "Heure du Pacifique". The string is only used in
+ places where "US", "Canada" or "Mexico" is already clear
+ from the context.
+ -->
+ <_name>Pacific Time</_name>
+ <obsoletes>America/Dawson</obsoletes>
+ <obsoletes>America/Whitehorse</obsoletes>
+ </timezone>
+ <timezone id="America/Edmonton">
+ <!-- Translators: This is the time zone used in the central-west
+ part of North America (ie, the Rocky Mountains). In Mexico
+ it is called "Tiempo de la MontaÃa", and in French-speaking
+ parts of Canada it is called "Heure des Rocheuses". The
+ string is only used in places where "US", "Canada" or
+ "Mexico" is already clear from the context.
+ -->
+ <_name>Mountain Time</_name>
+ <obsoletes>America/Cambridge_Bay</obsoletes>
+ <obsoletes>America/Inuvik</obsoletes>
+ <obsoletes>America/Yellowknife</obsoletes>
+ </timezone>
+ <timezone id="America/Dawson_Creek">
+ <!-- Translators: This represents the time zone in the
+ northeastern part of the Canadian province of British
+ Columbia (BC), which is part of the "Mountain Time" zone,
+ but does not observe Daylight Saving Time with the rest of
+ the zone.
+ -->
+ <_name>Mountain Time, no DST (Northeast BC)</_name>
+ </timezone>
+ <timezone id="America/Winnipeg">
+ <!-- Translators: This is the time zone used in the central-east
+ part of North America. In Mexico it is called "Tiempo del
+ Centro", and in French-speaking parts of Canada it is
+ called "Heure du Centre". The string is only used in places
+ where "US", "Canada" or "Mexico" is already clear from the
+ context.
+ -->
+ <_name>Central Time</_name>
+ <obsoletes>America/Rainy_River</obsoletes>
+ <obsoletes>America/Rankin_Inlet</obsoletes>
+ </timezone>
+ <timezone id="America/Regina">
+ <!-- Translators: This represents the time zone in the Canadian
+ province of Saskatchewan, which is part of the "Central
+ Time" zone, but does not observe Daylight Saving Time with
+ the rest of the zone.
+ -->
+ <_name>Central Time, no DST (Saskatchewan)</_name>
+ <obsoletes>America/Swift_Current</obsoletes>
+ </timezone>
+ <timezone id="America/Toronto">
+ <!-- Translators: This is the time zone used on the east coast
+ of the United States, and the corresponding (non-coastal)
+ part of Canada. In French-speaking parts of Canada it is
+ called "Heure de l'Est". The string is only used in places
+ where "US" or "Canada" is already clear from the context.
+ -->
+ <_name>Eastern Time</_name>
+ <obsoletes>America/Iqaluit</obsoletes>
+ <obsoletes>America/Montreal</obsoletes>
+ <obsoletes>America/Nipigon</obsoletes>
+ <obsoletes>America/Pangnirtung</obsoletes>
+ <obsoletes>America/Thunder_Bay</obsoletes>
+ </timezone>
+ <timezone id="America/Atikokan">
+ <!-- Translators: This represents the time zone in certain parts
+ of Canada (such as Southampton Island, Nunavut, and
+ Atikokan, Ontario) which are part of the "Eastern Time"
+ zone, but which do not observe Daylight Saving Time with
+ the rest of the zone.
+ -->
+ <_name>Eastern Time, no DST (Southampton Island, etc)</_name>
+ <obsoletes>America/Resolute</obsoletes>
+ </timezone>
+ <timezone id="America/Halifax">
+ <!-- Translators: This is the time zone used on the east coast
+ of Canada, in Bermuda, and on many Caribbean islands. In
+ French-speaking parts of Canada it is called "Heure de
+ l'Atlantique". The string is only used in places where a
+ country is already clear from the context.
+ -->
+ <_name>Atlantic Time</_name>
+ <obsoletes>America/Glace_Bay</obsoletes>
+ <obsoletes>America/Goose_Bay</obsoletes>
+ <obsoletes>America/Moncton</obsoletes>
+ </timezone>
+ <timezone id="America/Blanc-Sablon">
+ <!-- Translators: This represents the time zone in the far
+ eastern portion of the Canadian province of Quebec, which
+ is part of the "Atlantic Time" zone, but does not observe
+ Daylight Saving Time with the rest of the zone.
+ -->
+ <_name>Atlantic Time, no DST (Eastern Quebec)</_name>
+ </timezone>
+ <timezone id="America/St_Johns">
+ <!-- Translators: This is the time zone used in the Canadian
+ province of Newfoundland. In French-speaking parts of
+ Canada it is called "Heure de Terre-Neuve".
+ -->
+ <_name>Newfoundland Time</_name>
+ </timezone>
+ </timezones>
<state>
<!-- Translators: this is a state/province/territory in Canada -->
<_name>Alberta</_name>
@@ -33196,6 +34724,25 @@
-->
<iso-code>MX</iso-code>
<fips-code>MX</fips-code>
+ <timezones>
+ <!-- Translator comments for these timezone names appear in the
+ entry for Canada.
+ -->
+ <timezone id="America/Tijuana">
+ <_name>Pacific Time</_name>
+ </timezone>
+ <timezone id="America/Mazatlan">
+ <_name>Mountain Time</_name>
+ <obsoletes>America/Chihuahua</obsoletes>
+ <obsoletes>America/Hermosillo</obsoletes>
+ </timezone>
+ <timezone id="America/Mexico_City">
+ <_name>Central Time</_name>
+ <obsoletes>America/Cancun</obsoletes>
+ <obsoletes>America/Merida</obsoletes>
+ <obsoletes>America/Monterrey</obsoletes>
+ </timezone>
+ </timezones>
<state>
<!-- Translators: this is a state/province/territory in Mexico -->
<_name>Aguascalientes</_name>
@@ -34016,6 +35563,9 @@
<_name>Saint Pierre and Miquelon</_name>
<iso-code>PM</iso-code>
<fips-code>SB</fips-code>
+ <timezones>
+ <timezone id="America/Miquelon" />
+ </timezones>
<tz-hint>America/Miquelon</tz-hint>
<city>
<!-- Translators: this is the capital of Saint Pierre and
@@ -34079,6 +35629,78 @@
-->
<iso-code>US</iso-code>
<fips-code>US</fips-code>
+ <timezones>
+ <!-- Translator comments for PST, MST, CST, and EST appear in the
+ entry for Canada.
+ -->
+ <timezone id="America/Adak">
+ <!-- Translators: "Hawaiian-Aleutian Time" is the official name
+ of the time zone used in Hawaii and the Aleutian Islands of
+ Alaska in the United States. This string is for the time
+ zone as it is observed in the Aleutian Islands (with
+ Daylight Saving Time). It is only used in places where
+ "United States" is already clear from context.
+ -->
+ <_name>Hawaiian-Aleutian Time (Aleutian Islands)</_name>
+ </timezone>
+ <timezone id="Pacific/Honolulu">
+ <!-- Translators: "Hawaiian-Aleutian Time" is the official name
+ of the time zone used in Hawaii and the Aleutian Islands of
+ Alaska in the United States. This string is for the time
+ zone as it is observed in Hawaii, where they do not use
+ Daylight Saving Time. It is only used in places where
+ "United States" is already clear from context.
+ -->
+ <_name>Hawaiian-Aleutian Time, no DST (Hawaii)</_name>
+ </timezone>
+ <timezone id="America/Anchorage">
+ <!-- Translators: This is the time zone used in the majority of
+ Alaska in the United States. The string is only used in
+ places where "United States" is already clear from context.
+ -->
+ <_name>Alaska Time</_name>
+ <obsoletes>America/Juneau</obsoletes>
+ <obsoletes>America/Nome</obsoletes>
+ <obsoletes>America/Yakutat</obsoletes>
+ </timezone>
+ <timezone id="America/Los_Angeles">
+ <_name>Pacific Time</_name>
+ </timezone>
+ <timezone id="America/Denver">
+ <_name>Mountain Time</_name>
+ <obsoletes>America/Boise</obsoletes>
+ <obsoletes>America/Shiprock</obsoletes>
+ </timezone>
+ <timezone id="America/Phoenix">
+ <!-- Translators: This represents the time zone in the US state
+ of Arizona, which is part of the "Mountain Time" zone, but
+ does not observe Daylight Saving Time with the rest of the
+ zone. The string is only used in places where "United
+ States" is already clear from context.
+ -->
+ <_name>Mountain Time, no DST (Arizona)</_name>
+ </timezone>
+ <timezone id="America/Chicago">
+ <_name>Central Time</_name>
+ <obsoletes>America/Indiana/Knox</obsoletes>
+ <obsoletes>America/Indiana/Tell_City</obsoletes>
+ <obsoletes>America/Menominee</obsoletes> <!-- doot DOOO do do doo! -->
+ <obsoletes>America/North_Dakota/Center</obsoletes>
+ <obsoletes>America/North_Dakota/New_Salem</obsoletes>
+ </timezone>
+ <timezone id="America/New_York">
+ <_name>Eastern Time</_name>
+ <obsoletes>America/Detroit</obsoletes>
+ <obsoletes>America/Indiana/Indianapolis</obsoletes>
+ <obsoletes>America/Indiana/Marengo</obsoletes>
+ <obsoletes>America/Indiana/Petersburg</obsoletes>
+ <obsoletes>America/Indiana/Vevay</obsoletes>
+ <obsoletes>America/Indiana/Vincennes</obsoletes>
+ <obsoletes>America/Indiana/Winamac</obsoletes>
+ <obsoletes>America/Kentucky/Louisville</obsoletes>
+ <obsoletes>America/Kentucky/Monticello</obsoletes>
+ </timezone>
+ </timezones>
<state>
<!-- Translators: this is a state/province/territory in United
States
Modified: trunk/data/locations.dtd
==============================================================================
--- trunk/data/locations.dtd (original)
+++ trunk/data/locations.dtd Mon Aug 4 12:04:12 2008
@@ -5,11 +5,17 @@
<!ENTITY % name '(_name|name+)' >
<!ELEMENT region (%name;, country+) >
-<!ELEMENT country (%name;, iso-code, fips-code+, pref-lang?, tz-hint?, (location|state|city)*) >
+<!ELEMENT country (%name;, iso-code, fips-code+, pref-lang?, timezones, tz-hint?, (location|state|city)*) >
<!ELEMENT state (%name;, fips-code+, tz-hint?, (location|city)*) >
<!ELEMENT city (%name;, coordinates?, zone?, radar?, location+) >
<!ELEMENT location (%name;, code, tz-hint?, zone?, radar?, coordinates?) >
+<!ELEMENT timezones (timezone+) >
+<!ELEMENT timezone (_name?, name*, obsoletes*) >
+<!ATTLIST timezone
+ id CDATA #REQUIRED >
+<!ELEMENT obsoletes (#PCDATA) >
+
<!ELEMENT _name (#PCDATA) >
<!ELEMENT name (#PCDATA) >
<!ATTLIST name
Modified: trunk/libgweather/Makefile.am
==============================================================================
--- trunk/libgweather/Makefile.am (original)
+++ trunk/libgweather/Makefile.am Mon Aug 4 12:04:12 2008
@@ -1,7 +1,10 @@
lib_LTLIBRARIES = libgweather.la
libgweatherincdir = $(includedir)/libgweather
-libgweatherinc_HEADERS = weather.h gweather-gconf.h gweather-prefs.h gweather-xml.h
+libgweatherinc_HEADERS = \
+ weather.h gweather-gconf.h gweather-prefs.h gweather-xml.h \
+ gweather-location.h location-entry.h \
+ gweather-timezone.h timezone-menu.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = gweather.pc
@@ -13,7 +16,12 @@
weather-sun.c \
gweather-prefs.c gweather-prefs.h \
gweather-gconf.c gweather-gconf.h \
- gweather-xml.c gweather-xml.h
+ gweather-xml.c gweather-xml.h \
+ gweather-location.c gweather-location.h \
+ gweather-timezone.c gweather-timezone.h \
+ location-entry.c location-entry.h \
+ timezone-menu.c timezone-menu.h \
+ parser.c parser.h
libgweather_la_CFLAGS = \
-I$(top_srcdir) \
@@ -50,8 +58,20 @@
$(LIBSOUP_LIBS) \
libgweather.la
+test_locations_SOURCES = test_locations.c
+
+test_locations_CFLAGS = \
+ -I$(top_srcdir) \
+ -I$(srcdir) \
+ $(WARN_CFLAGS) \
+ $(GTK_CFLAGS) \
+ $(GNOME_VFS_APPLETS_CFLAGS) \
+ -DG_LOG_DOMAIN=\"GWeather\"
+
+test_locations_LDADD = libgweather.la
+
noinst_HEADERS = weather-priv.h
-noinst_PROGRAMS = test_metar
+noinst_PROGRAMS = test_metar test_locations
schemadir = @GCONF_SCHEMA_FILE_DIR@
schema_in_files = gweather.schemas.in
Added: trunk/libgweather/gweather-location.c
==============================================================================
--- (empty file)
+++ trunk/libgweather/gweather-location.c Mon Aug 4 12:04:12 2008
@@ -0,0 +1,567 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* gweather-locations.c - Location-handling code
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <string.h>
+#include <math.h>
+#include <locale.h>
+#include <gtk/gtk.h>
+#include <libxml/xmlreader.h>
+
+#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "gweather-location.h"
+#include "gweather-timezone.h"
+#include "parser.h"
+#include "weather-priv.h"
+
+struct _GWeatherLocation {
+ char *name, *sort_name;
+ GWeatherLocation *parent, **children;
+ GWeatherLocationLevel level;
+ char *country_code, *tz_hint;
+ char *station_code, *forecast_zone, *radar;
+ double latitude, longitude;
+ gboolean latlon_valid;
+ GWeatherTimezone **zones;
+
+ int ref_count;
+};
+
+static int
+sort_locations_by_name (gconstpointer a, gconstpointer b)
+{
+ GWeatherLocation *loc_a = *(GWeatherLocation **)a;
+ GWeatherLocation *loc_b = *(GWeatherLocation **)b;
+
+ return g_utf8_collate (loc_a->sort_name, loc_b->sort_name);
+}
+
+static int
+sort_locations_by_distance (gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ GWeatherLocation *loc_a = *(GWeatherLocation **)a;
+ GWeatherLocation *loc_b = *(GWeatherLocation **)b;
+ GWeatherLocation *city = (GWeatherLocation *)user_data;
+ double dist_a, dist_b;
+
+ dist_a = gweather_location_get_distance (loc_a, city);
+ dist_b = gweather_location_get_distance (loc_b, city);
+ if (dist_a < dist_b)
+ return -1;
+ else if (dist_a > dist_b)
+ return 1;
+ else
+ return 0;
+}
+
+/*
+ * Convert string of the form "DD-MM[-SS]H" to radians
+ * DD:degrees (to 3 digits), MM:minutes, SS:seconds H:hemisphere (NESW)
+ * Return value is positive for N,E; negative for S,W.
+ */
+static gboolean
+dmsh2rad (const char *latlon, double *value)
+{
+ char *p1, *p2;
+ int deg, min, sec, dir;
+
+ p1 = strchr (latlon, '-');
+ p2 = strrchr (latlon, '-');
+ if (p1 == NULL || p1 == latlon || p2 == p1 + 1)
+ return FALSE;
+
+ if (p1 == p2) {
+ sscanf (latlon, "%d-%d", °, &min);
+ sec = 0;
+ } else
+ sscanf (latlon, "%d-%d-%d", °, &min, &sec);
+ if (deg > 180 || min >= 60 || sec >= 60)
+ return FALSE;
+ *value = (double)((deg * 60 + min) * 60 + sec) * M_PI / 648000.0;
+
+ dir = g_ascii_toupper (latlon[strlen (latlon) - 1]);
+ if (dir == 'W' || dir == 'S')
+ *value = -*value;
+ else if (dir != 'E' && dir != 'N' && (*value != 0.0 || dir != '0'))
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean
+parse_coordinates (const char *coordinates,
+ double *latitude, double *longitude)
+{
+ char **pieces;
+ gboolean ret = FALSE;
+
+ pieces = g_strsplit (coordinates, " ", -1);
+ if (g_strv_length (pieces) == 2) {
+ ret = TRUE;
+ ret = ret && dmsh2rad (pieces[0], latitude);
+ ret = ret && dmsh2rad (pieces[1], longitude);
+ }
+
+ g_strfreev (pieces);
+ return ret;
+}
+
+static char *
+unparse_coordinates (double latitude, double longitude)
+{
+ int lat_d, lat_m, lat_s, lon_d, lon_m, lon_s;
+ char lat_dir, lon_dir;
+
+ latitude = latitude * 180.0 / M_PI;
+ longitude = longitude * 180.0 / M_PI;
+
+ if (latitude < 0.0) {
+ lat_dir = 'S';
+ latitude = -latitude;
+ } else
+ lat_dir = 'N';
+ if (longitude < 0.0) {
+ lon_dir = 'W';
+ longitude = -longitude;
+ } else
+ lon_dir = 'E';
+
+ lat_d = (int)latitude;
+ lat_m = (int)(latitude * 60.0) - lat_d * 60;
+ lat_s = (int)(latitude * 3600.0) - lat_d * 3600 - lat_m * 60;
+ lon_d = (int)longitude;
+ lon_m = (int)(longitude * 60.0) - lon_d * 60;
+ lon_s = (int)(longitude * 3600.0) - lon_d * 3600 - lon_m * 60;
+
+ return g_strdup_printf ("%02d-%02d-%02d%c %03d-%02d-%02d%c",
+ lat_d, lat_m, lat_s, lat_dir,
+ lon_d, lon_m, lon_s, lon_dir);
+}
+
+static GWeatherLocation *
+location_new_from_xml (GWeatherParser *parser, GWeatherLocationLevel level,
+ GWeatherLocation *parent)
+{
+ GWeatherLocation *loc, *child;
+ GPtrArray *children = NULL;
+ const char *tagname;
+ char *value, *normalized;
+ int tagtype, i;
+
+ loc = g_slice_new0 (GWeatherLocation);
+ loc->parent = parent;
+ loc->level = level;
+ loc->ref_count = 1;
+ children = g_ptr_array_new ();
+
+ if (xmlTextReaderRead (parser->xml) != 1)
+ goto error_out;
+ while ((tagtype = xmlTextReaderNodeType (parser->xml)) !=
+ XML_READER_TYPE_END_ELEMENT) {
+ if (tagtype != XML_READER_TYPE_ELEMENT) {
+ if (xmlTextReaderRead (parser->xml) != 1)
+ goto error_out;
+ continue;
+ }
+
+ tagname = (const char *) xmlTextReaderConstName (parser->xml);
+ if (!strcmp (tagname, "name") && !loc->name) {
+ value = gweather_parser_get_localized_value (parser);
+ if (!value)
+ goto error_out;
+ loc->name = g_strdup (value);
+ xmlFree (value);
+ normalized = g_utf8_normalize (loc->name, -1, G_NORMALIZE_ALL);
+ loc->sort_name = g_utf8_casefold (normalized, -1);
+ g_free (normalized);
+
+ } else if (!strcmp (tagname, "iso-code") && !loc->country_code) {
+ value = gweather_parser_get_value (parser);
+ if (!value)
+ goto error_out;
+ loc->country_code = g_strdup (value);
+ xmlFree (value);
+ } else if (!strcmp (tagname, "tz-hint") && !loc->tz_hint) {
+ value = gweather_parser_get_value (parser);
+ if (!value)
+ goto error_out;
+ loc->tz_hint = g_strdup (value);
+ xmlFree (value);
+ } else if (!strcmp (tagname, "code") && !loc->station_code) {
+ value = gweather_parser_get_value (parser);
+ if (!value)
+ goto error_out;
+ loc->station_code = g_strdup (value);
+ xmlFree (value);
+ } else if (!strcmp (tagname, "coordinates") && !loc->latlon_valid) {
+ value = gweather_parser_get_value (parser);
+ if (!value)
+ goto error_out;
+ if (parse_coordinates (value, &loc->latitude, &loc->longitude))
+ loc->latlon_valid = TRUE;
+ xmlFree (value);
+ } else if (!strcmp (tagname, "zone") && !loc->forecast_zone) {
+ value = gweather_parser_get_value (parser);
+ if (!value)
+ goto error_out;
+ loc->forecast_zone = g_strdup (value);
+ xmlFree (value);
+ } else if (!strcmp (tagname, "radar") && !loc->radar) {
+ value = gweather_parser_get_value (parser);
+ if (!value)
+ goto error_out;
+ loc->radar = g_strdup (value);
+ xmlFree (value);
+
+ } else if (!strcmp (tagname, "region")) {
+ child = location_new_from_xml (parser, GWEATHER_LOCATION_REGION, loc);
+ if (!child)
+ goto error_out;
+ if (parser->use_regions)
+ g_ptr_array_add (children, child);
+ else {
+ if (child->children) {
+ for (i = 0; child->children[i]; i++)
+ g_ptr_array_add (children, gweather_location_ref (child->children[i]));
+ }
+ gweather_location_unref (child);
+ }
+ } else if (!strcmp (tagname, "country")) {
+ child = location_new_from_xml (parser, GWEATHER_LOCATION_COUNTRY, loc);
+ if (!child)
+ goto error_out;
+ g_ptr_array_add (children, child);
+ } else if (!strcmp (tagname, "state")) {
+ child = location_new_from_xml (parser, GWEATHER_LOCATION_ADM1, loc);
+ if (!child)
+ goto error_out;
+ g_ptr_array_add (children, child);
+ } else if (!strcmp (tagname, "city")) {
+ child = location_new_from_xml (parser, GWEATHER_LOCATION_CITY, loc);
+ if (!child)
+ goto error_out;
+ g_ptr_array_add (children, child);
+ } else if (!strcmp (tagname, "location")) {
+ child = location_new_from_xml (parser, GWEATHER_LOCATION_WEATHER_STATION, loc);
+ if (!child)
+ goto error_out;
+ g_ptr_array_add (children, child);
+
+ } else if (!strcmp (tagname, "timezones")) {
+ loc->zones = gweather_timezones_parse_xml (parser);
+ if (!loc->zones)
+ goto error_out;
+
+ } else {
+ if (xmlTextReaderNext (parser->xml) != 1)
+ goto error_out;
+ }
+ }
+ if (xmlTextReaderRead (parser->xml) != 1 && parent)
+ goto error_out;
+
+ if (children->len) {
+ if (level == GWEATHER_LOCATION_CITY)
+ g_ptr_array_sort_with_data (children, sort_locations_by_distance, loc);
+ else
+ g_ptr_array_sort (children, sort_locations_by_name);
+
+ g_ptr_array_add (children, NULL);
+ loc->children = (GWeatherLocation **)g_ptr_array_free (children, FALSE);
+ } else
+ g_ptr_array_free (children, TRUE);
+
+ return loc;
+
+error_out:
+ gweather_location_unref (loc);
+ for (i = 0; i < children->len; i++)
+ gweather_location_unref (children->pdata[i]);
+ g_ptr_array_free (children, TRUE);
+
+ return NULL;
+}
+
+GWeatherLocation *
+gweather_location_new_world (gboolean use_regions)
+{
+ GWeatherParser *parser;
+ GWeatherLocation *world;
+
+ parser = gweather_parser_new (use_regions);
+ if (!parser)
+ return NULL;
+
+ world = location_new_from_xml (parser, GWEATHER_LOCATION_WORLD, NULL);
+
+ gweather_parser_free (parser);
+ return world;
+}
+
+GWeatherLocation *
+gweather_location_ref (GWeatherLocation *loc)
+{
+ loc->ref_count++;
+ return loc;
+}
+
+void
+gweather_location_unref (GWeatherLocation *loc)
+{
+ int i;
+
+ if (--loc->ref_count)
+ return;
+
+ g_free (loc->name);
+ g_free (loc->sort_name);
+ g_free (loc->country_code);
+ g_free (loc->tz_hint);
+ g_free (loc->station_code);
+ g_free (loc->forecast_zone);
+ g_free (loc->radar);
+
+ if (loc->children) {
+ for (i = 0; loc->children[i]; i++) {
+ loc->children[i]->parent = NULL;
+ gweather_location_unref (loc->children[i]);
+ }
+ g_free (loc->children);
+ }
+
+ if (loc->zones) {
+ for (i = 0; loc->zones[i]; i++)
+ gweather_timezone_unref (loc->zones[i]);
+ g_free (loc->zones);
+ }
+
+ g_slice_free (GWeatherLocation, loc);
+}
+
+const char *
+gweather_location_get_name (GWeatherLocation *loc)
+{
+ return loc->name;
+}
+
+const char *
+gweather_location_get_sort_name (GWeatherLocation *loc)
+{
+ return loc->sort_name;
+}
+
+GWeatherLocationLevel
+gweather_location_get_level (GWeatherLocation *loc)
+{
+ return loc->level;
+}
+
+GWeatherLocation *
+gweather_location_get_parent (GWeatherLocation *loc)
+{
+ return loc->parent;
+}
+
+GWeatherLocation **
+gweather_location_get_children (GWeatherLocation *loc)
+{
+ gweather_location_ref (loc);
+ if (loc->children)
+ return loc->children;
+ else
+ return g_new0 (GWeatherLocation *, 1);
+}
+
+void
+gweather_location_free_children (GWeatherLocation *loc,
+ GWeatherLocation **children)
+{
+ if (!loc->children)
+ g_free (children);
+ gweather_location_unref (loc);
+}
+
+gboolean
+gweather_location_has_coords (GWeatherLocation *loc)
+{
+ return loc->latlon_valid;
+}
+
+void
+gweather_location_get_coords (GWeatherLocation *loc,
+ double *latitude, double *longitude)
+{
+ //g_return_if_fail (loc->latlon_valid);
+
+ *latitude = loc->latitude / M_PI * 180.0;
+ *longitude = loc->longitude / M_PI * 180.0;
+}
+
+double
+gweather_location_get_distance (GWeatherLocation *loc, GWeatherLocation *loc2)
+{
+ /* average radius of the earth in km */
+ static const double radius = 6372.795;
+
+ //g_return_val_if_fail (loc->latlon_valid, 0.0);
+ //g_return_val_if_fail (loc2->latlon_valid, 0.0);
+
+ return acos (cos (loc->latitude) * cos (loc2->latitude) * cos (loc->longitude - loc2->longitude) +
+ sin (loc->latitude) * sin (loc2->latitude)) * radius;
+}
+
+const char *
+gweather_location_get_country (GWeatherLocation *loc)
+{
+ while (loc->parent && !loc->country_code)
+ loc = loc->parent;
+ return loc->country_code;
+}
+
+GWeatherTimezone *
+gweather_location_get_timezone (GWeatherLocation *loc)
+{
+ const char *tz_hint;
+ int i;
+
+ while (loc && !loc->tz_hint)
+ loc = loc->parent;
+ if (!loc)
+ return NULL;
+ tz_hint = loc->tz_hint;
+
+ while (loc) {
+ while (loc && !loc->zones)
+ loc = loc->parent;
+ if (!loc)
+ return NULL;
+ for (i = 0; loc->zones[i]; i++) {
+ if (!strcmp (tz_hint, gweather_timezone_get_tzid (loc->zones[i])))
+ return loc->zones[i];
+ }
+ loc = loc->parent;
+ }
+
+ return NULL;
+}
+
+static void
+add_timezones (GWeatherLocation *loc, GPtrArray *zones)
+{
+ int i;
+
+ if (loc->zones) {
+ for (i = 0; loc->zones[i]; i++)
+ g_ptr_array_add (zones, gweather_timezone_ref (loc->zones[i]));
+ }
+ if (loc->level < GWEATHER_LOCATION_COUNTRY && loc->children) {
+ for (i = 0; loc->children[i]; i++)
+ add_timezones (loc->children[i], zones);
+ }
+}
+
+GWeatherTimezone **
+gweather_location_get_timezones (GWeatherLocation *loc)
+{
+ GPtrArray *zones;
+
+ zones = g_ptr_array_new ();
+ add_timezones (loc, zones);
+ g_ptr_array_add (zones, NULL);
+ return (GWeatherTimezone **)g_ptr_array_free (zones, FALSE);
+}
+
+void
+gweather_location_free_timezones (GWeatherLocation *loc,
+ GWeatherTimezone **zones)
+{
+ int i;
+
+ for (i = 0; zones[i]; i++)
+ gweather_timezone_unref (zones[i]);
+ g_free (zones);
+}
+
+const char *
+gweather_location_get_code (GWeatherLocation *loc)
+{
+ return loc->station_code;
+}
+
+char *
+gweather_location_get_city_name (GWeatherLocation *loc)
+{
+ if (loc->level != GWEATHER_LOCATION_WEATHER_STATION ||
+ !loc->parent ||
+ loc->parent->level != GWEATHER_LOCATION_CITY)
+ return NULL;
+
+ return g_strdup (loc->parent->name);
+}
+
+WeatherLocation *
+gweather_location_to_weather_location (GWeatherLocation *gloc,
+ const char *name)
+{
+ const char *code = NULL, *zone = NULL, *radar = NULL, *tz_hint = NULL;
+ GWeatherLocation *l;
+ WeatherLocation *wloc;
+ char *coords;
+
+ if (!name)
+ name = gweather_location_get_name (gloc);
+
+ if (gloc->level == GWEATHER_LOCATION_CITY && gloc->children)
+ l = gloc->children[0];
+ else
+ l = gloc;
+
+ if (l->latlon_valid)
+ coords = unparse_coordinates (l->latitude, l->longitude);
+ else
+ coords = NULL;
+
+ while (l && (!code || !zone || !radar || !tz_hint)) {
+ if (!code && l->station_code)
+ code = l->station_code;
+ if (!zone && l->forecast_zone)
+ zone = l->forecast_zone;
+ if (!radar && l->radar)
+ radar = l->radar;
+ if (!tz_hint && l->tz_hint)
+ tz_hint = l->tz_hint;
+ l = l->parent;
+ }
+
+ wloc = weather_location_new (name, code, zone, radar, coords,
+ gweather_location_get_country (gloc),
+ tz_hint);
+ g_free (coords);
+ return wloc;
+}
+
+WeatherInfo *
+gweather_location_get_weather (GWeatherLocation *loc)
+{
+ WeatherLocation *wloc;
+ WeatherInfo *info;
+
+ wloc = gweather_location_to_weather_location (loc, NULL);
+ info = weather_info_new (wloc, NULL, NULL, NULL);
+ weather_location_free (wloc);
+ return info;
+}
Added: trunk/libgweather/gweather-location.h
==============================================================================
--- (empty file)
+++ trunk/libgweather/gweather-location.h Mon Aug 4 12:04:12 2008
@@ -0,0 +1,83 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* gweather-locations.c - Location-handling code
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef __GWEATHER_LOCATIONS_H__
+#define __GWEATHER_LOCATIONS_H__
+
+#ifndef GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#error "libgweather should only be used if you understand that it's subject to change, and is not supported as a fixed API/ABI or as part of the platform"
+#endif
+
+#include <glib.h>
+#include <libgweather/gweather-timezone.h>
+#include <libgweather/weather.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GWeatherLocation GWeatherLocation;
+typedef struct _GWeatherWeather GWeatherWeather;
+typedef struct _GWeatherForecast GWeatherForecast;
+
+typedef enum {
+ GWEATHER_LOCATION_WORLD,
+ GWEATHER_LOCATION_REGION,
+ GWEATHER_LOCATION_COUNTRY,
+ /* ADM1 = first-order administrative division = state/province, etc */
+ GWEATHER_LOCATION_ADM1,
+ /* ADM2 = second-order division = county, etc */
+ GWEATHER_LOCATION_ADM2,
+ GWEATHER_LOCATION_CITY,
+ GWEATHER_LOCATION_WEATHER_STATION
+} GWeatherLocationLevel;
+
+GWeatherLocation *gweather_location_new_world (gboolean use_regions);
+GWeatherLocation *gweather_location_ref (GWeatherLocation *loc);
+void gweather_location_unref (GWeatherLocation *loc);
+
+const char *gweather_location_get_name (GWeatherLocation *loc);
+const char *gweather_location_get_sort_name (GWeatherLocation *loc);
+GWeatherLocationLevel gweather_location_get_level (GWeatherLocation *loc);
+GWeatherLocation *gweather_location_get_parent (GWeatherLocation *loc);
+
+GWeatherLocation **gweather_location_get_children (GWeatherLocation *loc);
+void gweather_location_free_children (GWeatherLocation *loc,
+ GWeatherLocation **children);
+
+gboolean gweather_location_has_coords (GWeatherLocation *loc);
+void gweather_location_get_coords (GWeatherLocation *loc,
+ double *latitude,
+ double *longitude);
+double gweather_location_get_distance (GWeatherLocation *loc,
+ GWeatherLocation *loc2);
+
+const char *gweather_location_get_country (GWeatherLocation *loc);
+
+GWeatherTimezone *gweather_location_get_timezone (GWeatherLocation *loc);
+GWeatherTimezone **gweather_location_get_timezones (GWeatherLocation *loc);
+void gweather_location_free_timezones (GWeatherLocation *loc,
+ GWeatherTimezone **zones);
+
+const char *gweather_location_get_code (GWeatherLocation *loc);
+char *gweather_location_get_city_name (GWeatherLocation *loc);
+
+WeatherInfo *gweather_location_get_weather (GWeatherLocation *loc);
+
+G_END_DECLS
+
+#endif /* __GWEATHER_LOCATIONS_H__ */
Added: trunk/libgweather/gweather-timezone.c
==============================================================================
--- (empty file)
+++ trunk/libgweather/gweather-timezone.c Mon Aug 4 12:04:12 2008
@@ -0,0 +1,283 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* gweather-timezone.c - Timezone handling
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <string.h>
+
+#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "gweather-timezone.h"
+#include "parser.h"
+
+struct _GWeatherTimezone {
+ char *id, *name;
+ int offset, dst_offset;
+ gboolean has_dst;
+
+ int ref_count;
+};
+
+#define ZONEINFO_DIR "/usr/share/zoneinfo"
+
+#define TZ_MAGIC "TZif"
+#define TZ_HEADER_SIZE 44
+#define TZ_TIMECNT_OFFSET 32
+#define TZ_TRANSITIONS_OFFSET 44
+
+#define TZ_TTINFO_SIZE 6
+#define TZ_TTINFO_GMTOFF_OFFSET 0
+#define TZ_TTINFO_ISDST_OFFSET 4
+
+static gboolean
+parse_tzdata (const char *tzname, time_t start, time_t end,
+ int *offset, gboolean *has_dst, int *dst_offset)
+{
+ char *filename, *contents;
+ gsize length;
+ int timecnt, transitions_size, ttinfo_map_size;
+ int initial_transition = -1, second_transition = -1;
+ gint32 *transitions;
+ char *ttinfo_map, *ttinfos;
+ gint32 initial_offset, second_offset;
+ char initial_isdst, second_isdst;
+ int i;
+
+ filename = g_build_filename (ZONEINFO_DIR, tzname, NULL);
+ if (!g_file_get_contents (filename, &contents, &length, NULL)) {
+ g_free (filename);
+ return FALSE;
+ }
+ g_free (filename);
+
+ if (length < TZ_HEADER_SIZE ||
+ strncmp (contents, TZ_MAGIC, strlen (TZ_MAGIC)) != 0) {
+ g_free (contents);
+ return FALSE;
+ }
+
+ timecnt = GUINT32_FROM_BE (*(guint32 *)(contents + TZ_TIMECNT_OFFSET));
+ transitions = (void *)(contents + TZ_TRANSITIONS_OFFSET);
+ transitions_size = timecnt * sizeof (*transitions);
+ ttinfo_map = (void *)(contents + TZ_TRANSITIONS_OFFSET + transitions_size);
+ ttinfo_map_size = timecnt;
+ ttinfos = (void *)(ttinfo_map + ttinfo_map_size);
+
+ /* @transitions is an array of @timecnt time_t values. We need to
+ * find the transition into the current offset, which is the last
+ * transition before @start. If the following transition is before
+ * @end, then note that one too, since it presumably means we're
+ * doing DST.
+ */
+ for (i = 1; i < timecnt && initial_transition == -1; i++) {
+ if (GINT32_FROM_BE (transitions[i]) > start) {
+ initial_transition = ttinfo_map[i - 1];
+ if (GINT32_FROM_BE (transitions[i]) < end)
+ second_transition = ttinfo_map[i];
+ }
+ }
+ if (initial_transition == -1) {
+ if (timecnt)
+ initial_transition = ttinfo_map[timecnt - 1];
+ else
+ initial_transition = 0;
+ }
+
+ /* Copy the data out of the corresponding ttinfo structs */
+ initial_offset = *(gint32 *)(ttinfos +
+ initial_transition * TZ_TTINFO_SIZE +
+ TZ_TTINFO_GMTOFF_OFFSET);
+ initial_offset = GINT32_FROM_BE (initial_offset);
+ initial_isdst = *(ttinfos +
+ initial_transition * TZ_TTINFO_SIZE +
+ TZ_TTINFO_ISDST_OFFSET);
+
+ if (second_transition != -1) {
+ second_offset = *(gint32 *)(ttinfos +
+ second_transition * TZ_TTINFO_SIZE +
+ TZ_TTINFO_GMTOFF_OFFSET);
+ second_offset = GINT32_FROM_BE (second_offset);
+ second_isdst = *(ttinfos +
+ second_transition * TZ_TTINFO_SIZE +
+ TZ_TTINFO_ISDST_OFFSET);
+
+ *has_dst = (initial_isdst != second_isdst);
+ } else
+ *has_dst = FALSE;
+
+ if (!*has_dst)
+ *offset = initial_offset / 60;
+ else {
+ if (initial_isdst) {
+ *offset = second_offset / 60;
+ *dst_offset = initial_offset / 60;
+ } else {
+ *offset = initial_offset / 60;
+ *dst_offset = second_offset / 60;
+ }
+ }
+
+ g_free (contents);
+ return TRUE;
+}
+
+static GWeatherTimezone *
+parse_timezone (GWeatherParser *parser)
+{
+ GWeatherTimezone *zone = NULL;
+ char *id = NULL, *name = NULL;
+ int offset, dst_offset;
+ gboolean has_dst = FALSE;
+
+ id = (char *) xmlTextReaderGetAttribute (parser->xml, (xmlChar *) "id");
+ if (!id) {
+ xmlTextReaderNext (parser->xml);
+ return NULL;
+ }
+
+ if (!xmlTextReaderIsEmptyElement (parser->xml)) {
+ if (xmlTextReaderRead (parser->xml) != 1) {
+ xmlFree (id);
+ return NULL;
+ }
+
+ while (xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_END_ELEMENT) {
+ if (xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_ELEMENT) {
+ if (xmlTextReaderRead (parser->xml) != 1)
+ break;
+ continue;
+ }
+
+ if (!strcmp ((const char *) xmlTextReaderConstName (parser->xml), "name"))
+ name = gweather_parser_get_localized_value (parser);
+ else {
+ if (xmlTextReaderNext (parser->xml) != 1)
+ break;
+ }
+ }
+ }
+
+ if (parse_tzdata (id, parser->year_start, parser->year_end,
+ &offset, &has_dst, &dst_offset)) {
+ zone = g_slice_new0 (GWeatherTimezone);
+ zone->ref_count = 1;
+ zone->id = g_strdup (id);
+ zone->name = g_strdup (name);
+ zone->offset = offset;
+ zone->has_dst = has_dst;
+ zone->dst_offset = dst_offset;
+ }
+
+ xmlFree (id);
+ if (name)
+ xmlFree (name);
+
+ return zone;
+}
+
+GWeatherTimezone **
+gweather_timezones_parse_xml (GWeatherParser *parser)
+{
+ GPtrArray *zones;
+ GWeatherTimezone *zone;
+ const char *tagname;
+ int tagtype, i;
+
+ zones = g_ptr_array_new ();
+
+ if (xmlTextReaderRead (parser->xml) != 1)
+ goto error_out;
+ while ((tagtype = xmlTextReaderNodeType (parser->xml)) !=
+ XML_READER_TYPE_END_ELEMENT) {
+ if (tagtype != XML_READER_TYPE_ELEMENT) {
+ if (xmlTextReaderRead (parser->xml) != 1)
+ goto error_out;
+ continue;
+ }
+
+ tagname = (const char *) xmlTextReaderConstName (parser->xml);
+
+ if (!strcmp (tagname, "timezone")) {
+ zone = parse_timezone (parser);
+ if (!zone)
+ goto error_out;
+ g_ptr_array_add (zones, zone);
+ }
+
+ if (xmlTextReaderNext (parser->xml) != 1)
+ goto error_out;
+ }
+ if (xmlTextReaderRead (parser->xml) != 1)
+ goto error_out;
+
+ g_ptr_array_add (zones, NULL);
+ return (GWeatherTimezone **)g_ptr_array_free (zones, FALSE);
+
+error_out:
+ for (i = 0; i < zones->len; i++)
+ gweather_timezone_unref (zones->pdata[i]);
+ g_ptr_array_free (zones, TRUE);
+ return NULL;
+}
+
+GWeatherTimezone *
+gweather_timezone_ref (GWeatherTimezone *zone)
+{
+ zone->ref_count++;
+ return zone;
+}
+
+void
+gweather_timezone_unref (GWeatherTimezone *zone)
+{
+ if (!--zone->ref_count) {
+ g_free (zone->id);
+ g_free (zone->name);
+ g_slice_free (GWeatherTimezone, zone);
+ }
+}
+
+const char *
+gweather_timezone_get_name (GWeatherTimezone *zone)
+{
+ return zone->name;
+}
+
+const char *
+gweather_timezone_get_tzid (GWeatherTimezone *zone)
+{
+ return zone->id;
+}
+
+int
+gweather_timezone_get_offset (GWeatherTimezone *zone)
+{
+ return zone->offset;
+}
+
+gboolean
+gweather_timezone_has_dst (GWeatherTimezone *zone)
+{
+ return zone->has_dst;
+}
+
+int
+gweather_timezone_get_dst_offset (GWeatherTimezone *zone)
+{
+ g_return_val_if_fail (zone->has_dst, 0);
+ return zone->dst_offset;
+}
+
Added: trunk/libgweather/gweather-timezone.h
==============================================================================
--- (empty file)
+++ trunk/libgweather/gweather-timezone.h Mon Aug 4 12:04:12 2008
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* gweather-timezone.c - Timezones
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef __GWEATHER_TIMEZONE_H__
+#define __GWEATHER_TIMEZONE_H__
+
+#ifndef GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#error "libgweather should only be used if you understand that it's subject to change, and is not supported as a fixed API/ABI or as part of the platform"
+#endif
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GWeatherTimezone GWeatherTimezone;
+
+const char *gweather_timezone_get_name (GWeatherTimezone *zone);
+const char *gweather_timezone_get_tzid (GWeatherTimezone *zone);
+int gweather_timezone_get_offset (GWeatherTimezone *zone);
+gboolean gweather_timezone_has_dst (GWeatherTimezone *zone);
+int gweather_timezone_get_dst_offset (GWeatherTimezone *zone);
+
+GWeatherTimezone *gweather_timezone_ref (GWeatherTimezone *zone);
+void gweather_timezone_unref (GWeatherTimezone *zone);
+
+G_END_DECLS
+
+#endif /* __GWEATHER_TIMEZONE_H__ */
Modified: trunk/libgweather/gweather-xml.c
==============================================================================
--- trunk/libgweather/gweather-xml.c (original)
+++ trunk/libgweather/gweather-xml.c Mon Aug 4 12:04:12 2008
@@ -18,53 +18,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-
-/* There is very little error checking in the parsing code below, it relies
- * heavily on the locations file being in the correct format. If you have
- * <name> elements within a parent element, they must come first and be
- * grouped together.
- * The format is as follows:
- *
- * <gweather format="1.0">
- * <region>
- * <name>Name of the region</name>
- * <name xml:lang="xx">Translated Name</name>
- * <name xml:lang="zz">Another Translated Name</name>
- * <country>
- * <name>Name of the country</name>
- * <iso-code>2-letter ISO 3166 code for the country</iso-code>
- * <tz-hint>default timezone</tz-hint>
- * <location>
- * <name>Name of the location</name>
- * <code>IWIN code</code>
- * <zone>Forecast code (North America, Australia, UK only)</zone>
- * <radar>Weather.com radar map code (North America only)</radar>
- * <coordinates>Latitude and longitude as DD-MM[-SS][H] pair</coordinates>
- * </location>
- * <state>
- * <location>
- * ....
- * </location>
- * <city>
- * <name>Name of city with multiple locations</city>
- * <zone>Forecast code</zone>
- * <radar>Radar Map code</radar>
- * <location>
- * ...
- * </location>
- * </city>
- * </state>
- * </country>
- * </region>
- * <gweather>
- *
- * The thing to note is that each country can either contain different locations
- * or be split into "states" which in turn contain a list of locations.
- *
- * <iso-code> can appear at the country or location level. <tz-hint>
- * can appear at country, state, or location.
- */
-
#include <string.h>
#include <math.h>
#include <locale.h>
@@ -73,375 +26,106 @@
#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
#include "gweather-xml.h"
-
-static gint
-gweather_xml_location_sort_func (GtkTreeModel *model, GtkTreeIter *a,
- GtkTreeIter *b, gpointer user_data)
-{
- gint res;
- gchar *name_a, *name_b;
- gchar *fold_a, *fold_b;
-
- gtk_tree_model_get (model, a, GWEATHER_XML_COL_LOC, &name_a, -1);
- gtk_tree_model_get (model, b, GWEATHER_XML_COL_LOC, &name_b, -1);
-
- fold_a = g_utf8_casefold (name_a, -1);
- fold_b = g_utf8_casefold (name_b, -1);
-
- res = g_utf8_collate (fold_a, fold_b);
-
- g_free (name_a);
- g_free (name_b);
- g_free (fold_a);
- g_free (fold_b);
-
- return res;
-}
-
-static char *
-gweather_xml_get_value (xmlTextReaderPtr xml)
-{
- char* value;
-
- /* check for null node */
- if (xmlTextReaderIsEmptyElement (xml))
- return NULL;
-
- /* the next "node" is the text node containing the value we want to get */
- if (xmlTextReaderRead (xml) != 1)
- return NULL;
-
- value = (char *) xmlTextReaderValue (xml);
-
- /* move on to the end of this node */
- while (xmlTextReaderNodeType (xml) != XML_READER_TYPE_END_ELEMENT) {
- if (xmlTextReaderRead (xml) != 1) {
- xmlFree (value);
- return NULL;
- }
- }
-
- /* consume the end element too */
- if (xmlTextReaderRead (xml) != 1) {
- xmlFree (value);
- return NULL;
- }
-
- return value;
-}
-
-static char *
-gweather_xml_parse_name (xmlTextReaderPtr xml)
-{
- const char * const *locales;
- const char *this_language;
- int best_match = INT_MAX;
- char *lang, *tagname;
- gboolean keep_going;
- char *name = NULL;
- int i;
-
- locales = g_get_language_names ();
-
- do {
- /* First let's get the language */
- lang = (char *) xmlTextReaderXmlLang (xml);
-
- if (lang == NULL)
- this_language = "C";
- else
- this_language = lang;
-
- /* the next "node" is text node containing the actual name */
- if (xmlTextReaderRead (xml) != 1) {
- xmlFree (lang);
- return NULL;
- }
-
- for (i = 0; locales[i] && i < best_match; i++) {
- if (!strcmp (locales[i], this_language)) {
- /* if we've already encounted a less accurate
- translation, then free it */
- xmlFree (name);
-
- name = (char *) xmlTextReaderValue (xml);
- best_match = i;
-
- break;
- }
- }
-
- xmlFree (lang);
-
- while (xmlTextReaderNodeType (xml) != XML_READER_TYPE_ELEMENT) {
- if (xmlTextReaderRead (xml) != 1) {
- xmlFree (name);
- return NULL;
- }
-
- /* if the next tag is another <name> then keep going */
- tagname = (char *) xmlTextReaderName (xml);
- keep_going = !strcmp (tagname, "name");
- xmlFree (tagname);
- }
-
- } while (keep_going);
-
- return name;
-}
+#include "weather-priv.h"
static gboolean
-gweather_xml_parse_node (xmlTextReaderPtr xml,
- GtkTreeStore *store, GtkTreeIter *parent,
- const char *dflt_radar, const char *dflt_zone,
- const char *dflt_country_code,
- const char *dflt_tz_hint, const char *cityname)
+gweather_xml_parse_node (GWeatherLocation *gloc,
+ GtkTreeStore *store, GtkTreeIter *parent)
{
- char *name, *code, *zone, *radar, *coordinates;
- char *country_code, *tz_hint;
- char **city, *nocity = NULL;
- GtkTreeIter iter, *self;
- gboolean is_location;
- char *tagname;
- gboolean ret = FALSE;
- int tagtype;
-
- if ((tagname = (char *) xmlTextReaderName (xml)) == NULL)
- return FALSE;
-
- if (!strcmp (tagname, "city"))
- city = &name;
- else
- city = &nocity;
-
- is_location = !strcmp (tagname, "location");
-
- /* if we're processing the top-level, then don't create a new iter */
- if (!strcmp (tagname, "gweather"))
- self = NULL;
- else {
- self = &iter;
- /* insert this node into the tree */
- gtk_tree_store_append (store, self, parent);
- }
-
- xmlFree (tagname);
-
- coordinates = NULL;
- radar = NULL;
- zone = NULL;
- code = NULL;
- name = NULL;
-
- country_code = dflt_country_code ? (char *) xmlStrdup ((xmlChar *) dflt_country_code) : NULL;
- tz_hint = dflt_tz_hint ? (char *) xmlStrdup ((xmlChar *) dflt_tz_hint) : NULL;
-
- /* absorb the start tag */
- if (xmlTextReaderRead (xml) != 1)
- goto error_out;
-
- /* start parsing the actual contents of the node */
- while ((tagtype = xmlTextReaderNodeType (xml)) !=
- XML_READER_TYPE_END_ELEMENT) {
- /* skip non-element types */
- if (tagtype != XML_READER_TYPE_ELEMENT) {
- if (xmlTextReaderRead (xml) != 1)
- goto error_out;
-
- continue;
- }
-
- tagname = (char *) xmlTextReaderName (xml);
-
- if (!strcmp (tagname, "region") || !strcmp (tagname, "country") ||
- !strcmp (tagname, "state") || !strcmp (tagname, "city") ||
- !strcmp (tagname, "location")) {
- /* recursively handle sub-sections */
- if (!gweather_xml_parse_node (xml, store, self,
- radar, zone, country_code, tz_hint,
- *city))
- goto error_out;
- } else if (!strcmp (tagname, "name")) {
- xmlFree (name);
- if ((name = gweather_xml_parse_name (xml)) == NULL)
- goto error_out;
- } else if (!strcmp (tagname, "iso-code")) {
- xmlFree (country_code);
- if ((country_code = gweather_xml_get_value (xml)) == NULL)
- goto error_out;
- } else if (!strcmp (tagname, "tz-hint")) {
- xmlFree (tz_hint);
- if ((tz_hint = gweather_xml_get_value (xml)) == NULL)
- goto error_out;
- } else if (!strcmp (tagname, "code")) {
- xmlFree (code);
- if ((code = gweather_xml_get_value (xml)) == NULL)
- goto error_out;
- } else if (!strcmp (tagname, "zone")) {
- xmlFree (zone);
- if ((zone = gweather_xml_get_value (xml)) == NULL)
- goto error_out;
- } else if (!strcmp (tagname, "radar")) {
- xmlFree (radar);
- if ((radar = gweather_xml_get_value (xml)) == NULL)
- goto error_out;
- } else if (!strcmp (tagname, "coordinates")) {
- xmlFree (coordinates);
- if ((coordinates = gweather_xml_get_value (xml)) == NULL)
- goto error_out;
- } else /* some strange tag */ {
- /* skip past it (and any children it might have) */
- if (xmlTextReaderNext (xml) != 1)
- goto error_out;
- }
-
- xmlFree (tagname);
- }
-
- if (self)
- gtk_tree_store_set (store, self, GWEATHER_XML_COL_LOC, name, -1);
-
- /* if this is an actual location, setup the WeatherLocation for it */
- if (is_location) {
- WeatherLocation *new_loc;
-
- if (cityname == NULL)
- cityname = name;
-
- if (radar != NULL)
- dflt_radar = radar;
-
- if (zone != NULL)
- dflt_zone = zone;
-
- new_loc = weather_location_new (cityname, code, dflt_zone,
- dflt_radar, coordinates,
- country_code, tz_hint);
-
- gtk_tree_store_set (store, self, GWEATHER_XML_COL_POINTER, new_loc, -1);
- }
- /* if this is not a location and there's no child, then it's useless */
- else if (self && !gtk_tree_model_iter_has_child (GTK_TREE_MODEL (store), self)) {
- gtk_tree_store_remove (store, self);
- }
+ GtkTreeIter iter, *self = &iter;
+ GWeatherLocation **children, *parent_loc;
+ GWeatherLocationLevel level;;
+ WeatherLocation *wloc;
+ const char *name;
+ int i;
- /* if this is a city with only one location, then we merge the location and
- * the city */
- if (*city) {
- int n_children;
-
- n_children = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store),
- self);
- if (n_children == 1) {
- GtkTreeIter child;
- WeatherLocation *loc;
-
- gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &child, self);
- gtk_tree_model_get (GTK_TREE_MODEL (store), &child,
- GWEATHER_XML_COL_POINTER, &loc, -1);
- gtk_tree_store_remove (store, &child);
- gtk_tree_store_set (store, self, GWEATHER_XML_COL_POINTER, loc, -1);
+ name = gweather_location_get_name (gloc);
+ children = gweather_location_get_children (gloc);
+ level = gweather_location_get_level (gloc);
+
+ if (!children[0] && level < GWEATHER_LOCATION_WEATHER_STATION) {
+ gweather_location_free_children (gloc, children);
+ return TRUE;
+ }
+
+ switch (gweather_location_get_level (gloc)) {
+ case GWEATHER_LOCATION_WORLD:
+ case GWEATHER_LOCATION_ADM2:
+ self = parent;
+ break;
+
+ case GWEATHER_LOCATION_REGION:
+ case GWEATHER_LOCATION_COUNTRY:
+ case GWEATHER_LOCATION_ADM1:
+ /* Create a row with a name but no WeatherLocation */
+ gtk_tree_store_append (store, &iter, parent);
+ gtk_tree_store_set (store, &iter,
+ GWEATHER_XML_COL_LOC, name,
+ -1);
+ break;
+
+ case GWEATHER_LOCATION_CITY:
+ /* If multiple children, treat this like a
+ * region/country/adm1. If a single child, merge with that
+ * location.
+ */
+ gtk_tree_store_append (store, &iter, parent);
+ gtk_tree_store_set (store, &iter,
+ GWEATHER_XML_COL_LOC, name,
+ -1);
+ if (children[0] && !children[1]) {
+ wloc = gweather_location_to_weather_location (children[0], name);
+ gtk_tree_store_set (store, &iter,
+ GWEATHER_XML_COL_POINTER, wloc,
+ -1);
+ }
+ break;
+
+ case GWEATHER_LOCATION_WEATHER_STATION:
+ gtk_tree_store_append (store, &iter, parent);
+ gtk_tree_store_set (store, &iter,
+ GWEATHER_XML_COL_LOC, name,
+ -1);
+
+ parent_loc = gweather_location_get_parent (gloc);
+ if (parent_loc && gweather_location_get_level (parent_loc) == GWEATHER_LOCATION_CITY)
+ name = gweather_location_get_name (parent_loc);
+ wloc = gweather_location_to_weather_location (gloc, name);
+ gtk_tree_store_set (store, &iter,
+ GWEATHER_XML_COL_POINTER, wloc,
+ -1);
+ break;
+ }
+
+ for (i = 0; children[i]; i++) {
+ if (!gweather_xml_parse_node (children[i], store, self)) {
+ gweather_location_free_children (gloc, children);
+ return FALSE;
}
}
- /* absorb the end tag. in the case of processing a <gweather> then 'self'
- is NULL. In this case, we let this fail since we might be at EOF */
- if (xmlTextReaderRead (xml) == 1 || !self)
- ret = TRUE;
-
-error_out:
- xmlFree (name);
- xmlFree (code);
- xmlFree (zone);
- xmlFree (radar);
- xmlFree (coordinates);
- xmlFree (country_code);
- xmlFree (tz_hint);
-
- return ret;
+ gweather_location_free_children (gloc, children);
+ return TRUE;
}
GtkTreeModel *
gweather_xml_load_locations (void)
{
- const char * const *languages;
- int i;
- char *filename;
- char *tagname, *format;
- GtkTreeSortable *sortable;
- GtkTreeStore *store = NULL;
- xmlTextReaderPtr xml;
- int keep_going;
-
- /* First try to load a locale-specific XML. It's much faster. */
- languages = g_get_language_names ();
- filename = NULL;
-
- for (i = 0; languages[i] != NULL; i++) {
- filename = g_strdup_printf ("%s/Locations.%s.xml",
- GWEATHER_XML_LOCATION_DIR, languages[i]);
-
- if (g_file_test (filename, G_FILE_TEST_IS_REGULAR))
- break;
-
- g_free (filename);
- filename = NULL;
- }
-
- /* Fallback on the file containing either all translations, or only
- * the english names (depending on the configure flags). Note that it's
- * also the file that is advertised in our pkg-config file, so it's
- * part of the API. */
- if (!filename)
- filename = g_strdup (GWEATHER_XML_LOCATION_DIR "/Locations.xml");
-
- /* Open the xml file containing the different locations */
- xml = xmlNewTextReaderFilename (filename);
- g_free (filename);
+ GWeatherLocation *world;
+ GtkTreeStore *store;
- if (xml == NULL)
+ world = gweather_location_new_world (TRUE);
+ if (!world)
return NULL;
- /* fast forward to the first element */
- do {
- /* if we encounter a problem here, exit right away */
- if (xmlTextReaderRead (xml) != 1)
- goto error_out;
- } while (xmlTextReaderNodeType (xml) != XML_READER_TYPE_ELEMENT);
-
- /* check the name and format */
- tagname = (char *) xmlTextReaderName (xml);
- keep_going = tagname && !strcmp (tagname, "gweather");
- xmlFree (tagname);
-
- if (!keep_going)
- goto error_out;
-
- format = (char *) xmlTextReaderGetAttribute (xml, (xmlChar *) "format");
- keep_going = format && !strcmp (format, "1.0");
- xmlFree (format);
-
- if (!keep_going)
- goto error_out;
-
store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
- if (!gweather_xml_parse_node (xml, store, NULL, NULL, NULL, NULL, NULL, NULL)) {
+ if (!gweather_xml_parse_node (world, store, NULL)) {
g_object_unref (store);
store = NULL;
- goto error_out;
}
- /* Sort the tree */
- sortable = GTK_TREE_SORTABLE (store);
- gtk_tree_sortable_set_default_sort_func (sortable,
- &gweather_xml_location_sort_func,
- NULL, NULL);
- gtk_tree_sortable_set_sort_column_id (sortable,
- GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
- GTK_SORT_ASCENDING);
-error_out:
- xmlFreeTextReader (xml);
+ gweather_location_unref (world);
return (GtkTreeModel *)store;
}
Added: trunk/libgweather/location-entry.c
==============================================================================
--- (empty file)
+++ trunk/libgweather/location-entry.c Mon Aug 4 12:04:12 2008
@@ -0,0 +1,467 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "location-entry.h"
+
+#include <string.h>
+
+G_DEFINE_TYPE (GWeatherLocationEntry, gweather_location_entry, GTK_TYPE_ENTRY)
+
+enum {
+ PROP_0,
+
+ PROP_TOP,
+ PROP_LOCATION,
+
+ LAST_PROP
+};
+
+static void gweather_location_entry_build_model (GWeatherLocationEntry *entry,
+ GWeatherLocation *top);
+static void set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+
+enum
+{
+ GWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME = 0,
+ GWEATHER_LOCATION_ENTRY_COL_LOCATION,
+ GWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME,
+ GWEATHER_LOCATION_ENTRY_COL_SORT_NAME,
+ GWEATHER_LOCATION_ENTRY_NUM_COLUMNS
+};
+
+static gboolean matcher (GtkEntryCompletion *completion, const char *key,
+ GtkTreeIter *iter, gpointer user_data);
+static gboolean match_selected (GtkEntryCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer entry);
+
+static void
+gweather_location_entry_init (GWeatherLocationEntry *entry)
+{
+ GtkEntryCompletion *completion;
+
+ completion = gtk_entry_completion_new ();
+
+ gtk_entry_completion_set_popup_set_width (completion, FALSE);
+ gtk_entry_completion_set_text_column (completion, GWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME);
+ gtk_entry_completion_set_match_func (completion, matcher, NULL, NULL);
+
+ g_signal_connect (completion, "match_selected",
+ G_CALLBACK (match_selected), entry);
+
+ gtk_entry_set_completion (GTK_ENTRY (entry), completion);
+ g_object_unref (completion);
+}
+
+static void
+finalize (GObject *object)
+{
+ GWeatherLocationEntry *entry = GWEATHER_LOCATION_ENTRY (object);
+
+ if (entry->location)
+ gweather_location_unref (entry->location);
+ if (entry->top)
+ gweather_location_unref (entry->top);
+
+ G_OBJECT_CLASS (gweather_location_entry_parent_class)->finalize (object);
+}
+
+static void
+gweather_location_entry_class_init (GWeatherLocationEntryClass *location_entry_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (location_entry_class);
+
+ object_class->finalize = finalize;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+
+ /* properties */
+ g_object_class_install_property (
+ object_class, PROP_TOP,
+ g_param_spec_pointer ("top",
+ "Top Location",
+ "The GWeatherLocation whose children will be used to fill in the entry",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (
+ object_class, PROP_LOCATION,
+ g_param_spec_pointer ("location",
+ "Location",
+ "The selected GWeatherLocation",
+ G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ switch (prop_id) {
+ case PROP_TOP:
+ gweather_location_entry_build_model (GWEATHER_LOCATION_ENTRY (object),
+ g_value_get_pointer (value));
+ break;
+ case PROP_LOCATION:
+ gweather_location_entry_set_location (GWEATHER_LOCATION_ENTRY (object),
+ g_value_get_pointer (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GWeatherLocationEntry *entry = GWEATHER_LOCATION_ENTRY (object);
+
+ switch (prop_id) {
+ case PROP_LOCATION:
+ g_value_set_pointer (value, entry->location);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+set_location_internal (GWeatherLocationEntry *entry,
+ GtkTreeModel *model,
+ GtkTreeIter *iter)
+{
+ GWeatherLocation *loc;
+ char *name;
+
+ if (entry->location)
+ gweather_location_unref (entry->location);
+
+ if (iter) {
+ gtk_tree_model_get (model, iter,
+ GWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, &name,
+ GWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+ -1);
+ entry->location = gweather_location_ref (loc);
+ gtk_entry_set_text (GTK_ENTRY (entry), name);
+ g_free (name);
+ } else {
+ entry->location = NULL;
+ gtk_entry_set_text (GTK_ENTRY (entry), "");
+ }
+
+ gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
+ g_object_notify (G_OBJECT (entry), "location");
+}
+
+void
+gweather_location_entry_set_location (GWeatherLocationEntry *entry,
+ GWeatherLocation *loc)
+{
+ GtkEntryCompletion *completion;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GWeatherLocation *cmploc;
+
+ g_return_if_fail (GWEATHER_IS_LOCATION_ENTRY (entry));
+
+ completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+ model = gtk_entry_completion_get_model (completion);
+
+ gtk_tree_model_get_iter_first (model, &iter);
+ do {
+ gtk_tree_model_get (model, &iter,
+ GWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+ -1);
+ if (loc == cmploc) {
+ set_location_internal (entry, model, &iter);
+ return;
+ }
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ set_location_internal (entry, model, NULL);
+}
+
+GWeatherLocation *
+gweather_location_entry_get_location (GWeatherLocationEntry *entry)
+{
+ g_return_val_if_fail (GWEATHER_IS_LOCATION_ENTRY (entry), NULL);
+
+ if (entry->location)
+ return gweather_location_ref (entry->location);
+ else
+ return NULL;
+}
+
+void
+gweather_location_entry_set_city (GWeatherLocationEntry *entry,
+ const char *city_name,
+ const char *code)
+{
+ GtkEntryCompletion *completion;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GWeatherLocation *cmploc;
+ const char *cmpcode;
+ char *cmpname;
+
+ g_return_if_fail (GWEATHER_IS_LOCATION_ENTRY (entry));
+ g_return_if_fail (code != NULL);
+
+ completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+ model = gtk_entry_completion_get_model (completion);
+
+ gtk_tree_model_get_iter_first (model, &iter);
+ do {
+ gtk_tree_model_get (model, &iter,
+ GWEATHER_LOCATION_ENTRY_COL_LOCATION, &cmploc,
+ -1);
+
+ cmpcode = gweather_location_get_code (cmploc);
+ if (!cmpcode || strcmp (cmpcode, code) != 0)
+ continue;
+
+ if (city_name) {
+ cmpname = gweather_location_get_city_name (cmploc);
+ if (!cmpname || strcmp (cmpname, city_name) != 0) {
+ g_free (cmpname);
+ continue;
+ }
+ g_free (cmpname);
+ }
+
+ set_location_internal (entry, model, &iter);
+ return;
+ } while (gtk_tree_model_iter_next (model, &iter));
+
+ set_location_internal (entry, model, NULL);
+}
+
+static void
+fill_location_entry_model (GtkTreeStore *store, GWeatherLocation *loc,
+ const char *parent_display_name,
+ const char *parent_compare_name)
+{
+ GWeatherLocation **children;
+ char *display_name, *compare_name;
+ GtkTreeIter iter;
+ int i;
+
+ children = gweather_location_get_children (loc);
+
+ switch (gweather_location_get_level (loc)) {
+ case GWEATHER_LOCATION_WORLD:
+ case GWEATHER_LOCATION_REGION:
+ case GWEATHER_LOCATION_ADM2:
+ /* Ignore these levels of hierarchy; just recurse, passing on
+ * the names from the parent node.
+ */
+ for (i = 0; children[i]; i++) {
+ fill_location_entry_model (store, children[i],
+ parent_display_name,
+ parent_compare_name);
+ }
+ break;
+
+ case GWEATHER_LOCATION_COUNTRY:
+ /* Recurse, initializing the names to the country name */
+ for (i = 0; children[i]; i++) {
+ fill_location_entry_model (store, children[i],
+ gweather_location_get_name (loc),
+ gweather_location_get_sort_name (loc));
+ }
+ break;
+
+ case GWEATHER_LOCATION_ADM1:
+ /* Recurse, adding the ADM1 name to the country name */
+ display_name = g_strdup_printf ("%s, %s", gweather_location_get_name (loc), parent_display_name);
+ compare_name = g_strdup_printf ("%s, %s", gweather_location_get_sort_name (loc), parent_compare_name);
+
+ for (i = 0; children[i]; i++) {
+ fill_location_entry_model (store, children[i],
+ display_name, compare_name);
+ }
+
+ g_free (display_name);
+ g_free (compare_name);
+ break;
+
+ case GWEATHER_LOCATION_CITY:
+ /* If there are multiple (<location>) children, add a line for
+ * each of them.
+ */
+ if (children[1]) {
+ for (i = 0; children[i]; i++) {
+ display_name = g_strdup_printf ("%s (%s), %s",
+ gweather_location_get_name (loc),
+ gweather_location_get_name (children[i]),
+ parent_display_name);
+ compare_name = g_strdup_printf ("%s (%s), %s",
+ gweather_location_get_sort_name (loc),
+ gweather_location_get_sort_name (children[i]),
+ parent_compare_name);
+
+ gtk_tree_store_append (store, &iter, NULL);
+ gtk_tree_store_set (store, &iter,
+ GWEATHER_LOCATION_ENTRY_COL_LOCATION, children[i],
+ GWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+ GWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+ -1);
+
+ g_free (display_name);
+ g_free (compare_name);
+ }
+ break;
+ }
+ /* else, if there's only a single location, fall through */
+
+ case GWEATHER_LOCATION_WEATHER_STATION:
+ /* <location> with no parent <city>, or <city> with a single
+ * child <location>.
+ */
+ display_name = g_strdup_printf ("%s, %s",
+ gweather_location_get_name (loc),
+ parent_display_name);
+ compare_name = g_strdup_printf ("%s, %s",
+ gweather_location_get_sort_name (loc),
+ parent_compare_name);
+
+ gtk_tree_store_append (store, &iter, NULL);
+ gtk_tree_store_set (store, &iter,
+ GWEATHER_LOCATION_ENTRY_COL_LOCATION, loc,
+ GWEATHER_LOCATION_ENTRY_COL_DISPLAY_NAME, display_name,
+ GWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, compare_name,
+ -1);
+
+ g_free (display_name);
+ g_free (compare_name);
+ break;
+ }
+
+ gweather_location_free_children (loc, children);
+}
+
+static void
+gweather_location_entry_build_model (GWeatherLocationEntry *entry,
+ GWeatherLocation *top)
+{
+ GtkTreeStore *store = NULL;
+
+ entry->top = gweather_location_ref (top);
+
+ store = gtk_tree_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_STRING);
+ fill_location_entry_model (store, top, NULL, NULL);
+ gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (entry)),
+ GTK_TREE_MODEL (store));
+ g_object_unref (store);
+}
+
+static char *
+find_word (const char *full_name, const char *word, int word_len,
+ gboolean whole_word, gboolean is_first_word)
+{
+ char *p = (char *)full_name - 1;
+
+ while ((p = strchr (p + 1, *word))) {
+ if (strncmp (p, word, word_len) != 0)
+ continue;
+
+ if (p > (char *)full_name) {
+ char *prev = g_utf8_prev_char (p);
+
+ /* Make sure p points to the start of a word */
+ if (g_unichar_isalpha (g_utf8_get_char (prev)))
+ continue;
+
+ /* If we're matching the first word of the key, it has to
+ * match the first word of the location, city, state, or
+ * country. Eg, it either matches the start of the string
+ * (which we already know it doesn't at this point) or
+ * it is preceded by the string ", " (which isn't actually
+ * a perfect test. FIXME)
+ */
+ if (is_first_word) {
+ if (prev == (char *)full_name || strncmp (prev - 1, ", ", 2) != 0)
+ continue;
+ }
+ }
+
+ if (whole_word && g_unichar_isalpha (g_utf8_get_char (p + word_len)))
+ continue;
+
+ return p;
+ }
+ return NULL;
+}
+
+static gboolean
+matcher (GtkEntryCompletion *completion, const char *key,
+ GtkTreeIter *iter, gpointer user_data)
+{
+ char *name, *name_mem;
+ GWeatherLocation *loc;
+ gboolean is_first_word = TRUE, match;
+ int len;
+
+ gtk_tree_model_get (gtk_entry_completion_get_model (completion), iter,
+ GWEATHER_LOCATION_ENTRY_COL_COMPARE_NAME, &name_mem,
+ GWEATHER_LOCATION_ENTRY_COL_LOCATION, &loc,
+ -1);
+ name = name_mem;
+
+ if (!loc) {
+ g_free (name_mem);
+ return FALSE;
+ }
+
+ /* All but the last word in KEY must match a full word from NAME,
+ * in order (but possibly skipping some words from NAME).
+ */
+ len = strcspn (key, " ");
+ while (key[len]) {
+ name = find_word (name, key, len, TRUE, is_first_word);
+ if (!name) {
+ g_free (name_mem);
+ return FALSE;
+ }
+
+ key += len;
+ while (*key && !g_unichar_isalpha (g_utf8_get_char (key)))
+ key = g_utf8_next_char (key);
+ while (*name && !g_unichar_isalpha (g_utf8_get_char (name)))
+ name = g_utf8_next_char (name);
+
+ len = strcspn (key, " ");
+ is_first_word = FALSE;
+ }
+
+ /* The last word in KEY must match a prefix of a following word in NAME */
+ match = find_word (name, key, strlen (key), FALSE, is_first_word) != NULL;
+ g_free (name_mem);
+ return match;
+}
+
+static gboolean
+match_selected (GtkEntryCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer entry)
+{
+ set_location_internal (entry, model, iter);
+ return TRUE;
+}
+
+GtkWidget *
+gweather_location_entry_new (GWeatherLocation *top)
+{
+ return g_object_new (GWEATHER_TYPE_LOCATION_ENTRY,
+ "top", top,
+ NULL);
+}
Added: trunk/libgweather/location-entry.h
==============================================================================
--- (empty file)
+++ trunk/libgweather/location-entry.h Mon Aug 4 12:04:12 2008
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+#ifndef GWEATHER_LOCATION_ENTRY_H
+#define GWEATHER_LOCATION_ENTRY_H 1
+
+#include <gtk/gtk.h>
+#include <libgweather/gweather-location.h>
+
+#define GWEATHER_TYPE_LOCATION_ENTRY (gweather_location_entry_get_type ())
+#define GWEATHER_LOCATION_ENTRY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GWEATHER_TYPE_LOCATION_ENTRY, GWeatherLocationEntry))
+#define GWEATHER_LOCATION_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GWEATHER_TYPE_LOCATION_ENTRY, GWeatherLocationEntryClass))
+#define GWEATHER_IS_LOCATION_ENTRY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GWEATHER_TYPE_LOCATION_ENTRY))
+#define GWEATHER_IS_LOCATION_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GWEATHER_TYPE_LOCATION_ENTRY))
+#define GWEATHER_LOCATION_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GWEATHER_TYPE_LOCATION_ENTRY, GWeatherLocationEntryClass))
+
+typedef struct {
+ GtkEntry parent;
+
+ /*< private >*/
+ GWeatherLocation *location, *top;
+} GWeatherLocationEntry;
+
+typedef struct {
+ GtkEntryClass parent_class;
+
+} GWeatherLocationEntryClass;
+
+GType gweather_location_entry_get_type (void);
+
+GtkWidget *gweather_location_entry_new (GWeatherLocation *top);
+
+void gweather_location_entry_set_location (GWeatherLocationEntry *entry,
+ GWeatherLocation *loc);
+GWeatherLocation *gweather_location_entry_get_location (GWeatherLocationEntry *entry);
+
+void gweather_location_entry_set_city (GWeatherLocationEntry *entry,
+ const char *city_name,
+ const char *code);
+
+#endif
Added: trunk/libgweather/parser.c
==============================================================================
--- (empty file)
+++ trunk/libgweather/parser.c Mon Aug 4 12:04:12 2008
@@ -0,0 +1,222 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "parser.h"
+
+#include <string.h>
+#include <glib.h>
+#include <libxml/xmlreader.h>
+
+/**
+ * gweather_parser_get_value:
+ * @parser: a #GWeatherParser
+ *
+ * Gets the text of the element whose start tag @parser is pointing to.
+ * Leaves @parser pointing at the next node after the element's end tag.
+ *
+ * Return value: the text of the current node, as a libxml-allocated
+ * string, or %NULL if the node is empty.
+ **/
+char *
+gweather_parser_get_value (GWeatherParser *parser)
+{
+ char *value;
+
+ /* check for null node */
+ if (xmlTextReaderIsEmptyElement (parser->xml))
+ return NULL;
+
+ /* the next "node" is the text node containing the value we want to get */
+ if (xmlTextReaderRead (parser->xml) != 1)
+ return NULL;
+
+ value = (char *) xmlTextReaderValue (parser->xml);
+
+ /* move on to the end of this node */
+ while (xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_END_ELEMENT) {
+ if (xmlTextReaderRead (parser->xml) != 1) {
+ xmlFree (value);
+ return NULL;
+ }
+ }
+
+ /* consume the end element too */
+ if (xmlTextReaderRead (parser->xml) != 1) {
+ xmlFree (value);
+ return NULL;
+ }
+
+ return value;
+}
+
+/**
+ * gweather_parser_get_localized_value:
+ * @parser: a #GWeatherParser
+ *
+ * Looks at the name of the element @parser is currently pointing to, and
+ * returns the content of either that node, or a following node with
+ * the same name but an "xml:lang" attribute naming one of the locale
+ * languages. Leaves @parser pointing to the next node after the last
+ * consecutive element with the same name as the original element.
+ *
+ * Return value: the localized (or unlocalized) text, as a
+ * libxml-allocated string, or %NULL if the node is empty.
+ **/
+char *
+gweather_parser_get_localized_value (GWeatherParser *parser)
+{
+ const char *this_language;
+ int best_match = INT_MAX;
+ const char *lang, *tagname, *next_tagname;
+ gboolean keep_going;
+ char *name = NULL;
+ int i;
+
+ tagname = (const char *) xmlTextReaderConstName (parser->xml);
+
+ do {
+ /* First let's get the language */
+ lang = (const char *) xmlTextReaderConstXmlLang (parser->xml);
+
+ if (lang == NULL)
+ this_language = "C";
+ else
+ this_language = lang;
+
+ /* the next "node" is text node containing the actual name */
+ if (xmlTextReaderRead (parser->xml) != 1) {
+ if (name)
+ xmlFree (name);
+ return NULL;
+ }
+
+ for (i = 0; parser->locales[i] && i < best_match; i++) {
+ if (!strcmp (parser->locales[i], this_language)) {
+ /* if we've already encounted a less accurate
+ translation, then free it */
+ g_free (name);
+
+ name = (char *) xmlTextReaderValue (parser->xml);
+ best_match = i;
+
+ break;
+ }
+ }
+
+ /* Skip to close tag */
+ while (xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_END_ELEMENT) {
+ if (xmlTextReaderRead (parser->xml) != 1) {
+ xmlFree (name);
+ return NULL;
+ }
+ }
+
+ /* Skip junk */
+ do {
+ if (xmlTextReaderRead (parser->xml) != 1) {
+ xmlFree (name);
+ return NULL;
+ }
+ } while (xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_ELEMENT &&
+ xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_END_ELEMENT);
+
+ /* if the next tag has the same name then keep going */
+ next_tagname = (const char *) xmlTextReaderConstName (parser->xml);
+ keep_going = !strcmp (next_tagname, tagname);
+
+ } while (keep_going);
+
+ return name;
+}
+
+GWeatherParser *
+gweather_parser_new (gboolean use_regions)
+{
+ GWeatherParser *parser;
+ int i, keep_going;
+ char *filename;
+ char *tagname, *format;
+ time_t now;
+ struct tm tm;
+
+ parser = g_slice_new0 (GWeatherParser);
+ parser->use_regions = use_regions;
+ parser->locales = g_get_language_names ();
+
+ /* First try to load a locale-specific XML. It's much faster. */
+ filename = NULL;
+ for (i = 0; parser->locales[i] != NULL; i++) {
+ filename = g_strdup_printf ("%s/Locations.%s.xml",
+ GWEATHER_XML_LOCATION_DIR,
+ parser->locales[i]);
+
+ if (g_file_test (filename, G_FILE_TEST_IS_REGULAR))
+ break;
+
+ g_free (filename);
+ filename = NULL;
+ }
+
+ /* Fall back on the file containing either all translations, or only
+ * the english names (depending on the configure flags).
+ */
+ if (!filename)
+ filename = g_strdup (GWEATHER_XML_LOCATION_DIR "/Locations.xml");
+
+ /* Open the xml file containing the different locations */
+ parser->xml = xmlNewTextReaderFilename (filename);
+ g_free (filename);
+
+ if (parser->xml == NULL)
+ goto error_out;
+
+ /* fast forward to the first element */
+ do {
+ /* if we encounter a problem here, exit right away */
+ if (xmlTextReaderRead (parser->xml) != 1)
+ goto error_out;
+ } while (xmlTextReaderNodeType (parser->xml) != XML_READER_TYPE_ELEMENT);
+
+ /* check the name and format */
+ tagname = (char *) xmlTextReaderName (parser->xml);
+ keep_going = tagname && !strcmp (tagname, "gweather");
+ xmlFree (tagname);
+
+ if (!keep_going)
+ goto error_out;
+
+ format = (char *) xmlTextReaderGetAttribute (parser->xml, (xmlChar *) "format");
+ keep_going = format && !strcmp (format, "1.0");
+ xmlFree (format);
+
+ if (!keep_going)
+ goto error_out;
+
+ /* Get timestamps for the start and end of this year */
+ now = time (NULL);
+ tm = *gmtime (&now);
+ tm.tm_mon = 0;
+ tm.tm_mday = 1;
+ tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
+ parser->year_start = mktime (&tm);
+ tm.tm_year++;
+ parser->year_end = mktime (&tm);
+
+ return parser;
+
+error_out:
+ gweather_parser_free (parser);
+ return NULL;
+}
+
+void
+gweather_parser_free (GWeatherParser *parser)
+{
+ if (parser->xml)
+ xmlFreeTextReader (parser->xml);
+ g_slice_free (GWeatherParser, parser);
+}
Added: trunk/libgweather/parser.h
==============================================================================
--- (empty file)
+++ trunk/libgweather/parser.h Mon Aug 4 12:04:12 2008
@@ -0,0 +1,25 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+#ifndef GWEATHER_PARSER_H
+#define GWEATHER_PARSER_H 1
+
+#include <libxml/xmlreader.h>
+#include "gweather-timezone.h"
+
+typedef struct {
+ xmlTextReaderPtr xml;
+ const char * const *locales;
+ gboolean use_regions;
+ time_t year_start, year_end;
+} GWeatherParser;
+
+GWeatherParser *gweather_parser_new (gboolean use_regions);
+void gweather_parser_free (GWeatherParser *parser);
+
+char *gweather_parser_get_value (GWeatherParser *parser);
+char *gweather_parser_get_localized_value (GWeatherParser *parser);
+
+/* from gweather-timezone.c */
+GWeatherTimezone **gweather_timezones_parse_xml (GWeatherParser *parser);
+
+#endif
Added: trunk/libgweather/test_locations.c
==============================================================================
--- (empty file)
+++ trunk/libgweather/test_locations.c Mon Aug 4 12:04:12 2008
@@ -0,0 +1,65 @@
+
+#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "location-entry.h"
+#include "timezone-menu.h"
+
+static void
+deleted (GtkWidget *widget, GdkEvent *event, gpointer data)
+{
+ gtk_main_quit ();
+}
+
+static void
+location_changed (GObject *object, GParamSpec *param, gpointer tzmenu)
+{
+ GWeatherLocationEntry *entry = GWEATHER_LOCATION_ENTRY (object);
+ GWeatherLocation *loc;
+ GWeatherTimezone *zone;
+
+ loc = gweather_location_entry_get_location (entry);
+ g_return_if_fail (loc != NULL);
+ zone = gweather_location_get_timezone (loc);
+ if (zone)
+ gweather_timezone_menu_set_tzid (tzmenu, gweather_timezone_get_tzid (zone));
+ else
+ gweather_timezone_menu_set_tzid (tzmenu, NULL);
+ if (zone)
+ gweather_timezone_unref (zone);
+ gweather_location_unref (loc);
+}
+
+int
+main (int argc, char **argv)
+{
+ GWeatherLocation *loc;
+ GtkWidget *window, *vbox, *entry;
+ GtkWidget *combo;
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), "location");
+ gtk_container_set_border_width (GTK_CONTAINER (window), 8);
+ g_signal_connect (window, "delete-event",
+ G_CALLBACK (deleted), NULL);
+
+ vbox = gtk_vbox_new (FALSE, 8);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+
+ loc = gweather_location_new_world (FALSE);
+ entry = gweather_location_entry_new (loc);
+ gtk_widget_set_size_request (entry, 400, -1);
+ gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, TRUE, 0);
+
+ combo = gweather_timezone_menu_new (loc);
+ gweather_location_unref (loc);
+ gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, TRUE, 0);
+
+ g_signal_connect (entry, "notify::location",
+ G_CALLBACK (location_changed), combo);
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ return 0;
+}
Added: trunk/libgweather/timezone-menu.c
==============================================================================
--- (empty file)
+++ trunk/libgweather/timezone-menu.c Mon Aug 4 12:04:12 2008
@@ -0,0 +1,346 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
+#include "timezone-menu.h"
+
+#include <string.h>
+
+G_DEFINE_TYPE (GWeatherTimezoneMenu, gweather_timezone_menu, GTK_TYPE_COMBO_BOX)
+
+enum {
+ PROP_0,
+
+ PROP_TOP,
+ PROP_TZID,
+
+ LAST_PROP
+};
+
+static void set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+
+static void changed (GtkComboBox *combo);
+
+static GtkTreeModel *gweather_timezone_model_new (GWeatherLocation *top);
+static gboolean row_separator_func (GtkTreeModel *model, GtkTreeIter *iter,
+ gpointer data);
+static void is_sensitive (GtkCellLayout *cell_layout, GtkCellRenderer *cell,
+ GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data);
+
+static void
+gweather_timezone_menu_init (GWeatherTimezoneMenu *menu)
+{
+ GtkCellRenderer *renderer;
+
+ gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (menu),
+ row_separator_func, NULL, NULL);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (menu), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (menu), renderer,
+ "markup", 0,
+ NULL);
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (menu),
+ renderer, is_sensitive, NULL, NULL);
+}
+
+static void
+finalize (GObject *object)
+{
+ GWeatherTimezoneMenu *menu = GWEATHER_TIMEZONE_MENU (object);
+
+ if (menu->zone)
+ gweather_timezone_unref (menu->zone);
+
+ G_OBJECT_CLASS (gweather_timezone_menu_parent_class)->finalize (object);
+}
+
+static void
+gweather_timezone_menu_class_init (GWeatherTimezoneMenuClass *timezone_menu_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (timezone_menu_class);
+ GtkComboBoxClass *combo_class = GTK_COMBO_BOX_CLASS (timezone_menu_class);
+
+ object_class->finalize = finalize;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+
+ combo_class->changed = changed;
+
+ /* properties */
+ g_object_class_install_property (
+ object_class, PROP_TOP,
+ g_param_spec_pointer ("top",
+ "Top Location",
+ "The GWeatherLocation whose children will be used to fill in the menu",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (
+ object_class, PROP_TZID,
+ g_param_spec_string ("tzid",
+ "TZID",
+ "The selected TZID",
+ NULL,
+ G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ GtkTreeModel *model;
+
+ switch (prop_id) {
+ case PROP_TOP:
+ model = gweather_timezone_model_new (g_value_get_pointer (value));
+ gtk_combo_box_set_model (GTK_COMBO_BOX (object), model);
+ g_object_unref (model);
+ gtk_combo_box_set_active (GTK_COMBO_BOX (object), 0);
+ break;
+
+ case PROP_TZID:
+ gweather_timezone_menu_set_tzid (GWEATHER_TIMEZONE_MENU (object),
+ g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GWeatherTimezoneMenu *menu = GWEATHER_TIMEZONE_MENU (object);
+
+ switch (prop_id) {
+ case PROP_TZID:
+ g_value_set_string (value, gweather_timezone_menu_get_tzid (menu));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+enum {
+ GWEATHER_TIMEZONE_MENU_NAME,
+ GWEATHER_TIMEZONE_MENU_ZONE
+};
+
+static void
+changed (GtkComboBox *combo)
+{
+ GWeatherTimezoneMenu *menu = GWEATHER_TIMEZONE_MENU (combo);
+ GtkTreeIter iter;
+
+ if (menu->zone)
+ gweather_timezone_unref (menu->zone);
+
+ gtk_combo_box_get_active_iter (combo, &iter);
+ gtk_tree_model_get (gtk_combo_box_get_model (combo), &iter,
+ GWEATHER_TIMEZONE_MENU_ZONE, &menu->zone,
+ -1);
+
+ if (menu->zone)
+ gweather_timezone_ref (menu->zone);
+
+ g_object_notify (G_OBJECT (combo), "tzid");
+}
+
+static void
+append_offset (GString *desc, int offset)
+{
+ int hours, minutes;
+
+ hours = offset / 60;
+ minutes = (offset > 0) ? offset % 60 : -offset % 60;
+
+ if (minutes)
+ g_string_append_printf (desc, "GMT%+d:%02d", hours, minutes);
+ else if (hours)
+ g_string_append_printf (desc, "GMT%+d", hours);
+ else
+ g_string_append (desc, "GMT");
+}
+
+static char *
+get_offset (GWeatherTimezone *zone)
+{
+ GString *desc;
+
+ desc = g_string_new (NULL);
+ append_offset (desc, gweather_timezone_get_offset (zone));
+ if (gweather_timezone_has_dst (zone)) {
+ g_string_append (desc, " / ");
+ append_offset (desc, gweather_timezone_get_dst_offset (zone));
+ }
+ return g_string_free (desc, FALSE);
+}
+
+static void
+insert_locations (GtkTreeStore *store, GWeatherLocation *loc)
+{
+ int i;
+
+ if (gweather_location_get_level (loc) < GWEATHER_LOCATION_COUNTRY) {
+ GWeatherLocation **children;
+
+ children = gweather_location_get_children (loc);
+ for (i = 0; children[i]; i++)
+ insert_locations (store, children[i]);
+ gweather_location_free_children (loc, children);
+ } else {
+ GWeatherTimezone **zones;
+ GtkTreeIter iter, ziter;
+ char *name, *offset;
+
+ zones = gweather_location_get_timezones (loc);
+ if (zones[1]) {
+ gtk_tree_store_append (store, &iter, NULL);
+ gtk_tree_store_set (store, &iter,
+ GWEATHER_TIMEZONE_MENU_NAME, gweather_location_get_name (loc),
+ -1);
+
+ for (i = 0; zones[i]; i++) {
+ offset = get_offset (zones[i]);
+ name = g_strdup_printf ("%s <small>(%s)</small>",
+ gweather_timezone_get_name (zones[i]),
+ offset);
+ gtk_tree_store_append (store, &ziter, &iter);
+ gtk_tree_store_set (store, &ziter,
+ GWEATHER_TIMEZONE_MENU_NAME, name,
+ GWEATHER_TIMEZONE_MENU_ZONE, gweather_timezone_ref (zones[i]),
+ -1);
+ g_free (name);
+ g_free (offset);
+ }
+ } else if (zones[0]) {
+ offset = get_offset (zones[0]);
+ name = g_strdup_printf ("%s <small>(%s)</small>",
+ gweather_location_get_name (loc),
+ offset);
+ gtk_tree_store_append (store, &iter, NULL);
+ gtk_tree_store_set (store, &iter,
+ GWEATHER_TIMEZONE_MENU_NAME, name,
+ GWEATHER_TIMEZONE_MENU_ZONE, gweather_timezone_ref (zones[0]),
+ -1);
+ g_free (name);
+ g_free (offset);
+ }
+
+ gweather_location_free_timezones (loc, zones);
+ }
+}
+
+static GtkTreeModel *
+gweather_timezone_model_new (GWeatherLocation *top)
+{
+ GtkTreeStore *store;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+
+ store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_POINTER);
+ model = GTK_TREE_MODEL (store);
+
+ gtk_tree_store_append (store, &iter, NULL);
+ gtk_tree_store_set (store, &iter,
+ GWEATHER_TIMEZONE_MENU_NAME, "<i>Unknown</i>",
+ GWEATHER_TIMEZONE_MENU_ZONE, NULL,
+ -1);
+ gtk_tree_store_append (store, &iter, NULL);
+
+ insert_locations (store, top);
+
+ return model;
+}
+
+static gboolean
+row_separator_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
+{
+ char *name;
+
+ gtk_tree_model_get (model, iter,
+ GWEATHER_TIMEZONE_MENU_NAME, &name,
+ -1);
+ if (name) {
+ g_free (name);
+ return FALSE;
+ } else
+ return TRUE;
+}
+
+static void
+is_sensitive (GtkCellLayout *cell_layout, GtkCellRenderer *cell,
+ GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
+{
+ gboolean sensitive;
+
+ sensitive = !gtk_tree_model_iter_has_child (tree_model, iter);
+ g_object_set (cell, "sensitive", sensitive, NULL);
+}
+
+GtkWidget *
+gweather_timezone_menu_new (GWeatherLocation *top)
+{
+ return g_object_new (GWEATHER_TYPE_TIMEZONE_MENU,
+ "top", top,
+ NULL);
+}
+
+typedef struct {
+ GtkComboBox *combo;
+ const char *tzid;
+} SetTimezoneData;
+
+static gboolean
+check_tzid (GtkTreeModel *model, GtkTreePath *path,
+ GtkTreeIter *iter, gpointer data)
+{
+ SetTimezoneData *tzd = data;
+ GWeatherTimezone *zone;
+
+ gtk_tree_model_get (model, iter,
+ GWEATHER_TIMEZONE_MENU_ZONE, &zone,
+ -1);
+ if (!zone)
+ return FALSE;
+
+ if (!strcmp (gweather_timezone_get_tzid (zone), tzd->tzid)) {
+ gtk_combo_box_set_active_iter (tzd->combo, iter);
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+void
+gweather_timezone_menu_set_tzid (GWeatherTimezoneMenu *menu,
+ const char *tzid)
+{
+ SetTimezoneData tzd;
+
+ if (!tzid) {
+ gtk_combo_box_set_active (GTK_COMBO_BOX (menu), 0);
+ return;
+ }
+
+ tzd.combo = GTK_COMBO_BOX (menu);
+ tzd.tzid = tzid;
+ gtk_tree_model_foreach (gtk_combo_box_get_model (tzd.combo),
+ check_tzid, &tzd);
+}
+
+const char *
+gweather_timezone_menu_get_tzid (GWeatherTimezoneMenu *menu)
+{
+ if (!menu->zone)
+ return NULL;
+ return gweather_timezone_get_tzid (menu->zone);
+}
+
Added: trunk/libgweather/timezone-menu.h
==============================================================================
--- (empty file)
+++ trunk/libgweather/timezone-menu.h Mon Aug 4 12:04:12 2008
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+#ifndef GWEATHER_TIMEZONE_MENU_H
+#define GWEATHER_TIMEZONE_MENU_H 1
+
+#include <gtk/gtk.h>
+#include <libgweather/gweather-location.h>
+
+#define GWEATHER_TYPE_TIMEZONE_MENU (gweather_timezone_menu_get_type ())
+#define GWEATHER_TIMEZONE_MENU(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GWEATHER_TYPE_TIMEZONE_MENU, GWeatherTimezoneMenu))
+#define GWEATHER_TIMEZONE_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GWEATHER_TYPE_TIMEZONE_MENU, GWeatherTimezoneMenuClass))
+#define GWEATHER_IS_TIMEZONE_MENU(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GWEATHER_TYPE_TIMEZONE_MENU))
+#define GWEATHER_IS_TIMEZONE_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GWEATHER_TYPE_TIMEZONE_MENU))
+#define GWEATHER_TIMEZONE_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GWEATHER_TYPE_TIMEZONE_MENU, GWeatherTimezoneMenuClass))
+
+typedef struct {
+ GtkComboBox parent;
+
+ /*< private >*/
+ GWeatherTimezone *zone;
+} GWeatherTimezoneMenu;
+
+typedef struct {
+ GtkComboBoxClass parent_class;
+
+} GWeatherTimezoneMenuClass;
+
+GType gweather_timezone_menu_get_type (void);
+
+GtkWidget *gweather_timezone_menu_new (GWeatherLocation *top);
+
+void gweather_timezone_menu_set_tzid (GWeatherTimezoneMenu *menu,
+ const char *tzid);
+const char *gweather_timezone_menu_get_tzid (GWeatherTimezoneMenu *menu);
+
+#endif
Modified: trunk/libgweather/weather-priv.h
==============================================================================
--- trunk/libgweather/weather-priv.h (original)
+++ trunk/libgweather/weather-priv.h Mon Aug 4 12:04:12 2008
@@ -16,6 +16,12 @@
#include <libsoup/soup.h>
#include "weather.h"
+#include "gweather-location.h"
+
+#define WEATHER_LOCATION_CODE_LEN 4
+
+WeatherLocation *gweather_location_to_weather_location (GWeatherLocation *gloc,
+ const char *name);
/*
* Weather information.
Modified: trunk/libgweather/weather.h
==============================================================================
--- trunk/libgweather/weather.h (original)
+++ trunk/libgweather/weather.h Mon Aug 4 12:04:12 2008
@@ -29,8 +29,6 @@
* Location
*/
-#define WEATHER_LOCATION_CODE_LEN 4
-
struct _WeatherLocation {
gchar *name;
gchar *code;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]