package time

import "time"

Package time 提供用于测量和显示时间的功能。

日历计算始终假定使用公历(Gregorian calendar),且不含闰秒。

单调时钟(Monotonic Clocks)

操作系统同时提供“挂钟(wall clock)”和“单调时钟(monotonic clock)”, 前者会因时钟同步而改变,后者则不会。一般规则是:挂钟用于告知时间, 单调时钟用于测量时间。为了不拆分 API,本包中由 time.Now 返回的 Time 同时包含挂钟读数和单调时钟读数;后续的告知时间操作使用挂钟读数,而后续的 测量时间操作,特别是比较和减法,使用单调时钟读数。

例如,下面的代码总是计算出一个约为 20 毫秒的正的已流逝时间, 即使在被计时的操作期间挂钟被修改也是如此:

start := time.Now()
... 一个耗时 20 毫秒的操作 ...
t := time.Now()
elapsed := t.Sub(start)

其他惯用法,例如 time.Since(start)、time.Until(deadline) 以及 time.Now().Before(deadline),同样能够抵御挂钟被重置的影响。

本节其余部分给出操作如何使用单调时钟的精确细节,但理解这些细节 并非使用本包所必需。

time.Now 返回的 Time 包含一个单调时钟读数。 如果 Time t 具有单调时钟读数,t.Add 会将同一时长同时加到挂钟读数和 单调时钟读数上以计算结果。由于 t.AddDate(y, m, d)、t.Round(d) 和 t.Truncate(d) 是挂钟时间运算,它们总是从结果中去除任何单调时钟读数。 由于 t.In、t.Local 和 t.UTC 用于影响挂钟时间的解释方式,它们也会从 结果中去除任何单调时钟读数。去除单调时钟读数的规范做法是使用 t = t.Round(0)。

如果 Time t 和 u 都包含单调时钟读数,那么运算 t.After(u)、t.Before(u)、 t.Equal(u)、t.Compare(u) 和 t.Sub(u) 仅使用单调时钟读数进行,忽略挂钟 读数。如果 t 或 u 中的任一个不含单调时钟读数,这些运算则退回到使用 挂钟读数。

在某些系统上,如果计算机进入睡眠,单调时钟会停止。在此类系统上, t.Sub(u) 可能无法准确反映 t 与 u 之间实际流逝的时间。其他对时间进行 减法的函数和方法同样如此,例如 Since、Until、Time.Before、Time.After、 Time.Add、Time.Equal 和 Time.Compare。在某些情况下,你可能需要去除 单调时钟以获得准确结果。

由于单调时钟读数在当前进程之外没有意义,由 t.GobEncode、 t.MarshalBinary、t.MarshalJSON 和 t.MarshalText 生成的序列化形式会省略 单调时钟读数,而 t.Format 也不为其提供格式。类似地,构造器 time.Date、 time.Parse、time.ParseInLocation 和 time.Unix,以及反序列化方法 t.GobDecode、t.UnmarshalBinary、t.UnmarshalJSON 和 t.UnmarshalText 总是 创建不含单调时钟读数的时间。

单调时钟读数只存在于 Time 值中。它不是 Duration 值的一部分, 也不是 t.Unix 及其相关方法返回的 Unix 时间的一部分。

注意,Go 的 == 运算符不仅比较时间瞬间,还比较 Location 和单调时钟 读数。关于 Time 值相等性测试的讨论,请参阅 Time 类型的文档。

为了调试,如果存在单调时钟读数,t.String 的结果会包含该读数。 如果 t != u 是由于单调时钟读数不同,那么打印 t.String() 和 u.String() 时该差异将可见。

定时器精度(Timer Resolution)

Timer 的精度取决于 Go 运行时、操作系统和底层硬件。 在 Unix 上,精度约为 1 毫秒。 在 Windows 1803 及更高版本上,精度约为 0.5 毫秒。 在较旧的 Windows 版本上,默认精度约为 16 毫秒,但可以使用 golang.org/x/sys/windows.TimeBeginPeriod 请求更高的精度。

Index

Examples

Constants

const (
	Layout      = "01/02 03:04:05PM '06 -0700" // 按数字顺序排列的参考时间。
	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
	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
	RFC3339     = "2006-01-02T15:04:05Z07:00"
	RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
	Kitchen     = "3:04PM"
	// 便捷时间戳。
	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"
)

这些是预定义的布局,供 Time.Format 和 time.Parse 使用。 这些布局中使用的参考时间是如下特定的时间戳:

01/02 03:04:05PM '06 -0700

(2006 年 1 月 2 日 15:04:05,位于 GMT 以西七小时的时区)。 该值记录为下面列出的名为 Layout 的常量。作为 Unix 时间,它是 1136239445。 由于 MST 是 GMT-0700,Unix date 命令打印该参考时间会显示为:

Mon Jan 2 15:04:05 MST 2006

日期采用了将数字月份放在日期之前的美国惯例,这是一个令人遗憾的历史错误。

Time.Format 的示例详细演示了布局字符串的工作方式,是一个很好的参考。

注意 RFC822、RFC850 和 RFC1123 格式只应应用于本地时间。 将它们应用于 UTC 时间会使用 "UTC" 作为时区缩写,而严格来说这些 RFC 要求在这种情况下使用 "GMT"。 在解析时使用 RFC1123 或 RFC1123Z 格式时,请注意这些格式为月中的日期部分 定义了前导零,这并不被 RFC 1123 严格允许。这在解析某个月前 9 天出现的 日期字符串时会导致错误。 通常,对于坚持该格式的服务器,应使用 RFC1123Z 而不是 RFC1123, 而对于新协议应优先使用 RFC3339。 RFC3339、RFC822、RFC822Z、RFC1123 和 RFC1123Z 在格式化时很有用; 当与 time.Parse 一起使用时,它们并不接受 RFC 允许的所有时间格式, 并且会接受未正式定义的时间格式。 RFC3339Nano 格式会从秒字段中移除末尾的零,因此格式化后可能无法正确排序。

大多数程序可以使用已定义的常量之一作为传给 Format 或 Parse 的布局。 除非你要创建自定义布局字符串,否则可以忽略本注释的其余部分。

要定义自己的格式,请写下参考时间按你的方式格式化后看起来是什么样的; 有关示例,请参见 ANSIC、StampMicro 或 Kitchen 等常量的值。 这种模式旨在展示参考时间的样子,以便 Format 和 Parse 方法可以将相同的 变换应用于一般的时间值。

以下是布局字符串各组成部分的摘要。每个元素通过示例展示参考时间某个元素的 格式化方式。只有这些值会被识别。布局字符串中未被识别为参考时间一部分的文本 会在 Format 期间原样输出,并期望在 Parse 的输入中原样出现。

年: "2006" "06"
月: "Jan" "January" "01" "1"
星期: "Mon" "Monday"
月中的日: "2" "_2" "02"
年中的日: "__2" "002"
小时: "15" "3" "03"(下午或上午)
分钟: "4" "04"
秒: "5" "05"
AM/PM 标记: "PM"

数字时区偏移的格式如下:

"-0700"     ±hhmm
"-07:00"    ±hh:mm
"-07"       ±hh
"-070000"   ±hhmmss
"-07:00:00" ±hh:mm:ss

将格式中的符号替换为 Z 会触发 ISO 8601 行为, 即对于 UTC 时区打印 Z 而不是偏移量。因此:

"Z0700"      Z or ±hhmm
"Z07:00"     Z or ±hh:mm
"Z07"        Z or ±hh
"Z070000"    Z or ±hhmmss
"Z07:00:00"  Z or ±hh:mm:ss

在格式字符串中,"_2" 和 "__2" 中的下划线表示空格,如果后面的数字有多个 数字,这些空格可能会被数字替换,以兼容固定宽度的 Unix 时间格式。 前导零表示补零的值。

__2 和 002 格式是空格填充和零填充的三字符年中的日; 没有不填充的年中的日格式。

逗号或小数点后跟一个或多个零表示小数秒,会打印到给定的小数位数。 逗号或小数点后跟一个或多个九表示小数秒,会打印到给定的小数位数并移除 末尾的零。 例如 "15:04:05,000" 或 "15:04:05.000" 以毫秒精度格式化或解析。

由于诸如用于空格填充的 _ 和用于时区信息的 Z 等格式,一些有效的布局 对于 time.Parse 是无效的时间值。

