<div><img src="https://top-fwz1.mail.ru/counter?id=3548135;js=na" style="position:absolute;left:-9999px;" alt="Top.Mail.Ru" /></div>
Бесплатный перенос IT-инфраструктуры в облако

Работа с датой и временем в Go с помощью пакета time

Миша Курушин
Миша Курушин
Технический писатель
12 декабря 2024 г.
107
20 минут чтения
Средний рейтинг статьи: 5

Язык программирования Go (Golang), как и многие другие, имеет встроенный пакет time, который предоставляет специальные типы и методы для работы с датой и временем.

Полную и исчерпывающую информацию о пакете time можно найти на специальной странице официальной документации.

В этом руководстве мы рассмотрим базовые аспекты работы со временем в языке программирования Go.

Все показанные примеры запускались на облачном сервере Timeweb Cloud под управлением операционной системы Ubuntu 22.04 с использованием интерпретатора Go версии 1.21.3.

Предполагается, что вы уже знакомы с основами языка Go и знаете, как запускать созданные скрипты через соответствующую команду интерпретатора:

go run script.go

Также стоит упомянуть несколько отдельных руководств, опубликованных в официальном блоге Timeweb Cloud, которые подробно описывают установку Golang на популярные операционные системы:

Парсинг, форматирование и создание

Прежде чем переходить к работе с временем, важно понять важную особенность форматирования времени в Go.

В большинстве языков программирования формат даты и времени указывается с использованием специальных символов, вместо которых подставляются значения дня, месяца, года, часа, минуты, секунды.

Однако в языке Go все иначе. Вместо специальных символом используются значения даты и времени по умолчанию, представляющие собой возрастающую последовательность значений — 01-02-03-04-05-06.

Этот набор чисел означает следующее:

  • 1-й месяц в году (Январь)
  • 2-е число в месяце
  • 3-й час в 12-часовом формате (p.m.)
  • 4-я минута в 12-часовом формате (p.m.)
  • 5-я секунда в 12-часовом формате (p.m.)
  • 6-й год 21 века

Таким образом получается 2 января 15:04:05 2006 года, или 2 января 03:04:05 PM 2006 года, или 02.01.2006 03:04:05 PM.

Важно помнить, что это значение — ничто иное, как обычная возрастающая последовательность чисел. В ней нет особого сакрального смысла.

Таким образом, эти дата и время являются предопределенным макетом для работы с любыми явно указываемыми значениями даты и времени.

Например, можно привести абстрактный (синтаксически не связанный с Go) пример псевдокода:

времяСейчас = время.текущее()

консоль.написать("Текущая дата: ", времяСейчас.форматировать("%Д.%М.%Г"))
консоль.написать("Текущее время: ", времяСейчас.форматировать("%Ч:%М"))
консоль.написать("Текущие дата и время: ", времяСейчас.форматировать("%Д.%М.%Г %Ч:%М"))

И тогда в нашей псевдоконсоли появится следующий псевдовывод:

Текущая дата: 26.11.2024
Текущее время: 14:05
Текущие дата и время: 26.11.2024 14:05

Именно так устроено форматирование даты и времени в большинстве языков программирования.

В случае же с Go псевдокод выглядел бы так:

времяСейчас = время.текущее()

консоль.написать("Текущая дата: ", времяСейчас.форматировать("02.01.2006"))
консоль.написать("Текущее время: ", времяСейчас.форматировать("03:04"))
консоль.написать("Текущие дата и время: ", времяСейчас.форматировать("02.01.2006 03:04"))

При этом консольный вывод был бы аналогичным.

То есть стандартные значения шаблона даты и времени автоматически заменяются на конкретные значения даты и времени.

При этом значения шаблона имеют определенную вариативность Например, 01 месяц можно также указывать в виде слова Jan.

Благодаря этому язык Go позволяет задавать шаблоны в более понятном и человекочитаемом виде.

cloud

Парсинг

