1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "i18n_timezone.h"
16
17 #include <dlfcn.h>
18 #include <filesystem>
19 #include <fstream>
20 #include <sys/stat.h>
21 #include "hilog/log.h"
22 #include "libxml/globals.h"
23 #include "libxml/tree.h"
24 #include "libxml/xmlstring.h"
25 #include "locale_config.h"
26 #include "locale_info.h"
27 #include "map"
28 #include "securec.h"
29 #include "set"
30 #include "string"
31 #include "type_traits"
32 #include "umachine.h"
33 #include "utility"
34 #include "utils.h"
35 #include "utypes.h"
36 #include "vector"
37 #include "unicode/locid.h"
38 #include "unicode/unistr.h"
39 #include "utils.h"
40 #include <cstdio>
41 #include <cstdlib>
42 #include <iostream>
43 #include <regex>
44
45 namespace OHOS {
46 namespace Global {
47 namespace I18n {
48 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001E00, "I18nJs" };
49 using namespace OHOS::HiviewDFX;
50 using namespace std::filesystem;
51
52 const char *I18nTimeZone::TIMEZONE_KEY = "persist.time.timezone";
53 const char *I18nTimeZone::DEFAULT_TIMEZONE = "GMT";
54
55 const char *I18nTimeZone::CITY_TIMEZONE_DATA_PATH = "/system/usr/ohos_timezone/ohos_timezones.xml";
56 const char *I18nTimeZone::DEVICE_CITY_TIMEZONE_DATA_PATH = "/system/usr/ohos_timezone/device_timezones.xml";
57 const char *I18nTimeZone::TZ_PIXEL_PATH = "/system/usr/ohos_timezone";
58 const char *I18nTimeZone::DEFAULT_LOCALE = "root";
59 const char *I18nTimeZone::CITY_DISPLAYNAME_PATH = "/system/usr/ohos_timezone/ohos_city_dispname/";
60 const char *I18nTimeZone::DEVICE_CITY_DISPLAYNAME_PATH = "/system/usr/ohos_timezone/device_city_dispname/";
61
62 const char *I18nTimeZone::TIMEZONE_ROOT_TAG = "timezones";
63 const char *I18nTimeZone::TIMEZONE_SECOND_ROOT_TAG = "timezone";
64 const char *I18nTimeZone::CITY_DISPLAYNAME_ROOT_TAG = "display_names";
65 const char *I18nTimeZone::CITY_DISPLAYNAME_SECOND_ROOT_TAG = "display_name";
66 const char *I18nTimeZone::ZONEINFO_PATH = "/system/etc/zoneinfo";
67
68 std::set<std::string> I18nTimeZone::availableIDs {};
69 std::set<std::string> I18nTimeZone::supportedLocales {};
70 std::set<std::string> I18nTimeZone::availableZoneCityIDs {};
71 std::map<std::string, std::string> I18nTimeZone::city2TimeZoneID {};
72 bool I18nTimeZone::useDeviceCityDispName = false;
73
74 const int RECV_CHAR_LEN = 128;
75
76 std::map<int, std::string> I18nTimeZone::categoryNum2TimezoneWN {
77 { 0, "Africa/Abidjan" },
78 { 1, "Africa/Accra" },
79 { 2, "Africa/Algiers" },
80 { 3, "Africa/Bamako" },
81 { 4, "Africa/Banjul" },
82 { 5, "Africa/Bissau" },
83 { 6, "Africa/Casablanca" },
84 { 7, "Africa/Ceuta" },
85 { 8, "Africa/Conakry" },
86 { 9, "Africa/Dakar" },
87 { 10, "Africa/El_Aaiun" },
88 { 11, "Africa/Freetown" },
89 { 12, "Africa/Lome" },
90 { 13, "Africa/Monrovia" },
91 { 14, "Africa/Nouakchott" },
92 { 15, "Africa/Ouagadougou" },
93 { 16, "America/Adak" },
94 { 17, "America/Anchorage" },
95 { 18, "America/Anguilla" },
96 { 19, "America/Antigua" },
97 { 20, "America/Aruba" },
98 { 21, "America/Atikokan" },
99 { 22, "America/Bahia_Banderas" },
100 { 23, "America/Barbados" },
101 { 24, "America/Belem" },
102 { 25, "America/Belize" },
103 { 26, "America/Blanc-Sablon" },
104 { 27, "America/Boa_Vista" },
105 { 28, "America/Bogota" },
106 { 29, "America/Boise" },
107 { 30, "America/Cambridge_Bay" },
108 { 31, "America/Cancun" },
109 { 32, "America/Caracas" },
110 { 33, "America/Cayenne" },
111 { 34, "America/Cayman" },
112 { 35, "America/Chicago" },
113 { 36, "America/Chihuahua" },
114 { 37, "America/Mexico_City" }, // old data is 'America/Ciudad_Juarez'
115 { 38, "America/Costa_Rica" },
116 { 39, "America/Creston" },
117 { 40, "America/Curacao" },
118 { 41, "America/Danmarkshavn" },
119 { 42, "America/Dawson" },
120 { 43, "America/Dawson_Creek" },
121 { 44, "America/Denver" },
122 { 45, "America/Detroit" },
123 { 46, "America/Dominica" },
124 { 47, "America/Edmonton" },
125 { 48, "America/El_Salvador" },
126 { 49, "America/Fort_Nelson" },
127 { 50, "America/Glace_Bay" },
128 { 51, "America/Goose_Bay" },
129 { 52, "America/Grand_Turk" },
130 { 53, "America/Grenada" },
131 { 54, "America/Guadeloupe" },
132 { 55, "America/Guatemala" },
133 { 56, "America/Guayaquil" },
134 { 57, "America/Guyana" },
135 { 58, "America/Halifax" },
136 { 59, "America/Havana" },
137 { 60, "America/Hermosillo" },
138 { 61, "America/Indiana/Indianapolis" },
139 { 62, "America/Indiana/Knox" },
140 { 63, "America/Indiana/Marengo" },
141 { 64, "America/Indiana/Petersburg" },
142 { 65, "America/Indiana/Tell_City" },
143 { 66, "America/Indiana/Vevay" },
144 { 67, "America/Indiana/Vincennes" },
145 { 68, "America/Indiana/Winamac" },
146 { 69, "America/Inuvik" },
147 { 70, "America/Iqaluit" },
148 { 71, "America/Jamaica" },
149 { 72, "America/Juneau" },
150 { 73, "America/Kentucky/Louisville" },
151 { 74, "America/Kentucky/Monticello" },
152 { 75, "America/Kralendijk" },
153 { 76, "America/Los_Angeles" },
154 { 77, "America/Lower_Princes" },
155 { 78, "America/Managua" },
156 { 79, "America/Manaus" },
157 { 80, "America/Marigot" },
158 { 81, "America/Martinique" },
159 { 82, "America/Matamoros" },
160 { 83, "America/Mazatlan" },
161 { 84, "America/Menominee" },
162 { 85, "America/Merida" },
163 { 86, "America/Metlakatla" },
164 { 87, "America/Mexico_City" },
165 { 88, "America/Miquelon" },
166 { 89, "America/Moncton" },
167 { 90, "America/Monterrey" },
168 { 91, "America/Montserrat" },
169 { 92, "America/Nassau" },
170 { 93, "America/New_York" },
171 { 94, "America/Nome" },
172 { 95, "America/Noronha" },
173 { 96, "America/North_Dakota/Beulah" },
174 { 97, "America/North_Dakota/Center" },
175 { 98, "America/North_Dakota/New_Salem" },
176 { 99, "America/Nuuk" },
177 { 100, "America/Ojinaga" },
178 { 101, "America/Panama" },
179 { 102, "America/Paramaribo" },
180 { 103, "America/Phoenix" },
181 { 104, "America/Port-au-Prince" },
182 { 105, "America/Port_of_Spain" },
183 { 106, "America/Puerto_Rico" },
184 { 107, "America/Rankin_Inlet" },
185 { 108, "America/Regina" },
186 { 109, "America/Resolute" },
187 { 110, "America/Santarem" },
188 { 111, "America/Santo_Domingo" },
189 { 112, "America/Scoresbysund" },
190 { 113, "America/Sitka" },
191 { 114, "America/St_Barthelemy" },
192 { 115, "America/St_Johns" },
193 { 116, "America/St_Kitts" },
194 { 117, "America/St_Lucia" },
195 { 118, "America/St_Thomas" },
196 { 119, "America/St_Vincent" },
197 { 120, "America/Swift_Current" },
198 { 121, "America/Tegucigalpa" },
199 { 122, "America/Thule" },
200 { 123, "America/Tijuana" },
201 { 124, "America/Toronto" },
202 { 125, "America/Tortola" },
203 { 126, "America/Vancouver" },
204 { 127, "America/Whitehorse" },
205 { 128, "America/Winnipeg" },
206 { 129, "America/Yakutat" },
207 { 130, "Asia/Anadyr" },
208 { 131, "Atlantic/Azores" },
209 { 132, "Atlantic/Bermuda" },
210 { 133, "Atlantic/Canary" },
211 { 134, "Atlantic/Cape_Verde" },
212 { 135, "Atlantic/Faroe" },
213 { 136, "Atlantic/Madeira" },
214 { 137, "Atlantic/Reykjavik" },
215 { 138, "Etc/GMT" },
216 { 139, "Etc/GMT+1" },
217 { 140, "Etc/GMT+10" },
218 { 141, "Etc/GMT+11" },
219 { 142, "Etc/GMT+12" },
220 { 143, "Etc/GMT+2" },
221 { 144, "Etc/GMT+3" },
222 { 145, "Etc/GMT+4" },
223 { 146, "Etc/GMT+5" },
224 { 147, "Etc/GMT+6" },
225 { 148, "Etc/GMT+7" },
226 { 149, "Etc/GMT+8" },
227 { 150, "Etc/GMT+9" },
228 { 151, "Etc/GMT-12" },
229 { 152, "Europe/Dublin" },
230 { 153, "Europe/Gibraltar" },
231 { 154, "Europe/Guernsey" },
232 { 155, "Europe/Isle_of_Man" },
233 { 156, "Europe/Jersey" },
234 { 157, "Europe/Lisbon" },
235 { 158, "Europe/London" },
236 { 159, "Europe/Madrid" },
237 { 160, "Europe/Oslo" },
238 { 161, "Europe/Paris" },
239 { 162, "Pacific/Galapagos" },
240 { 163, "Pacific/Honolulu" },
241 { 164, "Pacific/Kiritimati" },
242 { 165, "Pacific/Midway" },
243 };
244 std::map<int, std::string> I18nTimeZone::categoryNum2TimezoneEN {
245 { 0, "Africa/Accra" },
246 { 1, "Africa/Addis_Ababa" },
247 { 2, "Africa/Algiers" },
248 { 3, "Africa/Asmara" },
249 { 4, "Africa/Bamako" },
250 { 5, "Africa/Bangui" },
251 { 6, "Africa/Brazzaville" },
252 { 7, "Africa/Cairo" },
253 { 8, "Africa/Djibouti" },
254 { 9, "Africa/Douala" },
255 { 10, "Africa/Juba" },
256 { 11, "Africa/Kampala" },
257 { 12, "Africa/Khartoum" },
258 { 13, "Africa/Kinshasa" },
259 { 14, "Africa/Lagos" },
260 { 15, "Africa/Libreville" },
261 { 16, "Africa/Lome" },
262 { 17, "Africa/Lubumbashi" },
263 { 18, "Africa/Malabo" },
264 { 19, "Africa/Mogadishu" },
265 { 20, "Africa/Nairobi" },
266 { 21, "Africa/Ndjamena" },
267 { 22, "Africa/Niamey" },
268 { 23, "Africa/Ouagadougou" },
269 { 24, "Africa/Porto-Novo" },
270 { 25, "Africa/Sao_Tome" },
271 { 26, "Africa/Tripoli" },
272 { 27, "Africa/Tunis" },
273 { 28, "America/Adak" },
274 { 29, "Arctic/Longyearbyen" },
275 { 30, "Asia/Aden" },
276 { 31, "Asia/Almaty" },
277 { 32, "Asia/Amman" },
278 { 33, "Asia/Anadyr" },
279 { 34, "Asia/Aqtau" },
280 { 35, "Asia/Aqtobe" },
281 { 36, "Asia/Ashgabat" },
282 { 37, "Asia/Atyrau" },
283 { 38, "Asia/Baghdad" },
284 { 39, "Asia/Bahrain" },
285 { 40, "Asia/Baku" },
286 { 41, "Asia/Bangkok" },
287 { 42, "Asia/Barnaul" },
288 { 43, "Asia/Beirut" },
289 { 44, "Asia/Bishkek" },
290 { 45, "Asia/Brunei" },
291 { 46, "Asia/Chita" },
292 { 47, "Asia/Choibalsan" },
293 { 48, "Asia/Colombo" },
294 { 49, "Asia/Damascus" },
295 { 50, "Asia/Dhaka" },
296 { 51, "Asia/Dubai" },
297 { 52, "Asia/Dushanbe" },
298 { 53, "Asia/Famagusta" },
299 { 54, "Asia/Gaza" },
300 { 55, "Asia/Hebron" },
301 { 56, "Asia/Ho_Chi_Minh" },
302 { 57, "Asia/Hong_Kong" },
303 { 58, "Asia/Hovd" },
304 { 59, "Asia/Irkutsk" },
305 { 60, "Asia/Jakarta" },
306 { 61, "Asia/Jayapura" },
307 { 62, "Asia/Jerusalem" },
308 { 63, "Asia/Kabul" },
309 { 64, "Asia/Kamchatka" },
310 { 65, "Asia/Karachi" },
311 { 66, "Asia/Kathmandu" },
312 { 67, "Asia/Khandyga" },
313 { 68, "Asia/Kolkata" },
314 { 69, "Asia/Krasnoyarsk" },
315 { 70, "Asia/Kuala_Lumpur" },
316 { 71, "Asia/Kuching" },
317 { 72, "Asia/Kuwait" },
318 { 73, "Asia/Macau" },
319 { 74, "Asia/Magadan" },
320 { 75, "Asia/Makassar" },
321 { 76, "Asia/Manila" },
322 { 77, "Asia/Muscat" },
323 { 78, "Asia/Nicosia" },
324 { 79, "Asia/Novokuznetsk" },
325 { 80, "Asia/Novosibirsk" },
326 { 81, "Asia/Omsk" },
327 { 82, "Asia/Oral" },
328 { 83, "Asia/Phnom_Penh" },
329 { 84, "Asia/Pontianak" },
330 { 85, "Asia/Pyongyang" },
331 { 86, "Asia/Qatar" },
332 { 87, "Asia/Qostanay" },
333 { 88, "Asia/Qyzylorda" },
334 { 89, "Asia/Riyadh" },
335 { 90, "Asia/Sakhalin" },
336 { 91, "Asia/Samarkand" },
337 { 92, "Asia/Seoul" },
338 { 93, "Asia/Shanghai" },
339 { 94, "Asia/Singapore" },
340 { 95, "Asia/Srednekolymsk" },
341 { 96, "Asia/Taipei" },
342 { 97, "Asia/Tashkent" },
343 { 98, "Asia/Tbilisi" },
344 { 99, "Asia/Tehran" },
345 { 100, "Asia/Thimbu" },
346 { 101, "Asia/Tokyo" },
347 { 102, "Asia/Tomsk" },
348 { 103, "Asia/Ulaanbaatar" },
349 { 104, "Asia/Urumqi" },
350 { 105, "Asia/Ust-Nera" },
351 { 106, "Asia/Vientiane" },
352 { 107, "Asia/Vladivostok" },
353 { 108, "Asia/Yakutsk" },
354 { 109, "Asia/Yangon" },
355 { 110, "Asia/Yekaterinburg" },
356 { 111, "Asia/Yerevan" },
357 { 112, "Etc/GMT" },
358 { 113, "Etc/GMT-1" },
359 { 114, "Etc/GMT-10" },
360 { 115, "Etc/GMT-11" },
361 { 116, "Etc/GMT-12" },
362 { 117, "Etc/GMT-2" },
363 { 118, "Etc/GMT-3" },
364 { 119, "Etc/GMT-4" },
365 { 120, "Etc/GMT-5" },
366 { 121, "Etc/GMT-6" },
367 { 122, "Etc/GMT-7" },
368 { 123, "Etc/GMT-8" },
369 { 124, "Etc/GMT-9" },
370 { 125, "Europe/Amsterdam" },
371 { 126, "Europe/Andorra" },
372 { 127, "Europe/Astrakhan" },
373 { 128, "Europe/Athens" },
374 { 129, "Europe/Belgrade" },
375 { 130, "Europe/Berlin" },
376 { 131, "Europe/Bratislava" },
377 { 132, "Europe/Brussels" },
378 { 133, "Europe/Bucharest" },
379 { 134, "Europe/Budapest" },
380 { 135, "Europe/Busingen" },
381 { 136, "Europe/Chisinau" },
382 { 137, "Europe/Copenhagen" },
383 { 138, "Europe/Helsinki" },
384 { 139, "Europe/Istanbul" },
385 { 140, "Europe/Kaliningrad" },
386 { 141, "Europe/Kirov" },
387 { 142, "Europe/Kiev" },
388 { 143, "Europe/Ljubljana" },
389 { 144, "Europe/London" },
390 { 145, "Europe/Luxembourg" },
391 { 146, "Europe/Madrid" },
392 { 147, "Europe/Malta" },
393 { 148, "Europe/Mariehamn" },
394 { 149, "Europe/Minsk" },
395 { 150, "Europe/Monaco" },
396 { 151, "Europe/Moscow" },
397 { 152, "Europe/Oslo" },
398 { 153, "Europe/Paris" },
399 { 154, "Europe/Podgorica" },
400 { 155, "Europe/Prague" },
401 { 156, "Europe/Riga" },
402 { 157, "Europe/Rome" },
403 { 158, "Europe/Samara" },
404 { 159, "Europe/San_Marino" },
405 { 160, "Europe/Sarajevo" },
406 { 161, "Europe/Saratov" },
407 { 162, "Europe/Simferopol" },
408 { 163, "Europe/Skopje" },
409 { 164, "Europe/Sofia" },
410 { 165, "Europe/Stockholm" },
411 { 166, "Europe/Tallinn" },
412 { 167, "Europe/Tirane" },
413 { 168, "Europe/Ulyanovsk" },
414 { 169, "Europe/Vaduz" },
415 { 170, "Europe/Vienna" },
416 { 171, "Europe/Vilnius" },
417 { 172, "Europe/Volgograd" },
418 { 173, "Europe/Warsaw" },
419 { 174, "Europe/Zagreb" },
420 { 175, "Europe/Zurich" },
421 { 176, "Indian/Maldives" },
422 { 177, "Pacific/Chuuk" },
423 { 178, "Pacific/Guam" },
424 { 179, "Pacific/Kosrae" },
425 { 180, "Pacific/Kwajalein" },
426 { 181, "Pacific/Majuro" },
427 { 182, "Pacific/Palau" },
428 { 183, "Pacific/Pohnpei" },
429 { 184, "Pacific/Saipan" },
430 { 185, "Pacific/Tarawa" },
431 { 186, "Pacific/Wake" },
432 };
433 std::map<int, std::string> I18nTimeZone::categoryNum2TimezoneWS {
434 { 0, "Africa/Johannesburg" },
435 { 1, "America/Araguaina" },
436 { 2, "America/Argentina/Buenos_Aires" },
437 { 3, "America/Argentina/Catamarca" },
438 { 4, "America/Argentina/Cordoba" },
439 { 5, "America/Argentina/Jujuy" },
440 { 6, "America/Argentina/La_Rioja" },
441 { 7, "America/Argentina/Mendoza" },
442 { 8, "America/Argentina/Rio_Gallegos" },
443 { 9, "America/Argentina/Salta" },
444 { 10, "America/Argentina/San_Juan" },
445 { 11, "America/Argentina/San_Luis" },
446 { 12, "America/Argentina/Tucuman" },
447 { 13, "America/Argentina/Ushuaia" },
448 { 14, "America/Asuncion" },
449 { 15, "America/Bahia" },
450 { 16, "America/Belem" },
451 { 17, "America/Boa_Vista" },
452 { 18, "America/Bogota" },
453 { 19, "America/Campo_Grande" },
454 { 20, "America/Cuiaba" },
455 { 21, "America/Eirunepe" },
456 { 22, "America/Fortaleza" },
457 { 23, "America/Guayaquil" },
458 { 24, "America/La_Paz" },
459 { 25, "America/Lima" },
460 { 26, "America/Maceio" },
461 { 27, "America/Manaus" },
462 { 28, "America/Montevideo" },
463 { 29, "America/Noronha" },
464 { 30, "America/Porto_Velho" },
465 { 31, "America/Punta_Arenas" },
466 { 32, "America/Recife" },
467 { 33, "America/Rio_Branco" },
468 { 34, "America/Santarem" },
469 { 35, "America/Santiago" },
470 { 36, "America/Sao_Paulo" },
471 { 37, "Antarctica/McMurdo" },
472 { 38, "Antarctica/Palmer" },
473 { 39, "Antarctica/Rothera" },
474 { 40, "Atlantic/South_Georgia" },
475 { 41, "Atlantic/St_Helena" },
476 { 42, "Atlantic/Stanley" },
477 { 43, "Etc/GMT" },
478 { 44, "Etc/GMT+1" },
479 { 45, "Etc/GMT+10" },
480 { 46, "Etc/GMT+11" },
481 { 47, "Etc/GMT+12" },
482 { 48, "Etc/GMT+2" },
483 { 49, "Etc/GMT+3" },
484 { 50, "Etc/GMT+4" },
485 { 51, "Etc/GMT+5" },
486 { 52, "Etc/GMT+6" },
487 { 53, "Etc/GMT+7" },
488 { 54, "Etc/GMT+8" },
489 { 55, "Etc/GMT+9" },
490 { 56, "Etc/GMT-12" },
491 { 57, "Etc/UTC" },
492 { 58, "Pacific/Apia" },
493 { 59, "Pacific/Auckland" },
494 { 60, "Pacific/Chatham" },
495 { 61, "Pacific/Easter" },
496 { 62, "Pacific/Fakaofo" },
497 { 63, "Pacific/Fiji" },
498 { 64, "Pacific/Funafuti" },
499 { 65, "Pacific/Galapagos" },
500 { 66, "Pacific/Gambier" },
501 { 67, "Pacific/Kanton" },
502 { 68, "Pacific/Kiritimati" },
503 { 69, "Pacific/Marquesas" },
504 { 70, "Pacific/Niue" },
505 { 71, "Pacific/Pago_Pago" },
506 { 72, "Pacific/Pitcairn" },
507 { 73, "Pacific/Rarotonga" },
508 { 74, "Pacific/Tahiti" },
509 { 75, "Pacific/Tongatapu" },
510 { 76, "Pacific/Wallis" },
511 };
512 std::map<int, std::string> I18nTimeZone::categoryNum2TimezoneES {
513 { 0, "Africa/Blantyre" },
514 { 1, "Africa/Brazzaville" },
515 { 2, "Africa/Bujumbura" },
516 { 3, "Africa/Dar_es_Salaam" },
517 { 4, "Africa/Gaborone" },
518 { 5, "Africa/Harare" },
519 { 6, "Africa/Johannesburg" },
520 { 7, "Africa/Kampala" },
521 { 8, "Africa/Kigali" },
522 { 9, "Africa/Kinshasa" },
523 { 10, "Africa/Libreville" },
524 { 11, "Africa/Luanda" },
525 { 12, "Africa/Lubumbashi" },
526 { 13, "Africa/Lusaka" },
527 { 14, "Africa/Malabo" },
528 { 15, "Africa/Maputo" },
529 { 16, "Africa/Maseru" },
530 { 17, "Africa/Mbabane" },
531 { 18, "Africa/Mogadishu" },
532 { 19, "Africa/Nairobi" },
533 { 20, "Africa/Sao_Tome" },
534 { 21, "Africa/Windhoek" },
535 { 22, "Antarctica/Casey" },
536 { 23, "Antarctica/Davis" },
537 { 24, "Antarctica/DumontDUrville" },
538 { 25, "Antarctica/Macquarie" },
539 { 26, "Antarctica/Mawson" },
540 { 27, "Antarctica/McMurdo" },
541 { 28, "Antarctica/Syowa" },
542 { 29, "Antarctica/Troll" },
543 { 30, "Antarctica/Vostok" },
544 { 31, "Asia/Dili" },
545 { 32, "Asia/Jakarta" },
546 { 33, "Asia/Jayapura" },
547 { 34, "Asia/Makassar" },
548 { 35, "Asia/Pontianak" },
549 { 36, "Australia/Adelaide" },
550 { 37, "Australia/Brisbane" },
551 { 38, "Australia/Broken_Hill" },
552 { 39, "Australia/Darwin" },
553 { 40, "Australia/Eucla" },
554 { 41, "Australia/Hobart" },
555 { 42, "Australia/Lindeman" },
556 { 43, "Australia/Lord_Howe" },
557 { 44, "Australia/Melbourne" },
558 { 45, "Australia/Perth" },
559 { 46, "Australia/Sydney" },
560 { 47, "Etc/GMT" },
561 { 48, "Etc/GMT-1" },
562 { 49, "Etc/GMT-10" },
563 { 50, "Etc/GMT-11" },
564 { 51, "Etc/GMT-12" },
565 { 52, "Etc/GMT-2" },
566 { 53, "Etc/GMT-3" },
567 { 54, "Etc/GMT-4" },
568 { 55, "Etc/GMT-5" },
569 { 56, "Etc/GMT-6" },
570 { 57, "Etc/GMT-7" },
571 { 58, "Etc/GMT-8" },
572 { 59, "Etc/GMT-9" },
573 { 60, "Indian/Antananarivo" },
574 { 61, "Indian/Chagos" },
575 { 62, "Indian/Christmas" },
576 { 63, "Indian/Cocos" },
577 { 64, "Indian/Comoro" },
578 { 65, "Indian/Kerguelen" },
579 { 66, "Indian/Mahe" },
580 { 67, "Indian/Maldives" },
581 { 68, "Indian/Mauritius" },
582 { 69, "Indian/Mayotte" },
583 { 70, "Indian/Reunion" },
584 { 71, "Pacific/Auckland" },
585 { 72, "Pacific/Bougainville" },
586 { 73, "Pacific/Efate" },
587 { 74, "Pacific/Fiji" },
588 { 75, "Pacific/Funafuti" },
589 { 76, "Pacific/Guadalcanal" },
590 { 77, "Pacific/Nauru" },
591 { 78, "Pacific/Norfolk" },
592 { 79, "Pacific/Noumea" },
593 { 80, "Pacific/Port_Moresby" },
594 { 81, "Pacific/Tarawa" },
595 };
596
I18nTimeZone(std::string & id,bool isZoneID)597 I18nTimeZone::I18nTimeZone(std::string &id, bool isZoneID)
598 {
599 if (isZoneID) {
600 if (id.empty()) {
601 std::string systemTimezone = ReadSystemParameter(TIMEZONE_KEY, SYS_PARAM_LEN);
602 if (systemTimezone.length() == 0) {
603 systemTimezone = DEFAULT_TIMEZONE;
604 }
605 icu::UnicodeString unicodeZoneID(systemTimezone.data(), systemTimezone.length());
606 timezone = icu::TimeZone::createTimeZone(unicodeZoneID);
607 } else {
608 icu::UnicodeString unicodeZoneID(id.data(), id.length());
609 timezone = icu::TimeZone::createTimeZone(unicodeZoneID);
610 }
611 } else {
612 if (city2TimeZoneID.size() == 0) {
613 GetAvailableZoneCityIDs();
614 }
615 if (city2TimeZoneID.find(id) == city2TimeZoneID.end()) {
616 timezone = icu::TimeZone::createDefault();
617 } else {
618 std::string timezoneID = city2TimeZoneID.at(id);
619 icu::UnicodeString unicodeZoneID(timezoneID.data(), timezoneID.length());
620 timezone = icu::TimeZone::createTimeZone(unicodeZoneID);
621 }
622 }
623 }
624
~I18nTimeZone()625 I18nTimeZone::~I18nTimeZone()
626 {
627 if (timezone != nullptr) {
628 delete timezone;
629 timezone = nullptr;
630 }
631 }
632
GetTimeZone()633 icu::TimeZone* I18nTimeZone::GetTimeZone()
634 {
635 return timezone;
636 }
637
CreateInstance(std::string & id,bool isZoneID)638 std::unique_ptr<I18nTimeZone> I18nTimeZone::CreateInstance(std::string &id, bool isZoneID)
639 {
640 std::unique_ptr<I18nTimeZone> i18nTimeZone = std::make_unique<I18nTimeZone>(id, isZoneID);
641 if (i18nTimeZone->GetTimeZone() == nullptr) {
642 return nullptr;
643 }
644 return i18nTimeZone;
645 }
646
GetOffset(double date)647 int32_t I18nTimeZone::GetOffset(double date)
648 {
649 int32_t rawOffset = 0;
650 int32_t dstOffset = 0;
651 bool local = false;
652 UErrorCode status = U_ZERO_ERROR;
653 if (timezone == nullptr) {
654 return 0;
655 }
656 timezone->getOffset(date, (UBool)local, rawOffset, dstOffset, status);
657 if (status != U_ZERO_ERROR) {
658 return 0;
659 }
660 return rawOffset + dstOffset;
661 }
662
GetRawOffset()663 int32_t I18nTimeZone::GetRawOffset()
664 {
665 if (timezone == nullptr) {
666 return 0;
667 }
668 return timezone->getRawOffset();
669 }
670
GetID()671 std::string I18nTimeZone::GetID()
672 {
673 if (timezone == nullptr) {
674 return "";
675 }
676 icu::UnicodeString zoneID;
677 timezone->getID(zoneID);
678 std::string result;
679 zoneID.toUTF8String(result);
680 return result;
681 }
682
GetDisplayName()683 std::string I18nTimeZone::GetDisplayName()
684 {
685 if (timezone == nullptr) {
686 return "";
687 }
688 std::string localeStr = LocaleConfig::GetSystemLocale();
689 return GetDisplayName(localeStr, false);
690 }
691
GetDisplayName(bool isDST)692 std::string I18nTimeZone::GetDisplayName(bool isDST)
693 {
694 std::string localeStr = LocaleConfig::GetSystemLocale();
695 return GetDisplayName(localeStr, isDST);
696 }
697
GetDisplayName(std::string localeStr)698 std::string I18nTimeZone::GetDisplayName(std::string localeStr)
699 {
700 return GetDisplayName(localeStr, false);
701 }
702
GetDisplayName(std::string localeStr,bool isDST)703 std::string I18nTimeZone::GetDisplayName(std::string localeStr, bool isDST)
704 {
705 icu::TimeZone::EDisplayType style = icu::TimeZone::EDisplayType::LONG_GENERIC;
706 UErrorCode status = U_ZERO_ERROR;
707 std::string systemLocale = LocaleConfig::GetSystemLocale();
708 icu::Locale locale = icu::Locale::forLanguageTag(systemLocale, status);
709 std::string result;
710 if (LocaleConfig::IsValidTag(localeStr)) {
711 locale = icu::Locale::forLanguageTag(localeStr, status);
712 }
713 if (U_FAILURE(status)) {
714 HiLog::Error(LABEL, "create icu Locale for %{public}s failed.", localeStr.c_str());
715 return result;
716 }
717 icu::UnicodeString name;
718 timezone->getDisplayName((UBool)isDST, style, locale, name);
719 name.toUTF8String(result);
720 return GetDisplayNameByTaboo(localeStr, result);
721 }
722
GetDisplayNameByTaboo(const std::string & localeStr,std::string result)723 std::string I18nTimeZone::GetDisplayNameByTaboo(const std::string& localeStr, std::string result)
724 {
725 void *i18nUtilHandle = dlopen("libi18n_util.z.so", RTLD_NOW);
726 if (i18nUtilHandle == nullptr) {
727 return result;
728 }
729 GetReplacedTimezoneDisplayName getReplacedTimezoneDisplayName =
730 (GetReplacedTimezoneDisplayName)dlsym(i18nUtilHandle, "GetReplacedTimezoneDisplayName");
731
732 char recvArr[RECV_CHAR_LEN];
733 int err = strcpy_s(recvArr, RECV_CHAR_LEN, result.c_str());
734 if (err != 0) {
735 return result;
736 }
737 if (getReplacedTimezoneDisplayName) {
738 getReplacedTimezoneDisplayName(localeStr.c_str(), GetID().c_str(), recvArr);
739 }
740 result = recvArr;
741 #ifndef SUPPORT_ASAN
742 dlclose(i18nUtilHandle);
743 #endif
744 return result;
745 }
746
ReadTimeZoneData(const char * xmlPath)747 bool I18nTimeZone::ReadTimeZoneData(const char *xmlPath)
748 {
749 xmlKeepBlanksDefault(0);
750 if (xmlPath == nullptr) {
751 return false;
752 }
753 xmlDocPtr doc = xmlParseFile(xmlPath);
754 if (!doc) {
755 return false;
756 }
757 xmlNodePtr cur = xmlDocGetRootElement(doc);
758 if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(TIMEZONE_ROOT_TAG))) {
759 xmlFreeDoc(doc);
760 return false;
761 }
762 cur = cur->xmlChildrenNode;
763 while (cur != nullptr && !xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(TIMEZONE_SECOND_ROOT_TAG))) {
764 xmlNodePtr value = cur->xmlChildrenNode;
765 xmlChar *contents[ELEMENT_NUM] = { 0 }; // 2 represent cityid, zoneid;
766 for (size_t i = 0; i < ELEMENT_NUM; i++) {
767 if (value != nullptr) {
768 contents[i] = xmlNodeGetContent(value);
769 value = value->next;
770 } else {
771 break;
772 }
773 }
774 // 0 represents cityid index, 1 represents zoneid index
775 availableZoneCityIDs.insert(reinterpret_cast<const char *>(contents[0]));
776 city2TimeZoneID.insert(
777 std::make_pair<std::string, std::string>(reinterpret_cast<const char *>(contents[0]),
778 reinterpret_cast<const char *>(contents[1])));
779 for (size_t i = 0; i < ELEMENT_NUM; i++) {
780 if (contents[i] != nullptr) {
781 xmlFree(contents[i]);
782 }
783 }
784 cur = cur->next;
785 }
786 xmlFreeDoc(doc);
787 return true;
788 }
789
GetTimezoneIDFromZoneInfo(std::set<std::string> & availableIDs,std::string & parentPath,std::string & parentName)790 void I18nTimeZone::GetTimezoneIDFromZoneInfo(std::set<std::string> &availableIDs, std::string &parentPath,
791 std::string &parentName)
792 {
793 using std::filesystem::directory_iterator;
794
795 struct stat s;
796 for (const auto &dirEntry : directory_iterator{parentPath}) {
797 std::string zonePath = dirEntry.path();
798 if (stat(zonePath.c_str(), &s) != 0) {
799 HiLog::Error(LABEL, "zoneinfo path %{public}s not exist.", parentPath.c_str());
800 return;
801 }
802 std::string zoneName = zonePath.substr(parentPath.length() + 1); // 1 add length of path splitor
803 std::string finalZoneName = parentName + "/" + zoneName;
804 if (s.st_mode & S_IFDIR) {
805 GetTimezoneIDFromZoneInfo(availableIDs, zonePath, finalZoneName);
806 } else {
807 availableIDs.insert(finalZoneName);
808 }
809 }
810 }
811
GetAvailableIDs(I18nErrorCode & errorCode)812 std::set<std::string> I18nTimeZone::GetAvailableIDs(I18nErrorCode &errorCode)
813 {
814 using std::filesystem::directory_iterator;
815
816 if (availableIDs.size() != 0) {
817 return availableIDs;
818 }
819 struct stat s;
820 for (const auto &dirEntry : directory_iterator{ZONEINFO_PATH}) {
821 std::string parentPath = dirEntry.path();
822 if (stat(parentPath.c_str(), &s) != 0) {
823 HiLog::Error(LABEL, "zoneinfo path %{public}s not exist.", parentPath.c_str());
824 errorCode = I18nErrorCode::FAILED;
825 return availableIDs;
826 }
827 std::string parentName = parentPath.substr(strlen(ZONEINFO_PATH) + 1);
828 if (s.st_mode & S_IFDIR) {
829 GetTimezoneIDFromZoneInfo(availableIDs, parentPath, parentName);
830 } else {
831 availableIDs.insert(parentName);
832 }
833 }
834 return availableIDs;
835 }
836
GetAvailableZoneCityIDs()837 std::set<std::string> I18nTimeZone::GetAvailableZoneCityIDs()
838 {
839 if (availableZoneCityIDs.size() != 0) {
840 return availableZoneCityIDs;
841 }
842 struct stat s;
843 if (stat(DEVICE_CITY_TIMEZONE_DATA_PATH, &s) == 0) {
844 ReadTimeZoneData(DEVICE_CITY_TIMEZONE_DATA_PATH);
845 } else {
846 ReadTimeZoneData(CITY_TIMEZONE_DATA_PATH);
847 }
848 return availableZoneCityIDs;
849 }
850
FindCityDisplayNameFromXml(std::string & cityID,std::string & locale)851 std::string I18nTimeZone::FindCityDisplayNameFromXml(std::string &cityID, std::string &locale)
852 {
853 xmlKeepBlanksDefault(0);
854 std::string xmlPath;
855 if (useDeviceCityDispName) {
856 xmlPath = DEVICE_CITY_DISPLAYNAME_PATH + locale + ".xml";
857 } else {
858 xmlPath = CITY_DISPLAYNAME_PATH + locale + ".xml";
859 }
860 xmlDocPtr doc = xmlParseFile(xmlPath.c_str());
861 if (!doc) {
862 HiLog::Error(LABEL, "can't parse city displayname file %{public}s", xmlPath.c_str());
863 return "";
864 }
865 xmlNodePtr cur = xmlDocGetRootElement(doc);
866 if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(CITY_DISPLAYNAME_ROOT_TAG))) {
867 xmlFreeDoc(doc);
868 HiLog::Error(LABEL, "city displayname file %{public}s has wrong root tag.", xmlPath.c_str());
869 return "";
870 }
871 cur = cur->xmlChildrenNode;
872 std::string displayName;
873 while (cur != nullptr && !xmlStrcmp(cur->name,
874 reinterpret_cast<const xmlChar *>(CITY_DISPLAYNAME_SECOND_ROOT_TAG))) {
875 xmlNodePtr value = cur->xmlChildrenNode;
876 xmlChar *contents[ELEMENT_NUM] = { 0 }; // 2 represent cityid, displayName;
877 for (size_t i = 0; i < ELEMENT_NUM; i++) {
878 if (value != nullptr) {
879 contents[i] = xmlNodeGetContent(value);
880 value = value->next;
881 } else {
882 break;
883 }
884 }
885 if (strcmp(cityID.c_str(), reinterpret_cast<const char *>(contents[0])) == 0) {
886 displayName = reinterpret_cast<const char *>(contents[1]);
887 }
888 for (size_t i = 0; i < ELEMENT_NUM; i++) {
889 if (contents[i] != nullptr) {
890 xmlFree(contents[i]);
891 }
892 }
893 if (displayName.length() != 0) {
894 break;
895 }
896 cur = cur->next;
897 }
898 xmlFreeDoc(doc);
899 return displayName;
900 }
901
FindCityDisplayNameMap(std::string & locale)902 std::map<std::string, std::string> I18nTimeZone::FindCityDisplayNameMap(std::string &locale)
903 {
904 xmlKeepBlanksDefault(0);
905 std::map<std::string, std::string> resultMap;
906 std::string xmlPath;
907 if (useDeviceCityDispName) {
908 xmlPath = DEVICE_CITY_DISPLAYNAME_PATH + locale + ".xml";
909 } else {
910 xmlPath = CITY_DISPLAYNAME_PATH + locale + ".xml";
911 }
912 xmlDocPtr doc = xmlParseFile(xmlPath.c_str());
913 if (!doc) {
914 HiLog::Error(LABEL, "can't parse city displayname file %{public}s", xmlPath.c_str());
915 return resultMap;
916 }
917 xmlNodePtr cur = xmlDocGetRootElement(doc);
918 if (!cur || xmlStrcmp(cur->name, reinterpret_cast<const xmlChar *>(CITY_DISPLAYNAME_ROOT_TAG))) {
919 xmlFreeDoc(doc);
920 HiLog::Error(LABEL, "city displayname file %{public}s has wrong root tag.", xmlPath.c_str());
921 return resultMap;
922 }
923 cur = cur->xmlChildrenNode;
924 while (cur != nullptr && !xmlStrcmp(cur->name,
925 reinterpret_cast<const xmlChar *>(CITY_DISPLAYNAME_SECOND_ROOT_TAG))) {
926 xmlNodePtr value = cur->xmlChildrenNode;
927 xmlChar *contents[ELEMENT_NUM] = { 0 }; // 2 represent cityid, displayName;
928 for (size_t i = 0; i < ELEMENT_NUM; i++) {
929 if (value != nullptr) {
930 contents[i] = xmlNodeGetContent(value);
931 value = value->next;
932 } else {
933 break;
934 }
935 }
936 resultMap.insert(
937 std::make_pair<std::string, std::string>(reinterpret_cast<const char *>(contents[0]),
938 reinterpret_cast<const char *>(contents[1])));
939 for (size_t i = 0; i < ELEMENT_NUM; i++) {
940 if (contents[i] != nullptr) {
941 xmlFree(contents[i]);
942 }
943 }
944 cur = cur->next;
945 }
946 xmlFreeDoc(doc);
947 return resultMap;
948 }
949
GetSupportedLocales()950 bool I18nTimeZone::GetSupportedLocales()
951 {
952 using std::filesystem::directory_iterator;
953
954 struct stat s;
955 std::string displayNamePath;
956 if (stat(DEVICE_CITY_DISPLAYNAME_PATH, &s) == 0) {
957 useDeviceCityDispName = true;
958 displayNamePath = DEVICE_CITY_DISPLAYNAME_PATH;
959 } else {
960 displayNamePath = CITY_DISPLAYNAME_PATH;
961 }
962 for (const auto &dirEntry : directory_iterator{displayNamePath}) {
963 std::string xmlPath = dirEntry.path();
964 if (stat(xmlPath.c_str(), &s) != 0) {
965 HiLog::Error(LABEL, "city displayname file %{public}s not exist.", xmlPath.c_str());
966 return false;
967 }
968 int32_t localeStrLen = static_cast<int32_t>(xmlPath.length()) - static_cast<int32_t>(
969 displayNamePath.length()) - 4; // 4 is the length of ".xml"
970 std::string localeStr = xmlPath.substr(displayNamePath.length(), localeStrLen);
971 supportedLocales.insert(localeStr);
972 }
973 return true;
974 }
975
GetFallBack(std::string & localeStr)976 std::string I18nTimeZone::GetFallBack(std::string &localeStr)
977 {
978 if (strcmp(localeStr.c_str(), DEFAULT_LOCALE) == 0) {
979 return "";
980 }
981 size_t begin = 0;
982 std::vector<std::string> localeParts;
983 bool breakFlag = true;
984 while (breakFlag) {
985 size_t end = localeStr.find('_', begin);
986 localeParts.push_back(localeStr.substr(begin, end - begin));
987 if (end == std::string::npos) {
988 breakFlag = false;
989 }
990 begin = end + 1;
991 }
992
993 if (localeParts.size() == 1) {
994 return DEFAULT_LOCALE;
995 }
996 std::string fallBackLocale;
997 for (size_t i = 0; i < localeParts.size() - 1; i++) {
998 fallBackLocale += localeParts[i];
999 if (i != localeParts.size() - 2) { // -2 represent the last part
1000 fallBackLocale += "_";
1001 }
1002 }
1003 return fallBackLocale;
1004 }
1005
GetCityDisplayName(std::string & cityID,std::string & localeStr)1006 std::string I18nTimeZone::GetCityDisplayName(std::string &cityID, std::string &localeStr)
1007 {
1008 if (availableZoneCityIDs.size() == 0) {
1009 GetAvailableZoneCityIDs();
1010 }
1011 if (availableZoneCityIDs.find(cityID) == availableZoneCityIDs.end()) {
1012 HiLog::Error(LABEL, "%{public}s is not supported cityID.", cityID.c_str());
1013 return "";
1014 }
1015 std::string requestLocaleStr = GetLocaleBaseName(localeStr);
1016 if (requestLocaleStr.length() != 0) {
1017 std::string displayName = FindCityDisplayNameFromXml(cityID, requestLocaleStr);
1018 if (displayName.length() != 0) {
1019 return displayName;
1020 }
1021 }
1022 return "";
1023 }
1024
GetLocaleBaseName(std::string & localeStr)1025 std::string I18nTimeZone::GetLocaleBaseName(std::string &localeStr)
1026 {
1027 if (supportedLocales.size() == 0) {
1028 bool status = GetSupportedLocales();
1029 if (!status) {
1030 HiLog::Error(LABEL, "get supported Locales failed");
1031 return "";
1032 }
1033 }
1034 UErrorCode errorCode = U_ZERO_ERROR;
1035 icu::Locale locale = icu::Locale::forLanguageTag(localeStr, errorCode);
1036 if (U_FAILURE(errorCode)) {
1037 HiLog::Error(LABEL, "create icu Locale for %{public}s failed", localeStr.c_str());
1038 return "";
1039 }
1040 std::string requestLocaleStr = locale.getBaseName();
1041 std::string displayName;
1042 if (supportedLocales.find(requestLocaleStr) != supportedLocales.end()) {
1043 return requestLocaleStr;
1044 }
1045 locale.addLikelySubtags(errorCode);
1046 if (U_FAILURE(errorCode)) {
1047 HiLog::Error(LABEL, "add likely subtags for %{public}s failed", localeStr.c_str());
1048 return "";
1049 }
1050 requestLocaleStr = locale.getBaseName();
1051 while (requestLocaleStr.length() != 0) {
1052 if (supportedLocales.find(requestLocaleStr) != supportedLocales.end() || strcmp(requestLocaleStr.c_str(),
1053 DEFAULT_LOCALE) == 0) {
1054 return requestLocaleStr;
1055 }
1056 requestLocaleStr = GetFallBack(requestLocaleStr);
1057 }
1058 return displayName;
1059 }
1060
GetTimezoneIdByCityId(const std::string & cityId)1061 std::string I18nTimeZone::GetTimezoneIdByCityId(const std::string &cityId)
1062 {
1063 if (city2TimeZoneID.size() == 0) {
1064 GetAvailableZoneCityIDs();
1065 }
1066 if (city2TimeZoneID.find(cityId) == city2TimeZoneID.end()) {
1067 return "";
1068 } else {
1069 return city2TimeZoneID.at(cityId);
1070 }
1071 }
1072
GetTimezoneIdByLocation(const double x,const double y)1073 std::vector<std::string> I18nTimeZone::GetTimezoneIdByLocation(const double x, const double y)
1074 {
1075 std::vector<std::string> tzIdList;
1076 #ifdef SUPPORT_GRAPHICS
1077 if (!CheckLatitudeAndLongitude(x, y)) {
1078 HiLog::Error(LABEL, "invalid longitude:%{public}f or latitude: %{public}f ", x, y);
1079 return tzIdList;
1080 }
1081 std::map<int, std::string> categoryMap = GetTimeZoneCategoryMap(x, y);
1082 std::vector<std::string> filePaths = FindTzData();
1083 size_t fileCount = filePaths.size();
1084 if (fileCount < 1) {
1085 return tzIdList;
1086 }
1087 std::string preferredPath = GetPreferredPath(x, filePaths);
1088 if (preferredPath == "") {
1089 return tzIdList;
1090 }
1091 uint32_t width;
1092 uint32_t height;
1093 GetTzDataWidth(filePaths, &width, &height);
1094 double calculateX = y * width / (TZ_X_PLUS * 1.0) + width / (TZ_HALF_OF_SIZE * 1.0);
1095 double calculateY = x * ((height * fileCount) / (TZ_X_PLUS * TZ_HALF_OF_SIZE * 1.0)) +
1096 (height * fileCount) / (TZ_HALF_OF_SIZE * 1.0);
1097 uint16_t fixedX = static_cast<uint16_t>(calculateX);
1098 uint16_t fixedY = static_cast<uint16_t>(calculateY);
1099 if (ParamExceedScope(fixedX, fixedY, width, height * fileCount)) {
1100 HiLog::Error(LABEL, "invalid width:%{public}d or height: %{public}d", fixedX, fixedY);
1101 return tzIdList;
1102 }
1103 uint16_t actualHeight = fileCount > 1 ? (fixedY % height) : fixedY;
1104 std::vector<int> pixel = GetColorData(fixedX, fixedY, actualHeight, preferredPath);
1105 for (size_t i = 0; i < pixel.size(); i++) {
1106 //255 is invalid pixel value required
1107 if (pixel[i] != TZ_MAX_PIXEL_VALUE && categoryMap.find(pixel[i]) != categoryMap.end()) {
1108 std::string zdId = categoryMap[pixel[i]];
1109 tzIdList.push_back(zdId);
1110 }
1111 }
1112 #endif
1113 return tzIdList;
1114 }
1115
GetTimeZoneCategoryMap(const double x,const double y)1116 std::map<int, std::string> I18nTimeZone::GetTimeZoneCategoryMap(const double x, const double y)
1117 {
1118 if (x < 0 && y >= 0) {
1119 return categoryNum2TimezoneWN;
1120 } else if (x >= 0 && y >= 0) {
1121 return categoryNum2TimezoneEN;
1122 } else if (x < 0 && y < 0) {
1123 return categoryNum2TimezoneWS;
1124 } else {
1125 return categoryNum2TimezoneES;
1126 }
1127 }
1128
CheckLatitudeAndLongitude(const double x,const double y)1129 bool I18nTimeZone::CheckLatitudeAndLongitude(const double x, const double y)
1130 {
1131 if (x < -1.0 * TZ_X_PLUS) {
1132 return false;
1133 }
1134 if (x >= TZ_X_PLUS * 1.0 - NUM_PRECISION) {
1135 return false;
1136 }
1137 if (y < -1.0 * TZ_X_PLUS/TZ_HALF_OF_SIZE) {
1138 return false;
1139 }
1140 if (y >= TZ_X_PLUS * 1.0/TZ_HALF_OF_SIZE - NUM_PRECISION) {
1141 return false;
1142 }
1143 return true;
1144 }
1145
GetColorData(const uint16_t x,const uint16_t y,uint16_t actualHeight,std::string preferredPath)1146 std::vector<int> I18nTimeZone::GetColorData(const uint16_t x, const uint16_t y,
1147 uint16_t actualHeight, std::string preferredPath)
1148 {
1149 std::vector<int> result;
1150 FILE *fp;
1151 png_structp png_ptr;
1152 png_infop info_ptr;
1153 png_bytep row_pointers;
1154 int code = InitPngptr(png_ptr, info_ptr, &fp, preferredPath);
1155 if (code != 0) {
1156 return result;
1157 }
1158 try {
1159 rewind(fp);
1160 png_init_io(png_ptr, fp);
1161 png_read_info(png_ptr, info_ptr);
1162 unsigned int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
1163 row_pointers = (png_bytep)png_malloc(png_ptr, rowbytes);
1164 if (row_pointers == nullptr) {
1165 png_destroy_read_struct(&png_ptr, &info_ptr, 0);
1166 CloseFile(fp);
1167 HiLog::Error(LABEL, "malloc rowbytes failed.");
1168 return result;
1169 }
1170 png_start_read_image(png_ptr);
1171 for (int i = 0; i < (actualHeight + 1); i++) {
1172 png_read_row(png_ptr, row_pointers, NULL);
1173 }
1174 for (size_t i = 0; i < 3; i++) { // 3 is RGB color pixel length
1175 std::string pixel = std::to_string(*(row_pointers + x * 3 + i)); // 3 is RGB color pixel length
1176 result.push_back(atoi(pixel.c_str()));
1177 }
1178 png_free(png_ptr, row_pointers);
1179 CloseFile(fp);
1180 } catch (...) {
1181 png_destroy_read_struct(&png_ptr, &info_ptr, 0);
1182 CloseFile(fp);
1183 }
1184 return result;
1185 }
1186
GetTzDataWidth(std::vector<std::string> filePaths,uint32_t * width,uint32_t * height)1187 void I18nTimeZone::GetTzDataWidth(std::vector<std::string> filePaths, uint32_t *width, uint32_t *height)
1188 {
1189 if (filePaths.size() == 0 || !CheckTzDataFilePath(filePaths.at(0))) {
1190 *width = 0;
1191 *height = 0;
1192 } else {
1193 FILE* fp;
1194 png_structp png_ptr;
1195 png_infop info_ptr;
1196 try {
1197 std::string path = filePaths.at(0);
1198 fp = fopen(path.c_str(), "rb");
1199 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1200 info_ptr = png_create_info_struct(png_ptr);
1201 rewind(fp);
1202 png_init_io(png_ptr, fp);
1203 png_read_info(png_ptr, info_ptr);
1204 unsigned int w, h;
1205 png_get_IHDR(png_ptr, info_ptr, &w, &h, NULL, NULL, NULL, NULL, NULL);
1206 *width = w;
1207 *height = h;
1208 png_destroy_read_struct(&png_ptr, &info_ptr, 0);
1209 CloseFile(fp);
1210 } catch(...) {
1211 png_destroy_read_struct(&png_ptr, &info_ptr, 0);
1212 CloseFile(fp);
1213 }
1214 }
1215 }
1216
InitPngptr(png_structp & png_ptr,png_infop & info_ptr,FILE ** fp,std::string preferredPath)1217 int I18nTimeZone::InitPngptr(png_structp &png_ptr, png_infop &info_ptr, FILE **fp,
1218 std::string preferredPath)
1219 {
1220 bool validFilePath = CheckTzDataFilePath(preferredPath);
1221 if (!validFilePath) {
1222 HiLog::Error(LABEL, "timezone data filepath invalid.");
1223 return 1;
1224 }
1225 *fp = fopen(preferredPath.c_str(), "rb");
1226 if (*fp == NULL) {
1227 HiLog::Error(LABEL, "timezone data resource file not exists.");
1228 return 1;
1229 }
1230 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1231 if (!png_ptr) {
1232 png_destroy_read_struct(&png_ptr, &info_ptr, 0);
1233 CloseFile(*fp);
1234 HiLog::Error(LABEL, "create read_struct failed.");
1235 return 1;
1236 }
1237 info_ptr = png_create_info_struct(png_ptr);
1238 if (!info_ptr) {
1239 png_destroy_read_struct(&png_ptr, &info_ptr, 0);
1240 CloseFile(*fp);
1241 HiLog::Error(LABEL, "create info_struct failed.");
1242 return 1;
1243 }
1244 return 0;
1245 }
1246
GetPreferredPath(const double x,const std::vector<std::string> & filePaths)1247 std::string I18nTimeZone::GetPreferredPath(const double x,
1248 const std::vector<std::string> &filePaths)
1249 {
1250 if (filePaths.size() == 1) {
1251 return filePaths.at(0);
1252 } else {
1253 int fixedX = (int)(x + TZ_X_PLUS);
1254 for (unsigned int i = 0; i < filePaths.size(); i++) {
1255 std::string path = filePaths.at(i);
1256 std::string left = path.substr(path.find("-") + 1, 3);
1257 std::string right = path.substr(path.find("-") + 4, 3);
1258 if (fixedX >= atoi(left.c_str()) && fixedX < atoi(right.c_str())) {
1259 return path;
1260 }
1261 }
1262 return "";
1263 }
1264 }
1265
FindTzData()1266 std::vector<std::string> I18nTimeZone::FindTzData()
1267 {
1268 using std::filesystem::directory_iterator;
1269 std::map<std::string, std::vector<std::string>> pathMap;
1270 std::regex reg("tz_[0-9]{7}-(\\d{6})\\.dat");
1271 std::regex regVersion("_[0-9]{7}");
1272 for (const auto& entry : directory_iterator{TZ_PIXEL_PATH}) {
1273 const std::string path = entry.path();
1274 std::smatch match;
1275 bool found = std::regex_search(path, match, reg);
1276 if (found) {
1277 bool hasVerison = std::regex_search(path, match, regVersion);
1278 if (hasVerison) {
1279 std::string version = match[0].str();
1280 SetVersionPathMap(version, path, &pathMap);
1281 }
1282 }
1283 }
1284 std::vector<std::string> filePaths;
1285 std::map<std::string, std::vector<std::string>>::reverse_iterator iter;
1286 for (iter = pathMap.rbegin(); iter != pathMap.rend(); ++iter) {
1287 if (ValidateDataIntegrity(iter->second)) {
1288 return iter->second;
1289 }
1290 }
1291 return filePaths;
1292 }
1293
ValidateDataIntegrity(const std::vector<std::string> & pathList)1294 bool I18nTimeZone::ValidateDataIntegrity(const std::vector<std::string> &pathList)
1295 {
1296 size_t total = 0;
1297 for (unsigned int i = 0; i < pathList.size(); i++) {
1298 std::string path = pathList.at(i);
1299 std::string left = path.substr(path.find("-") + 1, 3);
1300 std::string right = path.substr(path.find("-") + 4, 3);
1301 total += abs(atoi(right.c_str()) - atoi(left.c_str()));
1302 }
1303 return total == TZ_X_PLUS * TZ_HALF_OF_SIZE;
1304 }
1305
SetVersionPathMap(std::string verison,std::string path,std::map<std::string,std::vector<std::string>> * pathMap)1306 void I18nTimeZone::SetVersionPathMap(std::string verison, std::string path,
1307 std::map<std::string, std::vector<std::string>> *pathMap)
1308 {
1309 if (pathMap == nullptr) {
1310 return;
1311 }
1312 if (pathMap->find(verison) != pathMap->end()) {
1313 std::vector<std::string> *list = &(pathMap->find(verison)->second);
1314 list->push_back(path);
1315 } else {
1316 std::vector<std::string> list;
1317 list.push_back(path);
1318 pathMap->insert(std::pair<std::string, std::vector<std::string>>(verison, list));
1319 }
1320 }
1321
CloseFile(FILE * fp)1322 void I18nTimeZone::CloseFile(FILE *fp)
1323 {
1324 if (fp != nullptr && fp != NULL) {
1325 fclose(fp);
1326 }
1327 }
1328
ParamExceedScope(const int x,const int y,int fixedX,int fixedY)1329 bool I18nTimeZone::ParamExceedScope(const int x, const int y, int fixedX, int fixedY)
1330 {
1331 if (x < 0 || y < 0 || fixedX == 0 || fixedY == 0) {
1332 return true;
1333 }
1334 if (x > (fixedX - 1) || y > (fixedY - 1)) {
1335 return true;
1336 }
1337 return false;
1338 }
1339 }
1340 }
1341 }
1342