Carbon中文使用手冊

  • Introduction

Carbon 繼承了PHP的 Datetime 類和JsonSerialiable。因此 Carbon 中沒有涉及到的,但在 Datetime JsonSerializable中已經實現的方法都是可使用的。php

1 class Carbon extends DateTime implements JsonSerializable
2 {
3     //code here
4 }

Carbon 類聲明在 Carbon 命名空間下,能夠經過引入命名空間的方式來代替每次輸入完整的類名。git

1 <?php 
2 use Carbon\Carbon;

要特別留意是否使用了正確的時區,好比的全部差別比較都使用或者系統設定的時區github

1 $dtToronto = Carbon::create(2012, 1, 1, 0, 0, 0, 'America/Toronto');
2 $dtVancouver = Carbon::create(2012, 1, 1, 0, 0, 0, 'America/Vancouver');
3 
4 echo $dtVancouver->diffInHours($dtToronto); // 3

以上進行的時間比較是在提供的 Carbon 實例所在的時區下完成的。例如做者所在的時區爲 東京時間減13 小時,所以在下午一點後。Carbon::now(‘Asia/Tokyo’)->isToday() 將會返回 false ,若是在調用 now() 時設置時區爲東京時區,接下來的操做都使用東京時區是說不過去的。因此在與 now() 建立的實例進行比較時,默認是在當前時區下完成的。json

  • Instantiation

有幾種不一樣的方法能夠建立一個新的Carbon實例。首先是構造函數。它覆蓋父構造函數,您最好閱讀PHP手冊中的第一個參數,並瞭解它所接受的日期/時間字符串格式。您可能會發現本身不多使用構造函數,而是依賴於顯式靜態方法來提升可讀性api

1 $carbon = new Carbon();                  // 等同於 Carbon::now()
2 $carbon = new Carbon('first day of January 2008', 'America/Vancouver');
3 echo get_class($carbon);                 // 'Carbon\Carbon'
4 $carbon = Carbon::now(-5);//1表示英國倫敦,2表示法國巴黎

您將在上面注意到,timezone(2nd)參數是做爲字符串和整數而不是\DateTimeZone實例傳遞的。全部DateTimeZone參數都已被加強,所以您能夠將一個DateTimeZone實例、字符串或整型偏移量傳遞給GMT,併爲您建立時區。在下一個示例中再次顯示了這一點,該示例還介紹了now()函數。數組

$nowInLondonTz = Carbon::now(new \DateTimeZone('Europe/London'));
// 或者以字符串形式只傳時區
$nowInLondonTz = Carbon::now('Europe/London');

// 或者在DST期間建立一個時區爲+1到GMT的日期,而後傳遞一個整數
echo Carbon::now(1)->tzName;             // Europe/London

若是您真的喜歡您的動態方法調用,而且對使用構造函數時所需的額外的行或難看的括號感到失望,那麼您將喜歡parse方法。閉包

echo (new Carbon('first day of December 2008'))->addWeeks(2);     // 2008-12-15 00:00:00
echo Carbon::parse('first day of December 2008')->addWeeks(2);    // 2008-12-15 00:00:00

NOTE:PHP 5.4 以前(new MyClass())->method() 會報語法錯誤, 若是你使用PHP 5.3, 你須要建立一個變量而後再調用方法:app

$date = new Carbon('first day of December 2008'); 

echo $date->addWeeks(2);

傳遞給Carbon:::parsenew Carbon的字符串能夠表示相對時間(next sunday, tomorrow, first day of next month, last year)或絕對時間(first day of December 2008, 2017-01-06)。您能夠用Carbon::hasRelativeKeywords()測試一個字符串是否會產生一個相對或絕對日期。less

$string = 'first day of next month';
if (strtotime($string) === false) {
    echo "'$string' is not a valid date/time string.";
} elseif (Carbon::hasRelativeKeywords($string)) {
    echo "'$string' is a relative valid date/time string, it will returns different dates depending on the current date.";
} else {
    echo "'$string' is an absolute date/time string, it will always returns the same date.";
}

爲了配合now(),還存在一些靜態的實例化助手來建立廣爲人知的實例。這裏惟一須要注意的是,today()tomorrow()yesterday()除了按照預期的行爲,都接受一個時區參數,每一個參數的時間值都設置爲00:00:00。ide

$now = Carbon::now();
echo $now;                               // 2018-07-26 16:25:49
$today = Carbon::today();
echo $today;                             // 2018-07-26 00:00:00
$tomorrow = Carbon::tomorrow('Europe/London');
echo $tomorrow;                          // 2018-07-27 00:00:00
$yesterday = Carbon::yesterday();
echo $yesterday;                         // 2018-07-25 00:00:00

下一組靜態助手是createXXX() 函數。大多數靜態create函數容許您提供許多個或少許的參數,併爲全部其餘參數提供默認值。一般默認值是當前日期、時間或時區。更高的值將適當地包裝,但無效的值將拋出一個InvalidArgumentException,並附帶一條信息。錯誤消息從DateTime:::getLastErrors()調用中獲取。

Carbon::createFromDate($year, $month, $day, $tz);
Carbon::createFromTime($hour, $minute, $second, $tz);
Carbon::createFromTimeString("$hour:$minute:$second", $tz);
Carbon::create($year, $month, $day, $hour, $minute, $second, $tz);

createFromDate() 的默認值是當前時間. createFromTime() 默認值是今天. create()若是不傳參數也是當前時間. 與前面同樣,$tz默認設置爲當前時區,不然能夠是DateTimeZone實例,也能夠是字符串時區值。默認值(模擬底層PHP庫)的惟一特殊狀況發生在指定了小時值但沒有分鐘或秒時,它們將默認爲0。

注:createFromTime() will default the date to today。小編經實戰代碼打印出來發現createFromTime() 的默認值也是當前時間,不是今天(時分秒並非00:00:00)。

$xmasThisYear = Carbon::createFromDate(null, 12, 25);  // Year默認值是今年
$Y2K = Carbon::create(2000, 1, 1, 0, 0, 0); // 等價於Carbon::createMidnightDate(2000, 1, 1)
$alsoY2K = Carbon::create(1999, 12, 31, 24);
$noonLondonTz = Carbon::createFromTime(12, 0, 0, 'Europe/London');
$teaTime = Carbon::createFromTimeString('17:00:00', 'Europe/London');

