views:

728

answers:

4

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.

A: 

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.

Michael Johnson
Tnanks for the reply. It seems it is platform specific. My dev platform of OSX Leopard and the strptime in the underlying C library seems to be the culprit. I cannot reproduce it on Linux boxes either but both the Macs in the office display the same behaviour.
+1  A: 

This function is locale-dependent. Have you tried setting different locale? (see setlocale())

porneL
A: 

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.

Ross
A: 

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?

Jonathan Leffler