如何在围棋中使用日期和时间

作者选择了 多样性在技术基金作为 写给捐款计划的一部分接受捐款。

介绍

该软件旨在使工作更容易完成,对于许多人来说,这包括与日期和时间进行交互。日期和时间值在现代软件中显示到处。例如,跟踪汽车需要服务时,让车主知道,跟踪数据库中的变化,创建审计日志,或者只是将时间与时间进行比较,以确定过程需要多长时间。

在本教程中,您将创建一个Go程序来获取计算机的当前本地时间,然后在人们更容易阅读的格式上打印到屏幕上。接下来,您将解释一个字符串来提取日期和时间信息。

前提条件

要遵循本教程,您将需要:

  • Go 版本 1.16 或更高版本已安装. 若要设置此功能,请遵循 How To Install Go 教程为您的操作系统。

获取当前时间

在本节中,您将使用Go的时间包获取当前时间。Go的标准库中的时间包提供了各种与日期和时间相关的函数,并且可以用time.Time类型来表示特定时间点。

要开始创建一个程序来探索时间包,你需要为文件创建一个目录. 这个目录可以创建在您的计算机上任何地方,但许多开发者倾向于为他们的项目有一个目录. 在本教程中,你将使用名为项目的目录。

创建项目目录并导航到它:

1mkdir projects
2cd projects

项目目录中运行mkdir来创建一个日期目录,然后使用cd导航:

1mkdir datetime
2cd datetime

一旦您创建了项目目录,请使用nano或您喜爱的编辑器打开main.go文件:

1nano main.go

main.go文件中,添加一个main函数,以获取当前时间并打印它:

 1[label projects/datetime/main.go]
 2package main
 3
 4import (
 5    "fmt"
 6    "time"
 7)
 8
 9func main() {
10    currentTime := time.Now()
11    fmt.Println("The time is", currentTime)
12}

在此程序中,从time包中使用的time.Now函数将当前的本地时间作为time.Time值,然后将其存储在currentTime变量中。

使用go runmain.go文件运行程序:

1go run main.go

显示当前日期和时间的输出将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 14:30:45.0000001 -0500 CDT m=+0.000066626

此外,您看到的时区(-0500 CDT 在此输出中)可能会有所不同,因为 time.Now() 返回本地时区中的时间。

