From b70d5f33d2453ada03b44b9c4408b171737e0f6e Mon Sep 17 00:00:00 2001 From: Stash Dev Date: Mon, 4 Mar 2019 17:14:52 -0800 Subject: [PATCH] Improved date handling --- pkg/api/resolver_mutation_performer.go | 4 +-- pkg/api/resolver_mutation_scene.go | 2 +- pkg/manager/jsonschema/time_rails.go | 9 +++-- pkg/manager/task_import.go | 6 ++-- pkg/models/model_performer.go | 2 +- pkg/models/model_scene.go | 2 +- pkg/models/model_scraped_item.go | 2 +- pkg/models/sqlite_date.go | 38 +++++++++++++++++++++ pkg/utils/date.go | 46 +++++++++++++++++++++++--- 9 files changed, 93 insertions(+), 18 deletions(-) create mode 100644 pkg/models/sqlite_date.go diff --git a/pkg/api/resolver_mutation_performer.go b/pkg/api/resolver_mutation_performer.go index 570875dc9..37222b2d3 100644 --- a/pkg/api/resolver_mutation_performer.go +++ b/pkg/api/resolver_mutation_performer.go @@ -32,7 +32,7 @@ func (r *mutationResolver) PerformerCreate(ctx context.Context, input models.Per newPerformer.URL = sql.NullString{String: *input.URL, Valid: true} } if input.Birthdate != nil { - newPerformer.Birthdate = sql.NullString{String: *input.Birthdate, Valid: true} + newPerformer.Birthdate = models.SQLiteDate{String: *input.Birthdate, Valid: true} } if input.Ethnicity != nil { newPerformer.Ethnicity = sql.NullString{String: *input.Ethnicity, Valid: true} @@ -115,7 +115,7 @@ func (r *mutationResolver) PerformerUpdate(ctx context.Context, input models.Per updatedPerformer.URL = sql.NullString{String: *input.URL, Valid: true} } if input.Birthdate != nil { - updatedPerformer.Birthdate = sql.NullString{String: *input.Birthdate, Valid: true} + updatedPerformer.Birthdate = models.SQLiteDate{String: *input.Birthdate, Valid: true} } if input.Ethnicity != nil { updatedPerformer.Ethnicity = sql.NullString{String: *input.Ethnicity, Valid: true} diff --git a/pkg/api/resolver_mutation_scene.go b/pkg/api/resolver_mutation_scene.go index 7acaaa931..0331cbdfe 100644 --- a/pkg/api/resolver_mutation_scene.go +++ b/pkg/api/resolver_mutation_scene.go @@ -27,7 +27,7 @@ func (r *mutationResolver) SceneUpdate(ctx context.Context, input models.SceneUp updatedScene.URL = sql.NullString{String: *input.URL, Valid: true} } if input.Date != nil { - updatedScene.Date = sql.NullString{String: *input.Date, Valid: true} + updatedScene.Date = models.SQLiteDate{String: *input.Date, Valid: true} } if input.Rating != nil { updatedScene.Rating = sql.NullInt64{Int64: int64(*input.Rating), Valid: true} diff --git a/pkg/manager/jsonschema/time_rails.go b/pkg/manager/jsonschema/time_rails.go index c63526afd..15123b882 100644 --- a/pkg/manager/jsonschema/time_rails.go +++ b/pkg/manager/jsonschema/time_rails.go @@ -2,6 +2,7 @@ package jsonschema import ( "fmt" + "github.com/stashapp/stash/pkg/utils" "strings" "time" ) @@ -10,17 +11,15 @@ type RailsTime struct { time.Time } -const railsTimeLayout = "2006-01-02 15:04:05 MST" - func (ct *RailsTime) UnmarshalJSON(b []byte) (err error) { s := strings.Trim(string(b), "\"") if s == "null" { ct.Time = time.Time{} return } - ct.Time, err = time.Parse(railsTimeLayout, s) - if err != nil { - ct.Time, err = time.Parse(time.RFC3339, s) + t, err := utils.ParseDateStringAsTime(s) + if t != nil { + ct.Time = *t } return } diff --git a/pkg/manager/task_import.go b/pkg/manager/task_import.go index 0d360f1d7..e43322ce7 100644 --- a/pkg/manager/task_import.go +++ b/pkg/manager/task_import.go @@ -88,7 +88,7 @@ func (t *ImportTask) ImportPerformers(ctx context.Context) { newPerformer.URL = sql.NullString{String: performerJSON.URL, Valid: true} } if performerJSON.Birthdate != "" { - newPerformer.Birthdate = sql.NullString{String: performerJSON.Birthdate, Valid: true} + newPerformer.Birthdate = models.SQLiteDate{String: performerJSON.Birthdate, Valid: true} } if performerJSON.Ethnicity != "" { newPerformer.Ethnicity = sql.NullString{String: performerJSON.Ethnicity, Valid: true} @@ -317,7 +317,7 @@ func (t *ImportTask) ImportScrapedItems(ctx context.Context) { Title: sql.NullString{String: mappingJSON.Title, Valid: true}, Description: sql.NullString{String: mappingJSON.Description, Valid: true}, URL: sql.NullString{String: mappingJSON.URL, Valid: true}, - Date: sql.NullString{String: mappingJSON.Date, Valid: true}, + Date: models.SQLiteDate{String: mappingJSON.Date, Valid: true}, Rating: sql.NullString{String: mappingJSON.Rating, Valid: true}, Tags: sql.NullString{String: mappingJSON.Tags, Valid: true}, Models: sql.NullString{String: mappingJSON.Models, Valid: true}, @@ -392,7 +392,7 @@ func (t *ImportTask) ImportScenes(ctx context.Context) { newScene.URL = sql.NullString{String: sceneJSON.URL, Valid: true} } if sceneJSON.Date != "" { - newScene.Date = sql.NullString{String: sceneJSON.Date, Valid: true} + newScene.Date = models.SQLiteDate{String: sceneJSON.Date, Valid: true} } if sceneJSON.Rating != 0 { newScene.Rating = sql.NullInt64{Int64: int64(sceneJSON.Rating), Valid: true} diff --git a/pkg/models/model_performer.go b/pkg/models/model_performer.go index 97edb8051..8d3beb3db 100644 --- a/pkg/models/model_performer.go +++ b/pkg/models/model_performer.go @@ -12,7 +12,7 @@ type Performer struct { URL sql.NullString `db:"url" json:"url"` Twitter sql.NullString `db:"twitter" json:"twitter"` Instagram sql.NullString `db:"instagram" json:"instagram"` - Birthdate sql.NullString `db:"birthdate" json:"birthdate"` // TODO dates? + Birthdate SQLiteDate `db:"birthdate" json:"birthdate"` Ethnicity sql.NullString `db:"ethnicity" json:"ethnicity"` Country sql.NullString `db:"country" json:"country"` EyeColor sql.NullString `db:"eye_color" json:"eye_color"` diff --git a/pkg/models/model_scene.go b/pkg/models/model_scene.go index c065293c0..0b480c30e 100644 --- a/pkg/models/model_scene.go +++ b/pkg/models/model_scene.go @@ -11,7 +11,7 @@ type Scene struct { Title sql.NullString `db:"title" json:"title"` Details sql.NullString `db:"details" json:"details"` URL sql.NullString `db:"url" json:"url"` - Date sql.NullString `db:"date" json:"date"` // TODO dates? + Date SQLiteDate `db:"date" json:"date"` Rating sql.NullInt64 `db:"rating" json:"rating"` Size sql.NullString `db:"size" json:"size"` Duration sql.NullFloat64 `db:"duration" json:"duration"` diff --git a/pkg/models/model_scraped_item.go b/pkg/models/model_scraped_item.go index 6f3984777..8a24fabeb 100644 --- a/pkg/models/model_scraped_item.go +++ b/pkg/models/model_scraped_item.go @@ -9,7 +9,7 @@ type ScrapedItem struct { Title sql.NullString `db:"title" json:"title"` Description sql.NullString `db:"description" json:"description"` URL sql.NullString `db:"url" json:"url"` - Date sql.NullString `db:"date" json:"date"` // TODO dates? + Date SQLiteDate `db:"date" json:"date"` Rating sql.NullString `db:"rating" json:"rating"` Tags sql.NullString `db:"tags" json:"tags"` Models sql.NullString `db:"models" json:"models"` diff --git a/pkg/models/sqlite_date.go b/pkg/models/sqlite_date.go new file mode 100644 index 000000000..e2c670161 --- /dev/null +++ b/pkg/models/sqlite_date.go @@ -0,0 +1,38 @@ +package models + +import ( + "database/sql/driver" + "github.com/stashapp/stash/pkg/logger" + "github.com/stashapp/stash/pkg/utils" + "time" +) + +type SQLiteDate struct { + String string + Valid bool +} + +// Scan implements the Scanner interface. +func (t *SQLiteDate) Scan(value interface{}) error { + dateTime, ok := value.(time.Time) + if !ok { + t.String = "" + t.Valid = false + return nil + } + + t.String = dateTime.Format("2006-01-02") + if t.String != "" { + t.Valid = true + } + return nil +} + +// Value implements the driver Valuer interface. +func (t SQLiteDate) Value() (driver.Value, error) { + result, err := utils.ParseDateStringAsFormat(t.String, "2006-01-02") + if err != nil { + logger.Debugf("sqlite date conversion error: %s", err.Error()) + } + return result, nil +} diff --git a/pkg/utils/date.go b/pkg/utils/date.go index 715b304ff..b88f2d793 100644 --- a/pkg/utils/date.go +++ b/pkg/utils/date.go @@ -1,9 +1,47 @@ package utils -import "time" +import ( + "fmt" + "time" +) + +const railsTimeLayout = "2006-01-02 15:04:05 MST" func GetYMDFromDatabaseDate(dateString string) string { - t, _ := time.Parse(time.RFC3339, dateString) - // https://stackoverflow.com/a/20234207 WTF? - return t.Format("2006-01-02") + result, _ := ParseDateStringAsFormat(dateString, "2006-01-02") + return result +} + +func ParseDateStringAsFormat(dateString string, format string) (string, error) { + t, e := ParseDateStringAsTime(dateString) + if t != nil { + return t.Format(format), e + } + return "", fmt.Errorf("ParseDateStringAsFormat failed: dateString <%s>, format <%s>", dateString, format) +} + +func ParseDateStringAsTime(dateString string) (*time.Time, error) { + // https://stackoverflow.com/a/20234207 WTF? + + t, e := time.Parse(time.RFC3339, dateString) + if e == nil { + return &t, nil + } + + t, e = time.Parse("2006-01-02", dateString) + if e == nil { + return &t, nil + } + + t, e = time.Parse("2006-01-02 15:04:05", dateString) + if e == nil { + return &t, nil + } + + t, e = time.Parse(railsTimeLayout, dateString) + if e == nil { + return &t, nil + } + + return nil, fmt.Errorf("ParseDateStringAsTime failed: dateString <%s>", dateString) }