ENH: Add na_value argument to DataFrame.to_numpy
- [x] closes #33820
- [x] tests added / passed
- [x] passes `black pandas`
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [x] whatsnew entry

Another interesting issue is the behavior for mixed numeric and non-numeric data types. In the docstring we say that these will promote to object, which does happen but apparently numpy decides to convert the datetime to int beforehand anyways (we get the expected output if we explicitly ask for object):
```python
[ins] In [1]: df = pd.DataFrame({"A": [1, 2], "B": [3.0, 4.5]})                                                                                                                                              

[ins] In [2]: df['C'] = pd.date_range('2000', periods=2)                                                                                                                                                     

[ins] In [3]: df.to_numpy()                                                                                                                                                                                  
Out[3]: 
array([[1, 3.0, 946684800000000000],
       [2, 4.5, 946771200000000000]], dtype=object)

[ins] In [4]: df.to_numpy(dtype=object)                                                                                                                                                                      
Out[4]: 
array([[1, 3.0, Timestamp('2000-01-01 00:00:00')],
       [2, 4.5, Timestamp('2000-01-02 00:00:00')]], dtype=object)
``` So I think you need to deal with this deeper into the internals, as I mentioned before. It is there that the custom pandas logic to decide on the resulting dtype is done (which is indeed different from numpy's result dtype) Check BlockManager.as_array -> this also already handles the case of a single Block (to keep the no copy behaviour there).

I think we can expand that method to support na_value thanks @dsaxton 