Пакет time языка программирования Go
Categories:
Календарные вычисления всегда основаны на григорианском календаре без учета високосных секунд.
Монотонные часы
Операционные системы предоставляют как “системные часы” (которые могут корректироваться для синхронизации времени), так и “монотонные часы” (которые не подвержены таким изменениям). Общее правило гласит: системные часы используются для определения текущего времени, а монотонные часы - для измерения временных интервалов. Вместо разделения API, в данном пакете Time, возвращаемый функцией time.Now, содержит показания как системных, так и монотонных часов. Последующие операции определения времени используют показания системных часов, тогда как операции измерения времени (в частности, сравнения и вычитания) используют показания монотонных часов.
Например, следующий код всегда вычисляет положительный интервал времени около 20 миллисекунд, даже если системные часы были изменены во время выполнения измеряемой операции:
start := time.Now()
... operation that takes 20 milliseconds ...
t := time.Now()
elapsed := t.Sub(start)
Другие идиомы, такие как time.Since(start)
, time.Until(deadline)
и time.Now().Before(deadline)
, также устойчивы к сбросам системных часов.
Остальная часть этого раздела содержит точные детали использования монотонных часов в операциях, но для работы с пакетом понимание этих деталей не требуется.
Особенности работы с монотонными часами
-
Функция
time.Now()
Возвращаемое значениеTime
содержит показания монотонных часов. Если времяt
включает монотонные часы:t.Add
добавляет длительность как к системным, так и к монотонным часамt.AddDate
,t.Round
иt.Truncate
работают только с системным временем и удаляют монотонные показанияt.In
,t.Local
иt.UTC
также удаляют монотонные показания- Стандартный способ удалить монотонные показания:
t = t.Round(0)
-
Сравнение времен
Если оба значенияt
иu
содержат монотонные показания:t.After(u)
,t.Before(u)
,t.Equal(u)
,t.Compare(u)
иt.Sub(u)
используют только монотонные часы- Если одно из значений не имеет монотонных показаний, используются системные часы
-
Особые случаи
- На некоторых системах монотонные часы останавливаются при переходе в спящий режим
- В таких случаях
t.Sub(u)
и аналогичные операции могут давать неточные результаты - Иногда требуется удалить монотонные показания для получения точных данных
-
Сериализация и форматирование
Монотонные показания:- Не включаются при сериализации (
GobEncode
,MarshalJSON
и др.) - Не имеют формата вывода в
t.Format
- Не создаются конструкторами (
Date
,Parse
,Unix
и др.)
- Не включаются при сериализации (
-
Особенности реализации
- Монотонные показания существуют только в значениях
Time
- Не входят в
Duration
или Unix-время (t.Unix
) - Оператор
==
сравнивает Location и монотонные показания
- Монотонные показания существуют только в значениях
-
Отладка
t.String()
показывает монотонные показания при их наличии- Различия в монотонных показаниях видны при выводе
Разрешение таймеров ¶
Разрешение таймеров зависит от:
- Версии Go
- Операционной системы
- Аппаратного обеспечения
Типичные значения:
- Unix: ~1 мс
- Windows 1803+: ~0.5 мс
- Старые версии Windows: ~16 мс (можно улучшить через
windows.TimeBeginPeriod
)
Константы
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.9999999Z07: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
(2 января, 15:04:05, 2006, в часовом поясе на семь часов западнее 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.
Year: "2006" "06"
Month: "Jan" "January" "01" "1"
Day of the week: "Mon" "Monday"
Day of the month: "2" "_2" "02"
Day of the year: "__2" "002"
Hour: "15" "3" "03" (PM or AM)
Minute: "4" "04"
Second: "5" "05"
AM/PM mark: "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"
форматируют или парсят время с миллисекундной точностью.
Некоторые допустимые форматы являются недопустимыми значениями времени для time.Parse
, из-за элементов вроде _
(пробельного дополнения) или Z
(информации о временной зоне).
const (
Nanosecond Duration = 1
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute
)
Стандартные длительности (Common durations)
Не существует определения для единиц измерения “День” или больше, чтобы избежать путаницы из-за перехода на летнее/зимнее время в разных часовых поясах.
Чтобы подсчитать количество единиц в Duration (длительности), выполните деление:
second := time.Second
fmt.Print(int64(second/time.Millisecond)) // prints 1000
Чтобы преобразовать целое количество единиц в Duration (длительность), выполните умножение:
seconds := 10
fmt.Print(time.Duration(seconds)*time.Second) // prints 10s
func After
func After(d Duration) <-chan Time
After
ожидает истечения указанной длительности d
, после чего отправляет текущее время в возвращаемом канале. Эквивалентно NewTimer(d).C
.
Изменения в Go 1.23:
В ранних версиях документация предупреждала, что таймер не освобождался сборщиком мусора до срабатывания, и рекомендовала использовать NewTimer
с ручным вызовом Timer.Stop
для оптимизации. Начиная с Go 1.23, сборщик мусора может освобождать неиспользуемые таймеры, даже если они не остановлены. Нет необходимости использовать NewTimer
вместо After
.
Пример использования:
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
приостанавливает выполнение текущей горутины как минимум на указанную длительность d
. Отрицательное или нулевое значение приводит к немедленному возврату.
Пример:
package main
import (
"time"
)
func main() {
time.Sleep(100 * time.Millisecond) // Пауза на 100 мс
}
func Tick
func Tick(d Duration) <-chan Time
Tick
— это удобная обёртка над NewTicker
, предоставляющая только канал с тиками. В отличие от NewTicker
, возвращает nil
при d <= 0
.
Изменения в Go 1.23:
Ранее документация указывала, что сборщик мусора не освобождает неостановленные тикеры, и рекомендовала использовать NewTicker
с Ticker.Stop
. В Go 1.23 сборщик может освобождать неиспользуемые тикеры, даже без вызова Stop
. Нет причин предпочитать NewTicker
, если достаточно Tick
.
Пример использования:
package main
import (
"fmt"
"time"
)
func statusUpdate() string { return "" }
func main() {
c := time.Tick(5 * time.Second) // Тикер каждые 5 секунд
for next := range c {
fmt.Printf("%v %s\n", next, statusUpdate())
}
}
Вот перевод технической документации пакета time
на русский язык:
Типы
type Duration
type Duration int64
Тип Duration представляет промежуток времени между двумя моментами в виде количества наносекунд int64. Представление ограничивает максимальную продолжительность примерно 290 годами.
Пример
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”.
Пример
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).
Пример
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()).
Пример
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 наносекунду.
Пример
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 возвращает продолжительность как число часов с плавающей точкой.
Пример
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 возвращает продолжительность как целое количество микросекунд.
Пример
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 возвращает продолжительность как целое количество миллисекунд.
func (Duration) Minutes
func (d Duration) Minutes() float64
Minutes возвращает продолжительность как число минут с плавающей точкой.
func (Duration) Nanoseconds
func (d Duration) Nanoseconds() int64
Nanoseconds возвращает продолжительность как целое количество наносекунд.
func (Duration) Round
func (d Duration) Round(m Duration) Duration
Round возвращает результат округления d до ближайшего кратного m. При округлении половинных значений округление выполняется от нуля. Если результат превышает максимальное (или минимальное) значение, которое может храниться в Duration, возвращается максимальная (или минимальная) продолжительность. Если m <= 0, Round возвращает d без изменений.
Пример
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 возвращает продолжительность как число секунд с плавающей точкой.
func (Duration) String
func (d Duration) String() string
String возвращает строковое представление продолжительности в виде “72h3m0.5s”. Ведущие нулевые единицы опускаются. В особом случае продолжительности менее одной секунды используют меньшие единицы (милли-, микро- или наносекунды), чтобы ведущая цифра была не нулевой. Нулевая продолжительность форматируется как “0s”.
Пример
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 без изменений.
Пример
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 {
// содержит неэкспортируемые поля
}
Тип Location отображает моменты времени в часовом поясе, используемом в этот момент. Обычно Location представляет набор смещений времени, используемых в географическом регионе. Для многих Location смещение времени варьируется в зависимости от того, действует ли летнее время в данный момент.
Location используется для предоставления часового пояса в печатном значении Time и для вычислений, включающих интервалы, которые могут пересекать границы перехода на летнее время.
Пример
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).
Пример
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 в следующих местах по порядку:
- Каталог или распакованный zip-файл, указанный переменной окружения ZONEINFO
- В Unix-системах - стандартное системное местоположение установки
- $GOROOT/lib/time/zoneinfo.zip
- Пакет time/tzdata, если он был импортирован
Пример
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 с заданным именем, инициализированный из данных в формате базы данных часовых поясов IANA. Данные должны быть в формате стандартного файла часового пояса IANA (например, содержимое /etc/localtime в Unix-системах).
func (*Location) String
func (l *Location) String() string
String возвращает описательное имя для информации о часовом поясе, соответствующее аргументу name для LoadLocation или FixedZone.
type Month
type Month int
Month определяет месяц года (January = 1, …).
Пример
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 // Канал, по которому доставляются "тики"
// содержит неэкспортируемые поля
}
Ticker содержит канал, который доставляет “тики” часов с заданными интервалами.
Объяснение Ticker
Тип Ticker
в Go
Тип Ticker
в пакете time
представляет собой механизм для получения повторяющихся сигналов (“тиков”) через регулярные промежутки времени. Это полезный инструмент для выполнения периодических операций.
Основные характеристики:
-
Структура:
type Ticker struct { C <-chan Time // Канал для получения тиков // скрытые поля }
- Поле
C
- это канал только для чтения (<-chan
), по которому будут приходить значения времени при каждом тике
- Поле
-
Назначение:
- Регулярное выполнение кода (например, каждые 5 секунд)
- Создание таймеров с повторяющимся срабатыванием
- Периодический опрос или проверка состояния
- Реализация heartbeat-механизмов
-
Типичное использование:
ticker := time.NewTicker(1 * time.Second) defer ticker.Stop() for { select { case t := <-ticker.C: fmt.Println("Tick at", t) // выполнить периодическую операцию } }
-
Особенности:
- Тикер продолжает работать, пока не будет явно остановлен
- Интервал между тиками остается постоянным (в отличие от
time.Sleep
в цикле) - Если получатель не успевает обрабатывать тики, они могут быть пропущены
-
Важные методы:
NewTicker(d Duration)
- создает новый тикерStop()
- останавливает тикерReset(d Duration)
- изменяет интервал (добавлен в Go 1.15)
Когда использовать:
- Для регулярных фоновых задач (например, обновление кэша)
- Для реализации таймаутов с повторением
- Для периодического сбора метрик или логирования
- В долгоживущих горутинах для поддержания активности
Пример реального использования:
func startMonitoring() {
ticker := time.NewTicker(5 * time.Minute)
defer ticker.Stop()
for {
select {
case <-ticker.C:
err := checkSystemHealth()
if err != nil {
log.Printf("Health check failed: %v", err)
}
case <-ctx.Done():
return // завершение при отмене контекста
}
}
}
Важно всегда вызывать Stop()
для тикера, когда он больше не нужен, чтобы избежать утечек ресурсов. В современных версиях Go (1.23+) сборщик мусора может автоматически очищать неиспользуемые тикеры, но явная остановка остается хорошей практикой.
func NewTicker
func NewTicker(d Duration) *Ticker
NewTicker создает новый Ticker, содержащий канал, который будет отправлять текущее время на канал после каждого тика. Период тиков задается аргументом duration. Ticker будет корректировать интервал времени или пропускать тики для компенсации медленных получателей. Длительность d должна быть больше нуля; в противном случае NewTicker вызовет панику.
Пример
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 останавливает тикер и устанавливает его период в заданную продолжительность. Следующий тик придет после истечения нового периода. Длительность d должна быть больше нуля; в противном случае Reset вызовет панику.
func (*Ticker) Stop
func (t *Ticker) Stop()
Stop выключает тикер. После Stop больше не будет отправляться тиков. Stop не закрывает канал, чтобы предотвратить ошибочное чтение “тика” параллельной горутиной.
type Time
type Time struct {
// содержит неэкспортируемые поля
}
Time представляет момент времени с наносекундной точностью.
Программы, использующие время, обычно должны хранить и передавать его как значения, а не указатели. То есть переменные времени и поля структур должны быть типа time.Time, а не *time.Time.
Значение Time может использоваться несколькими горутинами одновременно, за исключением того, что методы Time.GobDecode, Time.UnmarshalBinary, Time.UnmarshalJSON и Time.UnmarshalText не являются безопасными для конкурентного использования.
Моменты времени можно сравнивать с помощью методов Time.Before, Time.After и Time.Equal. Метод Time.Sub вычитает два момента, производя Duration. Метод Time.Add добавляет Time и Duration, производя Time.
Нулевое значение типа Time - January 1, year 1, 00:00:00.000000000 UTC. Поскольку это время вряд ли встретится на практике, метод Time.IsZero дает простой способ обнаружения времени, которое не было инициализировано явно.
Каждое время имеет связанный Location. Методы Time.Local, Time.UTC и Time.In возвращают Time с конкретным Location. Изменение Location значения Time с помощью этих методов не изменяет фактический момент, который оно представляет, только часовой пояс, в котором оно интерпретируется.
func Date
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time
Date возвращает Time, соответствующее
в соответствующем часовом поясе для этого времени в заданном местоположении.
Значения month, day, hour, min, sec и nsec могут быть вне их обычных диапазонов и будут нормализованы во время преобразования. Например, 32 октября преобразуется в 1 ноября.
Переход на летнее время пропускает или повторяет моменты времени. Например, в США March 13, 2011 2:15am никогда не происходило, а November 6, 2011 1:15am произошло дважды. В таких случаях выбор часового пояса, а следовательно и времени, не определен однозначно. Date возвращает время, которое корректно в одном из двух участвующих в переходе часовых поясов, но не гарантирует, в каком именно.
Date вызывает панику, если loc равен nil.
Пример
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, чтобы понять, как представить формат. Второй аргумент должен быть разбираемым с использованием строки формата (layout), предоставленной в качестве первого аргумента.
Пример
package main
import (
"fmt"
"time"
)
func main() {
// Пример с Time.Format содержит подробное описание того, как
// определять строку формата для разбора значения time.Time;
// Parse и Format используют одну и ту же модель для описания
// входных и выходных данных.
// longForm демонстрирует на примере, как эталонное время будет представлено
// в желаемом формате.
const longForm = "Jan 2, 2006 at 3:04pm (MST)"
t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
fmt.Println(t)
// shortForm - это альтернативный способ представления эталонного времени
// в желаемом формате; он не содержит информации о часовом поясе.
// Примечание: без явного указания пояса возвращает время в UTC.
const shortForm = "2006-Jan-02"
t, _ = time.Parse(shortForm, "2013-Feb-03")
fmt.Println(t)
// Некоторые допустимые форматы могут быть недопустимыми значениями времени,
// из-за спецификаторов формата, таких как _ для заполнения пробелами
// и Z для информации о часовом поясе.
// Например, формат RFC3339 2006-01-02T15:04:05Z07:00
// содержит как Z, так и смещение часового пояса, чтобы обрабатывать оба варианта:
// 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("ошибка", err) // Возвращает ошибку, так как формат не является допустимым значением времени
}
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 использует заданное местоположение.
Пример
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 возвращает локальное Time, соответствующее заданному Unix-времени, sec секунд и nsec наносекунд с 1 января 1970 UTC. Допустимо передавать nsec вне диапазона [0, 999999999]. Не все значения sec имеют соответствующее значение времени. Одним из таких значений является 1«63-1 (максимальное значение int64).
Пример
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 возвращает локальное Time, соответствующее заданному Unix-времени, usec микросекунд с 1 января 1970 UTC.
Пример
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 возвращает локальное Time, соответствующее заданному Unix-времени, msec миллисекунд с 1 января 1970 UTC.
func (Time) Add
func (t Time) Add(d Duration) Time
Add возвращает время t+d.
Пример
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. Например, AddDate(-1, 2, 3), примененное к 1 января 2011, возвращает 4 марта 2010.
Пример
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.
Пример
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. Добавляет бинарное представление времени в срез байт b
и возвращает расширенный буфер.
func (Time) AppendFormat
func (t Time) AppendFormat(b []byte, layout string) []byte
AppendFormat аналогичен Time.Format, но добавляет текстовое представление времени в буфер b
и возвращает расширенный буфер. Формат определяется параметром layout
.
Пример
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 с субсекундной точностью и добавляет в буфер b
. Возвращает ошибку, если время невозможно представить в корректном формате RFC 3339 (например, при выходе года за допустимый диапазон).
func (Time) Before
func (t Time) Before(u Time) bool
Before сообщает, является ли момент времени t до u.
Пример
ackage 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.
Пример
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.
Пример
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 равны.
Пример
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. Смотрите документацию для константы Layout, чтобы понять, как представить формат.
Пример
package main
import (
"fmt"
"time"
)
func main() {
// Разбираем строку времени в стандартном Unix формате
t, err := time.Parse(time.UnixDate, "Wed Feb 25 11:06:39 PST 2015")
if err != nil { // Всегда проверяем ошибки, даже если они не должны возникать
panic(err)
}
tz, err := time.LoadLocation("Asia/Shanghai")
if err != nil { // Всегда проверяем ошибки
panic(err)
}
// Метод Stringer типа time.Time удобен для вывода без указания формата
fmt.Println("формат по умолчанию:", t)
// Предопределенные константы пакета реализуют распространенные форматы
fmt.Println("Unix формат:", t.Format(time.UnixDate))
// Часовой пояс, связанный со значением времени, влияет на его вывод
fmt.Println("То же время в UTC:", t.UTC().Format(time.UnixDate))
fmt.Println("в Шанхае с секундами:", t.In(tz).Format("2006-01-02T15:04:05 -070000"))
fmt.Println("в Шанхае с секундами и двоеточиями:", t.In(tz).Format("2006-01-02T15:04:05 -07:00:00"))
// Оставшаяся часть функции демонстрирует свойства
// строки формата, используемой в Format
// Строка формата, используемая функциями Parse и Format,
// на примере показывает, как должно быть представлено эталонное время.
// Важно подчеркнуть, что нужно показывать, как форматируется именно эталонное время,
// а не произвольное время пользователя. Таким образом, каждая строка формата -
// это представление временной метки:
// Jan 2 15:04:05 2006 MST
// Простой способ запомнить это значение - заметить, что при таком порядке
// оно содержит следующие значения (соответствующие элементам выше):
// 1 2 3 4 5 6 -7
// Ниже показаны некоторые особенности.
// Большинство использований Format и Parse применяют константные строки формата,
// такие как определенные в этом пакете, но интерфейс гибкий,
// как показывают следующие примеры.
// Вспомогательная функция для красивого вывода примеров
do := func(name, layout, want string) {
got := t.Format(layout)
if want != got {
fmt.Printf("ошибка: для %q получено %q; ожидалось %q\n", layout, got, want)
return
}
fmt.Printf("%-16s %q дает %q\n", name, layout, got)
}
// Заголовок для вывода
fmt.Printf("\nФорматы:\n\n")
// Простые начальные примеры
do("Полная дата", "Mon Jan 2 15:04:05 MST 2006", "Wed Feb 25 11:06:39 PST 2015")
do("Краткая дата", "2006/01/02", "2015/02/25")
// Час эталонного времени - 15 (3PM). Формат может выражать это
// любым способом, и так как наше значение утреннее, мы должны видеть его
// в AM-формате. Покажем оба варианта в одной строке формата. И в нижнем регистре.
do("AM/PM", "3PM==3pm==15h", "11AM==11am==11h")
// При разборе, если за секундами следует точка
// и цифры, это воспринимается как доля секунды, даже если
// строка формата не включает представление долей секунды.
// Добавим доли секунды к нашему значению времени
t, err = time.Parse(time.UnixDate, "Wed Feb 25 11:06:39.1234 PST 2015")
if err != nil {
panic(err)
}
// Доли секунды не отображаются, если строка формата не содержит
// их представления
do("Без долей секунды", time.UnixDate, "Wed Feb 25 11:06:39 PST 2015")
// Доли секунды можно вывести, добавив последовательность 0 или 9
// после точки в значении секунд в строке формата.
// Если используются 0, выводится указанное количество знаков.
// Обратите внимание, что вывод содержит завершающий ноль.
do("0 для долей секунды", "15:04:05.00000", "11:06:39.12340")
// Если используются 9, завершающие нули отбрасываются.
do("9 для долей секунды", "15:04:05.99999999", "11:06:39.1234")
}
формат по умолчанию: 2015-02-25 11:06:39 -0800 PST
Unix формат: Wed Feb 25 11:06:39 PST 2015
То же время в UTC: Wed Feb 25 19:06:39 UTC 2015
в Шанхае с секундами: 2015-02-26T03:06:39 +080000
в Шанхае с секундами и двоеточиями: 2015-02-26T03:06:39 +08:00:00
Форматы:
Полная дата "Mon Jan 2 15:04:05 MST 2006" дает "Wed Feb 25 11:06:39 PST 2015"
Краткая дата "2006/01/02" дает "2015/02/25"
AM/PM "3PM==3pm==15h" дает "11AM==11am==11h"
Без долей секунды "Mon Jan _2 15:04:05 MST 2006" дает "Wed Feb 25 11:06:39 PST 2015"
0 для долей секунды "15:04:05.00000" дает "11:06:39.12340"
9 для долей секунды "15:04:05.99999999" дает "11:06:39.1234"
Пример (Pad)
package main
import (
"fmt"
"time"
)
func main() {
// Разбор строки времени в стандартном Unix формате
t, err := time.Parse(time.UnixDate, "Sat Mar 7 11:06:39 PST 2015")
if err != nil { // Всегда проверяем ошибки, даже если они маловероятны
panic(err)
}
// Вспомогательная функция для форматированного вывода примеров
do := func(name, layout, want string) {
got := t.Format(layout)
if want != got {
fmt.Printf("ошибка: для формата %q получено %q; ожидалось %q\n", layout, got, want)
return
}
fmt.Printf("%-16s %q → %q\n", name, layout, got)
}
// Предопределенная константа Unix использует подчеркивание для выравнивания дня
do("Unix формат", time.UnixDate, "Sat Mar 7 11:06:39 PST 2015")
// Для выравнивания значений переменной ширины (например, дня месяца)
// используйте _ вместо пробела в строке формата
do("Без выравнивания", "<2>", "<7>")
// Подчеркивание добавляет пробел для однозначных чисел
do("С пробелом", "<_2>", "< 7>")
// "0" добавляет нулевое заполнение для однозначных чисел
do("С нулями", "<02>", "<07>")
// Если значение уже имеет нужную ширину, заполнение не применяется
// Например, секунды (39) не требуют заполнения, а минуты (06) - требуют
do("Пропуск заполнения", "04:05", "06:39")
}
Unix формат "Mon Jan _2 15:04:05 MST 2006" → "Sat Mar 7 11:06:39 PST 2015"
Без выравнивания "<2>" → "<7>"
С пробелом "<_2>" → "< 7>"
С нулями "<02>" → "<07>"
Пропуск заполнения "04:05" → "06:39"
func (Time) GoString
func (t Time) GoString() string
GoString реализует fmt.GoStringer и форматирует t для вывода в исходном коде Go.
Пример
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 возвращает год и номер недели ISO 8601, в которые происходит t. Неделя находится в диапазоне от 1 до 53. 1-3 января года n могут принадлежать 52 или 53 неделе года n-1, а 29-31 декабря могут принадлежать 1 неделе года n+1.
func (Time) In
func (t Time) In(loc *Location) Time
In возвращает копию t, представляющую тот же момент времени, но с информацией о местоположении, установленной в loc для целей отображения.
In вызывает панику, если loc равен nil.
func (Time) IsDST
func (t Time) IsDST() bool
IsDST сообщает, находится ли время в настроенном местоположении в летнем времени.
func (Time) IsZero
func (t Time) IsZero() bool
IsZero сообщает, представляет ли t нулевой момент времени, 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, лишенное любого монотонного показания часов, но в остальном неизменное.
Пример
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 возвращает время, отформатированное с использованием строки формата
Если время имеет монотонное показание часов, возвращаемая строка включает конечное поле “m=±
Пример
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", string(withNanoseconds))
fmt.Printf("withoutNanoseconds = %v\n", string(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, будет возвращена максимальная (или минимальная) продолжительность.
Пример
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, лишенное любого монотонного показания часов, но в остальном неизменное.
Пример
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 возвращает t с местоположением, установленным в UTC.
func (Time) Unix
func (t Time) Unix() int64
Unix возвращает t как Unix-время, количество секунд, прошедших с 1 января 1970 UTC. Результат не зависит от местоположения, связанного с t.
Пример
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-время, количество микросекунд, прошедших с 1 января 1970 UTC.
func (Time) UnixMilli
func (t Time) UnixMilli() int64
UnixMilli возвращает t как Unix-время, количество миллисекунд, прошедших с 1 января 1970 UTC.
func (Time) UnixNano
func (t Time) UnixNano() int64
UnixNano возвращает t как Unix-время, количество наносекунд, прошедших с 1 января 1970 UTC.
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. Местоположение возвращаемых времен будет таким же, как у t.
type Timer
type Timer struct {
C <-chan Time
// содержит неэкспортируемые поля
}
Timer представляет единичное событие. Когда Timer истекает, текущее время будет отправлено на C, если только Timer не был создан с помощью AfterFunc. Timer должен быть создан с помощью NewTimer или AfterFunc.
func AfterFunc
func AfterFunc(d Duration, f func()) *Timer
AfterFunc ждет истечения продолжительности, а затем вызывает f в своей собственной горутине. Возвращает Timer, который можно использовать для отмены вызова с помощью его метода Stop. Поле C возвращаемого Timer не используется и будет nil.
func NewTimer
func NewTimer(d Duration) *Timer
NewTimer создает новый Timer, который отправит текущее время на свой канал после как минимум продолжительности d.
func (*Timer) Reset
func (t *Timer) Reset(d Duration) bool
Reset изменяет таймер на истечение после продолжительности d. Возвращает true, если таймер был активен, false, если таймер уже истек или был остановлен.
func (t *Timer) Reset(d Duration) bool
Reset
изменяет таймер для срабатывания через интервал d
. Возвращает true
, если таймер был активен, и false
, если таймер уже сработал или был остановлен.
Для функционального таймера, созданного через AfterFunc(d, f)
:
Reset
либо переносит время выполненияf
(возвращаетtrue
)- либо планирует новое выполнение
f
(возвращаетfalse
)
При возврате false
:
Reset
не ожидает завершения предыдущего выполненияf
- Не гарантируется отсутствие конкурентного выполнения предыдущей и новой версий
f
- Для контроля завершения нужно реализовать собственную синхронизацию
Для канального таймера (создан через NewTimer
), начиная с Go 1.23:
- Гарантируется, что после
Reset
каналt.C
не получит значений от предыдущих настроек - Если программа еще не читала из
t.C
и таймер активен,Reset
гарантированно вернетtrue
До Go 1.23 безопасное использование требовало:
- Вызова
Timer.Stop()
- Явного чтения из канала (если
Stop
вернулаfalse
)
func (*Timer) Stop
func (t *Timer) Stop() bool
Stop
предотвращает срабатывание таймера. Возвращает:
true
- если таймер был успешно остановленfalse
- если таймер уже сработал или был остановлен
Для функционального таймера (AfterFunc
):
- При
false
функцияf
уже запущена в отдельной горутине Stop
не ожидает завершенияf
- Для контроля завершения нужна дополнительная синхронизация
Для канального таймера (Go 1.23+):
- После
Stop
чтение изt.C
гарантированно блокируется - Не будет получено “устаревших” значений времени
- Если таймер активен и канал не читался,
Stop
гарантированно вернетtrue
До Go 1.23 требовалось:
- При
false
выполнять дополнительное чтение<-t.C
для очистки канала
type Weekday
type Weekday int
Weekday определяет день недели (Sunday = 0, …).
Константы:
const (
Sunday Weekday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
func (Weekday) String
func (d Weekday) String() string
String возвращает английское название дня (“Sunday”, “Monday”, …).
Пакет time/tzdata
Пакет tzdata предоставляет встроенную копию базы данных часовых поясов. Если этот пакет импортируется в любое место программы, то, если пакет времени не может найти файлы tzdata
в системе, он будет использовать эту встроенную информацию.
Импорт этого пакета увеличит размер программы примерно на 450 КБ.
Обычно этот пакет должен импортироваться основным пакетом программы, а не библиотекой. Библиотеки обычно не должны решать, включать ли базу данных часовых поясов в программу.
Этот пакет будет автоматически импортирован, если вы построите с -tags timetzdata
.