Skip to content

Location Data is Ignored if UTC() was ever called on the time struct #1189

Open
@comsma

Description

@comsma

I had to build a query hook for bun that allows me to apply the database time zone loc to all time structs before inserting them into the database. For instance i am creating an order and when i call the .UTC() method on the time it causes the .In() called in the time zone hook. When printing the requested date into the console it shows the time with the database offset but bun inserts the time as utc still. This issue goes away if UTC() was not called and no location was set but i do not have control over the fact the UTC() was called because my protobuf api has a helper method called AsTime() that returns the time struct after calling the UTC() function.

I am using the mssql dialect v1.2.11

// Order Repository
requestedDate := time.Unix(1745335353,0).UTC()
orderDate := time.Unix(1745428361,0)

prophet.OeHdr{
			
			OrderNo:        strconv.Itoa(int(orderNo)),
			OrderDate:        &orderDate,
			RequestedDate:    &requestedDate,
			
}
// timeZoneHook
type TimeZoneHook struct {
	dbLocation *time.Location
}

func (h TimeZoneHook) BeforeQuery(ctx context.Context, event *bun.QueryEvent) context.Context {
	// Process different query types
	switch event.IQuery.(type) {
	case *bun.InsertQuery, *bun.UpdateQuery:
		// Skip processing if there is no model
		if event.Model == nil {
			return ctx
		}

		// Get the model value
		val := reflect.ValueOf(event.Model.Value())

		// Handle pointer types
		if val.Kind() == reflect.Ptr {
			if val.IsNil() {
				return ctx
			}
			val = val.Elem()
		}

		// Check if the value is valid for processing
		if !val.IsValid() {
			return ctx
		}

		// Process based on the kind of value
		switch val.Kind() {
		case reflect.Struct:
			// Process struct directly
			h.inDBTimezone(val)

		case reflect.Slice:
			// Process each element in the slice
			for i := 0; i < val.Len(); i++ {
				elem := val.Index(i)
				// If element is a struct or pointer to struct
				if elem.Kind() == reflect.Struct {
					h.inDBTimezone(val)
				} else if elem.Kind() == reflect.Ptr && !elem.IsNil() {
					elemVal := elem.Elem()
					if elemVal.Kind() == reflect.Struct {
						h.inDBTimezone(val)
					}
				}
			}
		}
	}
	return ctx
}

// inDBTimezone converts time fields to the database time zone
func (h TimeZoneHook) inDBTimezone(val reflect.Value) {
	h.processTimeFields(val, func(t *time.Time) time.Time {
		return t.In(h.dbLocation)
	})
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions