Pregunta

I have an XML file I am parsing and then inserting into my database using PHP. The date nodes however are in a weird XML format that I believed to be milliseconds. My attempts to convert this so far have been unsuccessful and I was hoping someone could point out my error.

XML

<est__start>1335744000000</est__start>
<est__end>1342742400000</est__end>

Which was this much more readable date before being converted

<est__start> 04-30-2012 </est__start>
<est__end> 07-20-2012 </est__end>

PHP

$start = $data->est__start;
if (empty($start)) {
    $start = '';
} else {
    $start = intval($start);            
    $seconds = $start / 1000;
    $start = date("d-m-Y", $seconds);
}
$end = $data->est__start;
if (empty($end)) {
    $end = '';
} else {
    $end = intval($end);            
    $seconds = $end / 1000;
    $end = date("d-m-Y", $end);
}

The end result however is always something similar to this

25-01-1970

and I need it to look like it did before the conversion. Like this

04-30-2012

Since I'm not handling the original date conversion when it goes into the XML file I'm not sure where I'm going wrong. Any help is appreciated.

¿Fue útil?

Solución

PHP uses the string value of the SimpleXMLElement if you use it in intval or as well directly in numeric calculations (which also cast to int).

As I already commented, my first quick guess was right, it truncates the number than to the maximum integer available on a 32 bit system signed (231 − 1) (I guess you're using one) which results in:

2 147 483 647
25-01-1970

This number btw. is sort of somewhat famous and has it's own Wikipedia page: 2147483647.

Instead use the floatval function, it gives you what you're looking for:

$seconds = floatval($start) / 1000;
echo date("d-m-Y", $seconds); # prints "30-04-2012"

Bonus: Here is some code you might find handy to have the conversion code in a central place and easily make use of:

/**
 * Class MySimpleXMLElement
 *
 * Extended SimpleXMLElement
 */
class MySimpleXMLElement extends SimpleXMLElement
{
    /**
     * @param string $format
     *
     * @return bool|string
     */
    public function getDateFromMilliseconds($format = "d-m-Y") {
        return date("d-m-Y", floatval($this) / 1000);
    }

    /**
     * @param DateTimeZone $timezone
     *
     * @return DateTime
     */
    public function createDateTimeFromMilliseconds(DateTimeZone $timezone = NULL) {
        return new DateTime('@' . (floatval($this) / 1000), $timezone);
    }
}

$data  = new MySimpleXMLElement('<r><est__start>1335744000000</est__start><est__end>1342742400000</est__end></r>');
/* @var $start MySimpleXMLElement */
$start = $data->est__start;

echo $start->getDateFromMilliseconds(), "\n"; # prints "30-04-2012"

echo $start->createDateTimeFromMilliseconds()->format('Y-m-d'); # prints "2012-04-30"

It works by extending from SimpleXMLElement and adding the date-creation functions, here one for a formatted string and for more advanced datetime operations one that gives back a DateTime object.

Last time I extended SimpleXMLElement on Stackoverflow was in an answer to the "How to replace XML node with SimpleXMLElement PHP" question.

Otros consejos

You're using intval but the numbers are too large for int. Just use:

date("m-d-Y", 1335744000000 / 1000); // 04-30-2012

you are not passing seconds in the second run:

enter image description here

Possible UTC, and switch day and month:

echo gmdate('m-d-Y',1342742400000 / 1000);

Result:

07-20-2012
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top