Комментарии 6
>часовые пояса — господи, почему они не могут быть просто целыми
В каком смысле целыми? Вы что, предлагаете закодировать Europe/Moscow в виде числа? И все остальные — тоже?
В каком смысле целыми? Вы что, предлагаете закодировать Europe/Moscow в виде числа? И все остальные — тоже?
Я имел в виду, что часовые пояса могут быть сдвинуты как на целое количество часов, так и на дробное, например в Иране сдвиг UTC+3:30
Я тогда не понял, что именно вы предлагаете? То что они не целые — это фича. Так устроено время в Иране. Можно конечно в минутах выразить… Но в целом приходится мириться с тем, что мир в этом месте устроен непросто, и нам с этим жить.
Это был просто плач Ярославны по поводу несовершенства мира, ничего я не предлагаю
А-а-а) Ну в этом смысле могу только согласиться — с датами и временем все сложно. Я бы сказал — намного сложнее, чем вы в этом посте описали. Берем ту же зону Europe/Moscow, например. Что означает некий момент времени в этой зоне, если это было 10 лет назад? А хз, это нужно смотреть, какое описание зоны было тогда. А может какое сейчас? А, блин, наверное от задачи зависит… А если это была дата перехода на летнее время — то все становится еще чудесатее.
Можно идею развить и задуматься над тем, чтобы, например, этот кастомный формат корректно сохранять в SQL и потом читать. Существенное отличие предложенного вами формата в том, что он не содержит долей секунд и таймзоны.
Для работы с SQL можем реализовать интерфейс sql.Scanner, чтобы обычная сохранённая дата, даже с долями секунд и таймзоной, интерпретировалась в нужный формат:
И интерфейс driver.Valuer:
Ну и для красивого вывода в строках (не только в JSON) — интерфейс fmt.Stringer:
Для работы с SQL можем реализовать интерфейс sql.Scanner, чтобы обычная сохранённая дата, даже с долями секунд и таймзоной, интерпретировалась в нужный формат:
func (c *CustomDate) Scan(v interface{}) error {
c.Time, ok := v.(time.Time)
if !ok {
return errors.New("invalid time format")
}
_, offset := c.Time.Zone()
c.Time = c.Time.Add(time.Second * time.Duration(offset))
c.Time = c.Time.Round(time.Second).UTC()
return nil
}
И интерфейс driver.Valuer:
func (c CustomDate) Value() (driver.Value, error) {
if с.Time.IsZero() {
return nil, nil
}
return t.Time.UTC().Format(layout), nil
}
Ну и для красивого вывода в строках (не только в JSON) — интерфейс fmt.Stringer:
func (c CustomDate) String() string {
return c.Time(c.Time.UTC()).Format(layout)
}
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Маршалинг и анмаршалинг нестандартных форматов дат в Go