split utils.datetime out in to .parse and .format
This commit is contained in:
parent
53c6cc8538
commit
d0d5cc4d08
26 changed files with 117 additions and 102 deletions
|
@ -22,7 +22,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
).replace(tzinfo=datetime.timezone.utc)
|
).replace(tzinfo=datetime.timezone.utc)
|
||||||
|
|
||||||
def _date_str(self, dt: datetime.datetime):
|
def _date_str(self, dt: datetime.datetime):
|
||||||
return utils.datetime.date_human(dt)
|
return utils.datetime.format.date_human(dt)
|
||||||
|
|
||||||
def _round_up_day(self, dt: datetime.datetime):
|
def _round_up_day(self, dt: datetime.datetime):
|
||||||
return dt.date()+datetime.timedelta(days=1)
|
return dt.date()+datetime.timedelta(days=1)
|
||||||
|
@ -57,7 +57,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
found_badge = self._find_badge(badges, badge)
|
found_badge = self._find_badge(badges, badge)
|
||||||
|
|
||||||
if found_badge:
|
if found_badge:
|
||||||
dt = utils.datetime.iso8601_parse(badges[found_badge])
|
dt = utils.datetime.parse.iso8601(badges[found_badge])
|
||||||
days_since = self._days_since(now, dt)
|
days_since = self._days_since(now, dt)
|
||||||
event["stdout"].write("(%s) %s on day %s (%s)" % (
|
event["stdout"].write("(%s) %s on day %s (%s)" % (
|
||||||
event["user"].nickname, found_badge, days_since,
|
event["user"].nickname, found_badge, days_since,
|
||||||
|
@ -78,7 +78,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
badges = []
|
badges = []
|
||||||
for badge, date in self._get_badges(user).items():
|
for badge, date in self._get_badges(user).items():
|
||||||
days_since = self._days_since(now,
|
days_since = self._days_since(now,
|
||||||
utils.datetime.iso8601_parse(date))
|
utils.datetime.parse.iso8601(date))
|
||||||
badges.append("%s on day %s" % (
|
badges.append("%s on day %s" % (
|
||||||
badge, days_since))
|
badge, days_since))
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
if badge_name.lower() == badge_lower:
|
if badge_name.lower() == badge_lower:
|
||||||
raise utils.EventError("You already have a '%s' badge" % badge)
|
raise utils.EventError("You already have a '%s' badge" % badge)
|
||||||
|
|
||||||
badges[badge] = utils.datetime.iso8601_format_now()
|
badges[badge] = utils.datetime.format.iso8601_now()
|
||||||
self._set_badges(event["user"], badges)
|
self._set_badges(event["user"], badges)
|
||||||
event["stdout"].write("Added '%s' badge" % badge)
|
event["stdout"].write("Added '%s' badge" % badge)
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
found_badge = self._find_badge(badges, badge)
|
found_badge = self._find_badge(badges, badge)
|
||||||
|
|
||||||
if found_badge:
|
if found_badge:
|
||||||
badges[found_badge] = utils.datetime.iso8601_format_now()
|
badges[found_badge] = utils.datetime.format.iso8601_now()
|
||||||
self._set_badges(event["user"], badges)
|
self._set_badges(event["user"], badges)
|
||||||
event["stdout"].write("Reset badge '%s'" % found_badge)
|
event["stdout"].write("Reset badge '%s'" % found_badge)
|
||||||
else:
|
else:
|
||||||
|
@ -158,7 +158,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
|
|
||||||
dt = self._parse_date(event["args_split"][-1])
|
dt = self._parse_date(event["args_split"][-1])
|
||||||
|
|
||||||
badges[found_badge] = utils.datetime.iso8601_format(dt)
|
badges[found_badge] = utils.datetime.format.iso8601(dt)
|
||||||
self._set_badges(event["user"], badges)
|
self._set_badges(event["user"], badges)
|
||||||
event["stdout"].write("Updated '%s' badge to %s" % (
|
event["stdout"].write("Updated '%s' badge to %s" % (
|
||||||
found_badge, self._date_str(dt)))
|
found_badge, self._date_str(dt)))
|
||||||
|
@ -176,7 +176,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
found_badge = self._find_badge(badges, badge)
|
found_badge = self._find_badge(badges, badge)
|
||||||
dt = self._parse_date(event["args_split"][-1])
|
dt = self._parse_date(event["args_split"][-1])
|
||||||
|
|
||||||
badges[found_badge or badge] = utils.datetime.iso8601_format(dt)
|
badges[found_badge or badge] = utils.datetime.format.iso8601(dt)
|
||||||
self._set_badges(event["user"], badges)
|
self._set_badges(event["user"], badges)
|
||||||
|
|
||||||
add_or_update = "Added" if not found_badge else "Updated"
|
add_or_update = "Added" if not found_badge else "Updated"
|
||||||
|
|
|
@ -27,7 +27,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
def _log(self, server, channel, line):
|
def _log(self, server, channel, line):
|
||||||
if self._enabled(server, channel):
|
if self._enabled(server, channel):
|
||||||
with open(self._file(str(server), str(channel)), "a") as log:
|
with open(self._file(str(server), str(channel)), "a") as log:
|
||||||
timestamp = utils.datetime.datetime_human(
|
timestamp = utils.datetime.format.datetime_human(
|
||||||
datetime.datetime.now())
|
datetime.datetime.now())
|
||||||
log.write("%s %s\n" % (timestamp, line))
|
log.write("%s %s\n" % (timestamp, line))
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
time_left = self.bot.cache.until_expiration(cache)
|
time_left = self.bot.cache.until_expiration(cache)
|
||||||
event["stderr"].write("%s: Please wait %s before redeeming" % (
|
event["stderr"].write("%s: Please wait %s before redeeming" % (
|
||||||
event["user"].nickname,
|
event["user"].nickname,
|
||||||
utils.datetime.to_pretty_time(math.ceil(time_left))))
|
utils.datetime.format.to_pretty_time(time_left)))
|
||||||
else:
|
else:
|
||||||
event["stderr"].write(
|
event["stderr"].write(
|
||||||
"%s: You can only redeem coins when you have none" %
|
"%s: You can only redeem coins when you have none" %
|
||||||
|
@ -520,7 +520,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
"""
|
"""
|
||||||
until = self._until_next_6_hour()
|
until = self._until_next_6_hour()
|
||||||
event["stdout"].write("Next lottery is in: %s" %
|
event["stdout"].write("Next lottery is in: %s" %
|
||||||
utils.datetime.to_pretty_time(until))
|
utils.datetime.format.to_pretty_time(until))
|
||||||
|
|
||||||
@utils.hook("received.command.lotterywinner")
|
@utils.hook("received.command.lotterywinner")
|
||||||
def lottery_winner(self, event):
|
def lottery_winner(self, event):
|
||||||
|
|
|
@ -52,7 +52,7 @@ class Server(object):
|
||||||
activities.append([activity_id, content, timestamp])
|
activities.append([activity_id, content, timestamp])
|
||||||
return activities
|
return activities
|
||||||
def _make_activity(self, content):
|
def _make_activity(self, content):
|
||||||
timestamp = utils.datetime.iso8601_format_now()
|
timestamp = utils.datetime.format.iso8601_now()
|
||||||
activity_id = self._random_id()
|
activity_id = self._random_id()
|
||||||
self.bot.set_setting("ap-activity-%s" % activity_id,
|
self.bot.set_setting("ap-activity-%s" % activity_id,
|
||||||
[content, timestamp])
|
[content, timestamp])
|
||||||
|
|
|
@ -183,7 +183,7 @@ class GitHub(object):
|
||||||
return url
|
return url
|
||||||
|
|
||||||
def _iso8601(self, s):
|
def _iso8601(self, s):
|
||||||
return utils.datetime.iso8601_parse(s)
|
return utils.datetime.parse.iso8601(s)
|
||||||
|
|
||||||
def ping(self, data):
|
def ping(self, data):
|
||||||
return ["Received new webhook"]
|
return ["Received new webhook"]
|
||||||
|
@ -444,7 +444,8 @@ class GitHub(object):
|
||||||
completed_at = self._iso8601(data["check_run"]["completed_at"])
|
completed_at = self._iso8601(data["check_run"]["completed_at"])
|
||||||
if completed_at > started_at:
|
if completed_at > started_at:
|
||||||
seconds = (completed_at-started_at).total_seconds()
|
seconds = (completed_at-started_at).total_seconds()
|
||||||
duration = " in %s" % utils.datetime.to_pretty_time(seconds)
|
duration = " in %s" % utils.datetime.format.to_pretty_time(
|
||||||
|
seconds)
|
||||||
|
|
||||||
status = data["check_run"]["status"]
|
status = data["check_run"]["status"]
|
||||||
status_str = ""
|
status_str = ""
|
||||||
|
|
|
@ -11,7 +11,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
@utils.kwarg("help", "Set a reminder")
|
@utils.kwarg("help", "Set a reminder")
|
||||||
@utils.kwarg("usage", "<time> <message>")
|
@utils.kwarg("usage", "<time> <message>")
|
||||||
def in_command(self, event):
|
def in_command(self, event):
|
||||||
seconds = utils.datetime.from_pretty_time(event["args_split"][0])
|
seconds = utils.datetime.parse.from_pretty_time(event["args_split"][0])
|
||||||
message = " ".join(event["args_split"][1:])
|
message = " ".join(event["args_split"][1:])
|
||||||
if seconds:
|
if seconds:
|
||||||
if seconds <= SECONDS_MAX:
|
if seconds <= SECONDS_MAX:
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
if line:
|
if line:
|
||||||
line.deleted = True
|
line.deleted = True
|
||||||
|
|
||||||
timestamp = utils.datetime.datetime_human(line.timestamp,
|
timestamp = utils.datetime.format.datetime_human(line.timestamp,
|
||||||
timespec=utils.datetime.TimeSpec.MILLISECOND)
|
timespec=utils.datetime.TimeSpec.MILLISECOND)
|
||||||
minimal = "{~NICK} deleted line from %s (%s)" % (
|
minimal = "{~NICK} deleted line from %s (%s)" % (
|
||||||
timestamp, line.message)
|
timestamp, line.message)
|
||||||
|
|
|
@ -16,7 +16,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
for i, message in enumerate(message_list):
|
for i, message in enumerate(message_list):
|
||||||
seconds = utils.datetime.seconds_since(message.line.timestamp)
|
seconds = utils.datetime.seconds_since(message.line.timestamp)
|
||||||
messages.append("(%d/%d) %s ago %s" % (i+1, message_count,
|
messages.append("(%d/%d) %s ago %s" % (i+1, message_count,
|
||||||
utils.datetime.to_pretty_time(seconds),
|
utils.datetime.format.to_pretty_time(seconds),
|
||||||
message.line.format()))
|
message.line.format()))
|
||||||
|
|
||||||
event["stdout"].write("%s: found: %s"
|
event["stdout"].write("%s: found: %s"
|
||||||
|
|
|
@ -35,8 +35,8 @@ class Module(ModuleManager.BaseModule):
|
||||||
seen_info = " (%s%s)" % (seen_info["action"],
|
seen_info = " (%s%s)" % (seen_info["action"],
|
||||||
utils.consts.RESET)
|
utils.consts.RESET)
|
||||||
|
|
||||||
since = utils.datetime.to_pretty_time(time.time()-seen_seconds,
|
since = utils.datetime.format.to_pretty_time(
|
||||||
max_units=2)
|
time.time()-seen_seconds, max_units=2)
|
||||||
event["stdout"].write("%s was last seen %s ago%s" % (
|
event["stdout"].write("%s was last seen %s ago%s" % (
|
||||||
event["args_split"][0], since, seen_info or ""))
|
event["args_split"][0], since, seen_info or ""))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -7,7 +7,7 @@ HIDDEN_MODES = set(["s", "p"])
|
||||||
|
|
||||||
class Module(ModuleManager.BaseModule):
|
class Module(ModuleManager.BaseModule):
|
||||||
def _uptime(self):
|
def _uptime(self):
|
||||||
return utils.datetime.to_pretty_time(
|
return utils.datetime.format.to_pretty_time(
|
||||||
int(time.time()-self.bot.start_time))
|
int(time.time()-self.bot.start_time))
|
||||||
|
|
||||||
@utils.hook("received.command.uptime")
|
@utils.hook("received.command.uptime")
|
||||||
|
|
|
@ -8,8 +8,9 @@ class Module(ModuleManager.BaseModule):
|
||||||
messages = event["channel"].get_user_setting(event["user"].get_id(),
|
messages = event["channel"].get_user_setting(event["user"].get_id(),
|
||||||
"to", [])
|
"to", [])
|
||||||
for nickname, message, timestamp in messages:
|
for nickname, message, timestamp in messages:
|
||||||
timestamp_parsed = utils.datetime.iso8601_parse(timestamp)
|
timestamp_parsed = utils.datetime.parse.iso8601(timestamp)
|
||||||
timestamp_human = utils.datetime.datetime_human(timestamp_parsed)
|
timestamp_human = utils.datetime.format.datetime_human(
|
||||||
|
timestamp_parsed)
|
||||||
event["channel"].send_message("%s: <%s> %s (at %s UTC)" % (
|
event["channel"].send_message("%s: <%s> %s (at %s UTC)" % (
|
||||||
event["user"].nickname, nickname, message, timestamp_human))
|
event["user"].nickname, nickname, message, timestamp_human))
|
||||||
if messages:
|
if messages:
|
||||||
|
@ -36,7 +37,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
|
|
||||||
messages.append([event["user"].nickname,
|
messages.append([event["user"].nickname,
|
||||||
" ".join(event["args_split"][1:]),
|
" ".join(event["args_split"][1:]),
|
||||||
utils.datetime.iso8601_format_now()])
|
utils.datetime.format.iso8601_now()])
|
||||||
event["target"].set_user_setting(target_user.get_id(),
|
event["target"].set_user_setting(target_user.get_id(),
|
||||||
"to", messages)
|
"to", messages)
|
||||||
event["stdout"].write("Message saved")
|
event["stdout"].write("Message saved")
|
||||||
|
|
|
@ -96,9 +96,9 @@ class Module(ModuleManager.BaseModule):
|
||||||
|
|
||||||
if first_details:
|
if first_details:
|
||||||
first_nickname, first_timestamp, _ = first_details
|
first_nickname, first_timestamp, _ = first_details
|
||||||
timestamp_parsed = utils.datetime.iso8601_parse(
|
timestamp_parsed = utils.datetime.parse.iso8601(
|
||||||
first_timestamp)
|
first_timestamp)
|
||||||
timestamp_human = utils.datetime.datetime_human(
|
timestamp_human = utils.datetime.format.datetime_human(
|
||||||
timestamp_parsed)
|
timestamp_parsed)
|
||||||
|
|
||||||
message = "%s (first posted by %s at %s)" % (title,
|
message = "%s (first posted by %s at %s)" % (title,
|
||||||
|
@ -106,7 +106,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
else:
|
else:
|
||||||
event["target"].set_setting(setting,
|
event["target"].set_setting(setting,
|
||||||
[event["user"].nickname,
|
[event["user"].nickname,
|
||||||
utils.datetime.iso8601_format_now(), url])
|
utils.datetime.format.iso8601_now(), url])
|
||||||
event["stdout"].write(message)
|
event["stdout"].write(message)
|
||||||
if code == -2:
|
if code == -2:
|
||||||
self.log.debug("Not showing title for %s, too similar", [url])
|
self.log.debug("Not showing title for %s, too similar", [url])
|
||||||
|
|
|
@ -3,7 +3,8 @@ from src import utils
|
||||||
|
|
||||||
def _timestamp(dt):
|
def _timestamp(dt):
|
||||||
seconds_since = time.time()-dt.timestamp()
|
seconds_since = time.time()-dt.timestamp()
|
||||||
timestamp = utils.datetime.to_pretty_time(seconds_since, max_units=2)
|
timestamp = utils.datetime.format.to_pretty_time(
|
||||||
|
seconds_since, max_units=2)
|
||||||
return "%s ago" % timestamp
|
return "%s ago" % timestamp
|
||||||
|
|
||||||
def _normalise(tweet):
|
def _normalise(tweet):
|
||||||
|
|
|
@ -52,7 +52,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
if utc_offset > 0:
|
if utc_offset > 0:
|
||||||
tz += "+"
|
tz += "+"
|
||||||
tz += "%g" % utc_offset
|
tz += "%g" % utc_offset
|
||||||
return "%s %s" % (utils.datetime.datetime_human(dt), tz)
|
return "%s %s" % (utils.datetime.format.datetime_human(dt), tz)
|
||||||
|
|
||||||
@utils.hook("received.command.time")
|
@utils.hook("received.command.time")
|
||||||
@utils.kwarg("help", "Get the time for you or someone else")
|
@utils.kwarg("help", "Get the time for you or someone else")
|
||||||
|
|
|
@ -81,8 +81,8 @@ class Module(ModuleManager.BaseModule):
|
||||||
since = ""
|
since = ""
|
||||||
first_words = target.get_setting("first-words", None)
|
first_words = target.get_setting("first-words", None)
|
||||||
if not first_words == None:
|
if not first_words == None:
|
||||||
since = " since %s" % utils.datetime.date_human(
|
since = " since %s" % utils.datetime.format.date_human(
|
||||||
utils.datetime.datetime_timestamp(first_words))
|
utils.datetime.timestamp(first_words))
|
||||||
|
|
||||||
event["stdout"].write("%s has used %d words (%d in %s)%s" % (
|
event["stdout"].write("%s has used %d words (%d in %s)%s" % (
|
||||||
target.nickname, total, this_channel, event["target"].name, since))
|
target.nickname, total, this_channel, event["target"].name, since))
|
||||||
|
|
|
@ -44,9 +44,10 @@ class Module(ModuleManager.BaseModule):
|
||||||
statistics = item["statistics"]
|
statistics = item["statistics"]
|
||||||
content = item["contentDetails"]
|
content = item["contentDetails"]
|
||||||
|
|
||||||
video_uploaded_at = utils.datetime.iso8601_parse(
|
video_uploaded_at = utils.datetime.parse.iso8601(
|
||||||
snippet["publishedAt"])
|
snippet["publishedAt"])
|
||||||
video_uploaded_at = utils.datetime.date_human(video_uploaded_at)
|
video_uploaded_at = utils.datetime.format.date_human(
|
||||||
|
video_uploaded_at)
|
||||||
|
|
||||||
video_uploader = snippet["channelTitle"]
|
video_uploader = snippet["channelTitle"]
|
||||||
video_title = utils.irc.bold(snippet["title"])
|
video_title = utils.irc.bold(snippet["title"])
|
||||||
|
|
|
@ -14,7 +14,7 @@ class LockFile(PollHook.PollHook):
|
||||||
with open(self._filename, "r") as lock_file:
|
with open(self._filename, "r") as lock_file:
|
||||||
timestamp_str = lock_file.read().strip().split(" ", 1)[0]
|
timestamp_str = lock_file.read().strip().split(" ", 1)[0]
|
||||||
|
|
||||||
timestamp = utils.datetime.iso8601_parse(timestamp_str)
|
timestamp = utils.datetime.parse.iso8601(timestamp_str)
|
||||||
|
|
||||||
if (now-timestamp).total_seconds() < EXPIRATION:
|
if (now-timestamp).total_seconds() < EXPIRATION:
|
||||||
return False
|
return False
|
||||||
|
@ -24,7 +24,7 @@ class LockFile(PollHook.PollHook):
|
||||||
def lock(self):
|
def lock(self):
|
||||||
with open(self._filename, "w") as lock_file:
|
with open(self._filename, "w") as lock_file:
|
||||||
last_lock = utils.datetime.utcnow()
|
last_lock = utils.datetime.utcnow()
|
||||||
lock_file.write("%s" % utils.datetime.iso8601_format(last_lock))
|
lock_file.write("%s" % utils.datetime.format.iso8601(last_lock))
|
||||||
self._next_lock = last_lock+datetime.timedelta(
|
self._next_lock = last_lock+datetime.timedelta(
|
||||||
seconds=EXPIRATION/2)
|
seconds=EXPIRATION/2)
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ LEVELS = {
|
||||||
class BitBotFormatter(logging.Formatter):
|
class BitBotFormatter(logging.Formatter):
|
||||||
def formatTime(self, record, datefmt=None):
|
def formatTime(self, record, datefmt=None):
|
||||||
datetime_obj = datetime.datetime.fromtimestamp(record.created)
|
datetime_obj = datetime.datetime.fromtimestamp(record.created)
|
||||||
return utils.datetime.iso8601_format(datetime_obj,
|
return utils.datetime.format.iso8601(datetime_obj,
|
||||||
timespec=utils.datetime.TimeSpec.MILLISECOND)
|
timespec=utils.datetime.TimeSpec.MILLISECOND)
|
||||||
|
|
||||||
class HookedHandler(logging.StreamHandler):
|
class HookedHandler(logging.StreamHandler):
|
||||||
|
|
|
@ -197,8 +197,8 @@ class Module(ModuleManager.BaseModule):
|
||||||
self._on_topic(event, event["setter"].nickname, "set",
|
self._on_topic(event, event["setter"].nickname, "set",
|
||||||
event["channel"].topic)
|
event["channel"].topic)
|
||||||
|
|
||||||
dt = utils.datetime.datetime_human(
|
dt = utils.datetime.format.datetime_human(
|
||||||
utils.datetime.datetime_timestamp(event["set_at"]))
|
utils.datetime.timestamp(event["set_at"]))
|
||||||
|
|
||||||
minimal = "topic set at %s" % dt
|
minimal = "topic set at %s" % dt
|
||||||
line = "- %s" % minimal
|
line = "- %s" % minimal
|
||||||
|
|
|
@ -21,5 +21,5 @@ class Module(ModuleManager.BaseModule):
|
||||||
def message(self, event):
|
def message(self, event):
|
||||||
server_time = self._get(event["line"].tags)
|
server_time = self._get(event["line"].tags)
|
||||||
if not server_time == None:
|
if not server_time == None:
|
||||||
dt = utils.datetime.iso8601_parse(server_time)
|
dt = utils.datetime.parse.iso8601(server_time)
|
||||||
event["buffer_line"].timestamp = dt
|
event["buffer_line"].timestamp = dt
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Module(ModuleManager.BaseModule):
|
||||||
def silence(self, event):
|
def silence(self, event):
|
||||||
duration = SILENCE_TIME
|
duration = SILENCE_TIME
|
||||||
if event["args"] and event["args_split"][0].startswith("+"):
|
if event["args"] and event["args_split"][0].startswith("+"):
|
||||||
duration = utils.datetime.from_pretty_time(
|
duration = utils.datetime.parse.from_pretty_time(
|
||||||
event["args_split"][0][1:])
|
event["args_split"][0][1:])
|
||||||
if duration == None:
|
if duration == None:
|
||||||
raise utils.EventError("Invalid duration provided")
|
raise utils.EventError("Invalid duration provided")
|
||||||
|
|
2
src/utils/datetime/__init__.py
Normal file
2
src/utils/datetime/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
from .common import *
|
||||||
|
from . import format, parse
|
42
src/utils/datetime/common.py
Normal file
42
src/utils/datetime/common.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import datetime as _datetime
|
||||||
|
import enum
|
||||||
|
|
||||||
|
ISO8601_FORMAT_DT = "%Y-%m-%dT%H:%M:%S"
|
||||||
|
ISO8601_FORMAT_TZ = "%z"
|
||||||
|
|
||||||
|
TIME_HUMAN = "%H:%M:%S"
|
||||||
|
DATE_HUMAN = "%Y-%m-%d"
|
||||||
|
|
||||||
|
class TimeSpec(enum.Enum):
|
||||||
|
NORMAL = 1
|
||||||
|
MILLISECOND = 2
|
||||||
|
|
||||||
|
TIME_SECOND = 1
|
||||||
|
TIME_MINUTE = TIME_SECOND*60
|
||||||
|
TIME_HOUR = TIME_MINUTE*60
|
||||||
|
TIME_DAY = TIME_HOUR*24
|
||||||
|
TIME_WEEK = TIME_DAY*7
|
||||||
|
|
||||||
|
SECONDS_MINUTES = 60
|
||||||
|
SECONDS_HOURS = SECONDS_MINUTES*60
|
||||||
|
SECONDS_DAYS = SECONDS_HOURS*24
|
||||||
|
SECONDS_WEEKS = SECONDS_DAYS*7
|
||||||
|
|
||||||
|
UNIT_MINIMUM = 6
|
||||||
|
UNIT_SECOND = 5
|
||||||
|
UNIT_MINUTE = 4
|
||||||
|
UNIT_HOUR = 3
|
||||||
|
UNIT_DAY = 2
|
||||||
|
UNIT_WEEK = 1
|
||||||
|
UNIT_MONTH = 1
|
||||||
|
UNIT_YEAR = 1
|
||||||
|
|
||||||
|
def utcnow() -> _datetime.datetime:
|
||||||
|
return _datetime.datetime.utcnow().replace(tzinfo=_datetime.timezone.utc)
|
||||||
|
|
||||||
|
def timestamp(seconds: float) -> _datetime.datetime:
|
||||||
|
return _datetime.datetime.fromtimestamp(seconds).replace(
|
||||||
|
tzinfo=_datetime.timezone.utc)
|
||||||
|
|
||||||
|
def seconds_since(dt: _datetime.datetime) -> float:
|
||||||
|
return (utcnow()-dt).total_seconds()
|
|
@ -1,24 +1,9 @@
|
||||||
import enum, re, typing
|
import typing
|
||||||
import datetime as _datetime
|
import datetime as _datetime
|
||||||
import dateutil.parser, dateutil.relativedelta
|
import dateutil.relativedelta
|
||||||
|
from .common import *
|
||||||
|
|
||||||
ISO8601_FORMAT_DT = "%Y-%m-%dT%H:%M:%S"
|
def iso8601(dt: _datetime.datetime, timespec: TimeSpec=TimeSpec.NORMAL
|
||||||
ISO8601_FORMAT_TZ = "%z"
|
|
||||||
|
|
||||||
TIME_HUMAN = "%H:%M:%S"
|
|
||||||
DATE_HUMAN = "%Y-%m-%d"
|
|
||||||
|
|
||||||
class TimeSpec(enum.Enum):
|
|
||||||
NORMAL = 1
|
|
||||||
MILLISECOND = 2
|
|
||||||
|
|
||||||
def utcnow() -> _datetime.datetime:
|
|
||||||
return _datetime.datetime.utcnow().replace(tzinfo=_datetime.timezone.utc)
|
|
||||||
def datetime_timestamp(seconds: float) -> _datetime.datetime:
|
|
||||||
return _datetime.datetime.fromtimestamp(seconds).replace(
|
|
||||||
tzinfo=_datetime.timezone.utc)
|
|
||||||
|
|
||||||
def iso8601_format(dt: _datetime.datetime, timespec: TimeSpec=TimeSpec.NORMAL
|
|
||||||
) -> str:
|
) -> str:
|
||||||
dt_format = dt.strftime(ISO8601_FORMAT_DT)
|
dt_format = dt.strftime(ISO8601_FORMAT_DT)
|
||||||
tz_format = dt.strftime(ISO8601_FORMAT_TZ)
|
tz_format = dt.strftime(ISO8601_FORMAT_TZ)
|
||||||
|
@ -29,10 +14,7 @@ def iso8601_format(dt: _datetime.datetime, timespec: TimeSpec=TimeSpec.NORMAL
|
||||||
|
|
||||||
return "%s%s%s" % (dt_format, ms_format, tz_format)
|
return "%s%s%s" % (dt_format, ms_format, tz_format)
|
||||||
def iso8601_format_now(timespec: TimeSpec=TimeSpec.NORMAL) -> str:
|
def iso8601_format_now(timespec: TimeSpec=TimeSpec.NORMAL) -> str:
|
||||||
return iso8601_format(utcnow(), timespec)
|
return iso8601(utcnow(), timespec)
|
||||||
|
|
||||||
def iso8601_parse(s: str) -> _datetime.datetime:
|
|
||||||
return dateutil.parser.parse(s)
|
|
||||||
|
|
||||||
def datetime_human(dt: _datetime.datetime, timespec: TimeSpec=TimeSpec.NORMAL):
|
def datetime_human(dt: _datetime.datetime, timespec: TimeSpec=TimeSpec.NORMAL):
|
||||||
date = _datetime.datetime.strftime(dt, DATE_HUMAN)
|
date = _datetime.datetime.strftime(dt, DATE_HUMAN)
|
||||||
|
@ -43,15 +25,6 @@ def datetime_human(dt: _datetime.datetime, timespec: TimeSpec=TimeSpec.NORMAL):
|
||||||
def date_human(dt: _datetime.datetime, timespec: TimeSpec=TimeSpec.NORMAL):
|
def date_human(dt: _datetime.datetime, timespec: TimeSpec=TimeSpec.NORMAL):
|
||||||
return _datetime.datetime.strftime(dt, DATE_HUMAN)
|
return _datetime.datetime.strftime(dt, DATE_HUMAN)
|
||||||
|
|
||||||
def seconds_since(dt: _datetime.datetime) -> float:
|
|
||||||
return (utcnow()-dt).total_seconds()
|
|
||||||
|
|
||||||
TIME_SECOND = 1
|
|
||||||
TIME_MINUTE = TIME_SECOND*60
|
|
||||||
TIME_HOUR = TIME_MINUTE*60
|
|
||||||
TIME_DAY = TIME_HOUR*24
|
|
||||||
TIME_WEEK = TIME_DAY*7
|
|
||||||
|
|
||||||
def time_unit(seconds: int) -> typing.Tuple[int, str]:
|
def time_unit(seconds: int) -> typing.Tuple[int, str]:
|
||||||
since = None
|
since = None
|
||||||
unit = None
|
unit = None
|
||||||
|
@ -75,37 +48,6 @@ def time_unit(seconds: int) -> typing.Tuple[int, str]:
|
||||||
unit = "%ss" % unit # pluralise the unit
|
unit = "%ss" % unit # pluralise the unit
|
||||||
return (since, unit)
|
return (since, unit)
|
||||||
|
|
||||||
REGEX_PRETTYTIME = re.compile(
|
|
||||||
r"(?:(\d+)w)?(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?", re.I)
|
|
||||||
|
|
||||||
SECONDS_MINUTES = 60
|
|
||||||
SECONDS_HOURS = SECONDS_MINUTES*60
|
|
||||||
SECONDS_DAYS = SECONDS_HOURS*24
|
|
||||||
SECONDS_WEEKS = SECONDS_DAYS*7
|
|
||||||
|
|
||||||
def from_pretty_time(pretty_time: str) -> typing.Optional[int]:
|
|
||||||
seconds = 0
|
|
||||||
|
|
||||||
match = re.match(REGEX_PRETTYTIME, pretty_time)
|
|
||||||
if match:
|
|
||||||
seconds += int(match.group(1) or 0)*SECONDS_WEEKS
|
|
||||||
seconds += int(match.group(2) or 0)*SECONDS_DAYS
|
|
||||||
seconds += int(match.group(3) or 0)*SECONDS_HOURS
|
|
||||||
seconds += int(match.group(4) or 0)*SECONDS_MINUTES
|
|
||||||
seconds += int(match.group(5) or 0)
|
|
||||||
|
|
||||||
if seconds > 0:
|
|
||||||
return seconds
|
|
||||||
return None
|
|
||||||
|
|
||||||
UNIT_MINIMUM = 6
|
|
||||||
UNIT_SECOND = 5
|
|
||||||
UNIT_MINUTE = 4
|
|
||||||
UNIT_HOUR = 3
|
|
||||||
UNIT_DAY = 2
|
|
||||||
UNIT_WEEK = 1
|
|
||||||
UNIT_MONTH = 1
|
|
||||||
UNIT_YEAR = 1
|
|
||||||
def to_pretty_time(total_seconds: int, minimum_unit: int=UNIT_SECOND,
|
def to_pretty_time(total_seconds: int, minimum_unit: int=UNIT_SECOND,
|
||||||
max_units: int=UNIT_MINIMUM) -> str:
|
max_units: int=UNIT_MINIMUM) -> str:
|
||||||
if total_seconds == 0:
|
if total_seconds == 0:
|
25
src/utils/datetime/parse.py
Normal file
25
src/utils/datetime/parse.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import re, typing
|
||||||
|
import datetime as _datetime
|
||||||
|
import dateutil.parser
|
||||||
|
from .common import *
|
||||||
|
|
||||||
|
def iso8601(s: str) -> _datetime.datetime:
|
||||||
|
return dateutil.parser.parse(s)
|
||||||
|
|
||||||
|
REGEX_PRETTYTIME = re.compile(
|
||||||
|
r"(?:(\d+)w)?(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?", re.I)
|
||||||
|
|
||||||
|
def from_pretty_time(pretty_time: str) -> typing.Optional[int]:
|
||||||
|
seconds = 0
|
||||||
|
|
||||||
|
match = re.match(REGEX_PRETTYTIME, pretty_time)
|
||||||
|
if match:
|
||||||
|
seconds += int(match.group(1) or 0)*SECONDS_WEEKS
|
||||||
|
seconds += int(match.group(2) or 0)*SECONDS_DAYS
|
||||||
|
seconds += int(match.group(3) or 0)*SECONDS_HOURS
|
||||||
|
seconds += int(match.group(4) or 0)*SECONDS_MINUTES
|
||||||
|
seconds += int(match.group(5) or 0)
|
||||||
|
|
||||||
|
if seconds > 0:
|
||||||
|
return seconds
|
||||||
|
return None
|
|
@ -2,7 +2,7 @@ from src.utils import datetime
|
||||||
|
|
||||||
def duration(s: str):
|
def duration(s: str):
|
||||||
if s[0] == "+":
|
if s[0] == "+":
|
||||||
duration = datetime.from_pretty_time(s[1:])
|
duration = datetime.parse.from_pretty_time(s[1:])
|
||||||
if not duration == None:
|
if not duration == None:
|
||||||
return duration
|
return duration
|
||||||
return None
|
return None
|
||||||
|
|
Loading…
Reference in a new issue