from typing import Optional, List, Dict, Any from datetime import datetime, date, timedelta import json def parse_date_string(date_str: Optional[str], default: Optional[date] = None) -> Optional[date]: """Parse date string to date object""" if not date_str: return default try: return date.fromisoformat(date_str) except ValueError: return default def parse_datetime_string(datetime_str: Optional[str], default: Optional[datetime] = None) -> Optional[datetime]: """Parse datetime string to datetime object""" if not datetime_str: return default try: return datetime.fromisoformat(datetime_str.replace('Z', '+00:00')) except ValueError: return default def get_date_range(days: int = 14) -> tuple[date, date]: """Get date range for last N days""" end_date = date.today() start_date = end_date - timedelta(days=days) return start_date, end_date def calculate_percentage(part: float, whole: float, decimals: int = 2) -> float: """Calculate percentage safely""" if whole == 0: return 0.0 return round((part / whole) * 100, decimals) def safe_divide(numerator: float, denominator: float, default: float = 0.0) -> float: """Divide safely, returning default if denominator is 0""" if denominator == 0: return default return numerator / denominator def format_hours(seconds: int) -> float: """Convert seconds to hours""" if not seconds: return 0.0 return round(seconds / 3600, 2) def format_days(hours: float) -> float: """Convert hours to days (8-hour workday)""" if not hours: return 0.0 return round(hours / 8, 2) def extract_unique_values(items: List[Dict[str, Any]], key: str) -> List[Any]: """Extract unique values from list of dictionaries""" return list(set([item.get(key) for item in items if item.get(key)])) def group_by_key(items: List[Dict[str, Any]], key: str) -> Dict[Any, List[Dict[str, Any]]]: """Group list of dictionaries by a specific key""" groups = {} for item in items: key_value = item.get(key) if key_value: if key_value not in groups: groups[key_value] = [] groups[key_value].append(item) return groups def serialize_datetime(obj): """JSON serializer for datetime objects""" if isinstance(obj, (datetime, date)): return obj.isoformat() raise TypeError(f"Type {type(obj)} not serializable") def to_json(data: Any) -> str: """Convert data to JSON string with datetime support""" return json.dumps(data, default=serialize_datetime, indent=2) class PerformanceTimer: """Simple performance timer context manager""" def __init__(self, name: str = "Operation"): self.name = name self.start_time = None self.end_time = None def __enter__(self): self.start_time = datetime.now() return self def __exit__(self, exc_type, exc_val, exc_tb): self.end_time = datetime.now() duration = (self.end_time - self.start_time).total_seconds() print(f"{self.name} took {duration:.2f} seconds") @property def duration(self) -> float: """Get duration in seconds""" if self.start_time and self.end_time: return (self.end_time - self.start_time).total_seconds() return 0.0