您也可以在输出中注意到一个 m= 值. 这个值是 monotonic clock,并且在测量时间差异时被 Go 内部使用。 单调的时钟旨在弥补计算机系统时钟的日期和时间的任何潜在变化,而程序正在运行。 使用单调的时钟,与 time.Now’ 值相比的 time.Now` 值五分钟后仍然会得到正确的结果(五分钟的间隔),即使计算机的系统时钟在五分钟的间隔内改变一个小时前进或后退。 您不需要仔细了解本教程中的代码或示例,但如果您想了解更多关于单调的时钟和 Go 如何使用它们,则《Monotonic Clocks(LINK0)》

现在,虽然显示了当前时间,但对用户来说可能并不有用,它可能不是您正在寻找的格式,或者它可能包含比您想要显示的日期或时间的更多部分。

幸运的是,‘time.Time’类型包括各种方法来获取您想要的日期或时间的特定部分,例如,如果您只想知道‘currentTime’变量的年份,您可以使用‘Year’方法,或者使用‘Hour’方法获取当前时间。

再次打开你的main.go文件,并将一些time.Time方法添加到输出中,以查看它们产生的结果:

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    currentTime := time.Now()
 6    fmt.Println("The time is", currentTime)
 7    
 8    fmt.Println("The year is", currentTime.Year())
 9    fmt.Println("The month is", currentTime.Month())
10    fmt.Println("The day is", currentTime.Day())
11    fmt.Println("The hour is", currentTime.Hour())
12    fmt.Println("The minute is", currentTime.Hour())
13    fmt.Println("The second is", currentTime.Second())
14}

接下来,使用go run再次运行您的程序:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 14:30:45.0000001 -0500 CDT m=+0.000066626
3The year is 2021
4The month is August
5The day is 15
6The hour is 14
7The minute is 14
8The second is 45

与之前的输出一样,当前的日期和时间将与示例不同,但格式应该相似。这次在输出中,你会看到完整的日期和时间印刷,就像以前一样,但你还有一份年份、月日、月日、小时、分钟和秒的列表。 注意,而不是按月印刷为数字(就像全日期一样),它将显示为英语字符串8月

现在,在你的程序中重新更新main.go文件,并用单个函数调用fmt.Printf来替换各种函数输出,这样你就可以以更接近你可能想要向用户显示的格式打印当前的日期和时间:

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    currentTime := time.Now()
 6    fmt.Println("The time is", currentTime)
 7    
 8    fmt.Printf("%d-%d-%d %d:%d:%d\n",
 9    	currentTime.Year(),
10    	currentTime.Month(),
11    	currentTime.Day(),
12    	currentTime.Hour(),
13    	currentTime.Hour(),
14    	currentTime.Second())
15}

一旦您将更新保存到main.go文件中,请使用go run命令运行它,就像以前一样:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 14:30:45.0000001 -0500 CDT m=+0.000066626
32021-8-15 14:14:45

这个时候你的输出可能更接近你想要的,但仍然有一些东西可以调整的输出. 这个月现在再次出现在数字格式中,因为fmt.Printf格式使用%d来告诉time.Month类型,它应该使用一个数字而不是一个字符串,但它只出现在单个数字中。 如果你想显示两个数字,你可以更改fmt.Printf格式来说,但如果你也想显示一个12小时的时间而不是一个24小时的时间,如上面的输出所示? 使用fmt.Printf方法,你需要做自己的数学来计算它。 使用fmt.Printf的日期和时间是可能的,但正如你所看到的,它最终可以变成子。 这样做,你可以

在本节中,您创建了一个新的程序,以使用time.Now来获取当前时间。一旦您有当前时间,您然后使用各种函数,如YearHourtime.Time类型上,以打印有关当前时间的信息。它确实开始变得很多工作,以显示它在自定义格式,然而. 为了使这种类型的常见工作更容易,许多编程语言,包括Go,提供一个特殊的方式来格式化日期和时间,类似于如何使用fmt.Printf来格式化字符串。

打印和格式化特定的日期

除了,小时和其他数据相关的方法,时间类型提供,它还提供一种称为格式的方法。格式方法允许您提供一个布局字符串,类似于您如何提供fmt.Printffmt.Sprintf一个格式,这将告诉格式方法您想要的日期和时间如何打印。

然而,在您使用格式方法之前,您将更容易地看到格式如何影响日期和时间的输出,如果它不每次运行程序时发生变化,直到现在,您使用time.Now来获取当前时间,所以每次运行时会出现不同的数字。

要开始在你的程序中使用time.Date而不是time.Now,请重新打开main.go文件,并更新它以代替time.Nowtime.Date:

1[label projects/datetime/main.go]
2...
3
4func main() {
5    theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
6    fmt.Println("The time is", theTime)
7}

参数的 time.Date 函数包括年份,月,月日,小时,分钟,第二日期和时间,你想要一个 time.Time 为. 最后两个参数的第一个计算纳米秒,最后一个参数是时间区创建的时间区。

保存更新后,使用go run来运行您的程序:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 14:30:45.0000001 -0500 CDT

您看到的输出现在应该更接近上面的输出,因为您在运行程序时使用特定的本地日期和时间,而不是当前的日期和时间(取决于您的计算机设置的时区,时区可能会有所不同)。

使用格式方法定制日期字符串

许多其他编程语言都包含类似的方式来格式化显示的日期和时间,但Go构建这些格式的布局方式可能略有不同于你在其他语言中使用它们的情况。在其他语言中,日期格式使用类似的方式来格式化 Go 中的Printf工作,一个%字符随后是代表日期或时间的一部分的字母。例如,4位数的年份可能代表%Y年份。在 Go 中,这些日期或时间的部分由代表特定日期的字符表示。要在 Go 日期格式中包含4位数的年份,你实际上会在字符串中包含2006字符。此布局类型的好处是,你在代码中看到的内容实际上代表了你在输出中看到的内容。当你能够看到

Go 在字符串格式中使用的日期和时间布局的具体日期是 01/02 03:04:05PM '06 -0700`. 如果你查看日期和时间的每个组件,你会看到它们在每个组件中增加一个。 月亮首先是 01 次,然后是月亮的日子是 02 次,然后是 03 次,分钟是 04 次,第二个是 05 次,年份是 06 次(或 2006 次),最后是 07 次的时区。 记住这个顺序将使未来更容易创建日期和时间格式。