// A two digit minute could not be found
try { Carbon::create(1975, 5, 21, 22, -2, 0); } catch(\InvalidArgumentException $x) { echo $x->getMessage()

建立異常發生在使用負值上,而不是在溢出上,要獲取溢出上的異常,請使用createSafe()

echo Carbon::create(2000, 1, 35, 13, 0, 0);// 2000-02-04 13:00:00
//(1月有31天,4天自動加上去轉換成了2月4號)

try {
    Carbon::createSafe(2000, 1, 35, 13, 0, 0);
} catch (\Carbon\Exceptions\InvalidDateException $exp) {
    echo $exp->getMessage();
}
// 會報錯:day : 35 is not a valid value.

NOTE1:2018-02-29會產生一個異常,而2020-02-29不會產生異常,由於2020年是閏年。

NOTE2:Carbon::createSafe(2014,3,30,1,30,0,'Europe/London');從PHP 5.4開始也會產生一個異常,由於在夏令時跳過一個小時,可是在PHP 5.4以前,它只會建立這個無效的日期。

Carbon::createFromFormat($format, $time, $tz);

createFromFormat()是最基本的php函數DateTime:::createFromFormat的包裝器。不一樣的是,$tz參數能夠是DateTimeZone實例或字符串時區值。此外,若是格式有錯誤,這個函數將調用DateTime::getLastErrors()方法,而後拋出一個InvalidArgumentException,錯誤做爲消息。若是您查看上面的createXX()函數的源代碼,它們都會調用createFromFormat()。

echo Carbon::createFromFormat('Y-m-d H', '1975-05-21 22')->toDateTimeString(); // 1975-05-21 22:00:00

最後三個create函數用於使用unix時間戳。第一個將建立一個與給定的時間戳相等的Carbon實例,並將設置時區或默認爲當前時區。第二個createFromTimestampUTC()是不一樣的,由於時區將保持UTC(GMT)。第二種方法與Carbon: createFromFormat('@'.$timestamp)的做用相同,但我只是讓它更明確了一點。第三個是createFromTimestampMs(),它接受以毫秒而不是秒爲單位的時間戳。也容許使用負時間戳。

echo Carbon::createFromTimestamp(-1)->toDateTimeString();                                  // 1969-12-31 18:59:59
echo Carbon::createFromTimestamp(-1, 'Europe/London')->toDateTimeString();                 // 1970-01-01 00:59:59
echo Carbon::createFromTimestampUTC(-1)->toDateTimeString();                               // 1969-12-31 23:59:59
echo Carbon::createFromTimestampMs(1)->format('Y-m-d\TH:i:s.uP T');                        // 1969-12-31T19:00:00.001000-05:00 EST
echo Carbon::createFromTimestampMs(1, 'Europe/London')->format('Y-m-d\TH:i:s.uP T');       // 1970-01-01T01:00:00.001000+01:00 BST

您還能夠copy()在現有Carbon實例上建立。如預期的那樣,日期、時間和時區值都被複制到新實例。

$dt = Carbon::now();
echo $dt->diffInYears($dt->copy()->addYear());  // 1
// $dt 實例沒有改變,任然是Carbon:now()

您能夠在現有的Carbon實例上使用nowWithSameTz()來在相同的時區中獲取一個新的實例。

$meeting = Carbon::createFromTime(19, 15, 00, 'Africa/Johannesburg');

// 19:15 in Johannesburg
echo 'Meeting starts at '.$meeting->format('H:i').' in Johannesburg.';                  // Meeting starts at 19:15 in Johannesburg.
// now in Johannesburg
echo "It's ".$meeting->nowWithSameTz()->format('H:i').' right now in Johannesburg.';    // It's 09:37 right now in Johannesburg.

最後,若是您發現本身從另外一個庫繼承了\DateTime實例,不要懼怕!您能夠經過友好的instance()方法建立一個Carbon實例。或者使用更靈活的方法make(),它能夠從DateTimeCarbonstring返回一個新的Carbon實例,不然它只返回null。

$dt = new \DateTime('first day of January 2008'); // <== instance from another API
$carbon = Carbon::instance($dt);
echo get_class($carbon);                               // 'Carbon\Carbon'
echo $carbon->toDateTimeString();                      // 2008-01-01 00:00:00

關於微秒的簡要說明。PHP DateTime對象容許您設置一個微秒值,可是忽略它的全部日期數學。如今,1.12.0的Carbon在實例化或複製操做過程當中支持微秒,並在默認狀況下使用format()方法。

$dt = Carbon::parse('1975-05-21 22:23:00.123456');
echo $dt->micro;                                       // 123456
echo $dt->copy()->micro;                               // 123456

在PHP 7.1以前 DateTime微秒未添加到「now」實例,而且以後不能更改,這意味着:

$date = new DateTime('now');
echo $date->format('u');
// display current microtime in PHP >= 7.1 (expect a bug in PHP 7.1.3 only)
// display 000000 before PHP 7.1

$date = new DateTime('2001-01-01T00:00:00.123456Z');
echo $date->format('u');
// display 123456 in all PHP versions

$date->modify('00:00:00.987654');
echo $date->format('u');
// display 987654 in PHP >= 7.1
// display 123456 before PHP 7.1

爲了解決這個限制,咱們在PHP < 7.1中調用了microseconds,可是這個特性在須要時能夠被禁用(PHP >= 7.1):

Carbon::useMicrosecondsFallback(false);
var_dump(Carbon::isMicrosecondsFallbackEnabled()); // false

echo Carbon::now()->micro; // 0 in PHP < 7.1, microtime in PHP >= 7.1

Carbon::useMicrosecondsFallback(true); // default value
var_dump(Carbon::isMicrosecondsFallbackEnabled()); // true

echo Carbon::now()->micro; // microtime in all PHP version

是否須要遍歷一些日期以找到最先或最近的日期?不知道如何設置初始最大值/最小值?如今有兩個助手能夠幫助你作出簡單的決定:

echo Carbon::maxValue();                               // '9999-12-31 23:59:59'
echo Carbon::minValue();                               // '0001-01-01 00:00:00'

最小和最大值主要取決於系統(32位或64位)。

使用32位OS系統或32位版本的PHP(您能夠在PHP中使用PHP_INT_SIZE == 4來檢查它),最小值是0-unix-timestamp(1970-01-01 00:00:00),最大值是常量PHP_INT_MAX給出的時間戳。

使用64位OS系統和64位PHP版本,最小值爲01-01 00:00,最大值爲9999-12-31 23:59:59。

  • Localization

不幸的是,基類DateTime沒有任何本地化支持。爲了開始本地化支持,還添加了一個formatLocalized($format)方法。實現使用當前實例時間戳對strftime進行調用。若是您首先使用PHP函數setlocale()設置當前的語言環境,那麼返回的字符串將被格式化爲正確的語言環境。

$newLocale = setlocale(LC_TIME, 'German');
if ($newLocale === false) {
    echo '"German" locale is not installed on your machine, it may have a different name a different name on your machine or you may need to install it.';
}
echo $dt->formatLocalized('%A %d %B %Y');          // Mittwoch 21 Mai 1975
setlocale(LC_TIME, 'English');
echo $dt->formatLocalized('%A %d %B %Y');          // Wednesday 21 May 1975
setlocale(LC_TIME, ''); // reset locale

diffForHumans()也被定位。您能夠經過使用靜態Carbon::setLocale()函數來設置Carbon locale(),並使用Carbon::getLocale()獲取當前的設置。

Carbon::setLocale('de');
echo Carbon::getLocale();                          // de
echo Carbon::now()->addYear()->diffForHumans();    // in 1 Jahr

Carbon::setLocale('en');
echo Carbon::getLocale();                          // en

或者,您能夠將一些代碼與給定的語言環境隔離:

Carbon::executeWithLocale('de', function ($newLocale) {
    // You can optionally get $newLocale as the first argument of the closure
    // It will be set to the new locale or false if the locale was not found.

    echo Carbon::now()->addYear()->diffForHumans();
}); // in 1 Jahr

// outside the function the locale did not change
echo Carbon::getLocale();                          // en

// or same using a return statement
$french = Carbon::executeWithLocale('fr', function () {
    return Carbon::now()->addYear()->diffForHumans();
});
echo $french; // dans 1 an

有些語言須要打印utf8編碼(主要以. utf8結尾的語言環境包)。在本例中,您可使用靜態方法Carbon::setUtf8()對對utf8字符集的formatlocalized()調用的結果進行編碼。

setlocale(LC_TIME, 'Spanish');
$dt = Carbon::create(2016, 01, 06, 00, 00, 00);
Carbon::setUtf8(false);
echo $dt->formatLocalized('%A %d %B %Y');          // mi�rcoles 06 enero 2016
Carbon::setUtf8(true);
echo $dt->formatLocalized('%A %d %B %Y');          // miércoles 06 enero 2016
Carbon::setUtf8(false);
setlocale(LC_TIME, '');

在Linux上

若是您在翻譯方面有問題,請檢查系統中安裝的地區(本地和生產)。

區域設置-列出已啓用的區域設置。

sudo locale-gen fr_FR。UTF-8安裝一個新的語言環境。

sudo dpkg-reconfigure locale來發布全部啓用的locale。

並重啓系統。

您能夠經過如下方式自定義現有語言:

Carbon::setLocale('en');
$translator = Carbon::getTranslator();
$translator->setMessages('en', array(
    'day' => ':count boring day|:count boring days',
));

$date1 = Carbon::create(2018, 1, 1, 0, 0, 0);
$date2 = Carbon::create(2018, 1, 4, 4, 0, 0);

echo $date1->diffForHumans($date2, true, false, 2); // 3 boring days 4 hours

$translator->resetMessages('en'); // reset language customizations for en language

請注意,您還可使用另外一個轉換器Carbon::setTranslator($custom),只要給定的轉換器繼承了Symfony\Component\Translation\TranslatorInterface。 所以,對格式本地化、getter(如localeMonth、localedayayofweek和短變體)的語言環境支持是由安裝在操做系統中的語言環境驅動的。對於其餘翻譯,因爲碳社區的支持,它在內部獲得了支持。您可使用如下方法檢查支持的內容:

echo implode(', ', array_slice(Carbon::getAvailableLocales(), 0, 3)).'...';      // af, ar, ar_Shakl...

// Support diff syntax (before, after, from now, ago)
var_dump(Carbon::localeHasDiffSyntax('en'));                                     // bool(true)
var_dump(Carbon::localeHasDiffSyntax('zh_TW'));                                  // bool(true)
// Support 1-day diff words (just now, yesterday, tomorrow)
var_dump(Carbon::localeHasDiffOneDayWords('en'));                                // bool(true)
var_dump(Carbon::localeHasDiffOneDayWords('zh_TW'));                             // bool(false)
// Support 2-days diff words (before yesterday, after tomorrow)
var_dump(Carbon::localeHasDiffTwoDayWords('en'));                                // bool(true)
var_dump(Carbon::localeHasDiffTwoDayWords('zh_TW'));                             // bool(false)
// Support short units (1y = 1 year, 1mo = 1 month, etc.)
var_dump(Carbon::localeHasShortUnits('en'));                                     // bool(true)
var_dump(Carbon::localeHasShortUnits('zh_TW'));                                  // bool(false)
// Support period syntax (X times, every X, from X, to X)
var_dump(Carbon::localeHasPeriodSyntax('en'));                                   // bool(true)
var_dump(Carbon::localeHasPeriodSyntax('zh_TW'));                                // bool(false)

如下是最後一個碳版本支持的73個地區的概述:

 

 

 

注意,若是您使用Laravel 5.5+,語言環境將根據當前的最後一個App:setLocale execution自動設置。因此擴散人類將是透明的。您可能仍然須要在某些中間件中運行setlocale以使formatlocalizedworking正確。

  • Testing Aids

測試方法容許您在建立「如今」實例時設置要返回的Carbon實例(real或mock)。所提供的實例將在如下條件下具體返回:

對static now()方法的調用,例如:Carbon::now()

當一個空(或空字符串)被傳遞給構造函數或parse()時,ex.new Carbon(空)

當字符串「now」傳遞給構造函數或parse()時,ex. new Carbon('now')

給定的實例也將做爲diff方法的默認相對時間。

$knownDate = Carbon::create(2001, 5, 21, 12);          // create testing date
Carbon::setTestNow($knownDate);                        // set the mock (of course this could be a real mock object)
echo Carbon::getTestNow();                             // 2001-05-21 12:00:00
echo Carbon::now();                                    // 2001-05-21 12:00:00
echo new Carbon();                                     // 2001-05-21 12:00:00
echo Carbon::parse();                                  // 2001-05-21 12:00:00
echo new Carbon('now');                                // 2001-05-21 12:00:00
echo Carbon::parse('now');                             // 2001-05-21 12:00:00
echo Carbon::create(2001, 4, 21, 12)->diffForHumans(); // 1 month ago
var_dump(Carbon::hasTestNow());                        // bool(true)
Carbon::setTestNow();                                  // clear the mock
var_dump(Carbon::hasTestNow());                        // bool(false)
echo Carbon::now();                                    // 2018-07-05 03:37:12

一個更有意義的完整例子:

class SeasonalProduct
{
    protected $price;

    public function __construct($price)
    {
        $this->price = $price;
    }

    public function getPrice() {
        $multiplier = 1;
        if (Carbon::now()->month == 12) {
            $multiplier = 2;
        }

        return $this->price * $multiplier;
    }
}

$product = new SeasonalProduct(100);
Carbon::setTestNow(Carbon::parse('first day of March 2000'));
echo $product->getPrice();                                             // 100
Carbon::setTestNow(Carbon::parse('first day of December 2000'));
echo $product->getPrice();                                             // 200
Carbon::setTestNow(Carbon::parse('first day of May 2000'));
echo $product->getPrice();                                             // 100
Carbon::setTestNow();

根據給定的「now」實例,還能夠對相關短語進行嘲笑。

$knownDate = Carbon::create(2001, 5, 21, 12);          // create testing date
Carbon::setTestNow($knownDate);                        // set the mock
echo new Carbon('tomorrow');                           // 2001-05-22 00:00:00  ... notice the time !
echo new Carbon('yesterday');                          // 2001-05-20 00:00:00
echo new Carbon('next wednesday');                     // 2001-05-23 00:00:00
echo new Carbon('last friday');                        // 2001-05-18 00:00:00
echo new Carbon('this thursday');                      // 2001-05-24 00:00:00
Carbon::setTestNow();                                  // always clear it !

被認爲是相對修飾語的單詞列表以下:

  • +
  • -
  • ago
  • first
  • next
  • last
  • this
  • today
  • tomorrow
  • yesterday

請注意,與next()、previous()和modify()方法相似,這些相對修飾符中的一些將把時間設置爲00:00。

Carbon: parse($time, $tz)和new Carbon($time, $tz)均可以將時區做爲第二個參數。

echo Carbon::parse('2012-9-5 23:26:11.223', 'Europe/Paris')->timezone->getName(); // Europe/Paris
  • Getters

getter方法是經過PHP的__get()方法實現的。這使您可以像訪問屬性而不是函數調用那樣訪問值。

$dt = Carbon::parse('2012-10-5 23:26:11.123789');

// 這些getter方法都將返回int類型
var_dump($dt->year);                                         // int(2012)
var_dump($dt->month);                                        // int(10)
var_dump($dt->day);                                          // int(5)
var_dump($dt->hour);                                         // int(23)
var_dump($dt->minute);                                       // int(26)
var_dump($dt->second);                                       // int(11)
var_dump($dt->micro);                                        // int(123789)
// dayOfWeek 返回一個數值 0 (sunday) 到 6 (saturday)
var_dump($dt->dayOfWeek);                                    // int(5)
// dayOfWeekIso 返回一個數值 1 (monday) 到 7 (sunday)
var_dump($dt->dayOfWeekIso);                                 // int(5)
setlocale(LC_TIME, 'German');
var_dump($dt->englishDayOfWeek);                             // string(6) "Friday"
var_dump($dt->shortEnglishDayOfWeek);                        // string(3) "Fri"
var_dump($dt->localeDayOfWeek);                              // string(7) "Freitag"
var_dump($dt->shortLocaleDayOfWeek);                         // string(2) "Fr"
var_dump($dt->englishMonth);                                 // string(7) "October"
var_dump($dt->shortEnglishMonth);                            // string(3) "Oct"
var_dump($dt->localeMonth);                                  // string(7) "Oktober"
var_dump($dt->shortLocaleMonth);                             // string(3) "Okt"
setlocale(LC_TIME, '');
var_dump($dt->dayOfYear);                                    // int(278)
var_dump($dt->weekNumberInMonth);    
// weekNumberInMonth consider weeks from monday to sunday, so the week 1 will
// contain 1 day if the month start with a sunday, and up to 7 if it starts with a monday
var_dump($dt->weekOfMonth);                                  // int(1)
// weekOfMonth will returns 1 for the 7 first days of the month, then 2 from the 8th to
// the 14th, 3 from the 15th to the 21st, 4 from 22nd to 28th and 5 above
var_dump($dt->weekOfYear);                                   // int(40)
var_dump($dt->daysInMonth);                                  // int(31)
var_dump($dt->timestamp);                                    // int(1349493971)
var_dump(Carbon::createFromDate(1975, 5, 21)->age);          // int(43) calculated vs now in the same tz
var_dump($dt->quarter);                                      // int(4)

// Returns an int of seconds difference from UTC (+/- sign included)
var_dump(Carbon::createFromTimestampUTC(0)->offset);         // int(0)
var_dump(Carbon::createFromTimestamp(0)->offset);            // int(-18000)

// Returns an int of hours difference from UTC (+/- sign included)
var_dump(Carbon::createFromTimestamp(0)->offsetHours);       // int(-5)

// Indicates if day light savings time is on
var_dump(Carbon::createFromDate(2012, 1, 1)->dst);           // bool(false)
var_dump(Carbon::createFromDate(2012, 9, 1)->dst);           // bool(true)

// Indicates if the instance is in the same timezone as the local timezone
var_dump(Carbon::now()->local);                              // bool(true)
var_dump(Carbon::now('America/Vancouver')->local);           // bool(false)

// Indicates if the instance is in the UTC timezone
var_dump(Carbon::now()->utc);                                // bool(false)
var_dump(Carbon::now('Europe/London')->utc);                 // bool(false)
var_dump(Carbon::createFromTimestampUTC(0)->utc);            // bool(true)

// Gets the DateTimeZone instance
echo get_class(Carbon::now()->timezone);                     // DateTimeZone
echo get_class(Carbon::now()->tz);                           // DateTimeZone

// Gets the DateTimeZone instance name, shortcut for ->timezone->getName()
echo Carbon::now()->timezoneName;                            // America/Toronto
echo Carbon::now()->tzName;                                  // America/Toronto

 

  • Setters

下面的setter是經過PHP的__set()方法實現的。值得注意的是,除了顯式地設置時區以外,任何設置程序都不會更改實例的時區。具體地說,設置時間戳不會將相應的時區設置爲UTC。

$dt = Carbon::now();

$dt->year = 1975;
$dt->month = 13;             //強制 year++ 而後 month = 1
$dt->month = 5;
$dt->day = 21;
$dt->hour = 22;
$dt->minute = 32;
$dt->second = 5;

$dt->timestamp = 169957925;  // 這不會改變時區

// 經過DateTimeZone實例或字符串設置時區
$dt->timezone = new DateTimeZone('Europe/London');
$dt->timezone = 'Europe/London';
$dt->tz = 'Europe/London';
  • Fluent Setters

對於setter沒有可選參數,可是函數定義中有足夠的多樣性,所以不管如何都不須要它們。值得注意的是,除了顯式地設置時區以外,任何設置程序都不會更改實例的時區。具體地說,設置時間戳不會將相應的時區設置爲UTC。

$dt = Carbon::now();

$dt->year(1975)->month(5)->day(21)->hour(22)->minute(32)->second(5)->toDateTimeString();
$dt->setDate(1975, 5, 21)->setTime(22, 32, 5)->toDateTimeString();
$dt->setDate(1975, 5, 21)->setTimeFromTimeString('22:32:05')->toDateTimeString();
$dt->setDateTime(1975, 5, 21, 22, 32, 5)->toDateTimeString();

$dt->timestamp(169957925)->timezone('Europe/London');

$dt->tz('America/Toronto')->setTimezone('America/Vancouver');

您還能夠將日期和時間與其餘DateTime/Carbon對象分開設置:

$source1 = new Carbon('2010-05-16 22:40:10');

$dt = new Carbon('2001-01-01 01:01:01');
$dt->setTimeFrom($source1);

echo $dt; // 2001-01-01 22:40:10

$source2 = new DateTime('2013-09-01 09:22:56');

$dt->setDateFrom($source2);

echo $dt; // 2013-09-01 22:40:10
  • IsSet

實現了PHP函數__isset()。這是在一些外部系統(例如Twig)在使用屬性以前驗證屬性的存在時完成的。這是使用isset()或empty()方法完成的。在PHP站點:__isset()、isset()、empty()上,您能夠閱讀更多關於這些內容的信息。

var_dump(isset(Carbon::now()->iDoNotExist));       // bool(false)
var_dump(isset(Carbon::now()->hour));              // bool(true)
var_dump(empty(Carbon::now()->iDoNotExist));       // bool(true)
var_dump(empty(Carbon::now()->year));              // bool(false)
  • String Formatting

全部可用的toXXXString()方法都依賴於基類方法DateTime: format()。您將注意到__toString()方法的定義,它容許在字符串上下文中使用時將一個Carbon實例打印爲一個漂亮的日期時間字符串。

$dt = Carbon::create(1975, 12, 25, 14, 15, 16);

var_dump($dt->toDateTimeString() == $dt);          // bool(true) => uses __toString()
echo $dt->toDateString();                          // 1975-12-25
echo $dt->toFormattedDateString();                 // Dec 25, 1975
echo $dt->toTimeString();                          // 14:15:16
echo $dt->toDateTimeString();                      // 1975-12-25 14:15:16
echo $dt->toDayDateTimeString();                   // Thu, Dec 25, 1975 2:15 PM

// ... of course format() is still available
echo $dt->format('l jS \\of F Y h:i:s A');         // Thursday 25th of December 1975 02:15:16 PM

// The reverse hasFormat method allows you to test if a string looks like a given format
var_dump($dt->hasFormat('Thursday 25th December 1975 02:15:16 PM', 'l jS F Y h:i:s A')); // bool(true)

您還能夠設置默認的__toString()格式(默認爲Y-m-d H:i:s),這是在發生類型雜耍時使用的格式。

Carbon::setToStringFormat('jS \o\f F, Y g:i:s a');
echo $dt;                                          // 25th of December, 1975 2:15:16 pm
Carbon::resetToStringFormat();
echo $dt;                                          // 1975-12-25 14:15:16

NOTE:對於本地化支持,請參閱本地化部分。

  • Common Formats

下面是DateTime類中提供的公共格式的包裝器。

$dt = Carbon::createFromFormat('Y-m-d H:i:s.u', '2019-02-01 03:45:27.612584');

// $dt->toAtomString() is the same as $dt->format(DateTime::ATOM);
echo $dt->toAtomString();        // 2019-02-01T03:45:27-05:00
echo $dt->toCookieString();      // Friday, 01-Feb-2019 03:45:27 EST

echo $dt->toIso8601String();     // 2019-02-01T03:45:27-05:00
// Be aware we chose to use the full-extended format of the ISO 8601 norm
// Natively, DateTime::ISO8601 format is not compatible with ISO-8601 as it
// is explained here in the PHP documentation:
// https://php.net/manual/class.datetime.php#datetime.constants.iso8601
// We consider it as a PHP mistake and chose not to provide method for this
// format, but you still can use it this way:
echo $dt->format(DateTime::ISO8601); // 2019-02-01T03:45:27-0500

echo $dt->toIso8601ZuluString(); // 2019-02-01T08:45:27Z
echo $dt->toRfc822String();      // Fri, 01 Feb 19 03:45:27 -0500
echo $dt->toRfc850String();      // Friday, 01-Feb-19 03:45:27 EST
echo $dt->toRfc1036String();     // Fri, 01 Feb 19 03:45:27 -0500
echo $dt->toRfc1123String();     // Fri, 01 Feb 2019 03:45:27 -0500
echo $dt->toRfc2822String();     // Fri, 01 Feb 2019 03:45:27 -0500
echo $dt->toRfc3339String();     // 2019-02-01T03:45:27-05:00
echo $dt->toRfc7231String();     // Fri, 01 Feb 2019 08:45:27 GMT
echo $dt->toRssString();         // Fri, 01 Feb 2019 03:45:27 -0500
echo $dt->toW3cString();         // 2019-02-01T03:45:27-05:00

var_dump($dt->toArray());
/*
array(12) {
  ["year"]=>
  int(2019)
  ["month"]=>
  int(2)
  ["day"]=>
  int(1)
  ["dayOfWeek"]=>
  int(5)
  ["dayOfYear"]=>
  int(31)
  ["hour"]=>
  int(3)
  ["minute"]=>
  int(45)
  ["second"]=>
  int(27)
  ["micro"]=>
  int(612584)
  ["timestamp"]=>
  int(1549010727)
  ["formatted"]=>
  string(19) "2019-02-01 03:45:27"
  ["timezone"]=>
  object(DateTimeZone)#118 (2) {
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(15) "America/Toronto"
  }
}
*/
  • Comparison

經過如下函數提供了簡單的比較。請記住,比較是在UTC時區進行的,因此事情並不老是像看上去的那樣。

echo Carbon::now()->tzName;                        // America/Toronto
$first = Carbon::create(2012, 9, 5, 23, 26, 11);
$second = Carbon::create(2012, 9, 5, 20, 26, 11, 'America/Vancouver');

echo $first->toDateTimeString();                   // 2012-09-05 23:26:11
echo $first->tzName;                               // America/Toronto
echo $second->toDateTimeString();                  // 2012-09-05 20:26:11
echo $second->tzName;                              // America/Vancouver

var_dump($first->eq($second));                     // bool(true)
var_dump($first->ne($second));                     // bool(false)
var_dump($first->gt($second));                     // bool(false)
var_dump($first->gte($second));                    // bool(true)
var_dump($first->lt($second));                     // bool(false)
var_dump($first->lte($second));                    // bool(true)

$first->setDateTime(2012, 1, 1, 0, 0, 0);
$second->setDateTime(2012, 1, 1, 0, 0, 0);         // Remember tz is 'America/Vancouver'

var_dump($first->eq($second));                     // bool(false)
var_dump($first->ne($second));                     // bool(true)
var_dump($first->gt($second));                     // bool(false)
var_dump($first->gte($second));                    // bool(false)
var_dump($first->lt($second));                     // bool(true)
var_dump($first->lte($second));                    // bool(true)

// All have verbose aliases and PHP equivalent code:

var_dump($first->eq($second));                     // bool(false)
var_dump($first->equalTo($second));                // bool(false)
var_dump($first == $second);                       // bool(false)

var_dump($first->ne($second));                     // bool(true)
var_dump($first->notEqualTo($second));             // bool(true)
var_dump($first != $second);                       // bool(true)

var_dump($first->gt($second));                     // bool(false)
var_dump($first->greaterThan($second));            // bool(false)
var_dump($first > $second);                        // bool(false)

var_dump($first->gte($second));                    // bool(false)
var_dump($first->greaterThanOrEqualTo($second));   // bool(false)
var_dump($first >= $second);                       // bool(false)

var_dump($first->lt($second));                     // bool(true)
var_dump($first->lessThan($second));               // bool(true)
var_dump($first < $second);                        // bool(true)

var_dump($first->lte($second));                    // bool(true)
var_dump($first->lessThanOrEqualTo($second));      // bool(true)
var_dump($first <= $second);                       // bool(true)

這些方法使用PHP $date1 == $date2提供的天然比較,所以在PHP 7.1以前,全部方法都將忽略milli/micro-seconds,而後從7.1開始考慮它們。

要肯定當前實例是否在其餘兩個實例之間,可使用恰當命名的between()方法。第三個參數表示是否應該進行相等的比較。默認值是true,它決定了它的中間值仍是等於邊界。

$first = Carbon::create(2012, 9, 5, 1);
$second = Carbon::create(2012, 9, 5, 5);
var_dump(Carbon::create(2012, 9, 5, 3)->between($first, $second));          // bool(true)
var_dump(Carbon::create(2012, 9, 5, 5)->between($first, $second));          // bool(true)
var_dump(Carbon::create(2012, 9, 5, 5)->between($first, $second, false));   // bool(false)

哇!你忘記了min()和max()了嗎?不。這也被適當命名的min()和max()方法或minimum()和maximum()別名所覆蓋。與往常同樣,若是指定爲null,則默認參數如今爲。

$dt1 = Carbon::createMidnightDate(2012, 1, 1);
$dt2 = Carbon::createMidnightDate(2014, 1, 30);
echo $dt1->min($dt2);                              // 2012-01-01 00:00:00
echo $dt1->minimum($dt2);                          // 2012-01-01 00:00:00

$dt1 = Carbon::createMidnightDate(2012, 1, 1);
$dt2 = Carbon::createMidnightDate(2014, 1, 30);
echo $dt1->max($dt2);                              // 2014-01-30 00:00:00
echo $dt1->maximum($dt2);                          // 2014-01-30 00:00:00

// now is the default param
$dt1 = Carbon::createMidnightDate(2000, 1, 1);
echo $dt1->max();                                  // 2018-07-05 03:37:12
echo $dt1->maximum();                              // 2018-07-05 03:37:12

$dt1 = Carbon::createMidnightDate(2010, 4, 1);
$dt2 = Carbon::createMidnightDate(2010, 3, 28);
$dt3 = Carbon::createMidnightDate(2010, 4, 16);

// returns the closest of two date (no matter before or after)
echo $dt1->closest($dt2, $dt3);                    // 2010-03-28 00:00:00
echo $dt2->closest($dt1, $dt3);                    // 2010-04-01 00:00:00
echo $dt3->closest($dt2, $dt1);                    // 2010-04-01 00:00:00

// returns the farthest of two date (no matter before or after)
echo $dt1->farthest($dt2, $dt3);                   // 2010-04-16 00:00:00
echo $dt2->farthest($dt1, $dt3);                   // 2010-04-16 00:00:00
echo $dt3->farthest($dt2, $dt1);                   // 2010-03-28 00:00:00

爲了處理最經常使用的狀況,這裏有一些簡單的幫助函數,但願它們的名稱能很明顯地反映出來。對於以某種方式與now() (ex.istoday()))進行比較的方法,now()是在與實例相同的時區建立的。