const (
	Nanosecond  Duration = 1
	Microsecond          = 1000 * Nanosecond
	Millisecond          = 1000 * Microsecond
	Second               = 1000 * Millisecond
	Minute               = 60 * Second
	Hour                 = 60 * Minute
)

常用时长。没有为 Day 或更大的单位定义常量, 以避免在夏令时时区转换时产生混淆。

要计算一个 Duration 中某种单位的数量,可进行除法:

second := time.Second
fmt.Print(int64(second/time.Millisecond)) // 输出 1000

要将一个整数个某单位转换为 Duration,可进行乘法:

seconds := 10
fmt.Print(time.Duration(seconds)*time.Second) // 输出 10s

Functions

func After

func After(d Duration) <-chan Time

After 等待时长过去,然后在返回的 channel 上发送当前时间。 它等价于 NewTimer(d).C。

在 Go 1.23 之前,本文档警告说,底层 Timer 在 timer 触发之前不会被垃圾回收器回收, 并且如果关心效率,代码应改用 NewTimer,并在不再需要该 timer 时调用 Timer.Stop。 从 Go 1.23 起,垃圾回收器可以回收未被引用的、 未被停止的 timer。当 After 可以满足需求时,没有理由更偏好 NewTimer。

Example
package main

import (
	"fmt"
	"time"
)

var c chan int

func handle(int) {}

func main() {
	select {
	case m := <-c:
		handle(m)
	case <-time.After(10 * time.Second):
		fmt.Println("timed out")
	}
}

func Sleep

func Sleep(d Duration)

Sleep 至少将当前 goroutine 暂停时长 d。 负数或零时长会导致 Sleep 立即返回。

Example
package main

import (
	"time"
)

func main() {
	time.Sleep(100 * time.Millisecond)
}

func Tick

func Tick(d Duration) <-chan Time

Tick 是 NewTicker 的便捷包装,仅提供对滴答 channel 的访问。与 NewTicker 不同,如果 d <= 0,Tick 将返回 nil。

在 Go 1.23 之前,本文档警告说,底层 Ticker 永远不会被垃圾回收器回收,并且 如果关心效率,代码应改用 NewTicker,并在 不再需要该 ticker 时调用 Ticker.Stop。 从 Go 1.23 起,垃圾回收器可以回收未被引用的 ticker,即使它们尚未被停止。 Stop 方法不再需要用于帮助垃圾回收器。 当 Tick 可以满足需求时,不再有任何理由更偏好 NewTicker。

Example
package main

import (
	"fmt"
	"time"
)

func statusUpdate() string { return "" }

func main() {
	c := time.Tick(5 * time.Second)
	for next := range c {
		fmt.Printf("%v %s\n", next, statusUpdate())
	}
}

Types

type Duration

type Duration int64

Duration 表示两个瞬间之间经过的时间, 以 int64 纳秒计数表示。该表示将最大可表示时长 限制在约 290 年。

Example
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))
}
func ParseDuration
func ParseDuration(s string) (Duration, error)

ParseDuration 解析持续时长字符串。 持续时长字符串是一个可能带符号的十进制数字序列, 每个数字带有可选的小数部分和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。 有效的时间单位有 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	hours, _ := time.ParseDuration("10h")
	complex, _ := time.ParseDuration("1h10m10s")
	micro, _ := time.ParseDuration("1µs")
	// The package also accepts the incorrect but common prefix u for micro.
	micro2, _ := time.ParseDuration("1us")

	fmt.Println(hours)
	fmt.Println(complex)
	fmt.Printf("There are %.0f seconds in %v.\n", complex.Seconds(), complex)
	fmt.Printf("There are %d nanoseconds in %v.\n", micro.Nanoseconds(), micro)
	fmt.Printf("There are %6.2e seconds in %v.\n", micro2.Seconds(), micro2)
}

Output:

10h0m0s
1h10m10s
There are 4210 seconds in 1h10m10s.
There are 1000 nanoseconds in 1µs.
There are 1.00e-06 seconds in 1µs.
func Since
func Since(t Time) Duration

Since 返回自 t 以来经过的时间。 它是 time.Now().Sub(t) 的简写。

Example
package main

import (
	"fmt"
	"time"
)

func expensiveCall() {}

func main() {
	start := time.Now()
	expensiveCall()
	elapsed := time.Since(start)
	fmt.Printf("The call took %v to run.\n", elapsed)
}
func Until
func Until(t Time) Duration

Until 返回到达 t 之前的时长。 它是 t.Sub(time.Now()) 的简写。

Example
package main

import (
	"fmt"
	"math"
	"time"
)

func main() {
	futureTime := time.Now().Add(5 * time.Second)
	durationUntil := time.Until(futureTime)
	fmt.Printf("Duration until future time: %.0f seconds", math.Ceil(durationUntil.Seconds()))
}

Output:

Duration until future time: 5 seconds
func (Duration) Abs
func (d Duration) Abs() Duration

Abs 返回 d 的绝对值。 作为特例,Duration(math.MinInt64) 会被转换为 Duration(math.MaxInt64), 其幅值减少 1 纳秒。

Example
package main

import (
	"fmt"
	"math"
	"time"
)

func main() {
	positiveDuration := 5 * time.Second
	negativeDuration := -3 * time.Second
	minInt64CaseDuration := time.Duration(math.MinInt64)

	absPositive := positiveDuration.Abs()
	absNegative := negativeDuration.Abs()
	absSpecial := minInt64CaseDuration.Abs() == time.Duration(math.MaxInt64)

	fmt.Printf("Absolute value of positive duration: %v\n", absPositive)
	fmt.Printf("Absolute value of negative duration: %v\n", absNegative)
	fmt.Printf("Absolute value of MinInt64 equal to MaxInt64: %t\n", absSpecial)

}

Output:

Absolute value of positive duration: 5s
Absolute value of negative duration: 3s
Absolute value of MinInt64 equal to MaxInt64: true
func (Duration) Hours
func (d Duration) Hours() float64

Hours 将该时长返回为浮点小时数。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	h, _ := time.ParseDuration("4h30m")
	fmt.Printf("I've got %.1f hours of work left.", h.Hours())
}

Output:

I've got 4.5 hours of work left.
func (Duration) Microseconds
func (d Duration) Microseconds() int64

Microseconds 将该时长返回为整数微秒计数。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	u, _ := time.ParseDuration("1s")
	fmt.Printf("One second is %d microseconds.\n", u.Microseconds())
}

Output:

One second is 1000000 microseconds.
func (Duration) Milliseconds
func (d Duration) Milliseconds() int64

Milliseconds 将该时长返回为整数毫秒计数。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	u, _ := time.ParseDuration("1s")
	fmt.Printf("One second is %d milliseconds.\n", u.Milliseconds())
}

Output:

One second is 1000 milliseconds.
func (Duration) Minutes
func (d Duration) Minutes() float64

Minutes 将该时长返回为浮点分钟数。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	m, _ := time.ParseDuration("1h30m")
	fmt.Printf("The movie is %.0f minutes long.", m.Minutes())
}

Output:

The movie is 90 minutes long.
func (Duration) Nanoseconds
func (d Duration) Nanoseconds() int64

Nanoseconds 将该时长返回为整数纳秒计数。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	u, _ := time.ParseDuration("1µs")
	fmt.Printf("One microsecond is %d nanoseconds.\n", u.Nanoseconds())
}

Output:

One microsecond is 1000 nanoseconds.
func (Duration) Round
func (d Duration) Round(m Duration) Duration

Round 返回将 d 舍入到 m 的最近倍数后的结果。 对于中间值的舍入行为是向远离零的方向舍入。 如果结果超出 Duration 能够存储的最大(或最小)值, Round 返回最大(或最小)时长。 如果 m <= 0,Round 原样返回 d。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	d, err := time.ParseDuration("1h15m30.918273645s")
	if err != nil {
		panic(err)
	}

	round := []time.Duration{
		time.Nanosecond,
		time.Microsecond,
		time.Millisecond,
		time.Second,
		2 * time.Second,
		time.Minute,
		10 * time.Minute,
		time.Hour,
	}

	for _, r := range round {
		fmt.Printf("d.Round(%6s) = %s\n", r, d.Round(r).String())
	}
}

Output:

d.Round(   1ns) = 1h15m30.918273645s
d.Round(   1µs) = 1h15m30.918274s
d.Round(   1ms) = 1h15m30.918s
d.Round(    1s) = 1h15m31s
d.Round(    2s) = 1h15m30s
d.Round(  1m0s) = 1h16m0s
d.Round( 10m0s) = 1h20m0s
d.Round(1h0m0s) = 1h0m0s
func (Duration) Seconds
func (d Duration) Seconds() float64

Seconds 将该时长返回为浮点秒数。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	m, _ := time.ParseDuration("1m30s")
	fmt.Printf("Take off in t-%.0f seconds.", m.Seconds())
}

Output:

Take off in t-90 seconds.
func (Duration) String
func (d Duration) String() string

String 返回以 "72h3m0.5s" 形式表示该时长的字符串。 前导的零单位会被省略。作为特例,小于一秒的时长在格式化时会使用更小的 单位(毫秒、微秒或纳秒),以确保首位数字非零。零时长格式化为 0s。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	fmt.Println(1*time.Hour + 2*time.Minute + 300*time.Millisecond)
	fmt.Println(300 * time.Millisecond)
}

Output:

1h2m0.3s
300ms
func (Duration) Truncate
func (d Duration) Truncate(m Duration) Duration

Truncate 返回将 d 向零舍入到 m 的倍数后的结果。 如果 m <= 0,Truncate 原样返回 d。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	d, err := time.ParseDuration("1h15m30.918273645s")
	if err != nil {
		panic(err)
	}

	trunc := []time.Duration{
		time.Nanosecond,
		time.Microsecond,
		time.Millisecond,
		time.Second,
		2 * time.Second,
		time.Minute,
		10 * time.Minute,
		time.Hour,
	}

	for _, t := range trunc {
		fmt.Printf("d.Truncate(%6s) = %s\n", t, d.Truncate(t).String())
	}
}

Output:

d.Truncate(   1ns) = 1h15m30.918273645s
d.Truncate(   1µs) = 1h15m30.918273s
d.Truncate(   1ms) = 1h15m30.918s
d.Truncate(    1s) = 1h15m30s
d.Truncate(    2s) = 1h15m30s
d.Truncate(  1m0s) = 1h15m0s
d.Truncate( 10m0s) = 1h10m0s
d.Truncate(1h0m0s) = 1h0m0s

type Location

type Location struct {
	// contains filtered or unexported fields
}

Location 将时间点映射到当时所使用的时区。 通常,Location 表示某个地理区域内使用的时间偏移量集合。 对于许多 Location,时间偏移量会根据该时间点是否处于夏令时而变化。

Location 用于为打印的 Time 值提供时区,也用于涉及可能跨越夏令时 边界的区间计算。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	// China doesn't have daylight saving. It uses a fixed 8 hour offset from UTC.
	secondsEastOfUTC := int((8 * time.Hour).Seconds())
	beijing := time.FixedZone("Beijing Time", secondsEastOfUTC)

	// If the system has a timezone database present, it's possible to load a location
	// from that, e.g.:
	//    newYork, err := time.LoadLocation("America/New_York")

	// Creating a time requires a location. Common locations are time.Local and time.UTC.
	timeInUTC := time.Date(2009, 1, 1, 12, 0, 0, 0, time.UTC)
	sameTimeInBeijing := time.Date(2009, 1, 1, 20, 0, 0, 0, beijing)

	// Although the UTC clock time is 1200 and the Beijing clock time is 2000, Beijing is
	// 8 hours ahead so the two dates actually represent the same instant.
	timesAreEqual := timeInUTC.Equal(sameTimeInBeijing)
	fmt.Println(timesAreEqual)

}

Output:

true
var Local *Location = &localLoc

Local 表示系统的本地时区。 在 Unix 系统上,Local 会查询 TZ 环境变量 以找到要使用的时区。没有 TZ 表示 使用系统默认的 /etc/localtime。 TZ="" 表示使用 UTC。 TZ="foo" 表示使用系统时区目录中的文件 foo。

var UTC *Location = &utcLoc

UTC 表示协调世界时(UTC)。

func FixedZone
func FixedZone(name string, offset int) *Location

FixedZone 返回一个 Location,它始终使用 给定的时区名称和偏移量(相对于 UTC 向东的秒数)。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	loc := time.FixedZone("UTC-8", -8*60*60)
	t := time.Date(2009, time.November, 10, 23, 0, 0, 0, loc)
	fmt.Println("The time is:", t.Format(time.RFC822))
}

Output:

The time is: 10 Nov 09 23:00 UTC-8
func LoadLocation
func LoadLocation(name string) (*Location, error)

LoadLocation 返回具有给定名称的 Location。

如果名称为 "" 或 "UTC",LoadLocation 返回 UTC。 如果名称为 "Local",LoadLocation 返回 Local。

否则,该名称被视为与 IANA 时区数据库中某个文件对应的位置名称, 例如 "America/New_York"。

LoadLocation 按以下顺序在以下位置查找 IANA 时区数据库:

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	location, err := time.LoadLocation("America/Los_Angeles")
	if err != nil {
		panic(err)
	}

	timeInUTC := time.Date(2018, 8, 30, 12, 0, 0, 0, time.UTC)
	fmt.Println(timeInUTC.In(location))
}

Output:

2018-08-30 05:00:00 -0700 PDT
func LoadLocationFromTZData
func LoadLocationFromTZData(name string, data []byte) (*Location, error)

LoadLocationFromTZData 返回一个具有给定名称的 Location, 该 Location 由 IANA 时区数据库格式的数据初始化。 数据应采用标准 IANA 时区文件的格式 (例如 Unix 系统上 /etc/localtime 的内容)。

func (*Location) String
func (l *Location) String() string

String 返回时区信息的描述性名称, 对应于 LoadLocation 或 FixedZone 的 name 参数。

type Month

type Month int

Month 指定一年中的月份(一月 = 1,……)。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	_, month, day := time.Now().Date()
	if month == time.November && day == 10 {
		fmt.Println("Happy Go day!")
	}
}
const (
	January Month = 1 + iota
	February
	March
	April
	May
	June
	July
	August
	September
	October
	November
	December
)
func (Month) String
func (m Month) String() string

String 返回月份的英文名称("January"、"February"、……)。

type ParseError

type ParseError struct {
	Layout     string
	Value      string
	LayoutElem string
	ValueElem  string
	Message    string
}

ParseError 描述解析时间字符串时出现的问题。

func (*ParseError) Error
func (e *ParseError) Error() string

Error 返回 ParseError 的字符串表示。

type Ticker

type Ticker struct {
	C <-chan Time // 传递滴答的 channel。
	// contains filtered or unexported fields
}

Ticker 持有一个 channel,它会按间隔 传递时钟的“滴答”。

func NewTicker
func NewTicker(d Duration) *Ticker

NewTicker 返回一个新的 Ticker,其中包含一个 channel,它将在每个 滴答后在该 channel 上发送当前时间。滴答的周期 由 duration 参数指定。ticker 会调整 时间间隔或丢弃滴答,以补偿接收缓慢的接收者。 时长 d 必须大于零;否则 NewTicker 将 panic。

在 Go 1.23 之前,垃圾回收器不会回收 尚未到期或尚未被停止的 ticker,因此代码通常 在调用 NewTicker 后立即 defer t.Stop,以便 在不再需要该 ticker 时使其可被回收。 从 Go 1.23 起,垃圾回收器可以回收未被引用的 ticker,即使它们尚未被停止。 Stop 方法不再需要用于帮助垃圾回收器。 (代码当然仍可能出于其他原因想要调用 Stop 来停止 ticker。)

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	ticker := time.NewTicker(time.Second)
	defer ticker.Stop()
	done := make(chan bool)
	go func() {
		time.Sleep(10 * time.Second)
		done <- true
	}()
	for {
		select {
		case <-done:
			fmt.Println("Done!")
			return
		case t := <-ticker.C:
			fmt.Println("Current time: ", t)
		}
	}
}
func (*Ticker) Reset
func (t *Ticker) Reset(d Duration)

Reset 停止一个 ticker 并将其周期重置为指定的时长。 下一个滴答将在新周期过去后到来。时长 d 必须大于零;否则 Reset 将 panic。

func (*Ticker) Stop
func (t *Ticker) Stop()

