153 lines
3.0 KiB
Go
153 lines
3.0 KiB
Go
package model
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func parseJumpTarget(raw string) (time.Duration, error) {
|
|
s := strings.TrimSpace(raw)
|
|
if s == "" {
|
|
return 0, fmt.Errorf("use ss, mm:ss, or hh:mm:ss format")
|
|
}
|
|
|
|
parts := strings.Split(s, ":")
|
|
switch len(parts) {
|
|
case 1:
|
|
secs, err := parseTotalSeconds(parts[0])
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return time.Duration(secs) * time.Second, nil
|
|
case 2:
|
|
minPart := normalizeClockField(parts[0])
|
|
secPart := normalizeClockField(parts[1])
|
|
|
|
mins, err := parseTotalMinutes(minPart)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
secs, err := parseClockSeconds(secPart)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return time.Duration(mins)*time.Minute + time.Duration(secs)*time.Second, nil
|
|
case 3:
|
|
hourPart := normalizeClockField(parts[0])
|
|
minPart := normalizeClockField(parts[1])
|
|
secPart := normalizeClockField(parts[2])
|
|
|
|
hours, err := parseTotalHours(hourPart)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
mins, err := parseClockMinutes(minPart)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
secs, err := parseClockSeconds(secPart)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return time.Duration(hours)*time.Hour +
|
|
time.Duration(mins)*time.Minute +
|
|
time.Duration(secs)*time.Second, nil
|
|
default:
|
|
return 0, fmt.Errorf("use ss, mm:ss, or hh:mm:ss format")
|
|
}
|
|
}
|
|
|
|
func normalizeClockField(s string) string {
|
|
s = strings.TrimSpace(s)
|
|
if s == "" {
|
|
return "0"
|
|
}
|
|
return s
|
|
}
|
|
|
|
func parseTotalSeconds(s string) (int, error) {
|
|
secs, err := parseNonNegativeInt(strings.TrimSpace(s), "seconds")
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return secs, nil
|
|
}
|
|
|
|
func parseTotalMinutes(s string) (int, error) {
|
|
mins, err := parseNonNegativeInt(s, "minutes")
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return mins, nil
|
|
}
|
|
|
|
func parseTotalHours(s string) (int, error) {
|
|
hours, err := parseNonNegativeInt(s, "hours")
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return hours, nil
|
|
}
|
|
|
|
func parseClockMinutes(s string) (int, error) {
|
|
if len(s) > 2 {
|
|
return 0, fmt.Errorf("minutes must be 0-59")
|
|
}
|
|
|
|
mins, err := parseNonNegativeInt(s, "minutes")
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if mins > 59 {
|
|
return 0, fmt.Errorf("minutes must be 0-59")
|
|
}
|
|
return mins, nil
|
|
}
|
|
|
|
func parseClockSeconds(s string) (int, error) {
|
|
if len(s) > 2 {
|
|
return 0, fmt.Errorf("seconds must be 0-59")
|
|
}
|
|
|
|
secs, err := parseNonNegativeInt(s, "seconds")
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if secs > 59 {
|
|
return 0, fmt.Errorf("seconds must be 0-59")
|
|
}
|
|
return secs, nil
|
|
}
|
|
|
|
func parseNonNegativeInt(s, label string) (int, error) {
|
|
if s == "" {
|
|
return 0, fmt.Errorf("%s must be a number", label)
|
|
}
|
|
for _, r := range s {
|
|
if r < '0' || r > '9' {
|
|
return 0, fmt.Errorf("%s must be a number", label)
|
|
}
|
|
}
|
|
v, err := strconv.Atoi(s)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("%s must be a number", label)
|
|
}
|
|
return v, nil
|
|
}
|
|
|
|
func formatJumpClock(d time.Duration) string {
|
|
if d < 0 {
|
|
d = 0
|
|
}
|
|
total := int(d.Seconds())
|
|
mm := total / 60
|
|
ss := total % 60
|
|
return fmt.Sprintf("%02d:%02d", mm, ss)
|
|
}
|
|
|
|
func formatJumpPlaceholder(d time.Duration) string {
|
|
return "00:00"
|
|
}
|