timedelta formatter

This commit is contained in:
Daniel Tsvetkov 2020-02-11 12:37:35 +01:00
parent abbba47bb5
commit ddd352865a

View File

@ -1,12 +1,13 @@
import json
import re
import sys
from datetime import datetime
from pygments import highlight, lexers, formatters
from tww import ISO_FORMAT, time_to_emoji
from tww import ISO_FORMAT, time_to_emoji, time_ago
from tww import resolve_timezone, dateparser_parse_dt, get_utcnow, get_s_since_epoch, get_ms_since_epoch, \
dt_tz_translation, DEFAULT_FORMAT, get_local_now, query_to_format_result
dt_tz_translation, get_local_now, query_to_format_result
r_generic = re.compile('(.*)', flags=re.IGNORECASE)
r_time_in_epoch_s_now = re.compile('(?:time since epoch|seconds since epoch)', flags=re.IGNORECASE)
@ -48,32 +49,28 @@ def handler_time_ms_now_utc() -> int:
return get_ms_since_epoch(get_utcnow())
def handler_time_diff(start_dt: str, end_dt: str) -> dict:
start, end = dateparser_parse_dt(start_dt), dateparser_parse_dt(end_dt)
return dict(start=start.strftime(DEFAULT_FORMAT),
end=end.strftime(DEFAULT_FORMAT),
diff=end - start)
def handler_time_diff(start_dt: datetime, end_dt: datetime) -> dict:
diff = end_dt - start_dt
return dict(start=dt_pretty(start_dt),
end=dt_pretty(end_dt),
diff=td_pretty(diff))
def handler_time_since(start_dt_s: str) -> dict:
return handler_time_diff(start_dt_s, str(get_utcnow()))
def handler_time_until(end_dt_s: str) -> dict:
return handler_time_diff(str(get_utcnow()), end_dt_s)
def handler_time_since_until(start_dt_s: str) -> dict:
return handler_time_diff(dateparser_parse_dt(start_dt_s), get_local_now())
def handler_timezone_translation(dt_s: str, timezone_like_s: str) -> dict:
dt = dateparser_parse_dt(dt_s)
src_dt = dateparser_parse_dt(dt_s)
tz = resolve_timezone(timezone_like_s)
if not tz:
tz, offset, the_time = '', '', dt
tz, dst_dt = {}, src_dt
else:
offset = tz.get('tz_offset')
translation = dt_tz_translation(dt, offset)
the_time = translation.strftime(DEFAULT_FORMAT)
return dict(dt=the_time,
offset=offset,
dst_dt = dt_tz_translation(src_dt, offset)
return dict(
src_dt=dt_pretty(src_dt),
dst_dt=dt_pretty(dst_dt),
tz=tz,
)
@ -109,8 +106,8 @@ regex_handlers = [
(r_time_in_epoch_ms2, handler_time_ms, QUERY_TYPE_DT),
(r_time_in_epoch_ms3, handler_time_ms, QUERY_TYPE_DT),
(r_timezone_translation, handler_timezone_translation, QUERY_TYPE_DT_TR),
(r_time_since, handler_time_since, QUERY_TYPE_TD),
(r_time_until, handler_time_until, QUERY_TYPE_TD),
(r_time_since, handler_time_since_until, QUERY_TYPE_TD),
(r_time_until, handler_time_since_until, QUERY_TYPE_TD),
(r_time_between, handler_time_diff, QUERY_TYPE_TD),
(r_time_in, handler_time_in_parser, QUERY_TYPE_DT),
(r_timezone, handler_timezone, QUERY_TYPE_TZ),
@ -140,7 +137,7 @@ def tokenize(s):
except Exception as e:
continue
if result is not None:
solutions.append((h.__name__, (result, ), t))
solutions.append((h.__name__, (result,), t))
return solutions
@ -197,6 +194,74 @@ def dt_pretty(dt):
return rv
def td_remainders(td):
# split seconds to larger units
seconds = td.total_seconds()
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
days, hours = divmod(hours, 24)
months, days = divmod(days, 30.42)
years, months = divmod(months, 12)
years, months, days, hours, minutes, seconds = map(int, (years, months, days, hours, minutes, seconds))
years, months, days, hours, minutes, seconds = map(abs, (years, months, days, hours, minutes, seconds))
return dict(
seconds=seconds,
minutes=minutes,
hours=hours,
days=days,
months=months,
years=years,
)
def td_totals(td):
seconds = td.total_seconds()
minutes = seconds // 60
hours = seconds // (60 * 60)
days = seconds // (24 * 60 * 60)
weeks = seconds // (7 * 24 * 60 * 60)
months = seconds // (30 * 24 * 60 * 60)
years = seconds // (365 * 24 * 60 * 60)
years, months, weeks, days, hours, minutes, seconds = map(abs, (years, months, weeks, days, hours, minutes, seconds))
return dict(
seconds=seconds,
minutes=minutes,
hours=hours,
days=days,
weeks=weeks,
months=months,
years=years,
)
def td_iso8601(td):
"""P[n]Y[n]M[n]DT[n]H[n]M[n]S"""
rem = td_remainders(td)
fmt = "P"
for short, timeframe in [("Y", "years"), ("M", "months"), ("D", "days")]:
if rem[timeframe]:
fmt += "{}{}".format(rem[timeframe], short)
hms = [("H", "hours"), ("M", "minutes"), ("S", "seconds")]
if any([rem[t[1]] for t in hms]):
fmt += "T"
for short, timeframe in hms:
if rem[timeframe]:
fmt += "{}{}".format(rem[timeframe], short)
return fmt
def td_pretty(td):
rv = {
"sign": '-' if td.days < 0 else '+',
"in_the": 'future' if td.days < 0 else 'past',
"time_ago": time_ago(td),
"duration_iso8601": td_iso8601(td),
"totals": td_totals(td),
"remainders": td_remainders(td),
}
return rv
def resolve_query_type(query):
solutions = tokenize(query)
if not solutions:
@ -230,7 +295,7 @@ def resolve_query(query):
if __name__ == "__main__":
query = "now in sofia"
# query = ' '.join(sys.argv[1:])
# query = "time since 27 January 1992"
query = ' '.join(sys.argv[1:])
result = resolve_query(query)
pretty_print_dict(result)