Line |
Branch |
Exec |
Source |
1 |
|
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ |
2 |
|
|
/* Generic timezone utilities. |
3 |
|
|
* |
4 |
|
|
* Copyright (C) 2000-2001 Ximian, Inc. |
5 |
|
|
* |
6 |
|
|
* Authors: Hans Petter Jansson <hpj@ximian.com> |
7 |
|
|
* |
8 |
|
|
* Largely based on Michael Fulbright's work on Anaconda. |
9 |
|
|
* |
10 |
|
|
* This program is free software; you can redistribute it and/or modify |
11 |
|
|
* it under the terms of the GNU General Public License as published by |
12 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
13 |
|
|
* (at your option) any later version. |
14 |
|
|
* |
15 |
|
|
* This program is distributed in the hope that it will be useful, |
16 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 |
|
|
* GNU General Public License for more details. |
19 |
|
|
* |
20 |
|
|
* You should have received a copy of the GNU General Public License |
21 |
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>. |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
|
25 |
|
|
#include <glib.h> |
26 |
|
|
#include <stdio.h> |
27 |
|
|
#include <stdlib.h> |
28 |
|
|
#include <unistd.h> |
29 |
|
|
#include <time.h> |
30 |
|
|
#include <math.h> |
31 |
|
|
#include <string.h> |
32 |
|
|
#include <ctype.h> |
33 |
|
|
#include "tz.h" |
34 |
|
|
#include "cc-system-resources.h" |
35 |
|
|
|
36 |
|
|
|
37 |
|
|
/* Forward declarations for private functions */ |
38 |
|
|
|
39 |
|
|
static float convert_pos (gchar *pos, int digits); |
40 |
|
|
static int compare_country_names (const void *a, const void *b); |
41 |
|
|
static void sort_locations_by_country (GPtrArray *locations); |
42 |
|
|
static gchar * tz_data_file_get (void); |
43 |
|
|
static void load_backward_tz (TzDB *tz_db); |
44 |
|
|
|
45 |
|
|
/* ---------------- * |
46 |
|
|
* Public interface * |
47 |
|
|
* ---------------- */ |
48 |
|
|
TzDB * |
49 |
|
✗ |
tz_load_db (void) |
50 |
|
|
{ |
51 |
|
✗ |
g_autofree gchar *tz_data_file = NULL; |
52 |
|
|
TzDB *tz_db; |
53 |
|
|
FILE *tzfile; |
54 |
|
|
char buf[4096]; |
55 |
|
|
|
56 |
|
✗ |
tz_data_file = tz_data_file_get (); |
57 |
|
✗ |
if (!tz_data_file) { |
58 |
|
✗ |
g_warning ("Could not get the TimeZone data file name"); |
59 |
|
✗ |
return NULL; |
60 |
|
|
} |
61 |
|
✗ |
tzfile = fopen (tz_data_file, "r"); |
62 |
|
✗ |
if (!tzfile) { |
63 |
|
✗ |
g_warning ("Could not open *%s*\n", tz_data_file); |
64 |
|
✗ |
return NULL; |
65 |
|
|
} |
66 |
|
|
|
67 |
|
✗ |
tz_db = g_new0 (TzDB, 1); |
68 |
|
✗ |
tz_db->locations = g_ptr_array_new (); |
69 |
|
|
|
70 |
|
✗ |
while (fgets (buf, sizeof(buf), tzfile)) |
71 |
|
|
{ |
72 |
|
✗ |
g_auto(GStrv) tmpstrarr = NULL; |
73 |
|
✗ |
g_autofree gchar *latstr = NULL; |
74 |
|
✗ |
g_autofree gchar *lngstr = NULL; |
75 |
|
|
gchar *p; |
76 |
|
|
TzLocation *loc; |
77 |
|
|
|
78 |
|
✗ |
if (*buf == '#') continue; |
79 |
|
|
|
80 |
|
✗ |
g_strchomp(buf); |
81 |
|
✗ |
tmpstrarr = g_strsplit(buf,"\t", 6); |
82 |
|
|
|
83 |
|
✗ |
latstr = g_strdup (tmpstrarr[1]); |
84 |
|
✗ |
p = latstr + 1; |
85 |
|
✗ |
while (*p != '-' && *p != '+') p++; |
86 |
|
✗ |
lngstr = g_strdup (p); |
87 |
|
✗ |
*p = '\0'; |
88 |
|
|
|
89 |
|
✗ |
loc = g_new0 (TzLocation, 1); |
90 |
|
✗ |
loc->country = g_strdup (tmpstrarr[0]); |
91 |
|
✗ |
loc->zone = g_strdup (tmpstrarr[2]); |
92 |
|
✗ |
loc->latitude = convert_pos (latstr, 2); |
93 |
|
✗ |
loc->longitude = convert_pos (lngstr, 3); |
94 |
|
|
|
95 |
|
|
#ifdef __sun |
96 |
|
|
if (tmpstrarr[3] && *tmpstrarr[3] == '-' && tmpstrarr[4]) |
97 |
|
|
loc->comment = g_strdup (tmpstrarr[4]); |
98 |
|
|
|
99 |
|
|
if (tmpstrarr[3] && *tmpstrarr[3] != '-' && !islower(loc->zone)) { |
100 |
|
|
TzLocation *locgrp; |
101 |
|
|
|
102 |
|
|
/* duplicate entry */ |
103 |
|
|
locgrp = g_new0 (TzLocation, 1); |
104 |
|
|
locgrp->country = g_strdup (tmpstrarr[0]); |
105 |
|
|
locgrp->zone = g_strdup (tmpstrarr[3]); |
106 |
|
|
locgrp->latitude = convert_pos (latstr, 2); |
107 |
|
|
locgrp->longitude = convert_pos (lngstr, 3); |
108 |
|
|
locgrp->comment = (tmpstrarr[4]) ? g_strdup (tmpstrarr[4]) : NULL; |
109 |
|
|
|
110 |
|
|
g_ptr_array_add (tz_db->locations, (gpointer) locgrp); |
111 |
|
|
} |
112 |
|
|
#else |
113 |
|
✗ |
loc->comment = (tmpstrarr[3]) ? g_strdup(tmpstrarr[3]) : NULL; |
114 |
|
|
#endif |
115 |
|
|
|
116 |
|
✗ |
g_ptr_array_add (tz_db->locations, (gpointer) loc); |
117 |
|
|
} |
118 |
|
|
|
119 |
|
✗ |
fclose (tzfile); |
120 |
|
|
|
121 |
|
|
/* now sort by country */ |
122 |
|
✗ |
sort_locations_by_country (tz_db->locations); |
123 |
|
|
|
124 |
|
|
/* Load up the hashtable of backward links */ |
125 |
|
✗ |
load_backward_tz (tz_db); |
126 |
|
|
|
127 |
|
✗ |
return tz_db; |
128 |
|
|
} |
129 |
|
|
|
130 |
|
|
static void |
131 |
|
✗ |
tz_location_free (TzLocation *loc) |
132 |
|
|
{ |
133 |
|
✗ |
g_free (loc->country); |
134 |
|
✗ |
g_free (loc->zone); |
135 |
|
✗ |
g_free (loc->comment); |
136 |
|
|
|
137 |
|
✗ |
g_free (loc); |
138 |
|
✗ |
} |
139 |
|
|
|
140 |
|
|
void |
141 |
|
✗ |
tz_db_free (TzDB *db) |
142 |
|
|
{ |
143 |
|
✗ |
g_ptr_array_foreach (db->locations, (GFunc) tz_location_free, NULL); |
144 |
|
✗ |
g_ptr_array_free (db->locations, TRUE); |
145 |
|
✗ |
g_hash_table_destroy (db->backward); |
146 |
|
✗ |
g_free (db); |
147 |
|
✗ |
} |
148 |
|
|
|
149 |
|
|
GPtrArray * |
150 |
|
✗ |
tz_get_locations (TzDB *db) |
151 |
|
|
{ |
152 |
|
✗ |
return db->locations; |
153 |
|
|
} |
154 |
|
|
|
155 |
|
|
|
156 |
|
|
gchar * |
157 |
|
✗ |
tz_location_get_country (TzLocation *loc) |
158 |
|
|
{ |
159 |
|
✗ |
return loc->country; |
160 |
|
|
} |
161 |
|
|
|
162 |
|
|
|
163 |
|
|
gchar * |
164 |
|
✗ |
tz_location_get_zone (TzLocation *loc) |
165 |
|
|
{ |
166 |
|
✗ |
return loc->zone; |
167 |
|
|
} |
168 |
|
|
|
169 |
|
|
|
170 |
|
|
gchar * |
171 |
|
✗ |
tz_location_get_comment (TzLocation *loc) |
172 |
|
|
{ |
173 |
|
✗ |
return loc->comment; |
174 |
|
|
} |
175 |
|
|
|
176 |
|
|
|
177 |
|
|
void |
178 |
|
✗ |
tz_location_get_position (TzLocation *loc, double *longitude, double *latitude) |
179 |
|
|
{ |
180 |
|
✗ |
*longitude = loc->longitude; |
181 |
|
✗ |
*latitude = loc->latitude; |
182 |
|
✗ |
} |
183 |
|
|
|
184 |
|
|
/* For timezone map display purposes, we try to highlight regions of the |
185 |
|
|
* world that keep the same time. There is no reasonable API to discover |
186 |
|
|
* this; at the moment we just group timezones by their non-daylight-savings |
187 |
|
|
* UTC offset and hope that's good enough. However, in some cases that |
188 |
|
|
* produces confusing results. For example, Irish Standard Time is legally |
189 |
|
|
* defined as the country's summer time, with a negative DST offset in |
190 |
|
|
* winter; but this results in the same observed clock times as countries |
191 |
|
|
* that observe Western European (Summer) Time, not those that observe |
192 |
|
|
* Central European (Summer) Time, so we should group Ireland with the |
193 |
|
|
* former, matching the grouping implied by data/timezone_*.png. |
194 |
|
|
* |
195 |
|
|
* This is something of a hack, and there remain other problems with |
196 |
|
|
* timezone grouping: for example, grouping timezones north and south of the |
197 |
|
|
* equator together where DST is observed at different times of the year is |
198 |
|
|
* dubious. |
199 |
|
|
*/ |
200 |
|
|
struct { |
201 |
|
|
const char *zone; |
202 |
|
|
gint offset; |
203 |
|
|
} base_offset_overrides[] = { |
204 |
|
|
{ "Europe/Dublin", 0 }, |
205 |
|
|
}; |
206 |
|
|
|
207 |
|
|
glong |
208 |
|
✗ |
tz_location_get_base_utc_offset (TzLocation *loc) |
209 |
|
|
{ |
210 |
|
✗ |
g_autoptr(TzInfo) tz_info = NULL; |
211 |
|
|
glong offset; |
212 |
|
|
guint i; |
213 |
|
|
|
214 |
|
✗ |
tz_info = tz_info_from_location (loc); |
215 |
|
✗ |
offset = tz_info->utc_offset + (tz_info->daylight ? -3600 : 0); |
216 |
|
|
|
217 |
|
✗ |
for (i = 0; i < G_N_ELEMENTS (base_offset_overrides); i++) { |
218 |
|
✗ |
if (g_str_equal (loc->zone, base_offset_overrides[i].zone)) { |
219 |
|
✗ |
offset = base_offset_overrides[i].offset; |
220 |
|
✗ |
break; |
221 |
|
|
} |
222 |
|
|
} |
223 |
|
|
|
224 |
|
✗ |
return offset; |
225 |
|
|
} |
226 |
|
|
|
227 |
|
|
TzInfo * |
228 |
|
✗ |
tz_info_from_location (TzLocation *loc) |
229 |
|
|
{ |
230 |
|
|
TzInfo *tzinfo; |
231 |
|
|
time_t curtime; |
232 |
|
|
struct tm *curzone; |
233 |
|
✗ |
g_autofree gchar *tz_env_value = NULL; |
234 |
|
|
|
235 |
|
✗ |
g_return_val_if_fail (loc != NULL, NULL); |
236 |
|
✗ |
g_return_val_if_fail (loc->zone != NULL, NULL); |
237 |
|
|
|
238 |
|
✗ |
tz_env_value = g_strdup (getenv ("TZ")); |
239 |
|
✗ |
setenv ("TZ", loc->zone, 1); |
240 |
|
|
|
241 |
|
|
#if 0 |
242 |
|
|
tzset (); |
243 |
|
|
#endif |
244 |
|
✗ |
tzinfo = g_new0 (TzInfo, 1); |
245 |
|
|
|
246 |
|
✗ |
curtime = time (NULL); |
247 |
|
✗ |
curzone = localtime (&curtime); |
248 |
|
|
|
249 |
|
|
#ifndef __sun |
250 |
|
✗ |
tzinfo->tzname = g_strdup (curzone->tm_zone); |
251 |
|
✗ |
tzinfo->utc_offset = curzone->tm_gmtoff; |
252 |
|
|
#else |
253 |
|
|
tzinfo->tzname = NULL; |
254 |
|
|
tzinfo->utc_offset = 0; |
255 |
|
|
#endif |
256 |
|
|
|
257 |
|
✗ |
tzinfo->daylight = curzone->tm_isdst; |
258 |
|
|
|
259 |
|
✗ |
if (tz_env_value) |
260 |
|
✗ |
setenv ("TZ", tz_env_value, 1); |
261 |
|
|
else |
262 |
|
✗ |
unsetenv ("TZ"); |
263 |
|
|
|
264 |
|
✗ |
return tzinfo; |
265 |
|
|
} |
266 |
|
|
|
267 |
|
|
|
268 |
|
|
void |
269 |
|
✗ |
tz_info_free (TzInfo *tzinfo) |
270 |
|
|
{ |
271 |
|
✗ |
g_return_if_fail (tzinfo != NULL); |
272 |
|
|
|
273 |
|
✗ |
if (tzinfo->tzname) g_free (tzinfo->tzname); |
274 |
|
✗ |
g_free (tzinfo); |
275 |
|
|
} |
276 |
|
|
|
277 |
|
|
struct { |
278 |
|
|
const char *orig; |
279 |
|
|
const char *dest; |
280 |
|
|
} aliases[] = { |
281 |
|
|
{ "Asia/Istanbul", "Europe/Istanbul" }, /* Istanbul is in both Europe and Asia */ |
282 |
|
|
{ "Europe/Nicosia", "Asia/Nicosia" }, /* Ditto */ |
283 |
|
|
{ "EET", "Europe/Istanbul" }, /* Same tz as the 2 above */ |
284 |
|
|
{ "HST", "Pacific/Honolulu" }, |
285 |
|
|
{ "WET", "Europe/Brussels" }, /* Other name for the mainland Europe tz */ |
286 |
|
|
{ "CET", "Europe/Brussels" }, /* ditto */ |
287 |
|
|
{ "MET", "Europe/Brussels" }, |
288 |
|
|
{ "Etc/Zulu", "Etc/GMT" }, |
289 |
|
|
{ "Etc/UTC", "Etc/GMT" }, |
290 |
|
|
{ "GMT", "Etc/GMT" }, |
291 |
|
|
{ "Greenwich", "Etc/GMT" }, |
292 |
|
|
{ "Etc/UCT", "Etc/GMT" }, |
293 |
|
|
{ "Etc/GMT0", "Etc/GMT" }, |
294 |
|
|
{ "Etc/GMT+0", "Etc/GMT" }, |
295 |
|
|
{ "Etc/GMT-0", "Etc/GMT" }, |
296 |
|
|
{ "Etc/Universal", "Etc/GMT" }, |
297 |
|
|
{ "PST8PDT", "America/Los_Angeles" }, /* Other name for the Atlantic tz */ |
298 |
|
|
{ "EST", "America/New_York" }, /* Other name for the Eastern tz */ |
299 |
|
|
{ "EST5EDT", "America/New_York" }, /* ditto */ |
300 |
|
|
{ "CST6CDT", "America/Chicago" }, /* Other name for the Central tz */ |
301 |
|
|
{ "MST", "America/Denver" }, /* Other name for the mountain tz */ |
302 |
|
|
{ "MST7MDT", "America/Denver" }, /* ditto */ |
303 |
|
|
}; |
304 |
|
|
|
305 |
|
|
static gboolean |
306 |
|
✗ |
compare_timezones (const char *a, |
307 |
|
|
const char *b) |
308 |
|
|
{ |
309 |
|
✗ |
if (g_str_equal (a, b)) |
310 |
|
✗ |
return TRUE; |
311 |
|
✗ |
if (strchr (b, '/') == NULL) { |
312 |
|
✗ |
g_autofree gchar *prefixed = NULL; |
313 |
|
|
|
314 |
|
✗ |
prefixed = g_strdup_printf ("/%s", b); |
315 |
|
✗ |
if (g_str_has_suffix (a, prefixed)) |
316 |
|
✗ |
return TRUE; |
317 |
|
|
} |
318 |
|
|
|
319 |
|
✗ |
return FALSE; |
320 |
|
|
} |
321 |
|
|
|
322 |
|
|
char * |
323 |
|
✗ |
tz_info_get_clean_name (TzDB *tz_db, |
324 |
|
|
const char *tz) |
325 |
|
|
{ |
326 |
|
|
char *ret; |
327 |
|
|
const char *timezone; |
328 |
|
|
guint i; |
329 |
|
|
gboolean replaced; |
330 |
|
|
|
331 |
|
|
/* Remove useless prefixes */ |
332 |
|
✗ |
if (g_str_has_prefix (tz, "right/")) |
333 |
|
✗ |
tz = tz + strlen ("right/"); |
334 |
|
✗ |
else if (g_str_has_prefix (tz, "posix/")) |
335 |
|
✗ |
tz = tz + strlen ("posix/"); |
336 |
|
|
|
337 |
|
|
/* Here start the crazies */ |
338 |
|
✗ |
replaced = FALSE; |
339 |
|
|
|
340 |
|
✗ |
for (i = 0; i < G_N_ELEMENTS (aliases); i++) { |
341 |
|
✗ |
if (compare_timezones (tz, aliases[i].orig)) { |
342 |
|
✗ |
replaced = TRUE; |
343 |
|
✗ |
timezone = aliases[i].dest; |
344 |
|
✗ |
break; |
345 |
|
|
} |
346 |
|
|
} |
347 |
|
|
|
348 |
|
|
/* Try again! */ |
349 |
|
✗ |
if (!replaced) { |
350 |
|
|
/* Ignore crazy solar times from the '80s */ |
351 |
|
✗ |
if (g_str_has_prefix (tz, "Asia/Riyadh") || |
352 |
|
✗ |
g_str_has_prefix (tz, "Mideast/Riyadh")) { |
353 |
|
✗ |
timezone = "Asia/Riyadh"; |
354 |
|
✗ |
replaced = TRUE; |
355 |
|
|
} |
356 |
|
|
} |
357 |
|
|
|
358 |
|
✗ |
if (!replaced) |
359 |
|
✗ |
timezone = tz; |
360 |
|
|
|
361 |
|
✗ |
ret = g_hash_table_lookup (tz_db->backward, timezone); |
362 |
|
✗ |
if (ret == NULL) |
363 |
|
✗ |
return g_strdup (timezone); |
364 |
|
✗ |
return g_strdup (ret); |
365 |
|
|
} |
366 |
|
|
|
367 |
|
|
/* ----------------- * |
368 |
|
|
* Private functions * |
369 |
|
|
* ----------------- */ |
370 |
|
|
|
371 |
|
|
static gchar * |
372 |
|
✗ |
tz_data_file_get (void) |
373 |
|
|
{ |
374 |
|
|
gchar *file; |
375 |
|
|
|
376 |
|
✗ |
file = g_strdup (TZ_DATA_FILE); |
377 |
|
|
|
378 |
|
✗ |
return file; |
379 |
|
|
} |
380 |
|
|
|
381 |
|
|
static float |
382 |
|
✗ |
convert_pos (gchar *pos, int digits) |
383 |
|
|
{ |
384 |
|
|
gchar whole[10]; |
385 |
|
|
gchar *fraction; |
386 |
|
|
gint i; |
387 |
|
|
float t1, t2; |
388 |
|
|
|
389 |
|
✗ |
if (!pos || strlen(pos) < 4 || digits > 9) return 0.0; |
390 |
|
|
|
391 |
|
✗ |
for (i = 0; i < digits + 1; i++) whole[i] = pos[i]; |
392 |
|
✗ |
whole[i] = '\0'; |
393 |
|
✗ |
fraction = pos + digits + 1; |
394 |
|
|
|
395 |
|
✗ |
t1 = g_strtod (whole, NULL); |
396 |
|
✗ |
t2 = g_strtod (fraction, NULL); |
397 |
|
|
|
398 |
|
✗ |
if (t1 >= 0.0) return t1 + t2/pow (10.0, strlen(fraction)); |
399 |
|
✗ |
else return t1 - t2/pow (10.0, strlen(fraction)); |
400 |
|
|
} |
401 |
|
|
|
402 |
|
|
|
403 |
|
|
#if 0 |
404 |
|
|
|
405 |
|
|
/* Currently not working */ |
406 |
|
|
static void |
407 |
|
|
free_tzdata (TzLocation *tz) |
408 |
|
|
{ |
409 |
|
|
|
410 |
|
|
if (tz->country) |
411 |
|
|
g_free(tz->country); |
412 |
|
|
if (tz->zone) |
413 |
|
|
g_free(tz->zone); |
414 |
|
|
if (tz->comment) |
415 |
|
|
g_free(tz->comment); |
416 |
|
|
|
417 |
|
|
g_free(tz); |
418 |
|
|
} |
419 |
|
|
#endif |
420 |
|
|
|
421 |
|
|
|
422 |
|
|
static int |
423 |
|
✗ |
compare_country_names (const void *a, const void *b) |
424 |
|
|
{ |
425 |
|
✗ |
const TzLocation *tza = * (TzLocation **) a; |
426 |
|
✗ |
const TzLocation *tzb = * (TzLocation **) b; |
427 |
|
|
|
428 |
|
✗ |
return strcmp (tza->zone, tzb->zone); |
429 |
|
|
} |
430 |
|
|
|
431 |
|
|
|
432 |
|
|
static void |
433 |
|
✗ |
sort_locations_by_country (GPtrArray *locations) |
434 |
|
|
{ |
435 |
|
✗ |
qsort (locations->pdata, locations->len, sizeof (gpointer), |
436 |
|
|
compare_country_names); |
437 |
|
✗ |
} |
438 |
|
|
|
439 |
|
|
static void |
440 |
|
✗ |
load_backward_tz (TzDB *tz_db) |
441 |
|
|
{ |
442 |
|
✗ |
g_auto(GStrv) lines = NULL; |
443 |
|
✗ |
g_autoptr(GBytes) bytes = NULL; |
444 |
|
|
const char *contents; |
445 |
|
|
guint i; |
446 |
|
|
|
447 |
|
✗ |
tz_db->backward = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); |
448 |
|
|
|
449 |
|
✗ |
bytes = g_resources_lookup_data ("/org/gnome/control-center/system/datetime/backward", |
450 |
|
|
G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); |
451 |
|
✗ |
contents = (const char *) g_bytes_get_data (bytes, NULL); |
452 |
|
|
|
453 |
|
✗ |
lines = g_strsplit (contents, "\n", -1); |
454 |
|
|
|
455 |
|
✗ |
for (i = 0; lines[i] != NULL; i++) |
456 |
|
|
{ |
457 |
|
✗ |
g_auto(GStrv) items = NULL; |
458 |
|
|
guint j; |
459 |
|
|
char *real, *alias; |
460 |
|
|
|
461 |
|
✗ |
if (g_ascii_strncasecmp (lines[i], "Link\t", 5) != 0) |
462 |
|
✗ |
continue; |
463 |
|
|
|
464 |
|
✗ |
items = g_strsplit (lines[i], "\t", -1); |
465 |
|
✗ |
real = NULL; |
466 |
|
✗ |
alias = NULL; |
467 |
|
|
/* Skip the "Link<tab>" part */ |
468 |
|
✗ |
for (j = 1; items[j] != NULL; j++) |
469 |
|
|
{ |
470 |
|
✗ |
if (items[j][0] == '\0') |
471 |
|
✗ |
continue; |
472 |
|
✗ |
if (real == NULL) |
473 |
|
|
{ |
474 |
|
✗ |
real = items[j]; |
475 |
|
✗ |
continue; |
476 |
|
|
} |
477 |
|
✗ |
alias = items[j]; |
478 |
|
✗ |
break; |
479 |
|
|
} |
480 |
|
|
|
481 |
|
✗ |
if (real == NULL || alias == NULL) |
482 |
|
✗ |
g_warning ("Could not parse line: %s", lines[i]); |
483 |
|
|
|
484 |
|
|
/* We don't need more than one name for it */ |
485 |
|
✗ |
if (g_str_equal (real, "Etc/UTC") || |
486 |
|
✗ |
g_str_equal (real, "Etc/UCT")) |
487 |
|
✗ |
real = "Etc/GMT"; |
488 |
|
|
|
489 |
|
✗ |
g_hash_table_insert (tz_db->backward, g_strdup (alias), g_strdup (real)); |
490 |
|
|
} |
491 |
|
✗ |
} |
492 |
|
|
|
493 |
|
|
|