Repository: pandas-dev/pandas
File: pandas/core/computation/pytables.py (Python)

Code before:
    def generate(self, v) -> str:
        """create and return the op string for this TermValue"""
        val = v.tostring(self.encoding)
        return f"({self.lhs} {self.op} {val})"

    def convert_value(self, conv_val) -> TermValue:
        """
        convert the expression that is in the term to something that is
        accepted by pytables
        """

        def stringify(value):
            if self.encoding is not None:
                return pprint_thing_encoded(value, encoding=self.encoding)
            return pprint_thing(value)

        kind = ensure_decoded(self.kind)
        meta = ensure_decoded(self.meta)
        if kind == "datetime" or (kind and kind.startswith("datetime64")):
            if isinstance(conv_val, (int, float)):
                conv_val = stringify(conv_val)
            conv_val = ensure_decoded(conv_val)
            unit = "ns"
            if "[" in kind:
                unit = cast("TimeUnit", kind.split("[")[-1][:-1])
            conv_val = Timestamp(conv_val).as_unit(unit)
            if conv_val.tz is not None:
                conv_val = conv_val.tz_convert("UTC")
            return TermValue(conv_val, conv_val._value, kind)
        elif kind.startswith("timedelta"):
            unit = "ns"
            if "[" in kind:
                unit = cast("TimeUnit", kind.split("[")[-1][:-1])
            if isinstance(conv_val, str):
                conv_val = Timedelta(conv_val)
            elif lib.is_integer(conv_val) or lib.is_float(conv_val):
                conv_val = Timedelta(conv_val, unit="s")
            else:
                conv_val = Timedelta(conv_val)
            conv_val = conv_val.as_unit(unit)._value
            return TermValue(int(conv_val), conv_val, kind)

        elif meta == "category":
            metadata = extract_array(self.metadata, extract_numpy=True)
            result: npt.NDArray[np.intp] | np.intp | int
            if conv_val not in metadata:
                result = -1
            else:
                # Find the index of the first match of conv_val in metadata
                result = np.flatnonzero(metadata == conv_val)[0]
            return TermValue(result, result, "integer")

Review comment (refactor):
Previously, the unit was hardcoded to `ns`, which caused this issue. Modified to extract the unit from kind, matching the `timedelta` logic(line 237-238)

Code after:
    def generate(self, v) -> str:
        """create and return the op string for this TermValue"""
        val = v.tostring(self.encoding)
        return f"({self.lhs} {self.op} {val})"

    def convert_value(self, conv_val) -> TermValue:
        """
        convert the expression that is in the term to something that is
        accepted by pytables
        """

        def stringify(value):
            if self.encoding is not None:
                return pprint_thing_encoded(value, encoding=self.encoding)
            return pprint_thing(value)

        kind = ensure_decoded(self.kind)
        meta = ensure_decoded(self.meta)
        if kind == "datetime" or (kind and kind.startswith("datetime64")):
            if isinstance(conv_val, (int, float)):
                conv_val = stringify(conv_val)
            conv_val = ensure_decoded(conv_val)
            unit: TimeUnit = "ns"
            if "[" in kind:
                unit = cast("TimeUnit", kind.split("[")[-1][:-1])
            conv_val = Timestamp(conv_val).as_unit(unit)
            if conv_val.tz is not None:
                conv_val = conv_val.tz_convert("UTC")
            return TermValue(conv_val, conv_val._value, kind)
        elif kind.startswith("timedelta"):
            unit = "ns"
            if "[" in kind:
                unit = cast("TimeUnit", kind.split("[")[-1][:-1])
            if isinstance(conv_val, str):
                conv_val = Timedelta(conv_val)
            elif lib.is_integer(conv_val) or lib.is_float(conv_val):
                conv_val = Timedelta(conv_val, unit="s")
            else:
                conv_val = Timedelta(conv_val)
            conv_val = conv_val.as_unit(unit)._value
            return TermValue(int(conv_val), conv_val, kind)

        elif meta == "category":
            metadata = extract_array(self.metadata, extract_numpy=True)
            result: npt.NDArray[np.intp] | np.intp | int
            if conv_val not in metadata:
                result = -1
            else:
                # Find the index of the first match of conv_val in metadata
                result = np.flatnonzero(metadata == conv_val)[0]
            return TermValue(result, result, "integer")