kanboard-api/timestamp.go
Oliver Jakoubek dbac08ac1e Implement Timestamp type for Unix timestamp JSON handling
Add custom Timestamp type that wraps time.Time for Kanboard's
Unix timestamp format:

UnmarshalJSON supports:
- Unix timestamps as integers
- Empty strings and "0" strings as zero time
- Null values as zero time
- Numeric strings (e.g., "1609459200")

MarshalJSON returns:
- 0 for zero time
- Unix timestamp for non-zero time

Includes comprehensive tests for round-trip marshaling
and struct embedding scenarios.

Closes: kanboard-api-25y
2026-01-15 18:15:33 +01:00

64 lines
1.4 KiB
Go

package kanboard
import (
"encoding/json"
"fmt"
"time"
)
// Timestamp wraps time.Time and handles Kanboard's Unix timestamp JSON format.
// Kanboard returns timestamps as Unix integers, with 0 or empty strings for null values.
type Timestamp struct {
time.Time
}
// UnmarshalJSON implements json.Unmarshaler.
// Supports Unix timestamps as integers, empty strings, "0" strings, and zero values.
func (t *Timestamp) UnmarshalJSON(data []byte) error {
// Try to unmarshal as integer (Unix timestamp)
var unix int64
if err := json.Unmarshal(data, &unix); err == nil {
if unix == 0 {
t.Time = time.Time{}
} else {
t.Time = time.Unix(unix, 0)
}
return nil
}
// Try to unmarshal as string (empty or "0")
var str string
if err := json.Unmarshal(data, &str); err == nil {
if str == "" || str == "0" {
t.Time = time.Time{}
return nil
}
// Try to parse as numeric string
var unix int64
if _, err := fmt.Sscanf(str, "%d", &unix); err == nil {
if unix == 0 {
t.Time = time.Time{}
} else {
t.Time = time.Unix(unix, 0)
}
return nil
}
}
// Handle null
if string(data) == "null" {
t.Time = time.Time{}
return nil
}
return fmt.Errorf("cannot unmarshal timestamp: %s", string(data))
}
// MarshalJSON implements json.Marshaler.
// Returns 0 for zero time, otherwise returns Unix timestamp.
func (t Timestamp) MarshalJSON() ([]byte, error) {
if t.IsZero() {
return []byte("0"), nil
}
return json.Marshal(t.Unix())
}