2023-01-29 22:00:40 +01:00
|
|
|
package rfctime
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2023-02-09 11:16:23 +01:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
2023-05-05 17:47:30 +02:00
|
|
|
"go.mongodb.org/mongo-driver/bson/bsoncodec"
|
|
|
|
"go.mongodb.org/mongo-driver/bson/bsonrw"
|
2023-02-09 11:16:23 +01:00
|
|
|
"go.mongodb.org/mongo-driver/bson/bsontype"
|
2024-04-15 10:43:26 +02:00
|
|
|
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
2023-05-05 17:47:30 +02:00
|
|
|
"reflect"
|
2023-01-29 22:00:40 +01:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
type RFC3339Time time.Time
|
|
|
|
|
|
|
|
func (t RFC3339Time) Time() time.Time {
|
|
|
|
return time.Time(t)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) MarshalBinary() ([]byte, error) {
|
|
|
|
return (time.Time)(t).MarshalBinary()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *RFC3339Time) UnmarshalBinary(data []byte) error {
|
|
|
|
return (*time.Time)(t).UnmarshalBinary(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) GobEncode() ([]byte, error) {
|
|
|
|
return (time.Time)(t).GobEncode()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *RFC3339Time) GobDecode(data []byte) error {
|
|
|
|
return (*time.Time)(t).GobDecode(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *RFC3339Time) UnmarshalJSON(data []byte) error {
|
|
|
|
str := ""
|
|
|
|
if err := json.Unmarshal(data, &str); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
t0, err := time.Parse(t.FormatStr(), str)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
*t = RFC3339Time(t0)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) MarshalJSON() ([]byte, error) {
|
|
|
|
str := t.Time().Format(t.FormatStr())
|
|
|
|
return json.Marshal(str)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) MarshalText() ([]byte, error) {
|
|
|
|
b := make([]byte, 0, len(t.FormatStr()))
|
|
|
|
return t.Time().AppendFormat(b, t.FormatStr()), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *RFC3339Time) UnmarshalText(data []byte) error {
|
|
|
|
var err error
|
|
|
|
v, err := time.Parse(t.FormatStr(), string(data))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
tt := RFC3339Time(v)
|
|
|
|
*t = tt
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-02-09 11:16:23 +01:00
|
|
|
func (t *RFC3339Time) UnmarshalBSONValue(bt bsontype.Type, data []byte) error {
|
2023-08-14 18:39:22 +02:00
|
|
|
if bt == bson.TypeNull {
|
2023-05-05 17:57:21 +02:00
|
|
|
// we can't set nil in UnmarshalBSONValue (so we use default(struct))
|
2023-05-05 18:22:15 +02:00
|
|
|
// Use mongoext.CreateGoExtBsonRegistry if you need to unmarsh pointer values
|
2023-05-05 17:57:21 +02:00
|
|
|
// https://stackoverflow.com/questions/75167597
|
|
|
|
// https://jira.mongodb.org/browse/GODRIVER-2252
|
|
|
|
*t = RFC3339Time{}
|
2023-04-13 14:40:07 +02:00
|
|
|
return nil
|
|
|
|
}
|
2023-08-14 18:39:22 +02:00
|
|
|
if bt != bson.TypeDateTime {
|
2023-02-09 11:16:23 +01:00
|
|
|
return errors.New(fmt.Sprintf("cannot unmarshal %v into RFC3339Time", bt))
|
|
|
|
}
|
|
|
|
var tt time.Time
|
2023-06-06 11:26:46 +02:00
|
|
|
err := bson.RawValue{Type: bt, Value: data}.Unmarshal(&tt)
|
2023-02-09 11:16:23 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
*t = RFC3339Time(tt)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) MarshalBSONValue() (bsontype.Type, []byte, error) {
|
|
|
|
return bson.MarshalValue(time.Time(t))
|
|
|
|
}
|
|
|
|
|
2023-05-05 17:47:30 +02:00
|
|
|
func (t RFC3339Time) DecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
|
|
|
|
if val.Kind() == reflect.Ptr && val.IsNil() {
|
|
|
|
if !val.CanSet() {
|
|
|
|
return errors.New("ValueUnmarshalerDecodeValue")
|
|
|
|
}
|
|
|
|
val.Set(reflect.New(val.Type().Elem()))
|
|
|
|
}
|
|
|
|
|
|
|
|
tp, src, err := bsonrw.Copier{}.CopyValueToBytes(vr)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if val.Kind() == reflect.Ptr && len(src) == 0 {
|
|
|
|
val.Set(reflect.Zero(val.Type()))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
err = t.UnmarshalBSONValue(tp, src)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2023-06-06 11:26:46 +02:00
|
|
|
if val.Kind() == reflect.Ptr {
|
|
|
|
val.Set(reflect.ValueOf(&t))
|
|
|
|
} else {
|
|
|
|
val.Set(reflect.ValueOf(t))
|
|
|
|
}
|
|
|
|
|
2023-05-05 17:47:30 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-01-29 22:00:40 +01:00
|
|
|
func (t RFC3339Time) Serialize() string {
|
|
|
|
return t.Time().Format(t.FormatStr())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) FormatStr() string {
|
|
|
|
return time.RFC3339
|
|
|
|
}
|
|
|
|
|
2023-03-15 15:41:55 +01:00
|
|
|
func (t RFC3339Time) After(u AnyTime) bool {
|
|
|
|
return t.Time().After(tt(u))
|
2023-01-29 22:00:40 +01:00
|
|
|
}
|
|
|
|
|
2023-03-15 15:41:55 +01:00
|
|
|
func (t RFC3339Time) Before(u AnyTime) bool {
|
|
|
|
return t.Time().Before(tt(u))
|
2023-01-29 22:00:40 +01:00
|
|
|
}
|
|
|
|
|
2023-03-15 15:41:55 +01:00
|
|
|
func (t RFC3339Time) Equal(u AnyTime) bool {
|
|
|
|
return t.Time().Equal(tt(u))
|
2023-01-29 22:00:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) IsZero() bool {
|
|
|
|
return t.Time().IsZero()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Date() (year int, month time.Month, day int) {
|
|
|
|
return t.Time().Date()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Year() int {
|
|
|
|
return t.Time().Year()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Month() time.Month {
|
|
|
|
return t.Time().Month()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Day() int {
|
|
|
|
return t.Time().Day()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Weekday() time.Weekday {
|
|
|
|
return t.Time().Weekday()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) ISOWeek() (year, week int) {
|
|
|
|
return t.Time().ISOWeek()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Clock() (hour, min, sec int) {
|
|
|
|
return t.Time().Clock()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Hour() int {
|
|
|
|
return t.Time().Hour()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Minute() int {
|
|
|
|
return t.Time().Minute()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Second() int {
|
|
|
|
return t.Time().Second()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Nanosecond() int {
|
|
|
|
return t.Time().Nanosecond()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) YearDay() int {
|
|
|
|
return t.Time().YearDay()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Add(d time.Duration) RFC3339Time {
|
|
|
|
return RFC3339Time(t.Time().Add(d))
|
|
|
|
}
|
|
|
|
|
2023-03-15 15:41:55 +01:00
|
|
|
func (t RFC3339Time) Sub(u AnyTime) time.Duration {
|
|
|
|
return t.Time().Sub(tt(u))
|
2023-01-29 22:00:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) AddDate(years int, months int, days int) RFC3339Time {
|
|
|
|
return RFC3339Time(t.Time().AddDate(years, months, days))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Unix() int64 {
|
|
|
|
return t.Time().Unix()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) UnixMilli() int64 {
|
|
|
|
return t.Time().UnixMilli()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) UnixMicro() int64 {
|
|
|
|
return t.Time().UnixMicro()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) UnixNano() int64 {
|
|
|
|
return t.Time().UnixNano()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) Format(layout string) string {
|
|
|
|
return t.Time().Format(layout)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) GoString() string {
|
|
|
|
return t.Time().GoString()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t RFC3339Time) String() string {
|
|
|
|
return t.Time().String()
|
|
|
|
}
|
|
|
|
|
2023-03-15 15:41:55 +01:00
|
|
|
func (t RFC3339Time) Location() *time.Location {
|
|
|
|
return t.Time().Location()
|
|
|
|
}
|
|
|
|
|
2023-01-29 22:00:40 +01:00
|
|
|
func NewRFC3339(t time.Time) RFC3339Time {
|
|
|
|
return RFC3339Time(t)
|
|
|
|
}
|
|
|
|
|
2024-04-15 10:43:26 +02:00
|
|
|
func NewRFC3339Ptr(t *time.Time) *RFC3339Time {
|
|
|
|
if t == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return langext.Ptr(RFC3339Time(*t))
|
|
|
|
}
|
|
|
|
|
2023-01-29 22:00:40 +01:00
|
|
|
func NowRFC3339() RFC3339Time {
|
|
|
|
return RFC3339Time(time.Now())
|
|
|
|
}
|