herolib_python/lib/data/ourtime/ourtime.py
2025-08-05 15:48:18 +02:00

123 lines
3.4 KiB
Python

from datetime import datetime, timedelta
import re
class OurTime:
def __init__(self, dt: datetime = None):
self._dt = dt if dt else datetime.min
def __str__(self) -> str:
return self.str()
def str(self) -> str:
if self._dt == datetime.min:
return ""
return self._dt.strftime('%Y-%m-%d %H:%M')
def day(self) -> str:
if self._dt == datetime.min:
return ""
return self._dt.strftime('%Y-%m-%d')
def key(self) -> str:
if self._dt == datetime.min:
return ""
return self._dt.strftime('%Y_%m_%d_%H_%M_%S')
def md(self) -> str:
if self._dt == datetime.min:
return ""
return self._dt.strftime('%Y-%m-%d %H:%M:%S')
def unix(self) -> int:
if self._dt == datetime.min:
return 0
return int(self._dt.timestamp())
def empty(self) -> bool:
return self._dt == datetime.min
def dayhour(self) -> str:
if self._dt == datetime.min:
return ""
return self._dt.strftime('%Y-%m-%d-%H')
def time(self):
# This is a simplified representation, as VLang's time() returns a time object.
# Here, we return self to allow chaining format_ss().
return self
def format_ss(self) -> str:
if self._dt == datetime.min:
return ""
return self._dt.strftime('%H:%M:%S')
def warp(self, expression: str):
if self._dt == datetime.min:
return
parts = expression.split()
for part in parts:
match = re.match(r'([+-]?\d+)([smhdwMQY])', part)
if not match:
continue
value = int(match.group(1))
unit = match.group(2)
if unit == 's':
self._dt += timedelta(seconds=value)
elif unit == 'm':
self._dt += timedelta(minutes=value)
elif unit == 'h':
self._dt += timedelta(hours=value)
elif unit == 'd':
self._dt += timedelta(days=value)
elif unit == 'w':
self._dt += timedelta(weeks=value)
elif unit == 'M':
# Approximate months, for more accuracy, a proper dateutil.relativedelta would be needed
self._dt += timedelta(days=value * 30)
elif unit == 'Q':
self._dt += timedelta(days=value * 90)
elif unit == 'Y':
self._dt += timedelta(days=value * 365)
def now() -> OurTime:
return OurTime(datetime.now())
def new(time_str: str) -> OurTime:
if not time_str:
return OurTime()
formats = [
'%Y-%m-%d %H:%M:%S',
'%Y-%m-%d %H:%M',
'%Y-%m-%d %H',
'%Y-%m-%d',
'%d-%m-%Y %H:%M:%S',
'%d-%m-%Y %H:%M',
'%d-%m-%Y %H',
'%d-%m-%Y',
'%H:%M:%S', # For time() and format_ss() usage
]
for fmt in formats:
try:
dt = datetime.strptime(time_str, fmt)
return OurTime(dt)
except ValueError:
pass
# Handle relative time expressions
try:
# Create a dummy OurTime object to use its warp method
temp_time = now()
temp_time.warp(time_str)
return temp_time
except Exception:
pass
raise ValueError(f"Could not parse time string: {time_str}")
def new_from_epoch(epoch: int) -> OurTime:
return OurTime(datetime.fromtimestamp(epoch))