tz = guess_timezone(DATE_TIMEZONEDB);
tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB);
if (! tzi) {
- php_error_docref(NULL, E_ERROR, "Timezone database is corrupt - this should *never* happen!");
+ zend_throw_error(NULL, "Timezone database is corrupt. Please file a bug report as this should never happen");
}
return tzi;
}
ret = php_idate(ZSTR_VAL(format)[0], ts, 0);
if (ret == -1) {
- php_error_docref(NULL, E_WARNING, "Unrecognized date format token.");
+ php_error_docref(NULL, E_WARNING, "Unrecognized date format token");
RETURN_FALSE;
}
RETURN_LONG(ret);
PHP_FUNCTION(strtotime)
{
zend_string *times;
- int error1, error2;
+ int parse_error, epoch_does_not_fit_in_zend_long;
timelib_error_container *error;
zend_long preset_ts, ts;
zend_bool preset_ts_is_null = 1;
Z_PARAM_LONG_OR_NULL(preset_ts, preset_ts_is_null)
ZEND_PARSE_PARAMETERS_END();
+ /* timelib_strtotime() expects the string to not be empty */
+ if (ZSTR_LEN(times) == 0) {
+ RETURN_FALSE;
+ }
+
tzi = get_timezone_info();
now = timelib_time_ctor();
t = timelib_strtotime(ZSTR_VAL(times), ZSTR_LEN(times), &error,
DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper);
- error1 = error->error_count;
+ parse_error = error->error_count;
timelib_error_container_dtor(error);
+ if (parse_error) {
+ timelib_time_dtor(now);
+ timelib_time_dtor(t);
+ RETURN_FALSE;
+ }
+
timelib_fill_holes(t, now, TIMELIB_NO_CLONE);
timelib_update_ts(t, tzi);
- ts = timelib_date_to_int(t, &error2);
+ ts = timelib_date_to_int(t, &epoch_does_not_fit_in_zend_long);
timelib_time_dtor(now);
timelib_time_dtor(t);
- if (error1 || error2) {
+ if (epoch_does_not_fit_in_zend_long) {
+ php_error_docref(NULL, E_WARNING, "Epoch doesn't fit in a PHP integer");
RETURN_FALSE;
- } else {
- RETURN_LONG(ts);
}
+
+ RETURN_LONG(ts);
}
/* }}} */
timelib_time *now;
timelib_tzinfo *tzi = NULL;
zend_long ts, adjust_seconds = 0;
- int error;
+ int epoch_does_not_fit_in_zend_long;
ZEND_PARSE_PARAMETERS_START(1, 6)
Z_PARAM_LONG(hou)
}
/* Clean up and return */
- ts = timelib_date_to_int(now, &error);
- ts += adjust_seconds;
- timelib_time_dtor(now);
+ ts = timelib_date_to_int(now, &epoch_does_not_fit_in_zend_long);
- if (error) {
+ if (epoch_does_not_fit_in_zend_long) {
+ timelib_time_dtor(now);
+ php_error_docref(NULL, E_WARNING, "Epoch doesn't fit in a PHP integer");
RETURN_FALSE;
- } else {
- RETURN_LONG(ts);
}
+
+ ts += adjust_seconds;
+ timelib_time_dtor(now);
+
+ RETURN_LONG(ts);
}
/* }}} */
dateobj = Z_PHPDATE_P(object);
if (!(dateobj->time)) {
- php_error_docref(NULL, E_WARNING, "The DateTime object has not been correctly initialized by its constructor");
+ zend_throw_error(NULL, "The DateTime object has not been correctly initialized by its constructor");
return 0;
}
zval *object;
php_date_obj *dateobj;
zend_long timestamp;
- int error;
+ int epoch_does_not_fit_in_zend_long;
if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &object, date_ce_interface) == FAILURE) {
RETURN_THROWS();
DATE_CHECK_INITIALIZED(dateobj->time, DateTime);
timelib_update_ts(dateobj->time, NULL);
- timestamp = timelib_date_to_int(dateobj->time, &error);
- if (error) {
- RETURN_FALSE;
- } else {
- RETVAL_LONG(timestamp);
+ timestamp = timelib_date_to_int(dateobj->time, &epoch_does_not_fit_in_zend_long);
+
+ if (epoch_does_not_fit_in_zend_long) {
+ zend_value_error("Epoch doesn't fit in a PHP integer");
+ RETURN_THROWS();
}
+
+ RETURN_LONG(timestamp);
}
/* }}} */
php_timezone_obj *tzobj;
ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_STR(tz)
+ Z_PARAM_PATH_STR(tz) /* To prevent null bytes */
ZEND_PARSE_PARAMETERS_END();
tzobj = Z_PHPTIMEZONE_P(php_date_instantiate(date_ce_timezone, return_value));
zend_error_handling error_handling;
ZEND_PARSE_PARAMETERS_START(1, 1)
- Z_PARAM_STR(tz)
+ Z_PARAM_PATH_STR(tz) /* To prevent null bytes */
ZEND_PARSE_PARAMETERS_END();
zend_replace_error_handling(EH_THROW, NULL, &error_handling);
/* Extra validation */
if (what == PHP_DATE_TIMEZONE_PER_COUNTRY && option_len != 2) {
- php_error_docref(NULL, E_NOTICE, "A two-letter ISO 3166-1 compatible country code is expected");
- RETURN_FALSE;
+ zend_argument_value_error(2, "must be a two-letter ISO 3166-1 compatible country code "
+ "when argument #1 ($timezoneGroup) is DateTimeZone::PER_COUNTRY");
+ RETURN_THROWS();
}
tzdb = DATE_TIMEZONEDB;
function date_timestamp_set(DateTime $object, int $timestamp): DateTime {}
-function date_timestamp_get(DateTimeInterface $object): int|false {}
+function date_timestamp_get(DateTimeInterface $object): int {}
function timezone_open(string $timezone): DateTimeZone|false {}
function timezone_location_get(DateTimeZone $object): array|false {}
-function timezone_identifiers_list(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): array|false {}
+function timezone_identifiers_list(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null): array {}
function timezone_abbreviations_list(): array {}
public function setTimestamp(int $timestamp) {}
/**
- * @return int|false
+ * @return int
* @alias date_timestamp_get
*/
public function getTimestamp() {}
public function getOffset() {}
/**
- * @return int|false
+ * @return int
* @alias date_timestamp_get
*/
public function getTimestamp() {}
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: fee95924adec03c89fdd677ec26bb6eea34d4b3c */
+ * Stub hash: cb1532309655d85eb2644cdcfbf23063dfa1ddaf */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, timestamp, IS_LONG, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_date_timestamp_get, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
- ZEND_ARG_OBJ_INFO(0, object, DateTimeInterface, 0)
-ZEND_END_ARG_INFO()
+#define arginfo_date_timestamp_get arginfo_date_offset_get
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_timezone_open, 0, 1, DateTimeZone, MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, timezone, IS_STRING, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTimeZone, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_timezone_identifiers_list, 0, 0, MAY_BE_ARRAY|MAY_BE_FALSE)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_timezone_identifiers_list, 0, 0, IS_ARRAY, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timezoneGroup, IS_LONG, 0, "DateTimeZone::ALL")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, countryCode, IS_STRING, 1, "null")
ZEND_END_ARG_INFO()
var_dump(idate(1,1));
var_dump(idate(""));
var_dump(idate(0));
-
var_dump(idate("B", $t));
var_dump(idate("[", $t));
var_dump(idate("'"));
echo "Done\n";
?>
--EXPECTF--
-Warning: idate(): Unrecognized date format token. in %s on line %d
+Warning: idate(): Unrecognized date format token in %s on line %d
bool(false)
Warning: idate(): idate format is one char in %s on line %d
bool(false)
-Warning: idate(): Unrecognized date format token. in %s on line %d
+Warning: idate(): Unrecognized date format token in %s on line %d
bool(false)
int(41)
-Warning: idate(): Unrecognized date format token. in %s on line %d
+Warning: idate(): Unrecognized date format token in %s on line %d
bool(false)
-Warning: idate(): Unrecognized date format token. in %s on line %d
+Warning: idate(): Unrecognized date format token in %s on line %d
bool(false)
Done
echo $dt->format( DateTime::ISO8601 ), "\n";
?>
---EXPECT--
+--EXPECTF--
array(12) {
["year"]=>
int(0)
["is_localtime"]=>
bool(false)
}
+
+Warning: strtotime(): Epoch doesn't fit in a PHP integer in %s on line %d
bool(false)
object(DateTime)#1 (3) {
["date"]=>
<?php
$d = new DateTime('@100000000000');
var_dump($d->format('Y-m-d H:i:s U'));
-var_dump($d->getTimestamp());
+try {
+ var_dump($d->getTimestamp());
+} catch (\ValueError $e) {
+ echo $e->getMessage() . \PHP_EOL;
+}
var_dump($d->format('U'));
try {
echo $e->getMessage(), "\n";
}
var_dump($d->format('Y-m-d H:i:s U'));
-var_dump($d->getTimestamp());
+try {
+ var_dump($d->getTimestamp());
+} catch (\ValueError $e) {
+ echo $e->getMessage() . \PHP_EOL;
+}
$i = new DateInterval('PT100000000000S');
var_dump($i->format('%s'));
?>
--EXPECT--
string(32) "5138-11-16 09:46:40 100000000000"
-bool(false)
+Epoch doesn't fit in a PHP integer
string(12) "100000000000"
DateTime::setTimestamp(): Argument #1 ($timestamp) must be of type int, float given
string(32) "5138-11-16 09:46:40 100000000000"
-bool(false)
+Epoch doesn't fit in a PHP integer
string(10) "1215752192"
--FILE--
<?php
$timezone = "Europe/Zurich\0Foo";
-var_dump(timezone_open($timezone));
-var_dump(new DateTimeZone($timezone));
+try {
+ var_dump(timezone_open($timezone));
+} catch (\ValueError $e) {
+ echo $e->getMessage() . \PHP_EOL;
+}
+try {
+ var_dump(new DateTimeZone($timezone));
+} catch (\ValueError $e) {
+ echo $e->getMessage() . \PHP_EOL;
+}
?>
---EXPECTF--
-Warning: timezone_open(): Timezone must not contain null bytes in %sbug70277.php on line %d
-bool(false)
-
-Fatal error: Uncaught Exception: DateTimeZone::__construct(): Timezone must not contain null bytes in %sbug70277.php:%d
-Stack trace:
-#0 %sbug70277.php(%d): DateTimeZone->__construct('Europe/Zurich\x00F...')
-#1 {main}
- thrown in %sbug70277.php on line %d
+--EXPECT--
+timezone_open(): Argument #1 ($timezone) must not contain any null bytes
+DateTimeZone::__construct(): Argument #1 ($timezone) must not contain any null bytes
--TEST--
-Test gmdate() function : usage variation - Valid and invalid range of timestamp.
+Test gmdate() function : usage variation - Valid and invalid range of timestamp 32 bits.
+--SKIPIF--
+<?php
+if (PHP_INT_SIZE != 4) die('skip 32 bit only');
+?>
--FILE--
<?php
echo "*** Testing gmdate() : usage variation ***\n";
// Initialise all required variables
date_default_timezone_set('UTC');
-$timestamp = mktime(20, 45, 54, 12, 13, 1901);
echo "\n-- Testing gmdate() function with minimum range of timestamp --\n";
+$timestamp = mktime(20, 45, 54, 12, 13, 1901);
var_dump( gmdate(DATE_ISO8601, $timestamp) );
-$timestamp = mktime(20, 45, 50, 12, 13, 1901);
echo "\n-- Testing gmdate() function with less than the range of timestamp --\n";
+$timestamp = mktime(20, 45, 50, 12, 13, 1901);
var_dump( gmdate(DATE_ISO8601, $timestamp) );
echo "\n-- Testing gmdate() function with maximum range of timestamp --\n";
var_dump( gmdate(DATE_ISO8601, $timestamp) );
?>
---EXPECTREGEX--
-\*\*\* Testing gmdate\(\) : usage variation \*\*\*
+--EXPECTF--
+*** Testing gmdate() : usage variation ***
+
+-- Testing gmdate() function with minimum range of timestamp --
+string(24) "1901-12-13T20:45:54+0000"
+
+-- Testing gmdate() function with less than the range of timestamp --
--- Testing gmdate\(\) function with minimum range of timestamp --
-string\(24\) "1901-12-13T20:45:54\+0000"
+Warning: mktime(): Epoch doesn't fit in a PHP integer in %s on line %d
+string(24) "1970-01-01T00:00:00+0000"
--- Testing gmdate\(\) function with less than the range of timestamp --
-string\(24\) "(1970-01-01T00:00:00\+0000|1901-12-13T20:45:50\+0000)"
+-- Testing gmdate() function with maximum range of timestamp --
+string(24) "2038-01-19T03:14:07+0000"
--- Testing gmdate\(\) function with maximum range of timestamp --
-string\(24\) "2038-01-19T03:14:07\+0000"
+-- Testing gmdate() function with greater than the range of timestamp --
--- Testing gmdate\(\) function with greater than the range of timestamp --
-string\(24\) "(1970-01-01T00:00:00\+0000|2038-01-19T03:14:10\+0000)"
+Warning: mktime(): Epoch doesn't fit in a PHP integer in %s on line %d
+string(24) "1970-01-01T00:00:00+0000"
--- /dev/null
+--TEST--
+Test gmdate() function : usage variation - Valid and invalid range of timestamp 64 bits.
+--SKIPIF--
+<?php
+if (PHP_INT_SIZE == 4) die('skip 64 bit only');
+?>
+--FILE--
+<?php
+echo "*** Testing gmdate() : usage variation ***\n";
+
+// Initialise all required variables
+date_default_timezone_set('UTC');
+
+$timestamp = mktime(20, 45, 54, 12, 13, 1901);
+echo "\n-- Testing gmdate() function with minimum range of timestamp --\n";
+var_dump( gmdate(DATE_ISO8601, $timestamp) );
+
+$timestamp = mktime(20, 45, 50, 12, 13, 1901);
+echo "\n-- Testing gmdate() function with less than the range of timestamp --\n";
+var_dump( gmdate(DATE_ISO8601, $timestamp) );
+
+echo "\n-- Testing gmdate() function with maximum range of timestamp --\n";
+$timestamp = mktime(03, 14, 07, 1, 19, 2038);
+var_dump( gmdate(DATE_ISO8601, $timestamp) );
+
+echo "\n-- Testing gmdate() function with greater than the range of timestamp --\n";
+$timestamp = mktime(03, 14, 10, 1, 19, 2038);
+var_dump( gmdate(DATE_ISO8601, $timestamp) );
+
+?>
+--EXPECT--
+*** Testing gmdate() : usage variation ***
+
+-- Testing gmdate() function with minimum range of timestamp --
+string(24) "1901-12-13T20:45:54+0000"
+
+-- Testing gmdate() function with less than the range of timestamp --
+string(24) "1901-12-13T20:45:50+0000"
+
+-- Testing gmdate() function with maximum range of timestamp --
+string(24) "2038-01-19T03:14:07+0000"
+
+-- Testing gmdate() function with greater than the range of timestamp --
+string(24) "2038-01-19T03:14:10+0000"
--TEST--
-Test gmmktime() function : usage variation - Passing positive and negative float values to arguments.
+Test gmmktime() function : usage variation - Passing positive and negative float values to arguments 32 bits.
+--SKIPIF--
+<?php
+if (PHP_INT_SIZE != 4) die('skip 32 bit only');
+?>
--FILE--
<?php
echo "*** Testing gmmktime() : usage variation ***\n";
var_dump( gmmktime($hour, $min, $sec, $mon, $value, $value) );
}
?>
---EXPECTREGEX--
-\*\*\* Testing gmmktime\(\) : usage variation \*\*\*
+--EXPECTF--
+*** Testing gmmktime() : usage variation ***
--float 123456--
-int\(1662595688\)
-int\(1225589768\)
-int\(1218306336\)
-(bool|int)\((false|325855037288)\)
-(bool|int)\((false|3844412784488)\)
+int(1662595688)
+int(1225589768)
+int(1218306336)
+
+Warning: gmmktime(): Epoch doesn't fit in a PHP integer in %s on line %d
+bool(false)
+
+Warning: gmmktime(): Epoch doesn't fit in a PHP integer in %s on line %d
+bool(false)
--float -123456--
-int\(773712488\)
-int\(1210775048\)
-int\(1218059424\)
-(bool|int)\((false|-323460834712)\)
-(bool|int)\((false|-3968710530712)\)
+int(773712488)
+int(1210775048)
+int(1218059424)
+
+Warning: gmmktime(): Epoch doesn't fit in a PHP integer in %s on line %d
+bool(false)
+
+Warning: gmmktime(): Epoch doesn't fit in a PHP integer in %s on line %d
+bool(false)
--float -10.5--
-int\(1218118088\)
-int\(1218181808\)
-int\(1218182870\)
-int\(1170922088\)
-(bool|int)\((false|-62465356312)\)
+int(1218118088)
+int(1218181808)
+int(1218182870)
+int(1170922088)
+
+Warning: gmmktime(): Epoch doesn't fit in a PHP integer in %s on line %d
+bool(false)
--- /dev/null
+--TEST--
+Test gmmktime() function : usage variation - Passing positive and negative float values to arguments 64 bits.
+--SKIPIF--
+<?php
+if (PHP_INT_SIZE == 4) die('skip 64 bit only');
+?>
+--FILE--
+<?php
+echo "*** Testing gmmktime() : usage variation ***\n";
+
+//Initialise variables
+$hour = 8;
+$min = 8;
+$sec = 8;
+$mon = 8;
+$day = 8;
+$year = 2008;
+
+$inputs = array(
+
+ 'float 123456' => 123456,
+ 'float -123456' => -123456,
+ 'float -10.5' => -10.5,
+);
+
+// loop through each element of the array for min
+foreach($inputs as $key =>$value) {
+ echo "\n--$key--\n";
+ var_dump( gmmktime($value, $min, $sec, $mon, $day, $year) );
+ var_dump( gmmktime($hour, $value, $sec, $mon, $day, $year) );
+ var_dump( gmmktime($hour, $min, $value, $mon, $day, $year) );
+ var_dump( gmmktime($hour, $min, $sec, $value, $day, $year) );
+ var_dump( gmmktime($hour, $min, $sec, $mon, $value, $value) );
+}
+?>
+--EXPECT--
+ *** Testing gmmktime() : usage variation ***
+
+--float 123456--
+int(1662595688)
+int(1225589768)
+int(1218306336)
+int(325855037288)
+int(3844412784488)
+
+--float -123456--
+int(773712488)
+int(1210775048)
+int(1218059424)
+int(-323460834712)
+int(-3968710530712)
+
+--float -10.5--
+int(1218118088)
+int(1218181808)
+int(1218182870)
+int(1170922088)
+int(-62465356312)
date_default_timezone_set($tz);
foreach ($years as $year) {
printf("Y: %4d - ", $year);
- $ret = mktime(1, 1, 1, 1, 1, $year);
+ $ret = @mktime(1, 1, 1, 1, 1, $year);
if ($ret == FALSE) {
echo "out of range\n";
} else {
}
}
?>
---EXPECT--
+--EXPECTF--
string(31) "Fri, 23 May 1997 09:15:28 +0000"
string(31) "Sun, 31 Dec 2000 18:58:59 +0000"
+
+Warning: strtotime(): Epoch doesn't fit in a PHP integer in %s on line %d
bool(false)
}
?>
---EXPECT--
+--EXPECTF--
bool(false)
bool(false)
string(31) "Thu, 15 Jun 2006 00:00:00 +0100"
string(31) "Fri, 16 Jun 2006 23:49:12 +0100"
bool(false)
string(31) "Fri, 16 Jun 2006 02:22:00 +0100"
+
+Warning: strtotime(): Epoch doesn't fit in a PHP integer in %s on line %d
bool(false)
string(31) "Fri, 16 Jun 2006 02:22:33 +0100"
bool(false)
--TEST--
-timezone_identifiers_list: Test that correct notice is given when timezone_identifiers_list is given 4096 as parameter
+timezone_identifiers_list: ValueError when timezoneGroup is DateTimeZone::PER_COUNTRY
--CREDITS--
Havard Eide <nucleuz@gmail.com>
#PHPTestFest2009 Norway 2009-06-09 \o/
--INI--
-error_reporting=E_ALL
date.timezone=UTC
--FILE--
<?php
-print_r(timezone_identifiers_list(4096));
+try {
+ var_dump(timezone_identifiers_list(DateTimeZone::PER_COUNTRY));
+} catch (\ValueError $e) {
+ echo $e->getMessage() . \PHP_EOL;
+}
+try {
+ var_dump(timezone_identifiers_list(DateTimeZone::PER_COUNTRY, 'A'));
+} catch (\ValueError $e) {
+ echo $e->getMessage() . \PHP_EOL;
+}
?>
--EXPECTF--
-Notice: timezone_identifiers_list(): A two-letter ISO 3166-1 compatible country code is expected in %s on line %d
+timezone_identifiers_list(): Argument #2 ($countryCode) must be a two-letter ISO 3166-1 compatible country code when argument #1 ($timezoneGroup) is DateTimeZone::PER_COUNTRY
+timezone_identifiers_list(): Argument #2 ($countryCode) must be a two-letter ISO 3166-1 compatible country code when argument #1 ($timezoneGroup) is DateTimeZone::PER_COUNTRY
F1("timezone_name_from_abbr", MAY_BE_FALSE | MAY_BE_STRING),
F1("timezone_transitions_get", MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY),
F1("timezone_location_get", MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_STRING | MAY_BE_ARRAY_OF_DOUBLE | MAY_BE_ARRAY_OF_STRING),
- F1("timezone_identifiers_list", MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_STRING),
+ F1("timezone_identifiers_list", MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_STRING),
F1("timezone_abbreviations_list", MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_STRING | MAY_BE_ARRAY_OF_ARRAY),
F1("timezone_version_get", MAY_BE_STRING),
F1("date_interval_create_from_date_string", MAY_BE_FALSE | MAY_BE_OBJECT),