#endif /* G_OS_WIN32 */
#include "glib.h"
+#include "gthread.h"
#include "galias.h"
+#define G_NSEC_PER_SEC 1000000000
+
+#define GETTIME(v) (v = g_thread_gettime ())
struct _GTimer
{
-#ifdef G_OS_WIN32
guint64 start;
guint64 end;
-#else /* !G_OS_WIN32 */
- struct timeval start;
- struct timeval end;
-#endif /* !G_OS_WIN32 */
guint active : 1;
};
-#ifdef G_OS_WIN32
-# define GETTIME(v) \
- GetSystemTimeAsFileTime ((FILETIME *)&v)
-#else /* !G_OS_WIN32 */
-# define GETTIME(v) \
- gettimeofday (&v, NULL)
-#endif /* !G_OS_WIN32 */
GTimer*
g_timer_new (void)
timer->active = FALSE;
- GETTIME(timer->end);
+ GETTIME (timer->end);
}
void
void
g_timer_continue (GTimer *timer)
{
-#ifdef G_OS_WIN32
guint64 elapsed;
-#else
- struct timeval elapsed;
-#endif /* G_OS_WIN32 */
g_return_if_fail (timer != NULL);
g_return_if_fail (timer->active == FALSE);
* elapsed interval.
*/
-#ifdef G_OS_WIN32
-
elapsed = timer->end - timer->start;
GETTIME (timer->start);
timer->start -= elapsed;
-#else /* !G_OS_WIN32 */
-
- if (timer->start.tv_usec > timer->end.tv_usec)
- {
- timer->end.tv_usec += G_USEC_PER_SEC;
- timer->end.tv_sec--;
- }
-
- elapsed.tv_usec = timer->end.tv_usec - timer->start.tv_usec;
- elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec;
-
- GETTIME (timer->start);
-
- if (timer->start.tv_usec < elapsed.tv_usec)
- {
- timer->start.tv_usec += G_USEC_PER_SEC;
- timer->start.tv_sec--;
- }
-
- timer->start.tv_usec -= elapsed.tv_usec;
- timer->start.tv_sec -= elapsed.tv_sec;
-
-#endif /* !G_OS_WIN32 */
-
timer->active = TRUE;
}
gulong *microseconds)
{
gdouble total;
-#ifdef G_OS_WIN32
gint64 elapsed;
-#else
- struct timeval elapsed;
-#endif /* G_OS_WIN32 */
g_return_val_if_fail (timer != NULL, 0);
-#ifdef G_OS_WIN32
if (timer->active)
GETTIME (timer->end);
elapsed = timer->end - timer->start;
- total = elapsed / 1e7;
+ total = elapsed / 1e9;
if (microseconds)
- *microseconds = (elapsed / 10) % 1000000;
-#else /* !G_OS_WIN32 */
- if (timer->active)
- gettimeofday (&timer->end, NULL);
-
- if (timer->start.tv_usec > timer->end.tv_usec)
- {
- timer->end.tv_usec += G_USEC_PER_SEC;
- timer->end.tv_sec--;
- }
-
- elapsed.tv_usec = timer->end.tv_usec - timer->start.tv_usec;
- elapsed.tv_sec = timer->end.tv_sec - timer->start.tv_sec;
-
- total = elapsed.tv_sec + ((gdouble) elapsed.tv_usec / 1e6);
- if (total < 0)
- {
- total = 0;
-
- if (microseconds)
- *microseconds = 0;
- }
- else if (microseconds)
- *microseconds = elapsed.tv_usec;
-
-#endif /* !G_OS_WIN32 */
+ *microseconds = (elapsed / 1000) % 1000000;
return total;
}
while (nanosleep (&request, &remaining) == -1 && errno == EINTR)
request = remaining;
# else /* !HAVE_NANOSLEEP */
+# ifdef HAVE_NSLEEP
+ /* on AIX, nsleep is analogous to nanosleep */
+ struct timespec request, remaining;
+ request.tv_sec = microseconds / G_USEC_PER_SEC;
+ request.tv_nsec = 1000 * (microseconds % G_USEC_PER_SEC);
+ while (nsleep (&request, &remaining) == -1 && errno == EINTR)
+ request = remaining;
+# else /* !HAVE_NSLEEP */
if (g_thread_supported ())
{
static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
tv.tv_usec = microseconds % G_USEC_PER_SEC;
select(0, NULL, NULL, NULL, &tv);
}
+# endif /* !HAVE_NSLEEP */
# endif /* !HAVE_NANOSLEEP */
#endif /* !G_OS_WIN32 */
}
/**
* g_time_val_from_iso8601:
- * @iso_date: a ISO 8601 encoded date string
+ * @iso_date: an ISO 8601 encoded date string
* @time_: a #GTimeVal
*
* Converts a string containing an ISO 8601 encoded date and time
g_time_val_from_iso8601 (const gchar *iso_date,
GTimeVal *time_)
{
- struct tm tm;
+ struct tm tm = {0};
long val;
g_return_val_if_fail (iso_date != NULL, FALSE);
g_return_val_if_fail (time_ != NULL, FALSE);
+ /* Ensure that the first character is a digit,
+ * the first digit of the date, otherwise we don't
+ * have an ISO 8601 date */
+ while (g_ascii_isspace (*iso_date))
+ iso_date++;
+
+ if (*iso_date == '\0')
+ return FALSE;
+
+ if (!g_ascii_isdigit (*iso_date) && *iso_date != '-' && *iso_date != '+')
+ return FALSE;
+
val = strtoul (iso_date, (char **)&iso_date, 10);
if (*iso_date == '-')
{
tm.tm_mon = strtoul (iso_date, (char **)&iso_date, 10) - 1;
if (*iso_date++ != '-')
- return FALSE;
+ return FALSE;
tm.tm_mday = strtoul (iso_date, (char **)&iso_date, 10);
}
tm.tm_hour = val / 10000;
}
- time_->tv_sec = mktime_utc (&tm);
- time_->tv_usec = 1;
+ time_->tv_usec = 0;
- if (*iso_date == '.')
- time_->tv_usec = strtoul (iso_date + 1, (char **)&iso_date, 10);
+ if (*iso_date == ',' || *iso_date == '.')
+ {
+ glong mul = 100000;
+
+ while (g_ascii_isdigit (*++iso_date))
+ {
+ time_->tv_usec += (*iso_date - '0') * mul;
+ mul /= 10;
+ }
+ }
- if (*iso_date == '+' || *iso_date == '-')
+ /* Now parse the offset and convert tm to a time_t */
+ if (*iso_date == 'Z')
+ {
+ iso_date++;
+ time_->tv_sec = mktime_utc (&tm);
+ }
+ else if (*iso_date == '+' || *iso_date == '-')
{
gint sign = (*iso_date == '+') ? -1 : 1;
- val = 60 * strtoul (iso_date + 1, (char **)&iso_date, 10);
+ val = strtoul (iso_date + 1, (char **)&iso_date, 10);
if (*iso_date == ':')
- val = 60 * val + strtoul (iso_date + 1, NULL, 10);
+ val = 60 * val + strtoul (iso_date + 1, (char **)&iso_date, 10);
else
val = 60 * (val / 100) + (val % 100);
- time_->tv_sec += (time_t) (val * sign);
+ time_->tv_sec = mktime_utc (&tm) + (time_t) (60 * val * sign);
}
+ else
+ {
+ /* No "Z" or offset, so local time */
+ tm.tm_isdst = -1; /* locale selects DST */
+ time_->tv_sec = mktime (&tm);
+ }
+
+ while (g_ascii_isspace (*iso_date))
+ iso_date++;
- return TRUE;
+ return *iso_date == '\0';
}
/**
* g_time_val_to_iso8601:
* @time_: a #GTimeVal
*
- * Converts @time_ into a ISO 8601 encoded string, relative to the
+ * Converts @time_ into an ISO 8601 encoded string, relative to the
* Coordinated Universal Time (UTC).
*
- * Return value: a newly allocated string containing a ISO 8601 date
+ * Return value: a newly allocated string containing an ISO 8601 date
*
* Since: 2.12
*/
g_time_val_to_iso8601 (GTimeVal *time_)
{
gchar *retval;
-
+ struct tm *tm;
+#ifdef HAVE_GMTIME_R
+ struct tm tm_;
+#endif
+ time_t secs;
+
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)));
+ secs = time_->tv_sec;
+#ifdef _WIN32
+ tm = gmtime (&secs);
+#else
+#ifdef HAVE_GMTIME_R
+ tm = gmtime_r (&secs, &tm_);
+#else
+ tm = gmtime (&secs);
+#endif
+#endif
+
+ if (time_->tv_usec != 0)
+ {
+ /* ISO 8601 date and time format, with fractionary seconds:
+ * YYYY-MM-DDTHH:MM:SS.MMMMMMZ
+ */
+ retval = g_strdup_printf ("%4d-%02d-%02dT%02d:%02d:%02d.%06ldZ",
+ tm->tm_year + 1900,
+ tm->tm_mon + 1,
+ tm->tm_mday,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec,
+ time_->tv_usec);
+ }
+ else
+ {
+ /* ISO 8601 date and time format:
+ * YYYY-MM-DDTHH:MM:SSZ
+ */
+ retval = g_strdup_printf ("%4d-%02d-%02dT%02d:%02d:%02dZ",
+ tm->tm_year + 1900,
+ tm->tm_mon + 1,
+ tm->tm_mday,
+ tm->tm_hour,
+ tm->tm_min,
+ tm->tm_sec);
+ }
return retval;
}