Голанг: Получить эквивалентное время в другом часовом поясе
Я пытаюсь сравнить два раза из разных часовых поясов и посмотреть, есть ли один перед другим. Как бы я сделал это на Голанге?
Примечание: в основном я хотел бы sfTime.Before(nyTime) == true
, но мой пример ниже будет иметь sfTime.Before(nyTime) == false
, Предложения о том, как это сделать, было бы здорово.
Например, в этом коде...
layout := "2006-01-02 15:04 MST"
sfTime, _ := time.Parse(layout, "2017-03-01 12:00 PDT")
nyTime, _ := time.Parse(layout, "2017-03-01 12:00 EDT")
fmt.Printf("Are these times equal? %v\n", sfTime.Equal(nyTime))
Это печатает:
Эти времена равны? правда
Ссылка на игровую площадку здесь.
Интуитивно, даже если вы установите их в качестве одного и того же часового пояса, это только меняет часовой пояс, но не HH:mm
значение.
layout := "2006-01-02 15:04 MST"
sfTime, _ := time.Parse(layout, "2017-03-01 12:00 PDT")
nyTime, _ := time.Parse(layout, "2017-03-01 12:00 EDT")
// Set timezone to UTC
utcLocation, _ := time.LoadLocation("UTC")
sfTime = sfTime.In(utcLocation)
nyTime = nyTime.In(utcLocation)
// Timezones should not be equal, but they are
fmt.Printf("Are these times still equal? %v\n", sfTime.Equal(nyTime))
fmt.Printf("The New York Time: %v\n", nyTime)
Печать
Эти времена все еще равны? правда
Время по Нью-Йорку: 2017-03-01 12:00:00 +0000 UTC
3 ответа
Не используйте Go Playground для расчета времени. Он работает в песочнице с фальшивым временем:
Go Playground - это веб-сервис, который работает на серверах golang.org. Служба получает программу Go, компилирует, связывает и запускает программу в песочнице, а затем возвращает выходные данные.
Есть ограничения на программы, которые можно запускать на детской площадке.
На игровой площадке время начинается в 2009-11-10 23:00:00 UTC (определение значимости этой даты является упражнением для читателя). Это облегчает кеширование программ, давая им детерминированный вывод.
Кроме того, все время на игровой площадке Go используется часовой пояс UTC. Игровая площадка Go не использует базу данных часовых поясов IANA.
Например, для этой программы
package main
import (
"fmt"
"time"
)
func main() {
layout := "2006-01-02 15:04 MST"
sfTime, err := time.Parse(layout, "2017-03-01 12:00 PDT")
if err != nil {
fmt.Println(err)
}
fmt.Println(sfTime, sfTime.UTC())
nyTime, err := time.Parse(layout, "2017-03-01 12:00 EDT")
if err != nil {
fmt.Println(err)
}
fmt.Println(nyTime, nyTime.UTC())
fmt.Printf("Are these times equal? %v\n", sfTime.Equal(nyTime))
}
Выход с игровой площадки Go:
2017-03-01 12:00:00 +0000 PDT 2017-03-01 12:00:00 +0000 UTC
2017-03-01 12:00:00 +0000 EDT 2017-03-01 12:00:00 +0000 UTC
Are these times equal? true
Для правильного вывода запустите программу с помощью компилятора Go gc или gccgo:
$ go run equal.go
2017-03-01 12:00:00 +0000 PDT 2017-03-01 12:00:00 +0000 UTC
2017-03-01 11:00:00 -0500 EST 2017-03-01 16:00:00 +0000 UTC
Are these times equal? false
Затем с помощью компилятора Go gc или gccgo sfTime.Before(nyTime) == true
:
package main
import (
"fmt"
"time"
)
func main() {
layout := "2006-01-02 15:04 MST"
sfTime, err := time.Parse(layout, "2017-03-01 12:00 PDT")
if err != nil {
fmt.Println(err)
}
fmt.Println(sfTime, sfTime.UTC())
nyTime, err := time.Parse(layout, "2017-03-01 12:00 EDT")
if err != nil {
fmt.Println(err)
}
fmt.Println(nyTime, nyTime.UTC())
fmt.Printf("Is the SF time before the NY time? %v\n", sfTime.Before(nyTime))
}
Выход:
$ go run before.go
2017-03-01 12:00:00 +0000 PDT 2017-03-01 12:00:00 +0000 UTC
2017-03-01 11:00:00 -0500 EST 2017-03-01 16:00:00 +0000 UTC
Is the SF time before the NY time? true
The Go time
методы сравнения пакетов (Equal
, Before
, а также After
) сравнить значения UTC.
Я думаю, что это ошибка в play.golang.org, когда я запускаю его на своей локальной машине, он возвращает Are these times equal? false
а также Are these times still equal? false
,
В соответствии с документами это ожидаемое поведение (возвращает false):
// Равно сообщает, представляют ли t и u один и тот же момент времени.
// Два раза могут быть равны, даже если они находятся в разных местах.
// Например, 6:00 +0200 CEST и 4:00 UTC равны.
Вы пытались запустить его локально? Время игровой площадки установлено на фиксированный момент, поэтому оно может как-то быть связано с этим.
Ваши примеры работают так, как задумано, равное сравнение мгновенно по времени. Если вы хотите убедиться, что часовые пояса равны, вы можете сделать что-то вроде t1.Equal(t2) && t1.Location().String() == t2.Location().String()
Из документов с дополнительным акцентом:
Каждое время связывает с ним местоположение, к которому обращаются при расчете формы представления времени, такой как методы Format, Hour и Year. Методы Local, UTC и In возвращают время с определенным местоположением. Изменение местоположения таким образом изменяет только представление; он не меняет момент времени, который обозначается, и, следовательно, не влияет на вычисления, описанные в предыдущих параграфах.
Итак, насколько я понимаю, будь ты time.Parse("... PDT")
, time.Parse("... EDT")
, или же sfTime.In(time.UTC)
Вы всегда получаете одно и то же время, одинаковое количество секунд с 1970 года и, следовательно, Equal
, Before
, а также After
на эти значения времени будет возвращать тот же результат, независимо от Location
,
Обновление: я просто хотел бы добавить к выбранному ответу, что это не специфично для Playground, исходные примеры на моей машине ведут себя так же, и если вы посмотрите на вывод peterSO времени PDT, вы увидите, что он все еще анализируется как UTC. Это поведение описано в последнем абзаце Parse
Документация. (акцент мой)
При разборе времени с аббревиатурой зоны, такой как MST, если аббревиатура зоны имеет определенное смещение в текущем местоположении, то это смещение используется. Аббревиатура зоны "UTC" распознается как UTC независимо от местоположения. Если аббревиатура зоны неизвестна, Parse записывает время как изготовленное местоположение с данной аббревиатурой зоны и нулевым смещением. Этот выбор означает, что такое время может быть проанализировано и переформатировано с той же компоновкой без потерь, но точный момент, используемый в представлении, будет отличаться фактическим смещением зоны. Чтобы избежать таких проблем, предпочтите временные макеты, которые используют числовое смещение зоны, или используйте ParseInLocation.
Вот пример использования ParseInLocation
и числовые смещения часового пояса: https://play.golang.org/p/vY0muIvk5d