init push

This commit is contained in:
2026-07-16 22:16:45 +07:00
commit 8b068bdb10
1021 changed files with 332816 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
package nextdue
import (
"fmt"
"strconv"
"strings"
"time"
)
type ValueKind string
const (
ValueKindUnknown ValueKind = ""
ValueKindHours ValueKind = "hours"
ValueKindDate ValueKind = "date"
)
type Value struct {
Kind ValueKind
Raw string
Hours *float64
Date *time.Time
}
type ParseError struct {
Field string
Raw string
Msg string
}
func (e *ParseError) Error() string {
if e == nil {
return ""
}
if strings.TrimSpace(e.Field) == "" {
return e.Msg
}
return fmt.Sprintf("%s: %s", e.Field, e.Msg)
}
type Parser struct {
DateLayout string
}
func NewParser() Parser { return Parser{DateLayout: "2006-01-02"} }
func (p Parser) Parse(field, raw string) (Value, error) {
raw = strings.TrimSpace(raw)
if raw == "" {
return Value{Kind: ValueKindUnknown, Raw: ""}, nil
}
if d, err := time.Parse(p.dateLayout(), raw); err == nil {
dd := d.UTC()
return Value{Kind: ValueKindDate, Raw: raw, Date: &dd}, nil
}
if h, err := strconv.ParseFloat(raw, 64); err == nil {
return Value{Kind: ValueKindHours, Raw: raw, Hours: &h}, nil
}
return Value{}, &ParseError{Field: field, Raw: raw, Msg: "must be either an ISO date (YYYY-MM-DD) or a numeric hour value"}
}
func IsUnset(v Value) bool {
switch v.Kind {
case ValueKindHours:
return v.Hours == nil || *v.Hours <= 0
case ValueKindDate:
return v.Date == nil || v.Date.IsZero()
default:
return true
}
}
func (p Parser) dateLayout() string {
if strings.TrimSpace(p.DateLayout) == "" {
return "2006-01-02"
}
return p.DateLayout
}
func NormalizeDate(t time.Time) time.Time {
return time.Date(t.UTC().Year(), t.UTC().Month(), t.UTC().Day(), 0, 0, 0, 0, time.UTC)
}