现在,使用这个新的格式方法来复制和清理您在上一节打印的日期格式,需要多个行和函数调用来显示,并且使用格式方法应该使复制变得更容易和更干净。

打开main.go文件,添加一个新的fmt.Println呼叫,并通过使用格式方法格式化的日期传递给TheTime:

1[label projects/datetime/main.go]
2...
3
4func main() {
5    theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
6    fmt.Println("The time is", theTime)
7
8    fmt.Println(theTime.Format("2006-1-2 15:4:5"))
9}

如果你看看格式使用的布局,你会看到它使用上面的同一时间来指定日期和时间应该如何格式化(2006年1月2日)。

若要查看此新格式的输出,请保存您的程序并使用go run运行它:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 14:30:45.0000001 -0500 CDT
32021-8-15 14:30:45

您现在看到的输出将类似于上一节的末尾输出,但它更容易完成. 您所需要的只是一个单行代码和一个布局字符串。

根据您显示的日期或时间,使用变量长度格式,如您在直接打印数字时使用的格式,可能很难为您自己,您的用户或其他代码读取该值。使用1为月份格式,将导致3月显示为3,而10月将使用两个字符并显示为10

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
 6    fmt.Println("The time is", theTime)
 7
 8    fmt.Println(theTime.Format("2006-1-2 15:4:5"))
 9    fmt.Println(theTime.Format("2006-01-02 03:04:05 pm"))
10}

保存代码后,使用go run再次运行该程序:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 14:30:45.0000001 -0500 CDT
32021-8-15 14:30:45
42021-08-15 02:30:45 pm

你会看到,通过在布局字符串中添加一个0前缀,新输出中的月份的8变成08,以匹配布局。现在在12小时格式中的时钟也有自己的0前缀。

很多时候,格式化日期是用来被其他程序解释的,每次想要使用这些格式时重新创建这些格式都可能成为一个负担。

使用预定义格式

有许多常用的日期格式,例如日志消息的时刻印,每次您想要使用它们时重新创建这些格式可能会导致麻烦,在某些情况下,时间包包括您可以使用的预定义格式。

一个可用的和经常使用的格式是RFC 3339(LINK0)中定义的格式之一。一个 _RFC_是用来定义互联网上的标准是如何工作的文件,然后其他RFC可以相互依赖。有一个RFC定义HTTP的工作方式(RFC 2616),例如,还有其他人建立在上面,以进一步定义HTTP。

时间包中的每一个预定义时间格式都以它们所代表的格式命名为const string。RFC 3339格式有两种可用格式,一种称为time.RFC3339,另一种称为time.RFC3339Nano

现在,重新打开您的 main.go 文件,并更新您的程序以使用 time.RFC3339Nano 格式为其输出:

1[label projects/datetime/main.go]
2...
3
4func main() {
5    theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
6    fmt.Println("The time is", theTime)
7    
8    fmt.Println(theTime.Format(time.RFC3339Nano))
9}

由于预定义的格式是具有所需格式的字符串值,您只需要将您通常使用的格式替换为其中一个。

