Carbon中文使用手册(下)

·         Serialization

Carbon实例能被序列化的。

$dt = Carbon::create(2012, 12, 25, 20, 30, 00, ‘Europe/Moscow’);

echo serialize($dt);                                              // O:13:”Carbon\Carbon”:3:{s:4:”date”;s:26:”2012-12-25 20:30:00.000000″;s:13:”timezone_type”;i:3;s:8:”timezone”;s:13:”Europe/Moscow”;}
// 等同于:
echo $dt->serialize();                                            // O:13:”Carbon\Carbon”:3:{s:4:”date”;s:26:”2012-12-25 20:30:00.000000″;s:13:”timezone_type”;i:3;s:8:”timezone”;s:13:”Europe/Moscow”;}

$dt = ‘O:13:”Carbon\Carbon”:3:{s:4:”date”;s:26:”2012-12-25 20:30:00.000000″;s:13:”timezone_type”;i:3;s:8:”timezone”;s:13:”Europe/Moscow”;}’;

echo unserialize($dt)->format(‘Y-m-d\TH:i:s.uP T’);               // 2012-12-25T20:30:00.000000+04:00 MSK
// 等同于:
echo Carbon::fromSerialized($dt)->format(‘Y-m-d\TH:i:s.uP T’);    // 2012-12-25T20:30:00.000000+04:00 MSK

·         JSON

Carbon实例可以从JSON编码和解码(这些特性只能从PHP 5.4+中获得,参见下面关于PHP 5.3的注释)

$dt = Carbon::create(2012, 12, 25, 20, 30, 00, ‘Europe/Moscow’);
echo json_encode($dt);
// {“date”:”2012-12-25 20:30:00.000000″,”timezone_type”:3,”timezone”:”Europe\/Moscow”}

$json = ‘{“date”:”2012-12-25 20:30:00.000000″,”timezone_type”:3,”timezone”:”Europe\/Moscow”}’;
$dt = Carbon::__set_state(json_decode($json, true));
echo $dt->format(‘Y-m-d\TH:i:s.uP T’);
// 2012-12-25T20:30:00.000000+04:00 MSK

您可以使用serializeUsing()自定义序列化。

$dt = Carbon::create(2012, 12, 25, 20, 30, 00, ‘Europe/Moscow’);
Carbon::serializeUsing(function ($date) {
    return $date->getTimestamp();
});
echo json_encode($dt);
/*
1356453000
*/

// Call serializeUsing with null to reset the serializer:
Carbon::serializeUsing(null);

jsonSerialize()方法返回中间通过“json_encode”将其转换为字符串,它还允许您使用PHP 5.3兼容性。

$dt = Carbon::create(2012, 12, 25, 20, 30, 00, ‘Europe/Moscow’);
echo json_encode($dt->jsonSerialize());
// {“date”:”2012-12-25 20:30:00.000000″,”timezone_type”:3,”timezone”:”Europe\/Moscow”}
// This is equivalent to the first json_encode example but works with PHP 5.3.

// And it can be used separately:
var_dump($dt->jsonSerialize());
// array(3) {
[“date”]=>
  string(26) “2012-12-25 20:30:00.000000”
[“timezone_type”]=>
  int(3)
  [“timezone”]=>
  string(13) “Europe/Moscow”
}

·         Macro

如果您习惯于使用Laravel和对象(如响应或集合),您可能熟悉这个宏概念。Carbon macro()的工作方式与Laravel宏特性相同,它将方法名作为第一个参数,闭包作为第二个参数。这使得闭包操作可以作为一个具有给定名称的方法在所有Carbon实例(也可以作为Carbon static方法)上使用。

PHP 5.4中,$this可用于闭包中引用当前实例。对于PHP 5.3的兼容性,我们还向闭包添加了一个“$self”属性。例子:

Carbon::macro(‘diffFromYear’, function ($year, $self = null) {
    // 
这个块是为了在独立的Carbon上与PHP版本< 5.4和Laravel兼容
    if (!isset($self) && isset($this)) {
        $self = $this;
    }
    //兼容性块的结束。

    return $self->diffForHumans(Carbon::create($year, 1, 1, 0, 0, 0), false, false, 3);
});
echo Carbon::parse(‘2020-01-12 12:00:00’)->diffFromYear(2019);                 // 1 year 1 week 4 days after

兼容性块允许您确保宏的完全兼容性。一个关于Illuminate\Support\Carbon (Laravel包装类)的宏将不会被定义,正如上面在PHP 5.3 $this中提到的,这个不会被定义。要使宏在任何地方都能工作,只需粘贴这个if语句测试如果它是定义的,而不是$self然后复制它,然后在函数体中使用$self

