如何使用PHP将日期显示为ISO 8601格式

82

我正在尝试使用PHP将来自MySQL数据库的日期时间显示为ISO 8601格式的字符串,但结果不正确。

2008年10月17日显示为1969-12-31T18:33:28-06:00,这显然是不正确的(年份应该是2008而不是1969)

这是我正在使用的代码:

<?= date("c", $post[3]) ?>

$post[3] 是来自我的 MySQL 数据库的日期时间(CURRENT_TIMESTAMP)。

有任何想法出了什么问题吗?

6个回答

103

date 的第二个参数是 UNIX 时间戳,而不是数据库时间戳字符串。

您需要使用 strtotime 将数据库时间戳转换为 UNIX 时间戳。

<?= date("c", strtotime($post[3])) ?>

1
请使用类!看看@John Conde的解决方案,;) - German Latorre
3
“date()”函数会降低精度,使用John的解决方案代替它! - Christian
@Christian,“date()函数降低了精度”是什么意思? - Yifan
1
@Christian 'c'格式不包括秒的小数部分,而John的答案目前仅使用'c'格式,因此John的答案并没有改进。你说得对,DateTime()允许更高的分辨率,但除非你使用具有更高分辨率的自定义8601格式,否则它对你没有帮助。因此,如果您只使用'c'格式并且喜欢函数式编程,那么我认为这个解决方案很好。对于那些想要更高分辨率的人,Clary的答案提供了一些示例。 - ADJenks
据我所记,这与“c”参数无关,而是因为日期需要一个以秒为整数的时间戳,而DateTime对象支持更小的单位。换句话说,我关心的是存储部分,而不是格式化部分。 - Christian
显示剩余2条评论

48

使用 PHP 5.2 版本中提供的 DateTime 类,可以按照以下方式完成:

$datetime = new DateTime('17 Oct 2008');
echo $datetime->format('c');

从PHP 5.4开始,你可以将这个操作变成单行代码:

echo (new DateTime('17 Oct 2008'))->format('c');

24

程序化风格:

echo date_format(date_create('17 Oct 2008'), 'c');
// Output : 2008-10-17T00:00:00+02:00

面向对象风格:

$formatteddate = new DateTime('17 Oct 2008');
echo $datetime->format('c');
// Output : 2008-10-17T00:00:00+02:00

混合1:

echo date_format(new DateTime('17 Oct 2008'), 'c');
// Output : 2008-10-17T00:00:00+02:00

混合2:

echo date_create('17 Oct 2008')->format('c');
// Output : 2008-10-17T00:00:00+02:00

注意:

1)您还可以使用'Y-m-d\TH:i:sP'作为您的格式的替代方式,而不是'c'

2)输入的默认时区是您服务器的时区。 如果您需要输入来自其他时区,则需要显式设置您的时区。 然而,这也会影响您的输出:

echo date_format(date_create('17 Oct 2008 +0800'), 'c');
// Output : 2008-10-17T00:00:00+08:00

3) 如果您想要的输出时区与您输入的时区不同,您可以明确地设置自己的时区:

echo date_format(date_create('17 Oct 2008')->setTimezone(new DateTimeZone('America/New_York')), 'c');
// Output : 2008-10-16T18:00:00-04:00

8
这是适用于 PHP 5 之前的好函数: 我在末尾添加了 GMT 差异,而不是硬编码。
function iso8601($time=false) {
    if ($time === false) $time = time();
    $date = date('Y-m-d\TH:i:sO', $time);
    return (substr($date, 0, strlen($date)-2).':'.substr($date, -2));
}

7

对于 PHP 5 之前的版本:

function iso8601($time=false) {
    if(!$time) $time=time();
    return date("Y-m-d", $time) . 'T' . date("H:i:s", $time) .'+00:00';
}

6
为什么不去掉T标志...并且$时间条件是不必要的,因为当没有时间参数给出或为空时,使用当前时间:date('Y-m-d\TH:i:s\Z', $time);// Z表示当前时区。 - gregor

7

许多时候,问题出现在毫秒和最终微秒上,它们通常是4或8个数字。要将DATE转换为ISO 8601格式,"date(DATE_ISO8601)"是我使用的其中一种解决方法:

// In this form it leaves the date as it is without taking the current date as a reference
$dt = new DateTime();
echo $dt->format('Y-m-d\TH:i:s.').substr($dt->format('u'),0,3).'Z';
// return-> 2020-05-14T13:35:55.191Z

// In this form it takes the reference of the current date
echo date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z');
return-> 2020-05-14T13:35:55.191Z

// Various examples:
$date_in = '2020-05-25 22:12 03.056';
$dt = new DateTime($date_in);
echo $dt->format('Y-m-d\TH:i:s.').substr($dt->format('u'),0,3).'Z';
// return-> 2020-05-25T22:12:03.056Z

//In this form it takes the reference of the current date
echo date('Y-m-d\TH:i:s'.substr((string)microtime(), 1, 4).'\Z',strtotime($date_in));
// return-> 2020-05-25T14:22:05.188Z

1
对于任何想在Swift的ISO8601DateFormatter和你的PHP服务器日期格式之间找到解决方案的人 - 上面的工作代码是 $dt->format('Y-m-d\TH:i:s.').substr($dt->format('u'),0,3).'Z';。谢谢你,伙计! - Sherbieny

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接