$dt = Carbon::now();
$dt2 = Carbon::createFromDate(1987, 4, 23);

$dt->isSameAs('w', $dt2); // w is the date of the week, so this will return true if $dt and $dt2
// the same day of week (both monday or both sunday, etc.)
// you can use any format and combine as much as you want.
$dt->isFuture();
$dt->isPast();

$dt->isSameYear($dt2);
$dt->isCurrentYear();
$dt->isNextYear();
$dt->isLastYear();
$dt->isLongYear(); // see https://en.wikipedia.org/wiki/ISO_8601#Week_dates
$dt->isLeapYear();

$dt->isSameQuarter($dt2); // same quarter (3 months) no matter the year of the given date
$dt->isSameQuarter($dt2, true); // same quarter of the same year of the given date
/*
    Alternatively, you can run Carbon::compareYearWithMonth() to compare both quarter and year by default,
    In this case you can use $dt->isSameQuarter($dt2, false) to compare ignoring the year
    Run Carbon::compareYearWithMonth(false) to reset to the default behavior
    Run Carbon::shouldCompareYearWithMonth() to get the current setting
*/
$dt->isCurrentQuarter();
$dt->isNextQuarter(); // date is in the next quarter
$dt->isLastQuarter(); // in previous quarter

$dt->isSameMonth($dt2); // same month no matter the year of the given date
$dt->isSameMonth($dt2, true); // same month of the same year of the given date
/*
    As for isSameQuarter, you can run Carbon::compareYearWithMonth() to compare both month and year by default,
    In this case you can use $dt->isSameMonth($dt2, false) to compare ignoring the year
    Run Carbon::compareYearWithMonth(false) to reset to the default behavior
    Run Carbon::shouldCompareYearWithMonth() to get the current setting
*/
$dt->isCurrentMonth();
$dt->isNextMonth();
$dt->isLastMonth();

