我们提供的服务让人们在滚动的两周时间内付款:
我们希望在反映一周前结束的付款期限的日期向人们付款:
等等
在PHP中计算这些时间段和某些“滚动”间隔的最佳方法是什么?我对DateTime
课并不陌生,但我不太清楚如何处理这个问题。
基本上,我们的想法是,当用户登陆他们的结算页面时,我们可以告诉他们他们在什么时间段内,以及何时可以预期在之前结束的时间段内付款。
更新
在进一步思考之后,似乎我需要给它一些参考点,知道从哪里开始。有什么想法吗?
谢谢。
更新#2 - 我的解决方案
class PayoutDate {
const PERIOD_LENGTH = 14;
public static $now;
public static $refStart;
public static $currentMonth;
public static $currentYear;
public static $currPeriodStart;
public static $currPeriodEnd;
public static $prevPeriodStart;
public static $prevPeriodEnd;
public function initialize(Controller $controller) {
self::$now = new DateTime();
self::$currentMonth = self::$now->format('m');
self::$currentYear = self::$now->format('Y');
self::$refStart = new DateTime("10/20/2013");
}
public function getPreviousPeriodStart() {
$daysIntoCurrentPeriod = ((int)self::$now->diff(self::$refStart)->format('%a') % self::PERIOD_LENGTH);
self::$prevPeriodStart = new DateTime('2 weeks ago');
self::$prevPeriodStart->sub(new DateInterval('P'.$daysIntoCurrentPeriod.'D'));
return self::$prevPeriodStart;
}
public function getPreviousPeriodEnd() {
$daysLeftCurrentPeriod = self::PERIOD_LENGTH - ((int)self::$now->diff(self::$refStart)->format('%a') % self::PERIOD_LENGTH) - 1;
self::$prevPeriodStart = new DateTime('2 weeks ago');
self::$prevPeriodStart->add(new DateInterval('P'.$daysLeftCurrentPeriod.'D'));
return (self::$prevPeriodStart);
}
public function getCurrentPeriodStart() {
$daysIntoCurrentPeriod = (int)self::$now->diff(self::$refStart)->format('%a') % self::PERIOD_LENGTH;
self::$currPeriodStart = clone self::$now;
self::$currPeriodStart->sub(new DateInterval('P'.$daysIntoCurrentPeriod.'D'));
return (self::$currPeriodStart);
}
public function getCurrentPeriodEnd() {
$daysLeftCurrentPeriod = self::PERIOD_LENGTH - ((int)self::$now->diff(self::$refStart)->format('%a') % self::PERIOD_LENGTH) - 1;
self::$currPeriodEnd = clone self::$now;
self::$currPeriodEnd->add(new DateInterval('P'.$daysLeftCurrentPeriod.'D'));
return (self::$currPeriodEnd);
}
public function getPreviousPeriodPayout() {
$prevEnd = new DateTime(self::getPreviousPeriodEnd());
return ($prevEnd->modify('next friday'));
}
public function getCurrentPeriodPayout() {
$currentEnd = new DateTime(self::getCurrentPeriodEnd());
return ($currentEnd->modify('next friday'));
}
}
我欢迎对此解决方案的反馈或改进:)
答案 0 :(得分:2)
嗯,我认为你需要某种参考点是正确的。我会选择一个工资期的任意开始时间。无论是在过去还是将来都没关系。您还需要一个表示支付期长度的变量。然后这只是做一些数学的问题。
$refStart = new DateTime('2013-03-31');
$periodLength = 14;
$now = new DateTime();
// do some modular arithmetic :)
$daysIntoCurrentPeriod = (int)$now->diff($refStart)->format('%a') % $periodLength;
$currentPeriodStart = clone $now;
$currentPeriodStart->sub(new DateInterval('P'.$daysIntoCurrentPeriod.'D'));
因此,在运行该代码后,$currentPeriodStart
将存储当前支付期的开始日期。 (它不会准确到第二个,但日期将是正确的。)然后你可以从它减去14天,以获得上一期间的开始,并添加/减去你需要的任何一天来获得支付日
这个解决方案还有一个额外的好处,就是可以节省夏令时(这可能很烦人),因为我很确定DateTime
可以说明这一点。
答案 1 :(得分:1)
这适用于我使用一些规则:
您可以根据自己的要求做一些调整,希望有所帮助:
<?php
/*
* Using:
* http://stackoverflow.com/a/1485512/496176
* http://www.php.net/manual/es/datetime.add.php
*/
date_default_timezone_set('Europe/London');
$interval = new DateInterval('P1W');
$payPeriod1 = new DateTime("2013-04-13");
$payPeriod1
->setISODate($payPeriod1->format("Y"), $payPeriod1->format("W"), 6)
->add($interval);
print "Pay day: " . $payPeriod1->format('Y-m-d') . "\n"; // Pay day: 2013-04-20
$payPeriod2 = new DateTime("2013-04-27");
$payPeriod2
->setISODate($payPeriod2->format("Y"), $payPeriod2->format("W"), 6)
->add($interval);
print "Pay day: " . $payPeriod2->format('Y-m-d') . "\n"; // Pay day: 2013-05-04
?>