package dashboard import ( "fmt" "strconv" "strings" "time" "github.com/shopspring/decimal" ) type Row map[string]interface{} func (r Row) String(name string) string { value, ok := r[name] if !ok || value == nil { return "" } switch typed := value.(type) { case []byte: return string(typed) case string: return typed default: return fmt.Sprint(typed) } } func (r Row) Int64(name string) int64 { value, ok := r[name] if !ok || value == nil { return 0 } switch typed := value.(type) { case int: return int64(typed) case int8: return int64(typed) case int16: return int64(typed) case int32: return int64(typed) case int64: return typed case uint: return int64(typed) case uint8: return int64(typed) case uint16: return int64(typed) case uint32: return int64(typed) case uint64: return int64(typed) case []byte: parsed, _ := strconv.ParseInt(string(typed), 10, 64) return parsed case string: parsed, _ := strconv.ParseInt(typed, 10, 64) return parsed default: parsed, _ := strconv.ParseInt(fmt.Sprint(typed), 10, 64) return parsed } } func (r Row) Bool(name string) bool { return r.Int64(name) != 0 } func (r Row) Decimal(name string) decimal.Decimal { value, ok := r[name] if !ok || value == nil { return decimal.Zero } switch typed := value.(type) { case decimal.Decimal: return typed case float32: return decimal.NewFromFloat32(typed) case float64: return decimal.NewFromFloat(typed) case int64: return decimal.NewFromInt(typed) case int: return decimal.NewFromInt(int64(typed)) case []byte: parsed, _ := decimal.NewFromString(string(typed)) return parsed case string: parsed, _ := decimal.NewFromString(typed) return parsed default: parsed, _ := decimal.NewFromString(fmt.Sprint(typed)) return parsed } } func (r Row) Time(name string) time.Time { value, ok := r[name] if !ok || value == nil { return time.Time{} } switch typed := value.(type) { case time.Time: return typed case []byte: return parseTimeString(string(typed)) case string: return parseTimeString(typed) default: return parseTimeString(fmt.Sprint(typed)) } } func (r Row) MillisTime(name string) time.Time { millis := r.Int64(name) if millis <= 0 { return time.Time{} } return time.UnixMilli(millis) } func parseTimeString(value string) time.Time { text := strings.TrimSpace(value) if text == "" || strings.EqualFold(text, "") { return time.Time{} } for _, layout := range []string{ time.RFC3339Nano, "2006-01-02 15:04:05.999999", "2006-01-02 15:04:05", "2006-01-02", } { parsed, err := time.ParseInLocation(layout, text, time.Local) if err == nil { return parsed } } return time.Time{} }