Stop 关闭一个 ticker。Stop 之后,将不再发送滴答。 Stop 不会关闭 channel,以防止正在从该 channel 读取的并发 goroutine 看到一个错误的 "tick"。

type Time

type Time struct {
	// contains filtered or unexported fields
}

Time 表示一个具有纳秒精度的时间瞬间。

使用时间的程序通常应以值而非指针的形式存储和传递它们。也就是说, 时间变量和结构体字段的类型应为 time.Time,而不是 *time.Time。

除方法 Time.GobDecode、Time.UnmarshalBinary、Time.UnmarshalJSON 和 Time.UnmarshalText 不是并发安全的之外,Time 值可被多个 goroutine 同时使用。

时间瞬间可以使用 Time.Before、Time.After 和 Time.Equal 方法进行比较。 Time.Sub 方法对两个瞬间求差,产生一个 Duration。 Time.Add 方法将一个 Time 与一个 Duration 相加,产生一个 Time。

Time 类型的零值是 1 年 1 月 1 日 00:00:00.000000000 UTC。 由于该时间在实践中最不可能出现,Time.IsZero 方法提供了一种简单的 方式来检测尚未被显式初始化的时间。

每个时间都有一个关联的 Location。方法 Time.Local、Time.UTC 和 Time.In 返回一个带有特定 Location 的 Time。使用这些方法改变 Time 值的 Location 不会改变它所表示的实际瞬间,只会改变解释它所使用的时区。

由 Time.GobEncode、Time.MarshalBinary、Time.AppendBinary、 Time.MarshalJSON、Time.MarshalText 和 Time.AppendText 方法保存的 Time 值的表示形式会存储 Time.Location 的偏移量,但不存储位置名称。 因此它们会丢失有关夏令时(Daylight Saving Time)的信息。

除了必需的“挂钟”读数外,Time 还可以包含当前进程单调时钟的可选读数, 以便在比较或减法时提供额外的精度。 详情请参阅包文档中的“单调时钟”部分。

注意,Go 的 == 运算符不仅比较时间瞬间,还比较 Location 和单调时钟读数。 因此,在未先保证所有值都设置了相同 Location(可通过使用 UTC 或 Local 方法实现)且通过设置 t = t.Round(0) 去除了单调时钟读数之前,Time 值 不应被用作 map 或数据库的键。一般而言,应优先使用 t.Equal(u) 而非 t == u,因为 t.Equal 使用可用的最精确比较,并且能正确处理只有一个 参数具有单调时钟读数的情况。

func Date
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time

Date 返回对应于

yyyy-mm-dd hh:mm:ss + nsec nanoseconds

的时间,位于给定位置中该时间对应的适当时区。

month、day、hour、min、sec 和 nsec 值可以超出其通常的范围, 并会在转换过程中被规范化。 例如,10 月 32 日会转换为 11 月 1 日。

夏令时转换会跳过或重复某些时间。 例如,在美国,2011 年 3 月 13 日 2:15am 从未出现, 而 2011 年 11 月 6 日 1:15am 出现了两次。在这种情况下, 时区的选择、因而时间的选择,并没有很好的定义。 Date 返回一个在转换所涉及的两个时区之一中正确的时间, 但不保证是哪一个。

如果 loc 为 nil,Date 会 panic。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	fmt.Printf("Go launched at %s\n", t.Local())
}

Output:

Go launched at 2009-11-10 15:00:00 -0800 PST
func Now
func Now() Time

Now 返回当前本地时间。

func Parse
func Parse(layout, value string) (Time, error)

Parse 解析格式化的字符串并返回它所表示的时间值。 有关如何表示格式,请参见名为 Layout 的常量的文档。第二个参数必须能够 使用作为第一个参数提供的格式字符串(布局)来解析。

Time.Format 的示例详细演示了布局字符串的工作方式,是一个很好的参考。

仅在解析时,输入可以在秒字段之后紧接着包含一个小数秒字段, 即使布局并未表明其存在。在这种情况下,逗号或小数点后跟最大一串数字 会被解析为小数秒。小数秒会被截断到纳秒精度。

布局中省略的元素被假定为零,或者在零不可能时假定为一,因此解析 "3:04pm" 返回对应 0 年 Jan 1 15:04:00 UTC 的时间(注意,由于年份为 0,该时间 早于零值 Time)。 年份必须在 0000..9999 范围内。星期几仅做语法检查,除此之外会被忽略。

对于指定两位数年份 06 的布局,值 NN >= 69 会被视为 19NN,NN < 69 会被视为 20NN。

本注释的其余部分描述时区的处理。

在没有时区指示符的情况下,Parse 返回 UTC 时间。

当解析带有诸如 -0700 的时区偏移的时间时,如果该偏移对应当前本地位置 (Local)所使用的时区,则 Parse 会在返回的时间中使用该位置和时区。 否则,它会将该时间记录为处于一个虚构的位置,时间固定为给定的时区偏移。

当解析带有诸如 MST 的时区缩写的时间时,如果该时区缩写当前本地位置有 已定义的偏移,则使用该偏移。无论位置如何,时区缩写 "UTC" 都被识别为 UTC。 如果时区缩写未知,Parse 会将该时间记录为处于一个虚构的位置, 使用给定的时区缩写和零偏移。这种选择意味着这样的时间可以用相同的布局 无损地解析和重新格式化,但表示中使用的确切时刻会因实际时区偏移而不同。 为避免此类问题,请优先使用采用数字时区偏移的时间布局,或使用 ParseInLocation。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	// See the example for Time.Format for a thorough description of how
	// to define the layout string to parse a time.Time value; Parse and
	// Format use the same model to describe their input and output.

	// longForm shows by example how the reference time would be represented in
	// the desired layout.
	const longForm = "Jan 2, 2006 at 3:04pm (MST)"
	t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
	fmt.Println(t)

	// shortForm is another way the reference time would be represented
	// in the desired layout; it has no time zone present.
	// Note: without explicit zone, returns time in UTC.
	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

}

Output:

2013-02-03 19:54:00 -0800 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"
func ParseInLocation
func ParseInLocation(layout, value string, loc *Location) (Time, error)

ParseInLocation 类似于 Parse,但有两点重要区别。 第一,在没有时区信息的情况下,Parse 将时间解释为 UTC; ParseInLocation 将时间解释为处于给定位置。 第二,给定一个时区偏移或缩写时,Parse 尝试将其与 Local 位置匹配; ParseInLocation 则使用给定位置。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	loc, _ := time.LoadLocation("Europe/Berlin")

	// This will look for the name CEST in the Europe/Berlin time zone.
	const longForm = "Jan 2, 2006 at 3:04pm (MST)"
	t, _ := time.ParseInLocation(longForm, "Jul 9, 2012 at 5:02am (CEST)", loc)
	fmt.Println(t)

	// Note: without explicit zone, returns time in given location.
	const shortForm = "2006-Jan-02"
	t, _ = time.ParseInLocation(shortForm, "2012-Jul-09", loc)
	fmt.Println(t)

}

Output:

2012-07-09 05:02:00 +0200 CEST
2012-07-09 00:00:00 +0200 CEST
func Unix
func Unix(sec int64, nsec int64) Time

Unix 返回给定 Unix 时间对应的本地 Time, 即自 1970 年 1 月 1 日 UTC 以来 sec 秒和 nsec 纳秒。 传入超出 [0, 999999999] 范围的 nsec 是合法的。 并非所有 sec 值都有对应的时间值。其中一个这样的值 是 1<<63-1(最大的 int64 值)。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	unixTime := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	fmt.Println(unixTime.Unix())
	t := time.Unix(unixTime.Unix(), 0).UTC()
	fmt.Println(t)

}

Output:

1257894000
2009-11-10 23:00:00 +0000 UTC
func UnixMicro
func UnixMicro(usec int64) Time

UnixMicro 返回给定 Unix 时间对应的本地 Time, 即自 1970 年 1 月 1 日 UTC 以来 usec 微秒。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	umt := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	fmt.Println(umt.UnixMicro())
	t := time.UnixMicro(umt.UnixMicro()).UTC()
	fmt.Println(t)

}

Output:

1257894000000000
2009-11-10 23:00:00 +0000 UTC
func UnixMilli
func UnixMilli(msec int64) Time

