ID: 28543 Updated by: [EMAIL PROTECTED] Reported By: rjones-php-ibase-bug at ico dot viva dot org Status: Bogus Bug Type: InterBase related Operating System: windows 2000 and Linux PHP Version: 4.3.6 New Comment:
First of all, my apologies if I offended you in any way. I didn't mean to be rude, but your patch was really bad. Anyway: the Interbase driver uses 'struct tm' internally, which is basically a non-textual representation of a timestamp [Try 'man mktime' in a Unix shell for more info] The conversion to a printable format is carried out by strftime(), which is a C library call, and _not_ a PHP [internal] function. Apparently, the different C libraries don't agree on the way years < 1000 should be printed [for the %Y conversion]. Some print leading zeroes, some don't. There's really nothing we can do about that. The only possibility you have is changing the format string which is being fed to strftime() [by using ibase_timefmt()] and replace %Y with %C%y, which will print the year 1 as 001 [not 0001]. However, %C is not supported by Win32 (as far as I can tell by looking at MSDN) Currently, the [badly chosen] default timestamp format is not compatible with literal timestamps in SQL, as you pointed out. This format is just the default, so you can change that yourself. The built-in default will not be changed before the release of PHP 5, as doing so might break backward compatibility for some users. Finally, there's no point in maintaining this report as a feature request, as the real underlying problem is in strftime() [if you can even call it a problem: POSIX does not dictate whether %Y should print leading zeroes or not] Previous Comments: ------------------------------------------------------------------------ [2004-05-28 16:12:21] rjones-php-ibase-bug at ico dot viva dot org My "patch" sucks, I freely admit it; except that it's not a patch. It's a workaround that I used to get things working in my situation, and not intended to be a general fix. My colleague, who is more familiar with C than I am pointed out that it would be better to use %04d. Maybe there's other stuff wrong with it. That is independent of whether there is a problem or not. I'm sorry I didn't make it clearer, but there was no need to be rude like that. I'll try to explain the problem further. I haven't tested this thoroughly, but it seems that the way years are displayed by interbase is with leading zeros making the number of digits exactly four. This is true in isql, ibconsole and all other programs I've used with it. It doesn't seem sensible to me that php's interbase driver doesn't do the same, particularly as passing the string back in a query causes the query to fail. If you would like me to find out more about this, I can in time. I would appreciate a more constructive approach to the problem, though I realise there are a lot of time-wasters about. I hope you will reconsider this, and if you cannot bring yourself to describe it as a valid bug, at least let it stand as a feature request. If I have thoroughly misunderstood the problem, perhaps you can direct me towards enlightenment. ------------------------------------------------------------------------ [2004-05-28 01:05:57] [EMAIL PROTECTED] Apparently, the Windows and GNU implementations of strftime() behave differently. Nothing we can do about that. You can use ibase_timefmt() to change the way strftime() is applied. BTW, your patch sucks. You're using tm_year, which holds the number of years since 1900, and comparing it < 10, causing '1900' to be printed as '0001900'. Please don't post untested crap here. ------------------------------------------------------------------------ [2004-05-27 16:54:47] rjones-php-ibase-bug at ico dot viva dot org Description: ------------ This function does not work consistently on Linux and Windows 2000 with dates with small years. The strings it returns are under Linux: "01/01/1" under Windows: "01/01/0001" I have traced this back: ibase_fetch_row -> _php_ibase_fetch_hash -> _php_ibase_var_zval -> strftime in interbase.c at line 1919: #if HAVE_STRFTIME Z_STRLEN_P(val) = strftime(string_data, sizeof(string_data), format, &t); #else /* FIXME */ if (!t.tm_hour && !t.tm_min && !t.tm_sec) { Z_STRLEN_P(val) = sprintf(string_data, "%02d/%02d/%4d", t.tm_mon + 1, t.tm_mday, t.tm_year + 1900); } else { Z_STRLEN_P(val) = sprintf(string_data, "%02d/%02d/%4d %02d:%02d:%02d", t.tm_mon+1, t.tm_mday, t.tm_year + 1900, t.tm_hour, t.tm_min, t.tm_sec); } #endif As a work-around, I've used #if HAVE_STRFTIME // Make this consistent with PHP on windows. // FixMe This should give consistent results for all years from 0001 onwards if(t.tm_year < 10) { if (!t.tm_hour && !t.tm_min && !t.tm_sec) { Z_STRLEN_P(val) = sprintf(string_data, "%02d/%02d/000%d", t.tm_mon + 1, t.tm_mday, t.tm_year+1900); } else { Z_STRLEN_P(val) = sprintf(string_data, "%02d/%02d/000%d %02d:%02d:%02d", t.tm_mon+1, t.tm_mday, t.tm_year+1900, t.tm_hour, t.tm_min, t.tm_sec); } } else { Z_STRLEN_P(val) = strftime(string_data, sizeof(string_data), format, &t); } #else /* FIXME */ if (!t.tm_hour && !t.tm_min && !t.tm_sec) { Z_STRLEN_P(val) = sprintf(string_data, "%02d/%02d/%4d", t.tm_mon + 1, t.tm_mday, t.tm_year + 1900); } else { Z_STRLEN_P(val) = sprintf(string_data, "%02d/%02d/%4d %02d:%02d:%02d", t.tm_mon+1, t.tm_mday, t.tm_year + 1900, t.tm_hour, t.tm_min, t.tm_sec); } #endif Reproduce code: --------------- $rs_temp=ibase_query("SELECT time_stamp_field FROM some_stored_procedure()"); $row_temp=ibase_fetch_row($rs_temp); print($row_temp[0]); Expected result: ---------------- 01/01/0001 Actual result: -------------- 01/01/1 ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=28543&edit=1