- Implemented Dmitry's const patch.
- Added support for "weekday" as relative item.
- Fixed bug #37368 (Incorrect timestamp returned for strtotime()).
This commit is contained in:
Derick Rethans 2006-05-14 17:36:05 +00:00
parent 4ab6eb3d19
commit 74dfa9f0ba
11 changed files with 14370 additions and 13917 deletions

1
NEWS
View File

@ -33,6 +33,7 @@ PHP NEWS
- Fixed bug #37392 (Unnecessary call to OCITransRollback() at the end of
request). (Tony)
- Fixed bug #37376 (fastcgi.c compile fail with gcc 2.95.4). (Ilia)
- Fixed bug #37368 (Incorrect timestamp returned for strtotime()). (Derick)
- Fixed bug #37348 (make PEAR install ignore open_basedir). (Ilia)
- Fixed bug #37313 (sigemptyset() used without including <signal.h>).
(jdolecek)

File diff suppressed because it is too large Load Diff

View File

@ -49,6 +49,7 @@
#define TIMELIB_MONTH 5
#define TIMELIB_YEAR 6
#define TIMELIB_WEEKDAY 7
#define TIMELIB_SPECIAL 8
#define EOI 257
#define TIME 258
@ -101,8 +102,9 @@ typedef unsigned char uchar;
#define TIMELIB_UNHAVE_TIME() { s->time->have_time = 0; s->time->h = 0; s->time->i = 0; s->time->s = 0; s->time->f = 0; }
#define TIMELIB_HAVE_DATE() { if (s->time->have_date) { add_error(s, "Double date specification"); timelib_string_free(str); return TIMELIB_ERROR; } else { s->time->have_date = 1; } }
#define TIMELIB_UNHAVE_DATE() { s->time->have_date = 0; s->time->d = 0; s->time->m = 0; s->time->y = 0; }
#define TIMELIB_HAVE_RELATIVE() { s->time->have_relative = 1; s->time->relative.weekday_behavior = 0; }
#define TIMELIB_HAVE_RELATIVE() { s->time->have_relative = 1; s->time->relative.weekday_behavior = 1; }
#define TIMELIB_HAVE_WEEKDAY_RELATIVE() { s->time->have_weekday_relative = 1; }
#define TIMELIB_HAVE_SPECIAL_RELATIVE() { s->time->have_special_relative = 1; }
#define TIMELIB_HAVE_TZ() { s->cur = cursor; if (s->time->have_zone) { add_warning(s, "Double timezone specification"); timelib_string_free(str); return TIMELIB_ERROR; } else { s->time->have_zone = 1; } }
#define TIMELIB_INIT s->cur = cursor; str = timelib_string(s); ptr = str
@ -143,7 +145,7 @@ typedef struct Scanner {
struct timelib_error_container *errors;
struct timelib_time *time;
timelib_tzdb *tzdb;
const timelib_tzdb *tzdb;
} Scanner;
typedef struct _timelib_lookup_table {
@ -161,17 +163,17 @@ typedef struct _timelib_relunit {
#define HOUR(a) (int)(a * 60)
/* The timezone table. */
static timelib_tz_lookup_table timelib_timezone_lookup[] = {
const static timelib_tz_lookup_table timelib_timezone_lookup[] = {
#include "timezonemap.h"
{ NULL, 0, 0, NULL },
};
static timelib_tz_lookup_table timelib_timezone_fallbackmap[] = {
const static timelib_tz_lookup_table timelib_timezone_fallbackmap[] = {
#include "fallbackmap.h"
{ NULL, 0, 0, NULL },
};
static timelib_tz_lookup_table timelib_timezone_utc[] = {
const static timelib_tz_lookup_table timelib_timezone_utc[] = {
{ "utc", 0, 0, "UTC" },
};
@ -214,6 +216,8 @@ static timelib_relunit const timelib_relunit_lookup[] = {
{ "sunday", TIMELIB_WEEKDAY, 0 },
{ "sun", TIMELIB_WEEKDAY, 0 },
{ "weekday", TIMELIB_SPECIAL, TIMELIB_SPECIAL_WEEKDAY },
{ "weekdays", TIMELIB_SPECIAL, TIMELIB_SPECIAL_WEEKDAY },
{ NULL, 0, 0 }
};
@ -602,14 +606,20 @@ static void timelib_set_relative(char **ptr, timelib_sll amount, int behavior, S
s->time->relative.weekday = relunit->multiplier;
s->time->relative.weekday_behavior = behavior;
break;
case TIMELIB_SPECIAL:
TIMELIB_HAVE_SPECIAL_RELATIVE();
TIMELIB_UNHAVE_TIME();
s->time->special.type = relunit->multiplier;
s->time->special.amount = amount;
}
}
static timelib_tz_lookup_table* zone_search(const char *word, long gmtoffset, int isdst)
const static timelib_tz_lookup_table* zone_search(const char *word, long gmtoffset, int isdst)
{
int first_found = 0;
timelib_tz_lookup_table *tp, *first_found_elem = NULL;
timelib_tz_lookup_table *fmp;
const timelib_tz_lookup_table *tp, *first_found_elem = NULL;
const timelib_tz_lookup_table *fmp;
if (strcasecmp("utc", word) == 0 || strcasecmp("gmt", word) == 0) {
return timelib_timezone_utc;
@ -648,7 +658,7 @@ static long timelib_lookup_zone(char **ptr, int *dst, char **tz_abbr, int *found
char *word;
char *begin = *ptr, *end;
long value = 0;
timelib_tz_lookup_table *tp;
const timelib_tz_lookup_table *tp;
while (**ptr != '\0' && **ptr != ')') {
++*ptr;
@ -670,7 +680,7 @@ static long timelib_lookup_zone(char **ptr, int *dst, char **tz_abbr, int *found
return value;
}
static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_found, timelib_tzdb *tzdb)
static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_found, const timelib_tzdb *tzdb)
{
timelib_tzinfo *res;
long retval = 0;
@ -788,7 +798,8 @@ daylz = "0" [1-9] | [1-2][0-9] | "3" [01];
dayfull = 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday';
dayabbr = 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun';
daytext = dayfull | dayabbr;
dayspecial = 'weekday' | 'weekdays';
daytext = dayfull | dayabbr | dayspecial;
monthfull = 'january' | 'february' | 'march' | 'april' | 'may' | 'june' | 'july' | 'august' | 'september' | 'october' | 'november' | 'december';
monthabbr = 'jan' | 'feb' | 'mar' | 'apr' | 'may' | 'jun' | 'jul' | 'aug' | 'sep' | 'sept' | 'oct' | 'nov' | 'dec';
@ -1328,6 +1339,9 @@ relativetext = reltextnumber space? reltextunit;
s->time->relative.i = 0 - s->time->relative.i;
s->time->relative.s = 0 - s->time->relative.s;
s->time->relative.weekday = 0 - s->time->relative.weekday;
if (s->time->have_special_relative && s->time->special.type == TIMELIB_SPECIAL_WEEKDAY) {
s->time->special.amount = 0 - s->time->special.amount;
}
TIMELIB_DEINIT;
return TIMELIB_AGO;
}
@ -1365,6 +1379,16 @@ relativetext = reltextnumber space? reltextunit;
return TIMELIB_RELATIVE;
}
monthfull | monthabbr
{
DEBUG_OUTPUT("monthtext");
TIMELIB_INIT;
TIMELIB_HAVE_DATE();
s->time->m = timelib_lookup_month((char **) &ptr);
TIMELIB_DEINIT;
return TIMELIB_DATE_TEXT;
}
tzcorrection | tz
{
int tz_not_found;
@ -1446,7 +1470,7 @@ relativetext = reltextnumber space? reltextunit;
/*!max:re2c */
timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container **errors, timelib_tzdb *tzdb)
timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container **errors, const timelib_tzdb *tzdb)
{
Scanner in;
int t;
@ -1551,7 +1575,7 @@ void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options)
char *timelib_timezone_id_from_abbr(const char *abbr, long gmtoffset, int isdst)
{
timelib_tz_lookup_table *tp;
const timelib_tz_lookup_table *tp;
tp = zone_search(abbr, gmtoffset, isdst);
if (tp) {
@ -1561,7 +1585,7 @@ char *timelib_timezone_id_from_abbr(const char *abbr, long gmtoffset, int isdst)
}
}
timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void)
const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void)
{
return timelib_timezone_lookup;
}

View File

@ -192,7 +192,7 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz)
}
}
static int tz_search(char *timezone, int left, int right, timelib_tzdb *tzdb)
static int tz_search(char *timezone, int left, int right, const timelib_tzdb *tzdb)
{
int mid, cmp;
@ -213,7 +213,7 @@ static int tz_search(char *timezone, int left, int right, timelib_tzdb *tzdb)
}
static int seek_to_tz_position(char **tzf, char *timezone, timelib_tzdb *tzdb)
static int seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb)
{
int pos;
@ -227,29 +227,29 @@ static int seek_to_tz_position(char **tzf, char *timezone, timelib_tzdb *tzdb)
return 1;
}
timelib_tzdb *timelib_builtin_db(void)
const timelib_tzdb *timelib_builtin_db(void)
{
return &timezonedb_builtin;
}
timelib_tzdb_index_entry *timelib_timezone_builtin_identifiers_list(int *count)
const timelib_tzdb_index_entry *timelib_timezone_builtin_identifiers_list(int *count)
{
*count = sizeof(timezonedb_idx_builtin) / sizeof(*timezonedb_idx_builtin);
return timezonedb_idx_builtin;
}
int timelib_timezone_id_is_valid(char *timezone, timelib_tzdb *tzdb)
int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb)
{
char *tzf;
return (seek_to_tz_position((char**) &tzf, timezone, tzdb));
unsigned char *tzf;
return (seek_to_tz_position((unsigned char**) &tzf, timezone, tzdb));
}
timelib_tzinfo *timelib_parse_tzfile(char *timezone, timelib_tzdb *tzdb)
timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb)
{
char *tzf;
const unsigned char *tzf;
timelib_tzinfo *tmp;
if (seek_to_tz_position((char**) &tzf, timezone, tzdb)) {
if (seek_to_tz_position((unsigned char**) &tzf, timezone, tzdb)) {
tmp = timelib_tzinfo_ctor(timezone);
read_header((char**) &tzf, tmp);

View File

@ -205,6 +205,13 @@ void timelib_dump_date(timelib_time *d, int options)
if (d->have_weekday_relative) {
printf(" / %d.%d", d->relative.weekday, d->relative.weekday_behavior);
}
if (d->have_special_relative) {
switch (d->special.type) {
case TIMELIB_SPECIAL_WEEKDAY:
printf(" / %lld weekday", d->special.amount);
break;
}
}
}
printf("\n");
}

View File

@ -26,6 +26,8 @@
#define TIMELIB_NONE 0x00
#define TIMELIB_OVERRIDE_TIME 0x01
#define TIMELIB_SPECIAL_WEEKDAY 0x01
#ifndef LONG_MAX
#define LONG_MAX 2147483647L
#endif
@ -51,10 +53,10 @@ 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, int len, timelib_error_container **errors, timelib_tzdb *tzdb);
timelib_time *timelib_strtotime(char *s, int len, timelib_error_container **errors, const timelib_tzdb *tzdb);
void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options);
char *timelib_timezone_id_from_abbr(const char *abbr, long gmtoffset, int isdst);
timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void);
const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void);
/* From tm2unixtime.c */
void timelib_update_ts(timelib_time* time, timelib_tzinfo* tzi);
@ -67,14 +69,14 @@ void timelib_update_from_sse(timelib_time *tm);
void timelib_set_timezone(timelib_time *t, timelib_tzinfo *tz);
/* From parse_tz.c */
int timelib_timezone_id_is_valid(char *timezone, timelib_tzdb *tzdb);
timelib_tzinfo *timelib_parse_tzfile(char *timezone, timelib_tzdb *tzdb);
int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb);
timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb);
int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz);
timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz);
timelib_sll timelib_get_current_offset(timelib_time *t);
void timelib_dump_tzinfo(timelib_tzinfo *tz);
timelib_tzdb *timelib_builtin_db(void);
timelib_tzdb_index_entry *timelib_timezone_builtin_identifiers_list(int *count);
const timelib_tzdb *timelib_builtin_db(void);
const timelib_tzdb_index_entry *timelib_timezone_builtin_identifiers_list(int *count);
/* From timelib.c */
timelib_tzinfo* timelib_tzinfo_ctor();