要查看输出,请重新运行您的程序,然后使用Go Run:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 14:30:45.0000001 -0500 CDT
32021-08-15T14:30:45.0000001-05:00

RFC 3339格式是很好的,如果您需要在某个地方保存一个时间值作为一个字符串,它可以被许多其他编程语言和应用程序读取,并且几乎和日期和时间在灵活的字符串格式一样紧凑。

在本节中,您更新了您的程序以使用格式方法来打印日期和时间。使用这种灵活的布局还允许您的代码看起来与最终输出相似。最后,您使用了预定义的布局字符串之一来打印日期和时间,使用受支持的格式。

在字符串中解析日期和时间

开发应用程序时,通常会遇到以字符串表示的日期值,你需要以某种方式解释它们。有时,你需要知道值的日期部分,有时你可能需要知道时间部分,但其他时候你可能需要整个值。除了使用格式方法来从时间值中创建字符串值,Go时间包还提供一个time.Parse函数来将一个字符串转换为时间值。

现在,在您的程序中打开main.go文件,并更新它以使用time.Parse函数将timeString解析为time.Time变量:

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    timeString := "2021-08-15 02:30:45"
 6    theTime, err := time.Parse("2006-01-02 03:04:05", timeString)
 7    if err != nil {
 8    	fmt.Println("Could not parse time:", err)
 9    }
10    fmt.Println("The time is", theTime)
11    
12    fmt.Println(theTime.Format(time.RFC3339Nano))
13}

格式方法不同,time.Parse方法还会返回一个潜在的错误值,如果传输的字符串值不匹配作为第一个参数提供的布局。

保存更新后,您可以使用去运行来运行更新的程序:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 02:30:45 +0000 UTC
32021-08-15T02:30:45Z

有一点要注意在这个输出中。 一点是,从timeString进行解析的时区正在使用默认时区,这是一个+0偏差,被称为协调通用时间(https://en.wikipedia.org/wiki/Coordinated_Universal_Time)(UTC)。既然时间值和布局都没有包含时区,所以time.Parse函数不知道该关联的时区。如果你在某个时候需要它,但time包装确实包含一个time.ParseInLocation(https://pkg.go.dev/time#ParseInLocation)函数,所以你可以提供使用的位置。另一个要注意的部分是在RFC 3339输出中。 输出使用time.RFC3339Nano布局,但输出不包括任何纳米秒。 这是因为time.Parse函数不包含任何纳米秒,所以设置的值

time.Parse 方法还可以使用任何在 time 包中提供的预定义时间布局来解析一个 string 值. 要在实践中看到这一点,请打开你的 main.go 文件并更新 timeString 值以匹配以前的 time.RFC3339Nano 的输出,并更新 time.Parse 参数以匹配:

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    timeString := "2021-08-15T14:30:45.0000001-05:00"
 6    theTime, err := time.Parse(time.RFC3339Nano, timeString)
 7    if err != nil {
 8    	fmt.Println("Could not parse time:", err)
 9    }
10    fmt.Println("The time is", theTime)
11    
12    fmt.Println(theTime.Format(time.RFC3339Nano))
13}

一旦你更新了代码,你可以保存你的程序,并使用去运行重新运行它:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 14:30:45.0000001 -0500 CDT
32021-08-15T14:30:45.0000001-05:00

这一次,从格式方法的输出显示,time.Parse能够从timeString解析时区和纳米秒。

在本节中,您使用了time.Parse函数来分析任意格式化的日期和时间字符串值以及预定义的布局. 到目前为止,您尚未与您所看到的各种时区进行交互。

与时区合作

在与世界各地的用户一起开发应用程序时,甚至仅跨几个时区,常见的做法是使用 Coordinated Universal Time (UTC) (UTC) 存储日期和时间,然后在需要时转换为用户的本地时间。

在本教程的早期部分中,您创建了一个程序,该程序主要基于您自己的本地时区的时间。 要将您的 time.Time 值保存为 UTC,您首先需要将其转换为 UTC。