Использование времени в Go начинается с его явного задания. Сделать это можно через функцию парсинга времени:

package main

import (
	"fmt" // пакет, содержащий функции для работы с консолью
	"time" // пакет, содержащий функции для работы с временем
	"reflect" // пакет, содержащий функцию для определения типа
)

func main() {
	timeLayout := "2006-01-02" // шаблон времени
	timeValue:= "2024-11-16" // значение времени

	timeVariable, err := time.Parse(timeLayout, timeValue) // парсинг значения времени по шаблону
	if err != nil { panic(err) } // обработка возможной ошибки парсинга

	fmt.Println(timeVariable) // вывод значения переменной времени в консоль
	fmt.Println(reflect.TypeOf(timeVariable)) // вывод типа переменной времени в консоль
}

В терминале появится вывод с результатом работы скрипта:

2024-11-16 00:00:00 +0000 UTC
time.Time

Обратите внимание, что после парсинга создается переменная типа time.Time, которая содержит указанное во время парсинга значение времени в своем внутреннем формате.

В показанном примере шаблон и значение времени можно было бы заменить на другую равнозначную запись:

func main() {
timeLayout := "2006-Jan-02"
timeValue:= "2024-Nov-16"
...

Итоговый результат остался бы таким же.

Во время парсинга в качестве дополнительного параметра можно указать временную зону, которую также именуют часовым поясом:

package main

import (
	"fmt"
	"time"
)

func main() {
	// Local

	timeLocation, err := time.LoadLocation("Local")
	if err != nil { panic(err) }

	timeVariable, err := time.ParseInLocation("2006-01-02 15:04", "2024-11-16 07:45", timeLocation)
	if err != nil { panic(err) }

	fmt.Println("Local: ", timeVariable)

	// Asia/Novosibirsk

	timeLocation, err = time.LoadLocation("Asia/Novosibirsk")
	if err != nil { panic(err) }

	timeVariable, err = time.ParseInLocation("2006-01-02 15:04", "2024-11-16 07:45", timeLocation)
	if err != nil { panic(err) }
 
	fmt.Println("Asia/Novosibirsk: ", timeVariable)

	// Europe/Moscow

	timeLocation, err = time.LoadLocation("Europe/Moscow")
	if err != nil { panic(err) }

	timeVariable, err = time.ParseInLocation("2006-01-02 15:04", "2024-11-16 07:45", timeLocation)
	if err != nil { panic(err) }
 
	fmt.Println("Europe/Moscow: ", timeVariable)
}

Консольный вывод этого скрипта будет таким:

Local:  2024-11-16 07:45:00 +0000 UTC
Asia/Novosibirsk:  2024-11-16 07:45:00 +0700 +07
Europe/Moscow:  2024-11-16 07:45:00 +0300 MSK

При этом вместо явно созданной переменной часового пояса можно использовать предопределенную константу:

package main

import (
	"fmt"
	"time"
)

func main() {
	// time.LoadLocation("Local")

	timeLocation, err := time.LoadLocation("Local")
	if err != nil { panic(err) }

	timeVariable, err := time.ParseInLocation("2006-01-02 15:04", "2024-11-16 07:45", timeLocation)
	if err != nil { panic(err) }

	fmt.Println(timeVariable)

	// time.Local

	timeVariable, err = time.ParseInLocation("2006-01-02 15:04", "2024-11-16 07:45", time.Local)
	if err != nil { panic(err) }

	fmt.Println(timeVariable)
}

В этом случае полные значения даты и времени в обоих вариантах будут идентичными:

2024-11-16 07:45:00 +0000 UTC
2024-11-16 07:45:00 +0000 UTC

Полный список существующих временных зон можно посмотреть в так называемой «Базе данных временных зон» (tz database).

Идентификатор временной зоны указываются с помощью названий двух регионов, записанных через косую черту. Например, так:

  • Europe/Moscow
  • Asia/Dubai
  • US/Alaska

Image1

Визуализация часовых поясов tz database

Форматирование

Уже созданную переменную времени можно отформатировать, чтобы представить ее значение в определенном текстовом виде.

Таким образом, переменная типа time.Time имеет встроенные методы для преобразования даты и времени в переменную типа string:

package main

import (
	"fmt"
	"time"
)

func main() {
	timeLayout := "2006-01-02 15:04:05"
	timeValue := "2024-11-15 12:45:20"
 
	timeVariable, err := time.Parse(timeLayout, timeValue)
	if err != nil { panic(err) }

	fmt.Print("\r", "ДАТА", "\r\n")

	fmt.Println(timeVariable.Format("2006-01-02"))
	fmt.Println(timeVariable.Format("01/02/06"))
	fmt.Println(timeVariable.Format("01/02/2006"))
	fmt.Println(timeVariable.Format("20060102"))
	fmt.Println(timeVariable.Format("010206"))
	fmt.Println(timeVariable.Format("January 02, 2006"))
	fmt.Println(timeVariable.Format("02 January 2006"))
	fmt.Println(timeVariable.Format("02-Jan-2006"))
	fmt.Println(timeVariable.Format("Jan-02-06"))
	fmt.Println(timeVariable.Format("Jan-02-2006"))
	fmt.Println(timeVariable.Format("06"))
	fmt.Println(timeVariable.Format("Mon"))
	fmt.Println(timeVariable.Format("Monday"))
	fmt.Println(timeVariable.Format("Jan-06"))

	fmt.Print("\r", "ВРЕМЯ", "\r\n")

	fmt.Println(timeVariable.Format("15:04"))
	fmt.Println(timeVariable.Format("15:04:05"))
	fmt.Println(timeVariable.Format("3:04 PM"))
	fmt.Println(timeVariable.Format("03:04:05 PM"))

	fmt.Print("\r", "ДАТА и ВРЕМЯ", "\r\n")

	fmt.Println(timeVariable.Format("2006-01-02T15:04:05"))
	fmt.Println(timeVariable.Format("2 Jan 2006 15:04:05"))
	fmt.Println(timeVariable.Format("2 Jan 2006 15:04"))
	fmt.Println(timeVariable.Format("Mon, 2 Jan 2006 15:04:05 MST"))

	fmt.Print("\r", "ПРЕДОПРЕДЕЛЕННЫЕ", "\r\n")

	fmt.Println(timeVariable.Format(time.RFC1123)) // предопределенный формат
	fmt.Println(timeVariable.Format(time.Kitchen)) // предопределенный формат
	fmt.Println(timeVariable.Format(time.Stamp)) // предопределенный формат
	fmt.Println(timeVariable.Format(time.DateOnly)) // предопределенный формат
}

В результате работы этого скрипта в терминале появится вывод, содержащий различные вариации возможных форматов даты и времени:

ДАТА

2024-11-15
11/15/24
11/15/2024
20241115
111524
November 15, 2024
15 November 2024
15-Nov-2024
Nov-15-24
Nov-15-2024
24
Fri
Friday
Nov-24

ВРЕМЯ

12:45
12:45:20
12:45 PM
12:45:20 PM

ДАТА и ВРЕМЯ

2024-11-15T12:45:20
15 Nov 2024 12:45:20
15 Nov 2024 12:45
Fri, 15 Nov 2024 12:45:20 UTC

ПРЕДОПРЕДЕЛЕННЫЕ

Fri, 15 Nov 2024 12:45:20 UTC
12:45PM
Nov 15 12:45:20
2024-11-15

Обратите внимание на несколько последних форматов, которые предопределены в виде константных значений. Полный список этих констант можно найти в отдельном разделе на странице пакета time в официальной документации.

time.Layout

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

time.ANSIC

Mon Jan _2 15:04:05 2006

time.UnixDate

Mon Jan _2 15:04:05 MST 2006

time.RubyDate

Mon Jan 02 15:04:05 -0700 2006

time.RFC822

02 Jan 06 15:04 MST

time.RFC822Z

02 Jan 06 15:04 -0700

time.RFC850

Monday, 02-Jan-06 15:04:05 MST

time.RFC1123

Mon, 02 Jan 2006 15:04:05 MST

time.RFC1123Z

Mon, 02 Jan 2006 15:04:05 -0700

time.RFC3339

2006-01-02T15:04:05Z07:00

time.RFC3339Nano

2006-01-02T15:04:05.999999999Z07:00

time.Kitchen

3:04PM

time.Stamp

Jan _2 15:04:05

time.StampMilli

Jan _2 15:04:05.000

time.StampMicro

Jan _2 15:04:05.000000

time.StampNano

Jan _2 15:04:05.000000000

time.DateTime

2006-01-02 15:04:05

time.DateOnly

2006-01-02

time.TimeOnly

15:04:05

Еще один способ отформатировать дату и время — конвертация в Unix:

package main

import (
	"fmt"
	"time"
	"reflect"
)

func main() {
	timeVariable := time.Unix(350, 50) // устанавливаем UNIX-время на 350 секунд и 50 наносекунд от 1 января 1970 года 00:00:00

	fmt.Println("Время:", timeVariable) // вывод времени в UTC-формате

	timeUnix := timeVariable.Unix()
	timeUnixNano := timeVariable.UnixNano()

	fmt.Println("Время (UNIX, секунды):", timeUnix) // вывод времени в UNIX-формате (секунды)
	fmt.Println("Время (UNIX, наносекунды):", timeUnixNano) // вывод времени в UNIX-формате (наносекунды)
	fmt.Println("Время (тип):", reflect.TypeOf(timeUnix)) // вывод типа переменной с UNIX-временем
}

После запуска этого скрипта в терминале появится следующий вывод:

Время:  1970-01-01 00:05:50.00000005 +0000 UTC
Время (UNIX, секунды):  350
Время (UNIX, наносекунды):  350000000050
Время (тип):  int64

Обратите внимание, что переменная, созданная для хранения UNIX-значения времени, имеет тип int64, а не time.Time.

Таким образом с помощью форматирования можно выполнять конвертацию из строкового времени в Unix и обратно:

package main

import (
	"fmt"
	"time"
)

func main() {
	timeString, _ := time.Parse("2006-01-02 15:04:05", "2024-11-15 12:45:20")
	fmt.Println(timeString.Unix())

	timeUnix := time.Unix(12345, 50)
	fmt.Println(timeUnix.Format("2006-01-02 15:04:05"))
}

Консольным выводом этого скрипта станут результаты конвертаций в Unix и из него:

1731674720
1970-01-01 03:25:45

Создание

В языке Go есть более тривиальный способ создания переменной time.Time через явное задание параметров даты и времени:

package main

import (
	"fmt"
	"time"
)

func main() {
	timeLocation, _ := time.LoadLocation("Europe/Vienna")

	// год, месяц, день, час, минута, секунда, наносекунд, часовой пояс
	timeVariable := time.Date(2024, 11, 20, 12, 30, 45, 50, timeLocation)

	fmt.Print(timeVariable)
}

После запуска скрипта в терминале появится следующий вывод:

2024-11-20 12:30:45.00000005 +0100 CET

Текущие дата и время

Помимо ручной установки произвольных даты и времени можно установить текущие дату и время:

package main

import (
	"fmt"
	"time"
	"reflect"
)

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

	fmt.Println(timeNow)
	fmt.Println(timeNow.Format(time.DateTime))
	fmt.Println(timeNow.Unix())
	fmt.Println(reflect.TypeOf(timeNow))
}

После запуска этого скрипта в терминале появится следующий вывод:

2024-11-27 17:08:18.195495127 +0000 UTC m=+0.000035621
2024-11-27 17:08:18
1732727298
time.Time

Как видно, в результате выполнения функции time.Now() создается уже знакомая переменная time.Time, значения которой можно произвольно форматировать.

Извлечение параметров

Переменная time.Time состоит из набор параметров, которые в совокупности образуют дату и время:

  • Год
  • Месяц
  • Число
  • День недели
  • Час
  • Минута
  • Секунда
  • Наносекунда
  • Часовой пояс

Соответственно, язык Go обладает набором методов для извлечения и изменения каждого из этих параметров.

Чаще всего необходимо просто узнать конкретные параметры уже созданной переменной времени:

package main

import (
	"fmt"
	"time"
	"reflect"
)
 
func main() {
	timeLayout := "2006-01-02 15:04:05"
	timeValue := "2024-11-15 12:45:20"
 
	timeVariable, _ := time.Parse(timeLayout, timeValue)

	fmt.Println("Год:", timeVariable.Year())
	fmt.Println("Месяц:", timeVariable.Month())
	fmt.Println("Число:", timeVariable.Day())
	fmt.Println("День недели:", timeVariable.Weekday())
	fmt.Println("Час:", timeVariable.Hour())
	fmt.Println("Минута:", timeVariable.Minute())
	fmt.Println("Секунда:", timeVariable.Second())
	fmt.Println("Наносекунда:", timeVariable.Nanosecond())
	fmt.Println("Часовой пояс:", timeVariable.Location())

	fmt.Println("")

	fmt.Println("Год (тип):", reflect.TypeOf(timeVariable.Year()))
	fmt.Println("Месяц (тип):", reflect.TypeOf(timeVariable.Month()))
	fmt.Println("Число (тип):", reflect.TypeOf(timeVariable.Day()))
	fmt.Println("День недели (тип):", reflect.TypeOf(timeVariable.Weekday()))
	fmt.Println("Час (тип):", reflect.TypeOf(timeVariable.Hour()))
	fmt.Println("Минута (тип):", reflect.TypeOf(timeVariable.Minute()))
	fmt.Println("Секунда (тип):", reflect.TypeOf(timeVariable.Second()))
	fmt.Println("Наносекунда (тип):", reflect.TypeOf(timeVariable.Nanosecond()))
	fmt.Println("Часовой пояс (тип):", reflect.TypeOf(timeVariable.Location()))
}

