Skip to content

Commit 1d1a2ef

Browse files
committed
Implement to unmarshal PT duration
1 parent 67a2211 commit 1d1a2ef

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

mpd/duration.go

+50
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ package mpd
44

55
import (
66
"encoding/xml"
7+
"strconv"
8+
"strings"
79
"time"
810
)
911

@@ -13,6 +15,15 @@ func (d Duration) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
1315
return xml.Attr{name, d.String()}, nil
1416
}
1517

18+
func (d *Duration) UnmarshalXMLAttr(attr xml.Attr) error {
19+
dur, err := parseDuration(attr.Value)
20+
if err != nil {
21+
return err
22+
}
23+
*d = Duration(dur)
24+
return nil
25+
}
26+
1627
// String renders a Duration in XML Duration Data Type format
1728
func (d *Duration) String() string {
1829
// Largest time is 2540400h10m10.000000000s
@@ -126,3 +137,42 @@ func fmtInt(buf []byte, v uint64) int {
126137
}
127138
return w
128139
}
140+
141+
func parseDuration(str string) (time.Duration, error) {
142+
if strings.HasPrefix(str, "PT") {
143+
offset := 2
144+
var sum float64
145+
146+
if i := strings.Index(str[offset:], "H"); i != -1 {
147+
hours, err := strconv.ParseInt(str[offset:offset+i], 10, 64)
148+
if err != nil {
149+
return 0, err
150+
}
151+
sum += float64(hours) * 60 * 60
152+
offset += i + 1
153+
}
154+
if i := strings.Index(str[offset:], "M"); i != -1 {
155+
minutes, err := strconv.ParseInt(str[offset:offset+i], 10, 64)
156+
if err != nil {
157+
return 0, err
158+
}
159+
sum += float64(minutes) * 60
160+
offset += i + 1
161+
}
162+
if i := strings.Index(str[offset:], "S"); i != -1 {
163+
seconds, err := strconv.ParseFloat(str[offset:offset+i], 64)
164+
if err != nil {
165+
return 0, err
166+
}
167+
sum += seconds
168+
}
169+
170+
return time.Duration(sum * float64(time.Second)), nil
171+
}
172+
173+
dur, err := strconv.ParseFloat(str, 64)
174+
if err != nil {
175+
return 0, err
176+
}
177+
return time.Duration(dur * float64(time.Second)), nil
178+
}

mpd/duration_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,19 @@ func TestDuration(t *testing.T) {
2020
assert.Equal(t, ex, dur.String())
2121
}
2222
}
23+
24+
func TestParseDuration(t *testing.T) {
25+
in := map[string]float64{
26+
"PT0S": 0,
27+
"PT1M": 60,
28+
"PT2H": 7200,
29+
"PT6M16S": 376,
30+
"PT1.97S": 1.97,
31+
"PT1H2M3.456S": 3723.456,
32+
}
33+
for ins, ex := range in {
34+
act, err := parseDuration(ins)
35+
assert.NoError(t, err)
36+
assert.Equal(t, ex, act.Seconds())
37+
}
38+
}

0 commit comments

Comments
 (0)