Compare commits

..

No commits in common. "7de4408926538d9a09e4a4aefd19833830fe5681" and "7360744e34f540acaec057390222505d065f9a2d" have entirely different histories.

7 changed files with 165 additions and 296 deletions

View File

@ -66,6 +66,7 @@ func (d *Date) UnmarshalJSON(data []byte) error {
} }
func NewDate(year, month, day int) Date { func NewDate(year, month, day int) Date {
if year == 0 || month == 0 || month > 12 || day == 0 { if year == 0 || month == 0 || month > 12 || day == 0 {
return Date{} return Date{}
} }

View File

@ -1,110 +1,111 @@
package item package item
import ( import (
"encoding/json"
"fmt"
"time" "time"
) )
type EventBody struct { type EventBody struct {
Title string `json:"title"` Title string `json:"title"`
Date Date `json:"date"` Start time.Time `json:"start"`
Time Time `json:"time"`
Duration time.Duration `json:"duration"` Duration time.Duration `json:"duration"`
} }
// func (e EventBody) MarshalJSON() ([]byte, error) { func (e EventBody) MarshalJSON() ([]byte, error) {
// type Alias EventBody type Alias EventBody
// return json.Marshal(&struct { return json.Marshal(&struct {
// Start string `json:"start"` Start string `json:"start"`
// Duration string `json:"duration"` Duration string `json:"duration"`
// *Alias *Alias
// }{ }{
// Start: e.Start.UTC().Format(time.RFC3339), Start: e.Start.UTC().Format(time.RFC3339),
// Duration: e.Duration.String(), Duration: e.Duration.String(),
// Alias: (*Alias)(&e), Alias: (*Alias)(&e),
// }) })
// } }
// func (e *EventBody) UnmarshalJSON(data []byte) error { func (e *EventBody) UnmarshalJSON(data []byte) error {
// type Alias EventBody type Alias EventBody
// aux := &struct { aux := &struct {
// Start string `json:"start"` Start string `json:"start"`
// Duration string `json:"duration"` Duration string `json:"duration"`
// *Alias *Alias
// }{ }{
// Alias: (*Alias)(e), Alias: (*Alias)(e),
// } }
// if err := json.Unmarshal(data, &aux); err != nil { if err := json.Unmarshal(data, &aux); err != nil {
// return err return err
// } }
// var err error var err error
// if e.Start, err = time.Parse(time.RFC3339, aux.Start); err != nil { if e.Start, err = time.Parse(time.RFC3339, aux.Start); err != nil {
// return err return err
// } }
// if e.Duration, err = time.ParseDuration(aux.Duration); err != nil { if e.Duration, err = time.ParseDuration(aux.Duration); err != nil {
// return err return err
// } }
// return nil return nil
// } }
// type Event struct { type Event struct {
// ID string `json:"id"` ID string `json:"id"`
// Recurrer Recurrer `json:"recurrer"` Recurrer Recurrer `json:"recurrer"`
// RecurNext time.Time `json:"recurNext"` RecurNext time.Time `json:"recurNext"`
// EventBody EventBody
// } }
// func NewEvent(i Item) (Event, error) { func NewEvent(i Item) (Event, error) {
// if i.Kind != KindEvent { if i.Kind != KindEvent {
// return Event{}, fmt.Errorf("item is not an event") return Event{}, fmt.Errorf("item is not an event")
// } }
// var e Event var e Event
// if err := json.Unmarshal([]byte(i.Body), &e); err != nil { if err := json.Unmarshal([]byte(i.Body), &e); err != nil {
// return Event{}, fmt.Errorf("could not unmarshal item body: %v", err) return Event{}, fmt.Errorf("could not unmarshal item body: %v", err)
// } }
// e.ID = i.ID e.ID = i.ID
// e.Recurrer = i.Recurrer e.Recurrer = i.Recurrer
// e.RecurNext = i.RecurNext e.RecurNext = i.RecurNext
// return e, nil return e, nil
// } }
// func (e Event) Item() (Item, error) { func (e Event) Item() (Item, error) {
// body, err := json.Marshal(EventBody{ body, err := json.Marshal(EventBody{
// Title: e.Title, Title: e.Title,
// Start: e.Start, Start: e.Start,
// Duration: e.Duration, Duration: e.Duration,
// }) })
// if err != nil { if err != nil {
// return Item{}, fmt.Errorf("could not marshal event to json") return Item{}, fmt.Errorf("could not marshal event to json")
// } }
// return Item{ return Item{
// ID: e.ID, ID: e.ID,
// Kind: KindEvent, Kind: KindEvent,
// Recurrer: e.Recurrer, Recurrer: e.Recurrer,
// RecurNext: e.RecurNext, RecurNext: e.RecurNext,
// Body: string(body), Body: string(body),
// }, nil }, nil
// } }
// func (e Event) Valid() bool { func (e Event) Valid() bool {
// if e.Title == "" { if e.Title == "" {
// return false return false
// } }
// if e.Start.IsZero() || e.Start.Year() < 2024 { if e.Start.IsZero() || e.Start.Year() < 2024 {
// return false return false
// } }
// if e.Duration.Seconds() < 1 { if e.Duration.Seconds() < 1 {
// return false return false
// } }
// // if e.Recurrer != nil && !e.Recurrer.Valid() { // if e.Recurrer != nil && !e.Recurrer.Valid() {
// // return false // return false
// // } // }
// return true return true
// } }

View File

@ -23,7 +23,7 @@ type Item struct {
Updated time.Time `json:"updated"` Updated time.Time `json:"updated"`
Deleted bool `json:"deleted"` Deleted bool `json:"deleted"`
Recurrer Recurrer `json:"recurrer"` Recurrer Recurrer `json:"recurrer"`
RecurNext Date `json:"recurNext"` RecurNext time.Time `json:"recurNext"`
Body string `json:"body"` Body string `json:"body"`
} }

View File

@ -1,70 +0,0 @@
package item
import (
"encoding/json"
"time"
)
const (
TimeFormat = "15:04"
)
type Time struct {
t time.Time
}
func (t Time) MarshalJSON() ([]byte, error) {
return json.Marshal(t.String())
}
func (t *Time) UnmarshalJSON(data []byte) error {
timeString := ""
if err := json.Unmarshal(data, &timeString); err != nil {
return err
}
nt := NewTimeFromString(timeString)
t.t = nt.Time()
return nil
}
func NewTime(hour, minute int) Time {
return Time{
t: time.Date(0, 0, 0, hour, minute, 0, 0, time.UTC),
}
}
func NewTimeFromString(timeStr string) Time {
tm, err := time.Parse(TimeFormat, timeStr)
if err != nil {
return Time{t: time.Time{}}
}
return Time{t: tm}
}
func (t *Time) String() string {
return t.t.Format(TimeFormat)
}
func (t *Time) Time() time.Time {
return t.t
}
func (t *Time) IsZero() bool {
return t.t.IsZero()
}
func (t *Time) Hour() int {
return t.t.Hour()
}
func (t *Time) Minute() int {
return t.t.Minute()
}
func (t *Time) Add(d time.Duration) Time {
return Time{
t: t.t.Add(d),
}
}

View File

@ -1,67 +0,0 @@
package item_test
import (
"encoding/json"
"fmt"
"testing"
"go-mod.ewintr.nl/planner/item"
)
func TestTime(t *testing.T) {
t.Parallel()
h, m := 11, 18
tm := item.NewTime(h, m)
expStr := "11:18"
if expStr != tm.String() {
t.Errorf("exp %v, got %v", expStr, tm.String())
}
actJSON, err := json.Marshal(tm)
if err != nil {
t.Errorf("exp nil, got %v", err)
}
expJSON := fmt.Sprintf("%q", expStr)
if expJSON != string(actJSON) {
t.Errorf("exp %v, got %v", expJSON, string(actJSON))
}
var actTM item.Time
if err := json.Unmarshal(actJSON, &actTM); err != nil {
t.Errorf("exp nil, got %v", err)
}
if expStr != actTM.String() {
t.Errorf("ecp %v, got %v", expStr, actTM.String())
}
}
func TestTimeFromString(t *testing.T) {
t.Parallel()
for _, tc := range []struct {
name string
str string
exp string
}{
{
name: "empty",
exp: "00:00",
},
{
name: "invalid",
str: "invalid",
exp: "00:00",
},
{
name: "valid",
str: "11:42",
exp: "11:42",
},
} {
t.Run(tc.name, func(t *testing.T) {
act := item.NewTimeFromString(tc.str)
if tc.exp != act.String() {
t.Errorf("exp %v, got %v", tc.exp, act.String())
}
})
}
}

View File

@ -2,66 +2,70 @@ package storage
import ( import (
"errors" "errors"
"sort"
"time"
"go-mod.ewintr.nl/planner/item"
) )
var ( var (
ErrNotFound = errors.New("not found") ErrNotFound = errors.New("not found")
) )
// type LocalID interface { type LocalID interface {
// FindAll() (map[string]int, error) FindAll() (map[string]int, error)
// FindOrNext(id string) (int, error) FindOrNext(id string) (int, error)
// Next() (int, error) Next() (int, error)
// Store(id string, localID int) error Store(id string, localID int) error
// Delete(id string) error Delete(id string) error
// } }
// type Sync interface { type Sync interface {
// FindAll() ([]item.Item, error) FindAll() ([]item.Item, error)
// Store(i item.Item) error Store(i item.Item) error
// DeleteAll() error DeleteAll() error
// LastUpdate() (time.Time, error) LastUpdate() (time.Time, error)
// } }
// type Event interface { type Event interface {
// Store(event item.Event) error Store(event item.Event) error
// Find(id string) (item.Event, error) Find(id string) (item.Event, error)
// FindAll() ([]item.Event, error) FindAll() ([]item.Event, error)
// Delete(id string) error Delete(id string) error
// } }
// func NextLocalID(used []int) int { func NextLocalID(used []int) int {
// if len(used) == 0 { if len(used) == 0 {
// return 1 return 1
// } }
// sort.Ints(used) sort.Ints(used)
// usedMax := 1 usedMax := 1
// for _, u := range used { for _, u := range used {
// if u > usedMax { if u > usedMax {
// usedMax = u usedMax = u
// } }
// } }
// var limit int var limit int
// for limit = 1; limit <= len(used) || limit < usedMax; limit *= 10 { for limit = 1; limit <= len(used) || limit < usedMax; limit *= 10 {
// } }
// newId := used[len(used)-1] + 1 newId := used[len(used)-1] + 1
// if newId < limit { if newId < limit {
// return newId return newId
// } }
// usedMap := map[int]bool{} usedMap := map[int]bool{}
// for _, u := range used { for _, u := range used {
// usedMap[u] = true usedMap[u] = true
// } }
// for i := 1; i < limit; i++ { for i := 1; i < limit; i++ {
// if _, ok := usedMap[i]; !ok { if _, ok := usedMap[i]; !ok {
// return i return i
// } }
// } }
// return limit return limit
// } }

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"fmt"
"slices" "slices"
"sync" "sync"
"time" "time"
@ -47,33 +48,32 @@ func (m *Memory) Updated(kinds []item.Kind, timestamp time.Time) ([]item.Item, e
} }
func (m *Memory) RecursBefore(date time.Time) ([]item.Item, error) { func (m *Memory) RecursBefore(date time.Time) ([]item.Item, error) {
// res := make([]item.Item, 0) res := make([]item.Item, 0)
// for _, i := range m.items { for _, i := range m.items {
// if i.Recurrer == nil { if i.Recurrer == nil {
// continue continue
// } }
// if i.RecurNext.Before(date) { if i.RecurNext.Before(date) {
// res = append(res, i) res = append(res, i)
// } }
// } }
// return res, nil return res, nil
return nil, nil
} }
func (m *Memory) RecursNext(id string, date time.Time, ts time.Time) error { func (m *Memory) RecursNext(id string, date time.Time, ts time.Time) error {
// i, ok := m.items[id] i, ok := m.items[id]
// if !ok { if !ok {
// return ErrNotFound return ErrNotFound
// } }
// if i.Recurrer == nil { if i.Recurrer == nil {
// return ErrNotARecurrer return ErrNotARecurrer
// } }
// if !i.Recurrer.On(date) { if !i.Recurrer.On(date) {
// return fmt.Errorf("item does not recur on %v", date) return fmt.Errorf("item does not recur on %v", date)
// } }
// i.RecurNext = date i.RecurNext = date
// i.Updated = ts i.Updated = ts
// m.items[id] = i m.items[id] = i
return nil return nil
} }