Консольный вывод этого скрипта будет таким:

Год: 2024
Месяц: November
Число: 15
День недели: Friday
Час: 12
Минута: 45
Секунда: 20
Наносекунда: 0
Часовой пояс: UTC

Год (тип): int
Месяц (тип): time.Month
Число (тип): int
День недели (тип): time.Weekday
Час (тип): int
Минута (тип): int
Секунда (тип): int
Наносекунда (тип): int
Часовой пояс (тип): *time.Location

Таким образом, можно по отдельности узнавать специфическую информацию о дате и времени, не прибегая к полноценному форматированию перед выводом в консоль.

Обратите внимание на типы полученных переменных — все они имеют тип int за исключением нескольких:

  • Месяц (time.Month)
  • День недели (time.Weekday)
  • Часовой пояс (*time.Location)

При этом последний (часовой пояс) является указателем.

Изменение, сложение и вычитание 

Изменение

Параметры даты и времени в уже созданной переменной time.Time напрямую нельзя изменить. Однако можно пересоздать переменную с обновленными значениями, тем самым изменив уже имеющиеся дату и время:

package main

import (
	"fmt"
	"time"
)

func main() {
	timeVariable := time.Now()
	fmt.Println(timeVariable)

	// год, месяц, день, час, минута, секунда, наносекунд, часовой пояс
	timeChanged := time.Date(timeVariable.Year(), timeVariable.Month(), timeVariable.Day(), timeVariable.Hour() + 14, timeVariable.Minute(), timeVariable.Second(), timeVariable.Nanosecond(), timeVariable.Location())
	fmt.Println(timeChanged)
}

