Extract datetime utils

This commit is contained in:
Ivan Habunek 2023-06-30 11:06:17 +02:00
parent 83b7f25678
commit 3df8e2722a
No known key found for this signature in database
GPG key ID: F5F0623FF5EBCB3D
6 changed files with 64 additions and 57 deletions

View file

@ -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):

View file

@ -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"])

View file

@ -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

View file

@ -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")

View file

@ -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
View 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"