$dt->isWeekday();
$dt->isWeekend();
$dt->isMonday();
$dt->isTuesday();
$dt->isWednesday();
$dt->isThursday();
$dt->isFriday();
$dt->isSaturday();
$dt->isSunday();
$dt->isDayOfWeek(Carbon::SATURDAY); // is a saturday
$dt->isLastOfMonth(); // is the last day of the month

$dt->isSameDay($dt2); // Same day of same month of same year
$dt->isCurrentDay();
$dt->isYesterday();
$dt->isToday();
$dt->isTomorrow();
$dt->isNextWeek();
$dt->isLastWeek();

$dt->isSameHour($dt2);
$dt->isCurrentHour();
$dt->isSameMinute($dt2);
$dt->isCurrentMinute();
$dt->isSameSecond($dt2);
$dt->isCurrentSecond();

$dt->isStartOfDay(); // check if hour is 00:00:00
$dt->isMidnight(); // check if hour is 00:00:00 (isStartOfDay alias)
$dt->isEndOfDay(); // check if hour is 23:59:59
$dt->isMidday(); // check if hour is 12:00:00 (or other midday hour set with Carbon::setMidDayAt())
$born = Carbon::createFromDate(1987, 4, 23);
$noCake = Carbon::createFromDate(2014, 9, 26);
$yesCake = Carbon::createFromDate(2014, 4, 23);
$overTheHill = Carbon::now()->subYears(50);
var_dump($born->isBirthday($noCake));              // bool(false)
var_dump($born->isBirthday($yesCake));             // bool(true)
var_dump($overTheHill->isBirthday());              // bool(true) -> default compare it to today!
  • Addition and Subtraction