Запустив этот скрипт можно наблюдать следующий вывод:

2024-11-28 14:35:05.287957345 +0000 UTC m=+0.000039131
2024-11-29 04:35:05.287957345 +0000 UTC

В этом примере было добавлено 14 часов к параметру текущему времени. Таким образом можно избирательно обновлять значения времени в уже имеющейся переменной time.Time.

Изменение по часовому поясу

Иногда необходимо узнать, какими будут заданные дата и время в другой временной зоне. Для этого в языке Go есть специальный метод:

package main
 
import (
	"fmt"
	"time"
)
 
func main() {
	locationFirst, _ := time.LoadLocation("Europe/Moscow")
	timeFirst := time.Date(2000, 1, 1, 0, 0, 0, 0, locationFirst)

	fmt.Println("Время (Europe/Moscow)", timeFirst)

	locationSecond, _ := time.LoadLocation("America/Chicago")
	timeSecond := timeFirst.In(locationSecond) // меняем часовой пояс и одновременно конвертируем дату и время на его основе

	fmt.Println("Время (America/Chicago)", timeSecond)
}

Результатом работы скрипта станет следующий консольный вывод:

Время (Europe/Vienna) 2000-01-01 00:00:00 +0100 CET
Время (America/Phoenix) 1999-12-31 16:00:00 -0700 MST

