I am wrestling with a php 5.2.6 problem. An api we use returns dates in this format DDMMYYYYHHMM. Exactly that format, fixed length, no delimiters. However, in my experimentation, this format seems to break strptime, which returns a false (fail) when I feed it a date in this format. It can reproduced, at least on my system, with this example:
$format = "%d%m%Y%H%M"; echo print_r(strptime(strftime($format,1225405967),$format),true);
If I add any character between the date and the time, it works, even a space. So, this DOES work:
$format = "%d%m%Y %H%M"; echo print_r(strptime(strftime($format,1225405967),$format),true);
Am I missing something obvious?
edit: further to this and owing to the results indicated by the comments, this seems to be platform specific. I can reproduce it on the Macs running OSX Leopard in the office but the Linux boxes parse it fine. I assume it is a bug or idiosyncrasy of the strptime in the underlying C library in the *nix of OSX.
This function is locale-dependent. Have you tried setting different locale? (see setlocale())
If you think the problem is on MacOS X and in the C library, then you could produce a test case to demonstrate it. For example, I ran the code below on MacOS X 10.4.11 (PPC, G4, 32-bit), and got the output:
Now: 1225573977
Formatted (12): 011120082112
End: 0xBFFFF553 (Buffer: 0xBFFFF547)
Then: year = 2008, month = 11, day = 1, hour = 21, minute = 12
Reformatted (12): 011120082112
The code I used is:
#include <time.h>
#include <stdio.h>
int main(void)
{
time_t now = time(0);
struct tm *tm = gmtime(&now);
char format[] = "%d%m%Y%H%M";
char buffer1[64];
char buffer2[64];
size_t f_len = strftime(buffer1, sizeof(buffer1), format, tm);
struct tm then;
char *end = strptime(buffer1, format, &then);
size_t p_len = strftime(buffer2, sizeof(buffer2), format, &then);
printf("Now: %ld\n", (long)now);
printf("Formatted (%lu): %s\n", (unsigned long)f_len, buffer1);
printf("End: 0x%08lX (Buffer: 0x%08lX)\n", (unsigned long)end, (unsigned long)buffer1);
printf("Then: year = %d, month = %d, day = %d, hour = %d, minute = %d\n",
then.tm_year + 1900, then.tm_mon + 1, then.tm_mday, then.tm_hour, then.tm_min);
printf("Reformatted (%lu): %s\n", (unsigned long)p_len, buffer2);
return(0);
}
On the basis of what I see, there is no bug in strptime() in the version I'm using. We can debate about the merits of the non-existent error checking, and of the casts versus C99 <inttypes.h> notations in the printing, but I think the code is accurate enough. I used gmtime() instead of localtime(); I doubt if that was a factor in not reproducing the problem.
Maybe you should look at the PHP test suite?
Maybe you should split your rather complex expression into pieces to detect where the error occurs in PHP?
Nothing obvious since both versions work fine in PHP 5.2.0. I can't readily check 5.2.6 at the moment, though. That will have to wait until I get home.
It's very likely that this is isolated to Macs only, as this hasn't even been implemented on Windows yet (although I've passed that suggestion along).
5.2.6
Fatal error: Call to undefined function strptime() in F:\htdocs\strptime.php on line 5
I would go ahead and submit a bug at bugs.php.net.
I confirm:
$p = strptime("09.02.2002", "%d.%m.%Y");
var_dump($p);
Output:
array(9) {
["tm_sec"]=>
int(0)
["tm_min"]=>
int(0)
["tm_hour"]=>
int(0)
["tm_mday"]=>
int(9)
["tm_mon"]=>
int(1)
["tm_year"]=>
int(102)
["tm_wday"]=>
int(0)
["tm_yday"]=>
int(0)
["unparsed"]=>
string(0) ""
}
OS X Leopard, PHP 5.3.2
Related
I recently upgraded the running version of PHP on my server to 5.3.20. Since then, whenever I pull datetimes out of a MSSQL database (mssql_query) I get weirdly wrong dates coming through.
I have checked the locale settings and the default timezone is set to 'Australia/Brisbane', I've also checked the php.ini settings and confirmed that the mssql.datetimeconvert is turned off. The dates seem to come through preformatted (without seconds) when the option is turned on, however when the option is turned off I get a date that looks like this.
mssql.datetimeconvert (off): 2013-07-38 16:00:20
mssql.datetimeconvert (on): Feb 07 2013 09:37PM
Is there a simple fix?
Here is the code that compares output between mysql/mssql sources:
$rs = $db->query("select id, servertime from bobstable where id = 86427420");
$mss_set = mssql_query("select id, servertime from T_bobstable WITH (NOLOCK) where id = 86427420");
$myrow = $rs->fetch_assoc();
$msrow = mssql_fetch_array($mss_set);
var_dump($myrow);
echo "<br>";
var_dump($msrow);
which outputs as follows:
array(2) { ["id"]=> string(8) "86427420" ["servertime"]=> string(19) "2013-02-08 14:00:24" }
array(4) { [0]=> float(86427420) ["id"]=> float(86427420) [1]=> string(19) "2013-08-39 24:673:0" ["servertime"]=> string(19) "2013-08-39 24:673:0" }
and this is the output that I receive right out of SQL Server Studio
2013-02-08 14:00:24.673
I can understand how it's been formatted (as that part of the problem was answered below) but I can't understand why it's coming through in this format or how to change PHP's configuration to avoid this. Before I upgraded PHP it used to come through as 2013-02-08 14:00:24. Has anyone experienced or seen this happen before?
Found a solution that seems to stick:-
I downgraded the FreeTDS version that was installed on the server from:
freetds.x86_64 0.91-2.el5 to
freetds.x86_64 0.64-11.el5.centos
And that fixed the dates.
Don't know why.
today the 07 february the DAYOFYEAR() is 38.
probably the probleme is on the date format
I've seen a few questions on people trying to get MySQL to use ',' as the floating point separator - what I'm trying to do is stop PHP from using it on a website running under the 'nl_NL' locale.
So in the code PHP is writing an SQL query ending like:
" ... HAVING `relevance` >= {$fFloatingPointNumber}";
The problem is, because PHP's locale is running as 'nl_NL' when it converts that floating point number to a string it's using ',' as the separator (e.g. 1,5).
What I'm doing to prevent this currently is:
" ... HAVING `relevance` >= " . number_format($fFloatingPointNumber, 2, '.', '');
Is there a better way of doing this - or is this my best bet?
Solution 1
I will post my answer in case it is the only solution apart from #Pete one.
I would suggest switching the locale to GB or some other period separated float/double locale before each query then switching back to the correct locale after. I can not think of any other way around this.
Solution 2 (Best Bet)
You could always use the number_format method as follows
$stringversion = number_format($theFloat, 2, ".","");
Pretty sure this would work, the documentation is here http://php.net/manual/en/function.number-format.php
Could you try this or something similar? Credit to Ludovico Grossi
<?php
setlocale(LC_ALL, 'nl_NL');
setlocale(LC_NUMERIC, 'en_GB'); //overwrite the decimal separator
?>
I'll try and keep this simple. I'm using a BIGINT data type on a MySQL database table. I have a function generating a unique random number that may span anywhere from 12 digits to 13 digest long.
When I insert into the database with a digit that is 12 digits in length, it enters it just fine,
but when I use a value that is 13 digits or longer, it seems like it rounds up or something. here is the
php
$defaultText = 'some string'; //just some string
$web_id = 12;
$element_id = 23112182735363; //case 1 (doesn't work)
//$element_id = 2311218333205; //case 2, does work ()
mysql_query("INSERT INTO tableName (web_id, element_id, content)
VALUES ($web_id, $element_id, '".mysql_real_escape_string($defaultText)."')");
results:
in case one, it inserts a slightly different number, usually rounds up for some reason.
in case two, it inserts the number just fine! Maybe someone can help shed some light on this mystery! Thanks again!
the big int datatype:
bigint(200)
Numbers lose their precision from PHP_INT_MAX onwards. See also: http://www.php.net/manual/en/reserved.constants.php#constant.php-int-max
After that they are turned into floats which have limited precision and causes weird rounding issues. The only way to support BIGINT in PHP is by using strings.
I assumed you were talking about a 32-bit server.
But in my server, PHP seemed not lose the precision.
echo(PHP_INT_MAX . "<br/>");
$big_int = -6174803190685607000;
echo($big_int . '<br/>');
output
9223372036854775807<br/>-6174803190685607000<br/>
Sadly I still got the precision losing. I guessed it might because i used 'i' in prepare statement of mysqli, but I could not prove it.
pycassa has pycassa.util.convert_time_to_uuid(time_arg, lowest_val=True, randomize=False)
phpcassa has static string uuid1 ([string $node = null], [int $time = null])
Can phpcassa's uuid1 be used to get lowest/highest uuids like in pycassa?
If not, what's the best approach to ensure you get everything between two given timestamps?
I believe that if you have a column with a type of UUID version 1, Cassandra will ignore the 'unique' component of the UUID and just use the time part for the range.
Strictly speaking, Cassandra sorts primarily by the timestamp component of a v1 UUID, and in the case of a tie, it sorts by the remaining bytes:
int res = compareTimestampBytes(o1, o2);
if (res != 0)
return res;
return o1.compareTo(o2);
phpcassa should offer something similar to pycassa here. As a workaround in the meantime, you can set the last 8 bytes of the return value to 0x00.
I have this code inside of a exit hook in a custom module:
$diff = round(((microtime(true)-$script_start_time)*1000));
watchdog('thaty', $diff);
if(variable_get('thingy', 0) == 1) {
$data = array(
'q'=>$_GET['q'],
'memory'=>memory_get_peak_usage(),
'execution_time'=>$diff
);
db_query('INSERT INTO {blah} (q,memory,dt,execution_time) VALUES (\'%s\',%b,UNIX_TIMESTAMP(),%b)',$data);
}
The value of $diff will occasionally consistently get saved in the database as 2147483647, which is the overflow value for an INT, I believe, in PHP. When I log the value via watchdog I can confirm that it does not get set to 2147483647, but the real value, which is a three digit whole number.
Typical values (confirmed from logging):
708
408
413
The execution_time column is int(11).
I can't seem to find the source of this issue. Things I've tried:
Using %d instead of %b for the value
Assigning $diff to a new an INT variable
Checking for this wrong value pre-insert
Confirming the value of $diff is not too large for an INT in PHP
Tried using %n, re: http://www.lullabot.com/articles/drupocalypse-now-or-dangerous-integer-handling-drupal-write-record
It seems db_query("INSERT....") is deprecated in favour of drupal_write_record().
Try drupal_write_record().
Seeing as this is most certainly a masking problem when building the query (rather than a database problem), maybe that does it better.