1

我们有一项服务可以让人们在两周的滚动时间范围内付款:

  • 03-31-13 至 04-13-13
  • 04-14-13 至 04-27-13
  • 04-28-13 至 05-11-13
  • ETC

我们希望在反映一周前结束的支付期的日期向人们付款:

  • 04-20-13 将是 03-31-13 至 04-13-13 期间的支付日期
  • 05-04-13 将是 04-14-13 至 04-27-13 期间的支付日期

等等

在 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'));

    }



}

我欢迎对此解决方案的反馈或改进 :)

4

2 回答 2

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考虑到这一点。

于 2013-10-21T05:33:00.590 回答
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 
?>
于 2013-10-21T05:12:26.210 回答