Featured image of post Golang中的日期与时间

Golang中的日期与时间

Golang 的日期及时间

Golang 的日期及时间 Golang提供良好的支持与日期和时间的工作。在 Golang,我们不需要任何第三方软件包来管理时间和日期。Go 标准库的 time 包非常容易理解和实现。

Golang 默认的 time.time 时间类型表示具有纳秒精度的时间瞬间。它是一个没有导出字段的结构,这意味着您永远不需要使用点运算符来访问不同的字段。相反,可以使用各种方法来获得所需的数据。

如何得到当前的系统时间?

这是最常出现的问题之一。作为开发人员,我们遇到了许多这样的情况,需要获得系统的当前时间。观察下面的代码,了解如何得到当前的系统时间。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()
    fmt.Println("Current time is:", now)
}
1
2
$ go run current_time.go 
Current time is: 2021-11-03 20:57:06.294753357 +0530 IST m=+0.000030078

正如我们所知,UTC (Universal Coordinated time)被选为主要的时间标准,它避免了时区、夏时制等的混淆。在 Golang中,我们也可以得到当前系统时间(UTC)。让我们通过示例来了解如何以 UTC 表示当前系统时间。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now().UTC()
    fmt.Println("Current time is:", now)
}
1
2
$ go run current_time.go
Current time is: 2021-11-03 15:32:48.441669614 +0000 UTC

日期和时间

我们还可以在 Golang 的 datetime 中访问不同的组件。为了访问年、月、日、小时、分钟和秒,我们可以对时间对象调用不同的函数。让我们通过下面的一个例子来理解。

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

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()

    fmt.Println("Year:", now.Year())
    fmt.Println("Month:", now.Month())
    fmt.Println("Day:", now.Day())
    fmt.Println("Hour:", now.Hour())
    fmt.Println("Minute:", now.Minute())
    fmt.Println("Second:", now.Second())
    fmt.Println("Nanosecond:", now.Nanosecond())
}
1
2
3
4
5
6
7
8
$ go run datetime.go
Year: 2021
Month: November
Day: 3
Hour: 21
Minute: 21
Second: 23
Nanosecond: 806031374

Golang 的日期函数

我们可以为特定的日期创建一个时间对象。我们可以将年、月、日、小时、分钟、秒、纳秒和位置参数传递给 time.Date 函数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main

import (
     "fmt"
     "time"
)

func main() {
     t := time.Date(2020, time.November, 10, 23, 0, 0, 0, time.UTC)
     fmt.Printf("Date-time is set to : %s\n", t.Local())
}
1
2
$ go run date_func.go 
Date-time is set to : 2020-11-11 04:30:00 +0530 IST

使用 Golang 解析和格式化日期时间

日期和时间都可以有多种表示形式,Golang 提供了 parse () 函数来对其进行解析。Go 语言中的 Parse() 函数用于解析格式化的字符串,然后查找它形成的时间值。让我们观察下面的代码示例。在本例中,我们使用 parse() 函数使用布局来解析日期/时间。这个例子取自 Golang 的官方文件。time.Parse() 函数接受一个时间字符串和一个布局作为输入,并尝试创建一个新的 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
package main

import (
	"fmt"
	"time"
)

func main() {
	// Define the layout as constant
	// Golang parse function will parse the given string in 
	// same format as provided in layout.
	const longForm = "Jan 2, 2006 at 3:04pm (MST)"
	t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
	fmt.Println(t)

	const shortForm = "2006-Jan-02"
	t, _ = time.Parse(shortForm, "2013-Feb-03")
	fmt.Println(t)

	// Some valid layouts are invalid time values, due to format specifiers
	// such as _ for space padding and Z for zone information.
	// For example the RFC3339 layout 2006-01-02T15:04:05Z07:00
	// contains both Z and a time zone offset in order to handle both valid options:
	// 2006-01-02T15:04:05Z
	// 2006-01-02T15:04:05+07:00
	t, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
	fmt.Println(t)
	t, _ = time.Parse(time.RFC3339, "2006-01-02T15:04:05+07:00")
	fmt.Println(t)
	_, err := time.Parse(time.RFC3339, time.RFC3339)
	fmt.Println("error", err) // Returns an error as the layout is not a valid time value

}
1
2
3
4
5
6
$ go run parse_time.go 
2013-02-03 19:54:00 +0000 PST
2013-02-03 00:00:00 +0000 UTC
2006-01-02 15:04:05 +0000 UTC
2006-01-02 15:04:05 +0700 +0700
error parsing time "2006-01-02T15:04:05Z07:00": extra text: "07:00"

Golang 的持续时间

简单地说,持续时间是两个时刻之间经过的时间。技术上,在Golang持续时间表示两个瞬间之间的经过时间,作为一个整数64纳秒计数。这代表将最长的持续时间限制在大约290年。让我们来看一个例子,如何计算方法调用之间的运行时间。观察下面的代码函数 t1.Sub(t0) 是用来计算运行时间的。

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

