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
141
142
143
144
145
146
|
// Code generated by astool. DO NOT EDIT.
package duration
import (
"fmt"
"math"
"regexp"
"strconv"
"time"
)
// SerializeDuration converts a duration value to an interface representation
// suitable for marshalling into a text or binary format.
func SerializeDuration(this time.Duration) (interface{}, error) {
// Seriously questioning my life choices.
s := "P"
if this < 0 {
s = "-P"
this = -1 * this
}
var tally time.Duration
// Assume 8760 Hours per 365 days, cannot account for leap years in xsd:duration. :(
if years := this.Hours() / 8760.0; years >= 1 {
nYears := int64(math.Floor(years))
tally += time.Duration(nYears) * 8760 * time.Hour
s = fmt.Sprintf("%s%dY", s, nYears)
}
// Assume 30 days per month, cannot account for months lasting 31, 30, 29, or 28 days in xsd:duration. :(
if months := (this.Hours() - tally.Hours()) / 720.0; months >= 1 {
nMonths := int64(math.Floor(months))
tally += time.Duration(nMonths) * 720 * time.Hour
s = fmt.Sprintf("%s%dM", s, nMonths)
}
if days := (this.Hours() - tally.Hours()) / 24.0; days >= 1 {
nDays := int64(math.Floor(days))
tally += time.Duration(nDays) * 24 * time.Hour
s = fmt.Sprintf("%s%dD", s, nDays)
}
if tally < this {
s = fmt.Sprintf("%sT", s)
if hours := this.Hours() - tally.Hours(); hours >= 1 {
nHours := int64(math.Floor(hours))
tally += time.Duration(nHours) * time.Hour
s = fmt.Sprintf("%s%dH", s, nHours)
}
if minutes := this.Minutes() - tally.Minutes(); minutes >= 1 {
nMinutes := int64(math.Floor(minutes))
tally += time.Duration(nMinutes) * time.Minute
s = fmt.Sprintf("%s%dM", s, nMinutes)
}
if seconds := this.Seconds() - tally.Seconds(); seconds >= 1 {
nSeconds := int64(math.Floor(seconds))
tally += time.Duration(nSeconds) * time.Second
s = fmt.Sprintf("%s%dS", s, nSeconds)
}
}
return s, nil
}
// DeserializeDuration creates duration value from an interface representation
// that has been unmarshalled from a text or binary format.
func DeserializeDuration(this interface{}) (time.Duration, error) {
// Maybe this time it will be easier.
if s, ok := this.(string); ok {
isNeg := false
if s[0] == '-' {
isNeg = true
s = s[1:]
}
if s[0] != 'P' {
return 0, fmt.Errorf("%s malformed: missing 'P' for xsd:duration", s)
}
re := regexp.MustCompile(`P(\d*Y)?(\d*M)?(\d*D)?(T(\d*H)?(\d*M)?(\d*S)?)?`)
res := re.FindStringSubmatch(s)
var dur time.Duration
nYear := res[1]
if len(nYear) > 0 {
nYear = nYear[:len(nYear)-1]
vYear, err := strconv.ParseInt(nYear, 10, 64)
if err != nil {
return 0, err
}
// Assume 8760 Hours per 365 days, cannot account for leap years in xsd:duration. :(
dur += time.Duration(vYear) * time.Hour * 8760
}
nMonth := res[2]
if len(nMonth) > 0 {
nMonth = nMonth[:len(nMonth)-1]
vMonth, err := strconv.ParseInt(nMonth, 10, 64)
if err != nil {
return 0, err
}
// Assume 30 days per month, cannot account for months lasting 31, 30, 29, or 28 days in xsd:duration. :(
dur += time.Duration(vMonth) * time.Hour * 720
}
nDay := res[3]
if len(nDay) > 0 {
nDay = nDay[:len(nDay)-1]
vDay, err := strconv.ParseInt(nDay, 10, 64)
if err != nil {
return 0, err
}
dur += time.Duration(vDay) * time.Hour * 24
}
nHour := res[5]
if len(nHour) > 0 {
nHour = nHour[:len(nHour)-1]
vHour, err := strconv.ParseInt(nHour, 10, 64)
if err != nil {
return 0, err
}
dur += time.Duration(vHour) * time.Hour
}
nMinute := res[6]
if len(nMinute) > 0 {
nMinute = nMinute[:len(nMinute)-1]
vMinute, err := strconv.ParseInt(nMinute, 10, 64)
if err != nil {
return 0, err
}
dur += time.Duration(vMinute) * time.Minute
}
nSecond := res[7]
if len(nSecond) > 0 {
nSecond = nSecond[:len(nSecond)-1]
vSecond, err := strconv.ParseInt(nSecond, 10, 64)
if err != nil {
return 0, err
}
dur += time.Duration(vSecond) * time.Second
}
if isNeg {
dur *= -1
}
return dur, nil
} else {
return 0, fmt.Errorf("%v cannot be interpreted as a string for xsd:duration", this)
}
}
// LessDuration returns true if the left duration value is less than the right
// value.
func LessDuration(lhs, rhs time.Duration) bool {
return lhs < rhs
}
|