diff options
Diffstat (limited to '')
| -rw-r--r-- | bot/utils/time.py | 56 | 
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}" | 