默認的DateTime提供了幾種不一樣的方法來方便地添加和減小時間。有modify()、add()和sub()。modify()使用一個魔術date/time格式字符串「last day of next month」,它解析並應用修改,而add()和sub()則指望一個不那麼明顯的日期間隔實例(例如新的\日期間隔('P6YT5M')將意味着6年5分鐘)。但願使用這些流暢的函數將會更加清晰,而且在幾個星期內沒有看到您的代碼後更容易閱讀。固然,我不會讓您選擇,由於基類函數仍然可用。

$dt = Carbon::create(2012, 1, 31, 0);

echo $dt->toDateTimeString();            // 2012-01-31 00:00:00

echo $dt->addCenturies(5);               // 2512-01-31 00:00:00
echo $dt->addCentury();                  // 2612-01-31 00:00:00
echo $dt->subCentury();                  // 2512-01-31 00:00:00
echo $dt->subCenturies(5);               // 2012-01-31 00:00:00

echo $dt->addYears(5);                   // 2017-01-31 00:00:00
echo $dt->addYear();                     // 2018-01-31 00:00:00
echo $dt->subYear();                     // 2017-01-31 00:00:00
echo $dt->subYears(5);                   // 2012-01-31 00:00:00

echo $dt->addQuarters(2);                // 2012-07-31 00:00:00
echo $dt->addQuarter();                  // 2012-10-31 00:00:00
echo $dt->subQuarter();                  // 2012-07-31 00:00:00
echo $dt->subQuarters(2);                // 2012-01-31 00:00:00

echo $dt->addMonths(60);                 // 2017-01-31 00:00:00
echo $dt->addMonth();                    // 2017-03-03 00:00:00 equivalent of $dt->month($dt->month + 1); so it wraps
echo $dt->subMonth();                    // 2017-02-03 00:00:00
echo $dt->subMonths(60);                 // 2012-02-03 00:00:00

echo $dt->addDays(29);                   // 2012-03-03 00:00:00
echo $dt->addDay();                      // 2012-03-04 00:00:00
echo $dt->subDay();                      // 2012-03-03 00:00:00
echo $dt->subDays(29);                   // 2012-02-03 00:00:00

echo $dt->addWeekdays(4);                // 2012-02-09 00:00:00
echo $dt->addWeekday();                  // 2012-02-10 00:00:00
echo $dt->subWeekday();                  // 2012-02-09 00:00:00
echo $dt->subWeekdays(4);                // 2012-02-03 00:00:00

echo $dt->addWeeks(3);                   // 2012-02-24 00:00:00
echo $dt->addWeek();                     // 2012-03-02 00:00:00
echo $dt->subWeek();                     // 2012-02-24 00:00:00
echo $dt->subWeeks(3);                   // 2012-02-03 00:00:00

echo $dt->addHours(24);                  // 2012-02-04 00:00:00
echo $dt->addHour();                     // 2012-02-04 01:00:00
echo $dt->subHour();                     // 2012-02-04 00:00:00
echo $dt->subHours(24);                  // 2012-02-03 00:00:00

echo $dt->addMinutes(61);                // 2012-02-03 01:01:00
echo $dt->addMinute();                   // 2012-02-03 01:02:00
echo $dt->subMinute();                   // 2012-02-03 01:01:00
echo $dt->subMinutes(61);                // 2012-02-03 00:00:00

echo $dt->addSeconds(61);                // 2012-02-03 00:01:01
echo $dt->addSecond();                   // 2012-02-03 00:01:02
echo $dt->subSecond();                   // 2012-02-03 00:01:01
echo $dt->subSeconds(61);                // 2012-02-03 00:00:00

