mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-01 10:40:30 -05:00
129 lines
2.9 KiB
Go
129 lines
2.9 KiB
Go
package saml
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Duration is a time.Duration that uses the xsd:duration format for text
|
|
// marshalling and unmarshalling.
|
|
type Duration time.Duration
|
|
|
|
// MarshalText implements the encoding.TextMarshaler interface.
|
|
func (d Duration) MarshalText() ([]byte, error) {
|
|
if d == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
out := "PT"
|
|
if d < 0 {
|
|
d *= -1
|
|
out = "-" + out
|
|
}
|
|
|
|
h := time.Duration(d) / time.Hour
|
|
m := time.Duration(d) % time.Hour / time.Minute
|
|
s := time.Duration(d) % time.Minute / time.Second
|
|
ns := time.Duration(d) % time.Second
|
|
if h > 0 {
|
|
out += fmt.Sprintf("%dH", h)
|
|
}
|
|
if m > 0 {
|
|
out += fmt.Sprintf("%dM", m)
|
|
}
|
|
if s > 0 || ns > 0 {
|
|
out += fmt.Sprintf("%d", s)
|
|
if ns > 0 {
|
|
out += strings.TrimRight(fmt.Sprintf(".%09d", ns), "0")
|
|
}
|
|
out += "S"
|
|
}
|
|
|
|
return []byte(out), nil
|
|
}
|
|
|
|
const (
|
|
day = 24 * time.Hour
|
|
month = 30 * day // Assumed to be 30 days.
|
|
year = 365 * day // Assumed to be non-leap year.
|
|
)
|
|
|
|
var (
|
|
durationRegexp = regexp.MustCompile(`^(-?)P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(.+))?$`)
|
|
durationTimeRegexp = regexp.MustCompile(`^(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?$`)
|
|
)
|
|
|
|
// UnmarshalText implements the encoding.TextUnmarshaler interface.
|
|
func (d *Duration) UnmarshalText(text []byte) error {
|
|
if text == nil {
|
|
*d = 0
|
|
return nil
|
|
}
|
|
|
|
var (
|
|
out time.Duration
|
|
sign time.Duration = 1
|
|
)
|
|
match := durationRegexp.FindStringSubmatch(string(text))
|
|
if match == nil || strings.Join(match[2:6], "") == "" {
|
|
return fmt.Errorf("invalid duration (%s)", text)
|
|
}
|
|
if match[1] == "-" {
|
|
sign = -1
|
|
}
|
|
if match[2] != "" {
|
|
y, err := strconv.Atoi(match[2])
|
|
if err != nil {
|
|
return fmt.Errorf("invalid duration years (%s): %s", text, err)
|
|
}
|
|
out += time.Duration(y) * year
|
|
}
|
|
if match[3] != "" {
|
|
m, err := strconv.Atoi(match[3])
|
|
if err != nil {
|
|
return fmt.Errorf("invalid duration months (%s): %s", text, err)
|
|
}
|
|
out += time.Duration(m) * month
|
|
}
|
|
if match[4] != "" {
|
|
d, err := strconv.Atoi(match[4])
|
|
if err != nil {
|
|
return fmt.Errorf("invalid duration days (%s): %s", text, err)
|
|
}
|
|
out += time.Duration(d) * day
|
|
}
|
|
if match[5] != "" {
|
|
match := durationTimeRegexp.FindStringSubmatch(match[5])
|
|
if match == nil {
|
|
return fmt.Errorf("invalid duration (%s)", text)
|
|
}
|
|
if match[1] != "" {
|
|
h, err := strconv.Atoi(match[1])
|
|
if err != nil {
|
|
return fmt.Errorf("invalid duration hours (%s): %s", text, err)
|
|
}
|
|
out += time.Duration(h) * time.Hour
|
|
}
|
|
if match[2] != "" {
|
|
m, err := strconv.Atoi(match[2])
|
|
if err != nil {
|
|
return fmt.Errorf("invalid duration minutes (%s): %s", text, err)
|
|
}
|
|
out += time.Duration(m) * time.Minute
|
|
}
|
|
if match[3] != "" {
|
|
s, err := strconv.ParseFloat(match[3], 64)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid duration seconds (%s): %s", text, err)
|
|
}
|
|
out += time.Duration(s * float64(time.Second))
|
|
}
|
|
}
|
|
|
|
*d = Duration(sign * out)
|
|
return nil
|
|
}
|