php Carbon 時間處理類 超詳細講解(一)
點選進入“PHP開源社群”
免費獲取進階面試、文件、影片資源
1. Introduction
Carbon 是php的日期處理類庫(A simple PHP API extension for DateTime.)。
Carbon 繼承了PHP的 Datetime 類,所以 Carbon 中沒有涉及到的,但在 Datetime 中已經實現的方法都是可以使用的。
看程式碼
<?php
namespace Carbon;
class Carbon extends \DateTime
{
// code here
}
Carbon 類宣告在 Carbon 名稱空間下,可以通過引入名稱空間的方式來代替每次輸入完整的類名。
<?php
use Carbon\Carbon;
Note:如果在使用 Carbon 時,沒有專門設定時區的話,預設使用 America/Toronto 的時區。
要特別留意是否使用了正確的時區,比如 Carbon 的所有差異比較都使用 UTC 或者系統設定的時區。
<?php
$dtToronto = Carbon::createFromDate(2012, 1, 1, 'America/Toronto');
$dtVancouver = Carbon::createFromDate(2012, 1, 1, 'America/Vancouver');
echo $dtVancouver->diffInHours($dtToronto); // 3
以上進行的時間比較是在提供的 Carbon 例項所在的時區下完成的。 例如作者所在的時區為 東京時間減13 小時,因此在下午一點後。 Carbon::now(‘Asia/Tokyo’)->isToday() 將會返回 false ,如果在呼叫 now() 時設定時區為東京時區,接下來的操作都使用東京時區是說不過去的。 所以在與 now() 建立的例項進行比較時,預設是在當前時區下完成的。
2.Instantiation
有好幾種方式可以建立 Carbon 的例項,但是大家應該更傾向於通過這種語義化的靜態方法來實現。
<?php
$carbon = new Carbon(); // equivalent to Carbon::now()
$carbon = new Carbon('first day of January 2008', 'America/Vancouver');
echo get_class($carbon); // 'Carbon\Carbon'
$carbon = Carbon::now(-5);
值得注意的是,Carbon 構造器的第二個引數被增強到了不僅限於\DateTimeZone 例項,還可以是 String、Integer (表示相對於GMT的偏移值)。舉個例子來說明下 now() 方法。
<?php
$now = Carbon::now();
$nowInLondonTz = Carbon::now(new DateTimeZone('Europe/London'));
// or just pass the timezone as a string
$nowInLondonTz = Carbon::now('Europe/London');
// or to create a date with a timezone of +1 to GMT during DST then just pass an integer
echo Carbon::now(1)->tzName; // Europe/London
你將會喜歡上用 parse() 方法來代替原有繁瑣的構造方式
<?php
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
類似 now() 這樣直接返回 Carbon 例項的方法還有 today(), tomorrow(),yesterday(),他們都接受一個 timezone 型別的引數,最後得到的結果時間部分都是 00:00:00
<?php
$now = Carbon::now();
echo $now; // 2016-06-24 15:18:34
$today = Carbon::today();
echo $today; // 2016-06-24 00:00:00
$tomorrow = Carbon::tomorrow('Europe/London');
echo $tomorrow; // 2016-06-25 00:00:00
$yesterday = Carbon::yesterday();
echo $yesterday; // 2016-06-23 00:00:00
下面是一些其他的 creatXXX() 形式的靜態方法。絕大多數靜態方法的引數是可傳可不傳的,如果不傳的話會使用方法預設的預設值,這些預設值一般都是針對當前日期、時間、時區的。如果為傳遞某個必要引數,會丟擲一個 InvalidArgumentException 型別的異常,用 DateTime::getLastErrors() 方法可以得到異常的詳細資訊。
<?php
Carbon::createFromDate($year, $month, $day, $tz);
Carbon::createFromTime($hour, $minute, $second, $tz);
Carbon::create($year, $month, $day, $hour, $minute, $second, $tz);
createFromDate() 預設返回當前時間,createFromTime()日期預設是今天。crete() 所有為 null 的引數都將預設為當前對應的時間。同樣,時區也預設是當前時區。如果只設置了小時數沒有設定分秒那麼分秒預設是 0
<?php
$xmasThisYear = Carbon::createFromDate(null, 12, 25); // Year defaults to current year
$Y2K = Carbon::create(2000, 1, 1, 0, 0, 0);
$alsoY2K = Carbon::create(1999, 12, 31, 24);
$noonLondonTz = Carbon::createFromTime(12, 0, 0, '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();
}
<?php
Carbon::createFromFormat($format, $time, $tz);
createFromFormat() 與php的DateTime::createFromFormat。不同之處是 $dt 引數可以是 DateTImeZone 的例項或者一個時區的字串。並且可以會返回引數異常的提示。從createXX()的原始碼可以看出,他們都呼叫了createFromFormat()方法。
<?php
echo Carbon::createFromFormat('Y-m-d H', '1975-05-21 22')->toDateTimeString(); // 1975-05-21 22:00:00
最後提到的這兩個create方法都是處理Unix時間戳的。第一個將會返回一個等於預期時間戳的 Carbon 例項,時區可以設定也可以選用預設值。第二個方法,createFromTimestampUTC() 與第一個不同的是時區將始終是 UTC(GMT) .第一個方法的第二個示例,只是為了讓這個函式的用法展現的更加明確。Negative timestamps are also allowed.
<?php
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
copy() 方法可以copy一個已經存在的 Carbon 例項。對copy生成例項進行修改並不會影響被copy物件的本身。
<?php
$dt = Carbon::now();
echo $dt->diffInYears($dt->copy()->addYear()); // 1
// $dt was unchanged and still holds the value of Carbon:now()
最後,當你正在使用的 DateTime 例項是通過例項化其他繼承了 \DateTime 庫而得到的,別怕!通過下邊的方式仍然可以極其友好建立 Carbon 例項。
<?php
$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 類也可以設定毫秒,但是在進行日期的數學預算時並不會考慮毫秒。從 Carbon 1.12.0版本起,例項化、copy也能像 format() 方法一樣支援毫秒(PHP預設的只有 Datetime::format() 支援毫秒)。
<?php
$dt = Carbon::parse('1975-05-21 22:23:00.123456');
echo $dt->micro; // 123456
echo $dt->copy()->micro; // 123456
獲取PHP支援的有效時間取值範圍:最早時間、最晚時間
<?php
echo Carbon::maxValue(); // '2038-01-18 22:14:07'
echo Carbon::minValue(); // '1901-12-13 15:45:52'
3.Localization
Carbon中,formatLocalized() 方法通過呼叫 strftime() 方法,彌補了php底層的 DateTime 類不支援區域化設定的缺陷。如果你已經通過使用setlocale() 方法設定過當前區域,formatLocalized($format) 方法將會按照設定的區域格式進行返回。
<?php
setlocale(LC_TIME, 'German');
echo $dt->formatLocalized('%A %d %B %Y'); // Mittwoch 21 Mai 1975
setlocale(LC_TIME, '');
echo $dt->formatLocalized('%A %d %B %Y'); // Wednesday 21 May 1975
diffForHumans() 的結果也會被轉化成區域語言。通過Carbon::setLocale() 方法可以設定 Carbon 的區域語言。
<?php
Carbon::setLocale('de');
echo Carbon::now()->addYear()->diffForHumans(); // in 1 Jahr
Carbon::setLocale('en');
注意:如果在linux系統中轉換出現了問題,請仔細檢查安裝在本地或生產系統中語言環境。
locale -a 列舉出所有可用的語言環境
sudo locale-gen zh_CN.utf8 安裝新的語言環境
sudo dpkg-reconfigure locales 配置啟用新的語言環境,並重啟
4.Testing Aids()
通過測試方法可以得到一個模擬或真實的 Carbon 例項。只有在以下情況下,主動提供的 Carbon 例項才會被特殊處理:
-
呼叫靜態方法 now(),例如:Carbon::now()
-
傳給 construct 或 parse() 方法的是 null (或空字串),例如:new Carbon(null)
-
當傳給 construct 或 parse()的是字串 now,例如:new Carbon(‘now’)
$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::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
var_dump(Carbon::hasTestNow()); // bool(true)
Carbon::setTestNow(); // clear the mock
var_dump(Carbon::hasTestNow()); // bool(false)
echo Carbon::now();
有用的例子:
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();
以下是當前支援的時間轉換字
-
this
-
last
-
next
-
tomorrow
-
yesterday
-
+
-
-
-
first
-
ago
值得注意的是像 next() , previous() 和 modify() 方法等相關的修改會把日期的時間部分設定成 00:00:00 。
5.Getters
獲取器通過PHP的 __get() 方式實現。可以直接通過一下方式直接獲取到屬性的值。
$dt = Carbon::parse('2012-9-5 23:26:11.123789');
// These getters specifically return integers, ie intval()
var_dump($dt->year); // int(2012)
var_dump($dt->month); // int(9)
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)
var_dump($dt->dayOfWeek); // int(3)
var_dump($dt->dayOfYear); // int(248)
var_dump($dt->weekOfMonth); // int(1)
var_dump($dt->weekOfYear); // int(36)
var_dump($dt->daysInMonth); // int(30)
var_dump($dt->timestamp); // int(1346901971)
var_dump(Carbon::createFromDate(1975, 5, 21)->age); // int(41) calculated vs now in the same tz
var_dump($dt->quarter); // int(3)
// 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
6.Setters
Setters 通過PHP的 __set() 方法實現。值得注意的是,通過這種方式設定時間戳時,時區不會相對於時間戳而改變。如果需要改變時區的話,需要針對時區單獨設定。
$dt = Carbon::now();
$dt->year = 1975;
$dt->month = 13; // would force year++ and month = 1
$dt->month = 5;
$dt->day = 21;
$dt->hour = 22;
$dt->minute = 32;
$dt->second = 5;
$dt->timestamp = 169957925; // This will not change the timezone
// Set the timezone via DateTimeZone instance or string
$dt->timezone = new DateTimeZone('Europe/London');
$dt->timezone = 'Europe/London';
$dt->tz = 'Europe/London';
7. Fluent Setters
此處 Setters 方法的引數是必選引數,Carbon 提供了更多種設定方式可供使用。值得注意的是,所有對於時區的修改都會影響整個到 Carbon 例項。對時間戳進行修改時不會自動轉換到時間戳對應的時區。
$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->setDateTime(1975, 5, 21, 22, 32, 5)->toDateTimeString();
$dt->timestamp(169957925)->timezone('Europe/London');
$dt->tz('America/Toronto')->setTimezone('America/Vancouver');
8.IsSet
當嘗試呼叫 Carbon 例項的屬性時,會首先檢查該屬性是否存在,存在返回 true,不存在返回 false。
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)
未完待續~~~
*宣告:本文於網路整理,版權歸原作者所有,如來源資訊有誤或侵犯權益,請聯絡我們刪除或授權事宜。
END
PHP開源社群
掃描關注 進入”PHP資料“
免費獲取進階
面試、文件、影片資源
點選“檢視原文”獲取更多
- 你會使用 Linux 編輯器 Vim 嗎?
- php實現圖書管理系統詳細介紹
- 面試官問:Redis 快取都有哪些異常,各自有哪些解決方案
- 面試被問到:關於php檔案包含你瞭解多少?
- 一張小圖看盡 Nginx
- php快速搭建swoole玩轉協程
- Laravel 使用Guzzle執行HTTP請求
- PHP中的異常處理機制
- 基於redis的分散式鎖詳解
- 如何通過查原始碼的方式解決程式設計中遇到的問題?
- PHP高併發商品秒殺問題的解決方案
- Thinkphp6專案基本操作(中介軟體處理登入流程)
- PHP實現非同步延遲訊息佇列(庫存歸還)
- php捕捉Warning、Notice錯誤
- 利用PHP的POST臨時檔案機制實現任意檔案上傳
- php Carbon 時間處理類 超詳細講解(一)
- 如何用 10 行 bash shell 指令碼監控 Linux?
- PDO方式連線資料庫、PHP連線資料庫
- php雪花演算法SnowFlake生成唯一ID
- 淺述 Docker 的容器編排