UnixMilli 返回给定 Unix 时间对应的本地 Time, 即自 1970 年 1 月 1 日 UTC 以来 msec 毫秒。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	umt := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	fmt.Println(umt.UnixMilli())
	t := time.UnixMilli(umt.UnixMilli()).UTC()
	fmt.Println(t)

}

Output:

1257894000000
2009-11-10 23:00:00 +0000 UTC
func (Time) Add
func (t Time) Add(d Duration) Time

Add 返回时间 t+d。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	start := time.Date(2009, 1, 1, 12, 0, 0, 0, time.UTC)
	afterTenSeconds := start.Add(time.Second * 10)
	afterTenMinutes := start.Add(time.Minute * 10)
	afterTenHours := start.Add(time.Hour * 10)
	afterTenDays := start.Add(time.Hour * 24 * 10)

	fmt.Printf("start = %v\n", start)
	fmt.Printf("start.Add(time.Second * 10) = %v\n", afterTenSeconds)
	fmt.Printf("start.Add(time.Minute * 10) = %v\n", afterTenMinutes)
	fmt.Printf("start.Add(time.Hour * 10) = %v\n", afterTenHours)
	fmt.Printf("start.Add(time.Hour * 24 * 10) = %v\n", afterTenDays)

}

Output:

start = 2009-01-01 12:00:00 +0000 UTC
start.Add(time.Second * 10) = 2009-01-01 12:00:10 +0000 UTC
start.Add(time.Minute * 10) = 2009-01-01 12:10:00 +0000 UTC
start.Add(time.Hour * 10) = 2009-01-01 22:00:00 +0000 UTC
start.Add(time.Hour * 24 * 10) = 2009-01-11 12:00:00 +0000 UTC
func (Time) AddDate
func (t Time) AddDate(years int, months int, days int) Time

AddDate 返回将给定的年数、月数和天数加到 t 上 所对应的时间。 例如,对 2011 年 1 月 1 日应用 AddDate(-1, 2, 3) 返回 2010 年 3 月 4 日。

注意,日期从根本上与时区耦合,而像天这样的日历周期并没有固定的 时长。AddDate 使用 Time 值的 Location 来确定这些时长。这意味着,相同 的 AddDate 参数可能会根据基础 Time 值及其 Location 产生不同的绝对时间 偏移。例如,对 3 月 27 日的 12:00 应用 AddDate(0, 0, 1) 总是返回 3 月 28 日 的 12:00。在某些位置和某些年份,这是 24 小时的偏移。在另一些情况下, 由于夏令时转换,它是 23 小时的偏移。

AddDate 会像 Date 那样对其结果进行规范化, 因此,例如在 10 月 31 日上加一个月会得到 12 月 1 日,即 11 月 31 日的规范化形式。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	start := time.Date(2023, 03, 25, 12, 0, 0, 0, time.UTC)
	oneDayLater := start.AddDate(0, 0, 1)
	dayDuration := oneDayLater.Sub(start)
	oneMonthLater := start.AddDate(0, 1, 0)
	oneYearLater := start.AddDate(1, 0, 0)

	zurich, err := time.LoadLocation("Europe/Zurich")
	if err != nil {
		panic(err)
	}
	// This was the day before a daylight saving time transition in Zürich.
	startZurich := time.Date(2023, 03, 25, 12, 0, 0, 0, zurich)
	oneDayLaterZurich := startZurich.AddDate(0, 0, 1)
	dayDurationZurich := oneDayLaterZurich.Sub(startZurich)

	fmt.Printf("oneDayLater: start.AddDate(0, 0, 1) = %v\n", oneDayLater)
	fmt.Printf("oneMonthLater: start.AddDate(0, 1, 0) = %v\n", oneMonthLater)
	fmt.Printf("oneYearLater: start.AddDate(1, 0, 0) = %v\n", oneYearLater)
	fmt.Printf("oneDayLaterZurich: startZurich.AddDate(0, 0, 1) = %v\n", oneDayLaterZurich)
	fmt.Printf("Day duration in UTC: %v | Day duration in Zürich: %v\n", dayDuration, dayDurationZurich)

}

Output:

oneDayLater: start.AddDate(0, 0, 1) = 2023-03-26 12:00:00 +0000 UTC
oneMonthLater: start.AddDate(0, 1, 0) = 2023-04-25 12:00:00 +0000 UTC
oneYearLater: start.AddDate(1, 0, 0) = 2024-03-25 12:00:00 +0000 UTC
oneDayLaterZurich: startZurich.AddDate(0, 0, 1) = 2023-03-26 12:00:00 +0200 CEST
Day duration in UTC: 24h0m0s | Day duration in Zürich: 23h0m0s
func (Time) After
func (t Time) After(u Time) bool

After 报告时间瞬间 t 是否在 u 之后。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	year2000 := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
	year3000 := time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)

	isYear3000AfterYear2000 := year3000.After(year2000) // True
	isYear2000AfterYear3000 := year2000.After(year3000) // False

	fmt.Printf("year3000.After(year2000) = %v\n", isYear3000AfterYear2000)
	fmt.Printf("year2000.After(year3000) = %v\n", isYear2000AfterYear3000)

}

Output:

year3000.After(year2000) = true
year2000.After(year3000) = false
func (Time) AppendBinary
func (t Time) AppendBinary(b []byte) ([]byte, error)

AppendBinary 实现 encoding.BinaryAppender 接口。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(2025, 4, 1, 15, 30, 45, 123456789, time.UTC)

	var buffer []byte
	buffer, err := t.AppendBinary(buffer)
	if err != nil {
		panic(err)
	}

	var parseTime time.Time
	err = parseTime.UnmarshalBinary(buffer[:])
	if err != nil {
		panic(err)
	}

	fmt.Printf("t: %v\n", t)
	fmt.Printf("parseTime: %v\n", parseTime)
	fmt.Printf("equal: %v\n", parseTime.Equal(t))

}

Output:

t: 2025-04-01 15:30:45.123456789 +0000 UTC
parseTime: 2025-04-01 15:30:45.123456789 +0000 UTC
equal: true
func (Time) AppendFormat
func (t Time) AppendFormat(b []byte, layout string) []byte

AppendFormat 类似于 Time.Format,但会将文本表示追加到 b 并返回扩展后的缓冲区。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(2017, time.November, 4, 11, 0, 0, 0, time.UTC)
	text := []byte("Time: ")

	text = t.AppendFormat(text, time.Kitchen)
	fmt.Println(string(text))

}

Output:

Time: 11:00AM
func (Time) AppendText
func (t Time) AppendText(b []byte) ([]byte, error)

AppendText 实现 encoding.TextAppender 接口。 时间采用 RFC 3339 格式、带亚秒精度进行格式化。 如果该时间戳无法表示为有效的 RFC 3339 (例如年份超出范围),则返回一个错误。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(2025, 4, 1, 15, 30, 45, 123456789, time.UTC)

	buffer := []byte("t: ")

	buffer, err := t.AppendText(buffer)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%s\n", buffer)

}

Output:

t: 2025-04-01T15:30:45.123456789Z
func (Time) Before
func (t Time) Before(u Time) bool

Before 报告时间瞬间 t 是否在 u 之前。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	year2000 := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
	year3000 := time.Date(3000, 1, 1, 0, 0, 0, 0, time.UTC)

	isYear2000BeforeYear3000 := year2000.Before(year3000) // True
	isYear3000BeforeYear2000 := year3000.Before(year2000) // False

	fmt.Printf("year2000.Before(year3000) = %v\n", isYear2000BeforeYear3000)
	fmt.Printf("year3000.Before(year2000) = %v\n", isYear3000BeforeYear2000)

}

Output:

year2000.Before(year3000) = true
year3000.Before(year2000) = false
func (Time) Clock
func (t Time) Clock() (hour, min, sec int)

Clock 返回 t 指定的一天内的小时、分钟和秒。

func (Time) Compare
func (t Time) Compare(u Time) int

Compare 将时间瞬间 t 与 u 进行比较。如果 t 在 u 之前,返回 -1; 如果 t 在 u 之后,返回 +1;如果二者相同,返回 0。

func (Time) Date
func (t Time) Date() (year int, month Month, day int)

Date 返回 t 所在的年、月、日。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	d := time.Date(2000, 2, 1, 12, 30, 0, 0, time.UTC)
	year, month, day := d.Date()

	fmt.Printf("year = %v\n", year)
	fmt.Printf("month = %v\n", month)
	fmt.Printf("day = %v\n", day)

}

