aboutsummaryrefslogtreecommitdiffstats
path: root/src/entry.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/entry.c')
-rw-r--r--src/entry.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/entry.c b/src/entry.c
new file mode 100644
index 0000000..64acdea
--- /dev/null
+++ b/src/entry.c
@@ -0,0 +1,178 @@
+#include "entry.h"
+
+#include <assert.h>
+
+static int sub_inc_year(struct tm *t, int n)
+{
+ if (n == 0)
+ return 0;
+
+ t->tm_year += n;
+
+ if (mktime(t) == -1)
+ return -1;
+
+ return 0;
+}
+
+static int sub_inc_month(struct tm *t, int n)
+{
+ unsigned i;
+
+ if (n == 0)
+ return 0;
+
+ for (i = 0; i < n; i++) {
+ t->tm_mon++;
+ if (mktime(t) == -1) {
+ t->tm_mon = 0;
+ if (sub_inc_year(t, 1) == -1)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int sub_inc_day(struct tm *t, int n)
+{
+ unsigned i;
+
+ if (n == 0)
+ return 0;
+
+ for (i = 0; i < n; i++) {
+ t->tm_mday++;
+ if (mktime(t) == -1) {
+ t->tm_mday = 1;
+ if (sub_inc_month(t, 1) == -1)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int sub_inc_hour(struct tm *t, int n)
+{
+ unsigned i;
+
+ if (n == 0)
+ return 0;
+
+ for (i = 0; i < n; i++) {
+ t->tm_hour++;
+ if (mktime(t) == -1) {
+ t->tm_hour = 0;
+ if (sub_inc_day(t, 1) == -1)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int sub_inc_minute(struct tm *t, int n)
+{
+ unsigned i;
+
+ if (n == 0)
+ return 0;
+
+ for (i = 0; i < n; i++) {
+ t->tm_min++;
+ if (mktime(t) == -1) {
+ t->tm_min = 0;
+ if (sub_inc_hour(t, 1) == -1)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int sub_inc_second(struct tm *t, int n)
+{
+ time_t r;
+ struct tm *tmp;
+
+ if (n == 0)
+ return 0;
+
+ r = mktime(t);
+
+ if (r + n <= r)
+ return -1;
+ r += n;
+
+ tmp = localtime(&r);
+ *t = *tmp;
+
+ return 0;
+}
+
+/* super inefficient, but should best-possible avoid any weird leap
+ * years/seconds/dst-problems/other future changes */
+bool entry_is_active(struct entry_s *e, time_t now)
+{
+ struct tm t, *tmp;
+ time_t rtmp, now_plus_warn;
+
+ assert(e != NULL);
+
+ tmp = localtime(&now);
+ assert(tmp != NULL);
+ t = *tmp;
+
+ if (sub_inc_year(&t, e->warn.year))
+ return false;
+ if (sub_inc_month(&t, e->warn.month))
+ return false;
+ if (sub_inc_day(&t, e->warn.day))
+ return false;
+ if (sub_inc_hour(&t, e->warn.hour))
+ return false;
+ if (sub_inc_minute(&t, e->warn.minute))
+ return false;
+ if (sub_inc_second(&t, e->warn.second))
+ return false;
+
+ now_plus_warn = mktime(&t);
+
+ if (e->type == ENTRY_TYPE_ON) {
+ if (e->start >= now && e->start <= now_plus_warn)
+ return true;
+
+ return false;
+ }
+
+ tmp = localtime(&(e->start));
+ assert(tmp != NULL);
+ t = *tmp;
+
+ if (e->has_end && now > e->end)
+ return false;
+
+ for (rtmp = e->start;;) {
+ rtmp = mktime(&t);
+
+ if (rtmp > now_plus_warn)
+ return false;
+
+ if (rtmp >= now)
+ return true;
+
+ if (sub_inc_year(&t, e->every.year))
+ return false;
+ if (sub_inc_month(&t, e->every.month))
+ return false;
+ if (sub_inc_day(&t, e->every.day))
+ return false;
+ if (sub_inc_hour(&t, e->every.hour))
+ return false;
+ if (sub_inc_minute(&t, e->every.minute))
+ return false;
+ if (sub_inc_second(&t, e->every.second))
+ return false;
+ }
+}