爲了好玩,您還能夠將負值傳遞給addXXX(),實際上這就是subXXX()實現的方式。 附註:若是你忘記並使用addDay(5) 或subYear(3),我支持你; 默認狀況下,Carbon依賴於底層父類PHP DateTime行爲。所以,增長或減小月份可能會溢出,例如:

$dt = Carbon::create(2017, 1, 31, 0);

echo $dt->copy()->addMonth();            // 2017-03-03 00:00:00
echo $dt->copy()->subMonths(2);          // 2016-12-01 00:00:00

爲了防止溢出Carbon:usemonthverflow (false)

Carbon::useMonthsOverflow(false);

$dt = Carbon::createMidnightDate(2017, 1, 31);

echo $dt->copy()->addMonth();            // 2017-02-28 00:00:00
echo $dt->copy()->subMonths(2);          // 2016-11-30 00:00:00

// Call the method with true to allow overflow again
Carbon::resetMonthsOverflow(); // same as Carbon::useMonthsOverflow(true);

方法Carbon:::shouldOverflowMonths()容許您知道當前是否啓用了溢出。您也可使用->addMonthsNoOverflow, ->subMonthsNoOverflow, ->addMonthsWithOverflow, -> submonth withoverflow(或單數方法,不含s至「month」),顯式add/sub,不管當前模式如何,均可以添加或不添加溢出。

Carbon::useMonthsOverflow(false);

$dt = Carbon::createMidnightDate(2017, 1, 31);

echo $dt->copy()->addMonthWithOverflow();          // 2017-03-03 00:00:00
// plural addMonthsWithOverflow() method is also available
echo $dt->copy()->subMonthsWithOverflow(2);        // 2016-12-01 00:00:00
// singular subMonthWithOverflow() method is also available
echo $dt->copy()->addMonthNoOverflow();            // 2017-02-28 00:00:00
// plural addMonthsNoOverflow() method is also available
echo $dt->copy()->subMonthsNoOverflow(2);          // 2016-11-30 00:00:00
// singular subMonthNoOverflow() method is also available

echo $dt->copy()->addMonth();                      // 2017-02-28 00:00:00
echo $dt->copy()->subMonths(2);                    // 2016-11-30 00:00:00

Carbon::useMonthsOverflow(true);

$dt = Carbon::createMidnightDate(2017, 1, 31);

echo $dt->copy()->addMonthWithOverflow();          // 2017-03-03 00:00:00
echo $dt->copy()->subMonthsWithOverflow(2);        // 2016-12-01 00:00:00
echo $dt->copy()->addMonthNoOverflow();            // 2017-02-28 00:00:00
echo $dt->copy()->subMonthsNoOverflow(2);          // 2016-11-30 00:00:00

echo $dt->copy()->addMonth();                      // 2017-03-03 00:00:00
echo $dt->copy()->subMonths(2);                    // 2016-12-01 00:00:00

Carbon::resetMonthsOverflow();

從1.23.0版本開始,在如下年份也可使用溢出控制:

Carbon::useYearsOverflow(false);

$dt = Carbon::createMidnightDate(2020, 2, 29);

var_dump(Carbon::shouldOverflowYears());           // bool(false)

echo $dt->copy()->addYearWithOverflow();           // 2021-03-01 00:00:00
// plural addYearsWithOverflow() method is also available
echo $dt->copy()->subYearsWithOverflow(2);         // 2018-03-01 00:00:00
// singular subYearWithOverflow() method is also available
echo $dt->copy()->addYearNoOverflow();             // 2021-02-28 00:00:00
// plural addYearsNoOverflow() method is also available
echo $dt->copy()->subYearsNoOverflow(2);           // 2018-02-28 00:00:00
// singular subYearNoOverflow() method is also available

echo $dt->copy()->addYear();                       // 2021-02-28 00:00:00
echo $dt->copy()->subYears(2);                     // 2018-02-28 00:00:00

Carbon::useYearsOverflow(true);

$dt = Carbon::createMidnightDate(2020, 2, 29);

var_dump(Carbon::shouldOverflowYears());           // bool(true)

echo $dt->copy()->addYearWithOverflow();           // 2021-03-01 00:00:00
echo $dt->copy()->subYearsWithOverflow(2);         // 2018-03-01 00:00:00
echo $dt->copy()->addYearNoOverflow();             // 2021-02-28 00:00:00
echo $dt->copy()->subYearsNoOverflow(2);           // 2018-02-28 00:00:00

echo $dt->copy()->addYear();                       // 2021-03-01 00:00:00
echo $dt->copy()->subYears(2);                     // 2018-03-01 00:00:00

Carbon::resetYearsOverflow();
  • Difference

因爲Carbon繼承了DateTime,它繼承了它的方法,如diff(),它將第二個date對象做爲參數,並返回一個DateInterval實例。

咱們還提供了diffAsCarbonInterval(),相似於diff(),但返回一個CarbonInterval實例。檢查CarbonInterval 章節瞭解更多信息。每一個單元的Carbon添加了diff方法,如diffInYears()、diffInMonths()等。diffAsCarbonInterval()和diffIn*()方法均可以使用兩個可選參數:date to compare with(若是缺失,now是默認值),以及一個絕對布爾選項(默認爲true),不管哪一個日期大於另外一個,該方法都返回一個絕對值。若是設置爲false,則在調用方法的實例大於比較日期(第一個參數或now)時返回負值。注意,diff()原型是不一樣的:它的第一個參數(date)是強制性的,第二個參數(絕對選項)默認爲false。

這些函數老是返回在指定的時間內表示的總差別。這與基類diff()函數不一樣,該函數的時間間隔爲122秒,經過DateInterval實例返回2分零2秒。diffInMinutes()函數只返回2,而diffInSeconds()將返回122。全部的值都被截斷而不是四捨五入。下面的每一個函數都有一個默認的第一個參數,該參數是要比較的Carbon實例,若是您想使用now(),則爲null。第二個參數也是可選的,若是您但願返回值是絕對值,或者若是傳遞的日期小於當前實例,則返回值可能具備-(負)符號的相對值。這將默認爲true,返回絕對值。

echo Carbon::now('America/Vancouver')->diffInSeconds(Carbon::now('Europe/London')); // 0

$dtOttawa = Carbon::createMidnightDate(2000, 1, 1, 'America/Toronto');
$dtVancouver = Carbon::createMidnightDate(2000, 1, 1, 'America/Vancouver');
echo $dtOttawa->diffInHours($dtVancouver);                             // 3
echo $dtVancouver->diffInHours($dtOttawa);                             // 3

echo $dtOttawa->diffInHours($dtVancouver, false);                      // 3
echo $dtVancouver->diffInHours($dtOttawa, false);                      // -3

$dt = Carbon::createMidnightDate(2012, 1, 31);
echo $dt->diffInDays($dt->copy()->addMonth());                         // 31
echo $dt->diffInDays($dt->copy()->subMonth(), false);                  // -31

$dt = Carbon::createMidnightDate(2012, 4, 30);
echo $dt->diffInDays($dt->copy()->addMonth());                         // 30
echo $dt->diffInDays($dt->copy()->addWeek());                          // 7

$dt = Carbon::createMidnightDate(2012, 1, 1);
echo $dt->diffInMinutes($dt->copy()->addSeconds(59));                  // 0
echo $dt->diffInMinutes($dt->copy()->addSeconds(60));                  // 1
echo $dt->diffInMinutes($dt->copy()->addSeconds(119));                 // 1
echo $dt->diffInMinutes($dt->copy()->addSeconds(120));                 // 2

echo $dt->addSeconds(120)->secondsSinceMidnight();                     // 120

$interval = $dt->diffAsCarbonInterval($dt->copy()->subYears(3), false);
echo ($interval->invert ? 'minus ' : 'plus ') . $interval->years;      // minus 3

關於夏令時(DST)的重要注意,默認狀況下,PHP DateTime不考慮DST,這意味着,像2014年3月30日這樣只有23小時的一天在倫敦將被計算爲24小時。

$date = new DateTime('2014-03-30 00:00:00', new DateTimeZone('Europe/London')); // DST off
echo $date->modify('+25 hours')->format('H:i');                   // 01:00 (DST on, 24 hours only have been actually added)

Carbon也遵循這種行爲,增長/減小/下降秒/分鐘/小時。可是咱們提供了使用時間戳進行實時工做的方法:

$date = new Carbon('2014-03-30 00:00:00', 'Europe/London');    // DST off
echo $date->addRealHours(25)->format('H:i');             // 02:00 (DST on)
echo $date->diffInRealHours('2014-03-30 00:00:00');               // 25
echo $date->diffInHours('2014-03-30 00:00:00');                   // 26
echo $date->diffInRealMinutes('2014-03-30 00:00:00');             // 1500
echo $date->diffInMinutes('2014-03-30 00:00:00');                 // 1560
echo $date->diffInRealSeconds('2014-03-30 00:00:00');             // 90000
echo $date->diffInSeconds('2014-03-30 00:00:00');                 // 93600
echo $date->subRealHours(25)->format('H:i');             // 00:00 (DST off)

