php interbase関数の日付フォーマット

古いinterbase(5.0)に接続するプログラムを作る必要が出てきまして firebirdのclientでもダイアレクト指定できれば使える(pdo_firebirdはdiarectが渡せる ようにはなってない)ことがわかり実際に検索とかしてみた時の事です。

日付で検索したいのでこのようにbindしてSELECTかけてみると

SELECT SALEDATE WHERE CAST(SALEDATE AS DATE)=?

php.iniの設定にはibase.dateformatがありこれでフォーマットを変えられるはずなのですが

interbase関数 php.ini設定

このフォーマットでbindしてもエラーになる、というか”%m-%d-%Y”という形式で条件を書いたときのみいける。

このフォーマット効いてるのかと、よく見ると返ってくるデータは変わっている。

らちが明かないのでphpのソースを追いかけてみる。

php-5.6.25のソースで確認

比較的新しいソースだと思いますが

php-5.6.25-src/ext/interbase

_php_ibase_bindという関数があったのでたぶんこれだろうと

SQL_TYPE_DATEの処理はこの辺のよう

			case SQL_TIMESTAMP:
			case SQL_TYPE_DATE:
			case SQL_TYPE_TIME:
				if (Z_TYPE_P(b_var) == IS_LONG) {
					struct tm *res;
					res = php_gmtime_r(&Z_LVAL_P(b_var), &t);
					if (!res) {
						return FAILURE;
					}
				} else {
#ifdef HAVE_STRPTIME
					char *format = INI_STR("ibase.timestampformat");

					convert_to_string(b_var);

					switch (var->sqltype & ~1) {
						case SQL_TYPE_DATE:
							format = INI_STR("ibase.dateformat");
							break;
						case SQL_TYPE_TIME:
							format = INI_STR("ibase.timeformat");
					}
					if (!strptime(Z_STRVAL_P(b_var), format, &t)) {
						/* strptime() cannot handle it, so let IB have a try */
						break;
					}
#else /* ifndef HAVE_STRPTIME */
					break; /* let IB parse it as a string */
#endif
				}

				switch (var->sqltype & ~1) {
					default: /* == case SQL_TIMESTAMP */
						isc_encode_timestamp(&t, &buf[i].val.tsval);
						break;
					case SQL_TYPE_DATE:
						isc_encode_sql_date(&t, &buf[i].val.dtval);
						break;
					case SQL_TYPE_TIME:
						isc_encode_sql_time(&t, &buf[i].val.tmval);
						break;
				}
				continue;

ibase.timeformatを参照してるのHAVE_STRPTIMEのところだけじゃん

VCのランタイムにはstrptimeなんてないからたぶんここは無視されている

VCランタイム関数

いや、でもなんで返ってくる値のほうは変換されてるの?

返値の処理は_php_ibase_var_zvalでやっていると思われる

		case SQL_DATE: /* == case SQL_TIMESTAMP: */
			format = INI_STR("ibase.timestampformat");
			isc_decode_timestamp((ISC_TIMESTAMP *) data, &t);
			goto format_date_time;
		case SQL_TYPE_DATE:
			format = INI_STR("ibase.dateformat");
			isc_decode_sql_date((ISC_DATE *) data, &t);
			goto format_date_time;
		case SQL_TYPE_TIME:
			format = INI_STR("ibase.timeformat");
			isc_decode_sql_time((ISC_TIME *) data, &t);

format_date_time:
			/*
			  XXX - Might have to remove this later - seems that isc_decode_date()
			   always sets tm_isdst to 0, sometimes incorrectly (InterBase 6 bug?)
			*/
			t.tm_isdst = -1;
#if HAVE_TM_ZONE
			t.tm_zone = tzname[0];
#endif
			if (flag & PHP_IBASE_UNIXTIME) {
				ZVAL_LONG(val, mktime(&t));
			} else {
#if HAVE_STRFTIME
				l = strftime(string_data, sizeof(string_data), format, &t);
#else
				switch (type & ~1) {
					default:
						l = slprintf(string_data, sizeof(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);
						break;
					case SQL_TYPE_DATE:
						l = slprintf(string_data, sizeof(string_data), "%02d/%02d/%4d", t.tm_mon + 1, t.tm_mday, t.tm_year+1900);
						break;
					case SQL_TYPE_TIME:
						l = slprintf(string_data, sizeof(string_data), "%02d:%02d:%02d", t.tm_hour, t.tm_min, t.tm_sec);
						break;
				}
#endif
				ZVAL_STRINGL(val,string_data,l,1);
				break;
			}

なにこれ、片やstrftimeが使われている

つまりVC++でコンパイルされたWindows版PHPのinterbaseでは返値のみフォーマットがなされてしまう

いやこれinterbase関数なんて使う機会があんまりないだろうとは思うけどどうなんでしょう

これってたぶんずっと前からこのままなんですよね?

カテゴリー: php タグ: , ,

関連してるかも記事

この記事へのコメント

※コメントはスパム対策の為、承認制となっています。あらかじめご了承ください。

トラックバックURL