mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
- Reimplemented date and gmdate with new timelib code.
- Removed old date/gmdate implementations. - Moved date() related testcases to ext/date/tests. - Implemented bug #33452. - Fixed testcase for bug #27719 - there is no timezone called "EST5DST".
This commit is contained in:
parent
2e79463120
commit
e155585e6e
1
NEWS
1
NEWS
@ -3,6 +3,7 @@ PHP NEWS
|
||||
?? ??? 2005, PHP 5.1 Beta 3
|
||||
- Upgraded bundled SQLite library for PDO:SQLite to 3.2.2 (Ilia)
|
||||
- Added PDO_MYSQL_ATTR_USE_BUFFERED_QUERY parameter for pdo_mysql. (Ilia)
|
||||
- Implemented feature request #33452 (Year belonging to ISO week). (Derick)
|
||||
- Fixed bug #33491 (crash after extending MySQLi internal class). (Tony)
|
||||
- Fixed bug #33475 (cURL handle is not closed on curl_close(). (Ilia)
|
||||
- Fixed bug #33469 (Compile error undefined reference to ifx_checkAPI). (Jani)
|
||||
|
@ -41,10 +41,74 @@ timelib_sll timelib_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d)
|
||||
}
|
||||
c1 = century_value(y / 100);
|
||||
y1 = (y % 100);
|
||||
m1 = is_leap(y) ? m_table_leap[m] : m_table_common[m];
|
||||
m1 = timelib_is_leap(y) ? m_table_leap[m] : m_table_common[m];
|
||||
return (c1 + y1 + m1 + (y1 / 4) + d) % 7;
|
||||
}
|
||||
|
||||
/* jan feb mar apr may jun jul aug sep oct nov dec */
|
||||
static int d_table_common[13] = { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
|
||||
static int d_table_leap[13] = { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
|
||||
static int ml_table_common[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
static int ml_table_leap[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
timelib_sll timelib_day_of_year(timelib_sll y, timelib_sll m, timelib_sll d)
|
||||
{
|
||||
return (timelib_is_leap(y) ? d_table_leap[m] : d_table_common[m]) + d - 1;
|
||||
}
|
||||
|
||||
timelib_sll timelib_days_in_month(timelib_sll y, timelib_sll m)
|
||||
{
|
||||
return timelib_is_leap(y) ? ml_table_leap[m] : ml_table_common[m];
|
||||
}
|
||||
|
||||
void timelib_isoweek_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iw, timelib_sll *iy)
|
||||
{
|
||||
int y_leap, prev_y_leap, doy, jan1weekday, weekday;
|
||||
|
||||
y_leap = timelib_is_leap(y);
|
||||
prev_y_leap = timelib_is_leap(y-1);
|
||||
doy = timelib_day_of_year(y, m, d) + 1;
|
||||
if (y_leap && m > 2) {
|
||||
doy++;
|
||||
}
|
||||
jan1weekday = timelib_day_of_week(y, 1, 1);
|
||||
weekday = timelib_day_of_week(y, m, d);
|
||||
if (weekday == 0) weekday = 7;
|
||||
if (jan1weekday == 0) jan1weekday = 7;
|
||||
/* Find if Y M D falls in YearNumber Y-1, WeekNumber 52 or 53 */
|
||||
if (doy <= (8 - jan1weekday) && jan1weekday > 4) {
|
||||
*iy = y - 1;
|
||||
if (jan1weekday == 5 || (jan1weekday == 6 && prev_y_leap)) {
|
||||
*iw = 53;
|
||||
} else {
|
||||
*iw = 52;
|
||||
}
|
||||
} else {
|
||||
*iy = y;
|
||||
}
|
||||
/* 8. Find if Y M D falls in YearNumber Y+1, WeekNumber 1 */
|
||||
if (*iy == y) {
|
||||
int i;
|
||||
|
||||
i = y_leap ? 366 : 365;
|
||||
if ((i - doy) < (4 - weekday)) {
|
||||
*iy = y + 1;
|
||||
*iw = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* 9. Find if Y M D falls in YearNumber Y, WeekNumber 1 through 53 */
|
||||
if (*iy == y) {
|
||||
int j;
|
||||
|
||||
j = doy + (7 - weekday) + (jan1weekday - 1);
|
||||
*iw = j / 7;
|
||||
if (jan1weekday > 4) {
|
||||
*iw -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
timelib_sll timelib_daynr_from_weeknr(timelib_sll y, timelib_sll w, timelib_sll d)
|
||||
{
|
||||
timelib_sll dow, day;
|
||||
|
@ -193,7 +193,7 @@ static int tz_search(char *timezone, int left, int right)
|
||||
|
||||
mid = (left + right) / 2;
|
||||
|
||||
cmp = strcmp(timezone, timezonedb_idx[mid].id);
|
||||
cmp = strcasecmp(timezone, timezonedb_idx[mid].id);
|
||||
if (cmp < 0) {
|
||||
return tz_search(timezone, left, mid - 1);
|
||||
} else if (cmp > 0) {
|
||||
|
@ -36,7 +36,10 @@
|
||||
|
||||
/* From dow.c */
|
||||
timelib_sll timelib_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d);
|
||||
timelib_sll timelib_day_of_year(timelib_sll y, timelib_sll m, timelib_sll d);
|
||||
timelib_sll timelib_daynr_from_weeknr(timelib_sll y, timelib_sll w, timelib_sll d);
|
||||
timelib_sll timelib_days_in_month(timelib_sll y, timelib_sll m);
|
||||
void timelib_isoweek_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iw, timelib_sll *iy);
|
||||
|
||||
/* From parse_date.re */
|
||||
timelib_time *timelib_strtotime(char *s);
|
||||
|
@ -154,7 +154,7 @@ typedef struct timelib_time {
|
||||
#define DAYS_PER_YEAR 365
|
||||
#define DAYS_PER_LYEAR 366
|
||||
|
||||
#define is_leap(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
|
||||
#define timelib_is_leap(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
|
||||
|
||||
#define DEBUG(s) if (0) { s }
|
||||
|
||||
|
@ -101,8 +101,8 @@ typedef struct { char *id; unsigned int pos; } tzdb_idx; tzdb_idx timezonedb_idx
|
||||
{ "America/Eirunepe" , 0x006E07 },
|
||||
{ "America/El_Salvador" , 0x006EF3 },
|
||||
{ "America/Ensenada" , 0x006F5C },
|
||||
{ "America/Fortaleza" , 0x0072A8 },
|
||||
{ "America/Fort_Wayne" , 0x0073BC },
|
||||
{ "America/Fortaleza" , 0x0072A8 },
|
||||
{ "America/Glace_Bay" , 0x0074DA },
|
||||
{ "America/Godthab" , 0x0077FE },
|
||||
{ "America/Goose_Bay" , 0x007AA8 },
|
||||
@ -118,8 +118,8 @@ typedef struct { char *id; unsigned int pos; } tzdb_idx; tzdb_idx timezonedb_idx
|
||||
{ "America/Indiana/Indianapolis" , 0x008C96 },
|
||||
{ "America/Indiana/Knox" , 0x008DB4 },
|
||||
{ "America/Indiana/Marengo" , 0x008FD9 },
|
||||
{ "America/Indianapolis" , 0x00910B },
|
||||
{ "America/Indiana/Vevay" , 0x009229 },
|
||||
{ "America/Indianapolis" , 0x00910B },
|
||||
{ "America/Inuvik" , 0x0092ED },
|
||||
{ "America/Iqaluit" , 0x0095E4 },
|
||||
{ "America/Jamaica" , 0x0098D6 },
|
||||
@ -157,8 +157,8 @@ typedef struct { char *id; unsigned int pos; } tzdb_idx; tzdb_idx timezonedb_idx
|
||||
{ "America/Paramaribo" , 0x00E0B3 },
|
||||
{ "America/Phoenix" , 0x00E139 },
|
||||
{ "America/Port-au-Prince" , 0x00E1BB },
|
||||
{ "America/Porto_Acre" , 0x00E2C1 },
|
||||
{ "America/Port_of_Spain" , 0x00E3A3 },
|
||||
{ "America/Porto_Acre" , 0x00E2C1 },
|
||||
{ "America/Porto_Velho" , 0x00E3EC },
|
||||
{ "America/Puerto_Rico" , 0x00E4CE },
|
||||
{ "America/Rainy_River" , 0x00E51C },
|
||||
@ -294,8 +294,8 @@ typedef struct { char *id; unsigned int pos; } tzdb_idx; tzdb_idx timezonedb_idx
|
||||
{ "Atlantic/Madeira" , 0x01BB39 },
|
||||
{ "Atlantic/Reykjavik" , 0x01C027 },
|
||||
{ "Atlantic/South_Georgia" , 0x01C1D4 },
|
||||
{ "Atlantic/Stanley" , 0x01C20C },
|
||||
{ "Atlantic/St_Helena" , 0x01C4D4 },
|
||||
{ "Atlantic/Stanley" , 0x01C20C },
|
||||
{ "Australia/ACT" , 0x01C51D },
|
||||
{ "Australia/Adelaide" , 0x01C82E },
|
||||
{ "Australia/Brisbane" , 0x01CB3F },
|
||||
@ -323,8 +323,8 @@ typedef struct { char *id; unsigned int pos; } tzdb_idx; tzdb_idx timezonedb_idx
|
||||
{ "Brazil/West" , 0x01F809 },
|
||||
{ "Canada/Atlantic" , 0x01F8F5 },
|
||||
{ "Canada/Central" , 0x01FDD1 },
|
||||
{ "Canada/Eastern" , 0x0201D2 },
|
||||
{ "Canada/East-Saskatchewan" , 0x0206B6 },
|
||||
{ "Canada/Eastern" , 0x0201D2 },
|
||||
{ "Canada/Mountain" , 0x020833 },
|
||||
{ "Canada/Newfoundland" , 0x020B9D },
|
||||
{ "Canada/Pacific" , 0x0210BC },
|
||||
@ -341,35 +341,35 @@ typedef struct { char *id; unsigned int pos; } tzdb_idx; tzdb_idx timezonedb_idx
|
||||
{ "EST" , 0x0236C9 },
|
||||
{ "EST5EDT" , 0x0237E7 },
|
||||
{ "Etc/GMT" , 0x023CDA },
|
||||
{ "Etc/GMT0" , 0x023D12 },
|
||||
{ "Etc/GMT-0" , 0x023D4A },
|
||||
{ "Etc/GMT+0" , 0x023D82 },
|
||||
{ "Etc/GMT-1" , 0x023DBA },
|
||||
{ "Etc/GMT+1" , 0x023DF4 },
|
||||
{ "Etc/GMT-10" , 0x023E2E },
|
||||
{ "Etc/GMT+10" , 0x023E69 },
|
||||
{ "Etc/GMT-11" , 0x023EA4 },
|
||||
{ "Etc/GMT+11" , 0x023EDF },
|
||||
{ "Etc/GMT-12" , 0x023F1A },
|
||||
{ "Etc/GMT+12" , 0x023F55 },
|
||||
{ "Etc/GMT+2" , 0x024040 },
|
||||
{ "Etc/GMT+3" , 0x0240B4 },
|
||||
{ "Etc/GMT+4" , 0x024128 },
|
||||
{ "Etc/GMT+5" , 0x02419C },
|
||||
{ "Etc/GMT+6" , 0x024210 },
|
||||
{ "Etc/GMT+7" , 0x024284 },
|
||||
{ "Etc/GMT+8" , 0x0242F8 },
|
||||
{ "Etc/GMT+9" , 0x02436C },
|
||||
{ "Etc/GMT-0" , 0x023D4A },
|
||||
{ "Etc/GMT-1" , 0x023DBA },
|
||||
{ "Etc/GMT-10" , 0x023E2E },
|
||||
{ "Etc/GMT-11" , 0x023EA4 },
|
||||
{ "Etc/GMT-12" , 0x023F1A },
|
||||
{ "Etc/GMT-13" , 0x023F90 },
|
||||
{ "Etc/GMT-14" , 0x023FCB },
|
||||
{ "Etc/GMT-2" , 0x024006 },
|
||||
{ "Etc/GMT+2" , 0x024040 },
|
||||
{ "Etc/GMT-3" , 0x02407A },
|
||||
{ "Etc/GMT+3" , 0x0240B4 },
|
||||
{ "Etc/GMT-4" , 0x0240EE },
|
||||
{ "Etc/GMT+4" , 0x024128 },
|
||||
{ "Etc/GMT-5" , 0x024162 },
|
||||
{ "Etc/GMT+5" , 0x02419C },
|
||||
{ "Etc/GMT-6" , 0x0241D6 },
|
||||
{ "Etc/GMT+6" , 0x024210 },
|
||||
{ "Etc/GMT-7" , 0x02424A },
|
||||
{ "Etc/GMT+7" , 0x024284 },
|
||||
{ "Etc/GMT-8" , 0x0242BE },
|
||||
{ "Etc/GMT+8" , 0x0242F8 },
|
||||
{ "Etc/GMT-9" , 0x024332 },
|
||||
{ "Etc/GMT+9" , 0x02436C },
|
||||
{ "Etc/GMT0" , 0x023D12 },
|
||||
{ "Etc/Greenwich" , 0x0243A6 },
|
||||
{ "Etc/UCT" , 0x0243DE },
|
||||
{ "Etc/Universal" , 0x024416 },
|
||||
@ -432,9 +432,9 @@ typedef struct { char *id; unsigned int pos; } tzdb_idx; tzdb_idx timezonedb_idx
|
||||
{ "GB" , 0x02F8AF },
|
||||
{ "GB-Eire" , 0x02FDDA },
|
||||
{ "GMT" , 0x030305 },
|
||||
{ "GMT0" , 0x03033D },
|
||||
{ "GMT-0" , 0x030375 },
|
||||
{ "GMT+0" , 0x0303AD },
|
||||
{ "GMT-0" , 0x030375 },
|
||||
{ "GMT0" , 0x03033D },
|
||||
{ "Greenwich" , 0x0303E5 },
|
||||
{ "Hongkong" , 0x03041D },
|
||||
{ "HST" , 0x0305C7 },
|
||||
@ -519,8 +519,8 @@ typedef struct { char *id; unsigned int pos; } tzdb_idx; tzdb_idx timezonedb_idx
|
||||
{ "US/Aleutian" , 0x03590D },
|
||||
{ "US/Arizona" , 0x035C67 },
|
||||
{ "US/Central" , 0x035CE9 },
|
||||
{ "US/Eastern" , 0x0361E8 },
|
||||
{ "US/East-Indiana" , 0x0366DB },
|
||||
{ "US/Eastern" , 0x0361E8 },
|
||||
{ "US/Hawaii" , 0x0367F9 },
|
||||
{ "US/Indiana-Starke" , 0x03687B },
|
||||
{ "US/Michigan" , 0x036AA0 },
|
||||
@ -529,8 +529,8 @@ typedef struct { char *id; unsigned int pos; } tzdb_idx; tzdb_idx timezonedb_idx
|
||||
{ "US/Pacific-New" , 0x037531 },
|
||||
{ "US/Samoa" , 0x03792A },
|
||||
{ "UTC" , 0x0379A7 },
|
||||
{ "WET" , 0x0379DF },
|
||||
{ "W-SU" , 0x037C86 },
|
||||
{ "WET" , 0x0379DF },
|
||||
{ "Zulu" , 0x037FB5 },
|
||||
};
|
||||
/* This is a generated file, do not modify */
|
||||
|
@ -58,7 +58,7 @@ static int do_range_limit_days(timelib_sll *y, timelib_sll *m, timelib_sll *d)
|
||||
|
||||
do_range_limit(1, 13, 12, m, y);
|
||||
|
||||
leapyear = is_leap(*y);
|
||||
leapyear = timelib_is_leap(*y);
|
||||
days_this_month = leapyear ? days_in_month_leap[*m] : days_in_month[*m];
|
||||
last_month = (*m) - 1;
|
||||
|
||||
@ -68,7 +68,7 @@ static int do_range_limit_days(timelib_sll *y, timelib_sll *m, timelib_sll *d)
|
||||
} else {
|
||||
last_year = (*y);
|
||||
}
|
||||
leapyear = is_leap(last_year);
|
||||
leapyear = timelib_is_leap(last_year);
|
||||
days_last_month = leapyear ? days_in_month_leap[last_month] : days_in_month[last_month];
|
||||
|
||||
if (*d <= 0) {
|
||||
@ -138,7 +138,7 @@ static timelib_sll do_years(timelib_sll year)
|
||||
|
||||
if (year >= 1970) {
|
||||
for (i = year - 1; i >= 1970; i--) {
|
||||
if (is_leap(i)) {
|
||||
if (timelib_is_leap(i)) {
|
||||
res += (DAYS_PER_LYEAR * SECS_PER_DAY);
|
||||
} else {
|
||||
res += (DAYS_PER_YEAR * SECS_PER_DAY);
|
||||
@ -146,7 +146,7 @@ static timelib_sll do_years(timelib_sll year)
|
||||
}
|
||||
} else {
|
||||
for (i = 1969; i >= year; i--) {
|
||||
if (is_leap(i)) {
|
||||
if (timelib_is_leap(i)) {
|
||||
res -= (DAYS_PER_LYEAR * SECS_PER_DAY);
|
||||
} else {
|
||||
res -= (DAYS_PER_YEAR * SECS_PER_DAY);
|
||||
@ -158,7 +158,7 @@ static timelib_sll do_years(timelib_sll year)
|
||||
|
||||
static timelib_sll do_months(timelib_ull month, timelib_ull year)
|
||||
{
|
||||
if (is_leap(year)) {
|
||||
if (timelib_is_leap(year)) {
|
||||
return ((month_tab_leap[month - 1] + 1) * SECS_PER_DAY);
|
||||
} else {
|
||||
return ((month_tab[month - 1]) * SECS_PER_DAY);
|
||||
|
@ -63,7 +63,7 @@ void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts)
|
||||
tmp_days = days + 1;
|
||||
while (tmp_days >= DAYS_PER_LYEAR) {
|
||||
cur_year++;
|
||||
if (is_leap(cur_year)) {
|
||||
if (timelib_is_leap(cur_year)) {
|
||||
tmp_days -= DAYS_PER_LYEAR;
|
||||
} else {
|
||||
tmp_days -= DAYS_PER_YEAR;
|
||||
@ -82,7 +82,7 @@ void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts)
|
||||
while (tmp_days <= 0) {
|
||||
cur_year--;
|
||||
DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););
|
||||
if (is_leap(cur_year)) {
|
||||
if (timelib_is_leap(cur_year)) {
|
||||
tmp_days += DAYS_PER_LYEAR;
|
||||
} else {
|
||||
tmp_days += DAYS_PER_YEAR;
|
||||
@ -92,7 +92,7 @@ void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts)
|
||||
}
|
||||
DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year););
|
||||
|
||||
months = is_leap(cur_year) ? month_tab_leap : month_tab;
|
||||
months = timelib_is_leap(cur_year) ? month_tab_leap : month_tab;
|
||||
i = 11;
|
||||
while (i > 0) {
|
||||
DEBUG(printf("month=%lld (%d)\n", i, months[i]););
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include <time.h>
|
||||
|
||||
function_entry date_functions[] = {
|
||||
PHP_FE(date, NULL)
|
||||
PHP_FE(gmdate, NULL)
|
||||
PHP_FE(strtotime, NULL)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
@ -85,6 +87,198 @@ PHP_MINFO_FUNCTION(date)
|
||||
php_info_print_table_end();
|
||||
}
|
||||
|
||||
/* =[ Helper functions ] ================================================== */
|
||||
|
||||
static char* guess_timezone(TSRMLS_D)
|
||||
{
|
||||
char *env;
|
||||
|
||||
env = getenv("TZ");
|
||||
if (env) {
|
||||
return env;
|
||||
}
|
||||
/* Check config setting */
|
||||
if (DATEG(default_timezone)) {
|
||||
return DATEG(default_timezone);
|
||||
}
|
||||
return "GMT";
|
||||
}
|
||||
|
||||
/* =[ date() and gmdate() ]================================================ */
|
||||
#include "ext/standard/php_smart_str.h"
|
||||
|
||||
static char *mon_full_names[] = {
|
||||
"January", "February", "March", "April",
|
||||
"May", "June", "July", "August",
|
||||
"September", "October", "November", "December"
|
||||
};
|
||||
|
||||
static char *mon_short_names[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
static char *day_full_names[] = {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
|
||||
};
|
||||
|
||||
static char *day_short_names[] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
|
||||
static char *english_suffix(int number)
|
||||
{
|
||||
if (number >= 10 && number <= 19) {
|
||||
return "th";
|
||||
} else {
|
||||
switch (number % 10) {
|
||||
case 1: return "st";
|
||||
case 2: return "nd";
|
||||
case 3: return "rd";
|
||||
}
|
||||
}
|
||||
return "th";
|
||||
}
|
||||
|
||||
static char *php_format_date(char *format, int format_len, timelib_time *t, int localtime)
|
||||
{
|
||||
smart_str string = {0};
|
||||
int i;
|
||||
char buffer[33];
|
||||
timelib_time_offset *offset;
|
||||
timelib_sll isoweek, isoyear;
|
||||
|
||||
if (localtime) {
|
||||
offset = timelib_get_time_zone_info(t->sse, t->tz_info);
|
||||
}
|
||||
buffer[32] = '\0';
|
||||
timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear);
|
||||
|
||||
for (i = 0; i < format_len; i++) {
|
||||
switch (format[i]) {
|
||||
/* day */
|
||||
case 'd': snprintf(&buffer, 32, "%02d", (int) t->d); break;
|
||||
case 'D': snprintf(&buffer, 32, "%s", day_short_names[timelib_day_of_week(t->y, t->m, t->d)]); break;
|
||||
case 'j': snprintf(&buffer, 32, "%d", (int) t->d); break;
|
||||
case 'l': snprintf(&buffer, 32, "%s", day_full_names[timelib_day_of_week(t->y, t->m, t->d)]); break;
|
||||
case 'S': snprintf(&buffer, 32, "%s", english_suffix(t->d)); break;
|
||||
case 'w': snprintf(&buffer, 32, "%d", (int) timelib_day_of_week(t->y, t->m, t->d)); break;
|
||||
case 'z': snprintf(&buffer, 32, "%d", (int) timelib_day_of_year(t->y, t->m, t->d)); break;
|
||||
|
||||
/* week */
|
||||
case 'W': snprintf(&buffer, 32, "%d", (int) isoweek); break; /* iso weeknr */
|
||||
case 'o': snprintf(&buffer, 32, "%d", (int) isoyear); break; /* iso year */
|
||||
|
||||
/* month */
|
||||
case 'F': snprintf(&buffer, 32, "%s", mon_full_names[t->m - 1]); break;
|
||||
case 'm': snprintf(&buffer, 32, "%02d", (int) t->m); break;
|
||||
case 'M': snprintf(&buffer, 32, "%s", mon_short_names[t->m - 1]); break;
|
||||
case 'n': snprintf(&buffer, 32, "%d", (int) t->m); break;
|
||||
case 't': snprintf(&buffer, 32, "%d", (int) timelib_days_in_month(t->y, t->m)); break;
|
||||
|
||||
/* year */
|
||||
case 'L': snprintf(&buffer, 32, "%d", timelib_is_leap((int) t->y)); break;
|
||||
case 'y': snprintf(&buffer, 32, "%02d", (int) t->y % 100); break;
|
||||
case 'Y': snprintf(&buffer, 32, "%04d", (int) t->y); break;
|
||||
|
||||
/* time */
|
||||
case 'a': snprintf(&buffer, 32, "%s", t->h >= 12 ? "pm" : "am"); break;
|
||||
case 'A': snprintf(&buffer, 32, "%s", t->h >= 12 ? "PM" : "AM"); break;
|
||||
case 'B': snprintf(&buffer, 32, "[B unimplemented]"); break;
|
||||
case 'g': snprintf(&buffer, 32, "%d", (t->h % 12) ? (int) t->h % 12 : 12); break;
|
||||
case 'G': snprintf(&buffer, 32, "%d", (int) t->h); break;
|
||||
case 'h': snprintf(&buffer, 32, "%02d", (t->h % 12) ? (int) t->h % 12 : 12); break;
|
||||
case 'H': snprintf(&buffer, 32, "%02d", (int) t->h); break;
|
||||
case 'i': snprintf(&buffer, 32, "%02d", (int) t->i); break;
|
||||
case 's': snprintf(&buffer, 32, "%02d", (int) t->s); break;
|
||||
|
||||
/* timezone */
|
||||
case 'I': snprintf(&buffer, 32, "%d", localtime ? offset->is_dst : 0); break;
|
||||
case 'O': snprintf(&buffer, 32, "%c%02d%02d",
|
||||
localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
|
||||
localtime ? abs(offset->offset / 3600) : 0,
|
||||
localtime ? abs((offset->offset % 3600) / 60) : 0
|
||||
);
|
||||
break;
|
||||
case 'T': snprintf(&buffer, 32, "%s", localtime ? offset->abbr : "GMT"); break;
|
||||
case 'e': snprintf(&buffer, 32, "%s", localtime ? t->tz_info->name : "UTC"); break;
|
||||
case 'Z': snprintf(&buffer, 32, "%d", localtime ? offset->offset : 0); break;
|
||||
|
||||
/* full date/time */
|
||||
case 'c': snprintf(&buffer, 32, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
|
||||
(int) t->y, (int) t->m, (int) t->d,
|
||||
(int) t->h, (int) t->i, (int) t->s,
|
||||
localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
|
||||
localtime ? abs(offset->offset / 3600) : 0,
|
||||
localtime ? abs((offset->offset % 3600) / 60) : 0
|
||||
);
|
||||
break;
|
||||
case 'r': snprintf(&buffer, 32, "%3s, %02d %3s %04d %02d:%02d:%02d %c%02d%02d",
|
||||
day_short_names[timelib_day_of_week(t->y, t->m, t->d)],
|
||||
(int) t->d, mon_short_names[t->m - 1],
|
||||
(int) t->y, (int) t->h, (int) t->i, (int) t->s,
|
||||
localtime ? ((offset->offset < 0) ? '-' : '+') : '+',
|
||||
localtime ? abs(offset->offset / 3600) : 0,
|
||||
localtime ? abs((offset->offset % 3600) / 60) : 0
|
||||
);
|
||||
break;
|
||||
case 'U': snprintf(&buffer, 32, "%lld", (long long) t->sse); break;
|
||||
|
||||
case '\\': if (i < format_len) i++; buffer[0] = format[i]; buffer[1] = '\0'; break;
|
||||
|
||||
default: buffer[0] = format[i]; buffer[1] = '\0';
|
||||
}
|
||||
smart_str_appends(&string, buffer);
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
|
||||
smart_str_0(&string);
|
||||
|
||||
return string.c;
|
||||
}
|
||||
|
||||
static void php_date(INTERNAL_FUNCTION_PARAMETERS, int localtime)
|
||||
{
|
||||
char *format;
|
||||
int format_len;
|
||||
long ts = time(NULL);
|
||||
timelib_time *t;
|
||||
char *string;
|
||||
timelib_tzinfo *tzi;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &format, &format_len, &ts) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
t = timelib_time_ctor();
|
||||
|
||||
if (localtime) {
|
||||
tzi = timelib_parse_tzfile(guess_timezone());
|
||||
if (! tzi) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot find any timezone setting");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
timelib_unixtime2local(t, ts, tzi);
|
||||
} else {
|
||||
tzi = NULL;
|
||||
timelib_unixtime2gmt(t, ts);
|
||||
}
|
||||
string = php_format_date(format, format_len, t, localtime);
|
||||
|
||||
RETVAL_STRING(string, 0);
|
||||
timelib_time_dtor(t);
|
||||
}
|
||||
|
||||
PHP_FUNCTION(date)
|
||||
{
|
||||
php_date(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
||||
}
|
||||
|
||||
PHP_FUNCTION(gmdate)
|
||||
{
|
||||
php_date(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
||||
}
|
||||
|
||||
/* Backwards compability function */
|
||||
signed long php_parse_date(char *string, signed long *now)
|
||||
{
|
||||
timelib_time *parsed_time;
|
||||
@ -101,23 +295,6 @@ signed long php_parse_date(char *string, signed long *now)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static char* guess_timezone(TSRMLS_D)
|
||||
{
|
||||
char *env;
|
||||
|
||||
env = getenv("TZ");
|
||||
if (env) {
|
||||
return env;
|
||||
}
|
||||
if (DATEG(default_timezone)) {
|
||||
return DATEG(default_timezone);
|
||||
}
|
||||
/* Check config setting */
|
||||
/*
|
||||
*/
|
||||
return "GMT";
|
||||
}
|
||||
|
||||
|
||||
/* {{{ proto int strtotime(string time, int now)
|
||||
Convert string representation of date and time to a timestamp */
|
||||
|
@ -25,6 +25,8 @@ extern zend_module_entry date_module_entry;
|
||||
#define phpext_date_ptr &date_module_entry
|
||||
|
||||
PHP_FUNCTION(strtotime);
|
||||
PHP_FUNCTION(date);
|
||||
PHP_FUNCTION(gmdate);
|
||||
|
||||
PHP_MINIT_FUNCTION(date);
|
||||
PHP_MSHUTDOWN_FUNCTION(date);
|
||||
|
10
ext/date/tests/bug33452.phpt
Normal file
10
ext/date/tests/bug33452.phpt
Normal file
@ -0,0 +1,10 @@
|
||||
--TEST--
|
||||
Bug #33452 (Support for year accompanying ISO week nr)
|
||||
--FILE--
|
||||
<?php
|
||||
echo date('Y-W', strtotime('2005-1-1')), "\n";
|
||||
echo date('o-W', strtotime('2005-1-1')), "\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
2005-53
|
||||
2004-53
|
@ -179,9 +179,7 @@ function_entry basic_functions[] = {
|
||||
PHP_FE(gmstrftime, NULL)
|
||||
#endif
|
||||
|
||||
PHP_FE(date, NULL)
|
||||
PHP_FE(idate, NULL)
|
||||
PHP_FE(gmdate, NULL)
|
||||
PHP_FE(getdate, NULL)
|
||||
PHP_FE(localtime, NULL)
|
||||
PHP_FE(checkdate, NULL)
|
||||
|
@ -281,416 +281,6 @@ PHP_FUNCTION(gmmktime)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_date
|
||||
*/
|
||||
static void php_date(INTERNAL_FUNCTION_PARAMETERS, int gm)
|
||||
{
|
||||
pval **format, **timestamp;
|
||||
time_t the_time;
|
||||
struct tm *ta, tmbuf;
|
||||
int i, size = 0, length, h, beat, fd, wd, yd, wk;
|
||||
char tmp_buff[32];
|
||||
#if !HAVE_TM_GMTOFF
|
||||
long tzone;
|
||||
char *tname[2]= {"GMT Standard Time", "BST"};
|
||||
#endif
|
||||
|
||||
switch(ZEND_NUM_ARGS()) {
|
||||
case 1:
|
||||
if (zend_get_parameters_ex(1, &format) == FAILURE) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
the_time = time(NULL);
|
||||
break;
|
||||
case 2:
|
||||
if (zend_get_parameters_ex(2, &format, ×tamp) == FAILURE) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
convert_to_long_ex(timestamp);
|
||||
the_time = Z_LVAL_PP(timestamp);
|
||||
#ifdef PHP_WIN32
|
||||
if (the_time < 0) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Windows does not support dates prior to midnight (00:00:00), January 1, 1970");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
convert_to_string_ex(format);
|
||||
|
||||
if (gm) {
|
||||
ta = php_gmtime_r(&the_time, &tmbuf);
|
||||
#if !HAVE_TM_GMTOFF
|
||||
tzone = 0;
|
||||
#endif
|
||||
} else {
|
||||
ta = php_localtime_r(&the_time, &tmbuf);
|
||||
#if !HAVE_TM_GMTOFF
|
||||
#ifdef __CYGWIN__
|
||||
tzone = _timezone;
|
||||
#else
|
||||
tzone = timezone;
|
||||
#endif
|
||||
if (tzname[0] != NULL) {
|
||||
tname[0] = tzname[0];
|
||||
} else {
|
||||
tname[0] = "???";
|
||||
}
|
||||
|
||||
if (tzname[1] != NULL) {
|
||||
tname[1] = tzname[1];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!ta) { /* that really shouldn't happen... */
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected error");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
for (i = 0; i < Z_STRLEN_PP(format); i++) {
|
||||
switch (Z_STRVAL_PP(format)[i]) {
|
||||
case 'r': /* rfc822 format */
|
||||
size += 31;
|
||||
break;
|
||||
case 'c': /* iso8601 date (Dublin Core Date) */
|
||||
size += 25;
|
||||
break;
|
||||
case 'U': /* seconds since the epoch */
|
||||
size += 10;
|
||||
break;
|
||||
case 'F': /* month, textual, full */
|
||||
case 'l': /* day (of the week), textual */
|
||||
size += 28;
|
||||
break;
|
||||
case 'T': /* timezone name */
|
||||
#if HAVE_TM_ZONE
|
||||
size += strlen(ta->tm_zone);
|
||||
#elif HAVE_TZNAME
|
||||
if (ta->tm_isdst > 0 ) {
|
||||
size += strlen(tname[1]);
|
||||
} else {
|
||||
size += strlen(tname[0]);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 'Z': /* timezone offset in seconds */
|
||||
size += 6;
|
||||
break;
|
||||
case 'O': /* GMT offset in [+-]HHMM format */
|
||||
size += 5;
|
||||
break;
|
||||
case 'Y': /* year, numeric, 4 digits */
|
||||
size += 4;
|
||||
break;
|
||||
case 'M': /* month, textual, 3 letters */
|
||||
case 'D': /* day, textual, 3 letters */
|
||||
case 'z': /* day of the year, 1 to 366 */
|
||||
case 'B': /* Swatch Beat, 3 digits */
|
||||
size += 3;
|
||||
break;
|
||||
case 'y': /* year, numeric, 2 digits */
|
||||
case 'm': /* month, numeric */
|
||||
case 'n': /* month, numeric, no leading zeroes */
|
||||
case 'd': /* day of the month, numeric */
|
||||
case 'j': /* day of the month, numeric, no leading zeros */
|
||||
case 'H': /* hour, numeric, 24 hour format */
|
||||
case 'h': /* hour, numeric, 12 hour format */
|
||||
case 'G': /* hour, numeric, 24 hour format, no leading zeroes */
|
||||
case 'g': /* hour, numeric, 12 hour format, no leading zeroes */
|
||||
case 'i': /* minutes, numeric */
|
||||
case 's': /* seconds, numeric */
|
||||
case 'A': /* AM/PM */
|
||||
case 'a': /* am/pm */
|
||||
case 'S': /* standard english suffix for the day of the month (e.g. 3rd, 2nd, etc) */
|
||||
case 't': /* days in current month */
|
||||
case 'W': /* ISO-8601 week number of year, weeks starting on Monday */
|
||||
size += 2;
|
||||
break;
|
||||
case '\\':
|
||||
if (i < Z_STRLEN_PP(format) - 1) {
|
||||
i++;
|
||||
}
|
||||
size ++;
|
||||
break;
|
||||
case 'L': /* boolean for leap year */
|
||||
case 'w': /* day of the week, numeric */
|
||||
case 'I': /* DST? */
|
||||
default:
|
||||
size++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Z_STRVAL_P(return_value) = (char *) emalloc(size + 1);
|
||||
Z_STRVAL_P(return_value)[0] = '\0';
|
||||
|
||||
for (i = 0; i < Z_STRLEN_PP(format); i++) {
|
||||
switch (Z_STRVAL_PP(format)[i]) {
|
||||
case '\\':
|
||||
if (i < Z_STRLEN_PP(format) - 1) {
|
||||
char ch[2];
|
||||
ch[0]=Z_STRVAL_PP(format)[i + 1];
|
||||
ch[1]='\0';
|
||||
strcat(Z_STRVAL_P(return_value), ch);
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
case 'U': /* seconds since the epoch */
|
||||
sprintf(tmp_buff, "%ld", (long)the_time); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'F': /* month, textual, full */
|
||||
strcat(Z_STRVAL_P(return_value), mon_full_names[ta->tm_mon]);
|
||||
break;
|
||||
case 'l': /* day (of the week), textual, full */
|
||||
strcat(Z_STRVAL_P(return_value), day_full_names[ta->tm_wday]);
|
||||
break;
|
||||
case 'Y': /* year, numeric, 4 digits */
|
||||
sprintf(tmp_buff, "%d", ta->tm_year + YEAR_BASE); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'M': /* month, textual, 3 letters */
|
||||
strcat(Z_STRVAL_P(return_value), mon_short_names[ta->tm_mon]);
|
||||
break;
|
||||
case 'D': /* day (of the week), textual, 3 letters */
|
||||
strcat(Z_STRVAL_P(return_value), day_short_names[ta->tm_wday]);
|
||||
break;
|
||||
case 'z': /* day (of the year) */
|
||||
sprintf(tmp_buff, "%d", ta->tm_yday); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'y': /* year, numeric, 2 digits */
|
||||
sprintf(tmp_buff, "%02d", ((ta->tm_year)%100)); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'm': /* month, numeric */
|
||||
sprintf(tmp_buff, "%02d", ta->tm_mon + 1); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'n': /* month, numeric, no leading zeros */
|
||||
sprintf(tmp_buff, "%d", ta->tm_mon + 1); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'd': /* day of the month, numeric */
|
||||
sprintf(tmp_buff, "%02d", ta->tm_mday); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'j':
|
||||
sprintf(tmp_buff, "%d", ta->tm_mday); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'H': /* hour, numeric, 24 hour format */
|
||||
sprintf(tmp_buff, "%02d", ta->tm_hour); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'h': /* hour, numeric, 12 hour format */
|
||||
h = ta->tm_hour % 12; if (h==0) h = 12;
|
||||
sprintf(tmp_buff, "%02d", h); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'G': /* hour, numeric, 24 hour format, no leading zeros */
|
||||
sprintf(tmp_buff, "%d", ta->tm_hour); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'g': /* hour, numeric, 12 hour format, no leading zeros */
|
||||
h = ta->tm_hour % 12; if (h==0) h = 12;
|
||||
sprintf(tmp_buff, "%d", h); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'i': /* minutes, numeric */
|
||||
sprintf(tmp_buff, "%02d", ta->tm_min); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 's': /* seconds, numeric */
|
||||
sprintf(tmp_buff, "%02d", ta->tm_sec); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'A': /* AM/PM */
|
||||
strcat(Z_STRVAL_P(return_value), (ta->tm_hour >= 12 ? "PM" : "AM"));
|
||||
break;
|
||||
case 'a': /* am/pm */
|
||||
strcat(Z_STRVAL_P(return_value), (ta->tm_hour >= 12 ? "pm" : "am"));
|
||||
break;
|
||||
case 'S': /* standard english suffix, e.g. 2nd/3rd for the day of the month */
|
||||
if (ta->tm_mday >= 10 && ta->tm_mday <= 19) {
|
||||
strcat(Z_STRVAL_P(return_value), "th");
|
||||
} else {
|
||||
switch (ta->tm_mday % 10) {
|
||||
case 1:
|
||||
strcat(Z_STRVAL_P(return_value), "st");
|
||||
break;
|
||||
case 2:
|
||||
strcat(Z_STRVAL_P(return_value), "nd");
|
||||
break;
|
||||
case 3:
|
||||
strcat(Z_STRVAL_P(return_value), "rd");
|
||||
break;
|
||||
default:
|
||||
strcat(Z_STRVAL_P(return_value), "th");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 't': /* days in current month */
|
||||
sprintf(tmp_buff, "%2d", phpday_tab[isleap((ta->tm_year+YEAR_BASE))][ta->tm_mon] );
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'w': /* day of the week, numeric EXTENSION */
|
||||
sprintf(tmp_buff, "%01d", ta->tm_wday); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'O': /* GMT offset in [+-]HHMM format */
|
||||
#if HAVE_TM_GMTOFF
|
||||
sprintf(tmp_buff, "%c%02d%02d", (ta->tm_gmtoff < 0) ? '-' : '+', abs(ta->tm_gmtoff / 3600), abs( (ta->tm_gmtoff % 3600) / 60 ));
|
||||
#else
|
||||
sprintf(tmp_buff, "%c%02d%02d", ((ta->tm_isdst ? tzone - 3600:tzone)>0)?'-':'+', abs((ta->tm_isdst ? tzone - 3600 : tzone) / 3600), abs(((ta->tm_isdst ? tzone - 3600 : tzone) % 3600) / 60));
|
||||
#endif
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'Z': /* timezone offset in seconds */
|
||||
#if HAVE_TM_GMTOFF
|
||||
sprintf(tmp_buff, "%ld", ta->tm_gmtoff);
|
||||
#else
|
||||
sprintf(tmp_buff, "%ld", ta->tm_isdst ? -(tzone- 3600) : -tzone);
|
||||
#endif
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'L': /* boolean for leapyear */
|
||||
sprintf(tmp_buff, "%d", (isleap((ta->tm_year+YEAR_BASE)) ? 1 : 0 ) );
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'T': /* timezone name */
|
||||
#if HAVE_TM_ZONE
|
||||
strcat(Z_STRVAL_P(return_value), ta->tm_zone);
|
||||
#elif HAVE_TZNAME
|
||||
strcat(Z_STRVAL_P(return_value), ta->tm_isdst ? tname[1] : tname[0]);
|
||||
#endif
|
||||
break;
|
||||
case 'B': /* Swatch Beat a.k.a. Internet Time */
|
||||
beat = (((((long)the_time)-(((long)the_time) -
|
||||
((((long)the_time) % 86400) + 3600))) * 10) / 864);
|
||||
while (beat < 0) {
|
||||
beat += 1000;
|
||||
}
|
||||
beat = beat % 1000;
|
||||
sprintf(tmp_buff, "%03d", beat); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'I':
|
||||
sprintf(tmp_buff, "%d", ta->tm_isdst);
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'r':
|
||||
#if HAVE_TM_GMTOFF
|
||||
sprintf(tmp_buff, "%3s, %02d %3s %04d %02d:%02d:%02d %c%02d%02d",
|
||||
day_short_names[ta->tm_wday],
|
||||
ta->tm_mday,
|
||||
mon_short_names[ta->tm_mon],
|
||||
ta->tm_year + YEAR_BASE,
|
||||
ta->tm_hour,
|
||||
ta->tm_min,
|
||||
ta->tm_sec,
|
||||
(ta->tm_gmtoff < 0) ? '-' : '+',
|
||||
abs(ta->tm_gmtoff / 3600),
|
||||
abs( (ta->tm_gmtoff % 3600) / 60 )
|
||||
);
|
||||
#else
|
||||
sprintf(tmp_buff, "%3s, %02d %3s %04d %02d:%02d:%02d %c%02d%02d",
|
||||
day_short_names[ta->tm_wday],
|
||||
ta->tm_mday,
|
||||
mon_short_names[ta->tm_mon],
|
||||
ta->tm_year + YEAR_BASE,
|
||||
ta->tm_hour,
|
||||
ta->tm_min,
|
||||
ta->tm_sec,
|
||||
((ta->tm_isdst ? tzone - 3600 : tzone) > 0) ? '-' : '+',
|
||||
abs((ta->tm_isdst ? tzone - 3600 : tzone) / 3600),
|
||||
abs( ((ta->tm_isdst ? tzone - 3600 : tzone) % 3600) / 60 )
|
||||
);
|
||||
#endif
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'c':
|
||||
#if HAVE_TM_GMTOFF
|
||||
sprintf(tmp_buff, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
|
||||
ta->tm_year + YEAR_BASE,
|
||||
ta->tm_mon + 1,
|
||||
ta->tm_mday,
|
||||
ta->tm_hour,
|
||||
ta->tm_min,
|
||||
ta->tm_sec,
|
||||
(ta->tm_gmtoff < 0) ? '-' : '+',
|
||||
abs(ta->tm_gmtoff / 3600),
|
||||
abs( (ta->tm_gmtoff % 3600) / 60 )
|
||||
);
|
||||
#else
|
||||
sprintf(tmp_buff, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
|
||||
ta->tm_year + YEAR_BASE,
|
||||
ta->tm_mon + 1,
|
||||
ta->tm_mday,
|
||||
ta->tm_hour,
|
||||
ta->tm_min,
|
||||
ta->tm_sec,
|
||||
((ta->tm_isdst ? tzone - 3600 : tzone) > 0) ? '-' : '+',
|
||||
abs((ta->tm_isdst ? tzone - 3600 : tzone) / 3600),
|
||||
abs( ((ta->tm_isdst ? tzone - 3600 : tzone) % 3600) / 60 )
|
||||
);
|
||||
#endif
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
case 'W': /* ISO-8601 week number of year, weeks starting on Monday */
|
||||
wd = ta->tm_wday == 0 ? 6 : ta->tm_wday - 1; /* weekday */
|
||||
yd = ta->tm_yday + 1; /* days since January 1st */
|
||||
|
||||
fd = (7 + wd - yd % 7+ 1) % 7; /* weekday (1st January) */
|
||||
|
||||
/* week is a last year week (52 or 53) */
|
||||
if ((yd <= 7 - fd) && fd > 3){
|
||||
wk = (fd == 4 || (fd == 5 && isleap((ta->tm_year + YEAR_BASE - 1)))) ? 53 : 52;
|
||||
}
|
||||
/* week is a next year week (1) */
|
||||
else if (isleap((ta->tm_year+YEAR_BASE)) + 365 - yd < 3 - wd){
|
||||
wk = 1;
|
||||
}
|
||||
/* normal week */
|
||||
else {
|
||||
wk = (yd + 6 - wd + fd) / 7 - (fd > 3);
|
||||
}
|
||||
|
||||
sprintf(tmp_buff, "%d", wk); /* SAFE */
|
||||
strcat(Z_STRVAL_P(return_value), tmp_buff);
|
||||
break;
|
||||
|
||||
default:
|
||||
length = strlen(Z_STRVAL_P(return_value));
|
||||
Z_STRVAL_P(return_value)[length] = Z_STRVAL_PP(format)[i];
|
||||
Z_STRVAL_P(return_value)[length + 1] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
||||
Z_TYPE_P(return_value) = IS_STRING;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string date(string format [, int timestamp])
|
||||
Format a local time/date */
|
||||
PHP_FUNCTION(date)
|
||||
{
|
||||
php_date(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto string gmdate(string format [, int timestamp])
|
||||
Format a GMT/UTC date/time */
|
||||
PHP_FUNCTION(gmdate)
|
||||
{
|
||||
php_date(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ php_idate
|
||||
*/
|
||||
PHPAPI int php_idate(char format, int timestamp, int gm)
|
||||
|
@ -25,9 +25,7 @@
|
||||
PHP_FUNCTION(time);
|
||||
PHP_FUNCTION(mktime);
|
||||
PHP_FUNCTION(gmmktime);
|
||||
PHP_FUNCTION(date);
|
||||
PHP_FUNCTION(idate);
|
||||
PHP_FUNCTION(gmdate);
|
||||
PHP_FUNCTION(localtime);
|
||||
PHP_FUNCTION(getdate);
|
||||
PHP_FUNCTION(checkdate);
|
||||
|
@ -10,7 +10,7 @@ Bug #27719: mktime returns incorrect timestamp for dst days
|
||||
echo "$b ".date("m/d/y h:i:s\n",$b);
|
||||
echo "$c ".date("m/d/y h:i:s\n",$c);
|
||||
echo "\n";
|
||||
putenv("TZ=EST5DST"); // DST not in effect
|
||||
putenv("TZ=EST5EDT"); // DST not in effect
|
||||
$a = mktime(0, 0, 0, 2, 4, 2004, 0);
|
||||
$b = mktime(0, 0, 0, 2, 4, 2004, 1);
|
||||
$c = mktime(0, 0, 0, 2, 4, 2004, -1);
|
||||
@ -18,7 +18,7 @@ Bug #27719: mktime returns incorrect timestamp for dst days
|
||||
echo "$b ".date("m/d/y h:i:s\n",$b);
|
||||
echo "$c ".date("m/d/y h:i:s\n",$c);
|
||||
echo "\n";
|
||||
putenv("TZ=EST5DST"); // Just before DST changeover
|
||||
putenv("TZ=EST5EDT"); // Just before DST changeover
|
||||
$a = mktime(0, 0, 0, 4, 4, 2004, 0);
|
||||
$b = mktime(0, 0, 0, 4, 4, 2004, 1);
|
||||
$c = mktime(0, 0, 0, 4, 4, 2004, -1);
|
||||
@ -26,7 +26,7 @@ Bug #27719: mktime returns incorrect timestamp for dst days
|
||||
echo "$b ".date("m/d/y h:i:s\n",$b);
|
||||
echo "$c ".date("m/d/y h:i:s\n",$c);
|
||||
echo "\n";
|
||||
putenv("TZ=EST5DST"); // Just after DST changeover
|
||||
putenv("TZ=EST5EDT"); // Just after DST changeover
|
||||
$a = mktime(3, 0, 0, 4, 4, 2004, 0);
|
||||
$b = mktime(3, 0, 0, 4, 4, 2004, 1);
|
||||
$c = mktime(3, 0, 0, 4, 4, 2004, -1);
|
||||
@ -34,7 +34,7 @@ Bug #27719: mktime returns incorrect timestamp for dst days
|
||||
echo "$b ".date("m/d/y h:i:s\n",$b);
|
||||
echo "$c ".date("m/d/y h:i:s\n",$c);
|
||||
echo "\n";
|
||||
putenv("TZ=EST5DST"); // DST in effect
|
||||
putenv("TZ=EST5EDT"); // DST in effect
|
||||
$a = mktime(0, 0, 0, 6, 4, 2004, 0);
|
||||
$b = mktime(0, 0, 0, 6, 4, 2004, 1);
|
||||
$c = mktime(0, 0, 0, 6, 4, 2004, -1);
|
||||
|
Loading…
Reference in New Issue
Block a user