forget-cancellare-vecchi-toot/libforget/interval.py

81 lines
2.4 KiB
Python
Raw Normal View History

2017-08-31 18:59:09 +02:00
from datetime import timedelta, datetime, timezone
2017-08-29 15:00:08 +02:00
from .timescales import SCALES
2017-08-29 14:46:32 +02:00
2017-08-01 20:57:15 +02:00
def decompose_interval(attrname):
scales = [scale[1] for scale in SCALES]
scales.reverse()
def decorator(cls):
scl_name = '{}_scale'.format(attrname)
sig_name = '{}_significand'.format(attrname)
@property
def scale(self):
if getattr(self, attrname) == timedelta(0):
2017-08-02 01:35:09 +02:00
return timedelta(minutes=1)
2017-08-01 20:57:15 +02:00
for m in scales:
if getattr(self, attrname) % m == timedelta(0):
return m
2017-08-02 01:35:09 +02:00
return timedelta(minutes=1)
2017-08-01 20:57:15 +02:00
@scale.setter
def scale(self, value):
2017-08-29 21:27:38 +02:00
if not isinstance(value, timedelta):
2017-08-01 20:57:15 +02:00
value = timedelta(seconds=float(value))
2017-08-09 09:14:42 +02:00
setattr(self, attrname, max(1, getattr(self, sig_name)) * value)
2017-08-01 20:57:15 +02:00
@property
def significand(self):
return int(getattr(self, attrname) / getattr(self, scl_name))
@significand.setter
def significand(self, value):
2017-08-29 21:27:38 +02:00
if isinstance(value, str) and value.strip() == '':
2017-08-07 16:33:35 +02:00
value = 0
try:
value = int(value)
2017-08-29 13:26:32 +02:00
if not value >= 0:
raise ValueError(value)
except ValueError as e:
2017-08-07 16:26:25 +02:00
raise ValueError("Incorrect time interval", e)
setattr(self, attrname, value * getattr(self, scl_name))
2017-08-01 20:57:15 +02:00
setattr(cls, scl_name, scale)
setattr(cls, sig_name, significand)
return cls
return decorator
2017-08-29 14:46:32 +02:00
def relative(interval):
# special cases
if interval > timedelta(seconds=-15) and interval < timedelta(0):
return "just now"
elif interval > timedelta(0) and interval < timedelta(seconds=15):
return "in a few seconds"
else:
output = None
for name, scale in reversed(SCALES):
if abs(interval) > scale:
value = abs(interval) // scale
output = '{} {}'.format(value, name)
if value == 1:
output = output[:-1]
break
if not output:
output = '{} seconds'.format(abs(interval).seconds)
if interval > timedelta(0):
return 'in {}'.format(output)
else:
return '{} ago'.format(output)
2017-08-29 14:46:32 +02:00
def relnow(time):
2017-08-31 18:59:09 +02:00
return relative(time - datetime.now(timezone.utc))