首页 > 解决方案 > PHP时间比较失败

问题描述

我正在开发一个 Wordpress 插件,但在时间比较方面遇到了问题。我基本上想要:如果选择的时间在当前时间之前,做这件事......但它不起作用。

expire如果比 time() 提前不到五个小时,则验证失败。我通过添加 gmt 偏移来纠正这个问题,expire但它仍然失败。有任何想法吗?

//$_POST['expire'] = '2019-01-31T12:00';

if(validateDate($_POST['expire'])) {
    $expires_epoch = (strtotime($_POST['expire']) - (get_option( 'gmt_offset' ) * HOUR_IN_SECONDS));
    if($expires_epoch < time()) {
        ...do the thing...
    }
 }

有什么想法吗?这看起来很简单,但似乎并没有按照我想要的方式工作。

标签: phpwordpressdatedatetime

解决方案


strtotime它可以接受的格式有限,并且不会总是提供所需的结果。为了避免日期格式的歧义,正如 PHP 文档所推荐的那样,替代方法是使用DateTime::createFromFormat. 这将允许您强制执行所提供的所需格式$_POST['expire']

使用格式Y-m-d\TH:i|规则,强制执行ISO-8601格式,不包括秒和时区。( |pipeline) 将剩余秒数重置为:00,否则 PHP 将使用当前秒数。

如果您希望您的代码在到期日期过后运行那么您只需要比较expire_date < current_date.

示例:https ://3v4l.org/EelYY

//current date is 2019-01-04 08:33:30
//$_POST['expire'] = '2019-01-04T08:32';

if ($expire_date = \DateTime::createFromFormat('Y-m-d\TH:i|', $_POST['expire'])) {
    $current_date = new \DateTime();
    if ($expire_date < $current_date) {
        /* example purposes only */
        $diff = $expire_date->diff($current_date);
        echo 'Expired ' . $diff->format('%y years %m months %d days %h hours %i minutes %s seconds') . ' ago';
        //do the thing
    }
} else {
    die('Invalid Date Format Provided');
}

结果

Expired 0 years 0 months 0 days 0 hours 1 minutes 30 seconds ago

澄清如何以及为什么使用 Wordpress 的时区偏移量。

默认情况下,PHP 将在使用 、 和 对象时使用您指定的值date.timezone。这仅对 Wordpress 和大多数其他应用程序在向查看器显示您的应用程序生成的日期或接受来自用户的要保存并显示给其他用户的日期字符串时很重要。例如显示创建帖子的时间或预期发生事件的时间。否则,通常可以忽略用户时区偏移量,因为 PHP 会将本地时区偏移量应用于解析的日期。php.inidate()time()strtotime()DateTime

例如,默认 PHPdate.timezone是 UTC。我创建了一个我想在2019-01-01 09:00我的时间 (EST) 发生的事件。但该活动将在 3 小时前在加利福尼亚州 (PST) 的某个人开始2019-01-01 06:00

为了向其他用户显示事件,必须将日期从 EST 的用户时区偏移量转换为 UTC 并存储在数据库中。然后从 UTC 转换为显示为其他时区。

示例:https ://3v4l.org/vA97A

$defaultTZ = new \DateTimeZone(date_default_timezone_get());
$event_start = '2019-01-01 09:00';
//event starts at 2019-01-01 09:00 EST
$est_date = new \DateTimeImmutable($event_start, new \DateTimeZone('America/New_York'));
//convert to native date to save in database
$utc_date = $est_date->setTimeZone($defaultTZ);
$db_date = $utc_date->format(DATE_ISO8601);

//event starts at 2019-01-01 14:00 UTC
$db_event_start = '2019-01-01T14:00:00+0000';
$event_date = new \DateTimeImmutable($db_event_start, $defaultTZ);

//display the start times to users
$pst_date = $event_date->setTimeZone(new \DateTimeZone('America/Los_Angeles'));
$est_date = $event_date->setTimeZone(new \DateTimeZone('America/New_York'));

echo 'Event Starts at:';
echo $event_date->format('Y-m-d H:i T');
echo $pst_date->format('Y-m-d H:i T');
echo $est_date->format('Y-m-d H:i T');

//display event status
echo 'Event ' . ($event_date <= new \DateTime('now', $defaultTZ) ? 'Has' : 'Not') . ' Started';

结果

Event Starts at:
2019-01-01 14:00 GMT+0000
2019-01-01 06:00 PST
2019-01-01 09:00 EST
Event Has Started

对于 WordPress,您通常会替换date_default_timezone_get()get_option('timezone_string')使用应用程序时区偏移量而不是 PHP 的默认时区偏移量。


推荐阅读