mirror of https://github.com/nirenjan/libx52.git
Fix daylight savings offset calculation bug
This commit changes the local timezone calculation to use tm.tm_gmtoff, and falling back to calculating it manually from the output of strftime when tm_gmtoff is not a member of struct tm. This also fixes the tests so that they are no longer expected to fail. Fixes #20.pull/22/head
parent
f5145de36b
commit
af49ce6500
|
@ -61,6 +61,14 @@ AM_COND_IF([HAVE_DOXYGEN],
|
||||||
[AC_CONFIG_FILES([Doxyfile])],
|
[AC_CONFIG_FILES([Doxyfile])],
|
||||||
[AC_MSG_WARN(["Doxygen not found; continuing without doxygen support"])])
|
[AC_MSG_WARN(["Doxygen not found; continuing without doxygen support"])])
|
||||||
|
|
||||||
|
# Check for the presence of tm_gmtoff in struct tm. If we have this, then we
|
||||||
|
# can use it to determine the true GMT offset
|
||||||
|
AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,
|
||||||
|
[AC_MSG_WARN(["Cannot find tm_gmtoff in struct tm, using slower method"])],
|
||||||
|
[#define _GNU_SOURCE
|
||||||
|
#include <time.h>
|
||||||
|
])
|
||||||
|
|
||||||
# Configuration headers
|
# Configuration headers
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,33 @@
|
||||||
#include "x52_commands.h"
|
#include "x52_commands.h"
|
||||||
#include "x52_common.h"
|
#include "x52_common.h"
|
||||||
|
|
||||||
|
#if !HAVE_STRUCT_TM_TM_GMTOFF
|
||||||
|
/* Slow method to compute GMT offset */
|
||||||
|
static int _x52_compute_gmtoff(struct tm *timeval)
|
||||||
|
{
|
||||||
|
char buf[20];
|
||||||
|
size_t written;
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
/* This function uses strftime to get the timezone as a string, then
|
||||||
|
* converts that back into an integer offset.
|
||||||
|
*/
|
||||||
|
written = strftime(buf, sizeof(buf), "%z", timeval);
|
||||||
|
if (written != 5) {
|
||||||
|
/* Expect %z to return 5 characters - e.g. +0530, -0700, +0000 */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 600 * (buf[1] - '0') + 60 * (buf[2] - '0') + 10 * (buf[3] - '0') + (buf[4] - '0');
|
||||||
|
if (buf[0] == '-') {
|
||||||
|
offset = -offset;
|
||||||
|
} else if (buf[0] != '+') {
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int libx52_set_clock(libx52_device *x52, time_t time, int local)
|
int libx52_set_clock(libx52_device *x52, time_t time, int local)
|
||||||
{
|
{
|
||||||
struct tm timeval;
|
struct tm timeval;
|
||||||
|
@ -36,10 +63,14 @@ int libx52_set_clock(libx52_device *x52, time_t time, int local)
|
||||||
|
|
||||||
if (local) {
|
if (local) {
|
||||||
ptr = localtime_r(&time, &timeval);
|
ptr = localtime_r(&time, &timeval);
|
||||||
/* timezone from time.h presents the offset in seconds west of GMT.
|
#if HAVE_STRUCT_TM_TM_GMTOFF
|
||||||
* Negate and divide by 60 to get the offset in minutes east of GMT.
|
/* If valid, then timeval.tm_gmtoff contains the offset in seconds
|
||||||
|
* east of GMT. Divide by 60 to get the offset in minutes east of GMT.
|
||||||
*/
|
*/
|
||||||
local_tz = (int)(-timezone / 60);
|
local_tz = (int)(timeval.tm_gmtoff / 60);
|
||||||
|
#else
|
||||||
|
local_tz = _x52_compute_gmtoff(&timeval);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
ptr = gmtime_r(&time, &timeval);
|
ptr = gmtime_r(&time, &timeval);
|
||||||
/* No offset from GMT */
|
/* No offset from GMT */
|
||||||
|
|
|
@ -33,9 +33,6 @@ timezone_test()
|
||||||
# Pacific Daylight Time
|
# Pacific Daylight Time
|
||||||
# Default offset for clocks 2 & 3 should be +420 minutes
|
# Default offset for clocks 2 & 3 should be +420 minutes
|
||||||
off=420
|
off=420
|
||||||
|
|
||||||
# TODO: Remove the following line once #20 is fixed.
|
|
||||||
TEST_ID="$TEST_ID # TODO Fix issue #20"
|
|
||||||
else
|
else
|
||||||
# Pacific Standard time
|
# Pacific Standard time
|
||||||
# Default offset for clocks 2 & 3 should be +480 minutes
|
# Default offset for clocks 2 & 3 should be +480 minutes
|
||||||
|
|
Loading…
Reference in New Issue