Skip to content

Conversation

blar
Copy link
Contributor

@blar blar commented Aug 17, 2017

https://bugs.php.net/bug.php?id=75088

getTransitions is slow with large negative or positive values. With the default values PHP_INT_MIN and PHP_INT_MAX the function takes a very long time.

@derickr As you wish in #2690. Please check if this patch is correct.

Comparing and Benchmark

I compared the output of date() with 1.000.000 random timestamps between PHP_INT_MIN and PHP_INT_MAX and 1.000.000 random timestamps between strtotime('1900-01-01') and strtotime('2100-01-01') with my local PHP 7.1.6 and PHP 7.3.0-dev.

PHP 7.1.6

PHP 7.1.6 (cli) (built: Jun 25 2017 18:59:00) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

real 79m48.622s
user 77m25.880s
sys 0m57.932s

PHP 7.3.0-dev

PHP 7.3.0-dev (cli) (built: Aug 11 2017 20:34:53) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.3.0-dev, Copyright (c) 1998-2017 Zend Technologies

real 0m18.027s
user 0m2.337s
sys 0m14.291s

Difference

With the 2.000.000 random timestamps i got only 4 different results which seems to be a bug. Any timestamp that is a multiple of 146097 (DAYS_PER_LYEAR_PERIOD) or 146096 (depends on timezone?) * 86400 (SECS_PER_DAY) lead to a zero day in a date (yyyy-01-00). https://3v4l.org/vBtut

PHP 7.1.6

Timestamp: Date
3191032750586206520: 101119804370-01-00 02:15:20
5278333347477533876: 167263727170-01-00 08:17:56
6202182859306740885: 196539352770-01-00 18:14:45
7060696112971042445: 223744554770-01-00 17:34:05

PHP 7.3.0-dev

Timestamp: Date
3191032750586206520: 101119804369-12-31 02:15:20
5278333347477533876: 167263727169-12-31 08:17:56
6202182859306740885: 196539352769-12-31 18:14:45
7060696112971042445: 223744554769-12-31 17:34:05

while (tmp_days >= DAYS_PER_LYEAR) {
while (days >= DAYS_PER_LYEAR) {
cur_year++;
TIMELIB_DEBUG(printf("days=%lld, year=%lld\n", days, cur_year););
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may be you should remove it

tmp_days += 1460970;
while (days <= 0) {
cur_year--;
TIMELIB_DEBUG(printf("days=%lld, year=%lld\n", days, cur_year););
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

i--;
}
TIMELIB_DEBUG(printf("A: ts=%lld, year=%lld, month=%lld, day=%lld,", ts, cur_year, i + 1, tmp_days - months[i]););
TIMELIB_DEBUG(printf("A: ts=%lld, year=%lld, month=%lld, day=%lld,", ts, cur_year, i + 1, days - months[i]););
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

@blar blar changed the title Bug #75088 getTransitions is slow with large values Bug #75088 date() and DateTimeZone::getTransitions() are slow with large timestamps Aug 20, 2017
@andrewnester
Copy link
Contributor

I guess changes should be done in upstream repository here
https://github.com/andrewnester/timelib/blob/master/unixtime2tm.c
cc @derickr

@blar
Copy link
Contributor Author

blar commented Aug 21, 2017

@andrewnester is https://github.com/derickr/timelib correct or should i send a pull request to https://github.com/andrewnester/timelib?

@andrewnester
Copy link
Contributor

@blar yes, it should be https://github.com/derickr/timelib , sorry

@krakjoe
Copy link
Member

krakjoe commented Sep 6, 2017

These changes belong upstream, the tests can be pulled into php-src when upstream pulls changes.

@krakjoe krakjoe closed this Sep 6, 2017
@derickr
Copy link
Member

derickr commented Sep 6, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants