2

I'm looking for a simple and neat way to check if a variable is positive where this can be either a float or a numpy.timedelta64 or datetime.timedelta.

I obviously tried x>0, but this doesn't work for timedeltas (neither numpy's or datetime's)

The only solution i found is x/abs(x) > 0 that I find somehow cumbersome. Not even np.sign returns an answer.

Is there a better way to check this?

EDIT: Using x.total_seconds() returns an error whenever x is a float. Using x > np.timedelta(0) does not work for datetime.timedeltas.

jpp
  • 159,742
  • 34
  • 281
  • 339
Luca
  • 1,610
  • 1
  • 19
  • 30
  • Possible duplicate of [Python timedelta issue with negative values](https://stackoverflow.com/questions/8408397/python-timedelta-issue-with-negative-values) – Nick Chapman Nov 26 '18 at 15:21
  • If i use `x.total_seconds()` I get an error whenever `x` is a `float` – Luca Nov 26 '18 at 15:23
  • 1
    if isinstance(x, timedelta): return x.total_seconds() > 0 else: return x > 0 – Nick Chapman Nov 26 '18 at 15:29
  • Sure. But I would need to add one case for `np,timedelta64`, one for `datetime.timedelta` (as they are different classes) and one for floats. If this is the best, I think `x/abs(x)>0`is still a better solution. – Luca Nov 26 '18 at 15:37
  • 1
    x==abs(x) seems to work with both. You may need a check for zero though. – Tls Chris Nov 26 '18 at 15:47

3 Answers3

3

You can compare against a "zero time-delta" object, then use try / except to cover numeric inputs:

import numpy as np
from datetime import timedelta

def pos_check(x, zero_value=timedelta()):
    try:
        return x > zero_value
    except TypeError:
        return x > 0

py_td = timedelta(days=1)      # 1-day, regular Python
np_td = np.timedelta64(py_td)  # 1-day, NumPy

assert pos_check(1.5)
assert pos_check(py_td)
assert pos_check(np_td)
jpp
  • 159,742
  • 34
  • 281
  • 339
2

If you are willing to use pandas, you can first cast all input types to a pandas Timedelta, and then check for positivity in a single line:

import numpy as np
import pandas as pd
from datetime import timedelta

def pos_check(x, zero_value=pd.Timedelta(0,'s')):
    return pd.Timedelta(x) > zero_value

py_td = timedelta(days=1)      # 1-day, regular Python
np_td = np.timedelta64(py_td)  # 1-day, NumPy
pd_td = pd.Timedelta(np_td)

assert pos_check(1.5)
assert pos_check(py_td)
assert pos_check(np_td)
assert pos_check(pd_td)
dloeckx
  • 1,110
  • 1
  • 10
  • 8
0

As @NickChapman noted, using isinstance is probably easier (to read). Dont forget you can test the type of data against many classes at once:

def check_positive(x):
    if isinstance(x, (datetime.timedelta, np.timedelta64)):
        return x.total_seconds() > 0
    else:
        return x > 0
Antwane
  • 20,760
  • 7
  • 51
  • 84