Во многих случаях вам придется писать код, работающий со временем. Вы можете написать программу часов или измерить разницу во времени между двумя точками в вашем коде. В любом случае, важно знать, как манипулировать данными о времени в Go. Это довольно просто, и знание некоторых отличных функций может помочь вам сэкономить время. Для работы с временными данными в Go необходимо импортировать пакет time из стандартной библиотеки Go. В этом пакете много методов и типов, которые вы можете использовать, но я взял самые используемые и описал их здесь, в этом посте. Если вы хотите получить больше информации по этому вопросу, посетите страницу документации для пакета time.

Сказать время

Это, вероятно, наиболее часто используемый метод в пакете. Как узнать текущее время? Так:

t := time.Now()
fmt.Println(t)
2023-02-06 23:01:48.9983151 -0500 EST m=+0.000030901

Это текущее время. Это довольно громоздко, поэтому я разобью это на компоненты.

  • 2023-02-06: Год, месяц, день.
  • 23:01:48.9983151: Часы, минуты, секунды
  • -0500: Разница во времени с GMT.
  • EST: Текущий часовой пояс, в котором вы находитесь.
  • m=+0.000030901: Монотонное чтение часов.

Мы перейдем к монотонным часам позже в этом посте. Мы можем двигаться дальше.

Есть ли лучший способ отформатировать это?

Вы держите пари.

t := time.Now()
fmt.Println(t.Year())
fmt.Println(t.Month())
fmt.Println(t.Day())
fmt.Println(t.Date())
fmt.Println(t.Hour())
fmt.Println(t.Minute())
fmt.Println(t.Second())
2023
February
6
2023 February 6
23
26
6

Вот как вы можете извлечь каждый элемент времени. Довольно просто, правда?

Как мы можем напечатать это в более красивом формате?

fmt.Printf("%d %d %d\n", t.Year(), t.Month(), t.Day())
2023 2 6

Вы можете видеть, как мы можем использовать функцию fmt.Printf для форматирования времени по своему вкусу.

Но что, если мы хотим показывать месяцы по их названиям, например Февраль вместо 2? Что, если мы хотим показывать время в 12-часовой шкале вместо 24-часовой? Вы можете видеть, как это очень быстро усложняется.

Есть лучший способ отформатировать время

К счастью, у нас есть функция time.Format, которая нам в помощь. Давайте посмотрим, как это работает.

fmt.Println(t.Format("Mon Jan 2 15:04:05 2006 MST"))
fmt.Println(t.Format("Mon Jan 2 15:04:05"))
fmt.Println(t.Format("2006/01/02"))
fmt.Println(t.Format("3:04PM"))
fmt.Println(t.Format("15:04PM"))
Mon Feb 6 23:47:43 2023 EST
Mon Feb 6 23:47:43
2023/02/06
11:47PM
23:47PM

Я думаю, что это та часть, которая больше всего сбила меня с толку, когда я впервые начал изучать эту тему. И это также та часть, где вы можете увидеть, насколько дерзкими были дизайнеры языка.

Мы можем видеть, что time.Format принимает строку, которая обозначает формат, в котором мы хотим, чтобы наше время было. Это странная часть, потому что Go очень, чрезвычайно привередлив к формату строки формата.

Mon Jan 2 15:04:05 2006 MST

Строка формата должна быть вариацией этой строки, иначе код выведет странное время. Интересно, что если исключить Mon, каждый элемент строки формата представляет целое число. Jan — это 1, 2 — это 2, 15 — это 3 и т. д. Зануды, эти разработчики.

1 2 3 4 5 6 -7

Однако из приведенного выше кода вы можете увидеть, как мы можем отформатировать наше время так, как мы этого хотим. И нам не нужно писать дополнительные функции для преобразования часов в 12- или 24-часовую шкалу или для сопоставления каждого целого числа с месяцем.

Вы также можете использовать предопределенный формат, например:

fmt.Println(time.UnixDate)
fmt.Println(time.RFC3339)
Mon Jan _2 15:04:05 MST 2006
2006-01-02T15:04:05Z07:00

Дополнительные форматы см. в документации по пакету time.

А как насчет разных часовых поясов?

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

