Is there any algorithm that finds the time complexity of another algorithm provided that it halts?
I think this is correct and incorrect at the same time. It depends on how we define the problem we want to solve.
Formulation I
If we are interested in an algorithm that given $\langle M, w\rangle$ will tell you how much time $M$ runs on $w$ (assuming it halts), then there is such an algorithm: emulate $M$ on $w$ and count the number of steps it does until it halts.

Formulation II
But, if we are interested in an algorithm that given $\langle M\rangle$ will give you a function $f:\mathbb{N}\rightarrow \mathbb{N}$ that bounds the running time of $M$, things get a little bit more complicated.
First, how do we describe a function $f$ with finite storage? there are $|\mathbb{N}^\mathbb{N}|=2^{\aleph_0}$ functions, and $2^{\aleph_0}$ words in $\{0,1\}^*$ as well. This means there is some way to map each word to a function and vice versa. We will ignore from now the problem of computing this mapping between words and functions, and will still show there is no algorithm for the problem.
Assume towards contradiction there is some $\hat M$ that solves our problem. Let us create a new machine $M'$ that given input $\langle M\rangle $, will first emulate $\hat M$ on $M$ to find some $f$ which describes the upper bound on the time it takes $M$ to halt (assuming it halts). Then, $M'$ will enter a loop for $f(|\langle M'\rangle |) + 1$ steps.
Now, consider what happens when $M'$ runs on the input $\langle M'\rangle$. $\hat M$ will give an upper bound $f$ on the running time of $M'$, and $M'$ will run for more than $f(|\langle M' \rangle|)$ steps, contradicting that $f$ is an upper bound (since the original input of $M'$ was $\langle M'\rangle$).
Thus, no such $\hat M$ can ever exist!