Check for timegm.

2006-03-23  Emmanuele Bassi  <ebassi@cvs.gnome.org>

	* configure.in: Check for timegm.

	* glib/gtimer.h:
	* glib/gtimer.c:
	* glib/glib.symbols:
	* docs/reference/glib/glib-sections.txt: Added g_time_val_to_iso8601
	and g_time_val_from_iso8601, to convert a GTimeVal to and from an
	ISO 8601 encoded date.

	* tests/testglib.c: Added test cases for g_time_val_to_iso8601()
	and g_time_val_from_iso8601() functions.
This commit is contained in:
Emmanuele Bassi
2006-03-23 02:54:29 +00:00
committed by Emmanuele Bassi
parent 0028b643bc
commit 6db9ec4070
9 changed files with 251 additions and 12 deletions

View File

@@ -31,6 +31,8 @@
#include "config.h"
#include "glibconfig.h"
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
@@ -308,5 +310,158 @@ g_time_val_add (GTimeVal *time_, glong microseconds)
}
}
/* converts a broken down date representation, relative to UTC, to
* a timestamp; it uses timegm() if it's available.
*/
static time_t
mktime_utc (struct tm *tm)
{
time_t retval;
#ifndef HAVE_TIMEGM
static const gint days_before[] =
{
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
};
#endif
#ifndef HAVE_TIMEGM
if (tm->tm_mon < 0 || tm->tm_mon > 11)
return (time_t) -1;
retval = (tm->tm_year - 70) * 365;
retval += (tm->tm_year - 68) / 4;
retval += days_before[tm->tm_mon] + tm->tm_mday - 1;
if (tm->tm_year % 4 == 2 && tm->tm_mon < 2)
retval -= 1;
retval = ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 + tm->tm_sec;
#else
retval = timegm (tm);
#endif /* !HAVE_TIMEGM */
return retval;
}
/**
* g_time_val_from_iso8601:
* @iso_date: a ISO 8601 encoded date string
* @time_: a #GTimeVal
*
* Converts a string containing an ISO 8601 encoded date and time
* to a #GTimeVal and puts it into @time_.
*
* Return value: %TRUE if the conversion was successful.
*
* Since: 2.10
*/
gboolean
g_time_val_from_iso8601 (const gchar *iso_date,
GTimeVal *time_)
{
struct tm tm;
long val;
g_return_val_if_fail (iso_date != NULL, FALSE);
g_return_val_if_fail (time_ != NULL, FALSE);
val = strtoul (iso_date, (char **)&iso_date, 10);
if (*iso_date == '-')
{
/* YYYY-MM-DD */
tm.tm_year = val - 1900;
iso_date++;
tm.tm_mon = strtoul (iso_date, (char **)&iso_date, 10) - 1;
if (*iso_date++ != '-')
return FALSE;
tm.tm_mday = strtoul (iso_date, (char **)&iso_date, 10);
}
else
{
/* YYYYMMDD */
tm.tm_mday = val % 100;
tm.tm_mon = (val % 10000) / 100 - 1;
tm.tm_year = val / 10000 - 1900;
}
if (*iso_date++ != 'T')
return FALSE;
val = strtoul (iso_date, (char **)&iso_date, 10);
if (*iso_date == ':')
{
/* hh:mm:ss */
tm.tm_hour = val;
iso_date++;
tm.tm_min = strtoul (iso_date, (char **)&iso_date, 10);
if (*iso_date++ != ':')
return FALSE;
tm.tm_sec = strtoul (iso_date, (char **)&iso_date, 10);
}
else
{
/* hhmmss */
tm.tm_sec = val % 100;
tm.tm_min = (val % 10000) / 100;
tm.tm_hour = val / 10000;
}
time_->tv_sec = mktime_utc (&tm);
time_->tv_usec = 1;
if (*iso_date == '.')
time_->tv_usec = strtoul (iso_date + 1, (char **)&iso_date, 10);
if (*iso_date == '+' || *iso_date == '-')
{
gint sign = (*iso_date == '+') ? -1 : 1;
val = 60 * strtoul (iso_date + 1, (char **)&iso_date, 10);
if (*iso_date == ':')
val = 60 * val + strtoul (iso_date + 1, NULL, 10);
else
val = 60 * (val / 100) + (val % 100);
time_->tv_sec += (time_t) (val * sign);
}
return TRUE;
}
/**
* g_time_val_to_iso8601:
* @time_: a #GTimeVal
*
* Converts @time_ into a ISO 8601 encoded string, relative to the
* Coordinated Universal Time (UTC).
*
* Return value: a newly allocated string containing a ISO 8601 date
*
* Since: 2.10
*/
gchar *
g_time_val_to_iso8601 (GTimeVal *time_)
{
gchar *retval;
g_return_val_if_fail (time_->tv_usec >= 0 && time_->tv_usec < G_USEC_PER_SEC, NULL);
#define ISO_8601_LEN 21
#define ISO_8601_FORMAT "%Y-%m-%dT%H:%M:%SZ"
retval = g_new0 (gchar, ISO_8601_LEN + 1);
strftime (retval, ISO_8601_LEN,
ISO_8601_FORMAT,
gmtime (&(time_->tv_sec)));
return retval;
}
#define __G_TIMER_C__
#include "galiasdef.c"