# Laravel 怎麼處理日期與時間 ? Carbon 使用 他的底層是使用了 Datetime 這個 PHP 處理時間格式已久的套件,在操作風格上,也跟 JavaScript 生態系熱門的時間套件 moment.js 有許多雷同之處 運算過程,會改變到原始的物件,所以不像執行 Laravel 本身 Collection 的 map , filter ,本來的物件仍會維持原樣,Carbon 裡經過計算的物件值會改變,所以要善用 copy() 語法 https://medium.com/johnliu-%E7%9A%84%E8%BB%9F%E9%AB%94%E5%B7%A5%E7%A8%8B%E6%80%9D%E7%B6%AD/laravel-%E6%80%8E%E9%BA%BC%E8%99%95%E7%90%86%E6%97%A5%E6%9C%9F%E8%88%87%E6%99%82%E9%96%93-carbon-%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7%E6%95%B4%E7%90%86-%E4%B8%8A-4f1ea985abad https://medium.com/johnliu-%E7%9A%84%E8%BB%9F%E9%AB%94%E5%B7%A5%E7%A8%8B%E6%80%9D%E7%B6%AD/laravel-%E6%80%8E%E9%BA%BC%E8%99%95%E7%90%86%E6%97%A5%E6%9C%9F%E8%88%87%E6%99%82%E9%96%93-carbon-%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7%E6%95%B4%E7%90%86-%E4%B8%8B-2cd9c8b99eb4 當前時間 https://www.cnblogs.com/hf8051/p/4466314.html ## 中文 https://medium.com/johnliu-%E7%9A%84%E8%BB%9F%E9%AB%94%E5%B7%A5%E7%A8%8B%E6%80%9D%E7%B6%AD/laravel-%E6%80%8E%E9%BA%BC%E8%99%95%E7%90%86%E6%97%A5%E6%9C%9F%E8%88%87%E6%99%82%E9%96%93-carbon-%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7%E6%95%B4%E7%90%86-%E4%B8%8A-4f1ea985abad ![](https://i.imgur.com/75iHVST.png) ![](https://i.imgur.com/eCtVzli.png) ## 抓取期間內的時間 使用 CarbonPeriod https://stackoverflow.com/questions/31849334/php-carbon-get-all-dates-between-date-range ## 使用 Eloquent 和 Carbon 生成月度圖表數據 https://genijaho.medium.com/generate-monthly-chart-data-with-eloquent-carbon-a0f1296c5a35 ## php用法 ![](https://i.imgur.com/kiXlLPP.png) 看看就好 ## Carbon 是在PHP裏頭負責處理日期運算的套件,非常強大。 使用前可使用 use \Carbon\Carbon; 來導入 ``` \Carbon\Carbon::setLocale('zh_TW'); 設定Carbon套件的語系 \Carbon\Carbon::now() 使用Carbon套件來生成日期 \Carbon\Carbon::parse($str) 將date字串進行轉換成carbon物件 \Carbon\Carbon::createFromFormat('Y-m-d',$date) 依照參數格式將date字串轉成Carbon物件 Carbon變數->year 取得年份 Carbon變數->month 取得月份 Carbon變數->addDays(8) 將此日期加上8天 Carbon變數->format('Y-m-d')將此日期依照yyyy-mm-dd的方式來呈現 Carbon變數->diffForHumans() 將顯示字串改成口語化表示 ``` ## 快速建立與 Parse ![](https://i.imgur.com/FcyOyOa.png) Carbon 的直接建立,就會是當下的時間,而且還能解析文字,像 first day of January 2008 就可以解析出 2008–12–01,且指定時區為 America / Vancouver。 最常用的就是 parse 方法,可以解析時間格式字串,直接產生 Carbon 物件,而 parse 底層使用的,其實是 PHP Datetime 的 strtotime。 ## 有規則建立 ![](https://i.imgur.com/fuznLRz.png) 如果有指定好的 year、month 等 value,就推薦使用 create 語法,第一行是完整的語法,也可以看到有 createFromDate, createFromTime 等等的設定方式,所以如果蒐集到的時間資料並不完整,也是可以產生 Carbon 物件,只是就預設填最小值! 而也可以用操作 parse 的方式操作 create,只是並不完全使用到了 create 函式的用途,另外如果不帶值,就會跑出 0001–01–01 這個奇怪的日期 ## Bug 注意與安全模式 操作 Carbon 要小心一個問題,建立時由於 createFromXXX 預設帶值的特性是抓『當下時間』的 day、hour 等等,所以變成在大月的月底時使用起來要非常小心,不然就會像例圖一樣,跨月了。 而如果使用 createSafe 的安全模式建立,Carbon 就會幫忙檢查合不合理,像是 2000, 1, 35 這種時間值不合理,就會有 Exception 跳出可以讓開發者處理。 ## 時間格式、時區與本地化( Localization ) ![](https://i.imgur.com/fueiRlb.png) 大小寫是有意義的,而這個縮寫觀念是各大語言共通,可能會有一些小細節不同,但整體邏輯是共用的。 再來,所謂時間會有個 ISO 的國際標準格式判斷,在 Carbon 裡會針對上表做一些特殊的轉化,例如: d, dd, dddd 會被轉成 0, Su, Sunday ; Y, YY 被轉成 2020, 20 等等。 再來是一些習慣計算方式的不同,d 代表的禮拜幾是 0–6,同義有個 E,但是是 (1–7),可能更符合我們華語地區的習慣。 同理,H 代表 ( 1–24),而也可用 k 代表 ( 0–23 ) 最後是語法糖的部分,Carbon 提供以『 L』作為變化的時間格式顯示,而且可以按照設定的時區產文字,例如當啟動 Carbon 的 Laravel 應用程式,時區預設為 Taipei,則當設定 Carbon::now()->isoFormat('LLLL') ,則會產生『2021年5月21日星期五 23:33』這樣子的文字。 ## 本地語系設定 ![](https://i.imgur.com/vKSU2Mx.png) 除了使用時才設定外,也可以用 Carbon 的 Factory 類別,產生一個已有特定設定的 Carbon 物件,很適合拿來做大範圍通用設定時使用。 而如果只是暫時設定,而且有多個包括語系、時區要設定,則也推薦使用 settings 語法。 ## Format ![](https://i.imgur.com/g5OwqGF.png) format 就是大家開發時最常用到,各種轉時間樣貌的功能,可以加上你要的 『/ 』、『-』、『_』 等等符號都可以!而有個有趣的地方是,如果轉出來的資料是有語系檔支援的,也可使用 translatedFormat,來拿到本地語系化的值喔。 不過依筆者開發經驗來說,這並不實用,想要呈現什麼文字還是另外用字串組合,更易讀也更具彈性,因此最實用的還是使用 format 語法。 除了利用 format + 時間格式縮碼調整時間資料,Carbon 也可以使用 toDateString() , toTimeString() , toISOString() 等各種不同 Carbon 物件轉成 string 格式的方式。除了轉成 string 的不同方式,也有提供 toArray() , toObject() 等轉不同格式的方法,讓開發者能更優雅的操作時間資料。 ## 判斷格式 ![](https://i.imgur.com/4xFW1PU.png) 而有些時候,我們的開發是必需要要先知道資料是屬於什麼格式,因此 Carbon 也有提供 hasFormat() 和 hasFormatWithModifiers() 兩個判斷 format 的函式,前者可以完全配合開發者設定的格式,就算日期之間都用『 ~ 』分隔也可以 ; 後者則是使用模糊比對,可以使用『 #』去區隔時間縮碼,這樣就能同時判斷『 /』和『 — 』,更加彈性 ## Getter & Setter ![](https://i.imgur.com/yr3JmLb.png) Carbon 提供 year , month 等等不同的時間屬性,可以讓開發者直接取得 integer 資料型別的屬性資料,同時也提供比較複雜的時間判斷,例如 dayOfYear 一年中的第幾天,daysInMonth 可以取得一個月中的天數。 **Setter** Carbon 也針對 year , month 等時間屬性提供 setter,讓你能直接設定為特定年度、月度、時等等。 ## 時區與語系 ![](https://i.imgur.com/bKITsut.png) 可以判斷 Carbon 物件的語系有沒有符合應用程式,以及有沒有使用 UTC 國際標準時區。 ## 複雜的 要時分秒 ![](https://i.imgur.com/OIpAiuM.png) 再來 Carbon 針對比較複雜的設定方式,例如只想設定時分秒,但日期要保持原樣,則可使用 setTimeFrom() ,這樣就能只改變時分秒,不改變日期。而 Carbon 也有提供 setDateFrom() , setDateTimeFrom() 兩種調整方式,但要注意一點,這樣做『不會』改掉 timezone,timezone 值仍會保持原狀。 ## 比較(Comparison) 預先認知: php 7.1 後,才會比對到毫秒 **大於、小於和等於** ![](https://i.imgur.com/6vRvIfr.png) 大家可以注意到範例,兩個變數最大的差別就在於時區,而就因為這點,在使用 equalTo 和 notEqualTo 的時候,就會有所不同。 ![](https://i.imgur.com/jcTl4fM.png) 再來是大於小於的比較部分,基本上就是用很口語化的 greaterThan(), lessThan() 去表示,也有縮寫的 gte(), lt()可以使用,如果不喜歡用函式表示,也可以用最基本的運算式 >、<、= 符號。 **between** ![](https://i.imgur.com/DP1XP9l.png) **mix max** ![](https://i.imgur.com/hREms2S.png) 再來還可以用 min、max 比對兩個 Carbon 物件的最小與最大值,然後是一個讓筆者覺得很好用,在用時間切割,算帳務、行程等等所屬相關的業務邏輯時,很常使用到的 closest 和 farthest 函式,可以找 ## Overflow 加減運算要注意 Carbon 的日期運算會有個嚴重的問題 overflow,這是實務上很常見的問題,主要是因為 Carbon 在做日期加減運算時,不一定會考量月份天數的合理性,所以運算完後會給出啼笑皆非的結果,例如: ![](https://i.imgur.com/XvWSXY1.png) 1/31 號的日期,經過加 1 個月,盡然變成 3/3,而不是合理上的 2/28 或 2/29,所以在運算上,比較常使用的,是加上 NoOverflow 關鍵字的版本,讓值不會『溢出』,例如: ![](https://i.imgur.com/R0x0EhR.png) ###### tags: `Laravel`