Skip to content

Instantly share code, notes, and snippets.

@CarsonSlovoka
Last active August 19, 2024 11:24
Show Gist options
  • Save CarsonSlovoka/39cdaf14276f0ec9010be2bbe4a2092a to your computer and use it in GitHub Desktop.
Save CarsonSlovoka/39cdaf14276f0ec9010be2bbe4a2092a to your computer and use it in GitHub Desktop.
xml.UnmarshalXML

go想對xml的時間自定義Unmarshal,那麼要滿足 xml.Unmarshaler 接口

type Unmarshaler interface {
	UnmarshalXML(d *Decoder, start StartElement) error
}

go-playground

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)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment