---
# System prepended metadata

title: Laravel 怎麼處理日期與時間 ? Carbon 使用
tags: [Laravel]

---

# 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`