go想對xml的時間自定義Unmarshal,那麼要滿足 xml.Unmarshaler 接口
type Unmarshaler interface {
UnmarshalXML(d *Decoder, start StartElement) error
}
go想對xml的時間自定義Unmarshal,那麼要滿足 xml.Unmarshaler 接口
type Unmarshaler interface {
UnmarshalXML(d *Decoder, start StartElement) error
}
package main | |
import ( | |
"encoding/xml" | |
"fmt" | |
"log" | |
"testing" | |
"time" | |
) | |
type CustomTime struct { | |
time.Time | |
} | |
var locTaipei *time.Location | |
func init() { | |
var err error | |
locTaipei, err = time.LoadLocation("Asia/Taipei") | |
if err != nil { | |
log.Fatal(err) | |
} | |
} | |
// UnmarshalXML implements the xml.Unmarshaler interface. | |
// https://go.dev/play/p/14Un1FWtUf6 | |
func (ct *CustomTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) { | |
var v string | |
if err = d.DecodeElement(&v, &start); err != nil { | |
return err | |
} | |
var theTime time.Time | |
switch len(v) { | |
case 10: | |
theTime, err = time.Parse("2006-01-02", v) | |
case 19: | |
theTime, err = time.Parse("2006-01-02 15:04:05", v) | |
// ... 實作你自己的其他格式 | |
default: | |
err = xml.Unmarshal([]byte(fmt.Sprintf("<my>%s</my>", v)), &theTime) | |
} | |
if err != nil { | |
return err | |
} | |
_, offset := theTime.Zone() | |
if offset == 0 { // 假設UTC+0的內容實際上指的是UTC+8 | |
theTime = theTime.Add(-8 * time.Hour) // UTC-8 | |
theTime = theTime.In(locTaipei) // 再換回台北時間,會再+8 | |
} | |
ct.Time = theTime | |
return nil | |
} | |
type Person struct { | |
Name string `xml:"name"` | |
BirthDate CustomTime `xml:"birthdate"` | |
BirthDateSimple CustomTime `xml:"birthdate-simple"` | |
BirthDateDefault CustomTime `xml:"birthdate-default"` | |
} | |
func Test_xmlUnmarshal(t *testing.T) { | |
xmlData := ` | |
<person> | |
<name>John Doe</name> | |
<birthdate-simple>2024-08-19</birthdate-simple> | |
<birthdate>2024-08-19 18:40:00</birthdate> | |
<birthdate-default>2006-01-02T15:04:05-07:00</birthdate-default> | |
</person> | |
` | |
var p Person | |
err := xml.Unmarshal([]byte(xmlData), &p) | |
if err != nil { | |
t.Fatal(err) | |
} | |
for i, tt := range []struct { | |
Actual int64 | |
Expected int64 | |
}{ | |
{p.BirthDateSimple.Unix(), 1723996800}, | |
{p.BirthDate.Unix(), 1724064000}, | |
{p.BirthDateDefault.Unix(), 1136239445}, | |
} { | |
if tt.Actual != tt.Expected { | |
t.Fatal(i) | |
} | |
} | |
} |