aboutsummaryrefslogtreecommitdiffstats
path: root/src/utils.c
diff options
context:
space:
mode:
authorLars Henriksen <LarsHenriksen@get2net.dk>2018-10-31 15:23:41 +0100
committerLukas Fleischer <lfleischer@calcurse.org>2018-11-10 12:19:28 +0100
commit4263a2850431b7328699c713b4e97667f9ba02e2 (patch)
treec15245e7187be4f081a90e851e77ae7093e8af64 /src/utils.c
parentf91b7cdee0efb7af2989eed56b6e3248da2b6712 (diff)
downloadcalcurse-4263a2850431b7328699c713b4e97667f9ba02e2.tar.gz
calcurse-4263a2850431b7328699c713b4e97667f9ba02e2.zip
DST fix: adjusting time in appointments
Calcurse saves time and date information on disk as local time in readable text file format. When loaded from disk or when entered by the user, local time is converted to Unix time (seconds since 00:00:00, 1 January 1970). When displayed, and later when saved to disk, the Unix time is converted back to readable local time. Both conversions depend on DST. Hence, if midnight for a day with DST in effect (i.e. local time) is converted, increased with an amount and converted back, the amount has changed if DST is _not_ in effect for the resulting time. In general, calculations on Unix time variables should be used with caution because of the DST-dependent conversions. Instead, the calculations should be performed on local time data with the help of mktime(). The commit fixes start time for pasted appointments (ordinary and recurrent) and the 'until'-date of recurrent appointments, pasted as well as new and edited. The latter problem is slightly different in that the adjustment is a number of days, as it is for exception dates. Update of the date in parse_datetime() has been corrected to be similar to update of the time, although no problem has been identified. Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
Diffstat (limited to 'src/utils.c')
-rw-r--r--src/utils.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/src/utils.c b/src/utils.c
index 09f1f98..7b02f12 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -530,7 +530,27 @@ long date_sec_change(long date, int delta_month, int delta_day)
return t;
}
-/* A time in seconds is updated with new hour and minutes and returned. */
+/*
+ * A date in seconds is updated with new day, month and year and returned.
+ */
+static time_t update_date_in_date(time_t date, int day, int month, int year)
+{
+ struct tm lt;
+
+ localtime_r(&date, &lt);
+ lt.tm_mday = day;
+ lt.tm_mon = month - 1;
+ lt.tm_year = year - 1900;
+ lt.tm_isdst = -1;
+ date = mktime(&lt);
+ EXIT_IF(date == -1, _("error in mktime"));
+
+ return date;
+}
+
+/*
+ * A date in seconds is updated with new hour and minutes and returned.
+ */
time_t update_time_in_date(time_t date, unsigned hr, unsigned mn)
{
struct tm lt;
@@ -1218,10 +1238,8 @@ int parse_datetime(const char *string, time_t *ts, time_t dur)
} else if (parse_date_interactive(d, &year, &month, &day)) {
ret |= PARSE_DATETIME_HAS_DATE;
}
- if (ret & PARSE_DATETIME_HAS_DATE) {
- struct date date = { day , month, year };
- *ts = date2sec(date, 0, 0) + get_item_time(*ts);
- }
+ if (ret & PARSE_DATETIME_HAS_DATE)
+ *ts = update_date_in_date(*ts, day, month, year);
if (ret & PARSE_DATETIME_HAS_TIME)
*ts = update_time_in_date(*ts, hour, minute);
mem_free(d);