From be6fe2527a6f5e6b9ebe2f124bdcb2749d9f7997 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 21 Dec 2016 14:06:12 +0000 Subject: [PATCH] [Feature] Add function to convert struct tm to time using timezone --- src/libutil/util.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ src/libutil/util.h | 9 +++++ 2 files changed, 104 insertions(+) diff --git a/src/libutil/util.c b/src/libutil/util.c index 0bb11e92b..0ddbaf9ef 100644 --- a/src/libutil/util.c +++ b/src/libutil/util.c @@ -2563,3 +2563,98 @@ rspamd_normalize_probability (gdouble x, gdouble bias) return pow (xx, 8); } + +/* + * Calculations from musl libc + */ +guint64 +rspamd_tm_to_time (const struct tm *tm, glong tz) +{ + guint64 result; + gboolean is_leap = FALSE; + gint leaps, y = tm->tm_year, cycles, rem, centuries; + glong offset = (tz / 100) * 3600 + (tz % 100) * 60; + + /* How many seconds in each month from the beginning of the year */ + static const gint secs_through_month[] = { + 0, 31*86400, 59*86400, 90*86400, + 120*86400, 151*86400, 181*86400, 212*86400, + 243*86400, 273*86400, 304*86400, 334*86400 + }; + + /* Convert year */ + if (tm->tm_year - 2ULL <= 136) { + leaps = (y - 68) / 4; + + if (!((y - 68) & 3)) { + leaps--; + is_leap = 1; + } + + result = 31536000 * (y - 70) + 86400 * leaps; + } + else { + cycles = (y - 100) / 400; + rem = (y - 100) % 400; + if (rem < 0) { + cycles--; + rem += 400; + } + + if (!rem) { + is_leap = 1; + centuries = 0; + leaps = 0; + } + else { + if (rem >= 200) { + if (rem >= 300) { + centuries = 3; + rem -= 300; + } + else { + centuries = 2; + rem -= 200; + } + } + else { + if (rem >= 100) { + centuries = 1; + rem -= 100; + } + else { + centuries = 0; + } + } + + if (!rem) { + is_leap = 1; + leaps = 0; + } else { + leaps = rem / 4U; + rem %= 4U; + is_leap = !rem; + } + } + + leaps += 97 * cycles + 24 * centuries - (gint)is_leap; + result = (y - 100) * 31536000LL + leaps * 86400LL + 946684800 + 86400; + } + + /* Now convert months to seconds */ + result += secs_through_month[tm->tm_mon]; + /* One more day */ + if (is_leap && tm->tm_mon >= 2) { + result += 86400; + } + + result += 86400LL * (tm->tm_mday-1); + result += 3600LL * tm->tm_hour; + result += 60LL * tm->tm_min; + result += tm->tm_sec; + + /* Now apply tz offset */ + result += offset; + + return result; +} diff --git a/src/libutil/util.h b/src/libutil/util.h index da10e419a..40144f7f7 100644 --- a/src/libutil/util.h +++ b/src/libutil/util.h @@ -12,6 +12,7 @@ #include #endif #include +#include struct rspamd_config; struct rspamd_main; @@ -507,5 +508,13 @@ gpointer rspamd_shmem_xmap (const char *fname, guint mode, */ gdouble rspamd_normalize_probability (gdouble x, gdouble bias); +/** + * Converts struct tm to time_t + * @param tm + * @param tz timezone in format (hours * 100) + minutes + * @return + */ +guint64 rspamd_tm_to_time (const struct tm *tm, glong tz); + #define PTR_ARRAY_FOREACH(ar, i, cur) if (ar != NULL) for ((i) = 0, (cur) = g_ptr_array_index((ar), 0); (i) < (ar)->len; (cur) = g_ptr_array_index((ar), (i + 1)), ++(i)) #endif -- 2.39.5