View File

@ -125,6 +125,11 @@ typedef struct timelib_time_offset {
timelib_sll transistion_time;
} timelib_time_offset;
typedef struct timelib_special {
unsigned int type;
timelib_sll amount;
} timelib_special;
typedef struct timelib_time {
timelib_sll y, m, d; /* Year, Month, Day */
timelib_sll h, i, s; /* Hour, mInute, Second */
@ -134,10 +139,11 @@ typedef struct timelib_time {
timelib_tzinfo *tz_info; /* Timezone structure */
signed int dst; /* Flag if we were parsing a DST zone */
timelib_rel_time relative;
timelib_special special;
timelib_sll sse; /* Seconds since epoch */
unsigned int have_time, have_date, have_zone, have_relative, have_weekday_relative, have_weeknr_day;
unsigned int have_time, have_date, have_zone, have_relative, have_weekday_relative, have_special_relative, have_weeknr_day;
unsigned int sse_uptodate; /* !0 if the sse member is up to date with the date/time members */
unsigned int tim_uptodate; /* !0 if the date/time members are up to date with the sse member */
@ -173,17 +179,17 @@ typedef struct _timelib_tzdb_index_entry {
} timelib_tzdb_index_entry;
typedef struct _timelib_tzdb {
char *version;
int index_size;
timelib_tzdb_index_entry *index;
char *data;
char *version;
int index_size;
const timelib_tzdb_index_entry *index;
const unsigned char *data;
} timelib_tzdb;
#define TIMELIB_ZONETYPE_OFFSET 1
#define TIMELIB_ZONETYPE_ABBR 2
#define TIMELIB_ZONETYPE_ID 3
#define SECS_PER_ERA 12622780800L
#define SECS_PER_ERA 12622780800LL
#define SECS_PER_DAY 86400
#define DAYS_PER_YEAR 365
#define DAYS_PER_LYEAR 366

View File

@ -1,4 +1,4 @@
timelib_tzdb_index_entry timezonedb_idx_builtin[538] = {
const timelib_tzdb_index_entry timezonedb_idx_builtin[538] = {
{ "Africa/Abidjan" , 0x000000 },
{ "Africa/Accra" , 0x000049 },
{ "Africa/Addis_Ababa" , 0x0000E5 },
@ -539,7 +539,7 @@ timelib_tzdb_index_entry timezonedb_idx_builtin[538] = {
{ "Zulu" , 0x03904E },
};
/* This is a generated file, do not modify */
unsigned char timelib_timezone_db_data_builtin[233606] = {
const unsigned char timelib_timezone_db_data_builtin[233606] = {
/* Africa/Abidjan */
@ -16492,4 +16492,4 @@ unsigned char timelib_timezone_db_data_builtin[233606] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x55, 0x54, 0x43, 0x00, 0x00, 0x00, };
timelib_tzdb timezonedb_builtin = { "2006.1", 538, timezonedb_idx_builtin, timelib_timezone_db_data_builtin };
const timelib_tzdb timezonedb_builtin = { "2006.1", 538, timezonedb_idx_builtin, timelib_timezone_db_data_builtin };

View File

@ -113,6 +113,11 @@ static void do_normalize(timelib_time* time)
static void do_adjust_relative(timelib_time* time)
{
if (time->have_weekday_relative) {
do_adjust_for_weekday(time);
}
do_normalize(time);
if (time->have_relative) {
time->s += time->relative.s;
time->i += time->relative.i;
@ -124,11 +129,53 @@ static void do_adjust_relative(timelib_time* time)
}
do_normalize(time);
if (time->have_weekday_relative) {
do_adjust_for_weekday(time);
memset(&(time->relative), 0, sizeof(time->relative));
}
static void do_adjust_special_weekday(timelib_time* time)
{
timelib_sll current_dow, this_weekday = 0, count;
current_dow = timelib_day_of_week(time->y, time->m, time->d);
count = time->special.amount;
if (count == 0) {
if (current_dow == 6) {
this_weekday = 2;
}
if (current_dow == 0) {
this_weekday = 1;
}
time->d += this_weekday;
return;
} else if (count > 0) {
if (current_dow == 5) {
this_weekday = 2;
}
if (current_dow == 6) {
this_weekday = 1;
}
} else if (count < 0) {
if (current_dow == 0) {
this_weekday = -1;
}
if (current_dow == 1) {
this_weekday = -2;
}
}
time->d += this_weekday + ((count / 5) * 7) + (count % 5);
}
static void do_adjust_special(timelib_time* time)
{
if (time->have_special_relative) {
switch (time->special.type) {
case TIMELIB_SPECIAL_WEEKDAY:
do_adjust_special_weekday(time);
break;
}
}
do_normalize(time);
memset(&(time->relative), 0, sizeof(time->relative));
memset(&(time->special), 0, sizeof(time->special));
}
static timelib_sll do_years(timelib_sll year)
@ -247,6 +294,7 @@ void timelib_update_ts(timelib_time* time, timelib_tzinfo* tzi)
timelib_sll res = 0;
do_adjust_relative(time);
do_adjust_special(time);
res += do_years(time->y);
res += do_months(time->m, time->y);
res += do_days(time->d);

View File

@ -106,7 +106,7 @@ zend_function_entry date_funcs_timezone[] = {
static void date_register_classes(TSRMLS_D);
#endif
static char* guess_timezone(timelib_tzdb *tzdb TSRMLS_DC);
static char* guess_timezone(const timelib_tzdb *tzdb TSRMLS_DC);
/* }}} */
ZEND_DECLARE_MODULE_GLOBALS(date)
@ -298,7 +298,7 @@ PHP_MSHUTDOWN_FUNCTION(date)
/* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(date)
{
timelib_tzdb *tzdb = DATE_TIMEZONEDB;
const timelib_tzdb *tzdb = DATE_TIMEZONEDB;
php_info_print_table_start();
php_info_print_table_row(2, "date/time support", "enabled");
@ -312,7 +312,7 @@ PHP_MINFO_FUNCTION(date)
/* }}} */
/* {{{ Timezone Cache functions */
static timelib_tzinfo *php_date_parse_tzfile(char *formal_tzname, timelib_tzdb *tzdb TSRMLS_DC)
static timelib_tzinfo *php_date_parse_tzfile(char *formal_tzname, const timelib_tzdb *tzdb TSRMLS_DC)
{
timelib_tzinfo *tzi, **ptzi;
@ -329,7 +329,7 @@ static timelib_tzinfo *php_date_parse_tzfile(char *formal_tzname, timelib_tzdb *
/* }}} */
/* {{{ Helper functions */
static char* guess_timezone(timelib_tzdb *tzdb TSRMLS_DC)
static char* guess_timezone(const timelib_tzdb *tzdb TSRMLS_DC)
{
char *env;
@ -783,7 +783,7 @@ PHP_FUNCTION(idate)
/* {{{ php_date_set_tzdb - NOT THREADSAFE */
PHPAPI void php_date_set_tzdb(timelib_tzdb *tzdb)
{
timelib_tzdb *builtin = timelib_builtin_db();
const timelib_tzdb *builtin = timelib_builtin_db();
if (php_version_compare(tzdb->version, builtin->version) > 0) {
php_date_global_timezone_db = tzdb;
@ -1708,9 +1708,9 @@ PHP_FUNCTION(timezone_transistions_get)
PHP_FUNCTION(timezone_identifiers_list)
{
timelib_tzdb *tzdb;
timelib_tzdb_index_entry *table;
int i, item_count;
const timelib_tzdb *tzdb;
const timelib_tzdb_index_entry *table;
int i, item_count;
tzdb = DATE_TIMEZONEDB;
item_count = tzdb->index_size;
@ -1725,8 +1725,8 @@ PHP_FUNCTION(timezone_identifiers_list)
PHP_FUNCTION(timezone_abbreviations_list)
{
timelib_tz_lookup_table *table, *entry;
zval *element, **abbr_array_pp, *abbr_array;
const timelib_tz_lookup_table *table, *entry;
zval *element, **abbr_array_pp, *abbr_array;
table = timelib_timezone_abbreviations_list();
array_init(return_value);

View File

@ -0,0 +1,10 @@
--TEST--
Bug #37368 (Incorrect timestamp returned for strtotime()).
--INI--
date.timezone=UTC
--FILE--
<?php
echo date("r", strtotime("Mon, 08 May 2006 13:06:44 -0400 +30 days"));
?>
--EXPECT--
Wed, 07 Jun 2006 17:06:44 +0000