<$>[注] **注:**本节将计算机的本地时区和UTC之间的时间转换。

现在,打开你的main.go文件来更新你的程序,使用UTC方法在TheTime返回时间的UTC版本:

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
 6    fmt.Println("The time is", theTime)
 7    fmt.Println(theTime.Format(time.RFC3339Nano))
 8    
 9    utcTime := theTime.UTC()
10    fmt.Println("The UTC time is", utcTime)
11    fmt.Println(utcTime.Format(time.RFC3339Nano))
12}

此时,您的程序在本地时区中创建theTime作为time.Time值,以两个不同的格式打印,然后使用UTC方法将该时间从本地时间转换为UTC时间。

要查看该程序的输出,您可以使用去运行来运行它:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 14:30:45.0000001 -0500 CDT
32021-08-15T14:30:45.0000001-05:00
4The UTC time is 2021-08-15 19:30:45.0000001 +0000 UTC
52021-08-15T19:30:45.0000001Z

您的输出将取决于您的本地时区,但在上面的输出中,您将看到第一个打印时间是CDT(北美中央日光时间),这是5小时从UTC。

也可以以同樣的方式將 UTC 時間轉換為當地時間,使用「Time.Time」上的「Local」方法。 再次開啟「main.go」檔案,並更新它以在「utcTime」上添加「Local」方法的呼叫,將其轉換回您的當地時區:

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.Local)
 6    fmt.Println("The time is", theTime)
 7    fmt.Println(theTime.Format(time.RFC3339Nano))
 8    
 9    utcTime := theTime.UTC()
10    fmt.Println("The UTC time is", utcTime)
11    fmt.Println(utcTime.Format(time.RFC3339Nano))
12
13    localTime := utcTime.Local()
14    fmt.Println("The Local time is", localTime)
15    fmt.Println(localTime.Format(time.RFC3339Nano))
16}

一旦你的文件被保存,运行你的程序使用去运行:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 14:30:45.0000001 -0500 CDT
32021-08-15T14:30:45.0000001-05:00
4The UTC time is 2021-08-15 19:30:45.0000001 +0000 UTC
52021-08-15T19:30:45.0000001Z
6The Local time is 2021-08-15 14:30:45.0000001 -0500 CDT
72021-08-15T14:30:45.0000001-05:00

在上面的输出中,UTC转换回CDT意味着从UTC中扣除了五个小时,将时间从19更改为14

在本节中,您更新了程序以使用UTC方法将本地时间区和标准UTC时间区之间的日期和时间转换,然后再使用本地方法返回。

一旦你有你的日期和时间值可用,Go时间包提供了一些额外的功能,可以在你的应用程序中有用。

两次比较

比较两个日期可能有时是错误的困难,因为所有变量需要考虑在比较它们时,例如,需要考虑时区,或事实上,月份有不同的天数。

时间包提供两种方法来简化这些比较:在time.Time类型上可用的之前之后方法,这些方法都接受单一的时间值,并返回真实错误,取决于他们被调用的时间是否在提供的时间之前或之后。

若要查看这些函数的示例,请打开main.go文件并将其更新为包含两个不同的日期,然后使用来比较这些日期以查看输出:

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    firstTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
 6    fmt.Println("The first time is", firstTime)
 7
 8    secondTime := time.Date(2021, 12, 25, 16, 40, 55, 200, time.UTC)
 9    fmt.Println("The second time is", secondTime)
10
11    fmt.Println("First time before second?", firstTime.Before(secondTime))
12    fmt.Println("First time after second?", firstTime.After(secondTime))
13
14    fmt.Println("Second time before first?", secondTime.Before(firstTime))
15    fmt.Println("Second time after first?", secondTime.After(firstTime))
16}

一旦你更新了你的文件,保存它,并使用去运行运行它:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The first time is 2021-08-15 14:30:45.0000001 +0000 UTC
3The second time is 2021-12-25 16:40:55.0000002 +0000 UTC
4First time before second? true
5First time after second? false
6Second time before first? false
7Second time after first? true

