A *time.Time placed in an any typed field is incorrectly encoded as a string in an XML formatted plist
type Structure struct {
UntypedPtr any
}
now := time.Date(2003, 2, 3, 9, 15, 30, 0, time.UTC)
s := &Structure{ UntypedPtr: &now }
Below is a test showing the current behaviour and expected output. The test shows that directly encoding the values works as expected. Only when the same values are embedded within a structure does the encoding bug appear:
func TestPlistDates(t *testing.T) {
var (
date time.Time = time.Date(2003, 2, 3, 9, 15, 30, 0, time.UTC)
datePtr = &date
untyped any = date
untypedPtr any = &date
)
expectDateEncoding := `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<date>2003-02-03T09:15:30Z</date>
</plist>`
if b, err := plist.MarshalIndent(date, plist.XMLFormat, " "); err != nil {
t.Error(err)
} else if string(b) != expectDateEncoding {
t.Errorf("expect:\n%s\ngot:\n%s", expectDateEncoding, string(b))
}
if b, err := plist.MarshalIndent(datePtr, plist.XMLFormat, " "); err != nil {
t.Error(err)
} else if string(b) != expectDateEncoding {
t.Errorf("expect:\n%s\ngot:\n%s", expectDateEncoding, string(b))
}
if b, err := plist.MarshalIndent(untyped, plist.XMLFormat, " "); err != nil {
t.Error(err)
} else if string(b) != expectDateEncoding {
t.Errorf("expect:\n%s\ngot:\n%s", expectDateEncoding, string(b))
}
if b, err := plist.MarshalIndent(untypedPtr, plist.XMLFormat, " "); err != nil {
t.Error(err)
} else if string(b) != expectDateEncoding {
t.Errorf("expect:\n%s\ngot:\n%s", expectDateEncoding, string(b))
}
type Structure struct {
Date time.Time
DatePtr *time.Time
Untyped any
UntypedPtr any
}
s := &Structure{
Date: date,
DatePtr: datePtr,
Untyped: untyped,
UntypedPtr: untypedPtr,
}
expectStructureEncoding := `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Date</key>
<date>2003-02-03T09:15:30Z</date>
<key>DatePtr</key>
<date>2003-02-03T09:15:30Z</date>
<key>Untyped</key>
<date>2003-02-03T09:15:30Z</date>
<key>UntypedPtr</key>
<date>2003-02-03T09:15:30Z</date>
</dict>
</plist>`
if b, err := plist.MarshalIndent(s, plist.XMLFormat, " "); err != nil {
t.Error(err)
} else if string(b) != expectStructureEncoding {
t.Errorf("expect:\n%s\ngot:\n%s", expectStructureEncoding, string(b))
}
}
The current incorrect output is below. The final key/value pair should be a date, not a string:
A
*time.Time
placed in anany
typed field is incorrectly encoded as astring
in an XML formatted plistBelow is a test showing the current behaviour and expected output. The test shows that directly encoding the values works as expected. Only when the same values are embedded within a structure does the encoding bug appear:
The current incorrect output is below. The final key/value pair should be a
date
, not astring
:This is an esoteric bug that is unlikely to have a significant impact. I am documenting the problem here in case others stumble upon it.