#!/usr/bin/env python3.9 # -*- coding: utf-8 -*- """ JFinal TimeKit - Date and Time Utilities """ from datetime import datetime, date, time, timedelta from typing import Union import threading class TimeKit: """Date and time utility class""" _formatters = {} _sdf_cache = threading.local() @staticmethod def _get_sdf(pattern: str): """Get thread-local SimpleDateFormat equivalent""" if not hasattr(TimeKit._sdf_cache, 'formatters'): TimeKit._sdf_cache.formatters = {} if pattern not in TimeKit._sdf_cache.formatters: TimeKit._sdf_cache.formatters[pattern] = _SimpleDateFormat(pattern) return TimeKit._sdf_cache.formatters[pattern] @staticmethod def now(pattern: str = "yyyy-MM-dd HH:mm:ss") -> str: """Get current time as string""" return datetime.now().strftime(TimeKit._to_python_pattern(pattern)) @staticmethod def now_with_millisecond() -> str: """Get current time with millisecond precision""" return datetime.now().strftime("%Y%m%d%H%M%S%f")[:-3] @staticmethod def format(dt: Union[datetime, date], pattern: str = "yyyy-MM-dd HH:mm:ss") -> str: """Format datetime or date to string""" python_pattern = TimeKit._to_python_pattern(pattern) if isinstance(dt, datetime): return dt.strftime(python_pattern) elif isinstance(dt, date): return dt.strftime(TimeKit._to_python_pattern(pattern)) elif isinstance(dt, time): return dt.strftime(TimeKit._to_python_pattern(pattern)) else: raise ValueError(f"Unsupported type: {type(dt)}") @staticmethod def parse(date_string: str, pattern: str = "yyyy-MM-dd HH:mm:ss") -> datetime: """Parse string to datetime""" try: python_pattern = TimeKit._to_python_pattern(pattern) return datetime.strptime(date_string, python_pattern) except ValueError as e: raise RuntimeError(f"Error parsing date: {e}") @staticmethod def parse_date(date_string: str, pattern: str = "yyyy-MM-dd") -> date: """Parse string to date""" dt = TimeKit.parse(date_string, pattern) return dt.date() @staticmethod def parse_time(time_string: str, pattern: str = "HH:mm:ss") -> time: """Parse string to time""" dt = TimeKit.parse(f"1970-01-01 {time_string}", f"yyyy-MM-dd {pattern}") return dt.time() @staticmethod def to_datetime(dt: Union[datetime, date]) -> datetime: """Convert date to datetime""" if isinstance(dt, datetime): return dt elif isinstance(dt, date): return datetime.combine(dt, time.min) else: raise ValueError(f"Unsupported type: {type(dt)}") @staticmethod def to_date(dt: Union[datetime, date]) -> date: """Convert datetime to date""" if isinstance(dt, datetime): return dt.date() elif isinstance(dt, date): return dt else: raise ValueError(f"Unsupported type: {type(dt)}") @staticmethod def is_after(dt1: datetime, dt2: datetime) -> bool: """Check if dt1 is after dt2""" return dt1 > dt2 @staticmethod def is_before(dt1: datetime, dt2: datetime) -> bool: """Check if dt1 is before dt2""" return dt1 < dt2 @staticmethod def is_equal(dt1: datetime, dt2: datetime) -> bool: """Check if dt1 equals dt2""" return dt1 == dt2 @staticmethod def _to_python_pattern(java_pattern: str) -> str: """Convert Java date pattern to Python strftime pattern""" mapping = { 'yyyy': '%Y', 'yy': '%y', 'MM': '%m', 'dd': '%d', 'HH': '%H', 'mm': '%M', 'ss': '%S', 'SSS': '%f', } result = java_pattern for java_fmt, python_fmt in mapping.items(): result = result.replace(java_fmt, python_fmt) return result class _SimpleDateFormat: """Simple date format implementation (Java SimpleDateFormat equivalent)""" def __init__(self, pattern: str): self.pattern = pattern self.python_pattern = TimeKit._to_python_pattern(pattern) def format(self, dt: Union[datetime, date]) -> str: """Format datetime to string""" if isinstance(dt, datetime): return dt.strftime(self.python_pattern) elif isinstance(dt, date): return dt.strftime(self.python_pattern) else: raise ValueError(f"Unsupported type: {type(dt)}") def parse(self, date_string: str) -> datetime: """Parse string to datetime""" try: return datetime.strptime(date_string, self.python_pattern) except ValueError as e: raise RuntimeError(f"Error parsing date: {e}")