Output:

year = 2000
month = February
day = 1
func (Time) Day
func (t Time) Day() int

Day 返回 t 指定的月内日。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	d := time.Date(2000, 2, 1, 12, 30, 0, 0, time.UTC)
	day := d.Day()

	fmt.Printf("day = %v\n", day)

}

Output:

day = 1
func (Time) Equal
func (t Time) Equal(u Time) bool

Equal 报告 t 和 u 是否表示同一时间瞬间。 即使两个时间位于不同位置,它们也可能相等。 例如,6:00 +0200 和 4:00 UTC 是 Equal 的。 关于对 Time 值使用 == 的陷阱,请参阅 Time 类型的文档; 大多数代码应改用 Equal。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	secondsEastOfUTC := int((8 * time.Hour).Seconds())
	beijing := time.FixedZone("Beijing Time", secondsEastOfUTC)

	// Unlike the equal operator, Equal is aware that d1 and d2 are the
	// same instant but in different time zones.
	d1 := time.Date(2000, 2, 1, 12, 30, 0, 0, time.UTC)
	d2 := time.Date(2000, 2, 1, 20, 30, 0, 0, beijing)

	datesEqualUsingEqualOperator := d1 == d2
	datesEqualUsingFunction := d1.Equal(d2)

	fmt.Printf("datesEqualUsingEqualOperator = %v\n", datesEqualUsingEqualOperator)
	fmt.Printf("datesEqualUsingFunction = %v\n", datesEqualUsingFunction)

}

Output:

datesEqualUsingEqualOperator = false
datesEqualUsingFunction = true
func (Time) Format
func (t Time) Format(layout string) string

Format 返回时间值的文本表示,按照参数定义的布局进行格式化。 有关如何表示布局格式,请参见名为 Layout 的常量的文档。

Time.Format 的可执行示例详细演示了布局字符串的工作方式,是一个很好的参考。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	// Parse a time value from a string in the standard Unix format.
	t, err := time.Parse(time.UnixDate, "Wed Feb 25 11:06:39 PST 2015")
	if err != nil { // Always check errors even if they should not happen.
		panic(err)
	}

	tz, err := time.LoadLocation("Asia/Shanghai")
	if err != nil { // Always check errors even if they should not happen.
		panic(err)
	}

	// time.Time's Stringer method is useful without any format.
	fmt.Println("default format:", t)

	// Predefined constants in the package implement common layouts.
	fmt.Println("Unix format:", t.Format(time.UnixDate))

	// The time zone attached to the time value affects its output.
	fmt.Println("Same, in UTC:", t.UTC().Format(time.UnixDate))

	fmt.Println("in Shanghai with seconds:", t.In(tz).Format("2006-01-02T15:04:05 -070000"))

	fmt.Println("in Shanghai with colon seconds:", t.In(tz).Format("2006-01-02T15:04:05 -07:00:00"))

	// The rest of this function demonstrates the properties of the
	// layout string used in the format.

	// The layout string used by the Parse function and Format method
	// shows by example how the reference time should be represented.
	// We stress that one must show how the reference time is formatted,
	// not a time of the user's choosing. Thus each layout string is a
	// representation of the time stamp,
	//	Jan 2 15:04:05 2006 MST
	// An easy way to remember this value is that it holds, when presented
	// in this order, the values (lined up with the elements above):
	//	  1 2  3  4  5    6  -7
	// There are some wrinkles illustrated below.

	// Most uses of Format and Parse use constant layout strings such as
	// the ones defined in this package, but the interface is flexible,
	// as these examples show.

	// Define a helper function to make the examples' output look nice.
	do := func(name, layout, want string) {
		got := t.Format(layout)
		if want != got {
			fmt.Printf("error: for %q got %q; expected %q\n", layout, got, want)
			return
		}
		fmt.Printf("%-16s %q gives %q\n", name, layout, got)
	}

	// Print a header in our output.
	fmt.Printf("\nFormats:\n\n")

	// Simple starter examples.
	do("Basic full date", "Mon Jan 2 15:04:05 MST 2006", "Wed Feb 25 11:06:39 PST 2015")
	do("Basic short date", "2006/01/02", "2015/02/25")

	// The hour of the reference time is 15, or 3PM. The layout can express
	// it either way, and since our value is the morning we should see it as
	// an AM time. We show both in one format string. Lower case too.
	do("AM/PM", "3PM==3pm==15h", "11AM==11am==11h")

	// When parsing, if the seconds value is followed by a decimal point
	// and some digits, that is taken as a fraction of a second even if
	// the layout string does not represent the fractional second.
	// Here we add a fractional second to our time value used above.
	t, err = time.Parse(time.UnixDate, "Wed Feb 25 11:06:39.1234 PST 2015")
	if err != nil {
		panic(err)
	}
	// It does not appear in the output if the layout string does not contain
	// a representation of the fractional second.
	do("No fraction", time.UnixDate, "Wed Feb 25 11:06:39 PST 2015")

	// Fractional seconds can be printed by adding a run of 0s or 9s after
	// a decimal point in the seconds value in the layout string.
	// If the layout digits are 0s, the fractional second is of the specified
	// width. Note that the output has a trailing zero.
	do("0s for fraction", "15:04:05.00000", "11:06:39.12340")

	// If the fraction in the layout is 9s, trailing zeros are dropped.
	do("9s for fraction", "15:04:05.99999999", "11:06:39.1234")

}

Output:

default format: 2015-02-25 11:06:39 -0800 PST
Unix format: Wed Feb 25 11:06:39 PST 2015
Same, in UTC: Wed Feb 25 19:06:39 UTC 2015
in Shanghai with seconds: 2015-02-26T03:06:39 +080000
in Shanghai with colon seconds: 2015-02-26T03:06:39 +08:00:00

Formats:

Basic full date  "Mon Jan 2 15:04:05 MST 2006" gives "Wed Feb 25 11:06:39 PST 2015"
Basic short date "2006/01/02" gives "2015/02/25"
AM/PM            "3PM==3pm==15h" gives "11AM==11am==11h"
No fraction      "Mon Jan _2 15:04:05 MST 2006" gives "Wed Feb 25 11:06:39 PST 2015"
0s for fraction  "15:04:05.00000" gives "11:06:39.12340"
9s for fraction  "15:04:05.99999999" gives "11:06:39.1234"
Example (Pad)
package main

import (
	"fmt"
	"time"
)

func main() {
	// Parse a time value from a string in the standard Unix format.
	t, err := time.Parse(time.UnixDate, "Sat Mar 7 11:06:39 PST 2015")
	if err != nil { // Always check errors even if they should not happen.
		panic(err)
	}

	// Define a helper function to make the examples' output look nice.
	do := func(name, layout, want string) {
		got := t.Format(layout)
		if want != got {
			fmt.Printf("error: for %q got %q; expected %q\n", layout, got, want)
			return
		}
		fmt.Printf("%-16s %q gives %q\n", name, layout, got)
	}

	// The predefined constant Unix uses an underscore to pad the day.
	do("Unix", time.UnixDate, "Sat Mar  7 11:06:39 PST 2015")

	// For fixed-width printing of values, such as the date, that may be one or
	// two characters (7 vs. 07), use an _ instead of a space in the layout string.
	// Here we print just the day, which is 2 in our layout string and 7 in our
	// value.
	do("No pad", "<2>", "<7>")

	// An underscore represents a space pad, if the date only has one digit.
	do("Spaces", "<_2>", "< 7>")

	// A "0" indicates zero padding for single-digit values.
	do("Zeros", "<02>", "<07>")

	// If the value is already the right width, padding is not used.
	// For instance, the second (05 in the reference time) in our value is 39,
	// so it doesn't need padding, but the minutes (04, 06) does.
	do("Suppressed pad", "04:05", "06:39")

}

Output:

Unix             "Mon Jan _2 15:04:05 MST 2006" gives "Sat Mar  7 11:06:39 PST 2015"
No pad           "<2>" gives "<7>"
Spaces           "<_2>" gives "< 7>"
Zeros            "<02>" gives "<07>"
Suppressed pad   "04:05" gives "06:39"
func (Time) GoString
func (t Time) GoString() string

