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
- Constants
- func After(d Duration) <-chan Time
- func Sleep(d Duration)
- func Tick(d Duration) <-chan Time
-
type Duration
- func ParseDuration(s string) (Duration, error)
- func Since(t Time) Duration
- func Until(t Time) Duration
- func (d Duration) Abs() Duration
- func (d Duration) Hours() float64
- func (d Duration) Microseconds() int64
- func (d Duration) Milliseconds() int64
- func (d Duration) Minutes() float64
- func (d Duration) Nanoseconds() int64
- func (d Duration) Round(m Duration) Duration
- func (d Duration) Seconds() float64
- func (d Duration) String() string
- func (d Duration) Truncate(m Duration) Duration
- type Location
- type Month
- type ParseError
- type Ticker
-
type Time
- func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time
- func Now() Time
- func Parse(layout, value string) (Time, error)
- func ParseInLocation(layout, value string, loc *Location) (Time, error)
- func Unix(sec int64, nsec int64) Time
- func UnixMicro(usec int64) Time
- func UnixMilli(msec int64) Time
- func (t Time) Add(d Duration) Time
- func (t Time) AddDate(years int, months int, days int) Time
- func (t Time) After(u Time) bool
- func (t Time) AppendBinary(b []byte) ([]byte, error)
- func (t Time) AppendFormat(b []byte, layout string) []byte
- func (t Time) AppendText(b []byte) ([]byte, error)
- func (t Time) Before(u Time) bool
- func (t Time) Clock() (hour, min, sec int)
- func (t Time) Compare(u Time) int
- func (t Time) Date() (year int, month Month, day int)
- func (t Time) Day() int
- func (t Time) Equal(u Time) bool
- func (t Time) Format(layout string) string
- func (t Time) GoString() string
- func (t *Time) GobDecode(data []byte) error
- func (t Time) GobEncode() ([]byte, error)
- func (t Time) Hour() int
- func (t Time) ISOWeek() (year, week int)
- func (t Time) In(loc *Location) Time
- func (t Time) IsDST() bool
- func (t Time) IsZero() bool
- func (t Time) Local() Time
- func (t Time) Location() *Location
- func (t Time) MarshalBinary() ([]byte, error)
- func (t Time) MarshalJSON() ([]byte, error)
- func (t Time) MarshalText() ([]byte, error)
- func (t Time) Minute() int
- func (t Time) Month() Month
- func (t Time) Nanosecond() int
- func (t Time) Round(d Duration) Time
- func (t Time) Second() int
- func (t Time) String() string
- func (t Time) Sub(u Time) Duration
- func (t Time) Truncate(d Duration) Time
- func (t Time) UTC() Time
- func (t Time) Unix() int64
- func (t Time) UnixMicro() int64
- func (t Time) UnixMilli() int64
- func (t Time) UnixNano() int64
- func (t *Time) UnmarshalBinary(data []byte) error
- func (t *Time) UnmarshalJSON(data []byte) error
- func (t *Time) UnmarshalText(data []byte) error
- func (t Time) Weekday() Weekday
- func (t Time) Year() int
- func (t Time) YearDay() int
- func (t Time) Zone() (name string, offset int)
- func (t Time) ZoneBounds() (start, end Time)
- type Timer
- type Weekday
Examples
- After
- Date
- Duration
- Duration.Abs
- Duration.Hours
- Duration.Microseconds
- Duration.Milliseconds
- Duration.Minutes
- Duration.Nanoseconds
- Duration.Round
- Duration.Seconds
- Duration.String
- Duration.Truncate
- FixedZone
- LoadLocation
- Location
- Month
- NewTicker
- Parse
- ParseDuration
- ParseInLocation
- Since
- Sleep
- Tick
- Time.Add
- Time.AddDate
- Time.After
- Time.AppendBinary
- Time.AppendFormat
- Time.AppendText
- Time.Before
- Time.Date
- Time.Day
- Time.Equal
- Time.Format
- Time.Format (Pad)
- Time.GoString
- Time.Round
- Time.String
- Time.Sub
- Time.Truncate
- Time.Unix
- Unix
- UnixMicro
- UnixMilli
- Until
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"。
Output: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)
}
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()) 的简写。
Output: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()))
}
Duration until future time: 5 seconds
func (Duration) Abs
func (d Duration) Abs() Duration
Abs 返回 d 的绝对值。
作为特例,Duration(math.MinInt64) 会被转换为 Duration(math.MaxInt64),
其幅值减少 1 纳秒。
Output: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)
}
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 将该时长返回为浮点小时数。
Output:Example
package main
import (
"fmt"
"time"
)
func main() {
h, _ := time.ParseDuration("4h30m")
fmt.Printf("I've got %.1f hours of work left.", h.Hours())
}
I've got 4.5 hours of work left.
func (Duration) Microseconds
func (d Duration) Microseconds() int64
Microseconds 将该时长返回为整数微秒计数。
Output:Example
package main
import (
"fmt"
"time"
)
func main() {
u, _ := time.ParseDuration("1s")
fmt.Printf("One second is %d microseconds.\n", u.Microseconds())
}
One second is 1000000 microseconds.
func (Duration) Milliseconds
func (d Duration) Milliseconds() int64
Milliseconds 将该时长返回为整数毫秒计数。
Output:Example
package main
import (
"fmt"
"time"
)
func main() {
u, _ := time.ParseDuration("1s")
fmt.Printf("One second is %d milliseconds.\n", u.Milliseconds())
}
One second is 1000 milliseconds.
func (Duration) Minutes
func (d Duration) Minutes() float64
Minutes 将该时长返回为浮点分钟数。
Output:Example
package main
import (
"fmt"
"time"
)
func main() {
m, _ := time.ParseDuration("1h30m")
fmt.Printf("The movie is %.0f minutes long.", m.Minutes())
}
The movie is 90 minutes long.
func (Duration) Nanoseconds
func (d Duration) Nanoseconds() int64
Nanoseconds 将该时长返回为整数纳秒计数。
Output:Example
package main
import (
"fmt"
"time"
)
func main() {
u, _ := time.ParseDuration("1µs")
fmt.Printf("One microsecond is %d nanoseconds.\n", u.Nanoseconds())
}
One microsecond is 1000 nanoseconds.
func (Duration) Round
func (d Duration) Round(m Duration) Duration
Round 返回将 d 舍入到 m 的最近倍数后的结果。
对于中间值的舍入行为是向远离零的方向舍入。
如果结果超出 Duration 能够存储的最大(或最小)值,
Round 返回最大(或最小)时长。
如果 m <= 0,Round 原样返回 d。
Output: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())
}
}
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 将该时长返回为浮点秒数。
Output:Example
package main
import (
"fmt"
"time"
)
func main() {
m, _ := time.ParseDuration("1m30s")
fmt.Printf("Take off in t-%.0f seconds.", m.Seconds())
}
Take off in t-90 seconds.
func (Duration) String
func (d Duration) String() string
String 返回以 "72h3m0.5s" 形式表示该时长的字符串。
前导的零单位会被省略。作为特例,小于一秒的时长在格式化时会使用更小的
单位(毫秒、微秒或纳秒),以确保首位数字非零。零时长格式化为 0s。
Output:Example
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(1*time.Hour + 2*time.Minute + 300*time.Millisecond)
fmt.Println(300 * time.Millisecond)
}
1h2m0.3s
300ms
func (Duration) Truncate
func (d Duration) Truncate(m Duration) Duration
Truncate 返回将 d 向零舍入到 m 的倍数后的结果。
如果 m <= 0,Truncate 原样返回 d。
Output: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())
}
}
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 值提供时区,也用于涉及可能跨越夏令时
边界的区间计算。
Output: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)
}
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 向东的秒数)。
Output: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))
}
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 时区数据库:
- 由 ZONEINFO 环境变量指定的目录或未压缩的 zip 文件
- 在 Unix 系统上,系统标准安装位置
- $GOROOT/lib/time/zoneinfo.zip
- time/tzdata 包(如果已被导入)
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。
Output: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())
}
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。
Output: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
}
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 则使用给定位置。
Output: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)
}
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 值)。
Output: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)
}
1257894000
2009-11-10 23:00:00 +0000 UTC
func UnixMicro
func UnixMicro(usec int64) Time
UnixMicro 返回给定 Unix 时间对应的本地 Time,
即自 1970 年 1 月 1 日 UTC 以来 usec 微秒。
Output: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)
}
1257894000000000
2009-11-10 23:00:00 +0000 UTC
func UnixMilli
func UnixMilli(msec int64) Time
UnixMilli 返回给定 Unix 时间对应的本地 Time,
即自 1970 年 1 月 1 日 UTC 以来 msec 毫秒。
Output: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)
}
1257894000000
2009-11-10 23:00:00 +0000 UTC
func (Time) Add
func (t Time) Add(d Duration) Time
Add 返回时间 t+d。
Output: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)
}
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 日的规范化形式。
Output: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)
}
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 之后。
Output: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)
}
year3000.After(year2000) = true
year2000.After(year3000) = false
func (Time) AppendBinary
func (t Time) AppendBinary(b []byte) ([]byte, error)
AppendBinary 实现 encoding.BinaryAppender 接口。
Output: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))
}
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
并返回扩展后的缓冲区。
Output: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))
}
Time: 11:00AM
func (Time) AppendText
func (t Time) AppendText(b []byte) ([]byte, error)
AppendText 实现 encoding.TextAppender 接口。
时间采用 RFC 3339 格式、带亚秒精度进行格式化。
如果该时间戳无法表示为有效的 RFC 3339
(例如年份超出范围),则返回一个错误。
Output: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)
}
t: 2025-04-01T15:30:45.123456789Z
func (Time) Before
func (t Time) Before(u Time) bool
Before 报告时间瞬间 t 是否在 u 之前。
Output: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)
}
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 所在的年、月、日。
Output: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)
}
year = 2000
month = February
day = 1
func (Time) Day
func (t Time) Day() int
Day 返回 t 指定的月内日。
Output: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)
}
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。
Output: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)
}
datesEqualUsingEqualOperator = false
datesEqualUsingFunction = true
func (Time) Format
func (t Time) Format(layout string) string
Format 返回时间值的文本表示,按照参数定义的布局进行格式化。 有关如何表示布局格式,请参见名为 Layout 的常量的文档。
Time.Format 的可执行示例详细演示了布局字符串的工作方式,是一个很好的参考。
Output: Output: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")
}
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")
}
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 源代码中打印的形式。
Output: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())
}
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) 可能返回
一个分钟非零的时间。
Output: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"))
}
}
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。
Output: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)
}
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)。
Output: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)
}
difference = 12h0m0s
func (Time) Truncate
func (t Time) Truncate(d Duration) Time
Truncate 返回将 t 向下舍入到 d 的倍数(自零时间起)后的结果。 如果 d <= 0,Truncate 返回去除任何单调时钟读数但其余保持不变的 t。
Truncate 将时间视为自零时间起的绝对时长进行运算;它不作用于时间
的展示形式。因此,取决于时间的 Location,Truncate(Hour) 可能返回
一个分钟非零的时间。
Output: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
}
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 位值,因此它在过去或未来数十亿年
内都有效。
Output: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
}
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 提供时区数据库的内嵌副本。 |