简介
一线开发人员每天都要使用日期和时间相关的功能,各种定时器,活动时间处理等。标准库time使用起来不太灵活,特别是日期时间的创建和运算。carbon库是一个时间扩展库,基于 PHP 的carbon库编写。提供易于使用的接口。Go社区还有另外一个同名库carbon,我称之为增强版,本文就来介绍一下这两个库,主要介绍低配版,二者差不多,会了低配版,增强版也就会了。增强版用的人更多,推荐使用增强版。
快速使用
第三方库需要先安装:
1
| $ go get -u github.com/uniplaces/carbon
|
后使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| package main
import (
"fmt"
"time"
"github.com/uniplaces/carbon"
)
func main() {
fmt.Printf("Right now is %s\n", carbon.Now().DateTimeString())
today, _ := carbon.NowInLocation("Japan")
fmt.Printf("Right now in Japan is %s\n", today)
fmt.Printf("Tomorrow is %s\n", carbon.Now().AddDay())
fmt.Printf("Last week is %s\n", carbon.Now().SubWeek())
nextOlympics, _ := carbon.CreateFromDate(2016, time.August, 5, "Europe/London")
nextOlympics = nextOlympics.AddYears(4)
fmt.Printf("Next olympics are in %d\n", nextOlympics.Year())
if carbon.Now().IsWeekend() {
fmt.Printf("Happy time!")
}
}
|
carbon
库的使用很便捷,首先它完全兼容标准库的time.Time
类型,实际上该库的日期时间类型Carbon
直接将time.Time
内嵌到结构中(继承了time.Time
结构体),所以time.Time
的方法可直接调用:
1
2
3
4
5
6
7
8
9
| // github.com/uniplaces/carbon/carbon.go
type Carbon struct {
time.Time
weekStartsAt time.Weekday
weekEndsAt time.Weekday
weekendDays []time.Weekday
stringFormat string
Translator *Translator
}
|
其次,简化了创建操作。标准库time
创建一个Time
对象,如果不是本地或 UTC 时区,需要自己先调用LoadLocation
加载对应时区。然后将该时区对象传给time.Time.In
或者time.Date
方法创建。carbon
可以直接传时区名字。底层其实也是用原始方法创建的,carbon
帮我们封装到了NowInLocation
方法中。只需要传入时区,就能获取指定时区当前时间。
carbon
还提供了很多方法做日期运算,如例子中的AddDay
,SubWeek
,Addyears
等。没有s默认+1,有s指定加多少,注意单位,都是见名知义的。
(上面的源码很简单,看不懂的话,建议去看一下源码)
CreateFromDate
方法,用于指定日期、时区创建Carbon
对象。时间部分默认是当前时间。如果没有指定时区(为空字符串),默认为UTC时区。字符串为Local,为本地时区。
一点点源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| // github.com\uniplaces\carbon\carbon.go
func CreateFromDate(y int, mon time.Month, d int, location string) (*Carbon, error) {
h, m, s := Now().Clock()
ns := Now().Nanosecond()
return Create(y, mon, d, h, m, s, ns, location)
func Create(y int, mon time.Month, d, h, m, s, ns int, location string) (*Carbon, error) {
l, err := time.LoadLocation(location)
if err != nil {
return nil, err
}
return create(y, mon, d, h, m, s, ns, l), nil
}
// time\zoneinfo.go
func LoadLocation(name string) (*Location, error) {
if name == "" || name == "UTC" {
return UTC, nil
}
if name == "Local" {
return Local, nil
}
...
// time\time.go
func Now() Time {
sec, nsec, mono := now()
mono -= startNano
sec += unixToInternal - minWall
if uint64(sec)>>33 != 0 {
// Seconds field overflowed the 33 bits available when
// storing a monotonic time. This will be true after
// March 16, 2157.
return Time{uint64(nsec), sec + minWall, Local}
}
return Time{hasMonotonic | uint64(sec)<<nsecShift | uint64(nsec), mono, Local} // 这里用本地时区。
}
|
总结:没有指定时区时,默认本地区时区,当要指定时区时,默认UTC时区。(底层源码目前看不懂😁😁😁)
时区
在介绍其它内容之前,我们先说一说这个时区的问题。以下引用维基百科的描述:
时区是地球上的区域使用同一个时间定义。以前,人们通过观察太阳的位置(时角)决定时间,这就使得不同经度的地方的时间有所不同(地方时)。1863年,首次使用时区的概念。时区通过设立一个区域的标准时间部分地解决了这个问题。 世界各国位于地球不同位置上,因此不同国家,特别是东西跨度大的国家日出、日落时间必定有所偏差。这些偏差就是所谓的时差。
例如,日本东京位于东九区,北京位于东八区,所以日本比中国快一个小时,日本14:00的时候中国13:00。
在 Linux 中,时区一般存放在类似/usr/share/zoneinfo
这样的目录。这个目录中有很多文件,每个时区一个文件。时区文件是二进制文件,可以执行info tzfile
查看具体格式。
时区名称的一般格式为city
,或country/city
,或continent/city
。即要么就是一个城市名,要么是国家名+/+城市名,要么是洲名+/+城市名。
例如上海时区为Asia/Shanghai
(在时区文件中表示东八区的时区,即北京时间),香港时区为Asia/Hong_Kong
或者Hongkong
(常识:中国标准时间(CST)为东八区时间,范围中国全境(大陆、港澳、台湾))意味着香港时间与北京时间一样,注意北京时间并不是北京的地方时,东八区在东经120°的地方,北京在东经116.4°。故东经120度地方时比北京的地方时早约14分半钟(了解)。还有CST,可能为其他地区的标准时间,如美国中部标准时间(Central Standard Time),使用的时候要注意上下文。
也有一些特殊的,如 UTC,Local等。
Go 语言为了可移植性,在安装包中提供了时区文件,在Go安装目录下的lib/time/zoneinfo.zip
文件,大家可以执行解压看看😀。
使用 Go 标准库time
创建某个时区的时间,需要先加载时区:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| package main
import (
"fmt"
"log"
"time"
)
func main() {
loc, err := time.LoadLocation("Japan")
if err != nil {
log.Fatal("failed to load location: ", err)
}
//t := time.Now().In(loc)
// 这里演示指定日期时间创建Time对象
d := time.Date(2020, time.July, 24, 20, 0, 0, 0, loc)
fmt.Printf("The opening ceremony of next olympics will start at %s in Japan\n", d)
}
|
使用carbon
就不用这么麻烦:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| package main
import (
"fmt"
"log"
"time"
"github.com/uniplaces/carbon"
)
func main() {
c, err := carbon.Create(2020, time.July, 24, 20, 0, 0, 0, "Japan")
if err != nil {
log.Fatal(err)
}
fmt.Printf("The opening ceremony of next olympics will start at %s in Japan\n", c)
}
|
创建对象
创建Carbon对象,可以通过:
Now
方法,返回本地时区的当前时间对象。
NewCarbon
方法,返回指定时间的本地时区时间对象。Now
方法是基于它创建的。
CreateFromDate
方法,用于指定日期、时区创建Carbon
对象。时间部分默认是当前时间。如果没有指定时区(为空字符串),默认为UTC时区。字符串为Local,为本地时区。
CrreateFromTime
方法一样,只不过是指定时间。- 注意,创建的日期,默认为当前日期。虽然没有指定,但不会没有。
Create
方法,返回根据日期、时间、时区创建的时间对象
Parse
方法,返回根据日期时间格式、指定的时间、时区解析的时间对象。
示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| package main
import (
"fmt"
"time"
"github.com/uniplaces/carbon"
)
func main() {
now := carbon.NewCarbon(time.Now())
fmt.Printf("New carbon from time instance: %s\n", now)
now = carbon.Now()
fmt.Printf("New carbon from Now function: %s\n", now)
fromDate, _ := carbon.CreateFromDate(2000, 1, 1, "Europe/London")
fmt.Printf("Created from date: %s\n", fromDate)
fromTime, _ := carbon.CreateFromTime(9, 16, 11, 0, "Europe/Madrid")
fmt.Printf("Created from time: %s\n", fromTime)
create, _ := carbon.Create(2024, 5, 14, 15, 3, 3, 3, "Local")
fmt.Println(create)
parsed, _ := carbon.Parse(carbon.DateFormat, "2000-08-20", "Europe/Berlin")
fmt.Printf("Parsed time: %s\n", parsed)
parse, _ := carbon.Parse(time.DateTime, "2024-05-14 22:10:22", "Local")
fmt.Println(parse)
timestamp, _ := carbon.CreateFromTimestamp(-1, "Local")
fmt.Println(timestamp) // 1970-01-01 07:59:59
}
|
后面会介绍时间格式化。
时间运算
使用标准库time
的时间运算需要先定义一个time.Duration
对象,time
库预定义的只有纳秒到小时的精度:
1
2
3
4
5
6
7
8
| const (
Nanosecond Duration = 1
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute
)
|
其它的时长就需要自己使用time.ParseDuration
构造了,而且time.ParseDuration
不能构造其它精度的时间。 如果想要增加/减少年月日,就需要使用time.Time
的AddDate
方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| package main
import (
"fmt"
"log"
"time"
)
func main() {
now := time.Now()
fmt.Println("now is:", now)
fmt.Println("one second later is:", now.Add(time.Second))
fmt.Println("one minute later is:", now.Add(time.Minute))
fmt.Println("one hour later is:", now.Add(time.Hour))
d, err := time.ParseDuration("3m20s")
if err != nil {
log.Fatal(err)
}
fmt.Println("3 minutes and 20 seconds later is:", now.Add(d))
d, err = time.ParseDuration("2h30m")
if err != nil {
log.Fatal(err)
}
fmt.Println("2 hours and 30 minutes later is:", now.Add(d))
fmt.Println("3 days and 2 hours later is:", now.AddDate(0, 0, 3).Add(time.Hour*2))
}
|
需要注意的是,时间操作都是返回一个新的对象,原对象不会修改。carbon
库也是如此。Go 的标准库也建议我们不要使用time.Time
的指针。 当然carbon
库也能使用上面的方法,它还提供了多种粒度的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| package main
import (
"fmt"
"github.com/uniplaces/carbon"
)
func main() {
now := carbon.Now()
fmt.Println("now is:", now)
fmt.Println("one second later is:", now.AddSecond())
fmt.Println("one minute later is:", now.AddMinute())
fmt.Println("one hour later is:", now.AddHour())
fmt.Println("3 minutes and 20 seconds later is:", now.AddMinutes(3).AddSeconds(20))
fmt.Println("2 hours and 30 minutes later is:", now.AddHours(2).AddMinutes(30))
fmt.Println("3 days and 2 hours later is:", now.AddDays(3).AddHours(2))
}
|
carbon
还提供了:
- 增加季度的方法:
AddQuarters/AddQuarter
,复数形式介绍一个表示倍数的参数,单数形式倍数为1; - 增加世纪的方法:
AddCenturies/AddCentury
; - 增加工作日的方法:
AddWeekdays/AddWeekday
,这个方法会跳过非工作日; - 增加周的方法:
AddWeeks/AddWeek
。
其实给上面方法传入负数就表示减少,另外carbon
也提供了对应的Sub*
方法。
时间比较
注意:时间比较的是快慢。
标准库time
可以使用time.Time
对象的Before/After/Equal
判断是否在另一个时间对象前,后,或相等。carbon
库也可以使用上面的方法比较时间。除此之外,它还提供了多组方法,每个方法提供一个简短名,一个详细名:
Eq/EqualTo
:是否相等;不同时区的日期时间不同,但时间可能会相等。如 6:00 +0200 and 4:00 UTC are Equal.Ne/NotEqualTo
:是否不等;Gt/GreaterThan
:是否在之后;Gte/GreaterThanOrEqualTo
:快或者相等。Lt/LessThan
:是否在之前;Lte/LessThanOrEqualTo
:是否相同或在之前;Between
:是否在两个时间之间。
另外carbon
提供了:
- 判断当前时间是周几的方法:
IsMonday/IsTuesday/.../IsSunday
; - 是否是工作日,周末,闰年,过去时间还是未来时间:
IsWeekday/IsWeekend/IsLeapYear/IsPast/IsFuture
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| package main
import (
"fmt"
"github.com/uniplaces/carbon"
)
func main() {
t1, _ := carbon.CreateFromDate(2010, 10, 1, "Asia/Shanghai")
t2, _ := carbon.CreateFromDate(2011, 10, 20, "Asia/Shanghai")
fmt.Printf("t1 equal to t2: %t\n", t1.Eq(t2))
fmt.Printf("t1 not equal to t2: %t\n", t1.Ne(t2))
fmt.Printf("t1 greater than t2: %t\n", t1.Gt(t2))
fmt.Printf("t1 less than t2: %t\n", t1.Lt(t2))
fmt.Printf("t1 greater than or equal: %t", t1.Gte(t2))
t3, _ := carbon.CreateFromDate(2011, 1, 20, "Asia/Shanghai")
fmt.Printf("t3 between t1 and t2: %t\n", t3.Between(t1, t2, true))
now := carbon.Now()
fmt.Printf("Weekday? %t\n", now.IsWeekday())
fmt.Printf("Weekend? %t\n", now.IsWeekend())
fmt.Printf("LeapYear? %t\n", now.IsLeapYear())
fmt.Printf("Past? %t\n", now.IsPast())
fmt.Printf("Future? %t\n", now.IsFuture())
}
|
时间差
我们还可以使用carbon
计算两个日期之间相差多少秒、分、小时、天。
用到的方法是func (c *Carbon) DiffInXXX(carb *Carbon, abs bool)
,表示的是相对于对象c快了还慢了多少XXX。正数表示c慢了,负数表示c快了。原理:
1
| diff := carb.Timestamp() - c.Timestamp()
|
abs表示是否启用绝对值。
示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| package main
import (
"fmt"
"github.com/uniplaces/carbon"
)
func main() {
cst, _ := carbon.Today("Asia/Shanghai")
hongKong, _ := carbon.Today("Hongkong")
Japan, _ := carbon.Today("Japan")
fmt.Println(cst.DiffInSeconds(hongKong, true)) // 0
fmt.Println(cst.DiffInHours(Japan, false)) // 0
Beijing, _ := carbon.CreateFromDate(2000, 1, 1, "Asia/Shanghai")
Tokyo, _ := carbon.CreateFromDate(2000, 1, 1, "Japan")
fmt.Println(Beijing.DiffInHours(Tokyo, true)) // 1
fmt.Println(Beijing.DiffInHours(Tokyo, false)) // -1
fmt.Println(Tokyo.DiffInHours(Beijing, false)) // 1
t, _ := carbon.CreateFromDate(2012, 1, 1, "UTC")
fmt.Println(t.DiffInDays(t.Copy().AddMonth(), false)) // 31
fmt.Println(t.DiffInDays(t.Copy().SubMonth(), false)) // -31
t, _ = carbon.CreateFromDate(2012, 4, 30, "UTC")
fmt.Println(t.DiffInDays(t.Copy().AddMonth(), false)) // 30
fmt.Println(t.DiffInDays(t.Copy().AddWeek(), false)) // 7
t, _ = carbon.CreateFromTime(10, 1, 1, 0, "UTC")
fmt.Println(t.DiffInMinutes(t.Copy().AddSeconds(59), true)) // 0
fmt.Println(t.DiffInMinutes(t.Copy().AddSeconds(60), true)) // 1
fmt.Println(t.DiffInMinutes(t.Copy().AddSeconds(119), true)) // 1
fmt.Println(t.DiffInMinutes(t.Copy().AddSeconds(120), true)) // 2
fmt.Println(t.DiffInHours(t.Copy().AddMinutes(59), false)) // 0
fmt.Println(t.DiffInHours(t.Copy().AddMinutes(60), false)) // 1
fmt.Println(t.DiffInHours(t.Copy().AddHours(2).AddMinutes(60), false)) // 3
}
|
注意:
- 上面输出完全正确。
- 不理解是因为:
- 正数表示c慢了,负数表示c快了。
- 当北京时间和东京时间数字相同时,其实北京时间要快一个小时。即相同数字的北京时间和东京时间,北京时间的时间戳要大一点。因为实际北京时间比东京时间慢一个小时。
格式化
我们知道time.Time
提供了一个Format
方法,相比于其他编程语言使用格式化符来描述格式(需要记忆%d/%m/%h
等的含义),Go 提供了一个一种更简单、直观的方式——使用 layout。即我们传入一个日期字符串,表示我们想要格式化成什么样子。Go 会用当前的时间替换字符串中的对应部分:
1
2
3
4
5
6
7
8
9
10
11
| package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Println(t.Format("2006-01-02 15:04:05"))
}
|
上面我们只需要传入一个2006-01-02 15:04:05
表示我们想要的格式为yyyy-mm-dd hh:mm:ss
,省去了我们需要记忆的麻烦。
为了使用方便,Go 内置了一些标准的时间格式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| // time/format.go
const (
Layout = "01/02 03:04:05PM '06 -0700" // The reference time, in numerical order.
ANSIC = "Mon Jan _2 15:04:05 2006"
UnixDate = "Mon Jan _2 15:04:05 MST 2006"
RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
RFC822 = "02 Jan 06 15:04 MST"
RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Kitchen = "3:04PM"
// Handy time stamps.
Stamp = "Jan _2 15:04:05"
StampMilli = "Jan _2 15:04:05.000"
StampMicro = "Jan _2 15:04:05.000000"
StampNano = "Jan _2 15:04:05.000000000"
DateTime = "2006-01-02 15:04:05"
DateOnly = "2006-01-02"
TimeOnly = "15:04:05"
)
|
后面三个是在后面版本加上进的。
除了上面这些格式,carbon
还提供了其他一些格式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // github.com/uniplaces/carbon
const (
DefaultFormat = "2006-01-02 15:04:05"
DateFormat = "2006-01-02"
FormattedDateFormat = "Jan 2, 2006"
TimeFormat = "15:04:05"
HourMinuteFormat = "15:04"
HourFormat = "15"
DayDateTimeFormat = "Mon, Jan 2, 2006 3:04 PM"
CookieFormat = "Monday, 02-Jan-2006 15:04:05 MST"
RFC822Format = "Mon, 02 Jan 06 15:04:05 -0700"
RFC1036Format = "Mon, 02 Jan 06 15:04:05 -0700"
RFC2822Format = "Mon, 02 Jan 2006 15:04:05 -0700"
RFC3339Format = "2006-01-02T15:04:05-07:00"
RSSFormat = "Mon, 02 Jan 2006 15:04:05 -0700"
)
|
注意一点,time
库默认使用2006-01-02 15:04:05.999999999 -0700 MST
格式,有点复杂了,carbon
库默认使用更简洁的2006-01-02 15:04:05
。
使用只需要调func (t Time) Format(layout string)
方法,layout
为上面提供的格式化字符串。
carbon
为了进一步方便使用,都将Fomat
方法封装到了指定XxxString
方法中.
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| package main
import (
"fmt"
"time"
"github.com/uniplaces/carbon"
)
func main() {
now := carbon.Now()
fmt.Println(now.Format(time.DateTime))
fmt.Println(now.Format(carbon.DefaultFormat), "=", now.DateTimeString())
fmt.Println(now.Format(time.RFC3339))
fmt.Println(now.Format(carbon.RFC3339Format), "=", now.RFC3339String())
fmt.Println(now.Format(carbon.DateFormat), "=", now.DateString())
}
|
运行输出:
1
2
3
4
5
6
| $ go run main.go
2024-05-14 11:23:01
2024-05-14 11:23:01 = 2024-05-14 11:23:01
2024-05-14T11:23:01+08:00
2024-05-14T11:23:01+08:00 = 2024-05-14T11:23:01+08:00
2024-05-14 = 2024-05-14
|
高级特性
修饰器
Boundary:边界
所谓修饰器(modifier)就是对一些特定的时间操作,获取开始和结束时间。如当天、月、季度、年、十年、世纪、周的开始和结束时间,还能获得上一个周二、下一个周一、下一个工作日的时间等等:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| package main
import (
"fmt"
"time"
"github.com/uniplaces/carbon"
)
func main() {
t := carbon.Now()
fmt.Printf("Start of day:%s\n", t.StartOfDay())
fmt.Printf("End of day:%s\n", t.EndOfDay())
fmt.Printf("Start of month:%s\n", t.StartOfMonth())
fmt.Printf("End of month:%s\n", t.EndOfMonth())
fmt.Printf("Start of year:%s\n", t.StartOfYear())
fmt.Printf("End of year:%s\n", t.EndOfYear())
fmt.Printf("Start of decade:%s\n", t.StartOfDecade())
fmt.Printf("End of decade:%s\n", t.EndOfDecade())
fmt.Printf("Start of century:%s\n", t.StartOfCentury())
fmt.Printf("End of century:%s\n", t.EndOfCentury())
fmt.Printf("Start of week:%s\n", t.StartOfWeek())
fmt.Printf("End of week:%s\n", t.EndOfWeek())
fmt.Printf("Next:%s\n", t.Next(time.Wednesday))
fmt.Printf("Previous:%s\n", t.Previous(time.Wednesday))
}
|
自定义工作日和周末
有些地区每周的开始、周末和我们的不一样。Carbon默认是
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| func NewCarbon(t time.Time) *Carbon {
wds := []time.Weekday{
time.Saturday,
time.Sunday,
}
return &Carbon{
Time: t,
weekStartsAt: time.Monday,
weekEndsAt: time.Sunday,
weekendDays: wds,
stringFormat: DefaultFormat,
Translator: translator(),
}
}
|
例如,在美国周日是新的一周开始。没关系,carbon
可以自定义每周的开始和周末:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| package main
import (
"fmt"
"log"
"time"
"github.com/uniplaces/carbon"
)
func main() {
t, err := carbon.Create(2020, 02, 11, 0, 0, 0, 0, "Asia/Shanghai")
if err != nil {
log.Fatal(err)
}
t.SetWeekStartsAt(time.Sunday)
t.SetWeekEndsAt(time.Saturday)
t.SetWeekendDays([]time.Weekday{time.Monday, time.Tuesday, time.Wednesday})
fmt.Printf("Today is %s, weekend? %t\n", t.Weekday(), t.IsWeekend())
}
|
这个库一般默认就行。
批量生成日期
利用Period
方法,可以批量生成日期,接收三个参数。
- 第一个:开始的时间。
- 第二个:日期间隔。
- 第三个:结束的时间。
- 返回值是一个时间对象切片。
效果为:从开始时间每隔多少天创建一个时间对象,直到结束日期。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| package main
import (
"fmt"
"github.com/uniplaces/carbon"
)
func main() {
t1, _ := carbon.Create(2012, 1, 1, 12, 0, 0, 0, "UTC")
t2, _ := carbon.Create(2012, 1, 31, 12, 0, 0, 0, "UTC")
days := 7
periods, err := carbon.Period(t1, days, t2)
if err != nil {
return
}
for _, val := range periods {
fmt.Println(val)
}
}
|
运行输出:
1
2
3
4
5
6
| $ go run main.go
2012-01-01 12:00:00
2012-01-08 12:00:00
2012-01-15 12:00:00
2012-01-22 12:00:00
2012-01-29 12:00:00
|
(不常用)
增强版介绍
下载:
1
2
| # 增强版
$ go get -u github.com/golang-module/carbon/v2
|
增强版创建对象
创建时间对象与低配版不一样。
增强版的Now
函数,参数是时区,为可选参数,默认为本地时区。增强版的时区,没有指定,一律为本地时区。
低配版直接通过NewCarbon
指定时间创建时间对象,而高配版还需要调CreateXxx
方法指定时间才能完成创建。
并且低配版如果只创建日期,那么时间为当前时间。而高配版只创建日期,时间为0:0:0
.
- 当只创建时间时,二者的日期都是为当前日期。
高配版移除了Create
方法,创建了更多CreateXxx
方法。用于指定时间或日期创建对象。
对Parse
方法进行了增强,并且还提供了另外两个方法,进行创建对象。这几个方法的时区都可选的,默认为本地时区。
增强版Parse
方法只能指定要解析的字符串和时区(可选)创建对象。如果没有指定时区,默认本地时区。时间布局任意。底层会遍历所有支持的布局模板(增强版叫Layout)。
ParseByLayout
方法在Parse
方法的基础上增加了一个布局模板参数。
ParseByFormat
方法在Parse
方法的基础上增加了一个格式模版参数。
布局模板以Layout结尾,就是原来的Format
方法的参数。
1
| DateLayout = "2006-01-02"
|
格式模版以format结尾,增强版新加的,由日期时间的格式化字符组成的字符串
1
| DateTimeFormat = "Y-m-d H:i:s"
|
注意carbon
包的内部错误,都封装到了时间对象的Error
属性下。
如果有多个错误发生,只返回第一个错误,前一个错误排除后才返回下一个错误
1
2
3
4
5
6
7
| c := carbon.SetTimezone("xxx").Parse("2020-08-05")
if c.Error != nil {
// 错误处理
log.Fatal(c.Error)
}
// 输出
invalid timezone "xxx", please see the file "$GOROOT/lib/time/zoneinfo.zip" for all valid timezones
|
实例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| package main
import (
"fmt"
"log"
"github.com/golang-module/carbon/v2"
)
func main() {
now := carbon.Now()
now = carbon.NewCarbon().Now()
fmt.Println(now) //
stdTime := carbon.CreateFromStdTime(time.Now())
fmt.Println(stdTime) //
fromDate := carbon.CreateFromDate(2024, 5, 14)
fromDate = carbon.NewCarbon().CreateFromDate(2024, 5, 14)
fmt.Println(fromDate) // 2024-05-14 00:00:00
dateTime := carbon.CreateFromDateTime(2024, 5, 14, 10, 22, 33)
dateTime = carbon.NewCarbon().CreateFromDateTime(2024, 5, 14, 10, 22, 33)
fmt.Println(dateTime) // 2024-05-14 10:22:33
assertErr := func(carbon carbon.Carbon) {
if carbon.Error != nil {
log.Fatal(carbon.Error)
}
}
parse := carbon.Parse("2024-05-20 10:22:33")
assertErr(parse)
fmt.Println(parse) // 2024-05-20 10:22:33
parse = carbon.ParseByLayout("2024-05-20", carbon.DateLayout)
assertErr(parse)
fmt.Println(parse) // 2024-05-20 00:00:00
parse = carbon.ParseByFormat("2024-05-20 10:22:33", carbon.DateTimeFormat)
assertErr(parse)
fmt.Println(parse) // 2024-05-20 10:22:33
toString := carbon.CreateFromTimestamp(-1)
fmt.Println(toString) // 1970-01-01 07:59:59
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| // Create a Carbon instance from a given hour, minute and second
carbon.CreateFromTime(13, 14, 15).ToString() // 2020-08-05 13:14:15 +0800 CST
// Create a Carbon instance from a given hour, minute and second with millisecond
carbon.CreateFromTimeMilli(13, 14, 15, 999).ToString() // 2020-08-05 13:14:15.999 +0800 CST
// Create a Carbon instance from a given hour, minute and second with microsecond
carbon.CreateFromTimeMicro(13, 14, 15, 999999).ToString() // 2020-08-05 13:14:15.999999 +0800 CST
// Create a Carbon instance from a given hour, minute and second with nanosecond
carbon.CreateFromTimeNano(13, 14, 15, 999999999).ToString() // 2020-08-05 13:14:15.999999999 +0800 CST
carbon.Parse("now").ToString() // 2020-08-05 13:14:15 +0800 CST
carbon.Parse("yesterday").ToString() // 2020-08-04 13:14:15 +0800 CST
carbon.Parse("tomorrow").ToString() // 2020-08-06 13:14:15 +0800 CST
carbon.Parse("2020").ToString() // 2020-01-01 00:00:00 +0800 CST
carbon.Parse("2020-8").ToString() // 2020-08-01 00:00:00 +0800 CST
carbon.ParseByFormat("2020|08|05 13|14|15", "Y|m|d H|i|s").ToDateTimeString() // 2020-08-05 13:14:15
carbon.ParseByFormat("It is 2020-08-05 13:14:15", "\\I\\t \\i\\s Y-m-d H:i:s").ToDateTimeString() // 2020-08-05 13:14:15
carbon.ParseByFormat("今天是 2020年08月05日13时14分15秒", "今天是 Y年m月d日H时i分s秒").ToDateTimeString() // 2020-08-05 13:14:15
carbon.ParseByLayout("2020|08|05 13|14|15", "2006|01|02 15|04|05").ToDateTimeString() // 2020-08-05 13:14:15
carbon.ParseByLayout("It is 2020-08-05 13:14:15", "It is 2006-01-02 15:04:05").ToDateTimeString() // 2020-08-05 13:14:15
carbon.ParseByLayout("今天是 2020年08月05日13时14分15秒", "今天是 2006年01月02日15时04分05秒").ToDateTimeString() // 2020-08-05 13:14:15
|
一些默认值
增强版创建的时间对象的默认值:
- 时间格式与低配版一直,名字改成
carbon.DateTimeLayout
。 - 时区默认都为本地时区。
- 工作日开始是在
Sunday
,低配版是在星期一。 - 默认的语言区域是en。支持的语言在
github.com\golang-module\carbon\lang
目录下。
这些属性可以通过func SetDefault(d Default)
方法修改。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| package main
import (
"fmt"
"github.com/golang-module/carbon/v2"
)
func main() {
now := carbon.Now()
fmt.Println(now)
carbon.SetDefault(carbon.Default{Layout: carbon.RFC3339Layout,
Timezone: carbon.Local,
WeekStartsAt: carbon.Monday,
Locale: "zh-CN"})
fmt.Println(now)
}
|
官方建议在main.go等入口文件中修改默认值。
对象互转
增强版可以实现time.Time
对象与Carbon
对象相互转换。
示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| package main
import (
"fmt"
"time"
"github.com/golang-module/carbon/v2"
)
func main() {
carbonTime := carbon.CreateFromTime(22, 22, 22)
stdTime := carbonTime.StdTime()
fmt.Println(stdTime) // 2024-05-14 22:22:22 +0800 CST
stdTime = time.Date(2024, 5, 14, 22, 22, 22, 0, time.Local)
carbonTime = carbon.CreateFromStdTime(stdTime)
fmt.Println(carbonTime) // 2024-05-14 22:22:22
}
|
更多细节的增强
对象转字符串
增强版提供了更多时间对象转字符串的方法。除了String
方法外,添加了ToXxxString方法:
1
2
3
4
5
6
7
8
9
| carbon.Now().String() // 2020-08-05 13:14:15
carbon.Now().ToString() // 2020-08-05 13:14:15 +0800 CST
carbon.Now().ToDateTimeString() // 2020-08-05 13:14:15
// Return date of today
carbon.Now().ToDateString() // 2020-08-05
// Return time of today
carbon.Now().ToTimeString() // 13:14:15
// Return datetime of today in a given timezone
carbon.Now(Carbon.NewYork).ToDateTimeString() // 2020-08-05 14:14:15
|
注意:增强版有一个坑:当我们直接输出Carbon
对象时,会自动调用String
方法,这个String
方法会将时区改成本地。若不希望修改时区,请不要调用String
方法,用别的转字符串的方法,如ToDateTimeString
。
更多内容参考时间输出
对象转时间戳
通过增强版,我们可以方便的将Carbon对象转换成指定单位的时间戳:
1
2
3
4
5
6
7
8
9
| carbon.Now(Carbon.NewYork).ToDateTimeString() // 2020-08-05 14:14:15
// Return timestamp with second of today
carbon.Now().Timestamp() // 1596604455
// Return timestamp with millisecond of today
carbon.Now().TimestampMilli() // 1596604455999
// Return timestamp with microsecond of today
carbon.Now().TimestampMicro() // 1596604455999999
// Return timestamp with nanosecond of today
carbon.Now().TimestampNano() // 1596604455999999999
|
获取昨天、明天的对象
增强版,不仅能够获取当前的时间对象,还能获取昨天或者明天的时间:
1
2
3
4
5
6
7
8
| fmt.Printf("%s", carbon.Yesterday()) // 2020-08-04 13:14:15
carbon.Yesterday().String() // 2020-08-04 13:14:15
carbon.Yesterday().ToString() // 2020-08-04 13:14:15 +0800 CST
carbon.Yesterday(Carbon.NewYork).ToDateTimeString() // 2020-08-04 13:14:15
carbon.Tomorrow().String() // 2020-08-06 13:14:15
carbon.Tomorrow().ToString() // 2020-08-06 13:14:15 +0800 CST
carbon.Tomorrow().ToDateTimeString() // 2020-08-06 13:14:15
|
增强时间戳创建对象
低配版只能通过CreateFromTimestamp
和CreateFromTimestampUTC
函数创建对象,增强版提供了毫秒、微秒、纳秒时间戳创建对象。时区默认本地时区。
1
2
3
4
5
6
7
8
| carbon.CreateFromTimestamp(1649735755).ToString() // 2022-04-12 11:55:55 +0800 CST
// Create a Carbon instance from a given timestamp with millisecond
carbon.CreateFromTimestampMilli(1649735755981).ToString() // 2022-04-12 11:55:55.981 +0800 CST
// Create a Carbon instance from a given timestamp with microsecond
carbon.CreateFromTimestampMicro(1649735755981566).ToString() // 2022-04-12 11:55:55.981566 +0800 CST
// Create a Carbon instance from a given timestamp with nanosecond
carbon.CreateFromTimestampNano(1649735755981566000).ToString() // 2022-04-12 11:55:55.981566 +0800 CST
carbon.CreateFromTimestampNano(1649735755981566000, "Japan").ToString() // 2022-04-12 12:55:55.981566 +0900 JST 快一个小时。
|
其他创建对象增强
时间的边界
与低配版一模一样。详情请看修饰器。
增强时间运算
支持链式调用,对应时间的运算,增加了不会溢出的方法。
默认低配版和高配版进行时间运算时,当为2月29的时候,即闰年的时候,计算到不是闰年,都没有29号,那么时间默认会溢出,变成3月1号。增强版提供了AddXxxNoOverflow
、SubXxxNoOverflow
方法(低配版部分有,高配版基本都有),让时间不会溢出,为2月28。(闰年比公历年多1天。)
增强版还增强了别的单位进行运算,如XxxDecades
十年、XxxDuration
根据片段进行运算。还更小单位的运算,如SubMillisecond
、SubNanossecond
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| // 三个年代后
carbon.Parse("2020-02-29 13:14:15").AddDecades(3).ToDateTimeString() // 2050-03-01 13:14:15
// 三个年代后(月份不溢出)
carbon.Parse("2020-02-29 13:14:15").AddDecadesNoOverflow(3).ToDateTimeString() // 2050-02-28 13:14:15
// 一个年代后
carbon.Parse("2020-02-29 13:14:15").AddDecade().ToDateTimeString() // 2030-03-01 13:14:15
// 一个年代后(月份不溢出)
carbon.Parse("2020-02-29 13:14:15").AddDecadeNoOverflow().ToDateTimeString() // 2030-02-28 13:14:15
// 二小时半前
carbon.Parse("2020-08-05 13:14:15").SubDuration("2.5h").ToDateTimeString() // 2020-08-05 10:44:15
carbon.Parse("2020-08-05 13:14:15").SubDuration("2h30m").ToDateTimeString() // 2020-08-05 10:44:15
// 三微秒后
carbon.Parse("2020-08-05 13:14:15.222222222").AddMicroseconds(3).ToString() // 2020-08-05 13:14:15.222225222 +0800 CST
// 一微秒后
carbon.Parse("2020-08-05 13:14:15.222222222").AddMicrosecond().ToString() // 2020-08-05 13:14:15.222223222 +0800 CST
|
其他的与低配版一直。
增强时间差
- 增强版移除了是否取绝对值参数,封装到了
DiffAbsInXxx
方法中。- 原理差不多,后面-前面。快为负数,慢为正数(相对调用的时间对象)。
- 其他相差多少分、小时、年、与低配版时间差一直
- 新增时间差的字符串表示,用
DiffInString
方法获取,默认参数为当前时间。- 同样提供了绝对值方法
DiffAbsInString
- 需要注意的是:目前时间差的字符串表示只能表示差里面的最大时间单位。
- 如差2分30秒,结果为差2分钟。差3月22天,结果为差3个月
- 该方法支持国际化。
- 新增相差时长(片段)字符串表示。用
DiffInDuration
方法获取,默认参数为当前时间。- 同样提供了绝对值方法
DiffAbsInDuration
- 需要注意的是:这个方法会具体到相差多少时差。当最大单位为小时。
- 该方法同样支持国际化。
- 新增对人类友好的可读格式时间差。用
DiffForHumans
方法获取,默认参数为当前时间。- 该方法人类可读,移除了绝对值方法。能够直观的看见参数时间对象是前(负数)还是后(正数)。
- 需要注意的是该方法,与
DiffInString
一样,只能表示最大的时间单位。 - 同样支持国际化。
示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| package main
import (
"fmt"
"github.com/golang-module/carbon/v2"
)
func main() {
carbon.SetDefault(carbon.Default{
Layout: carbon.DateTimeLayout,
Timezone: carbon.Local,
WeekStartsAt: carbon.Monday,
Locale: "zh-CN",
})
inString := carbon.Now().DiffInString(carbon.Now().AddDays(22).AddMinutes(22))
fmt.Println(inString) // 3 周
diffInString := carbon.Now().AddHours(22).AddMinutes(22).DiffInString()
fmt.Println(diffInString) // -22 小时
diffAbsInDuration := carbon.Now().AddYears(2).AddMinutes(22).AddMicroseconds(22).DiffAbsInDuration()
fmt.Println(diffAbsInDuration) // 17520h22m0.000022s
inString = carbon.Now().DiffForHumans(carbon.Now().AddDays(22).AddMinutes(22))
fmt.Println(inString) // 3 周前
diffInString = carbon.Now().AddHours(22).AddMinutes(22).DiffForHumans()
fmt.Println(diffInString) // 22 小时后
}
|
获取时间极值
低配版只提供了Closest
和Farthest
获取距对象最近或最远的时间对象,低配版和高配版都只能传递两个时间对象。
高配版增强版新增两个方法Max
和``Min`,获取多个时间里面的最大或最小,参数为至少一个时间对象。
示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| c0 := carbon.Parse("2023-04-01")
c1 := carbon.Parse("2023-03-28")
c2 := carbon.Parse("2023-04-16")
// 返回最近的 Carbon 实例
c0.Closest(c1, c2) // c1
// 返回最远的 Carbon 实例
c0.Farthest(c1, c2) // c2
yesterday := carbon.Yesterday()
today := carbon.Now()
tomorrow := carbon.Tomorrow()
// 返回最大的 Carbon 实例
carbon.Max(yesterday, today, tomorrow) // tomorrow
// 返回最小的 Carbon 实例
carbon.Min(yesterday, today, tomorrow) // yesterday
|
增强时间判断
增强版新增判断时间是否有效:IsValid
、IsInvalid
新增更多的时间判断:
- 判断是否是早上、下午、当前、未来、过去、闰年、长年、几月、星期几、工作日、周末、昨天、今天、明天、同一世纪、同一年代、同一年、同一季节、同一月、同一天、同一小时、同一分钟、同一秒。方法名是
IsXxx
。
需要注意的是:增强版移除了自定义周末。周末默认都为星期6、星期天。只保留了设置一周开始的日期。
新增星座判断,方法为IsXxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| // 获取星座
carbon.Parse("2020-08-05 13:14:15").Constellation() // Leo
// 是否是白羊座
carbon.Parse("2020-08-05 13:14:15").IsAries() // false
// 是否是金牛座
carbon.Parse("2020-08-05 13:14:15").IsTaurus() // false
// 是否是双子座
carbon.Parse("2020-08-05 13:14:15").IsGemini() // false
// 是否是巨蟹座
carbon.Parse("2020-08-05 13:14:15").IsCancer() // false
// 是否是狮子座
carbon.Parse("2020-08-05 13:14:15").IsLeo() // true
// 是否是处女座
carbon.Parse("2020-08-05 13:14:15").IsVirgo() // false
// 是否是天秤座
carbon.Parse("2020-08-05 13:14:15").IsLibra() // false
// 是否是天蝎座
carbon.Parse("2020-08-05 13:14:15").IsScorpio() // false
// 是否是射手座
carbon.Parse("2020-08-05 13:14:15").IsSagittarius() // false
// 是否是摩羯座
carbon.Parse("2020-08-05 13:14:15").IsCapricorn() // false
// 是否是水瓶座
carbon.Parse("2020-08-05 13:14:15").IsAquarius() // false
// 是否是双鱼座
carbon.Parse("2020-08-05 13:14:15").IsPisces() // false
|
新增季节判断:按照气象划分,即3-5月为春季,6-8月为夏季,9-11月为秋季,12-2月为冬季
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // 获取季节
carbon.Parse("2020-08-05 13:14:15").Season() // Summer
// 本季节开始时间
carbon.Parse("2020-08-05 13:14:15").StartOfSeason().ToDateTimeString() // 2020-06-01 00:00:00
// 本季节结束时间
carbon.Parse("2020-08-05 13:14:15").EndOfSeason().ToDateTimeString() // 2020-08-31 23:59:59
// 是否是春季
carbon.Parse("2020-08-05 13:14:15").IsSpring() // false
// 是否是夏季
carbon.Parse("2020-08-05 13:14:15").IsSummer() // true
// 是否是秋季
carbon.Parse("2020-08-05 13:14:15").IsAutumn() // false
// 是否是冬季
carbon.Parse("2020-08-05 13:14:15").IsWinter() // false
|
增强时间比较
高配版保留了低配版的所有时间比较方法,同时新增判断是否在两个时间之间,包括两端的时间方法和比较方法Compare
,该方法需要指定比较字符=,<=,!=,<>
等(只能接收一个比较符,因为只能有一个时间参数比较)。示例如下:
1
2
3
4
5
6
7
8
9
| // 是否在两个时间之间(包括开始时间)
carbon.Parse("2020-08-05 13:14:15").BetweenIncludedStart(carbon.Parse("2020-08-05 13:14:15"), carbon.Parse("2020-08-06 13:14:15")) // true
// 是否在两个时间之间(包括结束时间)
carbon.Parse("2020-08-05 13:14:15").BetweenIncludedEnd(carbon.Parse("2020-08-04 13:14:15"), carbon.Parse("2020-08-05 13:14:15")) // true
// 是否在两个时间之间(包括这两个时间)
carbon.Parse("2020-08-05 13:14:15").BetweenIncludedBoth(carbon.Parse("2020-08-05 13:14:15"), carbon.Parse("2020-08-06 13:14:15")) // true
carbon.Parse("2020-08-05 13:14:15").Compare(">=", carbon.Parse("2020-08-05 13:14:15")) // true
carbon.Parse("2020-08-05 13:14:15").Compare("<>", carbon.Parse("2020-08-05 13:14:15")) // false 就是不等于
|
增强时间设置
示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| package main
import (
"fmt"
"time"
"github.com/golang-module/carbon/v2"
)
func main() {
Shanghai, _ := time.LoadLocation(carbon.Shanghai)
Beijing := carbon.SetLocation(Shanghai).Now()
BeijingStr := Beijing.ToDateTimeString()
Japan := carbon.SetTimezone(carbon.Japan).Now()
JapanStr := Japan.ToDateTimeString()
fmt.Printf("东京时间%s比北京时间%s快一个小时,但表示的是同一时刻\n", BeijingStr, JapanStr)
Beijing = carbon.SetTimezone(carbon.HongKong).Now()
BeijingStr = Beijing.ToDateTimeString()
Tokyo, _ := time.LoadLocation(carbon.Tokyo)
Japan = carbon.SetLocation(Tokyo).Now()
JapanStr = Japan.ToDateTimeString()
fmt.Printf("东京时间%s比北京时间%s快一个小时,但表示的是同一时刻\n", BeijingStr, JapanStr)
}
|
注意:增强版有一个坑:当我们直接输出Carbon
对象时,会自动调用String
方法,这个String
方法会将时区改成本地。若不希望修改时区,请不要调用String
方法,用别的转字符串的方法,如ToDateTimeString
。
1
2
3
4
5
6
7
| // 设置年月日时分秒纳秒
carbon.Parse("2020-01-01").SetDateTimeNano(2019, 2, 2, 13, 14, 15, 999999999).ToString() // 2019-02-02 13:14:15.999999999 +0800 CST
carbon.Parse("2020-01-01").SetDateTimeNano(2019, 2, 31, 13, 14, 15, 999999999).ToString() // 2019-03-03 13:14:15.999999999 +0800 CST
// 单独设置纳秒
carbon.Parse("2020-08-05 13:14:15").SetNanosecond(100000000).Nanosecond() // 100000000
carbon.Parse("2020-08-05 13:14:15").SetNanosecond(999999999).Nanosecond() // 999999999
|
时间获取
一句话:直接调用你想获取的时间或日期,只要你想到的都能获取,如获取本年总天数DaysInYear
、获取本月总天数DaysInMonth
、获取本年第几天、 获取本周第几天:DayOfXxx
、获取具体日期或时间DateTime
、获取当前世纪Century
、获取当前年代Decade十年未一个年代、年月日时分秒毫米微秒纳秒、时间戳就不说了。获取时区Timezone
、获取位置Location
、获取距离UTC时区的偏移量,单位秒Offset
、获取当前区域Locale
、 获取当前星座Constellation
、获取当前季节Season
获取年龄Age
。(你就说强不强大~)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| // 获取年龄
carbon.Parse("2002-01-01 13:14:15").Age() // 17
// 获取当前星座
carbon.Now().SetLocale("en").Constellation() // Leo
carbon.Now().SetLocale("zh-CN").Constellation() // 狮子座
// 获取时区
carbon.SetTimezone(carbon.PRC).Timezone() // CST
carbon.SetTimezone(carbon.Tokyo).Timezone() // JST
// 获取位置
carbon.SetTimezone(carbon.PRC).Location() // PRC
carbon.SetTimezone(carbon.Tokyo).Location() // Asia/Tokyo
// 获取距离UTC时区的偏移量,单位秒
carbon.SetTimezone(carbon.PRC).Offset() // 28800
carbon.SetTimezone(carbon.Tokyo).Offset() // 32400
// 获取当前区域
carbon.Now().Locale() // en
carbon.Now().SetLocale("zh-CN").Locale() // zh-CN
// 获取本月第几天
carbon.Parse("2020-08-05 13:14:15").DayOfMonth() // 5
// 获取本月第几周
carbon.Parse("2020-08-05 13:14:15").WeekOfMonth() // 1
|
更多示例参考
时间输出
时间输出是ToXxxString
方法。(你能想到的格式都能输出😂)
注意:增强版有一个坑:当我们直接输出Carbon
对象时,会自动调用String
方法,这个String
方法会将时区改成本地。若不希望修改时区,请不要调用String
方法,用别的转字符串的方法,如ToDateTimeString
。
ToString
方法为输出time包的默认格式。
输出指定布局的字符串Layout
输出指定格式的字符串(如果使用的字母与格式化字符冲突时,请使用\符号转义该字符Format
示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| // 输出简写日期字符串
carbon.Parse("2020-08-05 13:14:15.999999999").ToShortDateString() // 20200805
// 输出简写时间字符串
carbon.Parse("2020-08-05 13:14:15.999999999").ToShortTimeString() // 131415
// 输出简写时间字符串,包含毫秒
carbon.Parse("2020-08-05 13:14:15.999999999").ToShortTimeMilliString() // 131415.999
// 输出简写时间字符串,包含微秒
carbon.Parse("2020-08-05 13:14:15.999999999").ToShortTimeMicroString() // 131415.999999
// 输出简写时间字符串,包含纳秒
carbon.Parse("2020-08-05 13:14:15.999999999").ToShortTimeNanoString() // 131415.999999999
// 输出 UnixDate 格式字符串
carbon.Parse("2020-08-05 13:14:15").ToUnixDateString() // Wed Aug 5 13:14:15 CST 2020
// 输出 RFC3339 格式字符串
carbon.Parse("2020-08-05T13:14:15.999999999+08:00").ToRfc3339String() // 2020-08-05T13:14:15+08:00
// 输出"2006-01-02 15:04:05.999999999 -0700 MST"格式字符串
carbon.Parse("2020-08-05 13:14:15").ToString() // 2020-08-05 13:14:15.999999 +0800 CST
// 输出 "Jan 2, 2006" 格式字符串
carbon.Parse("2020-08-05 13:14:15").ToFormattedDateString() // Aug 5, 2020
// 输出 "Mon, Jan 2, 2006" 格式字符串
carbon.Parse("2020-08-05 13:14:15").ToFormattedDayDateString() // Wed, Aug 5, 2020
// 输出指定布局的字符串
carbon.Parse("2020-08-05 13:14:15").Layout(carbon.ISO8601Layout) // 2020-08-05T13:14:15+08:00
carbon.Parse("2020-08-05 13:14:15").Layout("20060102150405") // 20200805131415
carbon.Parse("2020-08-05 13:14:15").Layout("2006年01月02日 15时04分05秒") // 2020年08月05日 13时14分15秒
carbon.Parse("2020-08-05 13:14:15").Layout("It is 2006-01-02 15:04:05") // It is 2020-08-05 13:14:15
// 输出指定格式的字符串(如果使用的字母与格式化字符冲突时,请使用\符号转义该字符)
carbon.Parse("2020-08-05 13:14:15").Format("YmdHis") // 20200805131415
carbon.Parse("2020-08-05 13:14:15").Format("Y年m月d日 H时i分s秒") // 2020年08月05日 13时14分15秒
carbon.Parse("2020-08-05 13:14:15").Format("l jS \\o\\f F Y h:i:s A") // Wednesday 5th of August 2020 01:14:15 PM
carbon.Parse("2020-08-05 13:14:15").Format("\\I\\t \\i\\s Y-m-d H:i:s") // It is 2020-08-05 13:14:15
|
更多示例参考
更多格式化输出符号请查看附录 格式化符号表
输出结构体
时间输出不仅能够输出指定字符串ToXxxString
,还能输出到指定的结构体类型ToXxxStruct
,用与序列化与反序列化指定日期时间格式。只不过输出的结构体类型只有Date和Time组合的。
示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| package main
import (
"encoding/json"
"fmt"
"log"
"github.com/golang-module/carbon/v2"
)
type Student struct {
Birthday1 carbon.DateTime `json:"birthday1"`
Birthday2 carbon.Date `json:"birthday2"`
}
func main() {
s := Student{
Birthday1: carbon.Now().SubYears(5).ToDateTimeStruct(),
Birthday2: carbon.Now().SubYears(10).ToDateStruct(),
}
marshal, err := json.Marshal(s)
if err != nil {
log.Fatal(err)
}
println(string(marshal)) // {"birthday1":"2019-05-15 14:57:07","birthday2":"2014-05-15"}
s2 := new(Student)
err = json.Unmarshal(marshal, s2)
if err != nil {
log.Fatal(err)
}
fmt.Println(s2.Birthday1) // 2019-05-15 15:00:27
fmt.Println(s2.Birthday2) // 2014-05-15
}
|
总结
carbon
提供了很多的实用方法,另外time
的方法它也能使用,使得它的功能非常强大。时间其实是一个非常复杂的问题,考虑到时区、闰秒、各地的夏令时等,自己处理起来简直是火葬场。幸好有这些库(┬_┬)
参考
- carbon GitHub 仓库: https://github.com/uniplaces/carbon
- 增强版carbon GitHub 仓库: https://github.com/golang-module/carbon
- Go 每日一库之 carbon