Таким образом получаются новые значения даты и времени, обновленные исходя из повторно указанной временной зоны.

Сложение и вычитание

В языке Go нет отдельных методов для операции сложения даты и времени. Вместо этого можно добавлять временные промежутки к уже созданной переменной time.Time:

package main

import (
	"fmt"
	"time"
)

func main() {
	// текущее время
	timeVariable := time.Now()
	fmt.Println(timeVariable)

	// прибавление 5 дней (24 часа * 5 дней = 120 часов)
	timeChanged := timeVariable.Add(120 * time.Hour)
	fmt.Println(timeChanged)

	// вычитание 65 дней (24 часа * 65 дней = 1560 часов)
	timeChanged = timeVariable.Add(-1560 * time.Hour)
	fmt.Println(timeChanged)
}

В результате работы этого скрипта в терминале появится следующий вывод:

2024-12-05 08:42:01.927334604 +0000 UTC m=+0.000035141
2024-12-10 08:42:01.927334604 +0000 UTC m=+432000.000035141
2024-10-01 08:42:01.927334604 +0000 UTC m=-5615999.999964859

Обратите внимание, что при вычитании из переменной time.Time достаточного количества дней происходит также изменение месяца.

При этом переменная time.Hour на самом деле имеет специальный тип time.Duration:

package main

import (
	"fmt"
	"time"
	"reflect"
)

func main() {
	fmt.Println(reflect.TypeOf(time.Hour))
	fmt.Println(reflect.TypeOf(120* time.Hour))
}

После запуска этого скрипта в терминале появится такой вывод:

time.Duration
time.Duration

Тем не менее, изменение даты и времени через добавление или удаление большого количества часов ненаглядно. В некоторых случаях лучше воспользоваться более продвинутыми методами изменения времени:

package main

import (
	"fmt"
	"time"
)

func main() {
	timeVariable := time.Now()
	fmt.Println(timeVariable)

	// год, месяц, день
	timeChanged := timeVariable.AddDate(3, 2, 1)
	fmt.Println(timeChanged)

	// день
	timeChanged = timeChanged.AddDate(0, 0, 15)
	fmt.Println(timeChanged)

	// год, месяц
	timeChanged = timeChanged.AddDate(5, 1, 0)
	fmt.Println(timeChanged)

	// -год, -день
	timeChanged = timeChanged.AddDate(-2, 0, -10)
	fmt.Println(timeChanged)
}

После запуска этого скрипта в терминале появится такой вывод:

