Date precision (#6359)

* Remove month/year only formats from ParseDateStringAsTime
* Add precision field to Date and handle parsing year/month-only dates
* Add date precision columns for date columns
* Adjust UI to account for fuzzy dates
This commit is contained in:
WithoutPants
2025-12-08 09:11:40 +11:00
committed by GitHub
parent eb9d0705bc
commit 7db394bbea
23 changed files with 285 additions and 154 deletions

View File

@@ -1,31 +1,63 @@
package models
import (
"fmt"
"time"
"github.com/stashapp/stash/pkg/utils"
)
type DatePrecision int
const (
// default precision is day
DatePrecisionDay DatePrecision = iota
DatePrecisionMonth
DatePrecisionYear
)
// Date wraps a time.Time with a format of "YYYY-MM-DD"
type Date struct {
time.Time
Precision DatePrecision
}
const dateFormat = "2006-01-02"
var dateFormatPrecision = []string{
"2006-01-02",
"2006-01",
"2006",
}
func (d Date) String() string {
return d.Format(dateFormat)
return d.Format(dateFormatPrecision[d.Precision])
}
func (d Date) After(o Date) bool {
return d.Time.After(o.Time)
}
// ParseDate uses utils.ParseDateStringAsTime to parse a string into a date.
// ParseDate tries to parse the input string into a date using utils.ParseDateStringAsTime.
// If that fails, it attempts to parse the string with decreasing precision (month, then year).
// It returns a Date struct with the appropriate precision set, or an error if all parsing attempts fail.
func ParseDate(s string) (Date, error) {
var errs []error
// default parse to day precision
ret, err := utils.ParseDateStringAsTime(s)
if err != nil {
return Date{}, err
if err == nil {
return Date{Time: ret, Precision: DatePrecisionDay}, nil
}
return Date{Time: ret}, nil
errs = append(errs, err)
// try month and year precision
for i, format := range dateFormatPrecision[1:] {
ret, err := time.Parse(format, s)
if err == nil {
return Date{Time: ret, Precision: DatePrecision(i + 1)}, nil
}
errs = append(errs, err)
}
return Date{}, fmt.Errorf("failed to parse date %q: %v", s, errs)
}