From 39c440444ff38c0e1702209c67cf018b92c71882 Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Sun, 27 Nov 2016 07:39:37 +0000 Subject: [PATCH] Add support for timezones date_t is always in local time so that we can work with it easier when displaying calendars but stamp_t is always in UTC UNIX time. Calendar's should can convert to the configured local time by first converting to stamp_t then to date_t. --- cals/ical.c | 20 ++-------- src/date.c | 103 +++++++++++++++++++++++++++++++++++----------------- src/date.h | 8 +++- src/main.c | 3 +- src/util.c | 4 +- 5 files changed, 85 insertions(+), 53 deletions(-) diff --git a/cals/ical.c b/cals/ical.c index b21cad0..57fff1e 100644 --- a/cals/ical.c +++ b/cals/ical.c @@ -58,26 +58,14 @@ static int ical_compare(const void *_a, const void *_b) ecomp != 0 ? ecomp : 0 ; } -static date_t to_date(struct icaltimetype time) +static date_t to_date(struct icaltimetype itime) { - return (date_t){ - .year = time.year, - .month = time.month ? time.month-1 : 0, - .day = time.day ? time.day -1 : 0, - .hour = time.hour, - .min = time.minute, - }; + return get_date(icaltime_as_timet_with_zone(itime, itime.zone)); } -static icaltimetype to_itime(date_t time) +static icaltimetype to_itime(date_t date) { - return (struct icaltimetype){ - .year = time.year, - .month = time.month + 1, - .day = time.day + 1, - .hour = time.hour, - .minute = time.min - }; + return icaltime_from_timet_with_zone(get_stamp(date), 0, NULL); } static void add_recur(cal_t *cal, diff --git a/src/date.c b/src/date.c index 8441441..4371dff 100644 --- a/src/date.c +++ b/src/date.c @@ -17,9 +17,15 @@ /* Time Keeping Bugs Abound! */ +#define _POSIX_C_SOURCE 200112L + #include +#include +#include #include +#include "util.h" +#include "conf.h" #include "date.h" /* Global data */ @@ -29,27 +35,24 @@ date_t SEL; /* Initialize */ void date_init(void) { - time_t sec = time(NULL); - struct tm *tm = localtime(&sec); + /* Sync current time */ + NOW = get_date(0); - SEL.year = tm->tm_year+1900; - SEL.month = tm->tm_mon; - SEL.day = tm->tm_mday-1; + /* Sync selection */ + SEL.year = NOW.year; + SEL.month = NOW.month; + SEL.day = NOW.day; +} - date_sync(); +void date_config(const char *group, const char *name, const char *key, const char *value) +{ + if (match(group, "date") && match(key, "timezone") && value) + setenv("TZ", get_string(value), 1); } void date_sync(void) { - time_t sec = time(NULL); - struct tm *tm = localtime(&sec); - - NOW.year = tm->tm_year+1900; - NOW.month = tm->tm_mon; - NOW.day = tm->tm_mday-1; - NOW.hour = tm->tm_hour; - NOW.min = tm->tm_min; - NOW.sec = tm->tm_sec; + NOW = get_date(0); } /* Time functions */ @@ -101,16 +104,17 @@ wday_t start_of_month(year_t year, month_t month) void add_days(year_t *year, month_t *month, day_t *day, int days) { - time_t time = mktime(&(struct tm){ - .tm_year = *year-1900, - .tm_mon = *month, - .tm_mday = *day+1, - .tm_hour = 12}); - time += days*24*60*60; - struct tm *tm = localtime(&time); - *year = tm->tm_year+1900; - *month = tm->tm_mon; - *day = tm->tm_mday-1; + date_t date = { + .year = *year, + .month = *month, + .day = *day, + .hour = 12 + }; + stamp_t stamp = get_stamp(date); + date_t then = get_date(stamp + days*24*60*60); + *year = then.year; + *month = then.month; + *day = then.day; } void add_months(year_t *year, month_t *month, int months) @@ -120,19 +124,39 @@ void add_months(year_t *year, month_t *month, int months) *month = total % 12; } -stamp_t get_time(date_t *date) +/* Date functions */ +date_t get_date(stamp_t stamp) +{ + time_t t = stamp ? stamp : time(NULL); + struct tm *tm = localtime(&t); + date_t date = { + .year = tm->tm_year+1900, + .month = tm->tm_mon, + .day = tm->tm_mday-1, + .hour = tm->tm_hour, + .min = tm->tm_min, + .sec = tm->tm_sec, + }; + return date; +} + +stamp_t get_stamp(date_t date) { - return mktime(&(struct tm){ - .tm_year = date->year-1900, - .tm_mon = date->month, - .tm_mday = date->day+1, - .tm_hour = date->hour, - .tm_min = date->min}); + struct tm tm = { + .tm_year = date.year-1900, + .tm_mon = date.month, + .tm_mday = date.day+1, + .tm_hour = date.hour, + .tm_min = date.min, + .tm_sec = date.sec, + }; + time_t t = mktime(&tm); + return (stamp_t)t; } int get_mins(date_t *start, date_t *end) { - return (get_time(end)-get_time(start))/60; + return (get_stamp(*end)-get_stamp(*start))/60; } int compare(date_t *a, date_t *b) @@ -209,6 +233,19 @@ const char *day_to_string(wday_t day) /* Test functions */ void date_test(void) { + setenv("TZ", "US/Central", 1); + + time_t timet = time(NULL); + date_t date = get_date(timet); + stamp_t stamp = get_stamp(date); + + printf("Time\n"); + printf(" time %ld\n", timet); + printf(" stamp %lld\n", stamp); + printf(" date %04d-%02d-%02d %02d:%02d %02ds\n", + date.year, date.month, date.day, + date.hour, date.min, date.sec); + printf("Info\n"); printf(" Year Month Start Weeks Days\n"); for (int y = 2012; y <= 2012; y++) diff --git a/src/date.h b/src/date.h index 7a0c8ac..ccd2252 100644 --- a/src/date.h +++ b/src/date.h @@ -15,9 +15,10 @@ * along with this program. If not, see . */ -/* Time types */ +/* UTC time stamp */ typedef long long stamp_t; +/* Local time type */ typedef int year_t; typedef int day_t; typedef int hour_t; @@ -65,6 +66,7 @@ extern date_t SEL; // date and time the user is looking at /* Initialize */ void date_init(void); void date_sync(void); +void date_config(const char *group, const char *name, const char *key, const char *value); /* Time functions */ int is_leap_year(year_t year); @@ -77,7 +79,9 @@ day_t start_of_week(year_t year, month_t month, day_t day); void add_days(year_t *year, month_t *month, day_t *day, int days); void add_months(year_t *year, month_t *month, int months); -stamp_t get_stamp(date_t *date); +/* Date functions */ +date_t get_date(stamp_t stamp); +stamp_t get_stamp(date_t date); int get_mins(date_t *start, date_t *end); int compare(date_t *a, date_t *b); int same_day(date_t *a, date_t *b); diff --git a/src/main.c b/src/main.c index 99816b1..ce35539 100644 --- a/src/main.c +++ b/src/main.c @@ -28,8 +28,9 @@ /* Config parser */ static void on_config(const char *group, const char *name, const char *key, const char *value) { - view_config(group, name, key, value); + date_config(group, name, key, value); cal_config(group, name, key, value); + view_config(group, name, key, value); } /* Control-C handler, so we don't hose the therminal */ diff --git a/src/util.c b/src/util.c index 1ebecfc..d74a746 100644 --- a/src/util.c +++ b/src/util.c @@ -28,6 +28,7 @@ #include "view.h" #include "util.h" +#pragma weak view_exit #pragma weak view_debug /* Static data */ @@ -155,6 +156,7 @@ void error(char *fmt, ...) fflush(stderr); message(stderr, "error", fmt, ap); va_end(ap); - view_exit(); + if (view_exit) + view_exit(); exit(-1); } -- 2.43.2