Skip to content

Commit ed02f20

Browse files
author
Derick Rethans
committed
- Fixed bug #30096 (gmmktime does not return the corrent time).
- Re-implemented mktime and gmmktime with new date time library. - Added testcase for bug #30096, updated test cases for E_STRICT warning of is_dst parameter usage for mktime/gmmktime.
1 parent f4b5a51 commit ed02f20

File tree

10 files changed

+161
-209
lines changed

10 files changed

+161
-209
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ PHP NEWS
1919
- Fixed bug #30828 (debug_backtrace() reports incorrect class in overridden
2020
methods). (Dmitry)
2121
- Fixed bug #30519 (Interface not existing says Class not found). (Dmitry)
22+
- Fixed bug #30096 (gmmktime does not return the corrent time). (Derick)
2223
- Fixed bug #30052 (Crash on shutdown after odbc_pconnect()). (Edin)
2324
- Fixed bug #28377 (debug_backtrace is intermittently passing args). (Dmitry)
2425
- Fixed bug #27268 (Bad references accentuated by clone). (Dmitry)

ext/date/php_date.c

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
function_entry date_functions[] = {
3232
PHP_FE(date, NULL)
3333
PHP_FE(gmdate, NULL)
34+
PHP_FE(mktime, NULL)
35+
PHP_FE(gmmktime, NULL)
3436
PHP_FE(strtotime, NULL)
3537
PHP_FE(date_timezone_set, NULL)
3638
PHP_FE(date_timezone_get, NULL)
@@ -400,6 +402,105 @@ PHP_FUNCTION(strtotime)
400402
}
401403
/* }}} */
402404

405+
PHPAPI static void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gmt)
406+
{
407+
long hou, min, sec, mon, day, yea, dst = -1;;
408+
timelib_time *now;
409+
timelib_tzinfo *tzi;
410+
long ts, adjust_seconds = 0;
411+
int error;
412+
413+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lllllll", &hou, &min, &sec, &mon, &day, &yea, &dst) == FAILURE) {
414+
RETURN_FALSE;
415+
}
416+
/* Initialize structure with current time */
417+
now = timelib_time_ctor();
418+
if (gmt) {
419+
timelib_unixtime2gmt(now, (timelib_sll) time(NULL));
420+
} else {
421+
tzi = get_timezone_info(TSRMLS_C);
422+
timelib_unixtime2local(now, (timelib_sll) time(NULL), tzi);
423+
}
424+
/* Fill in the new data */
425+
switch (ZEND_NUM_ARGS()) {
426+
case 7:
427+
/* break intentionally missing */
428+
case 6:
429+
now->y = yea;
430+
/* break intentionally missing again */
431+
case 5:
432+
now->d = day;
433+
/* break missing intentionally here too */
434+
case 4:
435+
now->m = mon;
436+
/* and here */
437+
case 3:
438+
now->s = sec;
439+
/* yup, this break isn't here on purpose too */
440+
case 2:
441+
now->i = min;
442+
/* last intentionally missing break */
443+
case 1:
444+
now->h = hou;
445+
break;
446+
default:
447+
php_error_docref(NULL TSRMLS_CC, E_STRICT, "You should be using the time() function instead.");
448+
}
449+
/* Update the timestamp */
450+
if (gmt) {
451+
timelib_update_ts(now, NULL);
452+
} else {
453+
timelib_update_ts(now, tzi);
454+
}
455+
/* Support for the deprecated is_dst parameter */
456+
if (dst != -1) {
457+
php_error_docref(NULL TSRMLS_CC, E_STRICT, "The is_dst parameter is deprecated.");
458+
if (gmt) {
459+
/* GMT never uses DST */
460+
if (dst == 1) {
461+
adjust_seconds = -3600;
462+
}
463+
} else {
464+
/* Figure out is_dst for current TS */
465+
timelib_time_offset *tmp_offset;
466+
tmp_offset = timelib_get_time_zone_info(now->sse, tzi);
467+
if (dst == 1 && tmp_offset->is_dst == 0) {
468+
adjust_seconds = -3600;
469+
}
470+
if (dst == 0 && tmp_offset->is_dst == 1) {
471+
adjust_seconds = +3600;
472+
}
473+
}
474+
}
475+
/* Clean up and return */
476+
ts = timelib_date_to_int(now, &error);
477+
ts += adjust_seconds;
478+
479+
timelib_time_dtor(now);
480+
481+
if (error) {
482+
RETURN_FALSE;
483+
} else {
484+
RETURN_LONG(ts);
485+
}
486+
}
487+
488+
/* {{{ proto int mktime(int hour, int min, int sec, int mon, int day, int year)
489+
Get UNIX timestamp for a date */
490+
PHP_FUNCTION(mktime)
491+
{
492+
php_mktime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
493+
}
494+
/* }}} */
495+
496+
/* {{{ proto int gmmktime(int hour, int min, int sec, int mon, int day, int year)
497+
Get UNIX timestamp for a GMT date */
498+
PHP_FUNCTION(gmmktime)
499+
{
500+
php_mktime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
501+
}
502+
/* }}} */
503+
403504
PHP_FUNCTION(date_timezone_set)
404505
{
405506
char *zone;

ext/date/php_date.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ extern zend_module_entry date_module_entry;
2727
PHP_FUNCTION(date);
2828
PHP_FUNCTION(gmdate);
2929
PHP_FUNCTION(strtotime);
30+
31+
PHP_FUNCTION(mktime);
32+
PHP_FUNCTION(gmmktime);
33+
3034
PHP_FUNCTION(date_timezone_set);
3135
PHP_FUNCTION(date_timezone_get);
3236

@@ -49,5 +53,6 @@ ZEND_END_MODULE_GLOBALS(date)
4953

5054
/* Backwards compability wrapper */
5155
signed long php_parse_date(char *string, signed long *now);
56+
PHPAPI static void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gmt);
5257

