BUG: combine_first does not retain dtypes with Timestamp DataFrames
- [x] closes #28481
- [x] tests added / passed
- [x] passes `black pandas`
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [x] whatsnew entry

Picking up #35514
Why does combin_first use expressions.where instead of mgr.where? Casting should be handled correctly there > Why does combin_first use expressions.where instead of mgr.where? Casting should be handled correctly there

That line hasn't been touched since #17744, will look Now that i have an actual keyboard: this would likely also require fixing Block.where #38073 > Now that i have an actual keyboard: this would likely also require fixing Block.where #38073 

Ok - in this case this would sit on top of that

I'm struggling a little with the pattern. Atm I have:
``` python
    def combine_first(self, other: DataFrame) -> DataFrame:
        def combiner(x, y):
            mask = extract_array(isna(x))

            x_values = extract_array(x, extract_numpy=True)
            y_values = extract_array(y, extract_numpy=True)

            # If the column y in other DataFrame is not in first DataFrame,
            # just return y_values.
            if y.name not in self.columns:
                return y_values

            _where = self._mgr.where(y_values, mask, align=True, errors="raise", try_cast=True, axis=1)
            # extract array from _where

        return self.combine(other, combiner, overwrite=False)
```
Is this in the right ballpark?  > is the current patch not good for 1.2? (agreed could use some refactoring).

This looks good for now @arw2019 ok small test comment. ping on green. thanks @arw2019  @arw2019 do you have time to try to make this go through `self._mgr.where`?  (no hurry) > @arw2019 do you have time to try to make this go through `self._mgr.where`? (no hurry)

yes, in the works