3

我正在尝试使用 DateTime 检查信用卡到期日期是否已过期,但我有点迷路了。

我只想比较 mm/yy 日期。

到目前为止,这是我的代码

$expmonth = $_POST['expMonth']; //e.g 08
$expyear = $_POST['expYear']; //e.g 15

$rawExpiry = $expmonth . $expyear;

$expiryDateTime = \DateTime::createFromFormat('my', $rawExpiry);
$expiryDate = $expiryDateTime->format('m y');

$currentDateTime = new \DateTime();
$currentDate = $currentDateTime->format('m y');

if ($expiryDate < $currentDate) {
    echo 'Expired';
} else {
    echo 'Valid';
}

我觉得我快到了,但是 if 语句产生了不正确的结果。任何帮助,将不胜感激。

4

7 回答 7

11

它比你想象的要简单。您正在使用的日期格式并不重要,因为 PHP 在内部进行比较。

$expires = \DateTime::createFromFormat('my', $_POST['expMonth'].$_POST['expYear']);
$now     = new \DateTime();

if ($expires < $now) {
    // expired
}
于 2013-10-21T14:04:30.350 回答
9

您可以使用DateTime 类使用DateTime::createFromFormat()构造函数生成与给定日期字符串格式匹配的 DateTime 对象。

格式 ('my') 将匹配任何带有字符串模式 'mmyy' 的日期字符串,例如 '0620'。或者对于具有 4 位数年份的日期,使用格式“mY”,它将匹配具有以下字符串模式“mmyyyy”的日期,例如“062020”。使用DateTimeZone类指定时区也是明智的。

$expiryMonth = 06;
$expiryYear = 20;
$timezone = new DateTimeZone('Europe/London');
$expiryTime = \DateTime::createFromFormat('my', $expiryMonth.$expiryYear, $timezone);

有关更多格式,请参阅DateTime::createFromFormat页面。

但是 - 对于信用卡/借记卡的到期日期,您还需要考虑完整的到期日期和时间- 而不仅仅是月份和年份。

如果未指定DateTime::createFromFormat,默认情况下将使用该月的今天(例如 17)。这意味着信用卡在还剩几天时可能会出现过期。如果一张卡在 06/20(即 2020 年 6 月)到期,那么它实际上会在 2020 年 7 月 1 日 00:00:00 停止工作。修改方法可以解决此问题。例如

$expiryTime = \DateTime::createFromFormat('my', $expiryMonth.$expiryYear, $timezone)->modify('+1 month first day of midnight');

字符串'+1 month first day of midnight'做了三件事。

  • '+1 个月' - 添加一个月。
  • 'first day of' - 切换到该月的第一天
  • '午夜' - 将时间更改为 00:00:00

modify 方法对于许多日期操作非常有用!

所以要回答这个问题,这就是你所需要的——稍微调整格式以适应个位数的月份:

$expiryMonth = 6;
$expiryYear = 20;
$timezone = new DateTimeZone('Europe/London');
$expiryTime = \DateTime::createFromFormat(
  'm-y',
   $expiryMonth.'-'.$expiryYear,
   $timezone
)->modify('+1 month first day of midnight');

$currentTime = new \DateTime('now', $timezone);

if ($expiryTime < $currentTime) {
    // Card has expired.
}
于 2017-07-17T14:54:50.120 回答
6

对上述答案的补充。请注意,默认情况下,天数也将在计算中。例如今天是2019-10-31,如果你运行这个:

\DateTime::createFromFormat('Ym', '202111');

它将输出2021-12-01,因为 11 月不存在第 31 天,并且它将为您的 DateTime 对象增加 1 天,并产生副作用,即您将在 12 月而不是预期的 11 月。

我的建议是始终在您的代码中使用这一天。

于 2019-10-31T12:19:51.050 回答
1

对于操作的问题:

$y=15;
$m=05;

if(strtotime( substr(date('Y'), 0, 2)."{$y}-{$m}" ) < strtotime( date("Y-m")  ))
{
  echo 'card is expired';
}

对于其他全年:

$y=2015;
$m=5;

if(strtotime("{$y}-{$m}") < strtotime( date("Y-m")  ))
{
  echo 'card is expired';
}
于 2015-06-20T16:18:20.470 回答
0

最佳答案由上面的 John Conde 提供。它只做最少的处理:创建两个正确的DateTime对象,比较它们,这就是它所需要的。

它也可以在您开始时工作,但您必须以将年份放在首位的方式格式化日期。

想一想:作为日期,08/15(August 2015) 在12/14(December 2014) 之后,但作为字符串,'08 15'在之前'12 14'

当年份在前面时,即使是字符串,也会首先比较年份,然后只有当年份相等时才会比较月份:

$expiryDate  = $expiryDateTime->format('y m');
$currentDate = $currentDateTime->format('y m');

if ($expiryDate < $currentDate) {
    echo 'Expired';
} else {
    echo 'Valid';
}
于 2015-06-20T16:45:21.327 回答
0

将字符串“201709”与当前的年月进行比较不是更简单吗?我想,创建日期时间对象将花费 php 一些精力。

if($_POST['expYear']. str_pad($_POST['expMonth'],2,'0') < date('Ym')) {
   echo 'expired';

}
于 2017-07-19T11:07:46.190 回答
0

保持简单,正如我上面的答案所说,除了你需要把 pad 放在左边:

isCardExpired($month, $year)
{
    $expires = $year.str_pad($month, 2, '0', STR_PAD_LEFT);
    $now = date('Ym');

    return $expires < $now;
}

无需使用添加额外的 PHP 负载DateTime

于 2019-04-16T13:40:05.973 回答