from datetime import datetime import re def calculate_age(birth_date_str): """Calculate age from a birth date string (YYYY-MM-DD).""" if not birth_date_str: return None try: birth_date = datetime.fromisoformat(birth_date_str) today = datetime.utcnow() age = today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day)) return age except (ValueError, TypeError): return None def standardize_language(language): """Standardize language codes or text to a consistent format.""" if not language: return "en" language = language.lower().strip() language_map = { "english": "en", "french": "fr", "spanish": "es", "german": "de" } return language_map.get(language, re.sub(r'[^a-z]', '', language)[:2]) def escape_latex_special_chars(text): """Escape special characters for LaTeX compatibility.""" if not isinstance(text, str) or not text: return "" latex_special_chars = { '&': r'\&', '%': r'\%', '$': r'\$', '#': r'\#', '_': r'\_', '{': r'\{', '}': r'\}', '~': r'\textasciitilde{}', '^': r'\textasciicircum{}', '\\': r'\textbackslash{}' } return ''.join(latex_special_chars.get(c, c) for c in text) def hyphenate_long_strings(text, max_length=30): """Insert hyphens into long strings to prevent LaTeX table overflow.""" if not isinstance(text, str) or not text: return "" if len(text) <= max_length: return text # Insert a zero-width space (allowing LaTeX to break) every max_length characters result = [] for i in range(0, len(text), max_length): chunk = text[i:i + max_length] result.append(chunk) return r"\-".join(result) def format_timestamp(timestamp_str): """Format a timestamp string for display in LaTeX.""" if not timestamp_str: return "N/A" try: # Handle ISO format timestamps dt = datetime.fromisoformat(timestamp_str.replace('Z', '+00:00')) return dt.strftime("%Y-%m-%d %H:%M") except (ValueError, TypeError): return str(timestamp_str)