aboutsummaryrefslogtreecommitdiffstats
path: root/bot/converters.py
diff options
context:
space:
mode:
Diffstat (limited to 'bot/converters.py')
-rw-r--r--bot/converters.py35
1 files changed, 35 insertions, 0 deletions
diff --git a/bot/converters.py b/bot/converters.py
index 7386187ab..b7340982b 100644
--- a/bot/converters.py
+++ b/bot/converters.py
@@ -1,4 +1,5 @@
import logging
+import re
from datetime import datetime
from ssl import CertificateError
from typing import Union
@@ -6,6 +7,7 @@ from typing import Union
import dateparser
import discord
from aiohttp import ClientConnectorError
+from dateutil.relativedelta import relativedelta
from discord.ext.commands import BadArgument, Context, Converter
@@ -197,3 +199,36 @@ class ExpirationDate(Converter):
expiry = now + (now - expiry)
return expiry
+
+
+class Duration(Converter):
+ """Convert duration strings into UTC datetime.datetime objects."""
+
+ duration_parser = re.compile(
+ r"((?P<years>\d+?)(years|year|Y|y))?"
+ r"((?P<months>\d+?)(months|month|m))?"
+ r"((?P<weeks>\d+?)(weeks|week|W|w))?"
+ r"((?P<days>\d+?)(days|day|D|d))?"
+ r"((?P<hours>\d+?)(hours|hour|H|h))?"
+ r"((?P<minutes>\d+?)(minutes|minute|M))?"
+ r"((?P<seconds>\d+?)(seconds|second|S|s))?"
+ )
+
+ async def convert(self, ctx: Context, duration: str) -> datetime:
+ """
+ Converts a `duration` string to a datetime object that's `duration` in the future.
+
+ The converter supports years (symbols: `years`, `year, `Y`, `y`), months (`months`, `month`,
+ `m`), weeks (`weeks`, `week`, `W`, `w`), days (`days`, `day`, `D`, `d`), hours (`hours`,
+ `hour`, `H`, `h`), minutes (`minutes`, `minute`, `M`), and seconds (`seconds`, `second`,
+ `S`, `s`), The units must be provided in descending order of magnitude.
+ """
+ match = self.duration_parser.fullmatch(duration)
+ if not match:
+ raise BadArgument(f"`{duration}` is not a valid duration string.")
+
+ duration_dict = {unit: int(amount) for unit, amount in match.groupdict().items() if amount}
+ delta = relativedelta(**duration_dict)
+ now = datetime.utcnow()
+
+ return now + delta