import (
	"fmt"
	"time"
)

func expensiveCall() {}

func main() {
	t0 := time.Now()
	expensiveCall()
	t1 := time.Now()
	fmt.Printf("The call took %v to run.\n", t1.Sub(t0))
}
1
2
$ go run elapsed.go
The call took 64ns to run.

加减和比较时间

Golang 提供各种功能,可对时间对象执行多种操作。通过这些方法,我们可以添加时间或时间相减,得到两个时间之间的差,并比较两个时间,看看哪个时间在另一个时间之后。让我们通过例子来理解这一点。

在下面的例子中,我们使用了两个函数: time.Add() 加/减去时间 和 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
package main

import (
	"fmt"
	"time"
)

func main() {
	// Adding time

	// Adding 5 minutes 
	currentTime := time.Now().UTC()
	inFiveMinutes := currentTime.Add(time.Minute * 5)
	fmt.Println("Five min in future", inFiveMinutes)

	// 5 minutes ago
	fiveMinutesAgo := currentTime.Add(-time.Minute * 5)
	fmt.Println("Five min in past", fiveMinutesAgo)


	// Adds years, months, and days
	
	// inOneMonth is 1 month in the future
	inOneMonth := currentTime.AddDate(0, 1, 0)	
	fmt.Println("One month in future", inOneMonth)


	oneDayAgo := currentTime.AddDate(0, 0, -1)
	fmt.Println("One day ago ", oneDayAgo)
}
1
2
3
4
Five min in future 2021-11-05 05:18:53.982233815 +0000 UTC
Five min in past 2021-11-05 05:08:53.982233815 +0000 UTC
One month in future 2021-12-05 05:13:53.982233815 +0000 UTC
One day ago  2021-11-04 05:13:53.982233815 +0000 UTC

现在让我们举一个例子,我们需要得到两个时间实例之间的差。 time.Sub() 获取两个时间实例之间的差。

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

import (
	"fmt"
	"time"
)

func main() {
	// Getting difference between time instances
	startTime := time.Date(2019, 1, 1, 3, 0, 0, 0, time.UTC)
	endTime := time.Date(2020, 1, 1, 3, 0, 0, 0, time.UTC)

	difference := endTime.Sub(startTime) 
	fmt.Printf("The time difference is = %v\n", difference)
}
1
2
$ go run time_diff.go 
The time difference is = 8760h0m0s

现在让我们举一个例子,我们需要找出哪个时间先于其他时间出现, 我们会利用 time.After() 函数。这是非常常见的用例,用于需要比较时间的地方。我们还将看看如何检查时间是否相等–就是使用 time.Equal()

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

import (
	"fmt"
	"time"
)

func main() {

	first := time.Date(2022, 2, 1, 3, 0, 0, 0, time.UTC)
	second := time.Date(2021, 2, 1, 12, 0, 0, 0, time.UTC)
	third := time.Date(2021, 2, 1, 12, 0, 0, 0, time.UTC)

	isFirstAfter := first.After(second)
	fmt.Printf("Is first come after %t\n",isFirstAfter)
	isThirdEqualSecond := third.Equal(second)
	fmt.Printf("Is third equal second %t\n",isThirdEqualSecond)

}
1
2
3
$ go run time_check.go 
Is first come after true
Is third equal second true

Sleep & time ticker

在 Golang中,我们可以使用 time.Sleep() 暂停代码的执行 。请记住,这是同步的,它会阻塞当前 Go 线程(routine)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
package main

import (
	"fmt"
	"time"
)

func main() {
	// Sleeping for 5 second
	fmt.Printf("Current Unix Time: %v\n", time.Now().Unix())
	time.Sleep(5 * time.Second)
	fmt.Printf("Current Unix Time: %v\n", time.Now().Unix())
}
1
2
3
$ go run sleep_5second.go
Current Unix Time: 1636090412
Current Unix Time: 1636090417

Golang ticker 是用来在特定的时间间隔执行代码的。如果我们需要在一个固定的时间间隔内做一些事情(比如说每秒或者每分钟) ,我们可以使用 Golang time.Ticker() 函数。举个例子。在下面的代码中,我们每秒钟打印一次语句。

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

import (
	"fmt"
	"time"
)

func printSomethingEverySecond() {
    ticker := time.NewTicker(time.Second)
    for range ticker.C {
	fmt.Printf("Current Unix Time: %v\n", time.Now().Unix())
    }
}
func main() {
	printSomethingEverySecond()
}
1
2
3
4
5
6
7
8
9
$ go run ticker_demo.go 
Current Unix Time: 1636090736
Current Unix Time: 1636090737
Current Unix Time: 1636090738
Current Unix Time: 1636090739
Current Unix Time: 1636090740
Current Unix Time: 1636090741
Current Unix Time: 1636090742
...