Repository: pandas-dev/pandas

Issue:
ENH: support diff with datetime64[ns] on series/frame
see #2984

workaround right now is

```
In [4]: s = pd.Series(pd.date_range('20130102',periods=5))

In [5]: s
Out[5]: 
0   2013-01-02 00:00:00
1   2013-01-03 00:00:00
2   2013-01-04 00:00:00
3   2013-01-05 00:00:00
4   2013-01-06 00:00:00
dtype: datetime64[ns]

This is the workaround right now
In [6]: s-s.shift(1)
Out[6]: 
0                NaT
1   1 days, 00:00:00
2   1 days, 00:00:00
3   1 days, 00:00:00
4   1 days, 00:00:00
dtype: timedelta64[ns]
```

Bad.....

```
In [7]: s.diff()
Out[7]: 
0             NaN
1    8.640000e+13
2    8.640000e+13
3    8.640000e+13
4    8.640000e+13
dtype: float64
```



Discussion:

Resolving patch:
diff --git a/pandas/core/common.py b/pandas/core/common.py
--- a/pandas/core/common.py
+++ b/pandas/core/common.py
@@ -617,9 +617,18 @@ def func(arr, indexer, out, fill_value=np.nan):
 
 
 def diff(arr, n, axis=0):
+    """ difference of n between self,
+        analagoust to s-s.shift(n) """
+
     n = int(n)
     dtype = arr.dtype
-    if issubclass(dtype.type, np.integer):
+    na = np.nan
+
+    if is_timedelta64_dtype(arr) or is_datetime64_dtype(arr):
+        dtype = 'timedelta64[ns]'
+        arr = arr.view('i8')
+        na = tslib.iNaT
+    elif issubclass(dtype.type, np.integer):
         dtype = np.float64
     elif issubclass(dtype.type, np.bool_):
         dtype = np.object_
@@ -628,7 +637,7 @@ def diff(arr, n, axis=0):
 
     na_indexer = [slice(None)] * arr.ndim
     na_indexer[axis] = slice(None, n) if n >= 0 else slice(n, None)
-    out_arr[tuple(na_indexer)] = np.nan
+    out_arr[tuple(na_indexer)] = na
 
     if arr.ndim == 2 and arr.dtype.name in _diff_special:
         f = _diff_special[arr.dtype.name]
@@ -642,7 +651,24 @@ def diff(arr, n, axis=0):
         lag_indexer[axis] = slice(None, -n) if n > 0 else slice(-n, None)
         lag_indexer = tuple(lag_indexer)
 
-        out_arr[res_indexer] = arr[res_indexer] - arr[lag_indexer]
+        # need to make sure that we account for na for datelike/timedelta
+        # we don't actually want to subtract these i8 numbers
+        if dtype == 'timedelta64[ns]':
+            res = arr[res_indexer]
+            lag = arr[lag_indexer]
+
+            mask = (arr[res_indexer] == na) | (arr[lag_indexer] == na)
+            if mask.any():
+                res = res.copy()
+                res[mask] = 0
+                lag = lag.copy()
+                lag[mask] = 0
+
+            result = res-lag
+            result[mask] = na
+            out_arr[res_indexer] = result
+        else:
+            out_arr[res_indexer] = arr[res_indexer] - arr[lag_indexer]
 
     return out_arr
 


Test patch:
diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py
--- a/pandas/tests/test_series.py
+++ b/pandas/tests/test_series.py
@@ -4039,6 +4039,17 @@ def test_diff(self):
         xp = self.ts - self.ts
         assert_series_equal(rs, xp)
 
+        # datetime diff (GH3100)
+        s  = Series(date_range('20130102',periods=5))
+        rs = s-s.shift(1)
+        xp = s.diff()
+        assert_series_equal(rs, xp)
+
+        # timedelta diff
+        nrs = rs-rs.shift(1)
+        nxp = xp.diff()
+        assert_series_equal(nrs, nxp)
+
     def test_pct_change(self):
         rs = self.ts.pct_change(fill_method=None)
         assert_series_equal(rs, self.ts / self.ts.shift(1) - 1)