-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathp6y.go
140 lines (118 loc) · 2.16 KB
/
p6y.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package p6y
import (
"errors"
"fmt"
"strconv"
"strings"
)
type duration struct {
years int
months int
days int
weeks int
hours int
minutes int
seconds int
}
func (d duration) Years() int {
return d.years
}
func (d duration) Months() int {
return d.months
}
func (d duration) Days() int {
return d.days
}
func (d duration) Weeks() int {
return d.weeks
}
func (d duration) Hours() int {
return d.hours
}
func (d duration) Minutes() int {
return d.minutes
}
func (d duration) Seconds() int {
return d.seconds
}
func NewDuration(s string) (duration, error) {
var d, tmp duration
e := errors.New("failed to parse input string")
if len(s) < 3 || s[0] != 'P' {
return d, e
}
var wc string
var err error
d.weeks, wc, err = extrct(s[1:], "W")
if err != nil || (err == nil && len(wc) > 0 && wc != s[1:]) {
return tmp, e
} else if wc != s[1:] {
return d, nil
}
cs := strings.Split(s, "T")
var dc, tc string
if len(cs) == 2 {
dc, tc = cs[0][1:], cs[1]
} else if len(cs) == 1 {
if cs[0][0] == 'P' {
dc = cs[0][1:]
} else {
tc = cs[0]
}
} else {
return tmp, e
}
if dc == "" && tc == "" {
return tmp, e
}
if dc != "" {
var err error
d.years, dc, err = extrct(dc, "Y")
if err != nil {
return tmp, err
}
d.months, dc, err = extrct(dc, "M")
if err != nil {
return tmp, err
}
d.days, dc, err = extrct(dc, "D")
if err != nil {
return tmp, err
}
}
if tc != "" {
var err error
d.hours, tc, err = extrct(tc, "H")
if err != nil {
return tmp, err
}
d.minutes, tc, err = extrct(tc, "M")
if err != nil {
return tmp, err
}
d.seconds, tc, err = extrct(tc, "S")
if err != nil {
return tmp, err
}
}
if len(tc) > 0 || len(dc) > 0 {
return tmp, e
}
return d, nil
}
func extrct(s, t string) (int, string, error) {
var tval int
tpos := strings.Index(s, t)
if tpos == 0 {
return 0, "", errors.New(fmt.Sprintf("'%s' token without value", t))
} else if tpos > 0 {
tpart := s[0:tpos]
var err error
tval, err = strconv.Atoi(tpart)
if err != nil || tval < 0 {
return 0, "", errors.New(fmt.Sprintf("negative '%s' token value", t))
}
s = s[tpos+1:]
}
return tval, s, nil
}