ID: 8828 Updated by: derick Reported By: [EMAIL PROTECTED] Old-Status: Open Status: Duplicate Bug Type: Date/time related Operating system: PHP Version: 4.0.4pl1 Assigned To: Comments: Dup of #10686 Previous Comments: --------------------------------------------------------------------------- [2001-04-16 03:20:21] [EMAIL PROTECTED] Now for tm_mon < 0, too: *** ext/standard/datetime.c.orig Fri Dec 8 12:38:02 2000 --- ext/standard/datetime.c Sun Apr 15 17:28:46 2001 *************** *** 81,87 **** struct tm *ta, tmbuf; time_t t; int i, gmadjust, seconds, arg_count = ZEND_NUM_ARGS(); ! int is_dst = -1; if (arg_count > 7 || zend_get_parameters_array_ex(arg_count,arguments) == FAILURE) { WRONG_PARAM_COUNT; --- 81,87 ---- struct tm *ta, tmbuf; time_t t; int i, gmadjust, seconds, arg_count = ZEND_NUM_ARGS(); ! int is_dst = -1, val, chgsecs = 0; if (arg_count > 7 || zend_get_parameters_array_ex(arg_count,arguments) == FAILURE) { WRONG_PARAM_COUNT; *************** *** 148,172 **** - (((*arguments[5])->value.lval > 1000) ? 1900 : 0); /* fall-through */ case 5: ! ta->tm_mday = (*arguments[4])->value.lval; /* fall-through */ case 4: ! ta->tm_mon = (*arguments[3])->value.lval - 1; /* fall-through */ case 3: ! ta->tm_sec = (*arguments[2])->value.lval; /* fall-through */ case 2: ! ta->tm_min = (*arguments[1])->value.lval; /* fall-through */ case 1: ! ta->tm_hour = (*arguments[0])->value.lval; /* fall-through */ case 0: break; } ! seconds = mktime(ta); if (is_dst == -1) is_dst = ta->tm_isdst; --- 148,182 ---- - (((*arguments[5])->value.lval > 1000) ? 1900 : 0); /* fall-through */ case 5: ! val = (*arguments[4])->value.lval; ! if (val < 1) { chgsecs += (1-val) * 60*60*24; val = 1; } ! ta->tm_mday = val; /* fall-through */ case 4: ! val = (*arguments[3])->value.lval - 1; ! while (val < 0) { val += 12; ta->tm_year--; } ! ta->tm_mon = val; /* fall-through */ case 3: ! val = (*arguments[2])->value.lval; ! if (val < 1) { chgsecs += (1-val); val = 1; } ! ta->tm_sec = val; /* fall-through */ case 2: ! val = (*arguments[1])->value.lval; ! if (val < 1) { chgsecs += (1-val) * 60; val = 1; } ! ta->tm_min = val; /* fall-through */ case 1: ! val = (*arguments[0])->value.lval; ! if (val < 1) { chgsecs += (1-val) * 60*60; val = 1; } ! ta->tm_hour = val; /* fall-through */ case 0: break; } ! seconds = mktime(ta) - chgsecs; if (is_dst == -1) is_dst = ta->tm_isdst; --------------------------------------------------------------------------- [2001-04-15 10:59:06] [EMAIL PROTECTED] FIRST patch to make php_mktime() more compatible [i think it is not complete for the whole PHP4-project]. It includes a time correction for values less then 1 on "mday", "hour", "min", "sec". NOT on "mon"!! *** ext/standard/datetime.c.orig Fri Dec 8 12:38:02 2000 --- ext/standard/datetime.c Sun Apr 15 16:42:37 2001 *************** *** 81,87 **** struct tm *ta, tmbuf; time_t t; int i, gmadjust, seconds, arg_count = ZEND_NUM_ARGS(); ! int is_dst = -1; if (arg_count > 7 || zend_get_parameters_array_ex(arg_count,arguments) == FAILURE) { WRONG_PARAM_COUNT; --- 81,87 ---- struct tm *ta, tmbuf; time_t t; int i, gmadjust, seconds, arg_count = ZEND_NUM_ARGS(); ! int is_dst = -1, val, chgsecs = 0; if (arg_count > 7 || zend_get_parameters_array_ex(arg_count,arguments) == FAILURE) { WRONG_PARAM_COUNT; *************** *** 148,172 **** - (((*arguments[5])->value.lval > 1000) ? 1900 : 0); /* fall-through */ case 5: ! ta->tm_mday = (*arguments[4])->value.lval; /* fall-through */ case 4: ta->tm_mon = (*arguments[3])->value.lval - 1; /* fall-through */ case 3: ! ta->tm_sec = (*arguments[2])->value.lval; /* fall-through */ case 2: ! ta->tm_min = (*arguments[1])->value.lval; /* fall-through */ case 1: ! ta->tm_hour = (*arguments[0])->value.lval; /* fall-through */ case 0: break; } ! seconds = mktime(ta); if (is_dst == -1) is_dst = ta->tm_isdst; --- 148,180 ---- - (((*arguments[5])->value.lval > 1000) ? 1900 : 0); /* fall-through */ case 5: ! val = (*arguments[4])->value.lval; ! if (val < 1) { chgsecs += (1-val) * 60*60*24; val = 1; } ! ta->tm_mday = val; /* fall-through */ case 4: ta->tm_mon = (*arguments[3])->value.lval - 1; /* fall-through */ case 3: ! val = (*arguments[2])->value.lval; ! if (val < 1) { chgsecs += (1-val); val = 1; } ! ta->tm_sec = val; /* fall-through */ case 2: ! val = (*arguments[1])->value.lval; ! if (val < 1) { chgsecs += (1-val) * 60; val = 1; } ! ta->tm_min = val; /* fall-through */ case 1: ! val = (*arguments[0])->value.lval; ! if (val < 1) { chgsecs += (1-val) * 60*60; val = 1; } ! ta->tm_hour = val; /* fall-through */ case 0: break; } ! seconds = mktime(ta) - chgsecs; if (is_dst == -1) is_dst = ta->tm_isdst; --------------------------------------------------------------------------- [2001-03-14 15:56:42] [EMAIL PROTECTED] I was incorrect, This is not a part of C99(ANSI/ISO/IEC9899-1999) this is just implemented in Solaris, Linux, Irix, and possibly a few others. -Jason --------------------------------------------------------------------------- [2001-03-14 13:34:47] [EMAIL PROTECTED] This actually is part of the Ansi C standard. Solaris 8 manpage ----------------------- The original values of the components may be either greater than or less than the specified range. For example, a tm_hour of -1 means 1 hour before midnight, tm_mday of 0 means the day preceding the current month, and tm_mon of -2 means 2 months before January of tm_year --------------------------------------- Alg from c standard ---------------------------------------- #define QUOT(a,b) ((a)>0 ? (a)/(b) : -(((b)-(a)-1)/(b))) #define REM(a,b) ((a)-(b)*QUOT(a,b)) SS = tm_hour*3600 + tm_min*60 + tm_sec + (tm_leapsecs == _NO_LEAP_SECONDS ? X1 : tm_leapsecs) - (tm_zone == _LOCALTIME ? X2 : tm_zone) * 60; // X1 is the appropriate number of leap seconds, determined by // the implementation, or 0 if it cannot be determined. // X2 is the appropriate offset from local time to UTC, // determined by the implementation, or // (tm_isdst >= 0 ? tm_isdst : 0) // if the offset cannot be determined M = REM(tm_mon, 12); Y = tm_year + 1900 + QUOT(tm_mon, 12); Z = Y - (M < 2 ? 1 : 0); D = Y*365 + (Z/400)*97 + (Z%400)/4 + M[(int []){0,31,59,90,120,151,181,212,243,273, 304,335}] + tm_mday + QUOT(SS, 86400); S = REM(SS, 86400); ------------------------------------------------------ Mac OS X is not following this standard -Jason --------------------------------------------------------------------------- [2001-01-27 07:26:19] [EMAIL PROTECTED] I have send a bug report to darwin-developers and apple, too, but i have check some UNIX-systems and i haven't found any man-page, where is describe what should be happend on "tm_mday" <= 0. IMHO this is a undocumented feature, which is used by PHP. man mktime (Linux 2.2.13) ------------------------------------ tm_mday The day of the month, in the range 1 to 31. Sun Release 4.1 ---------------------- int tm_mday; /* day of month (1 - 31) */ SunOS 5.5 --------------- int tm_mday; /* day of the month - [1, 31] */ HP-UX Release 10.20 ------------------------------ int tm_mday; /* day of month - [1,31] */ HP-UX Release 11.00 ------------------------------- int tm_mday; /* day of month - [1,31] */ AIX 4.3.2 ------------ int tm_mday; /* Day of month (1 - 31) */ Darwin 1.0.2 ----------------- int tm_mday; /* day of month (1 - 31) */ I think i should by much better to check mktime() on configure and set a #define for compilation. Only on "datetime.c" must be made a patch to support MacOS X's / Darwin's mktime()-systemcall, i think! --------------------------------------------------------------------------- The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online. ATTENTION! Do NOT reply to this email! To reply, use the web interface found at http://bugs.php.net/?id=8828&edit=2 -- PHP Development Mailing List <http://www.php.net/> To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]