Skip to content

Commit

Permalink
fix #1358 extend duration conversion to cover years
Browse files Browse the repository at this point in the history
  • Loading branch information
petersilva committed Dec 23, 2024
1 parent 518ed5d commit bbdbf18
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 28 deletions.
72 changes: 51 additions & 21 deletions sarracenia/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,28 +316,49 @@ def timev2tov3str(s):
else:
return s[0:8] + 'T' + s[8:]

"""
So for natural delta, tested stuff, and empirically it looks like humanize thinks this is how many days there are in a month.
At least assuming that makes calculations here match with what humanize does.
"""
days_in_a_month=30.7

def durationToString(d) -> str:
"""
given a numbner of seconds, return a short, human readable string.
"""
if (d < 60):
return f"{d:7.2f}s"

first_part= humanize.naturaldelta(d).replace("minutes","m").replace("seconds","s").replace("hours","h").replace("days","d").replace("an hour","1h").replace("a day","1d").replace("a minute","1m").replace(" ","")

second_part=""
if first_part[-1] == 'm':
rem=int(d-int(first_part[0:-1])*60)
if rem > 0:
second_part=f"{rem:d}s"
if first_part[-1] == 'h':
rem=int(( d-int(first_part[0:-1])*60*60 ) / 60 )
if rem > 0:
second_part=f"{rem:d}m"
if first_part[-1] == 'd':
rem=int (( d-int(first_part[0:-1])*60*60*24 ) / (60*60) )
if rem > 0:
second_part=f"{rem:d}h"
hnd = humanize.naturaldelta(d).replace("minute","m").replace("second","T").replace("hour","h").replace("day","d").replace("month","M").replace("year","y").replace(" ","").replace("s","").replace("T","s").replace("an", "1").replace("a","1")

if ',' in hnd:
( first_part, second_part ) = hnd.split(',')
else:
first_part=hnd
second_part=""

if not second_part:
if first_part[-1] == 'm':
rem=int(d-int(first_part[0:-1])*60)
if rem > 0:
second_part=f"{rem:d}s"
if first_part[-1] == 'h':
rem=int(( d-int(first_part[0:-1])*60*60 ) / 60 )
if rem > 0:
second_part=f"{rem:d}m"
if first_part[-1] == 'd':
rem=int (( d-int(first_part[0:-1])*60*60*24 ) / (60*60) )
if rem > 0:
second_part=f"{rem:d}h"
if first_part[-1] == 'M':
rem=int (( d-int(first_part[0:-1])*60*60*24*days_in_a_month ) / (60*60*24) )
if rem > 0:
second_part=f"{rem:d}d"
if first_part[-1] == 'y':
rem=int (( d-int(first_part[0:-1])*60*60*24*365.25 ) / (60*60*24*days_in_a_month ) )
if rem > 0:
second_part=f"{rem:d}M"
return first_part+second_part

def durationToSeconds(str_value, default=None) -> float:
Expand All @@ -364,7 +385,7 @@ def durationToSeconds(str_value, default=None) -> float:
return float(default)

first_unit=None
second_unit=str_value[-1].lower()
second_unit=str_value[-1]
if second_unit in 's':
factor *= 1
first_unit='m'
Expand All @@ -376,9 +397,16 @@ def durationToSeconds(str_value, default=None) -> float:
first_unit='d'
elif second_unit in 'd':
factor *= 60 * 60 * 24
first_unit='w'
elif second_unit in 'w':
factor *= 60 * 60 * 24 * 7
if 'y' in str_value:
first_unit='y'
else:
first_unit='M'
elif second_unit in 'M':
factor *= 60 * 60 * 24 * days_in_a_month
if 'y' in str_value:
first_unit='y'
elif second_unit in 'y':
factor *= 60 * 60 * 24 * 365.25

if str_value[-1].isalpha(): str_value = str_value[:-1]

