* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Ryan Lortie <desrt@desrt.ca>
*/
/**
* GTimeZone:
*
- * #GDateTime is an opaque structure whose members cannot be accessed
+ * #GTimeZone is an opaque structure whose members cannot be accessed
* directly.
*
* Since: 2.26
{
gint32 gmt_offset;
gboolean is_dst;
- gboolean is_standard;
- gboolean is_gmt;
gchar *abbrev;
} TransitionInfo;
}
if (tz->t_info != NULL)
- g_array_free (tz->t_info, TRUE);
+ {
+ gint idx;
+ for (idx = 0; idx < tz->t_info->len; idx++)
+ {
+ TransitionInfo *info = &g_array_index (tz->t_info, TransitionInfo, idx);
+ g_free (info->abbrev);
+ }
+ g_array_free (tz->t_info, TRUE);
+ }
if (tz->transitions != NULL)
g_array_free (tz->transitions, TRUE);
g_free (tz->name);
info.gmt_offset = offset;
info.is_dst = FALSE;
- info.is_standard = TRUE;
- info.is_gmt = TRUE;
info.abbrev = g_strdup (name);
{
gsize 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);
+ guint32 time_count, type_count;
+ guint8 *tz_transitions, *tz_type_index, *tz_ttinfo;
+ guint8 *tz_abbrs;
+ gsize timesize = sizeof (gint32);
const struct tzhead *header = g_bytes_get_data (zoneinfo, &size);
g_return_if_fail (size >= sizeof (struct tzhead) &&
}
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);
-
- g_assert (type_count == isgmt_count);
- g_assert (type_count == isstd_count);
- tz_transitions = (gpointer)(header + 1);
+ tz_transitions = ((guint8 *) (header) + sizeof (*header));
tz_type_index = tz_transitions + timesize * time_count;
tz_ttinfo = tz_type_index + time_count;
tz_abbrs = tz_ttinfo + sizeof (struct ttinfo) * type_count;
- tz_leaps = tz_abbrs + char_count;
- tz_isstd = tz_leaps + (timesize + countsize) * leap_count;
- tz_isgmt = tz_isstd + isstd_count;
gtz->t_info = g_array_sized_new (FALSE, TRUE, sizeof (TransitionInfo),
type_count);
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]);
+ t_info.abbrev = g_strdup ((gchar *) &tz_abbrs[info.tt_abbrind]);
g_array_append_val (gtz->t_info, t_info);
}
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];
+ trans.info_index = 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);
}
#elif defined (G_OS_WIN32)
if (RegQueryValueExA (key, "Std", NULL, NULL,
(LPBYTE)&(tzi.StandardName), &size) != ERROR_SUCCESS)
goto failed;
+
+ size = sizeof tzi.DaylightName;
+
if (RegQueryValueExA (key, "Dlt", NULL, NULL,
(LPBYTE)&(tzi.DaylightName), &size) != ERROR_SUCCESS)
goto failed;
info->gmt_offset = offset;
info->is_dst = is_dst;
- info->is_standard = FALSE;
- info->is_gmt = FALSE;
if (name)
info->abbrev = g_strdup (name);
return ret;
}
-static boolean
+static gboolean
set_tz_name (gchar **pos, gchar *buffer, guint size)
{
gchar *name_pos = *pos;
* Creates a #GTimeZone corresponding to @identifier.
*
* @identifier can either be an RFC3339/ISO 8601 time offset or
- * something that would pass as a valid value for the
- * <varname>TZ</varname> environment variable (including %NULL).
+ * something that would pass as a valid value for the `TZ` environment
+ * variable (including %NULL).
*
* In Windows, @identifier can also be the unlocalized name of a time
* zone for standard time, for example "Pacific Standard Time".
*
- * Valid RFC3339 time offsets are <literal>"Z"</literal> (for UTC) or
- * <literal>"±hh:mm"</literal>. ISO 8601 additionally specifies
- * <literal>"±hhmm"</literal> and <literal>"±hh"</literal>. Offsets are
+ * Valid RFC3339 time offsets are `"Z"` (for UTC) or
+ * `"±hh:mm"`. ISO 8601 additionally specifies
+ * `"±hhmm"` and `"±hh"`. Offsets are
* time values to be added to Coordinated Universal Time (UTC) to get
* the local time.
*
- * In Unix, the <varname>TZ</varname> environment variable typically
- * corresponds to the name of a file in the zoneinfo database, or
- * string in "std offset [dst [offset],start[/time],end[/time]]"
- * (POSIX) format. There are no spaces in the specification. The
- * name of standard and daylight savings time zone must be three or more
- * alphabetic characters. Offsets are time values to be added to local
- * time to get Coordinated Universal Time (UTC) and should be
- * <literal>"[±]hh[[:]mm[:ss]]"</literal>. Dates are either
- * <literal>"Jn"</literal> (Julian day with n between 1 and 365, leap
- * years not counted), <literal>"n"</literal> (zero-based Julian day
- * with n between 0 and 365) or <literal>"Mm.w.d"</literal> (day d
+ * In UNIX, the `TZ` environment variable typically corresponds
+ * to the name of a file in the zoneinfo database, or string in
+ * "std offset [dst [offset],start[/time],end[/time]]" (POSIX) format.
+ * There are no spaces in the specification. The name of standard
+ * and daylight savings time zone must be three or more alphabetic
+ * characters. Offsets are time values to be added to local time to
+ * get Coordinated Universal Time (UTC) and should be
+ * `"[±]hh[[:]mm[:ss]]"`. Dates are either
+ * `"Jn"` (Julian day with n between 1 and 365, leap
+ * years not counted), `"n"` (zero-based Julian day
+ * with n between 0 and 365) or `"Mm.w.d"` (day d
* (0 <= d <= 6) of week w (1 <= w <= 5) of month m (1 <= m <= 12), day
* 0 is a Sunday). Times are in local wall clock time, the default is
* 02:00:00.
* Coordinated Universal Time (UTC).
*
* g_time_zone_new_local() calls this function with the value of the
- * <varname>TZ</varname> environment variable. This function itself is
- * independent of the value of <varname>TZ</varname>, but if @identifier
- * is %NULL then <filename>/etc/localtime</filename> will be consulted
- * to discover the correct time zone on Unix and the registry will be
- * consulted or GetTimeZoneInformation() will be used to get the local
- * time zone on Windows.
+ * `TZ` environment variable. This function itself is independent of
+ * the value of `TZ`, but if @identifier is %NULL then `/etc/localtime`
+ * will be consulted to discover the correct time zone on UNIX and the
+ * registry will be consulted or GetTimeZoneInformation() will be used
+ * to get the local time zone on Windows.
*
- * If intervals are not available, only time zone rules from
- * <varname>TZ</varname> environment variable or other means, then they
- * will be computed from year 1900 to 2037. If the maximum year for the
- * rules is available and it is greater than 2037, then it will followed
+ * If intervals are not available, only time zone rules from `TZ`
+ * environment variable or other means, then they will be computed
+ * from year 1900 to 2037. If the maximum year for the rules is
+ * available and it is greater than 2037, then it will followed
* instead.
*
- * See <ulink
- * url='http://tools.ietf.org/html/rfc3339#section-5.6'>RFC3339
- * §5.6</ulink> for a precise definition of valid RFC3339 time offsets
- * (the <varname>time-offset</varname> expansion) and ISO 8601 for the
- * full list of valid time offsets. See <ulink
- * url='http://www.gnu.org/s/libc/manual/html_node/TZ-Variable.html'>The
- * GNU C Library manual</ulink> for an explanation of the possible
- * values of the <varname>TZ</varname> environment variable. See <ulink
- * url='http://msdn.microsoft.com/en-us/library/ms912391%28v=winembedded.11%29.aspx'>
- * Microsoft Time Zone Index Values</ulink> for the list of time zones
- * on Windows.
+ * See
+ * [RFC3339 §5.6](http://tools.ietf.org/html/rfc3339#section-5.6)
+ * for a precise definition of valid RFC3339 time offsets
+ * (the `time-offset` expansion) and ISO 8601 for the
+ * full list of valid time offsets. See
+ * [The GNU C Library manual](http://www.gnu.org/s/libc/manual/html_node/TZ-Variable.html)
+ * for an explanation of the possible
+ * values of the `TZ` environment variable. See
+ * [Microsoft Time Zone Index Values](http://msdn.microsoft.com/en-us/library/ms912391%28v=winembedded.11%29.aspx)
+ * for the list of time zones on Windows.
*
* You should release the return value by calling g_time_zone_unref()
* when you are done with it.
* zone may change between invocations to this function; for example,
* if the system administrator changes it.
*
- * This is equivalent to calling g_time_zone_new() with the value of the
- * <varname>TZ</varname> environment variable (including the possibility
- * of %NULL).
+ * This is equivalent to calling g_time_zone_new() with the value of
+ * the `TZ` environment variable (including the possibility of %NULL).
*
* You should release the return value by calling g_time_zone_unref()
* when you are done with it.
#define TRANSITION_INFO(n) g_array_index (tz->t_info, TransitionInfo, n)
/* Internal helpers {{{1 */
-/* Note that interval 0 is *before* the first transition time, so
- * interval 1 gets transitions[0].
+/* NB: Interval 0 is before the first transition, so there's no
+ * transition structure to point to which TransitionInfo to
+ * use. Rule-based zones are set up so that TI 0 is always standard
+ * time (which is what's in effect before Daylight time got started
+ * in the early 20th century), but IANA tzfiles don't follow that
+ * convention. The tzfile documentation says to use the first
+ * standard-time (i.e., non-DST) tinfo, so that's what we do.
*/
inline static const TransitionInfo*
interval_info (GTimeZone *tz,
if (interval && tz->transitions && interval <= tz->transitions->len)
index = (TRANSITION(interval - 1)).info_index;
else
- index = 0;
+ {
+ for (index = 0; index < tz->t_info->len; index++)
+ {
+ TransitionInfo *tzinfo = &(TRANSITION_INFO(index));
+ if (!tzinfo->is_dst)
+ return tzinfo;
+ }
+ index = 0;
+ }
+
return &(TRANSITION_INFO(index));
}
}
-inline static gboolean
-interval_isgmt (GTimeZone *tz,
- guint interval)
-{
- 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)