#!/usr/bin/env python3 from __future__ import print_function import string import datetime class Time: def __init__(self, secs, mins=0, hours=0, days=0): self.secs = secs self.mins = secs // 60 + mins self.secs %= 60 self.hours = self.mins // 60 + hours self.mins %= 60 self.days = self.hours // 24 + days self.hours %= 24 def epoch(self): return self.secs + (self.mins + (self.hours + self.days * 24) * 60) * 60 def __str__(self): s = "%02i:%02i" % (self.mins, self.secs) if self.hours > 0: s = "%02i:%s" % (self.hours, s) if self.days > 0: s = "%id %s" % (self.days, s) return s def __isub__(self, n): if isinstance(n, Time): self.secs -= n.secs self.mins -= n.mins self.hours -= n.hours self.days -= n.days else: self.secs -= n while self.secs < 0: self.secs += 60 self.mins -= 1 while self.mins < 0: self.mins += 60 self.hours -= 1 while self.hours < 0: self.hours += 24 self.days -= 1 def dec(self): if self.secs > 0: self.secs -= 1 else: self.secs += 59 if self.mins > 0: self.mins -= 1 else: self.mins += 59 if self.hours > 0: self.hours -= 1 else: self.hours += 23 self.days -= 1 def positive(self): return self.secs > 0 or self.mins > 0 or self.hours > 0 or self.days > 0 @staticmethod def parse(s): secs = 0 this = "" for c in s: if c in string.digits: this += c elif c in string.whitespace: continue else: it = int(this) if c == "d": it *= 24 if c in "dh": it *= 60 if c in "dhm": it *= 60 if c in "dhms": secs += it else: raise ValueError("Unknown time unit: %s, Valid: _d_ays, _h_ours, _m_inutes, _s_econds. s at the end can be omitted." % c) this = "" if this: secs += int(this) return secs @classmethod def until(cls, time): error = ValueError("--until format: :[:][+]") parts = time.rsplit("+", 1) if len(parts) > 2: raise error elif len(parts) < 2: time, dayoffset = parts[0], 0 else: time, dayoffset = parts[0], int(parts[1]) parts = time.split(":") if len(parts) < 2 or len(parts) > 3: raise error else: date = datetime.date.today() + datetime.timedelta(days=dayoffset) time = datetime.time(*map(int, parts)) comp = datetime.datetime.combine(date, time) diff = comp - datetime.datetime.now() return diff.total_seconds() import argparse import os import time import shlex def main(argv): parser = argparse.ArgumentParser(prog=argv[0], usage="Sleep with visual feedback, Time arguments will get summed") parser.add_argument("time", help="Time to sleep in seconds, or with units (d,h,m,s)", nargs="?", default=0) parser.add_argument("--mins", "--minutes", help="Time to sleep in minutes", default=0, type=int) parser.add_argument("--hours", help="Time to sleep in hours", default=0, type=int) parser.add_argument("--days", help="Time to sleep in days", default=0, type=int) parser.add_argument("--until", help="Sleep until: ':[:][+]'.") parser.add_argument("--exec", help="Execute command", dest="exec_") args = parser.parse_args(argv[1:]) if (args.time == args.mins == args.hours == args.days == 0 and args.until is None): raise SystemExit("You need to specify at least one time argument! (Try --help)") if args.until is not None: secs = Time.until(args.until) else: secs = 0 if args.time != 0: secs += Time.parse(args.time) visualsleep(Time(secs, args.mins, args.hours, args.days)) if args.exec_: argv = shlex.split(args.exec_) print("Executing: %s" % args.exec_) os.execvp(argv[0], argv) def visualsleep(t): copyoft = Time(t.epoch()) while t.positive(): print("Sleep %10s" % t, end="\r") time.sleep(1) t.dec() print("Slept %10s" % copyoft) if __name__ == "__main__": import sys main(sys.argv)