def assign_utc(self, reading_id, uptime=None, prefer="before"):
        if prefer not in ("before", "after"):
            raise ArgumentError("Invalid prefer parameter: {}, must be 'before' or 'after'".format(prefer))
        if len(self._anchor_points) == 0:
            return None
        if reading_id > self._anchor_points[-1].reading_id:
            return None
        i = self._anchor_points.bisect_key_left(reading_id)
        found_id = False
        crossed_break = False
        exact = True
        last = self._anchor_points[i].copy()
        if uptime is not None:
            last.uptime = uptime
        if last.reading_id == reading_id:
            found_id = True
            if last.utc is not None:
                return UTCAssignment(reading_id, last.utc, found_id, exact, crossed_break)
        left_assign = self._fix_left(reading_id, last, i, found_id)
        if left_assign is not None and left_assign.exact:
            return left_assign
        right_assign = self._fix_right(reading_id, last, i, found_id)
        if right_assign is not None and right_assign.exact:
            return right_assign
        return self._pick_best_fix(left_assign, right_assign, prefer)