GoString 实现了 fmt.GoStringer,并将 t 格式化为可在 Go 源代码中打印的形式。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
	fmt.Println(t.GoString())
	t = t.Add(1 * time.Minute)
	fmt.Println(t.GoString())
	t = t.AddDate(0, 1, 0)
	fmt.Println(t.GoString())
	t, _ = time.Parse("Jan 2, 2006 at 3:04pm (MST)", "Feb 3, 2013 at 7:54pm (UTC)")
	fmt.Println(t.GoString())

}

Output:

time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
time.Date(2009, time.November, 10, 23, 1, 0, 0, time.UTC)
time.Date(2009, time.December, 10, 23, 1, 0, 0, time.UTC)
time.Date(2013, time.February, 3, 19, 54, 0, 0, time.UTC)
func (*Time) GobDecode
func (t *Time) GobDecode(data []byte) error

GobDecode 实现 gob.GobDecoder 接口。

func (Time) GobEncode
func (t Time) GobEncode() ([]byte, error)

GobEncode 实现 gob.GobEncoder 接口。

func (Time) Hour
func (t Time) Hour() int

Hour 返回 t 指定的一天内的小时,范围是 [0, 23]。

func (Time) ISOWeek
func (t Time) ISOWeek() (year, week int)

ISOWeek 返回 t 所在的 ISO 8601 年份和周数。 周的范围是 1 到 53。n 年的 1 月 1 日到 1 月 3 日可能属于 n-1 年的 第 52 或 53 周,而 12 月 29 日到 12 月 31 日可能属于 n+1 年的第 1 周。

func (Time) In
func (t Time) In(loc *Location) Time

In 返回 t 的一个副本,它表示同一时间瞬间, 但为显示目的将该副本的位置信息设置为 loc。

如果 loc 为 nil,In 会 panic。

func (Time) IsDST
func (t Time) IsDST() bool

IsDST 报告配置位置中的时间是否处于夏令时。

func (Time) IsZero
func (t Time) IsZero() bool

IsZero 报告 t 是否表示零时间瞬间, 即 1 年 1 月 1 日 00:00:00 UTC。

func (Time) Local
func (t Time) Local() Time

Local 返回将位置设置为本地时间的 t。

func (Time) Location
func (t Time) Location() *Location

Location 返回与 t 关联的时区信息。

func (Time) MarshalBinary
func (t Time) MarshalBinary() ([]byte, error)

MarshalBinary 实现 encoding.BinaryMarshaler 接口。

func (Time) MarshalJSON
func (t Time) MarshalJSON() ([]byte, error)

MarshalJSON 实现 encoding/json.Marshaler 接口。 时间是一个采用 RFC 3339 格式、带亚秒精度的带引号字符串。 如果该时间戳无法表示为有效的 RFC 3339 (例如年份超出范围),则报告一个错误。

func (Time) MarshalText
func (t Time) MarshalText() ([]byte, error)

MarshalText 实现 encoding.TextMarshaler 接口。其输出 与调用 Time.AppendText 方法的结果一致。

更多信息请参见 Time.AppendText。

func (Time) Minute
func (t Time) Minute() int

Minute 返回 t 指定的小时内的分钟偏移,范围是 [0, 59]。

func (Time) Month
func (t Time) Month() Month

Month 返回 t 指定的一年中的月份。

func (Time) Nanosecond
func (t Time) Nanosecond() int

Nanosecond 返回 t 指定的秒内的纳秒偏移, 范围是 [0, 999999999]。

func (Time) Round
func (t Time) Round(d Duration) Time

Round 返回将 t 舍入到 d 的最近倍数(自零时间起)后的结果。 对于中间值的舍入行为是向上舍入。 如果 d <= 0,Round 返回去除任何单调时钟读数但其余保持不变的 t。

Round 将时间视为自零时间起的绝对时长进行运算;它不作用于时间 的展示形式。因此,取决于时间的 Location,Round(Hour) 可能返回 一个分钟非零的时间。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Date(0, 0, 0, 12, 15, 30, 918273645, time.UTC)
	round := []time.Duration{
		time.Nanosecond,
		time.Microsecond,
		time.Millisecond,
		time.Second,
		2 * time.Second,
		time.Minute,
		10 * time.Minute,
		time.Hour,
	}

	for _, d := range round {
		fmt.Printf("t.Round(%6s) = %s\n", d, t.Round(d).Format("15:04:05.999999999"))
	}
}

Output:

t.Round(   1ns) = 12:15:30.918273645
t.Round(   1µs) = 12:15:30.918274
t.Round(   1ms) = 12:15:30.918
t.Round(    1s) = 12:15:31
t.Round(    2s) = 12:15:30
t.Round(  1m0s) = 12:16:00
t.Round( 10m0s) = 12:20:00
t.Round(1h0m0s) = 12:00:00
func (Time) Second
func (t Time) Second() int

Second 返回 t 指定的分钟内的秒偏移,范围是 [0, 59]。

func (Time) String
func (t Time) String() string

String 返回按格式字符串格式化的时间

"2006-01-02 15:04:05.999999999 -0700 MST"

如果时间具有单调时钟读数,返回的字符串会包含一个最终字段 "m=±<value>", 其中 value 是单调时钟读数,格式化为十进制秒数。

返回的字符串用于调试;对于稳定的序列化表示, 请使用 t.MarshalText、t.MarshalBinary,或带有显式格式字符串的 t.Format。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	timeWithNanoseconds := time.Date(2000, 2, 1, 12, 13, 14, 15, time.UTC)
	withNanoseconds := timeWithNanoseconds.String()

	timeWithoutNanoseconds := time.Date(2000, 2, 1, 12, 13, 14, 0, time.UTC)
	withoutNanoseconds := timeWithoutNanoseconds.String()

	fmt.Printf("withNanoseconds = %v\n", withNanoseconds)
	fmt.Printf("withoutNanoseconds = %v\n", withoutNanoseconds)

}

Output:

withNanoseconds = 2000-02-01 12:13:14.000000015 +0000 UTC
withoutNanoseconds = 2000-02-01 12:13:14 +0000 UTC
func (Time) Sub
func (t Time) Sub(u Time) Duration

Sub 返回时长 t-u。如果结果超出 Duration 能够存储的最大(或最小) 值,将返回最大(或最小)时长。 要计算时长 d 对应的 t-d,请使用 t.Add(-d)。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	start := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
	end := time.Date(2000, 1, 1, 12, 0, 0, 0, time.UTC)

	difference := end.Sub(start)
	fmt.Printf("difference = %v\n", difference)

}

Output:

difference = 12h0m0s
func (Time) Truncate
func (t Time) Truncate(d Duration) Time

Truncate 返回将 t 向下舍入到 d 的倍数(自零时间起)后的结果。 如果 d <= 0,Truncate 返回去除任何单调时钟读数但其余保持不变的 t。

Truncate 将时间视为自零时间起的绝对时长进行运算;它不作用于时间 的展示形式。因此,取决于时间的 Location,Truncate(Hour) 可能返回 一个分钟非零的时间。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	t, _ := time.Parse("2006 Jan 02 15:04:05", "2012 Dec 07 12:15:30.918273645")
	trunc := []time.Duration{
		time.Nanosecond,
		time.Microsecond,
		time.Millisecond,
		time.Second,
		2 * time.Second,
		time.Minute,
		10 * time.Minute,
	}

	for _, d := range trunc {
		fmt.Printf("t.Truncate(%5s) = %s\n", d, t.Truncate(d).Format("15:04:05.999999999"))
	}
	// To round to the last midnight in the local timezone, create a new Date.
	midnight := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local)
	_ = midnight

}

Output:

t.Truncate(  1ns) = 12:15:30.918273645
t.Truncate(  1µs) = 12:15:30.918273
t.Truncate(  1ms) = 12:15:30.918
t.Truncate(   1s) = 12:15:30
t.Truncate(   2s) = 12:15:30
t.Truncate( 1m0s) = 12:15:00
t.Truncate(10m0s) = 12:10:00
func (Time) UTC
func (t Time) UTC() Time

UTC 返回将位置设置为 UTC 的 t。

func (Time) Unix
func (t Time) Unix() int64

Unix 将 t 作为 Unix 时间返回,即自 1970 年 1 月 1 日 UTC 以来 经过的秒数。结果不依赖于与 t 关联的位置。 类 Unix 操作系统通常将时间记录为 32 位的秒计数, 但由于此处的方法返回 64 位值,因此它在过去或未来数十亿年 内都有效。

