package rfctime import ( "encoding/json" "errors" "fmt" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/bsoncodec" "go.mongodb.org/mongo-driver/bson/bsonrw" "go.mongodb.org/mongo-driver/bson/bsontype" "gogs.mikescher.com/BlackForestBytes/goext/timeext" "reflect" "time" ) type SecondsF64 time.Duration func (d SecondsF64) Duration() time.Duration { return time.Duration(d) } func (d SecondsF64) String() string { return d.Duration().String() } func (d SecondsF64) Nanoseconds() int64 { return d.Duration().Nanoseconds() } func (d SecondsF64) Microseconds() int64 { return d.Duration().Microseconds() } func (d SecondsF64) Milliseconds() int64 { return d.Duration().Milliseconds() } func (d SecondsF64) Seconds() float64 { return d.Duration().Seconds() } func (d SecondsF64) Minutes() float64 { return d.Duration().Minutes() } func (d SecondsF64) Hours() float64 { return d.Duration().Hours() } func (d *SecondsF64) UnmarshalJSON(data []byte) error { var secs float64 = 0 if err := json.Unmarshal(data, &secs); err != nil { return err } *d = SecondsF64(timeext.FromSeconds(secs)) return nil } func (d SecondsF64) MarshalJSON() ([]byte, error) { secs := d.Seconds() return json.Marshal(secs) } func (d *SecondsF64) UnmarshalBSONValue(bt bsontype.Type, data []byte) error { if bt == bson.TypeNull { // we can't set nil in UnmarshalBSONValue (so we use default(struct)) // Use mongoext.CreateGoExtBsonRegistry if you need to unmarsh pointer values // https://stackoverflow.com/questions/75167597 // https://jira.mongodb.org/browse/GODRIVER-2252 *d = SecondsF64(0) return nil } if bt != bson.TypeDouble { return errors.New(fmt.Sprintf("cannot unmarshal %v into SecondsF64", bt)) } var secValue float64 err := bson.RawValue{Type: bt, Value: data}.Unmarshal(&secValue) if err != nil { return err } *d = SecondsF64(int64(secValue * float64(time.Second))) return nil } func (d SecondsF64) MarshalBSONValue() (bsontype.Type, []byte, error) { return bson.MarshalValue(d.Seconds()) } func (d SecondsF64) 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 = d.UnmarshalBSONValue(tp, src) if err != nil { return err } if val.Kind() == reflect.Ptr { val.Set(reflect.ValueOf(&d)) } else { val.Set(reflect.ValueOf(d)) } return nil } func NewSecondsF64(t time.Duration) SecondsF64 { return SecondsF64(t) }