virTimeFieldsNowRaw;
virTimeFieldsThen;
virTimeFieldsThenRaw;
+virTimeLocalOffsetFromUTC;
virTimeMillisNow;
virTimeMillisNowRaw;
virTimeStringNow;
/*
* virtime.c: Time handling functions
*
- * Copyright (C) 2006-2012 Red Hat, Inc.
+ * Copyright (C) 2006-2014 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
return ret;
}
+
+/**
+ * virTimeLocalOffsetFromUTC:
+ *
+ * This function is threadsafe, but is *not* async signal safe (due to
+ * localtime_r()).
+ *
+ * @offset: pointer to time_t that will be set to the difference
+ * between localtime and UTC in seconds (east of UTC is a
+ * positive number, and west of UTC is a negative number.
+ *
+ * Returns 0 on success, -1 on error with error reported
+ */
+int
+virTimeLocalOffsetFromUTC(long *offset)
+{
+ struct tm gmtimeinfo;
+ time_t current, utc;
+
+ /* time() gives seconds since Epoch in current timezone */
+ if ((current = time(NULL)) == (time_t)-1) {
+ virReportSystemError(errno, "%s",
+ _("failed to get current system time"));
+ return -1;
+ }
+
+ /* treat current as if it were in UTC */
+ if (!gmtime_r(¤t, &gmtimeinfo)) {
+ virReportSystemError(errno, "%s",
+ _("gmtime_r failed"));
+ return -1;
+ }
+
+ /* mktime() also obeys current timezone rules */
+ if ((utc = mktime(&gmtimeinfo)) == (time_t)-1) {
+ virReportSystemError(errno, "%s",
+ _("mktime failed"));
+ return -1;
+ }
+
+ *offset = current - utc;
+ return 0;
+}
/*
* virtime.h: Time handling functions
*
- * Copyright (C) 2006-2011 Red Hat, Inc.
+ * Copyright (C) 2006-2011, 2014 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
int virTimeStringThenRaw(unsigned long long when, char *buf)
ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
-
/* These APIs are *not* async signal safe and return -1,
* raising a libvirt error on failure
*/
char *virTimeStringNow(void);
char *virTimeStringThen(unsigned long long when);
+int virTimeLocalOffsetFromUTC(long *offset)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
#endif
}
+typedef struct {
+ const char *zone;
+ long offset;
+} testTimeLocalOffsetData;
+
+static int
+testTimeLocalOffset(const void *args)
+{
+ const testTimeLocalOffsetData *data = args;
+ long actual;
+
+ if (setenv("TZ", data->zone, 1) < 0) {
+ perror("setenv");
+ return -1;
+ }
+ tzset();
+
+ if (virTimeLocalOffsetFromUTC(&actual) < 0) {
+ return -1;
+ }
+
+ if (data->offset != actual) {
+ VIR_DEBUG("Expect Offset %ld got %ld\n",
+ data->offset, actual);
+ return -1;
+ }
+ return 0;
+}
+
static int
mymain(void)
{
TEST_FIELDS(2147483648000ull, 2038, 1, 19, 3, 14, 8);
+#define TEST_LOCALOFFSET(tz, off) \
+ do { \
+ testTimeLocalOffsetData data = { \
+ .zone = tz, \
+ .offset = off, \
+ }; \
+ if (virtTestRun("Test localtime offset for " #tz, \
+ testTimeLocalOffset, &data) < 0) \
+ ret = -1; \
+ } while (0)
+
+ TEST_LOCALOFFSET("VIR00:30", -30 * 60);
+ TEST_LOCALOFFSET("VIR01:30", -90 * 60);
+ TEST_LOCALOFFSET("UTC", 0);
+ TEST_LOCALOFFSET("VIR-00:30", 30 * 60);
+ TEST_LOCALOFFSET("VIR-01:30", 90 * 60);
+#if __TEST_DST
+ /* test DST processing with timezones that always
+ * have DST in effect; what's more, cover a zone with
+ * with an unusual DST different than a usual one hour
+ */
+ /* NB: These tests fail at certain times of the day, so
+ * must be disabled until we figure out why
+ */
+ TEST_LOCALOFFSET("VIR-00:30VID,0,365", 90 * 60);
+ TEST_LOCALOFFSET("VIR-02:30VID,0,365", 210 * 60);
+ TEST_LOCALOFFSET("VIR-02:30VID-04:30,0,365", 270 * 60);
+#endif
+
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}