summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Minichmayr <markus@tapkey.com>2022-09-15 09:23:37 +0200
committerMarkus Minichmayr <markus@tapkey.com>2022-09-24 16:02:33 +0200
commitc682c8858fdcab2c74476f61f9e16cbf30412c1c (patch)
treee270abdb7c6f67d7ca69413c254361f88f73fbd0
parent80e3e82dfadf06c52fe100da6793bbddb415e449 (diff)
downloadlibical-git-icaltime_as_timet_y2100.tar.gz
Fix icaltime_as_timet to support dates after year 2100.icaltime_as_timet_y2100
-rw-r--r--src/libical/icaltime.c10
-rw-r--r--src/libical/icaltime.h.cmake2
-rw-r--r--src/test/regression.c24
3 files changed, 34 insertions, 2 deletions
diff --git a/src/libical/icaltime.c b/src/libical/icaltime.c
index d98880b2..93eebf6c 100644
--- a/src/libical/icaltime.c
+++ b/src/libical/icaltime.c
@@ -102,6 +102,7 @@ static icaltime_t icaltime_timegm(const struct tm *tm)
static icaltime_t make_time(struct tm *tm, int tzm)
{
icaltime_t tim;
+ int febs;
static int days[] = { -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 };
@@ -136,12 +137,17 @@ static icaltime_t make_time(struct tm *tm, int tzm)
tim = (icaltime_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.cmake b/src/libical/icaltime.h.cmake
index 90b62ce8..4e24d4b6 100644
--- a/src/libical/icaltime.h.cmake
+++ b/src/libical/icaltime.h.cmake
@@ -190,6 +190,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 icaltime_t icaltime_as_timet(const struct icaltimetype);
diff --git a/src/test/regression.c b/src/test/regression.c
index 8f036110..106c08e0 100644
--- a/src/test/regression.c
+++ b/src/test/regression.c
@@ -5234,6 +5234,29 @@ static void test_remove_tzid_from_due(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_ICALTIME_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)
@@ -5300,6 +5323,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 calculation of DOY and WD", test_juldat_caldat, do_test, do_header);
test_run("Test day of Year", test_doy, do_test, do_header);