不管您是否省略了一些可选参数,只要$self有这个名称,并且是最后一个参数:

Carbon::macro(‘diffFromYear’, function ($year, $absolute = false, $short = false, $parts = 1, $self = null) {
    // compatibility chunk
    if (!isset($self) && isset($this)) {
        $self = $this;
    }

    return $self->diffForHumans(Carbon::create($year, 1, 1, 0, 0, 0), $absolute, $short, $parts);
});

echo Carbon::parse(‘2020-01-12 12:00:00’)->diffFromYear(2019);                 // 1 year after
echo Carbon::parse(‘2020-01-12 12:00:00’)->diffFromYear(2019, true);           // 1 year
echo Carbon::parse(‘2020-01-12 12:00:00’)->diffFromYear(2019, true, true);     // 1yr
echo Carbon::parse(‘2020-01-12 12:00:00’)->diffFromYear(2019, true, true, 5);  // 1yr 1w 4d 12h

还可以将宏分组到类中,并与mixin()一起应用

Class BeerDayCarbonMixin
{
    public function nextBeerDay()
    {
        return function ($self = null) {
            // compatibility chunk
            if (!isset($self) && isset($this)) {
                $self = $this;
            }

            return $self->modify(‘next wednesday’);
        };
    }

    public function previousBeerDay()
    {
        return function ($self = null) {
            // compatibility chunk
            if (!isset($self) && isset($this)) {
                $self = $this;
            }

            return $self->modify(‘previous wednesday’);
        };
    }
}

Carbon::mixin(new BeerDayCarbonMixin());

$date = Carbon::parse(‘First saturday of December 2018’);

echo $date->previousBeerDay();                                                 // 2018-11-28 00:00:00
echo $date->nextBeerDay();                                                     // 2018-12-05 00:00:00

您可以用hasMacro()检查是否可用宏(包括mixin)

var_dump(Carbon::hasMacro(‘previousBeerDay’));                                 // bool(true)
var_dump(Carbon::hasMacro(‘diffFromYear’));                                    // bool(true)
var_dump(Carbon::hasMacro(‘dontKnowWhat’));                                    // bool(false)

你猜怎么着?CarbonIntervalCarbonPeriod类上也可以使用所有的宏方法。

CarbonInterval::macro(‘twice’, function ($self = null) {
    return $self->times(2);
});
echo CarbonInterval::day()->twice()->forHumans();                        // 2 days
echo CarbonInterval::hours(2)->minutes(15)->twice()->forHumans(true);    // 4h 30m

CarbonPeriod::macro(‘countWeekdays’, function ($self = null) {
    return $self->filter(‘isWeekday’)->count();
});
echo CarbonPeriod::create(‘2017-11-01’, ‘2017-11-30’)->countWeekdays();  // 22
echo CarbonPeriod::create(‘2017-12-01’, ‘2017-12-31’)->countWeekdays();  // 21

以下是社区提出的一些有用的宏:

Carbon::macro(‘isHoliday’, function ($self = null) {
    // compatibility chunk
    if (!isset($self) && isset($this)) {
        $self = $this;
    }

    return in_array($self->format(‘d/m’), [
        ’25/12′, // Christmas
        ’01/01′, // New Year
        // …
    ]);
});
var_dump(Carbon::createMidnightDate(2012, 12, 25)->isHoliday());  // bool(true)
var_dump(Carbon::createMidnightDate(2017, 6, 25)->isHoliday());   // bool(false)
var_dump(Carbon::createMidnightDate(2021, 1, 1)->isHoliday());    // bool(true)

