Skip to content

Instantly share code, notes, and snippets.

@66Ton99
Last active March 9, 2022 13:30
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save 66Ton99/60571ee49bf1906aaa1c to your computer and use it in GitHub Desktop.
Save 66Ton99/60571ee49bf1906aaa1c to your computer and use it in GitHub Desktop.
DateTime
<?php
namespace MyNamespace;
/**
* @author Ton Sharp <66Ton99@gmail.com>
*/
class DateTime extends \DateTime
{
/**
* @param int|null $year
* @param int|null $month
* @param int|null $day
*
* @return $this
*/
public function setDate($year, $month, $day)
{
if (null == $year) {
$year = $this->format('Y');
}
if (null == $month) {
$month = $this->format('n');
}
if (null == $day) {
$day = $this->format('j');
}
$daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
$day = $day > $daysInMonth ? $daysInMonth : $day;
$return = parent::setDate($year, $month, $day);
return $return;
}
/**
* @inheritdoc
*/
public function modify($modify)
{
$pattern = '/( ?[-+]?\d?\w* months?)?( ?[-+]?\d?\w* years?)?/i';
$modify = preg_replace_callback(
$pattern,
function($matches) use ($pattern) {
if (empty($matches[0])) {
return;
}
$orDay = $this->format('j');
$this->setDate(null, null, 1);
if (!parent::modify($matches[0])) {
return;
}
$this->setDate(null, null, $orDay);
return;
},
$modify
);
if ($modify = trim($modify)) {
return parent::modify($modify);
}
return $this;
}
}
<?php
require_once __DIR__ . '/DateTime.php';
class DateTimeTest extends \PHPUnit_Framework_TestCase
{
public function providerSetDate()
{
$now = new \MyNamespace\DateTime();
return array(
array('2014-02-28', 31, 2),
array('2014-02-01', 1, 2),
array('2014-06-30', 31, 6),
array($now->format('Y-m-d'), null, null, null),
);
}
/**
* @test
* @dataProvider providerSetDate
*/
public function setDate($result, $day, $month, $year = '2014')
{
$dateTime = new \MyNamespace\DateTime();
$dateTime->setDate($year, $month, $day);
$this->assertEquals($result, $dateTime->format('Y-m-d'));
}
public function providerModify()
{
return array(
array('2014-02-28', '0 day 0 month 0 year'),
array('2014-01-28', 'next month'),
array('2014-01-28', 'next months'),
array('2014-01-02', '+1 month', '2014-02-02'),
array('2014-01-31', '1 months'),
array('2014-03-31', '-1 month'),
array('2012-02-29', '24 month'),
array('2016-02-29', '-24 months'),
array('2014-02-27', 'next day'),
array('2014-02-27', '1 day'),
array('2014-02-27', '+1 day'),
array('2013-02-01', '-1 day next month next year'),
array('2013-01-27', '1 day 1 month 1 year'),
array('2015-04-01', '-1 day -1 month -1 year'),
array('2011-12-26', '2 day 2 month 2 year'),
array('2011-12-31', '2 month 2 year'),
);
}
/**
* @test
* @dataProvider providerModify
*/
public function modify($date, $shift, $result = '2014-02-28')
{
$dateTime = new \MyNamespace\DateTime($date);
$dateTime->modify($shift);
$this->assertEquals($result, $dateTime->format('Y-m-d'));
}
/**
* @test
* @expectedException PHPUnit_Framework_Error_Warning
*/
public function modifyError()
{
$dateTime = new \MyNamespace\DateTime();
$dateTime->modify('2 month sdfg year');
}
}
@prgTW
Copy link

prgTW commented Sep 8, 2014

Below version with fixed handling of \DateInterval. Please re-check

<?php
class DateTime extends \DateTime
    /*
     PREVIOUS CODE HERE
     */
    /** {@inheritdoc} */
    public function add(DateInterval $interval)
    {
        $format = $this->intervalToString($interval, $interval->invert ? '-' : '+');

        return $this->modify($format);
    }

    /** {@inheritdoc} */
    public function sub(DateInterval $interval)
    {
        $format = $this->intervalToString($interval, $interval->invert ? '+' : '-');

        return $this->modify($format);
    }

    /**
     * @param DateInterval $interval
     * @param string       $sign
     *
     * @return string
     */
    protected function intervalToString(\DateInterval $interval, $sign)
    {
        $format = vsprintf('%1$s%2$d years %1$s%3$d months %1$s%4$d days %1$s%5$d hours %1$s%6$d minutes %1$s%7$d seconds', [
            $sign,
            $interval->y,
            $interval->m,
            $interval->d,
            $interval->h,
            $interval->i,
            $interval->s,
        ]);

        return $format;
    }
}
<?php
require_once __DIR__ . '/DateTime.php';

class DateTimeTest extends \PHPUnit_Framework_TestCase
{
    /*
     PREVIOUS CODE HERE
     */

    /**
     * @dataProvider providerAdd
     */
    public function testAdd($date, $format, $result = '2014-02-28')
    {
        $dateTime = new SqlDateTime($date);
        $dateTime->add(new \DateInterval($format));
        $this->assertEquals($result, $dateTime->format('Y-m-d'));
    }

    public function providerAdd()
    {
        return array(
            array('2014-02-28', 'PT1S'),
            array('2014-01-28', 'P1M'),
            array('2014-01-02', 'P1M', '2014-02-02'),
            array('2014-01-31', 'P1M'),
            array('2014-01-31', 'P2M', '2014-03-31'),
            array('2014-01-30', 'P3M', '2014-04-30'),
            array('2012-02-29', 'P2Y'),
            array('2012-02-29', 'P24M'),
            array('2014-02-27', 'P1D'),
            array('2013-01-27', 'P1Y1M1D'),
            array('2011-12-26', 'P2Y2M2D'),
            array('2011-12-31', 'P2Y2M'),
        );
    }

    /**
     * @dataProvider providerSub
     */
    public function testSub($date, $format, $result = '2014-02-28')
    {
        $dateTime = new SqlDateTime($date);
        $dateTime->sub(new \DateInterval($format));
        $this->assertEquals($result, $dateTime->format('Y-m-d'));
    }

    public function providerSub()
    {
        return array(
            array('2014-03-31', 'P1M'),
            array('2016-02-29', 'P24M'),
            array('2015-04-01', 'P1Y1M1D'),
        );
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment