115 lines
3.1 KiB
Python
Executable File
115 lines
3.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
timer - Countdown and stopwatch
|
|
|
|
Simple timing utilities.
|
|
"""
|
|
|
|
import sys
|
|
import time
|
|
from datetime import datetime, timedelta
|
|
|
|
def countdown(seconds: int, message: str = None):
|
|
"""Run a countdown timer."""
|
|
print(f"\n⏱️ Countdown: {format_time(seconds)}")
|
|
if message:
|
|
print(f" {message}")
|
|
print()
|
|
|
|
try:
|
|
while seconds > 0:
|
|
print(f"\r {format_time(seconds)} ", end='', flush=True)
|
|
time.sleep(1)
|
|
seconds -= 1
|
|
|
|
print(f"\r ✅ Done! ")
|
|
print("\n🔔 Time's up!")
|
|
if message:
|
|
print(f" {message}")
|
|
print()
|
|
|
|
except KeyboardInterrupt:
|
|
print(f"\r ⏸️ Cancelled at {format_time(seconds)}")
|
|
|
|
def stopwatch():
|
|
"""Run a stopwatch."""
|
|
print("\n⏱️ Stopwatch")
|
|
print(" Press Ctrl+C to stop\n")
|
|
|
|
start = time.time()
|
|
|
|
try:
|
|
while True:
|
|
elapsed = time.time() - start
|
|
print(f"\r {format_time(int(elapsed))} ", end='', flush=True)
|
|
time.sleep(0.1)
|
|
|
|
except KeyboardInterrupt:
|
|
elapsed = time.time() - start
|
|
print(f"\r ⏹️ {format_time(int(elapsed))} total")
|
|
print()
|
|
|
|
def format_time(seconds: int) -> str:
|
|
"""Format seconds as HH:MM:SS or MM:SS."""
|
|
if seconds >= 3600:
|
|
h = seconds // 3600
|
|
m = (seconds % 3600) // 60
|
|
s = seconds % 60
|
|
return f"{h:02d}:{m:02d}:{s:02d}"
|
|
else:
|
|
m = seconds // 60
|
|
s = seconds % 60
|
|
return f"{m:02d}:{s:02d}"
|
|
|
|
def parse_time(time_str: str) -> int:
|
|
"""Parse time string to seconds."""
|
|
# Handle formats: 30, 1:30, 1:30:00, 30s, 5m, 1h
|
|
time_str = time_str.lower().strip()
|
|
|
|
if time_str.endswith('s'):
|
|
return int(time_str[:-1])
|
|
elif time_str.endswith('m'):
|
|
return int(time_str[:-1]) * 60
|
|
elif time_str.endswith('h'):
|
|
return int(time_str[:-1]) * 3600
|
|
elif ':' in time_str:
|
|
parts = time_str.split(':')
|
|
if len(parts) == 2:
|
|
return int(parts[0]) * 60 + int(parts[1])
|
|
elif len(parts) == 3:
|
|
return int(parts[0]) * 3600 + int(parts[1]) * 60 + int(parts[2])
|
|
else:
|
|
return int(time_str)
|
|
|
|
def main():
|
|
if len(sys.argv) < 2:
|
|
print("Usage:")
|
|
print(" timer <time> [message] - Countdown timer")
|
|
print(" timer stop - Stopwatch")
|
|
print("")
|
|
print("Time formats:")
|
|
print(" 30 - 30 seconds")
|
|
print(" 30s - 30 seconds")
|
|
print(" 5m - 5 minutes")
|
|
print(" 1h - 1 hour")
|
|
print(" 1:30 - 1 min 30 sec")
|
|
print(" 1:30:00 - 1 hour 30 min")
|
|
print("")
|
|
print("Examples:")
|
|
print(" timer 5m 'Break time'")
|
|
print(" timer 25m 'Pomodoro done'")
|
|
print(" timer stop")
|
|
return
|
|
|
|
cmd = sys.argv[1]
|
|
|
|
if cmd in ['stop', 'stopwatch', 'sw']:
|
|
stopwatch()
|
|
else:
|
|
seconds = parse_time(cmd)
|
|
message = ' '.join(sys.argv[2:]) if len(sys.argv) > 2 else None
|
|
countdown(seconds, message)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|