event duration

This commit is contained in:
Erik Winter 2024-09-26 07:21:48 +02:00
parent f1afd21ea2
commit 5808b6a627
4 changed files with 64 additions and 31 deletions

View File

@ -40,7 +40,7 @@ func main() {
os.Exit(1) os.Exit(1)
} }
for _, e := range all { for _, e := range all {
fmt.Printf("%s\t%s\t%s\t%s\n", e.ID, e.Title, e.Start.Format(time.DateTime), e.End.Format(time.DateTime)) fmt.Printf("%s\t%s\t%s\t%s\n", e.ID, e.Title, e.Start.Format(time.DateTime), e.Duration.String())
} }
default: default:
fmt.Printf("unkown command %s\n", os.Args[1]) fmt.Printf("unkown command %s\n", os.Args[1])

View File

@ -14,7 +14,7 @@ const (
) )
var migrations = []string{ var migrations = []string{
`CREATE TABLE events ("id" TEXT UNIQUE, "title" TEXT, "start" TIMESTAMP, "end" TIMESTAMP)`, `CREATE TABLE events ("id" TEXT UNIQUE, "title" TEXT, "start" TIMESTAMP, "duration" TEXT)`,
`PRAGMA journal_mode=WAL`, `PRAGMA journal_mode=WAL`,
`PRAGMA synchronous=NORMAL`, `PRAGMA synchronous=NORMAL`,
`PRAGMA cache_size=2000`, `PRAGMA cache_size=2000`,
@ -51,16 +51,16 @@ func NewSqlite(dbPath string) (*Sqlite, error) {
func (s *Sqlite) Store(event item.Event) error { func (s *Sqlite) Store(event item.Event) error {
if _, err := s.db.Exec(` if _, err := s.db.Exec(`
INSERT INTO events INSERT INTO events
(id, title, start, end) (id, title, start, duration)
VALUES VALUES
(?, ?, ?, ?) (?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE ON CONFLICT(id) DO UPDATE
SET SET
title=?, title=?,
start=?, start=?,
end=?`, duration=?`,
event.ID, event.Title, event.Start.Format(timestampFormat), event.End.Format(timestampFormat), event.ID, event.Title, event.Start.Format(timestampFormat), event.Duration.String(),
event.Title, event.Start.Format(timestampFormat), event.End.Format(timestampFormat)); err != nil { event.Title, event.Start.Format(timestampFormat), event.Duration.String()); err != nil {
return fmt.Errorf("%w: %v", ErrSqliteFailure, err) return fmt.Errorf("%w: %v", ErrSqliteFailure, err)
} }
return nil return nil
@ -69,9 +69,9 @@ end=?`,
func (s *Sqlite) Find(id string) (item.Event, error) { func (s *Sqlite) Find(id string) (item.Event, error) {
var event item.Event var event item.Event
err := s.db.QueryRow(` err := s.db.QueryRow(`
SELECT id, title, start, end SELECT id, title, start, duration
FROM events FROM events
WHERE id = ?`, id).Scan(&event.ID, &event.Title, &event.Start, &event.End) WHERE id = ?`, id).Scan(&event.ID, &event.Title, &event.Start, &event.Duration)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return event, fmt.Errorf("event not found: %w", err) return event, fmt.Errorf("event not found: %w", err)
@ -85,7 +85,7 @@ WHERE id = ?`, id).Scan(&event.ID, &event.Title, &event.Start, &event.End)
func (s *Sqlite) FindAll() ([]item.Event, error) { func (s *Sqlite) FindAll() ([]item.Event, error) {
rows, err := s.db.Query(` rows, err := s.db.Query(`
SELECT id, title, start, end SELECT id, title, start, duration
FROM events`) FROM events`)
if err != nil { if err != nil {
return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err) return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
@ -95,7 +95,7 @@ FROM events`)
defer rows.Close() defer rows.Close()
for rows.Next() { for rows.Next() {
var event item.Event var event item.Event
if err := rows.Scan(&event.ID, &event.Title, &event.Start, &event.End); err != nil { if err := rows.Scan(&event.ID, &event.Title, &event.Start, &event.Duration); err != nil {
return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err) return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
} }
result = append(result, event) result = append(result, event)

View File

@ -9,22 +9,47 @@ import (
type EventBody struct { type EventBody struct {
Title string `json:"title"` Title string `json:"title"`
Start time.Time `json:"start"` Start time.Time `json:"start"`
End time.Time `json:"end"` 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"`
End string `json:"end"` Duration string `json:"duration"`
*Alias *Alias
}{ }{
Start: e.Start.UTC().Format(time.RFC3339), Start: e.Start.UTC().Format(time.RFC3339),
End: e.End.UTC().Format(time.RFC3339), Duration: e.Duration.String(),
Alias: (*Alias)(&e), Alias: (*Alias)(&e),
}) })
} }
func (e *EventBody) UnmarshalJSON(data []byte) error {
type Alias EventBody
aux := &struct {
Start string `json:"start"`
Duration string `json:"duration"`
*Alias
}{
Alias: (*Alias)(e),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
var err error
if e.Start, err = time.Parse(time.RFC3339, aux.Start); err != nil {
return err
}
if e.Duration, err = time.ParseDuration(aux.Duration); err != nil {
return err
}
return nil
}
type Event struct { type Event struct {
ID string `json:"id"` ID string `json:"id"`
EventBody EventBody
@ -49,7 +74,7 @@ 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,
End: e.End, 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")

View File

@ -11,6 +11,10 @@ import (
func TestNewEvent(t *testing.T) { func TestNewEvent(t *testing.T) {
t.Parallel() t.Parallel()
oneHour, err := time.ParseDuration("1h")
if err != nil {
t.Errorf("exp nil, got %v", err)
}
for _, tc := range []struct { for _, tc := range []struct {
name string name string
it item.Item it item.Item
@ -25,7 +29,7 @@ func TestNewEvent(t *testing.T) {
Body: `{ Body: `{
"title":"title", "title":"title",
"start":"2024-09-20T08:00:00Z", "start":"2024-09-20T08:00:00Z",
"end":"2024-09-20T10:00:00Z" "duration":"1h"
}`, }`,
}, },
expErr: true, expErr: true,
@ -47,7 +51,7 @@ func TestNewEvent(t *testing.T) {
Body: `{ Body: `{
"title":"title", "title":"title",
"start":"2024-09-20T08:00:00Z", "start":"2024-09-20T08:00:00Z",
"end":"2024-09-20T10:00:00Z" "duration":"1h"
}`, }`,
}, },
expEvent: item.Event{ expEvent: item.Event{
@ -55,7 +59,7 @@ func TestNewEvent(t *testing.T) {
EventBody: item.EventBody{ EventBody: item.EventBody{
Title: "title", Title: "title",
Start: time.Date(2024, 9, 20, 8, 0, 0, 0, time.UTC), Start: time.Date(2024, 9, 20, 8, 0, 0, 0, time.UTC),
End: time.Date(2024, 9, 20, 10, 0, 0, 0, time.UTC), Duration: oneHour,
}, },
}, },
}, },
@ -78,6 +82,10 @@ func TestNewEvent(t *testing.T) {
func TestEventItem(t *testing.T) { func TestEventItem(t *testing.T) {
t.Parallel() t.Parallel()
oneHour, err := time.ParseDuration("1h")
if err != nil {
t.Errorf("exp nil, got %v", err)
}
for _, tc := range []struct { for _, tc := range []struct {
name string name string
event item.Event event item.Event
@ -89,7 +97,7 @@ func TestEventItem(t *testing.T) {
expItem: item.Item{ expItem: item.Item{
Kind: item.KindEvent, Kind: item.KindEvent,
Updated: time.Time{}, Updated: time.Time{},
Body: `{"start":"0001-01-01T00:00:00Z","end":"0001-01-01T00:00:00Z","title":""}`, Body: `{"start":"0001-01-01T00:00:00Z","duration":"0s","title":""}`,
}, },
}, },
{ {
@ -99,14 +107,14 @@ func TestEventItem(t *testing.T) {
EventBody: item.EventBody{ EventBody: item.EventBody{
Title: "title", Title: "title",
Start: time.Date(2024, 9, 23, 8, 0, 0, 0, time.UTC), Start: time.Date(2024, 9, 23, 8, 0, 0, 0, time.UTC),
End: time.Date(2024, 9, 23, 10, 0, 0, 0, time.UTC), Duration: oneHour,
}, },
}, },
expItem: item.Item{ expItem: item.Item{
ID: "a", ID: "a",
Kind: item.KindEvent, Kind: item.KindEvent,
Updated: time.Time{}, Updated: time.Time{},
Body: `{"start":"2024-09-23T08:00:00Z","end":"2024-09-23T10:00:00Z","title":"title"}`, Body: `{"start":"2024-09-23T08:00:00Z","duration":"1h0m0s","title":"title"}`,
}, },
}, },
} { } {