60 lines
1.4 KiB
Go
60 lines
1.4 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// ErrZoneOffsetInvalid is thrown when a zone string is an invalid zone offset
|
|
var ErrZoneOffsetInvalid = errors.New("offset zone invalid")
|
|
|
|
const zoneHour = 60 * 60
|
|
const zoneMinute = 60
|
|
|
|
var zoneOffsetRegexp = regexp.MustCompile("^[+-\u2212][0-9]{2}:[0-9]{2}$")
|
|
|
|
// ParseZoneOffset parses a zone string into an offset
|
|
func ParseZoneOffset(zone string) (int, error) {
|
|
if !zoneOffsetRegexp.MatchString(zone) {
|
|
return 0, ErrZoneOffsetInvalid
|
|
}
|
|
// Assume that if it satisfies the regex, it satisfies the length and won't
|
|
// fail to parse
|
|
d := 0
|
|
if strings.HasPrefix(zone, "+") {
|
|
d = 1
|
|
}
|
|
if strings.HasPrefix(zone, "-") || strings.HasPrefix(zone, "\u2212") {
|
|
d = -1
|
|
}
|
|
zone = strings.TrimLeft(zone, "+-\u2212")
|
|
parts := strings.Split(zone, ":")
|
|
h, _ := strconv.ParseUint(parts[0], 10, 64)
|
|
// Allow hour offsets greater that 24
|
|
m, _ := strconv.ParseUint(parts[1], 10, 64)
|
|
if m >= 60 {
|
|
return 0, ErrZoneOffsetInvalid
|
|
}
|
|
offset := d * (int(h)*zoneHour + int(m)*zoneMinute)
|
|
return offset, nil
|
|
}
|
|
|
|
// FormatZoneOffset formats an offset into a string
|
|
func FormatZoneOffset(offset int) string {
|
|
neg := offset < 0
|
|
s := '+'
|
|
if neg {
|
|
s = '\u2212'
|
|
offset = -offset
|
|
}
|
|
if offset == 0 {
|
|
return "\u00b100:00"
|
|
}
|
|
h := offset / zoneHour
|
|
m := (offset % zoneHour) / zoneMinute
|
|
return fmt.Sprintf("%c%02d:%02d", s, h, m)
|
|
}
|