Finds operations by time and qubit.

        Args:
            time: Operations must end after this time to be returned.
            duration: Operations must start by time+duration to be
                returned.
            qubits: If specified, only operations touching one of the included
                qubits will be returned.
            include_query_end_time: Determines if the query interval includes
                its end time. Defaults to no.
            include_op_end_times: Determines if the scheduled operation
                intervals include their end times or not. Defaults to no.

        Returns:
            A list of scheduled operations meeting the specified conditions.

def query(
            self,
            *,  # Forces keyword args.
            time: Timestamp,
            duration: Union[Duration, timedelta] = Duration(),
            qubits: Iterable[Qid] = None,
            include_query_end_time=False,
            include_op_end_times=False) -> List[ScheduledOperation]:
        """Finds operations by time and qubit.

        Args:
            time: Operations must end after this time to be returned.
            duration: Operations must start by time+duration to be
                returned.
            qubits: If specified, only operations touching one of the included
                qubits will be returned.
            include_query_end_time: Determines if the query interval includes
                its end time. Defaults to no.
            include_op_end_times: Determines if the scheduled operation
                intervals include their end times or not. Defaults to no.

        Returns:
            A list of scheduled operations meeting the specified conditions.
        """
        duration = Duration.create(duration)
        earliest_time = time - self._max_duration
        end_time = time + duration
        qubits = None if qubits is None else frozenset(qubits)

        def overlaps_interval(op):
            if not include_op_end_times and op.time + op.duration == time:
                return False
            if not include_query_end_time and op.time == end_time:
                return False
            return op.time + op.duration >= time and op.time <= end_time

        def overlaps_qubits(op):
            if qubits is None:
                return True
            return not qubits.isdisjoint(op.operation.qubits)

        potential_matches = self.scheduled_operations.irange_key(earliest_time,
                                                                 end_time)
        return [op
                for op in potential_matches
                if overlaps_interval(op) and overlaps_qubits(op)]