package clocktime import ( "database/sql/driver" "encoding/json" "fmt" "io" "time" ) func marshalJSONString(s string) ([]byte, error) { return json.Marshal(s) } func unmarshalJSONString(data []byte) (string, error) { var s string if err := json.Unmarshal(data, &s); err != nil { return "", err } return s, nil } // MarshalJSON encodes ClockTime as a JSON string HH:MM:SS. func (t ClockTime) MarshalJSON() ([]byte, error) { return marshalJSONString(t.String()) } // UnmarshalJSON decodes a JSON string into ClockTime. func (t *ClockTime) UnmarshalJSON(data []byte) error { if string(data) == "null" { *t = ClockTime{} return nil } s, err := unmarshalJSONString(data) if err != nil { return err } parsed, err := ParseClockTime(s) if err != nil { return err } *t = parsed return nil } // MarshalText implements encoding.TextMarshaler. func (t ClockTime) MarshalText() ([]byte, error) { return []byte(t.String()), nil } // UnmarshalText implements encoding.TextUnmarshaler. func (t *ClockTime) UnmarshalText(text []byte) error { parsed, err := ParseClockTime(string(text)) if err != nil { return err } *t = parsed return nil } // MarshalGQL implements gqlgen's Marshaler interface. func (t ClockTime) MarshalGQL(w io.Writer) { fmt.Fprint(w, "\""+t.String()+"\"") } // UnmarshalGQL implements gqlgen's Unmarshaler interface. func (t *ClockTime) UnmarshalGQL(value any) error { if value == nil { *t = ClockTime{} return nil } str, ok := value.(string) if !ok { return fmt.Errorf("ClockTime must be a string, got %T", value) } parsed, err := ParseClockTime(str) if err != nil { return err } *t = parsed return nil } // Value implements driver.Valuer for SQL TIME columns as HH:MM:SS bytes. func (t ClockTime) Value() (driver.Value, error) { return []byte(t.String()), nil } // Scan implements sql.Scanner for time.Time, []byte, and string. func (t *ClockTime) Scan(value any) error { if value == nil { *t = ClockTime{} return nil } switch v := value.(type) { case time.Time: *t = ClockTimeFromTime(v) case []byte: parsed, err := ParseClockTime(string(v)) if err != nil { return fmt.Errorf("failed to parse ClockTime: %w", err) } *t = parsed case string: parsed, err := ParseClockTime(v) if err != nil { return fmt.Errorf("failed to parse ClockTime: %w", err) } *t = parsed default: return fmt.Errorf("ClockTime.Scan: unsupported type %T", value) } return nil } // MarshalJSON encodes ISODuration as a JSON ISO 8601 string. func (d ISODuration) MarshalJSON() ([]byte, error) { return marshalJSONString(d.String()) } // UnmarshalJSON decodes a JSON ISO 8601 duration string. func (d *ISODuration) UnmarshalJSON(data []byte) error { if string(data) == "null" { *d = ISODuration(0) return nil } s, err := unmarshalJSONString(data) if err != nil { return err } parsed, err := ParseISODuration(s) if err != nil { return err } *d = parsed return nil } // MarshalText implements encoding.TextMarshaler. func (d ISODuration) MarshalText() ([]byte, error) { return []byte(d.String()), nil } // UnmarshalText implements encoding.TextUnmarshaler. func (d *ISODuration) UnmarshalText(text []byte) error { parsed, err := ParseISODuration(string(text)) if err != nil { return err } *d = parsed return nil } // MarshalGQL implements gqlgen's Marshaler interface. func (d ISODuration) MarshalGQL(w io.Writer) { fmt.Fprint(w, "\""+d.String()+"\"") } // UnmarshalGQL implements gqlgen's Unmarshaler interface. func (d *ISODuration) UnmarshalGQL(value any) error { if value == nil { *d = ISODuration(0) return nil } s, ok := value.(string) if !ok { return fmt.Errorf("ISODuration must be a string, got %T", value) } parsed, err := ParseISODuration(s) if err != nil { return err } *d = parsed return nil } // Value stores ISODuration as nanoseconds in the database. func (d ISODuration) Value() (driver.Value, error) { return int64(d), nil } // Scan reads ISODuration from int64 nanoseconds or an ISO 8601 string. func (d *ISODuration) Scan(value any) error { if value == nil { *d = ISODuration(0) return nil } switch v := value.(type) { case int64: *d = ISODuration(v) case []byte: parsed, err := ParseISODuration(string(v)) if err != nil { return err } *d = parsed case string: parsed, err := ParseISODuration(v) if err != nil { return err } *d = parsed default: return fmt.Errorf("ISODuration.Scan: unsupported type %T", value) } return nil }