mirror of
				https://github.com/osmarks/autobotrobot
				synced 2025-11-04 01:23:04 +00:00 
			
		
		
		
	improve time parsing
- fix natural language style - metric prefix capability
This commit is contained in:
		
							
								
								
									
										42
									
								
								src/util.py
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								src/util.py
									
									
									
									
									
								
							@@ -13,26 +13,44 @@ config = toml.load(open("config.toml", "r"))
 | 
			
		||||
 | 
			
		||||
def timestamp(): return int(datetime.datetime.now(tz=datetime.timezone.utc).timestamp())
 | 
			
		||||
 | 
			
		||||
prefixes = {
 | 
			
		||||
    # big SI prefixes
 | 
			
		||||
    "Y": 24, "Z": 21, "E": 18, "P": 15, "T": 12, "G": 9, "M": 6, "k": 3, "h": 2, "da": 1,
 | 
			
		||||
    # small SI prefixes
 | 
			
		||||
    "d": -1, "c": -2, "m": -3, "µ": -6, "μ": -6, "u": -6, "n": -9, "p": -12, "f": -15, "a": -18, "z": -21, "y": -24,
 | 
			
		||||
    # highly dubiously useful unofficial prefixes
 | 
			
		||||
    "R": 27, "r": -27, "Q": 30, "q": -30, "X": 27, "x": -27, "W": 30, "w": -30
 | 
			
		||||
}
 | 
			
		||||
number = "(-?[0-9]+(?:\.[0-9]+)?)(" + "|".join(prefixes.keys()) + ")?"
 | 
			
		||||
 | 
			
		||||
# from here: https://github.com/Rapptz/RoboDanny/blob/18b92ae2f53927aedebc25fb5eca02c8f6d7a874/cogs/utils/time.py
 | 
			
		||||
short_timedelta_regex = re.compile("""
 | 
			
		||||
(?:(?P<years>[0-9]{1,12})(?:years?|y))?        # e.g. 2y
 | 
			
		||||
(?:(?P<months>[0-9]{1,12})(?:months?|mo))?     # e.g. 2months
 | 
			
		||||
(?:(?P<weeks>[0-9]{1,12})(?:weeks?|w))?        # e.g. 10w
 | 
			
		||||
(?:(?P<days>[0-9]{1,12})(?:days?|d))?          # e.g. 14d
 | 
			
		||||
(?:(?P<hours>[0-9]{1,12})(?:hours?|h))?        # e.g. 12h
 | 
			
		||||
(?:(?P<minutes>[0-9]{1,12})(?:minutes?|m))?    # e.g. 10m
 | 
			
		||||
(?:(?P<seconds>[0-9]{1,12})(?:seconds?|s))?    # e.g. 15s """, re.VERBOSE)
 | 
			
		||||
short_timedelta_regex = re.compile(f"""
 | 
			
		||||
(?:(?P<years>{number})(?:years?|y))?        # e.g. 2y
 | 
			
		||||
(?:(?P<months>{number})(?:months?|mo))?     # e.g. 2months
 | 
			
		||||
(?:(?P<weeks>{number})(?:weeks?|w))?        # e.g. 10w
 | 
			
		||||
(?:(?P<days>{number})(?:days?|d))?          # e.g. 14d
 | 
			
		||||
(?:(?P<hours>{number})(?:hours?|h))?        # e.g. 12h
 | 
			
		||||
(?:(?P<minutes>{number})(?:minutes?|m))?    # e.g. 10m
 | 
			
		||||
(?:(?P<seconds>{number})(?:seconds?|s))?    # e.g. 15s """, re.VERBOSE)
 | 
			
		||||
 | 
			
		||||
def parse_prefixed(s):
 | 
			
		||||
    match = re.match(number, s)
 | 
			
		||||
    if not match: raise ValueError("does not match metric-prefixed integer format - ensure prefix is valid")
 | 
			
		||||
    num = float(match.group(1))
 | 
			
		||||
    prefix = match.group(2)
 | 
			
		||||
    if prefix: num *= (10 ** prefixes[prefix])
 | 
			
		||||
    return num
 | 
			
		||||
 | 
			
		||||
def parse_short_timedelta(text):
 | 
			
		||||
    match = short_timedelta_regex.fullmatch(text)
 | 
			
		||||
    if match is None or not match.group(0): raise ValueError("parse failed")
 | 
			
		||||
    data = { k: int(v) for k, v in match.groupdict(default=0).items() }
 | 
			
		||||
    data = { k: parse_prefixed(v) if v else 0 for k, v in match.groupdict().items() }
 | 
			
		||||
    return datetime.datetime.now(tz=datetime.timezone.utc) + relativedelta(**data)
 | 
			
		||||
 | 
			
		||||
cal = parsedatetime.Calendar()
 | 
			
		||||
def parse_humantime(text):
 | 
			
		||||
    time_struct, parse_status = cal.nlp(text)
 | 
			
		||||
    if parse_status == 1: return datetime.datetime(*time_struct[:6])
 | 
			
		||||
    dt_tuple = cal.nlp(text)
 | 
			
		||||
    if dt_tuple: return dt_tuple[0][0]
 | 
			
		||||
    else: raise ValueError("parse failed")
 | 
			
		||||
 | 
			
		||||
def parse_time(text):
 | 
			
		||||
@@ -42,7 +60,7 @@ def parse_time(text):
 | 
			
		||||
    except: pass
 | 
			
		||||
    try: return parse_humantime(text)
 | 
			
		||||
    except: pass
 | 
			
		||||
    raise ValueError("could not parse time")
 | 
			
		||||
    raise ValueError("time matches no available format")
 | 
			
		||||
 | 
			
		||||
def format_time(dt):
 | 
			
		||||
    return dt.strftime("%H:%M:%S %d/%m/%Y")
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user