paint-brush
Hoy aprendí: Tratar con JSON DateTime cuando Unmarshal en Golang.por@imantumorang
66,205 lecturas
66,205 lecturas

Hoy aprendí: Tratar con JSON DateTime cuando Unmarshal en Golang.

por Iman Tumorang4m2018/09/20
Read on Terminal Reader
Read this story w/o Javascript

Demasiado Largo; Para Leer

Hoy aprendí: Tratar con JSON DateTime cuando Unmarshal en Golang. Ingeniero de software Iman Tumorang: "¡Cuidado con el estándar de fecha y hora!" No digo que esto sea un error, pero esta es solo mi historia debido a mi falta de experiencia al tratar con DateTime y la zona horaria en. Golang.com/labstack/echo como mi biblioteca de enrutamiento para facilitarme el manejo de mi solicitud. Con echo, para recibir el cuerpo de la respuesta y descomponerlo en mi estructura, puedo hacerlo con un código simple como el siguiente.

Company Mentioned

Mention Thumbnail
featured image - Hoy aprendí: Tratar con JSON DateTime cuando Unmarshal en Golang.
Iman Tumorang HackerNoon profile picture

¡Cuidado con el estándar de fecha y hora!

Golang tomado de la búsqueda de imágenes de Google

Entonces, la historia de hoy trata sobre el comportamiento extraño al desarmar DateTime de JSON en Golang. No digo que esto sea un error, pero esta es solo mi historia debido a mi falta de experiencia al tratar con DateTime y la zona horaria en Golang.

Sucede cuando quiero hacer un sistema API CRUD en Golang. Entonces, tengo un punto final, digamos:

 /event
que recibirá un objeto de evento de JSON.

 { "title" : "title here in string" , "place" : "place name here in string" , "start_time" : "date time here in string" }

Estoy usando labstack/echo como mi biblioteca de enrutamiento para facilitarme el manejo de mi solicitud. Con echo, para recibir el cuerpo de la respuesta y descomponerlo en mi estructura, puedo hacerlo con un código simple como el siguiente:

 package main import ( "log" "net/http" "time" "github.com/labstack/echo" ) type Event struct { Title string `json:"title"` Place string `json:"place"` StartTime time.Time `json:"start_time"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } func CreateEvent(c echo.Context) error { e := new (Event) err := c.Bind(&e) if err != nil { return err } now := time.Now() e.CreatedAt = now e.UpdatedAt = now // Other code here // .... // Store to DB // ... return c.JSON(http.StatusCreated, e) } func main() { e := echo.New() e.POST( "/event" , CreateEvent) if err := e.Start( ":9090" ); err != nil { log.Fatal(err) } }

Entonces, cuando quiero probarlo, hice el cuerpo de la solicitud como se muestra a continuación, simplemente lo copié y lo pegué de nuestro ejemplo de documentación de la API. Porque al principio, ni siquiera creo que importe.

 { "title" : "Core i13 Anniversarry" , "place" : "Ancol Beach" , "start_time" : "2018-09-22T12:42:31Z" }


La API ya se implementó en el servidor de ensayo, así que la pruebo directamente desde Postman al servidor de ensayo. Pero después de obtener todo el elemento de evento almacenado, start_time es diferente a lo que publiqué en el cuerpo de la solicitud. Se vuelve así a continuación.

 { "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" }


Y en la base de datos se almacenó así:


Mira el

 start_time
campo. Cambió de lo que publiqué. Lo que quiero es que los datos almacenados sean los mismos que publiqué desde Postman.

Descubrí que el problema ocurre debido a la zona horaria, obviamente. Así que solo necesito cuidar la zona horaria. Fue lo primero que pensé. Creo que mis sistemas tienen un error sobre esto.

Resolviendo el Problema

Para solucionar este problema, estoy haciendo todas estas acciones a continuación.

Buscando la cadena de conexión en el controlador de conexión

Debido a que estoy usando MySQL como mi base de datos de almacenamiento, necesito un controlador para conectar mi aplicación con MySQL. Estoy usando github.com/go-sql-driver/mysql como mi controlador de conexión. Entonces, después de buscar la documentación y verificar mi cadena de conexión, no sucedió nada malo. Lo hice correctamente.

 dsn := root:root@tcp( 127.0 .0 .1 : 3306 )/event?parseTime= true &loc=Asia% 2 FJakarta&charset=utf8mb4&collation=utf8mb4_unicode_ci


Reconstruir la fecha y hora manualmente

Todavía curioso, por qué sucede esto. Luego, estoy tratando de encontrar preguntas o respuestas o problemas sobre esto en StackOverflow o incluso en GitHub.

Para ser honesto, me toma hasta 2 horas intentar solucionar este problema 🤦‍
Hasta entonces, me frustré. Entonces tengo 2 opciones para resolver esto.

Reconstruiré start_time antes de almacenarlo en la base de datos. Preguntaré a mis compañeros de equipo (* incluso se siente tan tonto cuando pregunto esto de todos modos🤦‍)

Pero, solo quiero esforzarme más 😶, arreglé la reconstrucción de 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)


Luego, solo por curiosidad, le pregunto a mi equipo sobre el problema. Luego miran cómo lo reproduzco, igual que yo, también tienen curiosidad por qué sucede esto. Hasta que apenas unos minutos, uno de mi equipo encontró las razones por las que esto está sucediendo.

Esto sucede porque hice un desplazamiento de zona horaria incorrecto en el cuerpo de mi solicitud.

 { "title" : "Core i13 Anniversarry" , "place" : "Ancol Beach" , "start_time" : "2018-09-22T12:42:31Z" // look for the `Z` indicator }


Debido a que viví en la zona horaria +7.00 (Asia/Yakarta), debería incluirse en mi JSON.

Entonces, cuando cambio el

 start_time
de:

 2018 -09 -22 T12: 42 : 31 <strong>Z</strong>

dentro

 2018 -09 -22 T12: 42 : 31 <strong>+ 07 : 00 </strong>

resuelve mi problema No le pasó nada malo a mi sistema. Todo funciona perfectamente.

Cuando me di cuenta de esto, me siento tan tonto 🤦‍. He gastado mis dos horas de mi vida para nada 🤦‍.

Lección a ser aprendida

  • Siempre pregunta primero a tus compañeros de equipo (si estuvieran disponibles de todos modos)
  •  2018–09–22T12:42:31+07:00
    es el formato RFC 3339 , cada carácter es importante.

Si crees que vale la pena leer este artículo, dale un aplauso o compártelo en tu círculo de red, para que todos también puedan leerlo. ¡Sígueme para más historias como esta!