elnur/era

日期和时间库

dev-master 2015-06-24 16:22 UTC

This package is not auto-updated.

Last update: 2024-09-28 14:37:54 UTC


README

Build Status

Era 是一个日期和时间库。

日历

如果代码与系统时间相关联,基于日期时间的测试很难进行。假设您有一个年龄计算器

<?php
class AgeCalculator
{
    /**
     * @param DateTime $from
     * @return int
     */
    public function age(DateTime $from)
    {
        $now = new DateTime;

        return $from->diff($now)->y;
    }
}

以及对其的测试

<?php
class AgeCalculatorTest extends PHPUnit_Framework_TestCase
{
    public function testAge()
    {
        $ageCalculator = new AgeCalculator;
        $birthdate = new DateTime('1987-05-31');

        $this->assertEquals(25, $ageCalculator->age($birthdate));
    }
}

现在,这个测试是脆弱的,因为它只在 2012-05-312013-05-30 之间通过。在那之后,它将开始失败。

要使您的代码与系统时间解耦,您需要为它提供一个抽象层。这时就出现了 Calendar

<?php
use Elnur\Era\CalendarInterface;

class AgeCalculator
{
    /**
     * @var CalendarInterface
     */
    private $calendar;

    /**
     * @var CalendarInterface $calendar
     */
    public function __construct(CalendarInterface $calendar)
    {
        $this->calendar = $calendar;
    }

    /**
     * @param DateTime $from
     * @return int
     */
    public function age(DateTime $from)
    {
        $now = $this->calendar->now();

        return $from->diff($now)->y;
    }
}

注意我们是如何使用一个 CalendarInterface 实例来获取当前日期时间的。现在,您可以对其进行模拟以使测试更加稳固

<?php
class AgeCalculatorTest extends PHPUnit_Framework_TestCase
{
    public function testAge()
    {
        $now = new DateTime('2012-05-31');

        $calendar = $this->getMockForAbstractClass('Elnur\Era\CalendarInterface');
        $calendar
            ->expects($this->any())
            ->method('now')
            ->will($this->returnValue($now))
        ;

        $ageCalculator = new AgeCalculator($calendar);
        $birthdate = new DateTime('1987-05-31');

        $this->assertEquals(25, $ageCalculator->age($birthdate));
    }
}

现在,测试不会因为时间的流逝而失败。

下面是如何使用您的新颖的 AgeCalculator

<?php
$calendar = new Calendar;
$ageCalculator = new AgeCalculator($calendar);

$birthdate = new DateTime('1987-05-31');
$age = $ageCalculator->age($birthdate);

AgeCalculator

AgeCalculator 是上面实现的类,但进行了一些调整:如果您要求它计算未来的某个东西的年龄,它将返回 0