由于代码使用的是 UTC 时区中的明确日期,所以您的输出应与上面的输出匹配。 您会看到,当您在 firstTime 上使用Before 方法并提供secondTime 来比较时,它表示2021-08-152021-12-25之前是真的。 当您使用After 方法的firstTime并提供secondTime时,它表示2021-08-152021-12-25之后是

另一种方法是将两个日期和时间与时间包进行比较,是Sub方法。Sub方法会从另一个日期中抽取一个日期,并使用新类型time.Duration返回一个值。与time.Duration值不同,该值代表时间的绝对点,而time.Duration值代表时间的差异。例如,在一个小时内将是一个持续时间,因为它意味着基于当天时间的不同,但在中午代表一个特定的绝对时间。

现在,更新您的main.go文件以在firstTimesecondTime值上使用Sub方法,并打印结果:

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    firstTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
 6    fmt.Println("The first time is", firstTime)
 7
 8    secondTime := time.Date(2021, 12, 25, 16, 40, 55, 200, time.UTC)
 9    fmt.Println("The second time is", secondTime)
10
11    fmt.Println("Duration between first and second time is", firstTime.Sub(secondTime))
12    fmt.Println("Duration between second and first time is", secondTime.Sub(firstTime))

保存你的文件,然后使用go run运行它:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The first time is 2021-08-15 14:30:45.0000001 +0000 UTC
3The second time is 2021-12-25 16:40:55.0000002 +0000 UTC
4Duration between first and second time is -3170h10m10.0000001s
5Duration between second and first time is 3170h10m10.0000001s

上面的输出表示,两个日期之间有3170小时,10分钟,10秒,100纳秒,并且有几点要注意的输出。第一个是,第一次和第二次之间的持续时间是一个负值。这意味着第二次是在第一次之后,并且类似于如果你从0中扣除5并获得5。第二件事要注意的是,一个持续时间的最大测量单位是一个小时,所以它不会把它分解成几天或几个月。由于一个月的天数不一致,而一天在更换日光节省时间时可能会有不同的含义,一个小时是最准确的测量,肯定不会波动。

在本节中,您更新了您的程序以使用三种不同的方法进行两次比较。首先,您使用了方法来确定一个时间是否在另一个时间之前或之后,然后您使用了Sub来查看两次之间的时间。

添加或扣除时间

在撰写应用程序时,使用日期和时间的一个常见操作是根据另一个时间确定过去或未来的时间。 它可以用于功能,例如确定订阅何时会下次更新,或者如果某些值被检查后已经过了一段时间。

创建一个time.Duration值类似于在纸上写一个持续时间,只需以时间单位的倍数。例如,要创建一个time.Duration来表示一个小时,你会使用time.Hour值来定义它,以你想要的time.Duration来表示的小时数倍:

1oneHour := 1 * time.Hour
2twoHours := 2 * time.Hour
3tenHours := 10 * time.Hour

声明较小的时间单位以类似的方式处理,但使用time.Minute,time.Second,等等:

1tenMinutes := 10 * time.Minute
2fiveSeconds := 5 * time.Second

一个持续时间也可以添加到另一个持续时间来获取持续时间的总和. 若要在动作中看到这一点,请打开你的 main.go 文件并更新它以声明一个 toAdd 持续时间变量并添加不同的持续时间:

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    toAdd := 1 * time.Hour
 6    fmt.Println("1:", toAdd)
 7
 8    toAdd += 1 * time.Minute
 9    fmt.Println("2:", toAdd)
10
11    toAdd += 1 * time.Second
12    fmt.Println("3:", toAdd)
13}

完成更新后,保存文件并使用去运行运行您的程序:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
21: 1h0m0s
32: 1h1m0s
43: 1h1m1s

当你查看输出时,你会看到打印的第一个持续时间为一个小时,对应于你的代码中的1 * time.Hour。接下来,你将1 * time.Minute添加到ToAdd值中,显示为一个小时,一个分钟的值。

