Golang : Get missing location after unmarshal binary and gob decode time.




Problem :

You loaded some time based data, found out that the time is missing location data and somehow screw up your time sensitive graph or summary report. How to fix this missing location problem?

Solution :

The time.Time type has Location information before encoding/marshaling and because it is a pointer type. It won't be serialized properly as text data. To fix this problem, you need to use the time.Time.In() function to set the decoded time back to the location that you want. The only weakness about this solution is that ... you need to know in advance which location (i.e America/New_York) when it was encoded. Perhaps the location can be stored separately in a field in the database or separate file.

NOTE : I've tried to solve the missing location data from gob decoded by getting the offset and translating to location... but it won't work without introducing bugs and without a constantly updated database.

Here you go!

 package main

 import (
 "fmt"
 "strings"
 "time"
 )

 func main() {

 loc, _ := time.LoadLocation("America/New_York")
 t := time.Date(2015, 8, 6, 0, 0, 0, 0, loc)

 fmt.Println("Time : ", t)
 fmt.Println("Time Location : ", t.Location())

 gobEncoded, err := t.GobEncode()

 if err != nil {
 fmt.Println(err)
 }

 fmt.Println("Gob encoded : ", gobEncoded)

 // with GOB encoded(marshalled) data, can save to file(serialize)

 // now, pretend that we loaded the GOB data
 // we want to decode(unmarshal) the data

 var gobTime time.Time

 err = gobTime.GobDecode(gobEncoded)

 if err != nil {
 fmt.Println(err)
 }

 fmt.Println("Gob decoded time : ", gobTime)

 fmt.Println("Gob decoded location(missing!) : ", gobTime.Location())

 // because location is a pointer type (see http://golang.org/pkg/time/#Time.Location)
 // it won't be encoded by Gob
 // but you can translate it back to local time

 fmt.Println("Gob decoded local : ", gobTime.Local().String())

 // and convert back to target location
 NYTime := gobTime.In(loc)

 fmt.Println("Gob decoded back to America/New_York time : ", NYTime)

 // a better solution is to use the time zone offset
 // for our example is -0400

 gobArray := strings.Fields(gobTime.String())

 //fmt.Println(gobArray)

 offset := gobArray[3]
 fmt.Println("Offset time zone : ", offset)

 // time.Parse() will not work, because
 // in absence of a time zone indicator, Parse returns a time in UTC
 // even translating the above offset to location is a challenge
 // and the output below will be wrong
 //longForm := "2015-08-06"
 //newyorktime,_ := time.Parse(longForm, gobTime.String())
 //fmt.Println(newyorktime)

 }

Output :

Time : 2015-08-06 00:00:00 -0400 EDT

Time Location : America/New_York

Gob encoded : [1 0 0 0 14 205 84 210 192 0 0 0 0 255 16]

Gob decoded time : 2015-08-06 00:00:00 -0400 -0400

Gob decoded location(missing!) :

Gob decoded local : 2015-08-06 12:00:00 +0800 MYT

Gob decoded back to America/New_York time : 2015-08-06 00:00:00 -0400 EDT

Offset time zone : -0400





By Adam Ng

IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.


Advertisement