summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ReleaseNotes.txt2
-rw-r--r--src/libical/icaltime.c10
-rw-r--r--src/libical/icaltime.h2
-rw-r--r--src/test/regression.c24
4 files changed, 36 insertions, 2 deletions
diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt
index 4843d746..f027309a 100644
--- a/ReleaseNotes.txt
+++ b/ReleaseNotes.txt
@@ -5,6 +5,8 @@ Version 3.0.15 (UNRELEASED):
----------------------------
* Add missing property parameters into libical-glib
* Fix CMake option USE_32BIT_TIME_T actually uses a 32-bit time_t value
+ * Fix icaltime_as_timet, which returned incorrect results for years >= 2100,
+ to work properly between years 1902 and 10k.
* Fix x-property comma handling and escaping
Version 3.0.14 (05 February 2022):
diff --git a/src/libical/icaltime.c b/src/libical/icaltime.c
index 223ebb0a..fe03aee5 100644
--- a/src/libical/icaltime.c
+++ b/src/libical/icaltime.c
@@ -111,6 +111,7 @@ static time_t icaltime_timegm(const struct tm *tm)
static time_t make_time(struct tm *tm, int tzm)
{
time_t tim;
+ int febs;
static int days[] = { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 };
@@ -145,12 +146,17 @@ static time_t make_time(struct tm *tm, int tzm)
tim = (time_t) ((tm->tm_year - 70) * 365 + ((tm->tm_year - 1) / 4) - 17);
+ /* adjust: no leap days every 100 years, except every 400 years. */
+
+ febs = (tm->tm_year - 100) - ((tm->tm_mon <= 1) ? 1 : 0);
+ tim -= febs / 100;
+ tim += febs / 400;
+
/* add number of days elapsed in the current year */
tim += days[tm->tm_mon];
- /* check and adjust for leap years (the leap year check only valid
- during the 32-bit era */
+ /* check and adjust for leap years */
if ((tm->tm_year & 3) == 0 && tm->tm_mon > 1)
tim += 1;
diff --git a/src/libical/icaltime.h b/src/libical/icaltime.h
index ca69724f..e7c7d1a2 100644
--- a/src/libical/icaltime.h
+++ b/src/libical/icaltime.h
@@ -198,6 +198,8 @@ LIBICAL_ICAL_EXPORT struct icaltimetype icaltime_from_day_of_year(const int doy,
* This function probably won't do what you expect. In particular, you should
* only pass an icaltime in UTC, since no conversion is done. Even in that case,
* it's probably better to just use icaltime_as_timet_with_zone().
+ *
+ * The return value is defined for dates starting with 1902-01-01 until 10000-01-01 (excl.).
*/
LIBICAL_ICAL_EXPORT time_t icaltime_as_timet(const struct icaltimetype);
diff --git a/src/test/regression.c b/src/test/regression.c
index cdfc77c1..957b9c26 100644
--- a/src/test/regression.c
+++ b/src/test/regression.c
@@ -4963,6 +4963,29 @@ static void test_comma_in_xproperty(void)
icalcomponent_free(c);
}
+void test_icaltime_as_timet(void) {
+
+ ok("icaltime_from_string translates 19020101T000000Z to -2145916800", icaltime_as_timet(icaltime_from_string("19020101T000000Z")) == -2145916800);
+ ok("icaltime_from_string translates 19290519T000000Z to -1281916800", icaltime_as_timet(icaltime_from_string("19290519T000000Z")) == -1281916800);
+ ok("icaltime_from_string translates 19561004T000000Z to -417916800", icaltime_as_timet(icaltime_from_string("19561004T000000Z")) == -417916800);
+ ok("icaltime_from_string translates 19700101T000000Z to 0", icaltime_as_timet(icaltime_from_string("19700101T000000Z")) == 0);
+ ok("icaltime_from_string translates 19700301T235959Z to 5183999", icaltime_as_timet(icaltime_from_string("19700301T235959Z")) == 5183999);
+ ok("icaltime_from_string translates 19970717T235959Z to 869183999", icaltime_as_timet(icaltime_from_string("19970717T235959Z")) == 869183999);
+ ok("icaltime_from_string translates 20241202T235959Z to 1733183999", icaltime_as_timet(icaltime_from_string("20241202T235959Z")) == 1733183999);
+ ok("icaltime_from_string translates 20371231T235959Z to 2145916799", icaltime_as_timet(icaltime_from_string("20371231T235959Z")) == 2145916799);
+#if (SIZEOF_TIME_T > 4)
+ ok("icaltime_from_string translates 20520419T235959Z to 2597183999", icaltime_as_timet(icaltime_from_string("20520419T235959Z")) == 2597183999);
+ ok("icaltime_from_string translates 20790905T235959Z to 3461183999", icaltime_as_timet(icaltime_from_string("20790905T235959Z")) == 3461183999);
+ ok("icaltime_from_string translates 21000101T235959Z to 4102531199", icaltime_as_timet(icaltime_from_string("21000101T235959Z")) == 4102531199);
+ ok("icaltime_from_string translates 21000301T235959Z to 4107628799", icaltime_as_timet(icaltime_from_string("21000301T235959Z")) == 4107628799);
+ ok("icaltime_from_string translates 22370122T235959Z to 8427628799", icaltime_as_timet(icaltime_from_string("22370122T235959Z")) == 8427628799);
+ ok("icaltime_from_string translates 23731215T235959Z to 12747628799", icaltime_as_timet(icaltime_from_string("23731215T235959Z")) == 12747628799);
+ ok("icaltime_from_string translates 25101107T235959Z to 17067628799", icaltime_as_timet(icaltime_from_string("25101107T235959Z")) == 17067628799);
+ ok("icaltime_from_string translates 25821231T235959Z to 19344441599", icaltime_as_timet(icaltime_from_string("25821231T235959Z")) == 19344441599);
+ ok("icaltime_from_string translates 99991231T235959Z to 253402300799", icaltime_as_timet(icaltime_from_string("99991231T235959Z")) == 253402300799);
+#endif
+}
+
int main(int argc, char *argv[])
{
#if !defined(HAVE_UNISTD_H)
@@ -5018,6 +5041,7 @@ int main(int argc, char *argv[])
#endif
test_run("Test time parser functions", test_time_parser, do_test, do_header);
+ test_run("Test icaltime_as_timet", test_icaltime_as_timet, do_test, do_header);
test_run("Test time", test_time, do_test, do_header);
test_run("Test day of Year", test_doy, do_test, do_header);
test_run("Test duration", test_duration, do_test, do_header);