如何在PHP中计算时间段块并确定当前块?

时间:2013-10-21 02:55:07

标签: php datetime time

我们提供的服务让人们在滚动的两周时间内付款:

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

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

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

    }



}

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

2 个答案:

答案 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)

这适用于我使用一些规则:

  • 确定指定日期的下周六(支付日)并添加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 
?>