【问题标题】:php - convert xml (milliseconds?) to readable datephp - 将 xml(毫秒?)转换为可读日期
【发布时间】:2013-08-21 20:45:43
【问题描述】:

我有一个 XML 文件正在解析,然后使用 PHP 插入到我的数据库中。然而,日期节点采用奇怪的XML 格式,我认为它是毫秒。到目前为止,我尝试转换它没有成功,我希望有人能指出我的错误。

XML

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

在转换之前哪个日期更易读

<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);
}

然而,最终结果总是与此类似

25-01-1970

而且我需要它看起来像转换之前的样子。像这样

04-30-2012

由于当原始日期转换进入 XML 文件时我没有处理它,所以我不确定我哪里出错了。任何帮助表示赞赏。

【问题讨论】:

  • 我很快 intval 挡住了你的路。 echo PHP_INT_MAX; 了解您使用的系统为您提供了什么。它将秒数限制为 32 位有符号最大值。
  • @hakre 虽然问题与转换 Unix 时间戳有关,但 OP 的问题与他如何编写代码和整数的有限大小有关。这是个好问题。
  • 是的,我很快就完成了这个骗局,你需要使用浮点数而不是强制转换。我也把它放在我的答案stackoverflow.com/a/18367563/367456 中,这是在 32 位系统上处理它的标准方法在 PHP 中。对于这些情况,精度应该没问题,否则需要 bcmath 或 gmp。

标签: php xml simplexml integer-overflow


【解决方案1】:

如果您在intval 中使用SimpleXMLElement 的字符串值,或者直接在数值计算(也转换为int)中使用它,PHP 会使用它。

正如我已经评论过的,我的第一个快速猜测是正确的,它会将数字截断为 32 位系统上可用的最大整数签名 (231 - 1)(我猜你是使用一个)导致:

2 147 483 647
25-01-1970

顺便说一句,这个数字。有点有名,并且有自己的维基百科页面:2147483647

请改用floatval 函数,它会为您提供所需的内容:

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

奖励:以下是一些代码,您可能会发现这些代码很方便,可以将转换代码放在中心位置并轻松使用:

/**
 * 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"

它的工作原理是从 SimpleXMLElement 扩展并添加日期创建函数,这里一个用于格式化字符串,一个用于更高级的日期时间操作,返回一个 DateTime object

上次我在 Stackoverflow 上扩展 SimpleXMLElement 是在 answer to the "How to replace XML node with SimpleXMLElement PHP" question 中。

【讨论】:

  • 这很有意义,但是当我使用floatval 而不是date 运行代码时,它会引发错误:floatval() expects exactly 1 parameter, 2 given
  • 好吧不是日期,而不是 intval :) 看例子,我没有替换 date()。
  • 确实,先生,但是问题仍然存在,我觉得有点奇怪。我只通过了 1 个参数。为什么它会认为是两个?
  • 哈,我发现了我的笨蛋。愚蠢的小错别字,每次都找你。它有效,谢谢。我会接受这个答案,因为它是最完整的
  • @i_me_mine:嗯,错误发生了。我还给你加了一些奖金。
【解决方案2】:

您正在使用intval,但对于int,数字太大。 只需使用:

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

【讨论】:

  • 谢谢,我现在看看,虽然这很有意义
  • 您也可以检查一下 PHP 常量 PHP_INT_MAX 来确定。请注意,结果会因运行 PHP 的服务器的操作系统而异(32 位与 64 位)。
  • 取决于您的 PHP_INT_SIZE ini。试试echo PHP_INT_SIZE;我的是8,这些数字处理得很好。
【解决方案3】:

您在第二次运行中没有超过秒数:

【讨论】:

  • 非常好,不是这个问题的根源,但一旦我弄清楚了,肯定会是。谢谢!
【解决方案4】:

可能的UTC,并切换日期和月份:

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

结果:

07-20-2012

【讨论】:

  • 谢谢,我现在看看,虽然这很有意义
猜你喜欢
  • 2010-10-08
  • 2019-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-05
  • 2011-06-08
相关资源
最近更新 更多