2024-11-28 17:51:45.769245873 +0000 UTC m=+0.000024921
2028-01-29 17:51:45.769245873 +0000 UTC
2028-02-13 17:51:45.769245873 +0000 UTC
2033-03-13 17:51:45.769245873 +0000 UTC
2031-03-03 17:51:45.769245873 +0000 UTC

Нахождение разницы

В отличие от сложения, в языке Go есть специализированные методы для вычитания одной переменной time.Time из другой:

package main

import (
	"fmt"
	"time"
	"reflect"
)

func main() {
	timeFirst := time.Date(2024, 6, 14, 0, 0, 0, 0, time.Local)
	timeSecond := time.Date(2010, 3, 26, 0, 0, 0, 0, time.Local)

	timeDeltaSub := timeFirst.Sub(timeSecond) // timeFirst - timeSecond
	timeDeltaSince := time.Since(timeFirst) // time.Now() - timeFirst
	timeDeltaUntil := time.Until(timeFirst) // timeFirst - time.Now()

	fmt.Println("timeFirst - timeSecond =", timeDeltaSub)
	fmt.Println("time.Now() - timeFirst =", timeDeltaSince)
	fmt.Println("timeFirst - time.Now() =", timeDeltaUntil)

	fmt.Println("")

	fmt.Println(reflect.TypeOf(timeDeltaSub))
	fmt.Println(reflect.TypeOf(timeDeltaSince))
	fmt.Println(reflect.TypeOf(timeDeltaUntil))
}

Консольный вывод этого примера будет таким:

timeFirst - timeSecond = 124656h0m0s
time.Now() - timeFirst = 4029h37m55.577746026s
timeFirst - time.Now() = -4029h37m55.577746176s

time.Duration
time.Duration
time.Duration

Консольный вывод этого примера будет таким:

timeFirst - timeSecond = 124656h0m0s
time.Now() - timeFirst = 4029h37m55.577746026s
timeFirst - time.Now() = -4029h37m55.577746176s

time.Duration
time.Duration
time.Duration

Как можно заметить, результатом вычитания является уже знакомая переменная типа time.Duration.

На самом деле основной функцией для нахождения разницы является лишь time.Time.Sub(), а остальные две лишь ее производные:

package main

import (
	"fmt"
	"time"
)

func main() {
	timeVariable := time.Date(2024, 6, 14, 0, 0, 0, 0, time.Local)

	fmt.Println(time.Now().Sub(timeVariable))
	fmt.Println(time.Since(timeVariable))

	fmt.Println("")

	fmt.Println(timeVariable.Sub(time.Now()))
	fmt.Println(time.Until(timeVariable))
}

После запуска этого скрипта в терминале появится такой вывод:

4046h10m53.144212707s
4046h10m53.144254987s

-4046h10m53.144261117s
-4046h10m53.144267597s

Таким образом, можно наблюдать идентичность результатов описанных функций:

  • time.Time.Since() = time.Now().Sub(timeVariable)

  • time.Time.Until() = timeVariable.Sub(time.Now())

Временные продолжительности

Отдельные промежутки времени (продолжительности) в пакете time представляются в виде специальной переменной типа time.Duration. В отличие от time.Time, они хранят не полноценные дату и время, а временные интервалы.

С продолжительностями можно выполнять некоторые базовые операции, изменяющие их временные параметры.

Парсинг продолжительностей

Продолжительность в явном виде задается с помощью строки, содержащей значения временных параметров:

package main

import (
	"fmt"
	"time"
)

func main() {
	// часы, минуты, секунды
	durationHMS, _ := time.ParseDuration("4h30m20s")
	fmt.Println("Продолжительность (HMS):", durationHMS)

	// минуты, секунды
	durationMS, _ := time.ParseDuration("6m15s")
	fmt.Println("Продолжительность (MS):", durationMS)

	// часы, минуты
	durationHM, _ := time.ParseDuration("2h45m")
	fmt.Println("Продолжительность (HM):", durationHM)

	// часы, секунды
	durationHS, _ := time.ParseDuration("2h10s")
	fmt.Println("Продолжительность (HS):", durationHS)

	// часы, минуты, секунды, миллисекунды, микросекунды, наносекунды
	durationFULL, _ := time.ParseDuration("6h50m40s30ms4µs3ns")
	fmt.Println("Продолжительность (ПОЛНАЯ):", durationFULL)
}

