1
0
Fork 0
datetime.link/zoneoffset.go

57 lines
1.2 KiB
Go

package main
import (
"errors"
"fmt"
"regexp"
"strconv"
)
// 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(`^[+-][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 zone[0] == '+' {
d = 1
}
if zone[0] == '-' {
d = -1
}
h, _ := strconv.ParseUint(zone[1:1+2], 10, 64)
// Allow hour offsets greater that 24
m, _ := strconv.ParseUint(zone[1+3:1+3+2], 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 = '-'
offset = -offset
}
if offset == 0 {
return "\u00B100:00"
}
h := offset / zoneHour
m := (offset % zoneHour) / zoneMinute
return fmt.Sprintf("%c%02d:%02d", s, h, m)
}