git/aika/main
py/neralie.py
98 lines3 KB last change raw · history
#!/usr/bin/env python3

import sys
import time
import argparse
import re
from datetime import datetime

def to_neralie(h, m, s, ms=0):
    total_ms = (h * 3600 + m * 60 + s) * 1000 + ms
    nera = (total_ms * 5) // 432
    return f"{nera // 1000:03d}:{nera % 1000:03d}"

def count_mode():
    sys.stdout.write("\033[?25l")
    try:
        while True:
            now = datetime.now()
            ms = now.microsecond // 1000
            sys.stdout.write(f"\r{to_neralie(now.hour, now.minute, now.second, ms)}")
            sys.stdout.flush()
            time.sleep(0.0864)
    except KeyboardInterrupt:
        pass
    finally:
        sys.stdout.write("\033[?25h\n")
        sys.stdout.flush()

def parse_time(time_str):
    clean = re.sub(r'\s+', '', time_str)
    h, m, s = 0, 0, 0
    
    if ':' in clean:
        parts = clean.split(':')
        try:
            h = int(parts[0])
            if len(parts) > 1: m = int(parts[1])
            if len(parts) > 2: s = int(parts[2])
        except (ValueError, IndexError):
            sys.stderr.write("Error: Invalid time format.\n")
            sys.exit(1)
    else:
        try:
            length = len(clean)
            if length == 6:   h, m, s = int(clean[0:2]), int(clean[2:4]), int(clean[4:6])
            elif length == 5: h, m, s = int(clean[0:1]), int(clean[1:3]), int(clean[3:5])
            elif length == 4: h, m = int(clean[0:2]), int(clean[2:4])
            elif length == 3: h, m = int(clean[0:1]), int(clean[1:3])
            elif length == 2: h = int(clean)
            elif length == 1: h = int(clean)
            else: raise ValueError
        except ValueError:
            sys.stderr.write("Error: Invalid time format. Use HH:MM[:SS] or HHMM[SS].\n")
            sys.exit(1)

    if not (0 <= h <= 23 and 0 <= m <= 59 and 0 <= s <= 59):
        sys.stderr.write("Error: Invalid time values (Expected 00-23 for hours, 00-59 for min/sec).\n")
        sys.exit(1)

    return h, m, s

def main():
    parser = argparse.ArgumentParser(
        description="Convert standard time to Neralie, or run a continuous clock.",
        epilog="Examples:\n"
               "  %(prog)s             # Print current Neralie time\n"
               "  %(prog)s -c          # Run live Neralie clock\n"
               "  %(prog)s 14:30       # Convert 14:30:00 to Neralie\n"
               "  %(prog)s 143000      # Convert 14:30:00 to Neralie",
        formatter_class=argparse.RawDescriptionHelpFormatter
    )

    parser.add_argument("-v", "--version", action="version", version="Neralie 1.0.0")
    
    parser.add_argument("-c", "--count", action="store_true", help="run in continuous count mode")
    parser.add_argument(
        "time", 
        metavar="TIME", 
        nargs="?", 
        help="convert a specific time (formats: HH:MM:SS, HHMMSS, HH:MM, HHMM, HH)\n"
             "If omitted, prints the current local time."
    )

    args = parser.parse_args()

    if args.count:
        count_mode()
    elif args.time:
        h, m, s = parse_time(args.time)
        print(to_neralie(h, m, s))
    else:
        now = datetime.now()
        ms = now.microsecond // 1000
        print(to_neralie(now.hour, now.minute, now.second, ms))

if __name__ == "__main__":
    main()