一樣的方法可使用addRealMinutes()、subRealMinutes()、addRealSeconds()、subRealSeconds()和全部它們的惟一快捷方式:addRealHour()、subRealHour()、addrealmin()、subRealMinute()、addRealSecond()、subRealSecond()。

還有特殊的過濾器函數diffindaysfilter()、diffinhoursfilter()和difffilter(),以幫助您按天數、小時或自定義間隔過濾差別。例如,計算兩個實例之間的週末天數:

$dt = Carbon::create(2014, 1, 1);
$dt2 = Carbon::create(2014, 12, 31);
$daysForExtraCoding = $dt->diffInDaysFiltered(function(Carbon $date) {
    return $date->isWeekend();
}, $dt2);

echo $daysForExtraCoding;      // 104

$dt = Carbon::create(2014, 1, 1)->endOfDay();
$dt2 = $dt->copy()->startOfDay();
$littleHandRotations = $dt->diffFiltered(CarbonInterval::minute(), function(Carbon $date) {
    return $date->minute === 0;
}, $dt2, true); // true as last parameter returns absolute value

echo $littleHandRotations;     // 24

$date = Carbon::now()->addSeconds(3666);

echo $date->diffInSeconds();                       // 3666
echo $date->diffInMinutes();                       // 61
echo $date->diffInHours();                         // 1
echo $date->diffInDays();                          // 0

$date = Carbon::create(2016, 1, 5, 22, 40, 32);

echo $date->secondsSinceMidnight();                // 81632
echo $date->secondsUntilEndOfDay();                // 4767

$date1 = Carbon::createMidnightDate(2016, 1, 5);
$date2 = Carbon::createMidnightDate(2017, 3, 15);

echo $date1->diffInDays($date2);                   // 435
echo $date1->diffInWeekdays($date2);               // 311
echo $date1->diffInWeekendDays($date2);            // 124
echo $date1->diffInWeeks($date2);                  // 62
echo $date1->diffInMonths($date2);                 // 14
echo $date1->diffInYears($date2);                  // 1

全部的diffIn*濾波方法都採用1個可調用濾波器做爲必要參數,一個date對象做爲可選的第二個參數,若是缺失,使用now。您也能夠將true做爲第三個參數傳遞,以得到絕對值。

對於周/週末的高級處理,使用如下工具:

echo implode(', ', Carbon::getDays());                 // Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday

$saturday = new Carbon('first saturday of 2019');
$sunday = new Carbon('first sunday of 2019');
$monday = new Carbon('first monday of 2019');

echo implode(', ', Carbon::getWeekendDays());                // 6, 0
var_dump($saturday->isWeekend());                            // bool(true)
var_dump($sunday->isWeekend());                              // bool(true)
var_dump($monday->isWeekend());                              // bool(false)

Carbon::setWeekendDays(array(
    Carbon::SUNDAY,
    Carbon::MONDAY,
));                                                          //自定義設置「週末」

echo implode(', ', Carbon::getWeekendDays());           // 0, 1
var_dump($saturday->isWeekend());                            // bool(false),週六返回false
var_dump($sunday->isWeekend());                              // bool(true)
var_dump($monday->isWeekend());                              // bool(true),週一返回true

Carbon::setWeekendDays(array(
    Carbon::SATURDAY,
    Carbon::SUNDAY,
));
// weekend days and start/end of week or not linked
Carbon::setWeekStartsAt(Carbon::FRIDAY);
Carbon::setWeekEndsAt(Carbon::WEDNESDAY); // and it does not need neither to precede the start

var_dump(Carbon::getWeekStartsAt() === Carbon::FRIDAY);      // bool(true)
var_dump(Carbon::getWeekEndsAt() === Carbon::WEDNESDAY);     // bool(true)
echo $saturday->copy()->startOfWeek()->toRfc850String();     // Friday, 06-Jul-18 00:00:00 EDT
echo $saturday->copy()->endOfWeek()->toRfc850String();       // Wednesday, 11-Jul-18 23:59:59 EDT

Carbon::setWeekStartsAt(Carbon::MONDAY);
Carbon::setWeekEndsAt(Carbon::SUNDAY);

echo $saturday->copy()->startOfWeek()->toRfc850String();     // Monday, 02-Jul-18 00:00:00 EDT
echo $saturday->copy()->endOfWeek()->toRfc850String();       // Sunday, 08-Jul-18 23:59:59 EDT
  • Difference for Humans

對人類來講,一個月前比30天前更容易閱讀。這是在大多很多天期庫中常見的函數,因此我也想在這裏添加它。函數的惟一參數是另外一個要對其進行diff的Carbon實例,固然,若是沒有指定,它默認爲now()。

此方法將在相對於實例的差值和傳入實例的差值以後添加短語。有4個可能性:

當將過去的值與如今的默認值進行比較時:

1小時前

5個月前

當將將來的值與如今的默認值進行比較時:

從如今開始的1小時

從如今開始的5個月

當比較一個過去的值與另外一個值時:

前1小時

5個月前

當比較將來的價值與另外一個價值時:

1小時後

5個月後

您還能夠將true做爲第二個參數傳遞,以便從如今開始刪除修飾符,等等:diffforhuman ($other, true)。

若是在所使用的語言環境:diffforhuman ($other, false, true)中可用,您能夠將true做爲第三個參數傳遞給它,以使用簡短語法。

您能夠將1和6之間的數字做爲第4個參數傳遞給diffforhuman ($other, false, false, 4)。

$other實例能夠是DateTime、Carbon實例或任何實現DateTimeInterface的對象,若是傳遞了一個字符串,它將被解析爲獲取一個Carbon實例,若是傳遞了null,那麼將使用Carbon: now()。

// The most typical usage is for comments
// The instance is the date the comment was created and its being compared to default now()
echo Carbon::now()->subDays(5)->diffForHumans();               // 5 days ago

echo Carbon::now()->diffForHumans(Carbon::now()->subYear());   // 1 year after

$dt = Carbon::createFromDate(2011, 8, 1);

echo $dt->diffForHumans($dt->copy()->addMonth());                        // 1 month before
echo $dt->diffForHumans($dt->copy()->subMonth());                        // 1 month after

echo Carbon::now()->addSeconds(5)->diffForHumans();                      // 5 seconds from now

echo Carbon::now()->subDays(24)->diffForHumans();                        // 3 weeks ago(21-27都返回這個,一個周的單位是7天,小於7直接捨去)
echo Carbon::now()->subDays(24)->diffForHumans(null, true);    // 3 weeks(21-27都返回這個,一個周的單位是7天,小於7直接捨去)


echo Carbon::parse('2019-08-03')->diffForHumans('2019-08-13');           // 1 week before(時間間隔7-13天都是返回這個,一個周的單位是7天,小於7直接捨去)
echo Carbon::parse('2000-01-01 00:50:32')->diffForHumans('@946684800');  // 5 hours after(同理,都是捨去的)

echo Carbon::create(2018, 2, 26, 4, 29, 43)->diffForHumans(Carbon::create(2016, 6, 21, 0, 0, 0), false, false, 6); // 1 year 8 months 5 days 4 hours 29 minutes 43 seconds after

您還能夠在調用diffforhuman()以前使用Carbon::setLocale('fr')更改字符串的locale。有關更多細節,請參見本地化部分。

能夠經過如下方式啓用/禁用diffforhuman()選項:

Carbon::enableHumanDiffOption(Carbon::NO_ZERO_DIFF);
var_dump((bool) (Carbon::getHumanDiffOptions() & Carbon::NO_ZERO_DIFF)); // bool(true)
Carbon::disableHumanDiffOption(Carbon::NO_ZERO_DIFF);
var_dump((bool) (Carbon::getHumanDiffOptions() & Carbon::NO_ZERO_DIFF)); // bool(false)

可用的選項是:

Carbon::NO_ZERO_DIFF(默認啓用):將空diff變爲1秒

Carbon::JUST_NOW在默認狀況下是禁用的):從如今開始變爲「剛纔」

Carbon:ONE_DAY_WORDS(默認禁用):將「從如今/以前1天」變爲「昨天/明天」

Carbon::TWO_DAY_WORDS(默認禁用):將「從如今/以前2天」變爲「昨天/以後」

Carbon::JUST_NOW,Carbon::ONE_DAY_WORDS和Carbon::TWO_DAY_WORDS如今只能使用en和fr語言,其餘語言將會恢復到之前的行爲,直到添加缺失的翻譯。

使用管道操做符一次啓用/禁用多個選項,例如:Carbon::ONE_DAY_WORDS | Carbon::TWO_DAY_WORDS

您還可使用setHumanDiffOptions($options)禁用全部選項,而後只激活做爲參數傳遞的選項。

  • Modifiers