Expand All @@ -392,8 +420,10 @@ def durationToSeconds(str_value, default=None) -> float:
big = big*60*60
elif first_unit == 'd':
big = big*60*60*24
elif first_unit == 'w':
big = big*60*60*24*7
elif first_unit == 'M':
big = big*60*60*24*days_in_a_month
elif first_unit == 'y':
big = big*60*60*24*365.25
str_value = little
else:
big=0
Expand Down
26 changes: 19 additions & 7 deletions tests/sarracenia/__init___test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,28 @@ def test_durationToSeconds():
assert sarracenia.durationToSeconds('none') == sarracenia.durationToSeconds('off') == sarracenia.durationToSeconds('false') == 0.0
assert sarracenia.durationToSeconds('on', default=10) == sarracenia.durationToSeconds('true', default=10) == 10.0

assert sarracenia.durationToSeconds('1s') == sarracenia.durationToSeconds('1S') == 1.0
assert sarracenia.durationToSeconds('2m') == sarracenia.durationToSeconds('2M') == 120.0
assert sarracenia.durationToSeconds('3h') == sarracenia.durationToSeconds('3H') == 10800.0
assert sarracenia.durationToSeconds('4d') == sarracenia.durationToSeconds('4D') == 345600.0
assert sarracenia.durationToSeconds('1w') == sarracenia.durationToSeconds('1W') == 604800.0
assert sarracenia.durationToSeconds('0.5h') == sarracenia.durationToSeconds('0.5H') == 1800.0
assert sarracenia.durationToSeconds('1s') == 1.0
assert sarracenia.durationToSeconds('2m') == 120.0
assert sarracenia.durationToSeconds('3h') == 10800.0
assert sarracenia.durationToSeconds('4d') == 345600.0
assert sarracenia.durationToSeconds('0.5h') == 1800.0

assert sarracenia.durationToSeconds('invalid') == 0.0
assert sarracenia.durationToSeconds(b'5') == 0.0
assert sarracenia.durationToSeconds([5]) == 5.0

assert sarracenia.durationToSeconds(2.5) == 2.5
assert sarracenia.durationToSeconds('1s', default=None) == 1.0
assert sarracenia.durationToSeconds('1y') == 1.0
assert sarracenia.durationToSeconds('-1s') == -1.0
assert sarracenia.durationToSeconds('-1.5h') == -5400.0
assert sarracenia.durationToSeconds('2h2m') == 7320
assert sarracenia.durationToSeconds('3m2s') == 182
assert sarracenia.durationToSeconds( '6M1d' ) == 16001280.0
assert sarracenia.durationToSeconds( '6M5d' ) == 16346880.0
assert sarracenia.durationToSeconds( '1y' ) == 31557600.0
assert sarracenia.durationToSeconds( '1y28d' ) == 33976800.0
assert sarracenia.durationToSeconds( '1y1M' ) == 34210080.0


def test_durationToString():
assert sarracenia.durationToString( 3600 ) == '1h'
Expand All @@ -58,6 +62,14 @@ def test_durationToString():
assert sarracenia.durationToString( 6*3600 ) == '6h'
assert sarracenia.durationToString( 6*3600+120 ) == '6h2m'
assert sarracenia.durationToString( 26*3600+120 ) == '1d2h'
assert sarracenia.durationToString( 30*24*3600 ) == '30d'
assert sarracenia.durationToString( 35*24*3600 ) == '1M4d'
assert sarracenia.durationToString( 182*24*3600 ) == '5M28d'
assert sarracenia.durationToString( 186*24*3600 ) == '6M1d'
assert sarracenia.durationToString( 190*24*3600 ) == '6M5d'
assert sarracenia.durationToString( 365*24*3600 ) == '1y'
assert sarracenia.durationToString( 393*24*3600 ) == '1y28d'
assert sarracenia.durationToString( 396*24*3600 ) == '1y1M'

def test_timeValidate():
assert sarracenia.timeValidate('20230710120000') == True
Expand Down

0 comments on commit bbdbf18

Please sign in to comment.