aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2016-12-21 14:06:12 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2016-12-21 14:06:12 +0000
commitbe6fe2527a6f5e6b9ebe2f124bdcb2749d9f7997 (patch)
treeb171cc375191501085a4660fc3eebf889a673ce4
parentc9cdf449078ce760c0528600370b35e3f26c2f08 (diff)
downloadrspamd-be6fe2527a6f5e6b9ebe2f124bdcb2749d9f7997.tar.gz
rspamd-be6fe2527a6f5e6b9ebe2f124bdcb2749d9f7997.zip
[Feature] Add function to convert struct tm to time using timezone
-rw-r--r--src/libutil/util.c95
-rw-r--r--src/libutil/util.h9
2 files changed, 104 insertions, 0 deletions
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 <netdb.h>
#endif
#include <event.h>
+#include <time.h>
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