Example
package main

import (
	"fmt"
	"time"
)

func main() {
	// 1 billion seconds of Unix, three ways.
	fmt.Println(time.Unix(1e9, 0).UTC())     // 1e9 seconds
	fmt.Println(time.Unix(0, 1e18).UTC())    // 1e18 nanoseconds
	fmt.Println(time.Unix(2e9, -1e18).UTC()) // 2e9 seconds - 1e18 nanoseconds

	t := time.Date(2001, time.September, 9, 1, 46, 40, 0, time.UTC)
	fmt.Println(t.Unix())     // seconds since 1970
	fmt.Println(t.UnixNano()) // nanoseconds since 1970

}

Output:

2001-09-09 01:46:40 +0000 UTC
2001-09-09 01:46:40 +0000 UTC
2001-09-09 01:46:40 +0000 UTC
1000000000
1000000000000000000
func (Time) UnixMicro
func (t Time) UnixMicro() int64

UnixMicro 将 t 作为 Unix 时间返回,即自 1970 年 1 月 1 日 UTC 以来 经过的微秒数。如果以微秒表示的 Unix 时间无法用 int64 表示 (即日期早于 -290307 年或晚于 294246 年),则结果未定义。 结果不依赖于与 t 关联的位置。

func (Time) UnixMilli
func (t Time) UnixMilli() int64

UnixMilli 将 t 作为 Unix 时间返回,即自 1970 年 1 月 1 日 UTC 以来 经过的毫秒数。如果以毫秒表示的 Unix 时间无法用 int64 表示 (即日期距 1970 年往前或往后超过约 2.92 亿年),则结果未定义。 结果不依赖于与 t 关联的位置。

func (Time) UnixNano
func (t Time) UnixNano() int64

UnixNano 将 t 作为 Unix 时间返回,即自 1970 年 1 月 1 日 UTC 以来 经过的纳秒数。如果以纳秒表示的 Unix 时间无法用 int64 表示 (即日期早于 1678 年或晚于 2262 年),则结果未定义。注意这意味着 对零 Time 调用 UnixNano 的结果是未定义的。结果不依赖于与 t 关联的 位置。

func (*Time) UnmarshalBinary
func (t *Time) UnmarshalBinary(data []byte) error

UnmarshalBinary 实现 encoding.BinaryUnmarshaler 接口。

func (*Time) UnmarshalJSON
func (t *Time) UnmarshalJSON(data []byte) error

UnmarshalJSON 实现 encoding/json.Unmarshaler 接口。 时间必须是采用 RFC 3339 格式的带引号字符串。

func (*Time) UnmarshalText
func (t *Time) UnmarshalText(data []byte) error

UnmarshalText 实现 encoding.TextUnmarshaler 接口。 时间必须采用 RFC 3339 格式。

func (Time) Weekday
func (t Time) Weekday() Weekday

Weekday 返回 t 指定的星期几。

func (Time) Year
func (t Time) Year() int

Year 返回 t 所在的年份。

func (Time) YearDay
func (t Time) YearDay() int

YearDay 返回 t 指定的一年中的第几天,非闰年的范围是 [1,365], 闰年是 [1,366]。

func (Time) Zone
func (t Time) Zone() (name string, offset int)

Zone 计算在时间 t 生效的时区,返回时区的缩写名称 (例如 "CET")以及其相对 UTC 以东的偏移秒数。

func (Time) ZoneBounds
func (t Time) ZoneBounds() (start, end Time)

ZoneBounds 返回在时间 t 生效的时区的边界。 该时区始于 start,下一个时区始于 end。 如果该时区始于时间的起点,则 start 将作为零 Time 返回。 如果该时区永远持续,则 end 将作为零 Time 返回。 返回的时间的 Location 将与 t 相同。

type Timer

type Timer struct {
	C <-chan Time
	// contains filtered or unexported fields
}

Timer 类型表示单个事件。 当 Timer 到期时,当前时间将被发送到 C, 除非该 Timer 是由 AfterFunc 创建的。 Timer 必须使用 NewTimer 或 AfterFunc 创建。

func AfterFunc
func AfterFunc(d Duration, f func()) *Timer

AfterFunc 等待时长过去,然后在它自己的 goroutine 中调用 f。 它返回一个 Timer,可以使用其 Stop 方法 来取消该调用。 返回的 Timer 的 C 字段未被使用,将为 nil。

func NewTimer
func NewTimer(d Duration) *Timer

NewTimer 创建一个新的 Timer,它将在至少经过时长 d 后 在其 channel 上发送当前时间。

在 Go 1.23 之前,垃圾回收器不会回收 尚未到期或尚未被停止的 timer,因此代码通常 在调用 NewTimer 后立即 defer t.Stop,以便 在不再需要该 timer 时使其可被回收。 从 Go 1.23 起,垃圾回收器可以回收未被引用的 timer,即使它们尚未到期或尚未被停止。 Stop 方法不再需要用于帮助垃圾回收器。 (代码当然仍可能出于其他原因想要调用 Stop 来停止 timer。)

在 Go 1.23 之前,与 Timer 关联的 channel 是 异步的(带缓冲,容量为 1),这意味着 即使在 Timer.Stop 或 Timer.Reset 返回之后, 也可能接收到过期的时间值。 从 Go 1.23 起,该 channel 是同步的(无缓冲,容量为 0), 消除了这些过期值的可能性。

GODEBUG 设置 asynctimerchan=1 会恢复这两项 Go 1.23 之前的行为:设置后,未到期的 timer 不会被垃圾回收, 并且 channel 将具有缓冲容量。该设置在 Go 1.27 或更高版本中可能被移除。

func (*Timer) Reset
func (t *Timer) Reset(d Duration) bool

Reset 将 timer 改为在时长 d 后到期。 如果 timer 此前处于活动状态,则返回 true;如果 timer 已 到期或已被停止,则返回 false。

对于使用 AfterFunc(d, f) 创建的基于函数的 timer,Reset 要么重新安排 f 的运行时间(此时 Reset 返回 true),要么安排 f 再次运行(此时返回 false)。 当 Reset 返回 false 时,Reset 既不会在返回前等待先前的 f 完成,也不保证随后运行 f 的 goroutine 不会与先前那个并发运行。 如果调用者需要知道 f 先前的执行 是否已完成,必须与 f 显式协调。

对于使用 NewTimer 创建的基于 chan 的 timer,从 Go 1.23 起, 在 Reset 返回后从 t.C 进行的任何接收都保证不会 接收到与先前 timer 设置对应的时间值; 如果程序尚未从 t.C 接收过,并且 timer 正在 运行,则 Reset 保证返回 true。 在 Go 1.23 之前,使用 Reset 的唯一安全做法是先调用 Timer.Stop 并显式排空 timer。 详情参见 NewTimer 文档。

func (*Timer) Stop
func (t *Timer) Stop() bool

Stop 阻止 Timer 触发。 如果该调用停止了 timer,则返回 true;如果 timer 已经 到期或已被停止,则返回 false。

对于使用 AfterFunc(d, f) 创建的基于函数的 timer, 如果 t.Stop 返回 false,那么说明 timer 已经到期, 并且函数 f 已在它自己的 goroutine 中启动; Stop 在返回前不会等待 f 完成。 如果调用者需要知道 f 是否已完成, 必须与 f 显式协调。

对于使用 NewTimer(d) 创建的基于 chan 的 timer,从 Go 1.23 起, 在 Stop 返回后从 t.C 进行的任何接收都保证会阻塞, 而不会接收到 Stop 之前的过期时间值; 如果程序尚未从 t.C 接收过,并且 timer 正在 运行,则 Stop 保证返回 true。 在 Go 1.23 之前,使用 Stop 的唯一安全做法是在 Stop 返回 false 时 插入额外的 <-t.C 以排空可能存在的过期值。 详情参见 NewTimer 文档。

type Weekday

type Weekday int

Weekday 指定一周中的某天(星期日 = 0,……)。

const (
	Sunday Weekday = iota
	Monday
	Tuesday
	Wednesday
	Thursday
	Friday
	Saturday
)
func (Weekday) String
func (d Weekday) String() string

String 返回星期的英文名称("Sunday"、"Monday"、……)。

Directories

tzdata Package tzdata 提供时区数据库的内嵌副本。