Credit:kylekatarnls(# 116)

检查cmixin/业务日以获得更完整的业务日处理程序。

Class CurrentDaysCarbonMixin
{
    /**
     * Get the all dates of week
     *
     * @return array
     */
    public static function getCurrentWeekDays()
    {
        return function ($self = null) {
            // compatibility chunk
            if (!isset($self) && isset($this)) {
                $self = $this;
            }

            $startOfWeek = ($self ?: static::now())->startOfWeek()->subDay();
            $weekDays = array();

            for ($i = 0; $i < static::DAYS_PER_WEEK; $i++) {
                $weekDays[] = $startOfWeek->addDay()->startOfDay()->copy();
            }

            return $weekDays;
        };
    }

    /**
     * Get the all dates of month
     *
     * @return array
     */
    public static function getCurrentMonthDays()
    {
        return function ($self = null) {
            // compatibility chunk
            if (!isset($self) && isset($this)) {
                $self = $this;
            }

            $startOfMonth = ($self ?: static::now())->startOfMonth()->subDay();
            $endOfMonth = ($self ?: static::now())->endOfMonth()->format(‘d’);
            $monthDays = array();

            for ($i = 0; $i < $endOfMonth; $i++)
            {
                $monthDays[] = $startOfMonth->addDay()->startOfDay()->copy();
            }

            return $monthDays;
        };
    }
}

Carbon::mixin(new CurrentDaysCarbonMixin());

function dumpDateList($dates) {
    echo substr(implode(‘, ‘, $dates), 0, 100).’…’;
}

dumpDateList(Carbon::getCurrentWeekDays());                       // 2018-07-02 00:00:00, 2018-07-03 00:00:00, 2018-07-04 00:00:00, 2018-07-05 00:00:00, 2018-07-06 00:00…
dumpDateList(Carbon::getCurrentMonthDays());                      // 2018-07-01 00:00:00, 2018-07-02 00:00:00, 2018-07-03 00:00:00, 2018-07-04 00:00:00, 2018-07-05 00:00…
dumpDateList(Carbon::now()->subMonth()->getCurrentWeekDays());    // 2018-06-04 00:00:00, 2018-06-05 00:00:00, 2018-06-06 00:00:00, 2018-06-07 00:00:00, 2018-06-08 00:00…
dumpDateList(Carbon::now()->subMonth()->getCurrentMonthDays());   // 2018-06-01 00:00:00, 2018-06-02 00:00:00, 2018-06-03 00:00:00, 2018-06-04 00:00:00, 2018-06-05 00:00…

Credit: meteguerlek (#1191).

Carbon::macro(‘toAtomStringWithNoTimezone’, function ($self = null) {
    // compatibility chunk
    if (!isset($self) && isset($this)) {
        $self = $this;
    }

    return $self->format(‘Y-m-d\TH:i:s’);
});
echo Carbon::parse(‘2021-06-16 20:08:34’)->toAtomStringWithNoTimezone(); // 2021-06-16T20:08:34

Credit: afrojuju1 (#1063).

Carbon::macro(‘easterDate’, function ($year) {    
    return Carbon::createMidnightDate($year, 3, 21)->addDays(easter_days($year));
});
    echo Carbon::easterDate(2015)->format(‘d/m’); // 05/04
    echo Carbon::easterDate(2016)->format(‘d/m’); // 27/03
    echo Carbon::easterDate(2017)->format(‘d/m’); // 16/04
    echo Carbon::easterDate(2018)->format(‘d/m’); // 01/04
    echo Carbon::easterDate(2019)->format(‘d/m’); // 21/04

Credit: andreisena36864 (#1052).

查看cmixin/工作日以获得更完整的假日处理程序。

Carbon::macro(‘range’, function ($startDate, $endDate) {
    return new DatePeriod($startDate, new DateInterval(‘P1D’), $endDate);
});
foreach (Carbon::range(Carbon::createMidnightDate(2019, 3, 28), Carbon::createMidnightDate(2019, 4, 3)) as $date) {
    echo “$date\n”;
}
/*
2019-03-28 00:00:00
2019-03-29 00:00:00
2019-03-30 00:00:00
2019-03-31 00:00:00
2019-04-01 00:00:00
2019-04-02 00:00:00
*/

Credit: reinink (#132).

class UserTimezoneCarbonMixin
{
    public $userTimeZone;

    /**
     * Set user timezone, will be used before format function to apply current user timezone
     *
     * @param $timezone
     */
    public function setUserTimezone()
    {
        $mixin = $this;

        return function ($timezone) use ($mixin) {
            $mixin->userTimeZone = $timezone;
        };
    }

    /**
     * Returns date formatted according to given format.
     *
     * @param string $format
     *
     * @return string
     *
     * @link http://php.net/manual/en/datetime.format.php
     */
    public function tzFormat()
    {
        $mixin = $this;

        return function ($format, $self = null) use ($mixin) {
            // compatibility chunk
            if (!isset($self) && isset($this)) {
                $self = $this;
            }

            if (!is_null($mixin->userTimeZone)) {
                $self->timezone($mixin->userTimeZone);
            }

            return $self->format($format);
        };
    }
}

Carbon::mixin(new UserTimezoneCarbonMixin());

Carbon::setUserTimezone(‘Europe/Berlin’);
echo Carbon::createFromTime(12, 0, 0, ‘UTC’)->tzFormat(‘H:i’); // 14:00
echo Carbon::createFromTime(15, 0, 0, ‘UTC’)->tzFormat(‘H:i’); // 17:00
Carbon::setUserTimezone(‘America/Toronto’);
echo Carbon::createFromTime(12, 0, 0, ‘UTC’)->tzFormat(‘H:i’); // 08:00
echo Carbon::createFromTime(15, 0, 0, ‘UTC’)->tzFormat(‘H:i’); // 11:00

Credit: thiagocordeiro (#927).

·         CarbonInterval

CarbonInterval类继承了PHP DateInterval类。

<?php
class CarbonInterval extends \DateInterval
{    
    // code here
}

你可以通过以下方式创建实例

echo CarbonInterval::year();                           // 1 year
echo CarbonInterval::months(3);                        // 3 months
echo CarbonInterval::days(3)->seconds(32);             // 3 days 32 seconds
echo CarbonInterval::weeks(3);                         // 3 weeks
echo CarbonInterval::days(23);                         // 3 weeks 2 days
echo CarbonInterval::create(2, 0, 5, 1, 1, 2, 7);      // 2 years 5 weeks 1 day 1 hour 2 minutes 7 seconds

如果您发现自己从另一个库继承了\DateInterval实例,不要害怕!您可以通过一个友好的instance()函数创建一个CarbonInterval实例。

$di = new \DateInterval(‘P1Y2M’); // <== instance from another API
$ci = CarbonInterval::instance($di);
echo get_class($ci);                                   // ‘Carbon\CarbonInterval’
echo $ci;                                              // 1 year 2 months

其他的帮助程序,但是要注意实现提供了帮助程序来处理几周,但是只节省了几天。数周是根据当前实例的总天数计算的。

echo CarbonInterval::year()->years;                    // 1
echo CarbonInterval::year()->dayz;                     // 0
echo CarbonInterval::days(24)->dayz;                   // 24
echo CarbonInterval::days(24)->daysExcludeWeeks;       // 3
echo CarbonInterval::weeks(3)->days(14)->weeks;        // 2  <– days setter overwrites the current value
echo CarbonInterval::weeks(3)->weeks;                  // 3
echo CarbonInterval::minutes(3)->weeksAndDays(2, 5);   // 2 weeks 5 days 3 minutes

CarbonInterval扩展DateInterval,您可以使用ISO-8601的持续时间格式创建这两种格式:

$ci = CarbonInterval::create(‘P1Y2M3D’);
$ci = new CarbonInterval(‘PT0S’);

借助fromString()方法,可以从友好的字符串创建Carbon intervals

CarbonInterval::fromString(‘2 minutes 15 seconds’);

 CarbonInterval::fromString(‘2m 15s’); // or abbreviated

注意这个月缩写为“mo”以区别于分钟和整个语法不区分大小写。

它还有一个方便的for human(),它被映射为__toString()实现,用于为人类打印间隔。

CarbonInterval::setLocale(‘fr’);
echo CarbonInterval::create(2, 1)->forHumans();        // 2 ans 1 mois
echo CarbonInterval::hour()->seconds(3);               // 1 heure 3 secondes
CarbonInterval::setLocale(‘en’);

如您所见,您可以使用CarbonInterval::setLocale(‘fr’)更改字符串的语言环境。

至于Carbon,您可以使用make方法从其他区间或字符串返回一个新的CarbonInterval实例:

$dateInterval = new DateInterval(‘P2D’);
$carbonInterval = CarbonInterval::month();
echo CarbonInterval::make($dateInterval)->forHumans();       // 2 days
echo CarbonInterval::make($carbonInterval)->forHumans();     // 1 month
echo CarbonInterval::make(‘PT3H’)->forHumans();              // 3 hours
echo CarbonInterval::make(‘1h 15m’)->forHumans();            // 1 hour 15 minutes
// Pass true to get short format
echo CarbonInterval::make(‘1h 15m’)->forHumans(true);        // 1h 15m

本机DateInterval分别添加和相乘,因此:

$interval = CarbonInterval::make(‘7h 55m’);
$interval->add(CarbonInterval::make(’17h 35m’));
$interval->times(3);
echo $interval->forHumans(); // 72 hours 270 minutes

从单位到单位的输入中得到纯计算。将分钟级联成小时、小时级联成天等。使用级联方法:

echo $interval->forHumans();             // 72 hours 270 minutes
echo $interval->cascade()->forHumans();  // 3 days 4 hours 30 minutes

默认的因素有:

1分钟= 60

1小时=60分钟

1=24小时

1= 7

1个月= 4

1= 12个月

CarbonIntervals 没有上下文,所以它们不能更精确(没有DST、没有闰年、没有实际的月长或年长)。但是你可以完全定制这些因素。例如处理工作时间日志:

$cascades = CarbonInterval::getCascadeFactors(); // save initial factors

CarbonInterval::setCascadeFactors(array(
    ‘minute’ => array(60, ‘seconds’),
    ‘hour’ => array(60, ‘minutes’),
    ‘day’ => array(8, ‘hours’),
    ‘week’ => array(5, ‘days’),
    // in this example the cascade won’t go farther than week unit
));

echo CarbonInterval::fromString(’20h’)->cascade()->forHumans();              // 2 days 4 hours
echo CarbonInterval::fromString(’10d’)->cascade()->forHumans();              // 2 weeks
echo CarbonInterval::fromString(‘3w 18d 53h 159m’)->cascade()->forHumans();  // 7 weeks 4 days 7 hours 39 minutes

// You can see currently set factors with getFactor:
echo CarbonInterval::getFactor(‘minutes’, /* per */ ‘hour’);                 // 60
echo CarbonInterval::getFactor(‘days’, ‘week’);                              // 5

// And common factors can be get with short-cut methods:
echo CarbonInterval::getDaysPerWeek();                                       // 5
echo CarbonInterval::getHoursPerDay();                                       // 8
echo CarbonInterval::getMinutesPerHours();                                   // 60
echo CarbonInterval::getSecondsPerMinutes();                                 // 60

CarbonInterval::setCascadeFactors($cascades); // restore original factors

是否可能将间隔转换为给定的单元(使用提供的级联因子)

echo CarbonInterval::days(3)->hours(5)->total(‘hours’);    // 77
echo CarbonInterval::days(3)->hours(5)->totalHours;        // 77
echo CarbonInterval::months(6)->totalWeeks;                // 24
echo CarbonInterval::year()->totalDays;                    // 336

您还可以使用spec()获得invervalISO 8601规范

echo CarbonInterval::days(3)->hours(5)->spec(); // P3DT5H

也可以从DateInterval对象获取它,因为它是静态助手:

echo CarbonInterval::getDateIntervalSpec(new DateInterval(‘P3DT6M10S’)); // P3DT6M10S

使用compare()comparedateinterval()方法可以对日期间隔列表进行排序:

$halfDay = CarbonInterval::hours(12);
$oneDay = CarbonInterval::day();
$twoDay = CarbonInterval::days(2);

echo CarbonInterval::compareDateIntervals($oneDay, $oneDay);   // 0
echo $oneDay->compare($oneDay);                                // 0
echo CarbonInterval::compareDateIntervals($oneDay, $halfDay);  // 1
echo $oneDay->compare($halfDay);                               // 1
echo CarbonInterval::compareDateIntervals($oneDay, $twoDay);   // -1
echo $oneDay->compare($twoDay);                                // -1

$list = array($twoDay, $halfDay, $oneDay);
usort($list, array(‘Carbon\CarbonInterval’, ‘compareDateIntervals’));

echo implode(‘, ‘, $list);                                     // 12 hours, 1 day, 2 days

最后,通过使用互补参数调用toPeriod(),可以将一个CarbonInterval实例转换为一个CarbonPeriod实例。 

我听到你问什么是CarbonPeriod 实例。哦!完美过渡到下一章。

·         CarbonPeriod

CarbonPeriod是一个友好的DatePeriod版本,具有许多快捷方式。

// Create a new instance:
$period = new CarbonPeriod(‘2018-04-21’, ‘3 days’, ‘2018-04-27’);
// Use static constructor:
$period = CarbonPeriod::create(‘2018-04-21’, ‘3 days’, ‘2018-04-27’);
// Use the fluent setters:
$period = CarbonPeriod::since(‘2018-04-21’)->days(3)->until(‘2018-04-27’);
// Start from a CarbonInterval:
$period = CarbonInterval::days(3)->toPeriod(‘2018-04-21’, ‘2018-04-27’);

CarbonPeriod可以通过多种方式构建:

开始日期、结束日期和可选间隔(默认为1)

起始日期,递归次数和可选区间,

ISO 8601间隔规范。

日期可以是DateTime/Carbon实例,绝对字符串如“2007-10-15 15:00”或相对字符串,例如“next monday”Interval可以作为DateInterval/CarbonInterval实例、ISO 8601Interval规范(“P4D”)或人类可读字符串(“4 days”)给出。

默认构造函数和create()方法在参数类型和顺序方面都很容易理解,所以如果您想要更精确,建议使用fluent语法。另一方面,您可以将动态值数组传递给createFromArray(),它将使用给定的数组作为参数列表构造一个新实例。

CarbonPeriod实现迭代器接口。它意味着它可以直接传递给foreach循环:

$period = CarbonPeriod::create(‘2018-04-21’, ‘3 days’, ‘2018-04-27’);
foreach ($period as $key => $date) {
    if ($key) {
        echo ‘, ‘;
    }
    echo $date->format(‘m-d’);
}
// 04-21, 04-24, 04-27

// Here is what happens under the hood:
$period->rewind(); // restart the iteration
while ($period->valid()) { // check if current item is valid
    if ($period->key()) { // echo comma if current key is greater than 0
        echo ‘, ‘;
    }
    echo $period->current()->format(‘m-d’); // echo current date
    $period->next(); // move to the next item
}
// 04-21, 04-24, 04-27

参数可以在迭代过程中进行修改:

$period = CarbonPeriod::create(‘2018-04-29’, 7);
$dates = array();
foreach ($period as $key => $date) {
    if ($key === 3) {
        $period->invert()->start($date); // invert() is an alias for invertDateInterval()
    }
    $dates[] = $date->format(‘m-d’);
}

echo implode(‘, ‘, $dates); // 04-29, 04-30, 05-01, 05-02, 05-01, 04-30, 04-29

DatePeriod一样,CarbonPeriod也支持ISO 8601时间间隔规范。

请注意,本机日期周期将递归处理为多次重复间隔。因此,在排除开始日期时,它将减少一个结果。CarbonPeriod的自定义过滤器的引入使得知道结果的数量变得更加困难。由于这个原因,我们稍微改变了实现,递归被视为返回日期的总体限制。

// Possible options are: CarbonPeriod::EXCLUDE_START_DATE | CarbonPeriod::EXCLUDE_END_DATE
// Default value is 0 which will have the same effect as when no options are given.
$period = CarbonPeriod::createFromIso(‘R4/2012-07-01T00:00:00Z/P7D’, CarbonPeriod::EXCLUDE_START_DATE);
$dates = array();
foreach ($period as $date) {
    $dates[] = $date->format(‘m-d’);
}

echo implode(‘, ‘, $dates); // 07-08, 07-15, 07-22, 07-29

您可以从不同的getter中检索数据:

$period = CarbonPeriod::create(‘2010-05-06’, ‘2010-05-25’, CarbonPeriod::EXCLUDE_START_DATE);

$exclude = $period->getOptions() & CarbonPeriod::EXCLUDE_START_DATE;

echo $period->getStartDate();            // 2010-05-06 00:00:00
echo $period->getEndDate();              // 2010-05-25 00:00:00
echo $period->getDateInterval();         // 1 day
echo $exclude ? ‘exclude’ : ‘include’;   // exclude

var_dump($period->isStartExcluded());    // bool(true)
var_dump($period->isEndExcluded());      // bool(false)

echo $period->toString();                // Every 1 day from 2010-05-06 to 2010-05-25
echo $period; /*implicit toString*/      // Every 1 day from 2010-05-06 to 2010-05-25

附加的getter允许您以数组的形式访问结果:

$period = CarbonPeriod::create(‘2010-05-11’, ‘2010-05-13’);

echo $period->count();                   // 3, equivalent to count($period)
echo implode(‘, ‘, $period->toArray());  // 2010-05-11 00:00:00, 2010-05-12 00:00:00, 2010-05-13 00:00:00
echo $period->first();                   // 2010-05-11 00:00:00
echo $period->last();                    // 2010-05-13 00:00:00

注意,如果您打算使用上述函数,将toArray()调用的结果存储为变量并使用它是一个好主意,因为每个调用在内部执行一个完整的迭代。

想要更改参数,可以使用setter方法:

$period = CarbonPeriod::create(‘2010-05-01’, ‘2010-05-14’, CarbonPeriod::EXCLUDE_END_DATE);

$period->setStartDate(‘2010-05-11’);
echo implode(‘, ‘, $period->toArray());  // 2010-05-11 00:00:00, 2010-05-12 00:00:00, 2010-05-13 00:00:00

// Second argument can be optionally used to exclude the date from the results.
$period->setStartDate(‘2010-05-11’, false);
$period->setEndDate(‘2010-05-14’, true);
echo implode(‘, ‘, $period->toArray());  // 2010-05-12 00:00:00, 2010-05-13 00:00:00, 2010-05-14 00:00:00

$period->setRecurrences(2);
echo implode(‘, ‘, $period->toArray());  // 2010-05-12 00:00:00, 2010-05-13 00:00:00

$period->setDateInterval(‘PT12H’);
echo implode(‘, ‘, $period->toArray());  // 2010-05-11 12:00:00, 2010-05-12 00:00:00

您可以使用setOptions()更改选项以替换所有选项,但也可以分别更改:

$period = CarbonPeriod::create(‘2010-05-06’, ‘2010-05-25’);

var_dump($period->isStartExcluded());    // bool(false)
var_dump($period->isEndExcluded());      // bool(false)

$period->toggleOptions(CarbonPeriod::EXCLUDE_START_DATE, true); // true, false or nothing to invert the option
var_dump($period->isStartExcluded());    // bool(true)
var_dump($period->isEndExcluded());      // bool(false) (unchanged)

$period->excludeEndDate();               // specify false to include, true or omit to exclude
var_dump($period->isStartExcluded());    // bool(true) (unchanged)
var_dump($period->isEndExcluded());      // bool(true)

$period->excludeStartDate(false);        // specify false to include, true or omit to exclude
var_dump($period->isStartExcluded());    // bool(false)
var_dump($period->isEndExcluded());      // bool(true)

如前所述,根据ISO 8601规范,递归是重复间隔的数倍。因此,本机DatePeriod将根据开始日期的排除而改变返回日期的数量。与此同时,CarbonPeriod在输入和允许自定义过滤器方面更加宽容,将递归作为返回日期的总体限制:

$period = CarbonPeriod::createFromIso(‘R4/2012-07-01T00:00:00Z/P7D’);
$days = array();
foreach ($period as $date) {
    $days[] = $date->format(‘d’);
}

echo $period->getRecurrences();          // 4
echo implode(‘, ‘, $days);               // 01, 08, 15, 22

$days = array();
$period->setRecurrences(3)->excludeStartDate();
foreach ($period as $date) {
    $days[] = $date->format(‘d’);
}

echo $period->getRecurrences();          // 3
echo implode(‘, ‘, $days);               // 08, 15, 22

$days = array();
$period = CarbonPeriod::recurrences(3)->sinceNow();
foreach ($period as $date) {
    $days[] = $date->format(‘Y-m-d’);
}

echo implode(‘, ‘, $days);               // 2018-07-05, 2018-07-06, 2018-07-07

DatePeriod返回的日期可以很容易地过滤。例如,过滤器可以用于跳过某些日期或只在工作日或周末迭代。筛选函数应该返回true以接受日期,返回false以跳过日期,但继续搜索或CarbonPeriod::END_ITERATION以结束迭代。

$period = CarbonPeriod::between(‘2000-01-01’, ‘2000-01-15’);
$weekendFilter = function ($date) {
    return $date->isWeekend();
};
$period->filter($weekendFilter);

$days = array();
foreach ($period as $date) {
    $days[] = $date->format(‘m-d’);
}
echo implode(‘, ‘, $days);                         // 01-01, 01-02, 01-08, 01-09, 01-15

您还可以跳过循环中的一个或多个值。

$period = CarbonPeriod::between(‘2000-01-01’, ‘2000-01-10’);
$days = array();
foreach ($period as $date) {
    $day = $date->format(‘m-d’);
    $days[] = $day;
    if ($day === ’01-04′) {
        $period->skip(3);
    }
}
echo implode(‘, ‘, $days);                         // 01-01, 01-02, 01-03, 01-04, 01-08, 01-09, 01-10

getFilters()允许您在一个时间段内检索所有存储的过滤器。但是要注意递归限制和结束日期将出现在返回的数组中,因为它们作为过滤器存储在内部。

$period = CarbonPeriod::end(‘2000-01-01’)->recurrences(3);
var_export($period->getFilters());
/*
array (
  0 => 
  array (
    0 => ‘Carbon\\CarbonPeriod::filterEndDate’,
    1 => NULL,
  ),
  1 => 
  array (
    0 => ‘Carbon\\CarbonPeriod::filterRecurrences’,
    1 => NULL,
  ),
)
*/

过滤器存储在堆栈中,可以使用一组特殊的方法进行管理:

$period = CarbonPeriod::between(‘2000-01-01’, ‘2000-01-15’);
$weekendFilter = function ($date) {
    return $date->isWeekend();
};

var_dump($period->hasFilter($weekendFilter));      // bool(false)
$period->addFilter($weekendFilter);
var_dump($period->hasFilter($weekendFilter));      // bool(true)
$period->removeFilter($weekendFilter);
var_dump($period->hasFilter($weekendFilter));      // bool(false)

// To avoid storing filters as variables you can name your filters:
$period->prependFilter(function ($date) {
    return $date->isWeekend();
}, ‘weekend’);

var_dump($period->hasFilter(‘weekend’));           // bool(true)
$period->removeFilter(‘weekend’);
var_dump($period->hasFilter(‘weekend’));           // bool(false)

添加过滤器的顺序会对性能和结果产生影响,因此您可以使用addFilter()在堆栈末尾添加过滤器;您可以使用prependFilter()在开始时添加一个。甚至可以使用setfilter()替换所有的过滤器。请注意,您必须保持堆栈的正确格式,并记住关于递归限制和结束日期的内部过滤器。或者,您可以使用resetFilters()方法,然后逐个添加新的过滤器。

例如,当您添加一个限制尝试日期数量的自定义过滤器时,如果您在工作日过滤器之前或之后添加它,那么结果将是不同的。

// Note that you can pass a name of any Carbon method starting with “is”, including macros
$period = CarbonPeriod::between(‘2018-05-03’, ‘2018-05-25’)->filter(‘isWeekday’);

$attempts = 0;
$attemptsFilter = function () use (&$attempts) {
    return ++$attempts <= 5 ? true : CarbonPeriod::END_ITERATION;
};

$period->prependFilter($attemptsFilter, ‘attempts’);
$days = array();
foreach ($period as $date) {
    $days[] = $date->format(‘m-d’);
}
echo implode(‘, ‘, $days);                         // 05-03, 05-04, 05-07

$attempts = 0;

$period->removeFilter($attemptsFilter)->addFilter($attemptsFilter, ‘attempts’);
$days = array();
foreach ($period as $date) {
    $days[] = $date->format(‘m-d’);
}
echo implode(‘, ‘, $days);                         // 05-03, 05-04, 05-07, 05-08, 05-09

注意,内置的递归过滤器不是这样工作的。相反,它基于当前键,每个条目只增加一次,无论在找到有效日期之前需要检查多少个日期。如果您将它放在堆栈的开头或末尾,那么这个技巧将使它的工作方式相同。

为了简化CarbonPeriod的构建,添加了一些别名:

// “start”, “since”, “sinceNow”:
CarbonPeriod::start(‘2017-03-10’) == CarbonPeriod::create()->setStartDate(‘2017-03-10’);
// Same with optional boolean argument $inclusive to change the option about include/exclude start date:
CarbonPeriod::start(‘2017-03-10’, true) == CarbonPeriod::create()->setStartDate(‘2017-03-10’, true);
// “end”, “until”, “untilNow”:
CarbonPeriod::end(‘2017-03-20’) == CarbonPeriod::create()->setEndDate(‘2017-03-20’);
// Same with optional boolean argument $inclusive to change the option about include/exclude end date:
CarbonPeriod::end(‘2017-03-20’, true) == CarbonPeriod::create()->setEndDate(‘2017-03-20’, true);
// “dates”, “between”:
CarbonPeriod::dates(…, …) == CarbonPeriod::create()->setDates(…, …);
// “recurrences”, “times”:
CarbonPeriod::recurrences(5) == CarbonPeriod::create()->setRecurrences(5);
// “options”:
CarbonPeriod::options(…) == CarbonPeriod::create()->setOptions(…);
// “toggle”:
CarbonPeriod::toggle(…, true) == CarbonPeriod::create()->toggleOptions(…, true);
// “filter”, “push”:
CarbonPeriod::filter(…) == CarbonPeriod::create()->addFilter(…);
// “prepend”:
CarbonPeriod::prepend(…) == CarbonPeriod::create()->prependFilter(…);
// “filters”:
CarbonPeriod::filters(…) == CarbonPeriod::create()->setFilters(…);
// “interval”, “each”, “every”, “step”, “stepBy”:
CarbonPeriod::interval(…) == CarbonPeriod::create()->setDateInterval(…);
// “invert”:
CarbonPeriod::invert() == CarbonPeriod::create()->invertDateInterval();
// “year”, “months”, “month”, “weeks”, “week”, “days”, “dayz”, “day”,
// “hours”, “hour”, “minutes”, “minute”, “seconds”, “second”:
CarbonPeriod::hours(5) == CarbonPeriod::create()->setDateInterval(new CarbonInterval::hours(5));

可以很容易地将CarbonPeriod转换为人类可读的字符串和ISO 8601规范:

$period = CarbonPeriod::create(‘2000-01-01 12:00’, ‘3 days 12 hours’, ‘2000-01-15 12:00’);
echo $period->toString();            // Every 3 days 12 hours from 2000-01-01 12:00:00 to 2000-01-15 12:00:00
echo $period->toIso8601String();     // 2000-01-01T12:00:00-05:00/P3DT12H/2000-01-15T12:00:00-05:00

 

英文原档:https://carbon.nesbot.com/docs/#api-interval

翻译有问题的地方还请斧正~

 

点赞