Skip to content

Commit

Permalink
Fixed derickr#19: Inefficient algorithm for calculating dates far in …
Browse files Browse the repository at this point in the history
…the past.

Also related to PHP bug #75088.
  • Loading branch information
derickr authored and nzolnierzmdb committed Sep 18, 2017
1 parent 86dfc4f commit ac0c50f
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 26 deletions.
84 changes: 84 additions & 0 deletions tests/c/issues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,87 @@ TEST(issues, issue0017_test3)

timelib_time_dtor(t);
}

TEST(issues, issue0019_test1)
{
timelib_sll ts = -172800;
timelib_time *t = timelib_time_ctor();

timelib_set_timezone_from_offset(t, 0);
timelib_unixtime2local(t, ts);
LONGS_EQUAL(1969, t->y);
LONGS_EQUAL(12, t->m);
LONGS_EQUAL(30, t->d);

timelib_time_dtor(t);
}

TEST(issues, issue0019_test2)
{
timelib_sll ts = -86400;
timelib_time *t = timelib_time_ctor();

timelib_set_timezone_from_offset(t, 0);
timelib_unixtime2local(t, ts);
LONGS_EQUAL(1969, t->y);
LONGS_EQUAL(12, t->m);
LONGS_EQUAL(31, t->d);

timelib_time_dtor(t);
}

TEST(issues, issue0019_test3)
{
timelib_sll ts = 0;
timelib_time *t = timelib_time_ctor();

timelib_set_timezone_from_offset(t, 0);
timelib_unixtime2local(t, ts);
LONGS_EQUAL(1970, t->y);
LONGS_EQUAL(1, t->m);
LONGS_EQUAL(1, t->d);

timelib_time_dtor(t);
}

TEST(issues, issue0019_test4)
{
timelib_sll ts = -12622953600;
timelib_time *t = timelib_time_ctor();

timelib_set_timezone_from_offset(t, 0);
timelib_unixtime2local(t, ts);
LONGS_EQUAL(1569, t->y);
LONGS_EQUAL(12, t->m);
LONGS_EQUAL(30, t->d);

timelib_time_dtor(t);
}

TEST(issues, issue0019_test5)
{
timelib_sll ts = -12622867200;
timelib_time *t = timelib_time_ctor();

timelib_set_timezone_from_offset(t, 0);
timelib_unixtime2local(t, ts);
LONGS_EQUAL(1569, t->y);
LONGS_EQUAL(12, t->m);
LONGS_EQUAL(31, t->d);

timelib_time_dtor(t);
}

TEST(issues, issue0019_test6)
{
timelib_sll ts = -12622780800;
timelib_time *t = timelib_time_ctor();

timelib_set_timezone_from_offset(t, 0);
timelib_unixtime2local(t, ts);
LONGS_EQUAL(1570, t->y);
LONGS_EQUAL(1, t->m);
LONGS_EQUAL(1, t->d);

timelib_time_dtor(t);
}
41 changes: 15 additions & 26 deletions unixtime2tm.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,46 +48,35 @@ void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts)

if (ts >= 0) {
tmp_days = days + 1;
} else {
tmp_days = days;
}

if (tmp_days > DAYS_PER_LYEAR_PERIOD || tmp_days <= -DAYS_PER_LYEAR_PERIOD) {
cur_year += YEARS_PER_LYEAR_PERIOD * (tmp_days / DAYS_PER_LYEAR_PERIOD);
tmp_days -= DAYS_PER_LYEAR_PERIOD * (tmp_days / DAYS_PER_LYEAR_PERIOD);
}
if (tmp_days > DAYS_PER_LYEAR_PERIOD || tmp_days <= -DAYS_PER_LYEAR_PERIOD) {
cur_year += YEARS_PER_LYEAR_PERIOD * (tmp_days / DAYS_PER_LYEAR_PERIOD);
tmp_days -= DAYS_PER_LYEAR_PERIOD * (tmp_days / DAYS_PER_LYEAR_PERIOD);
}
TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););

if (ts >= 0) {
while (tmp_days >= DAYS_PER_LYEAR) {
cur_year++;
if (timelib_is_leap(cur_year)) {
tmp_days -= DAYS_PER_LYEAR;
} else {
tmp_days -= DAYS_PER_YEAR;
}
TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););
}
} else {
tmp_days = days;

/* Guess why this might be for, it has to do with a pope ;-). It's also
* only valid for Great Brittain and it's colonies. It needs fixing for
* other locales. *sigh*, why is this crap so complex! */
/*
if (ts <= TIMELIB_LL_CONST(-6857352000)) {
tmp_days -= 11;
}
*/

while (tmp_days <= 0) {
if (tmp_days < -1460970) {
cur_year -= 4000;
TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););
tmp_days += 1460970;
cur_year--;
if (timelib_is_leap(cur_year)) {
tmp_days += DAYS_PER_LYEAR;
} else {
cur_year--;
TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););
if (timelib_is_leap(cur_year)) {
tmp_days += DAYS_PER_LYEAR;
} else {
tmp_days += DAYS_PER_YEAR;
}
tmp_days += DAYS_PER_YEAR;
}
TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););
}
remainder += SECS_PER_DAY;
}
Expand Down

0 comments on commit ac0c50f

Please sign in to comment.