aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/utils/time.py56
1 files changed, 8 insertions, 48 deletions
diff --git a/bot/utils/time.py b/bot/utils/time.py
index d3000a7c2..ec47fce2e 100644
--- a/bot/utils/time.py
+++ b/bot/utils/time.py
@@ -1,21 +1,12 @@
import asyncio
import datetime
-from typing import List, Optional
+from typing import Optional
import dateutil.parser
from dateutil.relativedelta import relativedelta
RFC1123_FORMAT = "%a, %d %b %Y %H:%M:%S GMT"
INFRACTION_FORMAT = "%Y-%m-%d %H:%M"
-TIME_MARKS = (
- (60, 'second'), # 1 minute
- (60, 'minute'), # 1 hour
- (24, 'hour'), # 1 day
- (7, 'day'), # 1 week
- (4, 'week'), # 1 month
- (12, 'month'), # 1 year
- (999, 'year') # dumb the rest as year, max 999
-)
def _stringify_time_unit(value: int, unit: str) -> str:
@@ -122,48 +113,17 @@ def format_infraction(timestamp: str) -> str:
return dateutil.parser.isoparse(timestamp).strftime(INFRACTION_FORMAT)
-def get_duration(date_from: datetime.datetime, date_to: datetime.datetime, parts: Optional[int] = 2) -> str:
- """
- Get the duration between two datetime, in human readable format.
-
- Will return <parts> number of units if avaiable, for example:
- - 11 hours, 59 minutes
- - 1 week, 6 minutes
- - 7 months, 2 weeks
- - 3 years, 3 months
- - 5 minutes
-
- :param date_from: A datetime.datetime object.
- :param date_to: A datetime.datetime object.
- :param parts: An int, defauted to two - the amount of units to return.
- """
- div = abs(date_from - date_to).total_seconds()
- div = round(div, 0) # to avoid (14 minutes, 60 seconds)
- results: List[str] = []
- for unit, name in TIME_MARKS:
- div, amount = divmod(div, unit)
- if amount > 0:
- plural = 's' if amount > 1 else ''
- results.append(f"{amount:.0f} {name}{plural}")
- parts = parts if parts is not None else len(results) # allow passing None directly to return all parts
- # We have to reverse the order of units because currently it's smallest -> largest
- return ', '.join(results[::-1][:parts])
-
-
def get_duration_from_expiry(
expiry: str = None,
date_from: datetime.datetime = None,
- parts: Optional[int] = 2
+ max_units: int = 2
) -> Optional[str]:
"""
- Get the duration between datetime.utcnow() and an expiry, in human readable format.
+ Returns a human-readable version of the the duration between datetime.utcnow() and an expiry.
- Will return the two biggest units avaiable, for example:
- - 11 hours, 59 minutes
- - 1 week, 6 minutes
- - 7 months, 2 weeks
- - 3 years, 3 months
- - 5 minutes
+ Unlike the original function, this function will force the precision to be 'seconds' by not passing it.
+ max_units specifies the maximum number of units of time to include (e.g. 1 may include days but not hours).
+ By default, max_units is 2
:param expiry: A string. If not passed in, will early return a None ( Permanent infraction ).
:param date_from: A datetime.datetime object. If not passed in, will use datetime.utcnow().
@@ -173,11 +133,11 @@ def get_duration_from_expiry(
return None
date_from = date_from or datetime.datetime.utcnow()
- date_to = dateutil.parser.isoparse(expiry).replace(tzinfo=None)
+ date_to = dateutil.parser.isoparse(expiry).replace(tzinfo=None, microsecond=0)
expiry_formatted = format_infraction(expiry)
- duration = get_duration(date_from, date_to, parts)
+ duration = humanize_delta(relativedelta(date_to, date_from), max_units=max_units)
duration_formatted = f" ({duration})" if duration else ''
return f"{expiry_formatted}{duration_formatted}"