edgedb/edgedb-go

edgedb.Duration and time.Duration operate on different scales

joeyak opened this issue · 3 comments

The edgedb.Duration type is a microsecond count

// Duration represents the elapsed time between two instants
// as an int64 microsecond count.
type Duration int64

meanwhile the standard library time.Duration is a nanosecond count

// A Duration represents the elapsed time between two instants
// as an int64 nanosecond count. The representation limits the
// largest representable duration to approximately 290 years.
type Duration int64

I noticed this while running the code below with duration being time.Second * 15

err = w.db.Execute(context.Background(), `
	INSERT WatchTime {
		watch_duration := <duration>$0,
		user := (SELECT User FILTER .name = <str>$1),
		channel := (SELECT User FILTER .external_id = <str>$2)
	}
`, edgedb.Duration(duration), user, channel)

This results in a 4 hour and 10 minute duration
image

after updating the code to edgedb.Duration(duration/time.Microsecond) the time shows correctly
image

I also was able to get my code to work properly with time.Duration(watchTime.Duration)*time.Microsecond for going from edgedb to time

Is this the suggested way to handle the time conversion, or is this considered a bug?

fmoor commented

Is this the suggested way to handle the time conversion, or is this considered a bug?

This is a simple way to handle the conversion and it may be fine for some use cases but it is not correct in the general case because it doesn't detect overflows. Go's time.Duration can only go up to about 290 years, but edgedb.Duration can be much larger than that so to be correct the conversion should probably return an error if time.Duration can't represent the edgedb.Duration.

Are we supposed to be able to put time.Duration in the model to parse? I think I originally started using edgedb.Duration because I got an error on client.Query().

On the docs it mentions time.Duration as being a possible conversion, but maybe that was just a type?
image

below is the object

type WatchTime struct {
	edgedb.Optional
	ID        edgedb.UUID   `edgedb:"id" json:"id"`
	Duration  time.Duration `edgedb:"watch_duration" json:"watch_duration"`
	CreatedAt time.Time     `edgedb:"created_at" json:"created_at"`
}

and the error returned

error logging watchers for 46198525: could not log users watching: could not get watchtimes for 46198525: edgedb.InvalidArgumentError: the "out" argument does not match query schema: expected struct { Key struct { User database.User "edgedb:"user""; Channel database.User "edgedb:"channel"" } "edgedb:"key""; Info database.WatchTime "edgedb:"info"" }.info.watch_duration to be edgedb.Duration or edgedb.OptionalDuration got time.Duration

fmoor commented

Good catch! That is a typo. It should be edgedb.Duration.