Jinyun's Notes 🚀

没什么天赋,爱好也不多,但愿坚持做些喜欢的事情

0%

Go 日期时间

🕢 Go 中的日期时间使用布局来格式化,通过布局来完成日期时间的格式化和解析。

当前日期时间

标准日期时间格式

布局格式:

LayoutNote
January 2, 2006Date
01/02/06Date
Jan-02-06Date
15:04:05Time
3:04:05 PMTime
Jan _2 15:04:05Timestamp
Jan _2 15:04:05.000000With microseconds
2006-01-02T15:04:05-0700ISO 8601(RFC 3339)
2006-01-02ISO 8601(RFC 3339)
15:04:05ISO 8601(RFC 3339)
02 Jan 06 15:04 MSTRFC 822
02 Jan 06 15:04 -0700With numeric zone
Mon, 02 Jan 2006 15:04:05 MSTRFC 1123
Mon, 02 Jan 2006 15:04:05 -0700With numeric zone

布局选项:

TypeOptions
Year06 2006
Month01 1 Jan January
Day02 2 _2(width two, right justified)
WeekdayMon Monday
Hours03 3 15
Minutes04 4
Seconds05 5
ms us ns.000 .000000 .000000000
ms us ns.999 .999999 .999999999(trailing zeros removed)
am/pmAM am PM pm
TimezoneMST
Offset-0700 -07 -07:00 Z0700 Z07:00

以下是 Go 源码中预定义日期和时间格式常量:

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// These are predefined layouts for use in Time.Format and time.Parse.
// The reference time used in the layouts is the specific time:
// Mon Jan 2 15:04:05 MST 2006
// which is Unix time 1136239445. Since MST is GMT-0700,
// the reference time can be thought of as
// 01/02 03:04:05PM '06 -0700
// To define your own format, write down what the reference time would look
// like formatted your way; see the values of constants like ANSIC,
// StampMicro or Kitchen for examples. The model is to demonstrate what the
// reference time looks like so that the Format and Parse methods can apply
// the same transformation to a general time value.
//
// Some valid layouts are invalid time values for time.Parse, due to formats
// such as _ for space padding and Z for zone information.
//
// Within the format string, an underscore _ represents a space that may be
// replaced by a digit if the following number (a day) has two digits; for
// compatibility with fixed-width Unix time formats.
//
// A decimal point followed by one or more zeros represents a fractional
// second, printed to the given number of decimal places. A decimal point
// followed by one or more nines represents a fractional second, printed to
// the given number of decimal places, with trailing zeros removed.
// When parsing (only), the input may contain a fractional second
// field immediately after the seconds field, even if the layout does not
// signify its presence. In that case a decimal point followed by a maximal
// series of digits is parsed as a fractional second.
//
// Numeric time zone offsets format as follows:
// -0700 ±hhmm
// -07:00 ±hh:mm
// -07 ±hh
// Replacing the sign in the format with a Z triggers
// the ISO 8601 behavior of printing Z instead of an
// offset for the UTC zone. Thus:
// Z0700 Z or ±hhmm
// Z07:00 Z or ±hh:mm
// Z07 Z or ±hh
//
// The recognized day of week formats are "Mon" and "Monday".
// The recognized month formats are "Jan" and "January".
//
// The formats 2, _2, and 02 are unpadded, space-padded, and zero-padded
// day of month. The formats __2 and 002 are space-padded and zero-padded
// three-character day of year; there is no unpadded day of year format.
//
// Text in the format string that is not recognized as part of the reference
// time is echoed verbatim during Format and expected to appear verbatim
// in the input to Parse.
//
// The executable example for Time.Format demonstrates the working
// of the layout string in detail and is a good reference.
//
// Note that the RFC822, RFC850, and RFC1123 formats should be applied
// only to local times. Applying them to UTC times will use "UTC" as the
// time zone abbreviation, while strictly speaking those RFCs require the
// use of "GMT" in that case.
// In general RFC1123Z should be used instead of RFC1123 for servers
// that insist on that format, and RFC3339 should be preferred for new protocols.
// RFC3339, RFC822, RFC822Z, RFC1123, and RFC1123Z are useful for formatting;
// when used with time.Parse they do not accept all the time formats
// permitted by the RFCs and they do accept time formats not formally defined.
// The RFC3339Nano format removes trailing zeros from the seconds field
// and thus may not sort correctly once formatted.
const (
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"
)

获取当前日期时间

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
package main

import (
"fmt"
"time"
)

func main() {
now := time.Now()
fmt.Printf("当前日期时间:%v\n", now)
fmt.Printf("年:%v\n", now.Year())
fmt.Printf("月:%v\n", now.Month())
fmt.Printf("日:%v\n", now.Day())
fmt.Printf("时:%v\n", now.Hour())
fmt.Printf("分:%v\n", now.Minute())
fmt.Printf("秒:%v\n", now.Second())
fmt.Printf("纳秒:%v\n", now.Nanosecond())
fmt.Printf("\n")
}

/*
当前日期时间:2021-07-11 11:12:59.787921 +0800 CST m=+0.000104353
年:2021
月:July
日:11
时:11
分:12
秒:59
纳秒:787921000
/*

获取当前时间戳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import (
"fmt"
"time"
)

func main() {
now := time.Now()
fmt.Printf("当前时间戳(单位为秒):%v\n", now.Unix())
fmt.Printf("当前时间戳(单位为纳秒):%v\n", now.UnixNano())
}

/*
当前时间戳(单位为秒):1625973361
当前时间戳(单位为纳秒):1625973361766745000
*/

获取当前时间的字符串格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import (
"fmt"
"time"
)

func main() {
now := time.Now()
fmt.Printf("当前日期时间:%v\n", now.Format(time.RFC3339))
fmt.Printf("当前日期时间:%v\n", now.Format("2006-01-02 15:04:05"))
}