还可以将持续时间合并到一个陈述中,或者从另一个陈述中提取一个持续时间:

1oneHourOneMinute := 1 * time.Hour + 1 * time.Minute
2tenMinutes := 1 * time.Hour - 50 * time.Minute

接下来,打开你的main.go文件,并更新你的程序,使用这样的组合,从添加中提取一分钟和一秒:

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    
 6    ...
 7    
 8    toAdd += 1 * time.Second
 9    fmt.Println("3:", toAdd)
10    
11    toAdd -= 1*time.Minute + 1*time.Second
12    fmt.Println("4:", toAdd)
13}

保存代码后,您可以使用go run来运行该程序:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
21: 1h0m0s
32: 1h1m0s
43: 1h1m1s
54: 1h0m0s

新的第四行添加到输出中显示了你包含的新的代码,以减去1 * time.Minute1 * time.Second的总和正确工作,结果是原始的1小时值再次出现。

使用这些持续时间与添加方法相结合的time.Time类型允许你采取你已经拥有的时间值,并确定在该时间之前或之后的任何其他任意时刻的时间。 要看到一个例子,打开你的main.go文件,并更新它以将添加值设置为24小时,或24 * time.Hour

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
 6    fmt.Println("The time is", theTime)
 7
 8    toAdd := 24 * time.Hour
 9    fmt.Println("Adding", toAdd)
10
11    newTime := theTime.Add(toAdd)
12    fmt.Println("The new time is", newTime)
13}

保存檔案後,請使用「go run」執行您的程式:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 14:30:45.0000001 +0000 UTC
3Adding 24h0m0s
4The new time is 2021-08-16 14:30:45.0000001 +0000 UTC

看看输出,你会看到,将24小时添加到2021-08-15的结果是2021-08-16的新日期。

若要抽出时间,你还会使用添加方法,这种方法略有反直观性. 由于Sub方法用于获取两个日期之间的时间差异,你可以使用添加以负值从time.Time值中抽出时间。

再次,要在你的程序中看到这个运行,打开你的 main.go 文件,并更新它以将24小时的 toAdd 值更改为负值:

 1[label projects/datetime/main.go]
 2...
 3
 4func main() {
 5    theTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
 6    fmt.Println("The time is", theTime)
 7
 8    toAdd := -24 * time.Hour
 9    fmt.Println("Adding", toAdd)
10
11    newTime := theTime.Add(toAdd)
12    fmt.Println("The new time is", newTime)
13}

保存文件后,再一次使用去运行来运行您的程序:

1go run main.go

结果将看起来像这样:

1[secondary_label Output]
2The time is 2021-08-15 14:30:45.0000001 +0000 UTC
3Adding -24h0m0s
4The new time is 2021-08-14 14:30:45.0000001 +0000 UTC

这次在输出中,你会看到,而不是将24小时添加到原始时间,新的日期比原始时间提前24小时。

在本节中,您使用time.Hour,time.Minutetime.Second来创建不同程度的time.Duration值,您还使用了time.Duration值与添加方法,以获得原始值之前和之后的新time.Minute值。

结论

在本教程中,您使用time.Now来检索计算机上当前本地时间的time.Time值,然后使用Year,Month,Hour和其他方法访问有关该时间的特定信息。然后,您使用Format方法来打印使用自定义格式和预定义格式的时间。接下来,您使用time.Parse函数来解释其中包含的时间的字符串值,并从中提取时间值。一旦您有时间值,您使用UTCLocal方法来翻译时间与本地时间区之间的时间。

使用本教程中描述的各种功能和方法在您的应用程序中将走很长的路,但Go time包还包括一些其他功能,如果您感兴趣。

本教程也是 DigitalOcean How to Code in Go系列的一部分,该系列涵盖了许多 Go 主题,从首次安装 Go 到如何使用语言本身。

Published At
Categories with 技术
Tagged with
comments powered by Disqus