Skip to content

Commit 3c15cf1

Browse files
authored
Add support for -1 as valid year for idate() output. (#22657)
* Add support for -1 as valid year for idate() output. Closes GH-13273 * Simplify error handling * Add note in UPGRADING.INTERNALS about API change
1 parent 34951bf commit 3c15cf1

4 files changed

Lines changed: 37 additions & 29 deletions

File tree

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ PHP NEWS
2020
an error). (Derick)
2121
. Fixed Unix timestamps in February of the year 0 are misparsed with
2222
@-notation. (LukasGelbmann)
23+
. Fixed bug GH-11368 (idate() doesn't work for the year -1). (Derick)
2324

2425
- DBA:
2526
. Fixed OOB read on malformed length field in dba flatfile handler. (alhudz)

UPGRADING.INTERNALS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ PHP 8.6 INTERNALS UPGRADE NOTES
169169
3. Module changes
170170
========================
171171

172+
- ext/date:
173+
. php_idate() now returns the result state, and moves the return value into an
174+
out parameter.
175+
172176
- ext/mbstring:
173177
. Added GB18030-2022 to default encoding list for zh-CN.
174178

ext/date/php_date.c

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -901,13 +901,13 @@ PHPAPI zend_string *php_format_date(const char *format, size_t format_len, time_
901901
/* }}} */
902902

903903
/* {{{ php_idate */
904-
PHPAPI int php_idate(char format, time_t ts, bool localtime)
904+
PHPAPI bool php_idate(char format, time_t ts, bool localtime, int *result)
905905
{
906906
timelib_time *t;
907907
timelib_tzinfo *tzi;
908-
int retval = -1;
909908
timelib_time_offset *offset = NULL;
910909
timelib_sll isoweek, isoyear;
910+
bool success = true;
911911

912912
t = timelib_time_ctor();
913913

@@ -947,54 +947,57 @@ PHPAPI int php_idate(char format, time_t ts, bool localtime)
947947

948948
switch (format) {
949949
/* day */
950-
case 'd': case 'j': retval = (int) t->d; break;
950+
case 'd': case 'j': *result = (int) t->d; break;
951951

952-
case 'N': retval = (int) timelib_iso_day_of_week(t->y, t->m, t->d); break;
953-
case 'w': retval = (int) timelib_day_of_week(t->y, t->m, t->d); break;
954-
case 'z': retval = (int) timelib_day_of_year(t->y, t->m, t->d); break;
952+
case 'N': *result = (int) timelib_iso_day_of_week(t->y, t->m, t->d); break;
953+
case 'w': *result = (int) timelib_day_of_week(t->y, t->m, t->d); break;
954+
case 'z': *result = (int) timelib_day_of_year(t->y, t->m, t->d); break;
955955

956956
/* week */
957-
case 'W': retval = (int) isoweek; break; /* iso weeknr */
957+
case 'W': *result = (int) isoweek; break; /* iso weeknr */
958958

959959
/* month */
960-
case 'm': case 'n': retval = (int) t->m; break;
961-
case 't': retval = (int) timelib_days_in_month(t->y, t->m); break;
960+
case 'm': case 'n': *result = (int) t->m; break;
961+
case 't': *result = (int) timelib_days_in_month(t->y, t->m); break;
962962

963963
/* year */
964-
case 'L': retval = (int) timelib_is_leap((int) t->y); break;
965-
case 'y': retval = (int) (t->y % 100); break;
966-
case 'Y': retval = (int) t->y; break;
967-
case 'o': retval = (int) isoyear; break; /* iso year */
964+
case 'L': *result = (int) timelib_is_leap((int) t->y); break;
965+
case 'y': *result = (int) (t->y % 100); break;
966+
case 'Y': *result = (int) t->y; break;
967+
case 'o': *result = (int) isoyear; break; /* iso year */
968968

969969
/* Swatch Beat a.k.a. Internet Time */
970970
case 'B':
971-
retval = ((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10);
972-
if (retval < 0) {
973-
retval += 864000;
971+
*result = ((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10);
972+
if (*result < 0) {
973+
*result += 864000;
974974
}
975975
/* Make sure to do this on a positive int to avoid rounding errors */
976-
retval = (retval / 864) % 1000;
976+
*result = (*result / 864) % 1000;
977977
break;
978978

979979
/* time */
980-
case 'g': case 'h': retval = (int) ((t->h % 12) ? (int) t->h % 12 : 12); break;
981-
case 'H': case 'G': retval = (int) t->h; break;
982-
case 'i': retval = (int) t->i; break;
983-
case 's': retval = (int) t->s; break;
980+
case 'g': case 'h': *result = (int) ((t->h % 12) ? (int) t->h % 12 : 12); break;
981+
case 'H': case 'G': *result = (int) t->h; break;
982+
case 'i': *result = (int) t->i; break;
983+
case 's': *result = (int) t->s; break;
984984

985985
/* timezone */
986-
case 'I': retval = (int) (!localtime ? offset->is_dst : 0); break;
987-
case 'Z': retval = (int) (!localtime ? offset->offset : 0); break;
986+
case 'I': *result = (int) (!localtime ? offset->is_dst : 0); break;
987+
case 'Z': *result = (int) (!localtime ? offset->offset : 0); break;
988988

989-
case 'U': retval = (int) t->sse; break;
989+
case 'U': *result = (int) t->sse; break;
990+
991+
default:
992+
success = false;
990993
}
991994

992995
if (!localtime) {
993996
timelib_time_offset_dtor(offset);
994997
}
995998
timelib_time_dtor(t);
996999

997-
return retval;
1000+
return success;
9981001
}
9991002
/* }}} */
10001003

@@ -1018,7 +1021,7 @@ PHP_FUNCTION(idate)
10181021
zend_string *format;
10191022
zend_long ts;
10201023
bool ts_is_null = 1;
1021-
int ret;
1024+
int ret = 0;
10221025

10231026
ZEND_PARSE_PARAMETERS_START(1, 2)
10241027
Z_PARAM_STR(format)
@@ -1035,8 +1038,8 @@ PHP_FUNCTION(idate)
10351038
ts = php_time();
10361039
}
10371040

1038-
ret = php_idate(ZSTR_VAL(format)[0], ts, 0);
1039-
if (ret == -1) {
1041+
bool ok = php_idate(ZSTR_VAL(format)[0], ts, 0, &ret);
1042+
if (!ok) {
10401043
php_error_docref(NULL, E_WARNING, "Unrecognized date format token");
10411044
RETURN_FALSE;
10421045
}

ext/date/php_date.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ PHPAPI time_t php_time(void);
124124
/* Backwards compatibility wrapper */
125125
PHPAPI zend_long php_parse_date(const char *string, zend_long *now);
126126
PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, bool gmt);
127-
PHPAPI int php_idate(char format, time_t ts, bool localtime);
127+
PHPAPI bool php_idate(char format, time_t ts, bool localtime, int *result);
128128

129129
#define _php_strftime php_strftime
130130

0 commit comments

Comments
 (0)