PHP日期时间与夏令时

时间:2017-02-28 02:58:29

标签: php datetime

所以我正在构建一个网站应用程序,用于计算任何用户拥有的账单到期金额。我设法让所有计算工作都很顺利,直到下个月到期。计算用户在账单到期之前获得多少薪水时,出了点问题。在几个var_dumps之后,我意识到当我将循环添加到循环中时,我想要额外的3600秒(在3月12日的夏令时期间获得1小时)。所以这里是计算所有内容的代码的高峰。只是为了让人们在发布此消息后的几个月内看到这一点。今天的当前日期是2017-02-27

  //declare paychecks as counter
  $paychecks = 0;

  //the number of days a user has between paychecks
  $frequency = 14; 

  //users next payday
  $next_payday = strtotime(2017-03-10);

  //the date the next bill is due
  $due_date = strtotime(2017-03-24);

理论上,在due_date之前应该有2个薪水。 (第二次薪水发生在账单到期的那天)

  while ($next_payday <= $due_date) {

       $payday = new DateTime($next_payday);
       $date_array = $payday->add(new DateInterval('P'. $frequency . 'D'));
       $next_payday += strtotime($date_array->format('Y-m-d'));

       //I commented this out but this does not work either
       //$next_payday += ($frequency * 86400);

       //increase the counter
       $paychecks++;

   }

所以在理论上(除了DST是一个因素之外的任何其他时间都可以使用)我试图确定用户在账单到期之前有多少薪水。问题是这个实例返回1而不是2,因为当循环的第二次迭代发生时,$ next_payday实际上会额外增加3600秒。这使$ next_payday比$ due_dates值高3600秒。我会假设因为夏令时。

那么我应该比较字符串值(日期('Y-m-d',$ due_date)== date('Y-m-d',$ next_payday))呢?当到期日与下一个发薪日相同时,这将起作用,但是当日期大于或小于时,它将不起作用。我注意到在将这些日期转换回字符串格式时,它们是相同的。或者有一种更好的方法可以做到这一点,我错过了。

在通过while循环的同时将3600添加到$ next_payday也可以,但我真的不想这样做。我敢肯定,当DST再次发生时,它会让我陷入困境,我会失去一个小时。

感谢您的任何意见。

1 个答案:

答案 0 :(得分:1)

使用86400(60*60*24)增加时间会在遇到DST事件时扭曲您的结果。幸运的是,当您添加天,周等时,strtotime()不会受到影响

DateTime结构很好,但我还没有为任何简单的日期时间进程使用它。这种情况也不例外。

当我测试您的代码时,它从未进入while循环,因为strtotime()值未被引用,因此被转换为设置$next_payday大于$due_date的意外时间戳。

此代码将正确计算日期范围内的付费期数:

//declare paychecks as counter
$paychecks = 0;

//the number of days a user has between paychecks
$frequency = 14;
// or you could use 2 and set the strtotime unit to "+$frequency weeks"

//users next payday
$next_payday = strtotime("2017-03-10");  // this date value needed quotes

//the date the next bill is due
$due_date = strtotime("2017-03-24");  // this date value needed quotes

//echo date("Y-m-d",$next_payday),"<br>",date("Y-m-d",$due_date),"<br>";

while($next_payday<=$due_date){
    ++$paychecks;  // 2017-03-10 & 2017-03-24
    $next_payday=strtotime(date("Y-m-d",$next_payday)." +$frequency days");
}

//echo "next_payday=",date("Y-m-d",$next_payday),"<br>"; // this will be beyond $due_date
echo $paychecks;  // 2

P.S。是的,while循环本来可以变成一个不太可读的单行(我总是想要寻找)。

while($next_payday<=$due_date && $next_payday=strtotime(date("Y-m-d",$next_payday)." +$frequency days")){++$paychecks;}