這些方法組對當前實例進行了有益的修改。他們中的大多數方法的名字都是不言自明的……或者至少應該是這樣。您還會注意到startOfXXX()、next()和previous()方法將時間設置爲00:00,endOfXXX()方法將時間設置爲23:59:59。

惟一稍有不一樣的是average()函數。它將實例移動到其自己和提供的碳參數之間的中間日期。

$dt = Carbon::create(2012, 1, 31, 15, 32, 45);
echo $dt->startOfMinute();                         // 2012-01-31 15:32:00

$dt = Carbon::create(2012, 1, 31, 15, 32, 45);
echo $dt->endOfMinute();                           // 2012-01-31 15:32:59

$dt = Carbon::create(2012, 1, 31, 15, 32, 45);
echo $dt->startOfHour();                           // 2012-01-31 15:00:00

$dt = Carbon::create(2012, 1, 31, 15, 32, 45);
echo $dt->endOfHour();                             // 2012-01-31 15:59:59

$dt = Carbon::create(2012, 1, 31, 15, 32, 45);
echo Carbon::getMidDayAt();                        // 12獲取正午時間
echo $dt->midDay();                                // 2012-01-31 12:00:00
Carbon::setMidDayAt(13);                     //設置正午時間爲13點
echo Carbon::getMidDayAt();                        // 13
echo $dt->midDay();                                // 2012-01-31 13:00:00
Carbon::setMidDayAt(12);

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->startOfDay();                            // 2012-01-31 00:00:00

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->endOfDay();                              // 2012-01-31 23:59:59

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->startOfMonth();                          // 2012-01-01 00:00:00

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->endOfMonth();                            // 2012-01-31 23:59:59

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->startOfYear();                           // 2012-01-01 00:00:00

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->endOfYear();                             // 2012-12-31 23:59:59

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->startOfDecade();                         // 2010-01-01 00:00:00 十年(「年代?」)的開始1990,2000,2010,2010

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->endOfDecade();                           // 2019-12-31 23:59:59

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->startOfCentury();                        // 2001-01-01 00:00:00 世紀的開始?爲何不是2000-01-01 00:00:00???可能老外就是這個定義的吧……

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->endOfCentury();                          // 2100-12-31 23:59:59 世紀的結束?爲何不是2099-12-31 23:59:59???

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->startOfWeek();                           // 2012-01-30 00:00:00
var_dump($dt->dayOfWeek == Carbon::MONDAY);        // bool(true) : ISO8601 week starts on Monday ISO8601標準每週的開始是週一,老外好像認爲每週的開始是週日……

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->endOfWeek();                             // 2012-02-05 23:59:59
var_dump($dt->dayOfWeek == Carbon::SUNDAY);        // bool(true) : ISO8601 week ends on Sunday

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->next(Carbon::WEDNESDAY);                 // 2012-02-01 00:00:00 傳了參數表示「下一個週三」,不傳表示「明天」
var_dump($dt->dayOfWeek == Carbon::WEDNESDAY);     // bool(true)

$dt = Carbon::create(2012, 1, 1, 12, 0, 0);
echo $dt->next();                                  // 2012-01-08 00:00:00

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->previous(Carbon::WEDNESDAY);             // 2012-01-25 00:00:00 傳了參數表示「上一個週三」,不傳表示「昨天」
var_dump($dt->dayOfWeek == Carbon::WEDNESDAY);     // bool(true)

$dt = Carbon::create(2012, 1, 1, 12, 0, 0);
echo $dt->previous();                              // 2011-12-25 00:00:00

$start = Carbon::create(2014, 1, 1, 0, 0, 0);
$end = Carbon::create(2014, 1, 30, 0, 0, 0);
echo $start->average($end);                        // 2014-01-15 12:00:00 (1+30)/2 = 15 int運算

echo Carbon::create(2014, 5, 30, 0, 0, 0)->firstOfMonth();                       // 2014-05-01 00:00:00 這個月的第一天
echo Carbon::create(2014, 5, 30, 0, 0, 0)->firstOfMonth(Carbon::MONDAY);         // 2014-05-05 00:00:00 這個月的第一個週一
echo Carbon::create(2014, 5, 30, 0, 0, 0)->lastOfMonth();                        // 2014-05-31 00:00:00 這個月的最後一天
echo Carbon::create(2014, 5, 30, 0, 0, 0)->lastOfMonth(Carbon::TUESDAY);         // 2014-05-27 00:00:00 這個月的最後一個週二
echo Carbon::create(2014, 5, 30, 0, 0, 0)->nthOfMonth(2, Carbon::SATURDAY);      // 2014-05-10 00:00:00 這個月的第「2」個「週六」,2和週六是參數

echo Carbon::create(2014, 5, 30, 0, 0, 0)->firstOfQuarter();                     // 2014-04-01 00:00:00 這個季度的第一天(5月是第二個季度,因此是4月1號)
echo Carbon::create(2014, 5, 30, 0, 0, 0)->firstOfQuarter(Carbon::MONDAY);       // 2014-04-07 00:00:00 這個季度的第一個週一
echo Carbon::create(2014, 5, 30, 0, 0, 0)->lastOfQuarter();                      // 2014-06-30 00:00:00 這個季度的最後一天
echo Carbon::create(2014, 5, 30, 0, 0, 0)->lastOfQuarter(Carbon::TUESDAY);       // 2014-06-24 00:00:00 這個季度的最後一個週二
echo Carbon::create(2014, 5, 30, 0, 0, 0)->nthOfQuarter(2, Carbon::SATURDAY);    // 2014-04-12 00:00:00 這個季度的第「2」個「週六」,2和週六是參數
echo Carbon::create(2014, 5, 30, 0, 0, 0)->startOfQuarter();                     // 2014-04-01 00:00:00 這個季度的開始
echo Carbon::create(2014, 5, 30, 0, 0, 0)->endOfQuarter();                       // 2014-06-30 23:59:59 這個季度的結束

echo Carbon::create(2014, 5, 30, 0, 0, 0)->firstOfYear();                        // 2014-01-01 00:00:00 同上……
echo Carbon::create(2014, 5, 30, 0, 0, 0)->firstOfYear(Carbon::MONDAY);          // 2014-01-06 00:00:00
echo Carbon::create(2014, 5, 30, 0, 0, 0)->lastOfYear();                         // 2014-12-31 00:00:00
echo Carbon::create(2014, 5, 30, 0, 0, 0)->lastOfYear(Carbon::TUESDAY);          // 2014-12-30 00:00:00
echo Carbon::create(2014, 5, 30, 0, 0, 0)->nthOfYear(2, Carbon::SATURDAY);       // 2014-01-11 00:00:00

echo Carbon::create(2018, 2, 23, 0, 0, 0)->nextWeekday();                        // 2018-02-26 00:00:00 下週一
echo Carbon::create(2018, 2, 23, 0, 0, 0)->previousWeekday();                    // 2018-02-22 00:00:00 這周的上一個工做日
echo Carbon::create(2018, 2, 21, 0, 0, 0)->nextWeekendDay();                     // 2018-02-24 00:00:00 即將要過的週末的第一天(即這星期的週六,若是今天是週六,則結果是週日)
echo Carbon::create(2018, 2, 21, 0, 0, 0)->previousWeekendDay();                 // 2018-02-18 00:00:00 剛過完的週末的最後一個(即上一週的週日,若是今天是週日,則結果是週六)
  • Constants

下面的常數是在Carbon中定義的。

// These getters specifically return integers, ie intval()
var_dump(Carbon::SUNDAY);                          // int(0)
var_dump(Carbon::MONDAY);                          // int(1)
var_dump(Carbon::TUESDAY);                         // int(2)
var_dump(Carbon::WEDNESDAY);                       // int(3)
var_dump(Carbon::THURSDAY);                        // int(4)
var_dump(Carbon::FRIDAY);                          // int(5)
var_dump(Carbon::SATURDAY);                        // int(6)

var_dump(Carbon::YEARS_PER_CENTURY);               // int(100)
var_dump(Carbon::YEARS_PER_DECADE);                // int(10)
var_dump(Carbon::MONTHS_PER_YEAR);                 // int(12)
var_dump(Carbon::WEEKS_PER_YEAR);                  // int(52)
var_dump(Carbon::DAYS_PER_WEEK);                   // int(7)
var_dump(Carbon::HOURS_PER_DAY);                   // int(24)
var_dump(Carbon::MINUTES_PER_HOUR);                // int(60)
var_dump(Carbon::SECONDS_PER_MINUTE);              // int(60)

$dt = Carbon::createFromDate(2012, 10, 6);
if ($dt->dayOfWeek === Carbon::SATURDAY) {
    echo 'Place bets on Ottawa Senators Winning!';
}
  • 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)

你猜怎麼着?在CarbonInterval和CarbonPeriod類上也可使用全部的宏方法。

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()得到inverval的ISO 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 8601的Interval規範(如「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

翻譯有問題的地方還請斧正~

相關文章
相關標籤/搜索