73 lines
1.5 KiB
Go
73 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// ErrMissingComponent is thrown when the URL has empty or missing components
|
|
var ErrMissingComponent = errors.New("missing path component")
|
|
|
|
// ErrTooManyComponent is thrown when there are more than 2 components
|
|
var ErrTooManyComponent = errors.New("too many path components")
|
|
|
|
// ErrInvalidTime is thrown in a time.ParseError
|
|
var ErrInvalidTime = errors.New("invalid ISO 8601 time")
|
|
|
|
var timeRFC3339NoSec = "2006-01-02T15:04Z07:00"
|
|
var timeFormats = []string{time.RFC3339, timeRFC3339NoSec}
|
|
|
|
// Request is a parsed datetime URL
|
|
type Request struct {
|
|
Time time.Time
|
|
Zones []string
|
|
}
|
|
|
|
// ParseRequest parses an input URL into a Request
|
|
func ParseRequest(u *url.URL) (Request, error) {
|
|
var err error
|
|
|
|
parts := strings.Split(u.Path, "/")[1:]
|
|
if len(parts) > 2 {
|
|
return Request{}, ErrTooManyComponent
|
|
}
|
|
if len(parts) < 1 {
|
|
return Request{}, ErrMissingComponent
|
|
}
|
|
|
|
// Parse time portion
|
|
var t time.Time
|
|
timeString := parts[0]
|
|
if len(timeString) == 0 {
|
|
return Request{}, ErrMissingComponent
|
|
}
|
|
for _, f := range timeFormats {
|
|
t, err = time.Parse(f, timeString)
|
|
if err == nil {
|
|
break
|
|
}
|
|
}
|
|
if err != nil {
|
|
return Request{}, fmt.Errorf("%w: %v", ErrInvalidTime, err)
|
|
}
|
|
|
|
// Split zones
|
|
var z []string
|
|
zoneString := ""
|
|
if len(parts) >= 2 {
|
|
zoneString = parts[1]
|
|
}
|
|
if len(zoneString) == 0 {
|
|
return Request{}, ErrMissingComponent
|
|
}
|
|
z = strings.Split(zoneString, ",")
|
|
|
|
return Request{
|
|
Time: t,
|
|
Zones: z,
|
|
}, nil
|
|
}
|