- Introduced NanoToTime and TimeToNano functions for converting between UnixNano and time.Time, improving clarity and consistency in timestamp management. - Updated Assistant model to utilize the new utility functions for created_at and updated_at fields. - Refactored Xun store methods to ensure UTC compatibility for timestamp serialization across different database drivers. - Added unit tests for the new conversion functions to validate their correctness and behavior.
69 lines
1.8 KiB
Go
69 lines
1.8 KiB
Go
package xun
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"time"
|
|
|
|
jsoniter "github.com/json-iterator/go"
|
|
"github.com/yaoapp/yao/openapi/utils"
|
|
)
|
|
|
|
// isNil checks whether a value is truly nil, handling the Go typed-nil-in-interface pitfall.
|
|
// A nil map, slice, or pointer stored in an interface{} is not == nil in Go;
|
|
// this helper uses reflect to detect that case.
|
|
func isNil(v interface{}) bool {
|
|
if v == nil {
|
|
return true
|
|
}
|
|
rv := reflect.ValueOf(v)
|
|
switch rv.Kind() {
|
|
case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Interface, reflect.Chan, reflect.Func:
|
|
return rv.IsNil()
|
|
}
|
|
return false
|
|
}
|
|
|
|
// marshalJSONFields serialises each value in fields to a JSON string and writes
|
|
// it into data. Truly-nil values (including typed nils) are skipped so the
|
|
// database column keeps its SQL NULL / default.
|
|
func marshalJSONFields(data map[string]interface{}, fields map[string]interface{}) error {
|
|
for field, value := range fields {
|
|
if isNil(value) {
|
|
continue
|
|
}
|
|
jsonStr, err := jsoniter.MarshalToString(value)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal %s: %w", field, err)
|
|
}
|
|
data[field] = jsonStr
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Helper functions for type conversion
|
|
func getString(data map[string]interface{}, key string) string {
|
|
if v, ok := data[key].(string); ok {
|
|
return v
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func getBool(data map[string]interface{}, key string) bool {
|
|
return utils.ToBool(data[key])
|
|
}
|
|
|
|
func getInt(data map[string]interface{}, key string) int {
|
|
return utils.ToInt(data[key])
|
|
}
|
|
|
|
func getInt64(data map[string]interface{}, key string) int64 {
|
|
v := data[key]
|
|
if t, ok := v.(time.Time); ok {
|
|
return t.UnixNano()
|
|
}
|
|
return utils.ToInt64(v)
|
|
}
|
|
|
|
func nanoToTime(ns int64) time.Time { return utils.NanoToTime(ns) }
|
|
func timeToNano(t time.Time) int64 { return utils.TimeToNano(t) }
|