php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #28543 ibase_fetch_row returns inconsistent formats for TIMESTAMP fields on firebird
Submitted: 2004-05-27 16:54 UTC Modified: 2004-05-29 00:10 UTC
From: rjones-php-ibase-bug at ico dot viva dot org Assigned:
Status: Not a bug Package: InterBase related
PHP Version: 4.3.6 OS: windows 2000 and Linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
37 - 24 = ?
Subscribe to this entry?

 
 [2004-05-27 16:54 UTC] 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

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-05-28 01:05 UTC] abies@php.net
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-28 16:12 UTC] 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-29 00:10 UTC] abies@php.net
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]



 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 06:01:29 2024 UTC