package basic import ( "context" "fmt" "time" ) // datetime returns the current time, optionally formatted with a Go reference // layout and rendered in a named IANA timezone. type datetime struct{} const ( // defaultDTFormat is the layout used when the caller supplies none. defaultDTFormat = time.RFC3339 // defaultDTZone is the timezone used when the caller supplies none. defaultDTZone = "UTC" // maxDTFormatLen bounds a layout string to guard against absurd input. maxDTFormatLen = 128 // maxDTZoneLen bounds a timezone name to guard against absurd input. maxDTZoneLen = 64 ) // Name returns the tool identifier. func (datetime) Name() string { return "datetime" } // Description explains what the tool does for the model. func (datetime) Description() string { return "Return the current time, formatted with a Go reference layout and rendered in a named IANA timezone." } // Parameters returns the tool input JSON Schema. func (datetime) Parameters() (map[string]any, error) { return map[string]any{ "type": "object", "properties": map[string]any{ "format": map[string]any{"type": "string", "description": "Go reference layout, e.g. 2006-01-02 15:04:05"}, "timezone": map[string]any{"type": "string", "description": "IANA timezone name, e.g. Asia/Shanghai"}, }, }, nil } // Execute returns the current time in the requested format and timezone. func (datetime) Execute(ctx context.Context, args any) (any, error) { if err := ctx.Err(); err != nil { return nil, err } m, err := asMap(args) if err != nil { return nil, err } layout, err := optString(m, "format", defaultDTFormat) if err != nil { return nil, err } if len(layout) > maxDTFormatLen { return nil, fmt.Errorf("basic: layout too long: %w", ErrInvalidArgument) } zone, err := optString(m, "timezone", defaultDTZone) if err != nil { return nil, err } if len(zone) > maxDTZoneLen { return nil, fmt.Errorf("basic: timezone name too long: %w", ErrInvalidArgument) } loc, err := time.LoadLocation(zone) if err != nil { return nil, fmt.Errorf("basic: invalid timezone %q: %w", zone, err) } now := time.Now().In(loc) return map[string]any{ "now": now.Format(layout), "unix": now.Unix(), "timezone": zone, "format": layout, }, nil }