Extract datetime utils
This commit is contained in:
parent
83b7f25678
commit
3df8e2722a
6 changed files with 64 additions and 57 deletions
|
@ -11,8 +11,8 @@ from toot.exceptions import ApiError, ConsoleError
|
|||
from toot.output import (print_lists, print_out, print_instance, print_account, print_acct_list,
|
||||
print_search_results, print_status, print_timeline, print_notifications, print_tag_list,
|
||||
print_list_accounts, print_user_list)
|
||||
from toot.tui.utils import parse_datetime
|
||||
from toot.utils import args_get_instance, delete_tmp_status_file, editor_input, multiline_input, EOF_KEY
|
||||
from toot.utils.datetime import parse_datetime
|
||||
|
||||
|
||||
def get_timeline_generator(app, user, args):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from collections import namedtuple
|
||||
|
||||
from .utils import parse_datetime
|
||||
from toot.utils.datetime import parse_datetime
|
||||
|
||||
Author = namedtuple("Author", ["account", "display_name", "username"])
|
||||
|
||||
|
|
|
@ -3,7 +3,9 @@ import urwid
|
|||
from toot import api
|
||||
from toot.exceptions import ApiError
|
||||
from toot.utils import format_content
|
||||
from .utils import highlight_hashtags, parse_datetime
|
||||
from toot.utils.datetime import parse_datetime
|
||||
|
||||
from .utils import highlight_hashtags
|
||||
from .widgets import Button, CheckBox, RadioButton
|
||||
|
||||
|
||||
|
|
|
@ -5,14 +5,15 @@ import webbrowser
|
|||
|
||||
from typing import List, Optional
|
||||
|
||||
from toot.tui import app
|
||||
from toot.utils import format_content
|
||||
from toot.utils.datetime import parse_datetime, time_ago
|
||||
from toot.utils.language import language_name
|
||||
|
||||
from .entities import Status
|
||||
from .scroll import Scrollable, ScrollBar
|
||||
from .utils import highlight_hashtags, parse_datetime, highlight_keys
|
||||
from .utils import highlight_hashtags, highlight_keys
|
||||
from .widgets import SelectableText, SelectableColumns
|
||||
from toot.tui import app
|
||||
from toot.tui.utils import time_ago
|
||||
from toot.utils import format_content
|
||||
from toot.utils.language import language_name
|
||||
|
||||
logger = logging.getLogger("toot")
|
||||
|
||||
|
|
|
@ -1,62 +1,14 @@
|
|||
import base64
|
||||
import math
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
from typing import List
|
||||
import urwid
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from functools import reduce
|
||||
from html.parser import HTMLParser
|
||||
from typing import List
|
||||
|
||||
HASHTAG_PATTERN = re.compile(r'(?<!\w)(#\w+)\b')
|
||||
SECOND = 1
|
||||
MINUTE = SECOND * 60
|
||||
HOUR = MINUTE * 60
|
||||
DAY = HOUR * 24
|
||||
WEEK = DAY * 7
|
||||
|
||||
|
||||
def parse_datetime(value):
|
||||
"""Returns an aware datetime in local timezone"""
|
||||
|
||||
# In Python < 3.7, `%z` does not match `Z` offset
|
||||
# https://docs.python.org/3.7/library/datetime.html#strftime-and-strptime-behavior
|
||||
if value.endswith("Z"):
|
||||
dttm = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%fZ").replace(tzinfo=timezone.utc)
|
||||
else:
|
||||
dttm = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f%z")
|
||||
|
||||
# When running tests return datetime in UTC so that tests don't depend on
|
||||
# the local timezone
|
||||
if "PYTEST_CURRENT_TEST" in os.environ:
|
||||
return dttm.astimezone(timezone.utc)
|
||||
|
||||
return dttm.astimezone()
|
||||
|
||||
|
||||
def time_ago(value: datetime) -> str:
|
||||
now = datetime.now().astimezone()
|
||||
delta = now.timestamp() - value.timestamp()
|
||||
|
||||
if delta < 1:
|
||||
return "now"
|
||||
|
||||
if delta < 8 * DAY:
|
||||
if delta < MINUTE:
|
||||
return f"{math.floor(delta / SECOND)}".rjust(2, " ") + "s"
|
||||
if delta < HOUR:
|
||||
return f"{math.floor(delta / MINUTE)}".rjust(2, " ") + "m"
|
||||
if delta < DAY:
|
||||
return f"{math.floor(delta / HOUR)}".rjust(2, " ") + "h"
|
||||
return f"{math.floor(delta / DAY)}".rjust(2, " ") + "d"
|
||||
|
||||
if delta < 53 * WEEK: # not exactly correct but good enough as a boundary
|
||||
return f"{math.floor(delta / WEEK)}".rjust(2, " ") + "w"
|
||||
|
||||
return ">1y"
|
||||
|
||||
|
||||
def highlight_keys(text, high_attr, low_attr=""):
|
||||
|
|
52
toot/utils/datetime.py
Normal file
52
toot/utils/datetime.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
import math
|
||||
import os
|
||||
import re
|
||||
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
def parse_datetime(value):
|
||||
"""Returns an aware datetime in local timezone"""
|
||||
|
||||
# In Python < 3.7, `%z` does not match `Z` offset
|
||||
# https://docs.python.org/3.7/library/datetime.html#strftime-and-strptime-behavior
|
||||
if value.endswith("Z"):
|
||||
dttm = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%fZ").replace(tzinfo=timezone.utc)
|
||||
else:
|
||||
dttm = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f%z")
|
||||
|
||||
# When running tests return datetime in UTC so that tests don't depend on
|
||||
# the local timezone
|
||||
if "PYTEST_CURRENT_TEST" in os.environ:
|
||||
return dttm.astimezone(timezone.utc)
|
||||
|
||||
return dttm.astimezone()
|
||||
|
||||
|
||||
SECOND = 1
|
||||
MINUTE = SECOND * 60
|
||||
HOUR = MINUTE * 60
|
||||
DAY = HOUR * 24
|
||||
WEEK = DAY * 7
|
||||
|
||||
|
||||
def time_ago(value: datetime) -> str:
|
||||
now = datetime.now().astimezone()
|
||||
delta = now.timestamp() - value.timestamp()
|
||||
|
||||
if delta < 1:
|
||||
return "now"
|
||||
|
||||
if delta < 8 * DAY:
|
||||
if delta < MINUTE:
|
||||
return f"{math.floor(delta / SECOND)}".rjust(2, " ") + "s"
|
||||
if delta < HOUR:
|
||||
return f"{math.floor(delta / MINUTE)}".rjust(2, " ") + "m"
|
||||
if delta < DAY:
|
||||
return f"{math.floor(delta / HOUR)}".rjust(2, " ") + "h"
|
||||
return f"{math.floor(delta / DAY)}".rjust(2, " ") + "d"
|
||||
|
||||
if delta < 53 * WEEK: # not exactly correct but good enough as a boundary
|
||||
return f"{math.floor(delta / WEEK)}".rjust(2, " ") + "w"
|
||||
|
||||
return ">1y"
|
Loading…
Reference in a new issue