nt := time.Now()
lt := time.Now().Local()
ut := time.Now().UTC()
fmt.Println(nt)
fmt.Println(lt)
fmt.Println(ut)
2023-02-07 00:09:08.7052349 -0500 EST m=+0.000121601
2023-02-07 00:09:08.705235 -0500 EST
2023-02-07 05:09:08.705235 +0000 UTC

Local() получает местный часовой пояс, который автоматически определяет time.Now(). При вызове UTC() часовой пояс будет преобразован в UTC.

Но что, если нам нужно что-то более надежное?

l, _ := time.LoadLocation("UTC")
fmt.Printf("%s\n", nt.In(l))

l, _ = time.LoadLocation("Europe/London")
fmt.Printf("%s\n", nt.In(l))

l, _ = time.LoadLocation("America/Los_Angeles")
fmt.Printf("%s\n", nt.In(l))

l, _ = time.LoadLocation("Asia/Seoul")
fmt.Printf("%s\n", nt.In(l))
2023-02-07 05:12:10.4423244 +0000 UTC
2023-02-07 05:12:10.4423244 +0000 GMT
2023-02-06 21:12:10.4423244 -0800 PST
2023-02-07 14:12:10.4423244 +0900 KST

time.LoadLocation загрузит локаль по вашему выбору. Вы можете использовать этот результат, чтобы преобразовать свое время, перейдя к yourTime.In.

Вы также можете читать время из строк

Во многих случаях вам придется читать строку. Часто это будут временные метки. Разве не было бы здорово использовать функции библиотеки time для этих строк временных меток?

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

timestamp := "2023-02-06 23:49:01"
ts, err := time.Parse("2006-01-02 15:04:05", timestamp)
if err != nil {
    fmt.Println(err)
}
fmt.Println(ts)
2023-02-06 23:49:01 +0000 UTC

Вы также можете отформатировать ts, используя метод Format, описанный выше.

Подождите, что такое монотонные часы?

Вернемся к этой теме. Звучит намного страшнее, чем есть на самом деле.

На вашем компьютере есть часы, которые измеряют время. Скорее всего, это время довольно нестабильно. Вы когда-нибудь сталкивались с тем, что ваши часы сбиваются на пару часов после поездки в другую страну? Вам когда-нибудь приходилось заново настраивать часы, чтобы они соответствовали вашим часам? Эти часы называются настенными часами, и их можно менять.

Хотя настенные часы хорошо показывают время, они не годятся для измерения времени. Например, посмотрите на этот фрагмент кода.

t1 := time.Now()
fmt.Println(t1)
time.Sleep(time.Second())
t2 := time.Now()
fmt.Println(time.Now())
fmt.Println(t2.Sub(t1))
2023-02-06 23:23:32.2520709 -0500 EST m=+0.000031501
2023-02-06 23:23:33.2525152 -0500 EST m=+1.000475801
1.0004442s

Приведенный выше код измеряет время, прошедшее между t1 и t2. Это кажется очевидным, потому что мы ждали одну секунду, прежде чем объявить t2. Но что, если бы нам каким-то образом удалось переключить настройки времени нашей ОС в этот промежуток времени? Если мы добавим 4 часа к часам нашей системы, означает ли это, что время, прошедшее между t1 и t2, будет 4 часа и 1 секунду? Это вздор!

Вот почему Go вместо этого использует монотонные часы для измерения времени. Из значений m в распечатанном времени видно, что разница во времени составляет около одной секунды. Монотонные часы позволяют точно измерять время.

Заключение

Мы настолько знакомы с концепцией времени, что склонны принимать наше понимание ее как должное. Тем не менее, время, как правило, является одной из самых неприятных вещей для представления в компьютере. К счастью, разработчики Go абстрагировали от нас большую часть необработанных преобразований, так что мы можем использовать простые для понимания функции пакета time. Этот пост охватывает множество необходимых функций, но если вам нужны мельчайшие детали, вы всегда можете обратиться к официальной документации.

Спасибо за чтение! Вы также можете просмотреть этот пост на Dev.to.

Повышение уровня кодирования

Спасибо, что являетесь частью нашего сообщества! Перед тем, как ты уйдешь:

  • 👏 Хлопайте за историю и подписывайтесь на автора 👉
  • 📰 Смотрите больше контента в публикации Level Up Coding
  • 🔔 Подписывайтесь на нас: Twitter | ЛинкедИн | "Новостная рассылка"

🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите прекрасную работу