event duration
This commit is contained in:
parent
f1afd21ea2
commit
5808b6a627
|
@ -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])
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -7,24 +7,49 @@ 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
|
||||||
|
@ -47,9 +72,9 @@ func NewEvent(i Item) (Event, error) {
|
||||||
|
|
||||||
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,
|
||||||
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")
|
||||||
|
|
|
@ -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,15 +51,15 @@ 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{
|
||||||
ID: "a",
|
ID: "a",
|
||||||
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":""}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -97,16 +105,16 @@ func TestEventItem(t *testing.T) {
|
||||||
event: item.Event{
|
event: item.Event{
|
||||||
ID: "a",
|
ID: "a",
|
||||||
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"}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
|
|
Loading…
Reference in New Issue