Остерегайтесь стандарта даты и времени !!
Итак, сегодняшняя история о странном поведении при демаршалинге DateTime из JSON в Golang. Я не говорю, что это ошибка, но это только моя история из-за отсутствия у меня опыта работы с DateTime и часовым поясом в Golang.
Это случается, когда я хочу создать систему CRUD API на Golang. Итак, у меня есть конечная точка, скажем: /event
, которая получит объект события из JSON.
{ "title": "title here in string", "place": "place name here in string", "start_time": "date time here in string" }
Я использую labstack / echo в качестве библиотеки маршрутизации, чтобы упростить обработку моего запроса. С помощью echo, чтобы получить тело ответа и демаршалировать его в мою структуру, я могу сделать это с помощью простого кода, как показано ниже:
Итак, когда я хочу его протестировать, я создал тело запроса, как показано ниже, я просто скопировал и вставил его из нашего примера документации API. Потому что сначала я даже не думаю, что это имеет значение.
{ "title": "Core i13 Anniversarry", "place": "Ancol Beach", "start_time": "2018-09-22T12:42:31Z" }
API уже развернут на промежуточном сервере, поэтому я тестирую его прямо из Postman на промежуточный сервер. Но после получения всего сохраненного элемента события start_time
отличается от того, что я разместил в теле запроса. Ниже это будет выглядеть так.
{ "id": "1", // auto increment from database "title": "Core i13 Anniversarry", "place": "Ancol Beach", "start_time": "2018-09-22T19:42:31+07:00", "created_at": "2018-09-22T16:35:08+07:00", "updated_at": "2018-09-22T16:35:08+07:00" }
А в базе он хранится вот так:
Посмотрите поле start_time
. Это изменилось по сравнению с тем, что я опубликовал. Я хочу, чтобы сохраненные данные были такими же, как и данные, которые я отправил из Postman.
Я обнаружил, что проблема возникает, очевидно, из-за часового пояса. Так что мне просто нужно позаботиться о часовом поясе. Это была моя первая мысль. Я думаю, что в моих системах есть ошибка по этому поводу.
Решение проблемы
Чтобы решить эту проблему, я выполняю все действия, указанные ниже.
Ищем строку подключения в драйвере подключения
Поскольку я использую MySQL в качестве хранилища БД, мне нужен драйвер для подключения моего приложения к MySQL. Я использую github.com/go-sql-driver/mysql в качестве драйвера подключения. Итак, после поиска документации и проверки моей строки подключения ничего плохого не произошло. Я сделал правильно.
dsn := root:root@tcp(127.0.0.1:3306)/event?parseTime=true&loc=Asia%2FJakarta&charset=utf8mb4&collation=utf8mb4_unicode_ci
Восстановите Datetime вручную
Все еще любопытно, почему это происходит. Затем я пытаюсь найти ответы на вопросы или проблемы по этому поводу в StackOverflow или даже на GitHub.
Честно говоря, у меня уходит до 2 часов, когда я пытаюсь решить эту проблему 🤦
А пока я был разочарован. Итак, у меня есть 2 варианта, как решить эту проблему.
- Я перестрою
start_time
перед сохранением в базе данных. - Спрашивать моих товарищей по команде (* даже если это так глупо, когда я спрашиваю об этом)
Но просто хочу приложить больше усилий 😶, я исправил ситуацию, перестроив DateTime.
startTime := e.StartTime loc, _ := time.LoadLocation("Asia/Jakarta") localStartTime := time.Date(startTime.Year(), startTime.Month(), startTime.Day(), startTime.Hour(), startTime.Minute(), startTime.Second(), startTime.Nanosecond(), loc)
Затем, просто из любопытства, я спрашиваю свою команду о проблеме. Потом смотрят, как я это воспроизводю, тоже как и я, им тоже любопытно, почему это происходит. Всего за несколько минут один из моих сотрудников нашел причины, по которым это происходит.
Это происходит из-за неправильного смещения часового пояса в теле запроса.
{ "title": "Core i13 Anniversarry", "place": "Ancol Beach", "start_time": "2018-09-22T12:42:31Z" // look for the `Z` indicator }
Поскольку я жил в +7.00 timezone (Asia/Jakarta)
, он должен быть включен в мой JSON.
Итак, когда я меняю start_time
с:
2018-09-22T12:42:31Z
в
2018-09-22T12:42:31+07:00
это решает мою проблему. С моей системой ничего плохого не произошло. Все работает отлично.
Когда я это понял, я почувствовал себя таким тупым 🤦. Я зря потратил два часа своей жизни 🤦.
Урок, который нужно усвоить
- Всегда сначала спрашивайте своих товарищей по команде (были ли они в любом случае доступны)
2018–09–22T12:42:31+07:00
- это формат RFC 3339, каждый символ имеет значение.
Если вы считаете, что эту статью стоит прочитать, похлопайте в ладоши или поделитесь в своем сетевом кругу, чтобы все также могли это прочитать. Следите за другими подобными историями!