5358
#endif /* PHP_DATE_H */

ext/date/tests/bug30096.phpt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
Bug #30096 (gmmktime does not return the corrent time)
3+
--INI--
4+
error_reporting=2047
5+
--FILE--
6+
<?php
7+
echo "no dst --> dst\n";
8+
$ts = -1;
9+
gm_date_check(01,00,00,03,27,2005);
10+
gm_date_check(02,00,00,03,27,2005);
11+
gm_date_check(03,00,00,03,27,2005);
12+
gm_date_check(04,00,00,03,27,2005);
13+
14+
echo "\ndst --> no dst\n";
15+
$ts = -1;
16+
gm_date_check(01,00,00,10,30,2005);
17+
gm_date_check(02,00,00,10,30,2005);
18+
gm_date_check(03,00,00,10,30,2005);
19+
gm_date_check(04,00,00,10,30,2005);
20+
21+
function gm_date_check($hour, $minute, $second, $month, $day, $year) {
22+
global $ts, $tsold;
23+
24+
echo "gmmktime($hour,$minute,$second,$month,$day,$year): ";
25+
26+
$tsold = $ts;
27+
$ts = gmmktime($hour, $minute, $second, $month, $day, $year);
28+
29+
echo $ts, " | gmdate('r', $ts):", gmdate('r', $ts);
30+
if ($tsold > 0) {
31+
echo " | Diff: " . ($ts - $tsold);
32+
}
33+
echo "\n";
34+
}
35+
36+
?>
37+
--EXPECT--
38+
no dst --> dst
39+
gmmktime(1,0,0,3,27,2005): 1111885200 | gmdate('r', 1111885200):Sun, 27 Mar 2005 01:00:00 +0000
40+
gmmktime(2,0,0,3,27,2005): 1111888800 | gmdate('r', 1111888800):Sun, 27 Mar 2005 02:00:00 +0000 | Diff: 3600
41+
gmmktime(3,0,0,3,27,2005): 1111892400 | gmdate('r', 1111892400):Sun, 27 Mar 2005 03:00:00 +0000 | Diff: 3600
42+
gmmktime(4,0,0,3,27,2005): 1111896000 | gmdate('r', 1111896000):Sun, 27 Mar 2005 04:00:00 +0000 | Diff: 3600
43+
44+
dst --> no dst
45+
gmmktime(1,0,0,10,30,2005): 1130634000 | gmdate('r', 1130634000):Sun, 30 Oct 2005 01:00:00 +0000
46+
gmmktime(2,0,0,10,30,2005): 1130637600 | gmdate('r', 1130637600):Sun, 30 Oct 2005 02:00:00 +0000 | Diff: 3600
47+
gmmktime(3,0,0,10,30,2005): 1130641200 | gmdate('r', 1130641200):Sun, 30 Oct 2005 03:00:00 +0000 | Diff: 3600
48+
gmmktime(4,0,0,10,30,2005): 1130644800 | gmdate('r', 1130644800):Sun, 30 Oct 2005 04:00:00 +0000 | Diff: 3600

ext/standard/basic_functions.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,6 @@ function_entry basic_functions[] = {
169169
PHP_FE(time_sleep_until, NULL)
170170
#endif
171171
PHP_FE(time, NULL)
172-
PHP_FE(mktime, NULL)
173-
PHP_FE(gmmktime, NULL)
174172
#if HAVE_STRPTIME
175173
PHP_FE(strptime, NULL)
176174
#endif

0 commit comments

Comments
 (0)