#!/bin/env python3 import datetime from tkinter import Tk, CENTER, Label import click import typing as t import os DELTASECONDS = "+%Ss" DELTAMINUTES = "+%Mm" DELTAHOURS = "+%Hh" HOURS = "%H:%M" DATETIME_FORMAT = [ "%Y-%m-%d", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M", HOURS, DELTAHOURS, DELTAMINUTES, DELTASECONDS, ] class DateTime(click.DateTime): def _try_to_convert_date(self, value: t.Any, format: str) -> t.Optional[datetime]: try: if value[0] == "+": if format == DELTASECONDS and value[-1] == "s": return datetime.datetime.now() + datetime.timedelta( seconds=int(value[1:-1]) ) if format == DELTAMINUTES and value[-1] == "m": return datetime.datetime.now() + datetime.timedelta( minutes=int(value[1:-1]) ) if format == DELTAHOURS and value[-1] == "h": return datetime.datetime.now() + datetime.timedelta( hours=int(value[1:-1]) ) if format == HOURS: return datetime.datetime.combine( datetime.datetime.now().date(), datetime.datetime.strptime(value, format).time(), ) return datetime.datetime.strptime(value, format) except ValueError: return None def start_app(enddate): root = Tk() root.geometry("300x100+200+200") root.configure(background="#000") tlbl = Label(root, text="", font=("Arial", -100), fg="#fff", bg="#000") tlbl.pack() tlbl.place(relx=0.5, rely=0.5, anchor=CENTER) def deltaStr(t): days, remainder = divmod(t.total_seconds(), 60 * 60 * 24) hours, remainder = divmod(remainder, 3600) minutes, seconds = divmod(remainder, 60) if days == 0: if hours == 0: if minutes == 0: return f"{int(seconds):02d}" return f"{int(minutes):02d}:{int(seconds):02d}" return f"{int(hours):02d}:{int(minutes):02d}:{int(seconds):02d}" return f"{int(days):02d}:{int(hours):02d}:{int(minutes):02d}:{int(seconds):02d}" def resize(_): ratio = root.winfo_width() / 1920 tlbl.configure(font=("Chicago", int(ratio * -200))) def update(): delta = enddate - datetime.datetime.now() if delta.total_seconds() < 0: tlbl.configure(text="Now") tlbl.config(fg="red") else: tlbl.configure(text=deltaStr(delta)) root.after(1000 - datetime.datetime.now().microsecond // 1000, update) root.bind("", resize) root.bind("", lambda x: root.destroy()) root.after(1, update) if os.environ.get("XDG_CURRENT_DESKTOP", "") == "i3": root.wm_attributes("-type", "splash") root.mainloop() @click.command() @click.argument("enddate", type=DateTime(formats=DATETIME_FORMAT)) def main(enddate): start_app(enddate) if __name__ == "__main__": main()