Move NaT to self-contained module
State: closed

This completes the messing-with-NaT sequence of PRs.

Highlights:
- Removes duplicate definitions of `_nat_strings` across a couple of modules.
- `tslibs.nattype` relies on `util` but is otherwise free of pandas dependencies.
- `lib` currently depends on `tslib`; this is a big step towards changing this (note that in setup.py tslib is declared as depending on lib.  I think that declaration is wrong, but thats a separate issue.  Regardless, DAG for the win)

Lowlights:
- We have to patch some of the `NaT` method docstrings after importing into `tslib`.  I'm not wild about that.

Optimizations to consider:
- If we cdef the constant NaN at the module-level and return it instead of `np.nan`, the property lookups are about 15% faster.  The downside of this is that `NaT.day is np.nan` is no longer True.
- `@cython.final` may offer an optimization for some methods in `cdef class`es.  Because `_NaT` no longer subclasses `_Timestamp`, we can apply that optimization to `_Timestamp` methods, too.  No idea what level of speedup we get.

- [ ] closes #xxxx
- [ ] tests added / passed
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [ ] whatsnew entry


Labels:
name: Datetime
description: Datetime data dtype
name: Missing-data
description: np.nan, pd.NaT, pd.NA, dropna, isnull, interpolate

Comments:
circleci error:
```
ImportError: numpy.core.multiarray failed to import
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/ubuntu/pandas/pandas/__init__.py", line 61, in <module>
    from pandas.io.api import *
  File "/home/ubuntu/pandas/pandas/io/api.py", line 9, in <module>
    from pandas.io.excel import ExcelFile, ExcelWriter, read_excel
  File "/home/ubuntu/pandas/pandas/io/excel.py", line 25, in <module>
    import pandas._libs.json as json
SystemError: initialization of json raised unreported exception
```

<b>Update</b> never mind, I think I see where this came from.  Fixing shortly.
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=h1) Report
> Merging [#18014](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/b2d0d1bfe578ce91d545bd2f806655d0bf497440?src=pr&el=desc) will **decrease** coverage by `0.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/18014/graphs/tree.svg?height=150&width=650&token=eZ4WkYLtcO&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #18014      +/-   ##
==========================================
- Coverage   91.23%   91.22%   -0.02%     
==========================================
  Files         163      163              
  Lines       50091    50092       +1     
==========================================
- Hits        45703    45696       -7     
- Misses       4388     4396       +8
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `89.03% <100%> (ø)` | :arrow_up: |
| #single | `40.24% <0%> (-0.06%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/compat/pickle\_compat.py](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree#diff-cGFuZGFzL2NvbXBhdC9waWNrbGVfY29tcGF0LnB5) | `75.6% <ø> (ø)` | :arrow_up: |
| [pandas/core/tools/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvdG9vbHMvZGF0ZXRpbWVzLnB5) | `82.97% <100%> (ø)` | :arrow_up: |
| [pandas/tslib.py](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree#diff-cGFuZGFzL3RzbGliLnB5) | `100% <100%> (ø)` | :arrow_up: |
| [pandas/io/gbq.py](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree#diff-cGFuZGFzL2lvL2dicS5weQ==) | `25% <0%> (-58.34%)` | :arrow_down: |
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `97.75% <0%> (-0.1%)` | :arrow_down: |
| [pandas/io/pytables.py](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree#diff-cGFuZGFzL2lvL3B5dGFibGVzLnB5) | `92.84% <0%> (+0.04%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=footer). Last update [b2d0d1b...05e5981](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=h1) Report
> Merging [#18014](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/4578a039e95a18b453baf1e6d409b1c4a51aa238?src=pr&el=desc) will **decrease** coverage by `0.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/18014/graphs/tree.svg?height=150&width=650&token=eZ4WkYLtcO&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #18014      +/-   ##
==========================================
- Coverage   91.24%   91.23%   -0.02%     
==========================================
  Files         163      163              
  Lines       50114    50115       +1     
==========================================
- Hits        45729    45721       -8     
- Misses       4385     4394       +9
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `89.04% <100%> (ø)` | :arrow_up: |
| #single | `40.24% <0%> (-0.06%)` | :arrow_down: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/compat/pickle\_compat.py](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree#diff-cGFuZGFzL2NvbXBhdC9waWNrbGVfY29tcGF0LnB5) | `75.6% <ø> (ø)` | :arrow_up: |
| [pandas/core/tools/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvdG9vbHMvZGF0ZXRpbWVzLnB5) | `82.97% <100%> (ø)` | :arrow_up: |
| [pandas/tslib.py](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree#diff-cGFuZGFzL3RzbGliLnB5) | `100% <100%> (ø)` | :arrow_up: |
| [pandas/io/gbq.py](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree#diff-cGFuZGFzL2lvL2dicS5weQ==) | `25% <0%> (-58.34%)` | :arrow_down: |
| [pandas/core/frame.py](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZnJhbWUucHk=) | `97.75% <0%> (-0.1%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=footer). Last update [4578a03...4b7593e](https://codecov.io/gh/pandas-dev/pandas/pull/18014?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

```
___________ test_pickles[0.20.3-0.20.3_x86_64_darwin_2.7.14.pickle] ____________
[gw0] linux2 -- Python 2.7.14 /home/travis/miniconda3/envs/pandas/bin/python
current_pickle_data = {'cat': {'int16': [0, 1, 2, 3, 4, ..., 995, 996, 997, 998, 999]
Length: 1000
Categories (1000, int64): [0, 1, 2, 3, .....x'], [u'one', u'two']],
      ...2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]],
           names=[u'first', u'second'])}, ...}
version = '0.20.3', f = '0.20.3_x86_64_darwin_2.7.14.pickle'
    @pytest.mark.parametrize('version, f', legacy_pickle_versions())
    def test_pickles(current_pickle_data, version, f):
        if not is_platform_little_endian():
            pytest.skip("known failure on non-little endian")
    
        vf = tm.get_data_path('legacy_pickle/{}/{}'.format(version, f))
        with catch_warnings(record=True):
>           compare(current_pickle_data, vf, version)
pandas/tests/io/test_pickle.py:207: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pandas/tests/io/test_pickle.py:66: in compare
    data = pandas.read_pickle(vf)
pandas/io/pickle.py:110: in read_pickle
    return try_read(path)
pandas/io/pickle.py:108: in try_read
    lambda f: pc.load(f, encoding=encoding, compat=True))
pandas/io/pickle.py:84: in read_wrapper
    return func(f)
pandas/io/pickle.py:108: in <lambda>
    lambda f: pc.load(f, encoding=encoding, compat=True))
pandas/compat/pickle_compat.py:196: in load
    return up.load()
../../../miniconda3/envs/pandas/lib/python2.7/pickle.py:864: in load
    dispatch[key](self)
../../../miniconda3/envs/pandas/lib/python2.7/pickle.py:1096: in load_global
    klass = self.find_class(module, name)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
self = <pandas.compat.pickle_compat.Unpickler instance at 0x7f8e9438e320>
module = 'pandas._libs.tslib', name = '__nat_unpickle'
    def find_class(self, module, name):
        # override superclass
        key = (module, name)
        module, name = _class_locations_map.get(key, key)
        __import__(module)
        mod = sys.modules[module]
>       klass = getattr(mod, name)
E       AttributeError: 'module' object has no attribute '__nat_unpickle'
```
needs a rebase
thanks @jbrockmendel this was the big one!