Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue1358 date/time duration breakage #1359

Open
wants to merge 4 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions docs/source/Reference/sr3_options.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ count, size

duration
a floating point number indicating a quantity of seconds (0.001 is 1 milisecond)
modified by a unit suffix ( m-minute, h-hour, w-week )
modified by a unit suffix ( m-minute, h-hour, M-month, y-year )

flag
an option that has only True or False values (aka: a boolean value)
Expand Down Expand Up @@ -798,18 +798,18 @@ expire <duration> (default: 5m == five minutes. RECOMMEND OVERRIDING)
The **expire** option is expressed as a duration... it sets how long should live
a queue without connections.

A raw integer is expressed in seconds, if the suffix m,h,d,w
are used, then the interval is in minutes, hours, days, or weeks. After the queue expires,
A raw integer is expressed in seconds, if the suffix m,h,d,M
are used, then the interval is in minutes, hours, days, or months. After the queue expires,
the contents are dropped, and so gaps in the download data flow can arise. A value of
1d (day) or 1w (week) can be appropriate to avoid data loss. It depends on how long
1d (day) or 1m (month) can be appropriate to avoid data loss. It depends on how long
the subscriber is expected to shutdown, and not suffer data loss.

if no units are given, then a decimal number of seconds can be provided, such as
to indicate 0.02 to specify a duration of 20 milliseconds.

The **expire** setting must be overridden for operational use.
The default is set low because it defines how long resources on the broker will be assigned,
and in early use (when default was 1 week) brokers would often get overloaded with very
and in early use (when default was 1 month) brokers would often get overloaded with very
long queues for left-over experiments.

This *subtopic* option should appear after the *expire* setting in files
Expand Down Expand Up @@ -1304,10 +1304,10 @@ process looks for files in the cache that have not been referenced in **cache**
and deletes them, in order to keep the cache size limited. Different settings are
appropriate for different use cases.

A raw integer interval is in seconds, if the suffix m,h,d, or w are used, then the interval
is in minutes, hours, days, or weeks. After the interval expires the contents are
A raw integer interval is in seconds, if the suffix m,h,d, or M are used, then the interval
is in minutes, hours, days, or months. After the interval expires the contents are
dropped, so duplicates separated by a large enough interval will get through.
A value of 1d (day) or 1w (week) can be appropriate. Setting the option without specifying
A value of 1d (day) or 1M (Month) can be appropriate. Setting the option without specifying
a time will result in 300 seconds (or 5 minutes) being the expiry interval.

Default value in a Poll is 8 hours, should be longer than nodupe_fileAgeMax to prevent
Expand Down
10 changes: 5 additions & 5 deletions docs/source/fr/Reference/sr3_options.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ count

duration
un nombre à virgule flottante qui indique une quantité en secondes (0.001 est 1 milliseconde)
modifié par un suffixe unitaire ( m-minute, h-heure, w-semaine ).
modifié par un suffixe unitaire ( m-minute, h-heure, M-mois ).

flag
une option qui a la valeur soit Vrai (True ou on) ou Faux (False ou off) (une valeur booléenne).
Expand Down Expand Up @@ -786,18 +786,18 @@ expire <duration> (défaut: 5m == cinq minutes. RECOMMENDE DE REMPLACER)
L'option *expire* est exprimée sous forme d'une duration... ça fixe combien de temps une fil d’attente devrait
vivre sans connexions.

Un entier brut est exprimé en secondes, et si un des suffixe m,h,d,w est utilisés, l’intervalle est en minutes,
heures, jours ou semaines respectivement. Après l’expiration de la fil d’attente, le contenu est supprimé et
Un entier brut est exprimé en secondes, et si un des suffixe m,h,d,m est utilisés, l’intervalle est en minutes,
heures, jours ou mois respectivement. Après l’expiration de la fil d’attente, le contenu est supprimé et
des différences peuvent donc survenir dans le flux de données de téléchargement. Une valeur de
1d (jour) ou 1w (semaine) peut être approprié pour éviter la perte de données. Cela dépend de combien de temps
1d (jour) ou 1m (mois) peut être approprié pour éviter la perte de données. Cela dépend de combien de temps
l’abonné est sensé s’arrêter et ne pas subir de perte de données.

Si aucune unité n’est donnée, un nombre décimal de secondes peut être fourni, tel que
0,02 pour spécifier une durée de 20 millisecondes.

Le paramètre **expire** doit être remplacé pour une utilisation opérationnelle.
Le défaut est défini par une valeur basse car il définit combien de temps les ressources vont être
assigné au courtier, et dans les premières utilisations (lorsque le défaut était de de 1 semaine), les courtiers
assigné au courtier, et dans les premières utilisations (lorsque le défaut était de de 1 mois), les courtiers
étaient souvent surchargés de très longues files d’attente pour les tests restants.

l´option *subtopic* devrait apparaître après le paramètre *expire* dans les fichiers
Expand Down
76 changes: 59 additions & 17 deletions sarracenia/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,28 +316,51 @@ 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.

naturaldelta does not do weeks...
"""
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 +387,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 +399,24 @@ def durationToSeconds(str_value, default=None) -> float:
first_unit='d'
elif second_unit in 'd':
factor *= 60 * 60 * 24
first_unit='w'
if 'y' in str_value:
first_unit='y'
elif 'M' in str_value:
first_unit='M'
else:
first_unit='w'
elif second_unit in 'w':
factor *= 60 * 60 * 24 * 7
if 'y' in str_value:
first_unit='y'
elif 'M' in str_value:
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 @@ -394,6 +432,10 @@ def durationToSeconds(str_value, default=None) -> float:
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
31 changes: 24 additions & 7 deletions tests/sarracenia/__init___test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,33 @@ 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('1w') == 24*3600*7
assert sarracenia.durationToSeconds('2h2m') == 7320
assert sarracenia.durationToSeconds('3m2s') == 182
assert sarracenia.durationToSeconds( '6w1d' ) == 24*3600*(6*7.0+1)
assert sarracenia.durationToSeconds( '6M1d' ) == 16001280
assert sarracenia.durationToSeconds( '6M5d' ) == round( (6*30.7+5)*24*3600 ) # the math came out .99999 ...
assert sarracenia.durationToSeconds( '1y' ) == 365.25*24*3600
assert sarracenia.durationToSeconds( '1y28d' ) == (365.25+28)*24*3600
assert sarracenia.durationToSeconds( '1y1M' ) == (365.25+30.7)*24*3600
assert sarracenia.durationToSeconds( '1000w' ) == 1000*7*24*3600
assert sarracenia.durationToSeconds( '11y' ) == 11*365.25*24*3600



def test_durationToString():
assert sarracenia.durationToString( 3600 ) == '1h'
Expand All @@ -58,6 +67,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
Loading