]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Add function to convert struct tm to time using timezone
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 21 Dec 2016 14:06:12 +0000 (14:06 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 21 Dec 2016 14:06:12 +0000 (14:06 +0000)
src/libutil/util.c
src/libutil/util.h

index 0bb11e92bdfb8a9a1c98eb026cc140fd73d5eee9..0ddbaf9ef34860e11ebf2633c8ada71194308113 100644 (file)
@@ -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;
+}
index da10e419ae15fea833ae6c07681a3f50cb9b4798..40144f7f70f4e2d84a1fe665f6dfdb0cdaec173c 100644 (file)
@@ -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