mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-04-16 12:28:48 +02:00
Replace zoneinfo pointers with structs
The approach of sucking a zoneinfo file into a GBytes and working with pointers into it might be fast, but it's obtuse and not compatible with Microsoft Windows.
This commit is contained in:
parent
489e031f22
commit
59f2da1749
353
glib/gtimezone.c
353
glib/gtimezone.c
@ -115,24 +115,28 @@ struct ttinfo
|
|||||||
guint8 tt_abbrind;
|
guint8 tt_abbrind;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gint32 gmt_offset;
|
||||||
|
gboolean is_dst;
|
||||||
|
gboolean is_standard;
|
||||||
|
gboolean is_gmt;
|
||||||
|
gchar *abbrev;
|
||||||
|
} TransitionInfo;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gint64 time;
|
||||||
|
gint info_index;
|
||||||
|
} Transition;
|
||||||
|
|
||||||
|
|
||||||
/* GTimeZone structure and lifecycle {{{1 */
|
/* GTimeZone structure and lifecycle {{{1 */
|
||||||
struct _GTimeZone
|
struct _GTimeZone
|
||||||
{
|
{
|
||||||
gchar *name;
|
gchar *name;
|
||||||
gchar version;
|
GArray *t_info;
|
||||||
GBytes *zoneinfo;
|
GArray *transitions;
|
||||||
|
|
||||||
const struct tzhead *header;
|
|
||||||
const struct ttinfo *infos;
|
|
||||||
union
|
|
||||||
{
|
|
||||||
const gint32_be *one;
|
|
||||||
const gint64_be *two;
|
|
||||||
} trans;
|
|
||||||
const guint8 *indices;
|
|
||||||
const gchar *abbrs;
|
|
||||||
gint timecnt;
|
|
||||||
|
|
||||||
gint ref_count;
|
gint ref_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -174,9 +178,9 @@ again:
|
|||||||
G_UNLOCK(time_zones);
|
G_UNLOCK(time_zones);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tz->zoneinfo)
|
g_array_free (tz->t_info, TRUE);
|
||||||
g_bytes_unref (tz->zoneinfo);
|
if (tz->transitions != NULL)
|
||||||
|
g_array_free (tz->transitions, TRUE);
|
||||||
g_free (tz->name);
|
g_free (tz->name);
|
||||||
|
|
||||||
g_slice_free (GTimeZone, tz);
|
g_slice_free (GTimeZone, tz);
|
||||||
@ -254,6 +258,11 @@ static gboolean
|
|||||||
parse_constant_offset (const gchar *name,
|
parse_constant_offset (const gchar *name,
|
||||||
gint32 *offset)
|
gint32 *offset)
|
||||||
{
|
{
|
||||||
|
if (g_strcmp0 (name, "UTC") == 0)
|
||||||
|
{
|
||||||
|
*offset = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
switch (*name++)
|
switch (*name++)
|
||||||
{
|
{
|
||||||
case 'Z':
|
case 'Z':
|
||||||
@ -275,36 +284,30 @@ parse_constant_offset (const gchar *name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GBytes *
|
static void
|
||||||
zone_for_constant_offset (const gchar *name)
|
zone_for_constant_offset (GTimeZone *gtz, const gchar *name)
|
||||||
{
|
{
|
||||||
const gchar fake_zoneinfo_headers[] =
|
|
||||||
"TZif" "2..." "...." "...." "...."
|
|
||||||
"\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0"
|
|
||||||
"TZif" "2..." "...." "...." "...."
|
|
||||||
"\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\1" "\0\0\0\7";
|
|
||||||
struct {
|
|
||||||
struct tzhead headers[2];
|
|
||||||
struct ttinfo info;
|
|
||||||
gchar abbr[8];
|
|
||||||
} *fake;
|
|
||||||
gint32 offset;
|
gint32 offset;
|
||||||
|
TransitionInfo info;
|
||||||
|
|
||||||
if (name == NULL || !parse_constant_offset (name, &offset))
|
if (name == NULL || !parse_constant_offset (name, &offset))
|
||||||
return NULL;
|
return;
|
||||||
|
|
||||||
offset = GINT32_TO_BE (offset);
|
info.gmt_offset = offset;
|
||||||
|
info.is_dst = FALSE;
|
||||||
|
info.is_standard = TRUE;
|
||||||
|
info.is_gmt = TRUE;
|
||||||
|
info.abbrev = g_strdup (name);
|
||||||
|
|
||||||
fake = g_malloc (sizeof *fake);
|
|
||||||
memcpy (fake, fake_zoneinfo_headers, sizeof fake_zoneinfo_headers);
|
|
||||||
memcpy (&fake->info.tt_gmtoff, &offset, sizeof offset);
|
|
||||||
fake->info.tt_isdst = FALSE;
|
|
||||||
fake->info.tt_abbrind = 0;
|
|
||||||
strcpy (fake->abbr, name);
|
|
||||||
|
|
||||||
return g_bytes_new_take (fake, sizeof *fake);
|
gtz->t_info = g_array_sized_new (FALSE, TRUE, sizeof (TransitionInfo), 1);
|
||||||
|
g_array_append_val (gtz->t_info, info);
|
||||||
|
|
||||||
|
/* Constant offset, no transitions */
|
||||||
|
gtz->transitions = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
static GBytes*
|
static GBytes*
|
||||||
zone_info_unix (const gchar *identifier)
|
zone_info_unix (const gchar *identifier)
|
||||||
{
|
{
|
||||||
@ -349,23 +352,25 @@ zone_info_unix (const gchar *identifier)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_zone_from_iana_info (GTimeZone *tz)
|
init_zone_from_iana_info (GTimeZone *gtz, GBytes *zoneinfo)
|
||||||
{
|
{
|
||||||
gsize size;
|
gsize size;
|
||||||
const struct tzhead *header = g_bytes_get_data (tz->zoneinfo, &size);
|
guint index;
|
||||||
|
guint32 time_count, type_count, leap_count, isgmt_count;
|
||||||
|
guint32 isstd_count, char_count ;
|
||||||
|
gpointer tz_transitions, tz_type_index, tz_ttinfo;
|
||||||
|
gpointer tz_leaps, tz_isgmt, tz_isstd;
|
||||||
|
gchar* tz_abbrs;
|
||||||
|
guint timesize = sizeof (gint32), countsize = sizeof (gint32);
|
||||||
|
const struct tzhead *header = g_bytes_get_data (zoneinfo, &size);
|
||||||
|
|
||||||
if (size < sizeof (struct tzhead) || memcmp (header, "TZif", 4))
|
g_return_if_fail (size >= sizeof (struct tzhead) &&
|
||||||
{
|
memcmp (header, "TZif", 4) == 0);
|
||||||
g_bytes_unref (tz->zoneinfo);
|
|
||||||
tz->zoneinfo = NULL;
|
if (header->tzh_version == '2')
|
||||||
}
|
{
|
||||||
else
|
/* Skip ahead to the newer 64-bit data if it's available. */
|
||||||
{
|
header = (const struct tzhead *)
|
||||||
gint typecnt;
|
|
||||||
tz->version = header->tzh_version;
|
|
||||||
/* we trust the file completely. */
|
|
||||||
if (tz->version == '2')
|
|
||||||
tz->header = (const struct tzhead *)
|
|
||||||
(((const gchar *) (header + 1)) +
|
(((const gchar *) (header + 1)) +
|
||||||
guint32_from_be(header->tzh_ttisgmtcnt) +
|
guint32_from_be(header->tzh_ttisgmtcnt) +
|
||||||
guint32_from_be(header->tzh_ttisstdcnt) +
|
guint32_from_be(header->tzh_ttisstdcnt) +
|
||||||
@ -373,26 +378,59 @@ init_zone_from_iana_info (GTimeZone *tz)
|
|||||||
5 * guint32_from_be(header->tzh_timecnt) +
|
5 * guint32_from_be(header->tzh_timecnt) +
|
||||||
6 * guint32_from_be(header->tzh_typecnt) +
|
6 * guint32_from_be(header->tzh_typecnt) +
|
||||||
guint32_from_be(header->tzh_charcnt));
|
guint32_from_be(header->tzh_charcnt));
|
||||||
else
|
timesize = sizeof (gint64);
|
||||||
tz->header = header;
|
}
|
||||||
|
time_count = guint32_from_be(header->tzh_timecnt);
|
||||||
|
type_count = guint32_from_be(header->tzh_typecnt);
|
||||||
|
leap_count = guint32_from_be(header->tzh_leapcnt);
|
||||||
|
isgmt_count = guint32_from_be(header->tzh_ttisgmtcnt);
|
||||||
|
isstd_count = guint32_from_be(header->tzh_ttisstdcnt);
|
||||||
|
char_count = guint32_from_be(header->tzh_charcnt);
|
||||||
|
|
||||||
typecnt = guint32_from_be (tz->header->tzh_typecnt);
|
g_assert (type_count == isgmt_count);
|
||||||
tz->timecnt = guint32_from_be (tz->header->tzh_timecnt);
|
g_assert (type_count == isstd_count);
|
||||||
if (tz->version == '2')
|
|
||||||
{
|
tz_transitions = (gpointer)(header + 1);
|
||||||
tz->trans.two = (gconstpointer) (tz->header + 1);
|
tz_type_index = tz_transitions + timesize * time_count;
|
||||||
tz->indices = (gconstpointer) (tz->trans.two + tz->timecnt);
|
tz_ttinfo = tz_type_index + time_count;
|
||||||
}
|
tz_abbrs = tz_ttinfo + sizeof (struct ttinfo) * type_count;
|
||||||
else
|
tz_leaps = tz_abbrs + char_count;
|
||||||
{
|
tz_isstd = tz_leaps + (timesize + countsize) * leap_count;
|
||||||
tz->trans.one = (gconstpointer) (tz->header + 1);
|
tz_isgmt = tz_isstd + isstd_count;
|
||||||
tz->indices = (gconstpointer) (tz->trans.one + tz->timecnt);
|
|
||||||
}
|
gtz->t_info = g_array_sized_new (FALSE, TRUE, sizeof (TransitionInfo),
|
||||||
tz->infos = (gconstpointer) (tz->indices + tz->timecnt);
|
type_count);
|
||||||
tz->abbrs = (gconstpointer) (tz->infos + typecnt);
|
gtz->transitions = g_array_sized_new (FALSE, TRUE, sizeof (Transition),
|
||||||
|
time_count);
|
||||||
|
|
||||||
|
for (index = 0; index < type_count; index++)
|
||||||
|
{
|
||||||
|
TransitionInfo t_info;
|
||||||
|
struct ttinfo info = ((struct ttinfo*)tz_ttinfo)[index];
|
||||||
|
t_info.gmt_offset = gint32_from_be (info.tt_gmtoff);
|
||||||
|
t_info.is_dst = info.tt_isdst ? TRUE : FALSE;
|
||||||
|
t_info.is_standard = ((guint8*)tz_isstd)[index] ? TRUE : FALSE;
|
||||||
|
t_info.is_gmt = ((guint8*)tz_isgmt)[index] ? TRUE : FALSE;
|
||||||
|
t_info.abbrev = g_strdup (&tz_abbrs[info.tt_abbrind]);
|
||||||
|
g_array_append_val (gtz->t_info, t_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (index = 0; index < time_count; index++)
|
||||||
|
{
|
||||||
|
Transition trans;
|
||||||
|
if (header->tzh_version == '2')
|
||||||
|
trans.time = gint64_from_be (((gint64_be*)tz_transitions)[index]);
|
||||||
|
else
|
||||||
|
trans.time = gint32_from_be (((gint32_be*)tz_transitions)[index]);
|
||||||
|
trans.info_index = ((guint8*)tz_type_index)[index];
|
||||||
|
g_assert (trans.info_index >= 0);
|
||||||
|
g_assert (trans.info_index < gtz->t_info->len);
|
||||||
|
g_array_append_val (gtz->transitions, trans);
|
||||||
|
}
|
||||||
|
g_bytes_unref (zoneinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Construction {{{1 */
|
/* Construction {{{1 */
|
||||||
/**
|
/**
|
||||||
@ -439,31 +477,46 @@ init_zone_from_iana_info (GTimeZone *tz)
|
|||||||
GTimeZone *
|
GTimeZone *
|
||||||
g_time_zone_new (const gchar *identifier)
|
g_time_zone_new (const gchar *identifier)
|
||||||
{
|
{
|
||||||
GTimeZone *tz;
|
GTimeZone *tz = NULL;
|
||||||
GMappedFile *file;
|
|
||||||
|
|
||||||
G_LOCK (time_zones);
|
G_LOCK (time_zones);
|
||||||
if (time_zones == NULL)
|
if (time_zones == NULL)
|
||||||
time_zones = g_hash_table_new (g_str_hash, g_str_equal);
|
time_zones = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
|
|
||||||
if (identifier)
|
if (identifier)
|
||||||
tz = g_hash_table_lookup (time_zones, identifier);
|
|
||||||
else
|
|
||||||
tz = NULL;
|
|
||||||
|
|
||||||
if (tz == NULL)
|
|
||||||
{
|
{
|
||||||
tz = g_slice_new0 (GTimeZone);
|
tz = g_hash_table_lookup (time_zones, identifier);
|
||||||
tz->name = g_strdup (identifier);
|
if (tz)
|
||||||
tz->ref_count = 0;
|
{
|
||||||
|
g_atomic_int_inc (&tz->ref_count);
|
||||||
|
G_UNLOCK (time_zones);
|
||||||
|
return tz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tz->zoneinfo = zone_for_constant_offset (identifier);
|
tz = g_slice_new0 (GTimeZone);
|
||||||
|
tz->name = g_strdup (identifier);
|
||||||
|
tz->ref_count = 0;
|
||||||
|
|
||||||
if (tz->zoneinfo == NULL)
|
zone_for_constant_offset (tz, identifier);
|
||||||
tz->zoneinfo = zone_info_unix (identifier);
|
|
||||||
|
|
||||||
if (tz->zoneinfo != NULL)
|
if (tz->t_info == NULL)
|
||||||
init_zone_from_iana_info (tz);
|
{
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
|
GBytes *zoneinfo = zone_info_unix (identifier);
|
||||||
|
if (!zoneinfo)
|
||||||
|
zone_for_constant_offset (tz, "UTC");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
init_zone_from_iana_info (tz, zoneinfo);
|
||||||
|
g_bytes_unref (zoneinfo);
|
||||||
|
}
|
||||||
|
#elif defined G_OS_WIN32
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tz->t_info != NULL)
|
||||||
|
{
|
||||||
if (identifier)
|
if (identifier)
|
||||||
g_hash_table_insert (time_zones, tz->name, tz);
|
g_hash_table_insert (time_zones, tz->name, tz);
|
||||||
}
|
}
|
||||||
@ -518,69 +571,89 @@ g_time_zone_new_local (void)
|
|||||||
return g_time_zone_new (getenv ("TZ"));
|
return g_time_zone_new (getenv ("TZ"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internal helpers {{{1 */
|
#define TRANSITION(n) g_array_index (tz->transitions, Transition, n)
|
||||||
inline static const struct ttinfo *
|
#define TRANSITION_INFO(n) g_array_index (tz->t_info, TransitionInfo, n)
|
||||||
interval_info (GTimeZone *tz,
|
|
||||||
gint interval)
|
|
||||||
{
|
|
||||||
if (interval)
|
|
||||||
return tz->infos + tz->indices[interval - 1];
|
|
||||||
|
|
||||||
return tz->infos;
|
/* Internal helpers {{{1 */
|
||||||
|
/* Note that interval 0 is *before* the first transition time, so
|
||||||
|
* interval 1 gets transitions[0].
|
||||||
|
*/
|
||||||
|
inline static const TransitionInfo*
|
||||||
|
interval_info (GTimeZone *tz,
|
||||||
|
guint interval)
|
||||||
|
{
|
||||||
|
guint index;
|
||||||
|
g_return_val_if_fail (tz->t_info != NULL, NULL);
|
||||||
|
if (interval && tz->transitions && interval <= tz->transitions->len)
|
||||||
|
index = (TRANSITION(interval - 1)).info_index;
|
||||||
|
else
|
||||||
|
index = 0;
|
||||||
|
return &(TRANSITION_INFO(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static gint64
|
inline static gint64
|
||||||
interval_start (GTimeZone *tz,
|
interval_start (GTimeZone *tz,
|
||||||
gint interval)
|
guint interval)
|
||||||
{
|
{
|
||||||
if (interval)
|
if (!interval || tz->transitions == NULL || tz->transitions->len == 0)
|
||||||
{
|
return G_MININT64;
|
||||||
if (tz->version == '2')
|
if (interval > tz->transitions->len)
|
||||||
return gint64_from_be (tz->trans.two[interval - 1]);
|
interval = tz->transitions->len;
|
||||||
else
|
return (TRANSITION(interval - 1)).time;
|
||||||
return gint32_from_be (tz->trans.one[interval - 1]);
|
|
||||||
}
|
|
||||||
return G_MININT64;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static gint64
|
inline static gint64
|
||||||
interval_end (GTimeZone *tz,
|
interval_end (GTimeZone *tz,
|
||||||
gint interval)
|
guint interval)
|
||||||
{
|
{
|
||||||
if (interval < tz->timecnt)
|
if (tz->transitions && interval < tz->transitions->len)
|
||||||
{
|
return (TRANSITION(interval)).time - 1;
|
||||||
if (tz->version == '2')
|
|
||||||
return gint64_from_be (tz->trans.two[interval]) - 1;
|
|
||||||
else
|
|
||||||
return gint32_from_be (tz->trans.one[interval]) - 1;
|
|
||||||
}
|
|
||||||
return G_MAXINT64;
|
return G_MAXINT64;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static gint32
|
inline static gint32
|
||||||
interval_offset (GTimeZone *tz,
|
interval_offset (GTimeZone *tz,
|
||||||
gint interval)
|
guint interval)
|
||||||
{
|
{
|
||||||
return gint32_from_be (interval_info (tz, interval)->tt_gmtoff);
|
g_return_val_if_fail (tz->t_info != NULL, 0);
|
||||||
|
return interval_info (tz, interval)->gmt_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static gboolean
|
inline static gboolean
|
||||||
interval_isdst (GTimeZone *tz,
|
interval_isdst (GTimeZone *tz,
|
||||||
gint interval)
|
guint interval)
|
||||||
{
|
{
|
||||||
return interval_info (tz, interval)->tt_isdst;
|
g_return_val_if_fail (tz->t_info != NULL, 0);
|
||||||
|
return interval_info (tz, interval)->is_dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static guint8
|
|
||||||
interval_abbrind (GTimeZone *tz,
|
inline static gboolean
|
||||||
gint interval)
|
interval_isgmt (GTimeZone *tz,
|
||||||
|
guint interval)
|
||||||
{
|
{
|
||||||
return interval_info (tz, interval)->tt_abbrind;
|
g_return_val_if_fail (tz->t_info != NULL, 0);
|
||||||
|
return interval_info (tz, interval)->is_gmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static gboolean
|
||||||
|
interval_isstandard (GTimeZone *tz,
|
||||||
|
guint interval)
|
||||||
|
{
|
||||||
|
return interval_info (tz, interval)->is_standard;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static gchar*
|
||||||
|
interval_abbrev (GTimeZone *tz,
|
||||||
|
guint interval)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (tz->t_info != NULL, 0);
|
||||||
|
return interval_info (tz, interval)->abbrev;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static gint64
|
inline static gint64
|
||||||
interval_local_start (GTimeZone *tz,
|
interval_local_start (GTimeZone *tz,
|
||||||
gint interval)
|
guint interval)
|
||||||
{
|
{
|
||||||
if (interval)
|
if (interval)
|
||||||
return interval_start (tz, interval) + interval_offset (tz, interval);
|
return interval_start (tz, interval) + interval_offset (tz, interval);
|
||||||
@ -590,9 +663,9 @@ interval_local_start (GTimeZone *tz,
|
|||||||
|
|
||||||
inline static gint64
|
inline static gint64
|
||||||
interval_local_end (GTimeZone *tz,
|
interval_local_end (GTimeZone *tz,
|
||||||
gint interval)
|
guint interval)
|
||||||
{
|
{
|
||||||
if (interval < tz->timecnt)
|
if (tz->transitions && interval < tz->transitions->len)
|
||||||
return interval_end (tz, interval) + interval_offset (tz, interval);
|
return interval_end (tz, interval) + interval_offset (tz, interval);
|
||||||
|
|
||||||
return G_MAXINT64;
|
return G_MAXINT64;
|
||||||
@ -600,9 +673,11 @@ interval_local_end (GTimeZone *tz,
|
|||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
interval_valid (GTimeZone *tz,
|
interval_valid (GTimeZone *tz,
|
||||||
gint interval)
|
guint interval)
|
||||||
{
|
{
|
||||||
return interval <= tz->timecnt;
|
if ( tz->transitions == NULL)
|
||||||
|
return interval == 0;
|
||||||
|
return interval <= tz->transitions->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* g_time_zone_find_interval() {{{1 */
|
/* g_time_zone_find_interval() {{{1 */
|
||||||
@ -640,13 +715,16 @@ g_time_zone_adjust_time (GTimeZone *tz,
|
|||||||
gint64 *time_)
|
gint64 *time_)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
|
guint intervals;
|
||||||
|
|
||||||
if (tz->zoneinfo == NULL)
|
if (tz->transitions == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
intervals = tz->transitions->len;
|
||||||
|
|
||||||
/* find the interval containing *time UTC
|
/* find the interval containing *time UTC
|
||||||
* TODO: this could be binary searched (or better) */
|
* TODO: this could be binary searched (or better) */
|
||||||
for (i = 0; i < tz->timecnt; i++)
|
for (i = 0; i <= intervals; i++)
|
||||||
if (*time_ <= interval_end (tz, i))
|
if (*time_ <= interval_end (tz, i))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -686,7 +764,7 @@ g_time_zone_adjust_time (GTimeZone *tz,
|
|||||||
if (i && *time_ <= interval_local_end (tz, i - 1))
|
if (i && *time_ <= interval_local_end (tz, i - 1))
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
else if (i < tz->timecnt &&
|
else if (i < intervals &&
|
||||||
*time_ >= interval_local_start (tz, i + 1))
|
*time_ >= interval_local_start (tz, i + 1))
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -730,11 +808,12 @@ g_time_zone_find_interval (GTimeZone *tz,
|
|||||||
gint64 time_)
|
gint64 time_)
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
|
guint intervals;
|
||||||
|
|
||||||
if (tz->zoneinfo == NULL)
|
if (tz->transitions == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
intervals = tz->transitions->len;
|
||||||
for (i = 0; i < tz->timecnt; i++)
|
for (i = 0; i <= intervals; i++)
|
||||||
if (time_ <= interval_end (tz, i))
|
if (time_ <= interval_end (tz, i))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -758,7 +837,7 @@ g_time_zone_find_interval (GTimeZone *tz,
|
|||||||
if (i && time_ <= interval_local_end (tz, i - 1))
|
if (i && time_ <= interval_local_end (tz, i - 1))
|
||||||
i--;
|
i--;
|
||||||
|
|
||||||
else if (i < tz->timecnt && time_ >= interval_local_start (tz, i + 1))
|
else if (i < intervals && time_ >= interval_local_start (tz, i + 1))
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -787,12 +866,9 @@ const gchar *
|
|||||||
g_time_zone_get_abbreviation (GTimeZone *tz,
|
g_time_zone_get_abbreviation (GTimeZone *tz,
|
||||||
gint interval)
|
gint interval)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (interval_valid (tz, interval), NULL);
|
g_return_val_if_fail (interval_valid (tz, (guint)interval), NULL);
|
||||||
|
|
||||||
if (tz->header == NULL)
|
return interval_abbrev (tz, (guint)interval);
|
||||||
return "UTC";
|
|
||||||
|
|
||||||
return tz->abbrs + interval_abbrind (tz, interval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -816,12 +892,9 @@ gint32
|
|||||||
g_time_zone_get_offset (GTimeZone *tz,
|
g_time_zone_get_offset (GTimeZone *tz,
|
||||||
gint interval)
|
gint interval)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (interval_valid (tz, interval), 0);
|
g_return_val_if_fail (interval_valid (tz, (guint)interval), 0);
|
||||||
|
|
||||||
if (tz->header == NULL)
|
return interval_offset (tz, (guint)interval);
|
||||||
return 0;
|
|
||||||
|
|
||||||
return interval_offset (tz, interval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -842,10 +915,10 @@ g_time_zone_is_dst (GTimeZone *tz,
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (interval_valid (tz, interval), FALSE);
|
g_return_val_if_fail (interval_valid (tz, interval), FALSE);
|
||||||
|
|
||||||
if (tz->header == NULL)
|
if (tz->transitions == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return interval_isdst (tz, interval);
|
return interval_isdst (tz, (guint)interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Epilogue {{{1 */
|
/* Epilogue {{{1 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user