阅读时间4分钟 (803个单词)

日期包总结,第2部分

Summary for Date Package, Part 2

不喜欢Joomla\DateTime中处理翻译的方式?或许你想更改一些日期计算的功能?好吧,这不是问题。让我们定制你的DateTime对象。

我真的可以定制DateTime的行为吗?

是的,你可以!但仅限于使用Joomla\DateTime。你可以在不修改DateTime类本身的情况下更改一些事情。你可以

  • 添加新的getter,
  • 添加新的解析器,
  • 更改since方法的处理方式,
  • 更改翻译的处理方式,
  • 更改日期计算的处理方式。

第一篇文章中,我展示了如何添加新的getter和解析器。在这篇文章中,我将介绍其余的内容。

since方法

有两种since方法:since()和sinceAlmost()。它们都能生成两个日期之间时间差的字符串

$today = DateTime::today();
echo $today->since(DateTime::yesterday()); // output: '1 day ago'

它们之间的区别在于sinceAlmost()添加了“几乎”前缀,并进行了一些近似

$date = new DateTime('2014-08-24 16:00');
echo $today->sinceAlmost(new DateTime('2014-08-24 15:02')); // output: 'almost 1 hour ago'

这是默认功能,你可以轻松地更改它。为了做到这一点,你需要编写一个实现SinceInterface的类

interface SinceInterface
{
    public function since(DateTime $base, DateTime $datetime = null, $detailLevel = 1);

    public function almost(DateTime $base, DateTime $datetime = null);
}

当你有了它,你还需要将你的SinceInterface对象注入到DateTime中

use Joomla\DateTime\DateTime;
DateTime::setSince(new MySince());

就是这样。

翻译

很可能你有自己的翻译系统,并且更喜欢使用它而不是默认系统。你可以通过非常简单的方式实现这一点——只需看看AbstractTranslation类即可

abstract class AbstractTranslator
{
    protected $locale = 'en';

    public function setLocale($locale)
    {
        $this->locale = $locale;
    }

    /** Returns a translated item. */
    abstract public function get($item, array $replace = array());

    /** Returns a translated item with a proper form for pluralization. */
    abstract public function choice($item, $number, array $replace = array());
}

如你所见,你需要实现两个方法,然后你可以注入自己的翻译器

use Joomla\DateTime\DateTime;
DateTime::setTranslator(new MyTranslator());

策略

假设你不喜欢startOfDay()方法返回午夜时间——或许你希望它是9点钟。这类行为修改可以通过创建自己的Strategy对象来实现,该对象必须实现StrategyInterface

interface StrategyInterface
{
    public function startOfDay(\DateTime $datetime);

    public function endOfDay(\DateTime $datetime);

    public function startOfWeek(\DateTime $datetime);

    public function startOfMonth(\DateTime $datetime);

    public function endOfMonth(\DateTime $datetime);

    public function startOfYear(\DateTime $datetime);

    public function endOfYear(\DateTime $datetime);
}

在包中有一个名为DateTimeStrategy的类,它实现了该接口,并返回以下值

startOfDay()    // The current day at 00:00:00
endOfDay()      // The current day at 23:59:59
startOfWeek() // Monday of the current week at 00:00:00 endOfWeek() // Sunday of the current week at 23:59:59
startOfMonth() // First day of the current month at 00:00:00 endOfMonth() // Last day of the current month at 23:59:59
startOfYear() // First day of the current year at 00:00:00 endOfYear() // Last day of the current year at 23:59:59

假设我们想更改startOfDay()和endOfDay()的返回值,将它们更改为9:00和17:00。实际上,我们只想覆盖两个默认行为,因此最好通过扩展DateTimeStrategy而不是实现StrategyInterface来创建类。

use Joomla\DateTime\Strategy\DateTimeStrategy;
class MyStrategy extends DateTimeStrategy
{
    public function startOfDay(\DateTime $datetime)
    {
        $datetime->setTime(9, 0, 0);
    }
public function endOfDay(\DateTime $datetime) { $datetime->setTime(17, 0, 0); } }

请注意,在 StrategyInterface 的所有方法中,我们都得到一个 PHP DateTime 对象,并利用其可变性。我们对该 PHP DateTime 对象进行所有更改,甚至不需要返回它。

实际上,更改 StrategyInterface 是一个重要的过程。这也是为什么没有公共静态 setStrategy() 方法,因为它会带来更多麻烦而不是收益。例如,我们的项目中不可能有两个不同的策略。因为当我们把 StrategyInterface 作为类属性时,我们只能有一个。

来回更改 StrategyInterface 也不是一个好主意。我们也不能为我们的对象设置 StrategyInterface,因为当我们忘记设置了,我们会得到很多意外的结果。所以为了提醒我们是否设置了某些内容,我们需要一个对象来告诉我们。

如何做到这一点?创建一个自定义的 DateTime 并在构造函数中设置 StrategyInterface

use Joomla\DateTime\DateTime;
class MyDateTime extends DateTime
{
    public function __construct($datetime, \DateTimeZone $timezone = null)
    {
        parent::__construct($datetime, $timezone);
        $this->setStrategy(new MyStrategy());
    }
}

现在,在所有我们会得到 MyDateTime 对象的地方,我们都可以确定这个对象已经更改了某些方法的行为。

Joomla 社区杂志上发布的一些文章代表了作者在特定主题上的个人观点或经验,可能并不代表 Joomla 项目的官方立场

0
新的 Joomla 资源目录!
 

评论

已注册? 登录这里
暂无评论。成为第一个发表评论的人

通过接受,您将访问 https://magazine.joomla.net.cn/ 外部第三方提供的服务