Результатом работы этого скрипта будет следующий вывод:

Продолжительность (HMS): 4h30m20s
Продолжительность (MS): 6m15s
Продолжительность (HM): 2h45m0s
Продолжительность (HS): 2h0m10s
Продолжительность (ПОЛНАЯ): 6h50m40.030004003s

Обратите внимание на последнюю продолжительность, которая содержит все возможные временные параметры в порядке убывания размерности — часы, минуты, секунды, миллисекунды, микросекунды, наносекунды.

Во время парсинга каждый из параметров задается с помощью следующих ключевых слов:

  • Часы — h
  • Минуты — m
  • Секунды — s
  • Миллисекунды — ms
  • Микросекунды — µs
  • Наносекунды— ns

Более того, различный порядок указания параметров продолжительности не оказывает на нее никакого влияния:

package main

import (
	"fmt"
	"time"
)

func main() {
	duration, _ := time.ParseDuration("7ms20s4h30m")
	fmt.Println("Продолжительность:", duration)
}

После запуска скрипта в терминале будет такой вывод:

Продолжительность: 4h30m20.007s

Форматирование продолжительностей

В языке Go одну и ту же продолжительность можно представлять в виде разных единиц измерения:

package main

import (
	"fmt"
	"time"
	"reflect"
)

func main() {
	duration, _ := time.ParseDuration("4h30m20s")

	fmt.Println("Продолжительность:", duration)

	fmt.Println("")

	fmt.Println("В часах:", duration.Hours())
	fmt.Println("В минутах:", duration.Minutes())
	fmt.Println("В секундах:", duration.Seconds())
	fmt.Println("В миллисекундах:", duration.Milliseconds())
	fmt.Println("В микросекундах:", duration.Microseconds())
	fmt.Println("В наносекундах:", duration.Nanoseconds())

	fmt.Println("")

	fmt.Println(reflect.TypeOf(duration.Hours()))
	fmt.Println(reflect.TypeOf(duration.Minutes()))
	fmt.Println(reflect.TypeOf(duration.Seconds()))
	fmt.Println(reflect.TypeOf(duration.Milliseconds()))
	fmt.Println(reflect.TypeOf(duration.Microseconds()))
	fmt.Println(reflect.TypeOf(duration.Nanoseconds()))
}

После запуска скрипта в терминале появится такой вывод:

Продолжительность: 4h30m20s

В часах: 4.5055555555555555
В минутах: 270.3333333333333
В секундах: 16220
В миллисекундах: 16220000
В микросекундах: 16220000000
В наносекундах: 16220000000000

float64
float64
float64
int64
int64
int64

Как видно, параметры часов, минут и секунд имеют вещественный тип (float64), а все остальные — целочисленный (int).

Выгодные тарифы на облако в Timeweb Cloud

Заключение

В этом руководстве были рассмотрены основные функции работы с датой и временем в языке программирования Go — все они содержатся во встроенном пакете time.

Таким образом, язык Go позволяет:

  • Форматировать дату и время
  • Конвертировать дату и время
  • Устанавливать часовые пояса
  • Извлекать конкретные параметры даты и времени
  • Устанавливать конкретные параметры даты и времени
  • Складывать и вычитать дату и время
  • Выполнять код исходя из определенных временных установок

Дополнительную информацию об особенностях работы с пакетом time можно найти на специальной странице официальной документации языка Go.

Хотите внести свой вклад?
Участвуйте в нашей контент-программе за
вознаграждение или запросите нужную вам инструкцию
img-server
12 декабря 2024 г.
107
20 минут чтения
Средний рейтинг статьи: 5
Пока нет комментариев