Bug #8828 Updated: mktime using mday<=0
| From: | hholzgra@php.net | Date: | Wed, 12 Jun 2002 15:37:16 +0000 |
| Subject: | Bug #8828 Updated: mktime using mday<=0 | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-10262@lists.php.net to get a copy of this message | ||
ID: 8828
Updated by: hholzgra@php.net
Reported By: dieter@fiebelkorn.net
-Status: Duplicate
+Status: Closed
Bug Type: Date/time related
Operating System: MacOS X (Darwin 1.2)
PHP Version: 4.0.4pl1
New Comment:
fixed in latest CVS, should work on all OS/libc versions now
as negative offsets are now taken care of internaly so libc mktime()
won't receive any negative (or 0 for tm_mday) values anymore (see also
#10686)
Previous Comments:
------------------------------------------------------------------------
[2001-05-07 12:54:05] derick@php.net
Dup of #10686
------------------------------------------------------------------------
[2001-04-16 03:20:21] dieter@fiebelkorn.net
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] dieter@fiebelkorn.net
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] jason@php.net
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] jason@php.net
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
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
http://bugs.php.net/8828
--
Edit this bug report at http://bugs.php.net/?id=8828&edit=1