1
0
mirror of https://github.com/dstotijn/go-notion.git synced 2024-12-04 10:24:57 +02:00
go-notion/time.go

96 lines
2.1 KiB
Go

package notion
import (
"encoding/json"
"errors"
"time"
)
// Length of a date string, e.g. `2006-01-02`.
const dateLength = 10
// DateTimeFormat is used when calling time.Parse, using RFC3339 with microsecond
// precision, which is what the Notion API returns in JSON response data.
const DateTimeFormat = "2006-01-02T15:04:05.999Z07:00"
// DateTime represents a Notion date property with optional time.
type DateTime struct {
time.Time
hasTime bool
}
// ParseDateTime parses an RFC3339 formatted string with optional time.
func ParseDateTime(value string) (DateTime, error) {
if len(value) > len(DateTimeFormat) {
return DateTime{}, errors.New("invalid datetime string")
}
t, err := time.Parse(DateTimeFormat[:len(value)], value)
if err != nil {
return DateTime{}, err
}
dt := DateTime{
Time: t,
hasTime: len(value) > dateLength,
}
return dt, nil
}
// UnmarshalJSON implements json.Unmarshaler.
func (dt *DateTime) UnmarshalJSON(b []byte) error {
if len(b) < 2 {
return errors.New("invalid datetime string")
}
parsed, err := ParseDateTime(string(b[1 : len(b)-1]))
if err != nil {
return err
}
*dt = parsed
return nil
}
// MarshalJSON implements json.Marshaler. It returns an RFC399 formatted string,
// using microsecond precision ()
func (dt DateTime) MarshalJSON() ([]byte, error) {
if dt.hasTime {
return json.Marshal(dt.Time)
}
return []byte(`"` + dt.Time.Format(DateTimeFormat[:dateLength]) + `"`), nil
}
// NewDateTime returns a new DateTime. If `haseTime` is true, time is included
// when encoding to JSON.
func NewDateTime(t time.Time, hasTime bool) DateTime {
var tt time.Time
if hasTime {
tt = t
} else {
tt = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC)
}
return DateTime{
Time: tt,
hasTime: hasTime,
}
}
// HasTime returns true if the datetime was parsed from a string that included time.
func (dt *DateTime) HasTime() bool {
return dt.hasTime
}
// Equal returns true if both DateTime values have equal underlying time.Time and
// hasTime fields.
func (dt DateTime) Equal(value DateTime) bool {
if !dt.Time.Equal(value.Time) {
return false
}
return dt.hasTime == value.hasTime
}