types.go

  1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2//
  3// SPDX-License-Identifier: AGPL-3.0-or-later
  4
  5package lunatask
  6
  7import (
  8	"encoding/json"
  9	"fmt"
 10	"time"
 11)
 12
 13// Source tracks where an entity originated, useful for syncing with external
 14// systems. The values are free-form strings you define.
 15type Source struct {
 16	Source   string `json:"source"`
 17	SourceID string `json:"source_id"`
 18}
 19
 20// Date is a date without time, marshaled as "YYYY-MM-DD" in JSON.
 21type Date struct {
 22	time.Time
 23}
 24
 25// NewDate creates a Date from a time.Time, discarding time-of-day.
 26func NewDate(t time.Time) Date {
 27	return Date{time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC)}
 28}
 29
 30const dateFormat = "2006-01-02"
 31
 32// MarshalJSON implements [json.Marshaler].
 33func (d *Date) MarshalJSON() ([]byte, error) {
 34	if d.IsZero() {
 35		return []byte("null"), nil
 36	}
 37
 38	data, err := json.Marshal(d.Format(dateFormat))
 39	if err != nil {
 40		return nil, fmt.Errorf("marshaling date: %w", err)
 41	}
 42
 43	return data, nil
 44}
 45
 46// UnmarshalJSON implements [json.Unmarshaler].
 47func (d *Date) UnmarshalJSON(data []byte) error {
 48	if string(data) == "null" {
 49		return nil
 50	}
 51
 52	var str string
 53	if err := json.Unmarshal(data, &str); err != nil {
 54		return fmt.Errorf("unmarshaling date string: %w", err)
 55	}
 56
 57	t, err := time.Parse(dateFormat, str)
 58	if err != nil {
 59		return fmt.Errorf("parsing date %q: %w", str, err)
 60	}
 61
 62	d.Time = t
 63
 64	return nil
 65}
 66
 67// String returns the date as "YYYY-MM-DD", or empty string if zero.
 68func (d *Date) String() string {
 69	if d.IsZero() {
 70		return ""
 71	}
 72
 73	return d.Format(dateFormat)
 74}
 75
 76// ParseDate parses "YYYY-MM-DD" into a Date.
 77func ParseDate(s string) (Date, error) {
 78	t, err := time.Parse(dateFormat, s)
 79	if err != nil {
 80		return Date{}, fmt.Errorf("parsing date %q: %w", s, err)
 81	}
 82
 83	return Date{t}, nil
 84}
 85
 86// Today returns the current date in local time.
 87func Today() Date {
 88	return NewDate(time.Now())
 89}
 90
 91// RelationshipStrength categorizes the closeness of a relationship.
 92type RelationshipStrength string
 93
 94// Valid relationship strength values.
 95const (
 96	RelationshipFamily         RelationshipStrength = "family"
 97	RelationshipIntimateFriend RelationshipStrength = "intimate-friends"
 98	RelationshipCloseFriend    RelationshipStrength = "close-friends"
 99	RelationshipCasualFriend   RelationshipStrength = "casual-friends"
100	RelationshipAcquaintance   RelationshipStrength = "acquaintances"
101	RelationshipBusiness       RelationshipStrength = "business-contacts"
102	RelationshipAlmostStranger RelationshipStrength = "almost-strangers"
103)