Numpy: Checking if a value is NaT


Python Problem Overview

nat = np.datetime64('NaT')
nat == nat
>> FutureWarning: In the future, 'NAT == x' and 'x == NAT' will always be False.

>> TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

How can I check if a datetime64 is NaT? I can't seem to dig anything out of the docs. I know Pandas can do it, but I'd rather not add a dependency for something so basic.

Python Solutions

Solution 1 - Python

[tag:pandas] can check for NaT with pandas.isnull:

>>> import numpy as np
>>> import pandas as pd
>>> pd.isnull(np.datetime64('NaT'))

If you don't want to use pandas you can also define your own function (parts are taken from the pandas source):

nat_as_integer = np.datetime64('NAT').view('i8')

def isnat(your_datetime):
    dtype_string = str(your_datetime.dtype)
    if 'datetime64' in dtype_string or 'timedelta64' in dtype_string:
        return your_datetime.view('i8') == nat_as_integer
    return False  # it can't be a NaT if it's not a dateime

This correctly identifies NaT values:

>>> isnat(np.datetime64('NAT'))

>>> isnat(np.timedelta64('NAT'))

And realizes if it's not a datetime or timedelta:

>>> isnat(np.timedelta64('NAT').view('i8'))

In the future there might be an isnat-function in the numpy code, at least they have a (currently open) pull request about it: Link to the PR (NumPy github)

Solution 2 - Python

Since NumPy version 1.13 it contains an isnat function:

>>> import numpy as np
>>> np.isnat(np.datetime64('nat'))

It also works for arrays:

>>> np.isnat(np.array(['nat', 1, 2, 3, 4, 'nat', 5], dtype='datetime64[D]'))
array([ True, False, False, False, False,  True, False], dtype=bool)

Solution 3 - Python

INTRO: This answer was written in a time when Numpy was version 1.11 and behaviour of NAT comparison was supposed to change since version 1.12. Clearly that wasn't the case and the second part of answer became wrong. The first part of answer may be not applicable for new versions of numpy. Be sure you've checked MSeifert's answers below.

When you make a comparison at the first time, you always have a warning. But meanwhile returned result of comparison is correct:

import numpy as np    
nat = np.datetime64('NaT')

def nat_check(nat):
    return nat == np.datetime64('NaT')    

Out[4]: FutureWarning: In the future, 'NAT == x' and 'x == NAT' will always be False.

Out[5]: True

If you want to suppress the warning you can use the catch_warnings context manager:

import numpy as np
import warnings

nat = np.datetime64('NaT')

def nat_check(nat):
    with warnings.catch_warnings():
        return nat == np.datetime64('NaT')    

Out[5]: True

EDIT: For some reason behavior of NAT comparison in Numpy version 1.12 wasn't change, so the next code turned out to be inconsistent.

And finally you might check numpy version to handle changed behavior since version 1.12.0:

def nat_check(nat):
    if [int(x) for x in np.__version__.split('.')[:-1]] > [1, 11]:
        return nat != nat
    with warnings.catch_warnings():
        return nat == np.datetime64('NaT')

EDIT: As MSeifert mentioned, Numpy contains isnat function since version 1.13.

Solution 4 - Python

Very simple and surprisingly fast: (without numpy or pandas)

    str( myDate ) == 'NaT'            # True if myDate is NaT

Ok, it's a little nasty, but given the ambiguity surrounding 'NaT' it does the job nicely.

It's also useful when comparing two dates either of which might be NaT as follows:

   str( date1 ) == str( date1 )       # True
   str( date1 ) == str( NaT )         # False
   str( NaT )   == str( date1 )       # False

wait for it...

   str( NaT )   == str( Nat )         # True    (hooray!)

Solution 5 - Python

This approach avoids the warnings while preserving the array-oriented evaluation.

import numpy as np
def isnat(x):
    datetime64 analog to isnan.
    doesn't yet exist in numpy - other ways give warnings
    and are likely to change.  
    return x.astype('i8') == np.datetime64('NaT').astype('i8')

Solution 6 - Python

Another way would be to catch the exeption:

def is_nat(npdatetime):
        return False
        return True


All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser65View Question on Stackoverflow
Solution 1 - PythonMSeifertView Answer on Stackoverflow
Solution 2 - PythonMSeifertView Answer on Stackoverflow
Solution 3 - PythonVadim ShkaberdaView Answer on Stackoverflow
Solution 4 - PythonCodeCabbieView Answer on Stackoverflow
Solution 5 - PythonrustyView Answer on Stackoverflow
Solution 6 - PythonGuestView Answer on Stackoverflow