/*
当前日期时间:2021-07-11T11:42:19+08:00
当前日期时间:2021-07-11 11:42:19
*/

指定时区获取日期时间

使用 FixedZone 指定

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 (
"testing"
"time"
)

const TheCSTLayout = "2006-01-02T15:04:05"

var theCSTZone *time.Location

func init() {
theCSTZone = time.FixedZone("CST", 8*3600)
}

func TestNowDateTime(t *testing.T) {
dateTime := time.Now().In(theCSTZone).Format(TheCSTLayout)
t.Logf("The date time: %v", dateTime)
now, _ := time.ParseInLocation(TheCSTLayout, dateTime, theCSTZone)
t.Logf("Now date time: %v", now)
}

/*
$ go test -v -timeout 30s -run ^TestNowDateTime$ example.org/hello/v2
=== RUN TestNowDateTime
main_test.go:18: The date time: 2021-09-25T09:02:03
main_test.go:20: Now date time: 2021-09-25 09:02:03 +0800 CST
--- PASS: TestNowDateTime (0.00s)
PASS
ok example.org/hello/v2 0.234s
*/

使用 LoadLocation 指定

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 (
"log"
"testing"
"time"
)

const TheCSTLayout = "2006-01-02T15:04:05"

var theCSTLocation *time.Location

func init() {
var err error
theCSTLocation, err = time.LoadLocation("Asia/Shanghai")
if err != nil {
log.Fatalf("Load location failed, %v", err)
}
}

func TestNowDateTime(t *testing.T) {
dateTime := time.Now().In(theCSTLocation).Format(TheCSTLayout)
t.Logf("The date time: %v", dateTime)
now, _ := time.ParseInLocation(TheCSTLayout, dateTime, theCSTLocation)
t.Logf("Now date time: %v", now)
}

/*
$ go test -v -timeout 30s -run ^TestNowDateTime$ example.org/hello/v2
=== RUN TestNowDateTime
main_test.go:23: The date time: 2021-09-25T09:39:02
main_test.go:25: Now date time: 2021-09-25 09:39:02 +0800 CST
--- PASS: TestNowDateTime (0.00s)
PASS
ok example.org/hello/v2 1.777s
*/

常用日期时间转换

时间戳转日期时间字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import (
"fmt"
"strconv"
"time"
)

func main() {
layout := "2006-01-02 15:04:05"
now := time.Now().Unix()
fmt.Printf("转换后的日期时间:%v\n", time.Unix(now, 0).Format(layout))

a, b := 1626005415, "1626005415"
c, _ := strconv.ParseInt(b, 10, 64)
fmt.Printf("转换后的日期时间:%v\n", time.Unix(int64(a), 0).Format(layout))
fmt.Printf("转换后的日期时间:%v\n", time.Unix(c, 0).Format(layout))
}

/*
转换后的日期时间:2021-07-11 20:35:31
转换后的日期时间:2021-07-11 20:10:15
转换后的日期时间:2021-07-11 20:10:15
*/

日期时间字符串转时间戳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
"fmt"
"time"
)

const (
ChinaFormat = "2006-01-02 15:04:05"
)

func main() {
a, b := "2021-07-11 20:27:33", "Sun, 11 Jul 2021 15:04:05 UTC"
at1, _ := time.Parse(ChinaFormat, a)
at2, _ := time.Parse(time.RFC1123, b)
fmt.Printf("转换后的时间戳:%v\n", at1.Unix())
fmt.Printf("转换后的时间戳:%v\n", at2.Unix())
}

/*
转换后的时间戳:1626035253
转换后的时间戳:1626015845
*/

日期时间字符串转时间对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"fmt"
"time"
)

func main() {
str := "2008-08-08 08:08:08"

// Parse the date string into Go's time object
at, _ := time.Parse("2006-01-02 15:04:05", str)
fmt.Printf("转换后的日期时间:%v\n", at)
fmt.Println(at.Date())
}

/*
转换后的日期时间:2008-08-08 08:08:08 +0000 UTC
2008 August 8
*/

常用日期时间计算

计算两个给定日期之前相差的天数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"fmt"
"time"
)

func main() {
t1, t2 := Date(2020, 1, 1), Date(2021, 1, 1)
days := t2.Sub(t1).Hours() / 24
fmt.Printf("两个给定日期之前相差的天数为:%v\n", days)
}

func Date(year, month, day int) time.Time {
return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
}

/*
两个给定日期之前相差的天数为:366
*/

统计代码运行时间

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
package main

import (
"fmt"
"time"
)

func main() {
fn := TimeSpent(execSlowFunc)
fmt.Printf("Exec result: %v\n", fn(9999))
}

func execSlowFunc(x int) int {
time.Sleep(3 * time.Second)
return x + 1
}

func TimeSpent(fn func(x int) int) func(n int) int {
return func(x int) int {
start := time.Now()
ret := fn(x)
fmt.Println("Time spent:", time.Since(start).Seconds())
return ret
}
}

/*
Time spent: 3.004356442
Exec result: 10000
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
"log"
"time"
)

func main() {
defer TimeSpent(execSlowFunc("Hello World!"))
}

func execSlowFunc(s string) (string, time.Time) {
time.Sleep(1 * time.Second)
return s + " 🌏🌈💫🔥🎉🚀🙏", time.Now()
}

func TimeSpent(s string, start time.Time) {
log.Printf("%v: %v\n", s, time.Since(start))
}

/*
2021/07/14 08:22:38 Hello World! 🌏🌈💫🔥🎉🚀🙏: 4.582µs
*/
本笔记是笔者在学习和工作中的一些整理,如对您有用,请鼓励我继续写作