Repository: pandas-dev/pandas

Issue:
pd.Timedelta.resolution is different from datetime.timedelta.resolution
`timedelta.resolution` is documented as:
> The smallest possible difference between non-equal timedelta objects, timedelta(microseconds=1).

while `pandas.Timedelta.resolution` is doc-string'd as:
>return a string representing the lowest resolution that we have
```
In [9]: pd.Timedelta(minutes=30).resolution
Out[9]: 'T'

In [10]: timedelta(minutes=30).resolution
Out[10]: datetime.timedelta(0, 0, 1)
```

I think this difference should be addressed by either:
1) Documenting the difference between both but also supporting `datetime.timedelta`'s notion of resolution in `Timedelta` (i.e. something that returns `Timedelta(nanoseconds=1)`)
2) Making `Timedelta.resolution` consistent with `timedelta.resolution` and creating a new property for "the lowest resolution" of a `Timedelta` instance

Thoughts? 

xref #21336



Discussion:
I would prefer option 1.  Option 2 would commit us (to some extent) to tracking `datetime`, which is not necessarily bad, but I do prefer flexibility in general.
(Sorry this was initially posted against the wrong issue): 
I'm looking at https://github.com/pandas-dev/pandas/blob/9d61ab5aae0dd4ca3f805275c6a8ebcaeef77d64/pandas/_libs/tslibs/timedeltas.pyx#L797 and I think fixing this would be breaking change ... it isn't hard to change the return values but is that really the desired behavior?
@drewmassey if we move forward with option 1. Then we would:

1) Make a note in `pd.Timedelta.resolution` that this is different from `datetime.timedelta`
2) Create a separate property for `pd.Timedelta` to return `pd.Timedelta(nanoseconds=1)`

If we move forward with option 2 then yes it would be a breaking change. I would slightly prefer option 1 as well since it doesn't disrupt the current API.
Ok I can handle this. Let me get the PR through for issue #21336 to make sure I have the pandas workflow in shape and then I'll submit this one.
I think we should deprecate the current behavior and eventually change it to match the stdlib.  @mroeschke thoughts?
Agreed that we should match the stdlib.
Working on this I'm noticing that we also have Timestamp.resolution subtly different from datetime.resolution.  On datetime it is a class attribute, whereas on Timestamp it is a property
Yikes, and pd.NaT.resolution has the datetime behavior

Resolving patch:
diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py
--- a/pandas/core/indexes/timedeltas.py
+++ b/pandas/core/indexes/timedeltas.py
@@ -551,11 +551,11 @@ def _maybe_cast_slice_bound(self, label, side, kind):
 
         if isinstance(label, str):
             parsed = Timedelta(label)
-            lbound = parsed.round(parsed.resolution)
+            lbound = parsed.round(parsed.resolution_string)
             if side == 'left':
                 return lbound
             else:
-                return (lbound + to_offset(parsed.resolution) -
+                return (lbound + to_offset(parsed.resolution_string) -
                         Timedelta(1, 'ns'))
         elif ((is_integer(label) or is_float(label)) and
               not is_timedelta64_dtype(label)):


Test patch:
diff --git a/pandas/tests/scalar/test_nat.py b/pandas/tests/scalar/test_nat.py
--- a/pandas/tests/scalar/test_nat.py
+++ b/pandas/tests/scalar/test_nat.py
@@ -142,8 +142,8 @@ def test_nat_iso_format(get_nat):
 
 @pytest.mark.parametrize("klass,expected", [
     (Timestamp, ["freqstr", "normalize", "to_julian_date", "to_period", "tz"]),
-    (Timedelta, ["components", "delta", "is_populated", "to_pytimedelta",
-                 "to_timedelta64", "view"])
+    (Timedelta, ["components", "delta", "is_populated", "resolution_string",
+                 "to_pytimedelta", "to_timedelta64", "view"])
 ])
 def test_missing_public_nat_methods(klass, expected):
     # see gh-17327
diff --git a/pandas/tests/scalar/timedelta/test_timedelta.py b/pandas/tests/scalar/timedelta/test_timedelta.py
--- a/pandas/tests/scalar/timedelta/test_timedelta.py
+++ b/pandas/tests/scalar/timedelta/test_timedelta.py
@@ -742,6 +742,22 @@ def test_components(self):
         assert not result.iloc[0].isna().all()
         assert result.iloc[1].isna().all()
 
+    def test_resolution_string(self):
+        assert Timedelta(days=1).resolution_string == 'D'
+        assert Timedelta(days=1, hours=6).resolution_string == 'H'
+        assert Timedelta(days=1, minutes=6).resolution_string == 'T'
+        assert Timedelta(days=1, seconds=6).resolution_string == 'S'
+        assert Timedelta(days=1, milliseconds=6).resolution_string == 'L'
+        assert Timedelta(days=1, microseconds=6).resolution_string == 'U'
+        assert Timedelta(days=1, nanoseconds=6).resolution_string == 'N'
+
+    def test_resolution_deprecated(self):
+        # GH#21344
+        td = Timedelta(days=4, hours=3)
+        with tm.assert_produces_warning(FutureWarning) as w:
+            td.resolution
+        assert "Use Timedelta.resolution_string instead" in str(w[0].message)
+
 
 @pytest.mark.parametrize('value, expected', [
     (Timedelta('10S'), True),