#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @XZGUtil    : 2020-12-23 21:28
# @File    : timeUtil.py
"""
时间工具模块，提供了一系列函数用于处理时间和日期。
提供两种调用方式：完整函数名和快捷别名。
"""
import datetime
import time
from typing import Optional, List, Dict, Tuple, Union, Callable, Any
from functools import wraps
from dateutil.relativedelta import relativedelta
from retrying import retry
import requests


# ==================== 时间戳相关 ====================

def time_stamp(many: int = 13) -> str:
    """返回指定位数的时间戳（字符串形式）。"""
    ts_int = int(time.time() * 1000)
    return str(ts_int)[:many]


def format_nowtime_millisecond() -> int:
    """获取当前毫秒级时间戳。"""
    return int(round(time.time() * 1000))


# ==================== 格式化相关 ====================

def _datetime_to_str(dt: datetime.datetime, fmt: str) -> str:
    """内部通用方法：将 datetime 对象格式化为字符串。"""
    return dt.strftime(fmt)


def datetime_toStr(dt: datetime.datetime, fm: str = "%Y-%m-%d") -> str:
    """将 datetime 对象格式化为 '年-月-日' 字符串。"""
    return _datetime_to_str(dt, fm)


def datetime_toStr_dil(dt: datetime.datetime, fm: str = "%Y-%m-%d %H:%M:%S") -> str:
    """将 datetime 对象格式化为 '年-月-日 时:分:秒' 字符串。"""
    return _datetime_to_str(dt, fm)


def datetime_toChinStr(dt: datetime.datetime, fm: str = "%Y年%m月%d日") -> str:
    """将 datetime 对象格式化为中文 '年月日' 字符串。"""
    return _datetime_to_str(dt, fm)


def datetime_toChinStr_dil(dt: datetime.datetime, fm: str = "%Y年%m月%d日 %H时%M分%S秒") -> str:
    """将 datetime 对象格式化为详细的中文 '年月日 时分秒' 字符串。"""
    return _datetime_to_str(dt, fm)


def datetime_toCustStr(dt: datetime.datetime, fmat: str) -> str:
    """将 datetime 对象格式化为自定义格式的字符串。"""
    return _datetime_to_str(dt, fmat)


def get_now_date(fm: str = "%Y-%m-%d") -> str:
    """获取当前日期的字符串表示。"""
    return _datetime_to_str(datetime.datetime.now(), fm)


def get_now_time(fm: str = "%Y-%m-%d %H:%M:%S") -> str:
    """获取当前时间的字符串表示。"""
    return _datetime_to_str(datetime.datetime.now(), fm)


# ==================== 解析相关 ====================

def parse_datetime(date_string: str) -> Optional[datetime.datetime]:
    """
    尝试使用多种常见格式将字符串解析为 datetime 对象。
    支持格式：%Y-%m-%d, %Y/%m/%d, %Y-%m-%d %H:%M:%S, %Y年%m月%d日 等
    """
    formats = [
        '%Y-%m-%d',
        '%Y/%m/%d',
        '%Y%m%d',
        '%Y-%m-%d %H:%M:%S',
        '%Y-%m-%d %H:%M',
        '%Y/%m/%d %H:%M:%S',
        '%Y年%m月%d日',
        '%Y年%m月%d日 %H时%M分%S秒',
        '%Y.%m.%d',
        '%d/%m/%Y',
        '%d-%m-%Y',
    ]

    for fmt in formats:
        try:
            return datetime.datetime.strptime(date_string, fmt)
        except ValueError:
            continue
    return None


def _str_to_datetime(date_str: str, fmt: str) -> Optional[datetime.datetime]:
    """内部通用方法：将字符串按照指定格式解析为 datetime 对象。"""
    try:
        return datetime.datetime.strptime(date_str, fmt)
    except ValueError:
        return None


def str_toDatetime(date_str: str, fm: str = "%Y-%m-%d") -> Optional[datetime.datetime]:
    """将 '年-月-日' 格式的字符串转换为 datetime 对象。"""
    return _str_to_datetime(date_str, fm)


def dil_str_toDatetime(date_str: str, fm: str = "%Y-%m-%d %H:%M:%S") -> Optional[datetime.datetime]:
    """将 '年-月-日 时:分:秒' 格式的字符串转换为 datetime 对象。"""
    return _str_to_datetime(date_str, fm)


# ==================== 时间戳转换 ====================

def str_toTimestamp(str_time: str) -> Optional[int]:
    """将 '年-月-日' 格式的字符串转换为秒级时间戳。"""
    dt = str_toDatetime(str_time)
    return int(time.mktime(dt.timetuple())) if dt else None


def _timestamp_to_str(stamp: int, fmt: str) -> str:
    """内部通用方法：将时间戳转换为指定格式的字符串。"""
    return time.strftime(fmt, time.localtime(stamp))


def timestamp_tostr(stamp: int, fm: str = "%Y-%m-%d") -> str:
    """将秒级时间戳转换为 '年-月-日' 字符串。"""
    return _timestamp_to_str(stamp, fm)


def ts_toStr_det(stamp: int, fm: str = "%Y-%m-%d %H:%M:%S") -> str:
    """将秒级时间戳转换为 '年-月-日 时:分:秒' 字符串。"""
    return _timestamp_to_str(stamp, fm)


def datetime_toTimestamp(date_time: datetime.datetime) -> int:
    """将 datetime 对象转换为秒级时间戳。"""
    return int(time.mktime(date_time.timetuple()))


# ==================== 兼容性方法 ====================
# 保持原有方法名，内部调用新方法

def str_totime_dil(str_p: str, fm: str = "%Y-%m-%d %H:%M:%S") -> Optional[datetime.datetime]:
    """已弃用，请使用 dil_str_toDatetime。"""
    return dil_str_toDatetime(str_p, fm)


def str_totime(str_p: str, fm: str = "%Y-%m-%d") -> Optional[datetime.datetime]:
    """已弃用，请使用 str_toDatetime。"""
    return str_toDatetime(str_p, fm)


# ==================== 时间计算 ====================

def substract_Time_dil(date_str1: str, date_str2: str) -> Optional[Dict[str, float]]:
    """计算两个 '年-月-日 时:分:秒' 格式字符串之间的时间差。"""
    d1 = dil_str_toDatetime(date_str1)
    d2 = dil_str_toDatetime(date_str2)
    if d1 and d2:
        diff = d2 - d1
        return {
            'days': diff.days,
            'hours': diff.total_seconds() / 3600,
            'minutes': diff.total_seconds() / 60,
            'seconds': diff.total_seconds(),
            'total_seconds': diff.total_seconds(),
            'total_days': diff.total_seconds() / 86400
        }
    return None


def substract_DateTime(date_str1: str, date_str2: str) -> Optional[datetime.timedelta]:
    """计算两个 '年-月-日' 格式字符串之间的时间差。"""
    d1 = str_toDatetime(date_str1)
    d2 = str_toDatetime(date_str2)
    return d2 - d1 if d1 and d2 else None


def substract_TimeStamp(date_str1: str, date_str2: str) -> Optional[int]:
    """计算两个日期字符串时间戳的差值（秒）。"""
    ts1 = str_toTimestamp(date_str1)
    ts2 = str_toTimestamp(date_str2)
    return ts1 - ts2 if ts1 is not None and ts2 is not None else None


def compare_dateTime(date_str1: str, date_str2: str) -> Optional[bool]:
    """比较两个 '年-月-日' 格式的日期字符串。"""
    d1 = str_toDatetime(date_str1)
    d2 = str_toDatetime(date_str2)
    if d1 and d2:
        return d1.date() > d2.date()
    return None


def dateTime_Add(date_str: str, days: int = 0, hours: int = 0, minutes: int = 0,
                 seconds: int = 0, weeks: int = 0) -> Optional[datetime.datetime]:
    """在指定日期上增加一段时间。"""
    d = dil_str_toDatetime(date_str)
    if d:
        return d + datetime.timedelta(days=days, hours=hours,
                                      minutes=minutes, seconds=seconds, weeks=weeks)
    return None


def date_time_subtraction(date_str: str, days: int = 0, hours: int = 0,
                          minutes: int = 0, seconds: int = 0, weeks: int = 0) -> Optional[datetime.datetime]:
    """从指定日期上减去一段时间。"""
    d = dil_str_toDatetime(date_str)
    if d:
        return d - datetime.timedelta(days=days, hours=hours,
                                      minutes=minutes, seconds=seconds, weeks=weeks)
    return None


# ==================== 月份相关 ====================

def month_get(date: datetime.datetime) -> tuple[datetime.datetime, datetime.datetime]:
    """返回指定日期上个月的第一天和最后一天。"""
    first_day_of_current_month = date.replace(day=1)
    last_day_of_previous_month = first_day_of_current_month - datetime.timedelta(days=1)
    first_day_of_previous_month = last_day_of_previous_month.replace(day=1)

    date_from = datetime.datetime.combine(first_day_of_previous_month, datetime.time.min)
    date_to = datetime.datetime.combine(last_day_of_previous_month, datetime.time.max)

    return date_from, date_to


def get_month_b_e_day(month: str = '202001') -> tuple[str, str]:
    """传入 'YYYYMM' 格式的月份，返回该月的第一天和最后一天。"""
    try:
        year = int(month[:4])
        mon = int(month[4:])
        first_day = datetime.date(year, mon, 1)
        next_month = first_day + relativedelta(months=1)
        last_day = next_month - datetime.timedelta(days=1)
        return first_day.strftime("%Y-%m-%d"), last_day.strftime("%Y-%m-%d")
    except (ValueError, IndexError):
        return '', ''


# ==================== 日期范围 ====================

def getBetweenDay(begin_date: str, end_date: str) -> List[str]:
    """获取两个日期之间的所有日期列表。"""
    date_list = []
    try:
        begin_dt = str_toDatetime(begin_date)
        end_dt = str_toDatetime(end_date)
    except ValueError:
        # 如果无法解析，尝试去掉时间部分
        begin_dt = str_toDatetime(begin_date.split(' ')[0])
        end_dt = str_toDatetime(end_date.split(' ')[0])

    if not begin_dt or not end_dt:
        return []

    current_dt = begin_dt
    while current_dt <= end_dt:
        date_list.append(current_dt.strftime("%Y-%m-%d"))
        current_dt += datetime.timedelta(days=1)
    return date_list


def month_datelist(start_day: str) -> List[List[str]]:
    """传入 'YYYY-MM' 格式的开始月份，生成从该月到上个月的所有月份的起止日期列表。"""
    try:
        start_dt = datetime.datetime.strptime(start_day, r"%Y-%m")
    except ValueError:
        return []

    end_dt = datetime.datetime.now() - relativedelta(months=1)
    month_list = []
    current_dt = start_dt

    while current_dt <= end_dt:
        month_str = current_dt.strftime('%Y%m')
        month_begin, month_end = get_month_b_e_day(month_str)
        month_list.append([month_begin, month_end])
        current_dt += relativedelta(months=1)

    return month_list


# ==================== 获取特定日期 ====================

def getdate(before_of_day: int, fm: str = "%Y-%m-%d", today: Optional[str] = None) -> str:
    """获取指定日期的前 N 天或后 N 天的日期。"""
    if isinstance(today, str):
        today_dt = str_toDatetime(today)
        if not today_dt:
            return ""
    else:
        today_dt = datetime.datetime.now()

    offset = datetime.timedelta(days=-before_of_day)
    return (today_dt + offset).strftime(fm)


def getBeforeWeekDays(weeks: int = 1) -> List[str]:
    """获取过去 N 周的所有日期列表。"""
    days_list = []
    today = datetime.datetime.now()
    start_day = today - datetime.timedelta(days=7 * weeks + today.weekday())
    end_day = today - datetime.timedelta(days=today.weekday() + 1)

    current_day = start_day
    while current_day <= end_day:
        days_list.append(current_day.strftime("%Y-%m-%d"))
        current_day += datetime.timedelta(days=1)
    return days_list


# ==================== 装饰器相关 ====================

def monitoring_run_time(f: Callable) -> Callable:
    """
    基础计时装饰器 - 测量函数执行时间（秒级）

    示例:
        @monitoring_run_time
        def my_function():
            time.sleep(1)
            return "完成"

    输出: my_function 执行成功，用时: 1.00 秒
    """

    @wraps(f)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = f(*args, **kwargs)
        end_time = time.time()
        print(f"{f.__name__} 执行成功，用时: {end_time - start_time:.2f} 秒")
        return result

    return wrapper


def time_decorator(print_result: bool = False, verbose: bool = False) -> Callable:
    """
    可配置的计时装饰器 - 灵活控制输出内容

    参数:
        print_result: 是否打印函数的返回结果
        verbose: 是否显示详细参数信息

    示例:
        @time_decorator(print_result=True, verbose=True)
        def add(a, b):
            return a + b

        add(1, 2)

    输出:
        函数 add(2 args, 0 kwargs) 执行时间: 0.0001 秒
        返回结果: 3
    """

    def decorator(f: Callable) -> Callable:
        @wraps(f)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            result = f(*args, **kwargs)
            end_time = time.time()
            elapsed = end_time - start_time

            # 构建输出信息
            if verbose:
                arg_info = f"({len(args)} args, {len(kwargs)} kwargs)"
                print(f"函数 {f.__name__}{arg_info} 执行时间: {elapsed:.4f} 秒")
            else:
                print(f"函数 {f.__name__} 执行时间: {elapsed:.4f} 秒")

            if print_result and result is not None:
                result_str = str(result)
                if len(result_str) > 100:
                    result_str = result_str[:97] + "..."
                print(f"返回结果: {result_str}")

            return result

        return wrapper

    return decorator


def time_decorator_with_return(f: Callable) -> Callable:
    """
    返回执行时间的装饰器 - 函数返回(结果, 执行时间)元组

    示例:
        @time_decorator_with_return
        def process_data():
            time.sleep(0.5)
            return {"status": "success"}

        result, elapsed = process_data()
        print(f"结果: {result}, 用时: {elapsed}秒")

    返回: (函数结果, 执行时间秒数)
    """

    @wraps(f)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = f(*args, **kwargs)
        end_time = time.time()
        elapsed = end_time - start_time
        return (result, elapsed)

    return wrapper


def time_decorator_silent(f: Callable) -> Callable:
    """
    静默计时装饰器 - 不输出任何信息，仅用于调试

    示例:
        @time_decorator_silent
        def critical_function():
            # 重要函数，不希望在控制台输出计时信息
            pass
    """

    @wraps(f)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = f(*args, **kwargs)
        end_time = time.time()
        # 静默执行，不输出任何信息
        return result

    return wrapper


def time_decorator_threshold(threshold: float = 1.0) -> Callable:
    """
    阈值警告装饰器 - 只在执行时间超过阈值时输出警告

    参数:
        threshold: 时间阈值（秒），默认1秒

    示例:
        @time_decorator_threshold(threshold=0.5)
        def slow_function():
            time.sleep(1)  # 超过阈值
            return "完成"

    输出: ⚠️ 函数 slow_function 执行较慢: 1.00s (阈值: 0.5s)
    """

    def decorator(f: Callable) -> Callable:
        @wraps(f)
        def wrapper(*args, **kwargs):
            start_time = time.time()
            result = f(*args, **kwargs)
            end_time = time.time()
            elapsed = end_time - start_time

            if elapsed > threshold:
                print(f"⚠️ 函数 {f.__name__} 执行较慢: {elapsed:.2f}s (阈值: {threshold}s)")

            return result

        return wrapper

    return decorator


def time_context() -> "TimerContext":
    """
    上下文管理器计时器 - 使用with语句测量代码块执行时间

    示例:
        with time_context() as timer:
            time.sleep(0.5)
            result = some_operation()
        print(f"执行时间: {timer.elapsed:.2f}秒")
        print(f"执行结果: {result}")
    """

    class TimerContext:
        def __enter__(self):
            self.start_time = time.time()
            return self

        def __exit__(self, exc_type, exc_val, exc_tb):
            self.end_time = time.time()
            self.elapsed = self.end_time - self.start_time

    return TimerContext()


# ==================== 时间判断 ====================

def judge_time(ti: str, st: str, en: str, year: bool = True) -> bool:
    """判断时间字符串 ti 是否在 st 和 en 之间。"""
    try:
        if year:
            fmt = '%Y-%m-%d %H:%M:%S'
        else:
            fmt = '%H:%M:%S'

        t_time = datetime.datetime.strptime(ti, fmt)
        s_time = datetime.datetime.strptime(st, fmt)
        e_time = datetime.datetime.strptime(en, fmt)

        if e_time <= s_time:
            print("警告：结束时间应大于开始时间！")
            return False

        return s_time < t_time < e_time
    except (ValueError, TypeError) as e:
        print(f"判断时间失败: {e}")
        return False


# ==================== 网络时间 ====================

@retry(stop_max_attempt_number=3, wait_exponential_multiplier=1000)
def get_taobao_time() -> Dict[str, str]:
    """尝试从淘宝API获取标准时间，如果失败则返回本地时间。"""
    try:
        url = 'http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp'
        response = requests.get(url, timeout=5)
        response.raise_for_status()

        data = response.json()
        if data.get('ret') and 'SUCCESS' in data.get('ret')[0]:
            timestamp = int(data.get('data', {}).get('t', 0)) // 1000
            return {
                "sysTime1": str(timestamp * 1000),  # 毫秒
                "sysTime2": timestamp_tostr(timestamp),
                "sysTime3": ts_toStr_det(timestamp)
            }
    except requests.exceptions.RequestException as e:
        print(f"获取淘宝时间失败: {e}")

    # 如果API调用失败，使用本地时间作为备用
    local_timestamp = int(time.time())
    return {
        "sysTime1": str(local_timestamp * 1000),
        "sysTime2": timestamp_tostr(local_timestamp),
        "sysTime3": ts_toStr_det(local_timestamp)
    }


# ==================== 时间拆分 ====================

def split_time_h(start_time: str, end_time: str) -> List[str]:
    """将给定的时间范围按小时拆分。"""
    start_dt = dil_str_toDatetime(start_time)
    end_dt = dil_str_toDatetime(end_time)

    if not start_dt or not end_dt:
        return []

    hour_list = []
    current_dt = start_dt.replace(minute=0, second=0, microsecond=0)

    while current_dt <= end_dt:
        hour_list.append(current_dt.strftime("%Y-%m-%d %H:00:00"))
        current_dt += datetime.timedelta(hours=1)

    return hour_list


# ==================== 月份列表 ====================

def get_month_list(start_date: str, end_date: str) -> List[str]:
    """获取两个月份之间的所有月份列表。"""
    try:
        start_dt = datetime.datetime.strptime(start_date, '%Y-%m')
        end_dt = datetime.datetime.strptime(end_date, '%Y-%m')
    except ValueError:
        return []

    month_list = []
    current_dt = start_dt
    while current_dt <= end_dt:
        month_list.append(current_dt.strftime('%Y-%m'))
        current_dt += relativedelta(months=1)
    return month_list


def get_previous_months(start_date: str, num_months: int) -> List[str]:
    """获取从指定月份向前追溯 N 个月的所有月份列表。"""
    try:
        start_dt = datetime.datetime.strptime(start_date, '%Y-%m')
    except ValueError:
        return []

    month_list = []
    for _ in range(num_months + 1):
        month_list.append(start_dt.strftime('%Y-%m'))
        start_dt -= relativedelta(months=1)

    month_list.reverse()
    return month_list


# ==================== 新增的便捷方法 ====================

def get_current_month_range() -> tuple[str, str]:
    """获取当前月份的第一天和最后一天。"""
    today = datetime.date.today()
    first_day = today.replace(day=1)
    last_day = get_last_day_of_month(datetime.datetime.combine(today, datetime.time.min))
    return first_day.strftime("%Y-%m-%d"), last_day.strftime("%Y-%m-%d")


def get_last_day_of_month(date: datetime.datetime) -> datetime.date:
    """获取指定日期所在月份的最后一天。"""
    next_month = date.replace(day=28) + datetime.timedelta(days=4)
    return (next_month - datetime.timedelta(days=next_month.day)).date()


def is_leap_year(year: int) -> bool:
    """判断给定的年份是否为闰年。"""
    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)


def get_business_days(start_date: str, end_date: str) -> List[str]:
    """获取两个日期之间的所有工作日（周一至周五）列表。"""
    business_days = []
    start_dt = str_toDatetime(start_date)
    end_dt = str_toDatetime(end_date)

    if not start_dt or not end_dt:
        return []

    current_dt = start_dt
    while current_dt <= end_dt:
        if current_dt.weekday() < 5:  # 0-4 表示周一到周五
            business_days.append(current_dt.strftime("%Y-%m-%d"))
        current_dt += datetime.timedelta(days=1)
    return business_days


def get_week_day(date: datetime.datetime) -> str:
    """根据日期返回星期几的中文名称。"""
    week_day_dict = {
        0: '星期一', 1: '星期二', 2: '星期三', 3: '星期四',
        4: '星期五', 5: '星期六', 6: '星期日',
    }
    return week_day_dict.get(date.weekday(), '未知')


def get_age(birth_date: str, current_date: Optional[str] = None) -> int:
    """计算年龄（周岁）。"""
    birth_dt = str_toDatetime(birth_date)
    if not birth_dt:
        return 0

    if current_date:
        current_dt = str_toDatetime(current_date)
    else:
        current_dt = datetime.datetime.now()

    if not current_dt:
        return 0

    age = current_dt.year - birth_dt.year
    if (current_dt.month, current_dt.day) < (birth_dt.month, birth_dt.day):
        age -= 1
    return age


def get_quarter(date: datetime.datetime) -> int:
    """获取日期所在的季度（1-4）。"""
    return (date.month - 1) // 3 + 1


def get_quarter_range(date: datetime.datetime) -> tuple[str, str]:
    """获取日期所在季度的开始和结束日期。"""
    quarter = get_quarter(date)
    year = date.year

    if quarter == 1:
        start_date = datetime.datetime(year, 1, 1)
        end_date = datetime.datetime(year, 3, 31)
    elif quarter == 2:
        start_date = datetime.datetime(year, 4, 1)
        end_date = datetime.datetime(year, 6, 30)
    elif quarter == 3:
        start_date = datetime.datetime(year, 7, 1)
        end_date = datetime.datetime(year, 9, 30)
    else:  # quarter == 4
        start_date = datetime.datetime(year, 10, 1)
        end_date = datetime.datetime(year, 12, 31)

    return start_date.strftime("%Y-%m-%d"), end_date.strftime("%Y-%m-%d")


def is_workday(date: datetime.datetime) -> bool:
    """判断是否为工作日（周一到周五）。"""
    return date.weekday() < 5


def is_weekend(date: datetime.datetime) -> bool:
    """判断是否为周末（周六或周日）。"""
    return date.weekday() >= 5


def get_time_difference(start_time: str, end_time: str, unit: str = 'seconds') -> float:
    """计算两个时间的差值，支持多种单位。"""
    start_dt = dil_str_toDatetime(start_time)
    end_dt = dil_str_toDatetime(end_time)

    if not start_dt or not end_dt:
        return 0.0

    diff_seconds = (end_dt - start_dt).total_seconds()

    units = {
        'seconds': diff_seconds,
        'minutes': diff_seconds / 60,
        'hours': diff_seconds / 3600,
        'days': diff_seconds / 86400,
        'weeks': diff_seconds / 604800
    }

    return units.get(unit, diff_seconds)


def get_current_season() -> str:
    """获取当前季度。"""
    month = datetime.datetime.now().month
    season = (month - 1) // 3 + 1
    year = datetime.datetime.now().year
    return f"{year}年第{season}季度"


def format_duration(seconds: int) -> str:
    """格式化时间间隔为可读格式。"""
    if seconds < 60:
        return f"{seconds}秒"
    elif seconds < 3600:
        minutes = seconds // 60
        return f"{minutes}分钟{seconds % 60}秒"
    elif seconds < 86400:
        hours = seconds // 3600
        minutes = (seconds % 3600) // 60
        return f"{hours}小时{minutes}分钟"
    else:
        days = seconds // 86400
        hours = (seconds % 86400) // 3600
        return f"{days}天{hours}小时"


def get_last_n_days(n: int, include_today: bool = False) -> List[str]:
    """获取最近N天的日期列表。"""
    today = datetime.date.today()
    dates = []

    for i in range(n):
        if i == 0 and not include_today:
            continue
        date = today - datetime.timedelta(days=i)
        dates.append(date.strftime("%Y-%m-%d"))

    return dates[::-1]  # 按时间顺序返回


def get_first_and_last_day_of_year(year: int) -> tuple[str, str]:
    """获取指定年份的第一天和最后一天。"""
    first_day = datetime.date(year, 1, 1)
    last_day = datetime.date(year, 12, 31)
    return first_day.strftime("%Y-%m-%d"), last_day.strftime("%Y-%m-%d")


def is_valid_date(date_str: str, fmt: str = "%Y-%m-%d") -> bool:
    """验证日期字符串是否有效。"""
    try:
        datetime.datetime.strptime(date_str, fmt)
        return True
    except ValueError:
        return False


def get_week_number(date: datetime.datetime) -> int:
    """获取日期所在的周数（ISO周数）。"""
    return date.isocalendar()[1]


def get_week_range(date: datetime.datetime) -> tuple[str, str]:
    """获取日期所在周的周一和周日。"""
    monday = date - datetime.timedelta(days=date.weekday())
    sunday = monday + datetime.timedelta(days=6)
    return monday.strftime("%Y-%m-%d"), sunday.strftime("%Y-%m-%d")


def time_elapsed_since(start_time: datetime.datetime) -> str:
    """计算从指定时间到现在的时间差（人性化显示）。"""
    now = datetime.datetime.now()
    diff = now - start_time

    if diff.days > 365:
        years = diff.days // 365
        return f"{years}年前"
    elif diff.days > 30:
        months = diff.days // 30
        return f"{months}个月前"
    elif diff.days > 7:
        weeks = diff.days // 7
        return f"{weeks}周前"
    elif diff.days > 0:
        return f"{diff.days}天前"
    elif diff.seconds > 3600:
        hours = diff.seconds // 3600
        return f"{hours}小时前"
    elif diff.seconds > 60:
        minutes = diff.seconds // 60
        return f"{minutes}分钟前"
    else:
        return "刚刚"


def convert_timezone(dt: datetime.datetime, from_tz: str, to_tz: str) -> datetime.datetime:
    """
    时区转换（需要安装pytz）。
    示例：convert_timezone(now, 'UTC', 'Asia/Shanghai')
    """
    try:
        import pytz
        from_zone = pytz.timezone(from_tz)
        to_zone = pytz.timezone(to_tz)
        dt = from_zone.localize(dt)
        return dt.astimezone(to_zone)
    except ImportError:
        print("请先安装pytz库：pip install pytz")
        return dt
    except Exception as e:
        print(f"时区转换失败: {e}")
        return dt


def get_current_week_range() -> tuple[str, str]:
    """获取当前周的周一和周日。"""
    return get_week_range(datetime.datetime.now())


def get_yesterday_date(fmt: str = "%Y-%m-%d") -> str:
    """获取昨天的日期。"""
    yesterday = datetime.datetime.now() - datetime.timedelta(days=1)
    return yesterday.strftime(fmt)


def get_tomorrow_date(fmt: str = "%Y-%m-%d") -> str:
    """获取明天的日期。"""
    tomorrow = datetime.datetime.now() + datetime.timedelta(days=1)
    return tomorrow.strftime(fmt)


def get_week_start_end(date_str: str) -> tuple[str, str]:
    """获取指定日期所在周的周一和周日。"""
    date = str_toDatetime(date_str)
    if not date:
        return "", ""
    return get_week_range(date)


def is_same_day(date1: datetime.datetime, date2: datetime.datetime) -> bool:
    """判断两个日期是否为同一天。"""
    return date1.date() == date2.date()


def is_same_month(date1: datetime.datetime, date2: datetime.datetime) -> bool:
    """判断两个日期是否为同一月。"""
    return date1.year == date2.year and date1.month == date2.month


def is_same_year(date1: datetime.datetime, date2: datetime.datetime) -> bool:
    """判断两个日期是否为同一年。"""
    return date1.year == date2.year


def get_days_in_month(year: int, month: int) -> int:
    """获取指定年月的天数。"""
    if month == 12:
        next_month = datetime.date(year + 1, 1, 1)
    else:
        next_month = datetime.date(year, month + 1, 1)

    last_day = next_month - datetime.timedelta(days=1)
    return last_day.day


def get_remaining_days_in_year() -> int:
    """获取今年剩余天数。"""
    today = datetime.date.today()
    end_of_year = datetime.date(today.year, 12, 31)
    return (end_of_year - today).days


def get_passed_days_in_year() -> int:
    """获取今年已过天数。"""
    today = datetime.date.today()
    start_of_year = datetime.date(today.year, 1, 1)
    return (today - start_of_year).days + 1


def get_current_time_in_millis() -> int:
    """获取当前时间的毫秒数。"""
    return int(time.time() * 1000)


def sleep_until(target_time: str) -> None:
    """休眠直到指定的时间。"""
    target_dt = dil_str_toDatetime(target_time)
    if not target_dt:
        return

    now = datetime.datetime.now()
    if target_dt > now:
        seconds_to_wait = (target_dt - now).total_seconds()
        time.sleep(seconds_to_wait)


def is_time_in_range(target_time: str, start_time: str, end_time: str) -> bool:
    """判断时间是否在指定范围内（只比较时间部分，忽略日期）。"""
    try:
        fmt = "%H:%M:%S"
        target = datetime.datetime.strptime(target_time, fmt).time()
        start = datetime.datetime.strptime(start_time, fmt).time()
        end = datetime.datetime.strptime(end_time, fmt).time()

        if start <= end:
            return start <= target <= end
        else:  # 跨天的时间段
            return start <= target or target <= end
    except ValueError:
        return False


def get_current_year() -> int:
    """获取当前年份。"""
    return datetime.datetime.now().year


def get_current_month() -> int:
    """获取当前月份。"""
    return datetime.datetime.now().month


def get_current_day() -> int:
    """获取当前日期（几号）。"""
    return datetime.datetime.now().day


def get_current_hour() -> int:
    """获取当前小时。"""
    return datetime.datetime.now().hour


def get_current_minute() -> int:
    """获取当前分钟。"""
    return datetime.datetime.now().minute


def get_current_second() -> int:
    """获取当前秒数。"""
    return datetime.datetime.now().second


def get_current_microsecond() -> int:
    """获取当前微秒数。"""
    return datetime.datetime.now().microsecond


def is_future(date_str: str) -> bool:
    """判断日期是否为未来时间。"""
    dt = str_toDatetime(date_str)
    if not dt:
        return False
    return dt > datetime.datetime.now()


def is_past(date_str: str) -> bool:
    """判断日期是否为过去时间。"""
    dt = str_toDatetime(date_str)
    if not dt:
        return False
    return dt < datetime.datetime.now()


def get_next_weekday(date: datetime.datetime, weekday: int) -> datetime.datetime:
    """获取指定日期后的下一个星期几（0=周一，6=周日）。"""
    days_ahead = weekday - date.weekday()
    if days_ahead <= 0:
        days_ahead += 7
    return date + datetime.timedelta(days=days_ahead)


def get_previous_weekday(date: datetime.datetime, weekday: int) -> datetime.datetime:
    """获取指定日期前的上一个星期几（0=周一，6=周日）。"""
    days_before = date.weekday() - weekday
    if days_before < 0:
        days_before += 7
    return date - datetime.timedelta(days=days_before)


def get_midnight_time(date_str: str) -> str:
    """获取指定日期的午夜时间（00:00:00）。"""
    dt = str_toDatetime(date_str)
    if not dt:
        return ""
    midnight = dt.replace(hour=0, minute=0, second=0, microsecond=0)
    return datetime_toStr_dil(midnight)


def get_end_of_day_time(date_str: str) -> str:
    """获取指定日期的结束时间（23:59:59）。"""
    dt = str_toDatetime(date_str)
    if not dt:
        return ""
    end_of_day = dt.replace(hour=23, minute=59, second=59, microsecond=999999)
    return datetime_toStr_dil(end_of_day)


def get_start_of_hour(date_str: str) -> str:
    """获取指定时间的小时开始时间。"""
    dt = dil_str_toDatetime(date_str)
    if not dt:
        return ""
    start_of_hour = dt.replace(minute=0, second=0, microsecond=0)
    return datetime_toStr_dil(start_of_hour)


def get_end_of_hour(date_str: str) -> str:
    """获取指定时间的小时结束时间。"""
    dt = dil_str_toDatetime(date_str)
    if not dt:
        return ""
    end_of_hour = dt.replace(minute=59, second=59, microsecond=999999)
    return datetime_toStr_dil(end_of_hour)


def get_iso_format(date_str: str) -> str:
    """获取ISO格式的日期时间字符串。"""
    dt = dil_str_toDatetime(date_str)
    if not dt:
        return ""
    return dt.isoformat()


def get_rfc2822_format(date_str: str) -> str:
    """获取RFC 2822格式的日期时间字符串。"""
    from email.utils import formatdate
    dt = dil_str_toDatetime(date_str)
    if not dt:
        return ""
    timestamp = datetime_toTimestamp(dt)
    return formatdate(timeval=timestamp, localtime=True)


def get_human_readable_time_diff(start_time: str, end_time: str) -> str:
    """获取两个时间之间的人性化时间差。"""
    start_dt = dil_str_toDatetime(start_time)
    end_dt = dil_str_toDatetime(end_time)

    if not start_dt or not end_dt:
        return ""

    diff = end_dt - start_dt
    if diff.days > 0:
        if diff.days > 365:
            years = diff.days // 365
            months = (diff.days % 365) // 30
            if months > 0:
                return f"{years}年{months}个月"
            return f"{years}年"
        elif diff.days > 30:
            months = diff.days // 30
            days = diff.days % 30
            if days > 0:
                return f"{months}个月{days}天"
            return f"{months}个月"
        elif diff.days > 7:
            weeks = diff.days // 7
            days = diff.days % 7
            if days > 0:
                return f"{weeks}周{days}天"
            return f"{weeks}周"
        else:
            return f"{diff.days}天{diff.seconds // 3600}小时"
    else:
        if diff.seconds >= 3600:
            hours = diff.seconds // 3600
            minutes = (diff.seconds % 3600) // 60
            if minutes > 0:
                return f"{hours}小时{minutes}分钟"
            return f"{hours}小时"
        elif diff.seconds >= 60:
            minutes = diff.seconds // 60
            seconds = diff.seconds % 60
            if seconds > 0:
                return f"{minutes}分钟{seconds}秒"
            return f"{minutes}分钟"
        else:
            return f"{diff.seconds}秒"


# ==================== 常用快捷方法别名 ====================

# 时间戳相关
timestamp = time_stamp  # 获取指定位数的时间戳字符串
timestamp_ms = format_nowtime_millisecond  # 获取当前毫秒级时间戳
ts = time_stamp  # 获取指定位数的时间戳字符串（简写）
current_ts_ms = format_nowtime_millisecond  # 获取当前毫秒级时间戳
millis = get_current_time_in_millis  # 获取当前时间的毫秒数

# 当前时间相关
now = get_now_date  # 获取当前日期字符串
now_time = get_now_time  # 获取当前完整时间字符串
today = get_now_date  # 获取今天日期字符串
current_time = get_now_time  # 获取当前时间字符串
current_date = get_now_date  # 获取当前日期字符串
ctime = get_now_time  # 获取当前时间字符串（简写）
cdate = get_now_date  # 获取当前日期字符串（简写）

# 解析转换相关
str2dt = str_toDatetime  # 字符串转datetime对象
dt2str = datetime_toStr  # datetime对象转字符串
str2ts = str_toTimestamp  # 字符串转时间戳
ts2str = timestamp_tostr  # 时间戳转字符串
dt2ts = datetime_toTimestamp  # datetime对象转时间戳
parse = parse_datetime  # 智能解析字符串为datetime对象
to_dt = str_toDatetime  # 字符串转datetime对象
to_str = datetime_toStr  # datetime对象转字符串
to_ts = str_toTimestamp  # 字符串转时间戳

# 详细转换
str2dt_det = dil_str_toDatetime  # 详细时间字符串转datetime对象
dt2str_det = datetime_toStr_dil  # datetime对象转详细时间字符串
ts2str_det = ts_toStr_det  # 时间戳转详细时间字符串
dt2str_ch = datetime_toChinStr  # datetime对象转中文日期字符串
dt2str_ch_det = datetime_toChinStr_dil  # datetime对象转详细中文日期字符串

# 时间计算
add_time = dateTime_Add  # 在指定日期上增加时间
sub_time = date_time_subtraction  # 从指定日期上减去时间
time_diff = get_time_difference  # 计算两个时间的差值
diff = get_time_difference  # 计算时间差（简写）
time_span = get_time_difference  # 计算时间跨度
elapsed = time_elapsed_since  # 计算从过去时间到现在的经过时间

# 日期比较
is_future_date = is_future  # 判断日期是否为未来时间
is_past_date = is_past  # 判断日期是否为过去时间
is_same_date = is_same_day  # 判断两个日期是否为同一天
compare = compare_dateTime  # 比较两个日期大小
is_after = compare_dateTime  # 判断第一个日期是否在第二个日期之后

# 工作日相关
is_weekday = is_workday  # 判断是否为工作日（周一到周五）
business_days = get_business_days  # 获取两个日期之间的工作日列表
workdays = get_business_days  # 获取工作日列表（同business_days）
is_business_day = is_workday  # 判断是否为工作日

# 日期范围
days_between = getBetweenDay  # 获取两个日期之间的所有日期列表
date_range = getBetweenDay  # 获取日期范围（同days_between）
range_days = getBetweenDay  # 获取日期范围内的天数
week_range = get_week_range  # 获取日期所在周的周一和周日
month_range = get_current_month_range  # 获取当前月份的第一天和最后一天
quarter_range = get_quarter_range  # 获取日期所在季度的开始和结束日期
year_range = get_first_and_last_day_of_year  # 获取指定年份的第一天和最后一天

# 获取特定日期
yesterday = get_yesterday_date  # 获取昨天的日期
tomorrow = get_tomorrow_date  # 获取明天的日期
last_n_days = get_last_n_days  # 获取最近N天的日期列表
prev_days = get_last_n_days  # 获取前几天的日期列表
next_weekday = get_next_weekday  # 获取指定日期后的下一个星期几
prev_weekday = get_previous_weekday  # 获取指定日期前的上一个星期几

# 星期相关
weekday = get_week_day  # 获取日期的星期几中文名称
day_of_week = get_week_day  # 获取星期几（同weekday）
week_num = get_week_number  # 获取日期所在的周数（ISO周数）
iso_week = get_week_number  # 获取ISO周数（同week_num）

# 月份相关
last_day = get_last_day_of_month  # 获取指定日期所在月份的最后一天
days_in_month = get_days_in_month  # 获取指定年月的天数
month_days = get_days_in_month  # 获取月份天数（同days_in_month）
is_leap = is_leap_year  # 判断是否为闰年
quarter = get_quarter  # 获取日期所在的季度（1-4）
season = get_quarter  # 获取季度（同quarter）
get_season = get_current_season  # 获取当前季度字符串

# 年份相关
year = get_current_year  # 获取当前年份
month = get_current_month  # 获取当前月份
day = get_current_day  # 获取当前日期（几号）
remaining_days = get_remaining_days_in_year  # 获取今年剩余天数
passed_days = get_passed_days_in_year  # 获取今年已过天数
year_start_end = get_first_and_last_day_of_year  # 获取年份的开始和结束日期

# 时间部分
hour = get_current_hour  # 获取当前小时
minute = get_current_minute  # 获取当前分钟
second = get_current_second  # 获取当前秒数
microsecond = get_current_microsecond  # 获取当前微秒数

# 验证判断
is_valid = is_valid_date  # 验证日期字符串是否有效
valid_date = is_valid_date  # 验证日期有效性（同is_valid）
in_range = is_time_in_range  # 判断时间是否在指定范围内
is_in_range = is_time_in_range  # 判断时间是否在范围内（同in_range）
is_work_time = is_time_in_range  # 判断是否为工作时间范围

# 格式化相关
format_dt = datetime_toStr  # 格式化datetime对象为字符串
format_ts = timestamp_tostr  # 格式化时间戳为字符串
human_time = time_elapsed_since  # 人性化显示从过去到现在的时间
human_diff = get_human_readable_time_diff  # 人性化显示两个时间之间的差值
duration = format_duration  # 格式化时间间隔为可读格式
iso = get_iso_format  # 获取ISO格式的日期时间字符串
rfc2822 = get_rfc2822_format  # 获取RFC 2822格式的日期时间字符串

# 特殊时间点
midnight = get_midnight_time  # 获取指定日期的午夜时间（00:00:00）
end_of_day = get_end_of_day_time  # 获取指定日期的结束时间（23:59:59）
start_of_hour = get_start_of_hour  # 获取指定时间的小时开始时间
end_of_hour = get_end_of_hour  # 获取指定时间的小时结束时间
start_of_day = get_midnight_time  # 获取天开始时间（同midnight）
start_of_week = get_current_week_range  # 获取当前周的开始日期
start_of_month = get_current_month_range  # 获取当前月的开始日期

# 网络时间
taobao_time = get_taobao_time  # 从淘宝API获取标准时间
network_time = get_taobao_time  # 获取网络时间（同taobao_time）
internet_time = get_taobao_time  # 获取互联网时间（同taobao_time）

# 年龄计算
age = get_age  # 计算年龄（周岁）
get_age_years = get_age  # 计算年龄（同age）
calc_age = get_age  # 计算年龄（同age）

# 装饰器相关别名
timer = monitoring_run_time  # 基础计时装饰器 - 测量函数执行时间（秒级）
timeit = time_decorator()  # 可配置的计时装饰器 - 灵活控制输出内容
measure_time = time_decorator_with_return  # 返回执行时间的装饰器 - 函数返回(结果, 执行时间)元组
timed = time_decorator  # 可配置的计时装饰器（工厂函数）
clock = time_decorator_silent  # 静默计时装饰器 - 不输出任何信息，仅用于调试
profile = time_decorator_threshold(1.0)  # 阈值警告装饰器 - 只在执行时间超过1秒时输出警告
slow_warn = time_decorator_threshold  # 阈值警告装饰器（工厂函数）
time_context = time_context  # 上下文管理器计时器 - 使用with语句测量代码块执行时间
time_log = time_decorator_silent  # 静默计时装饰器（同clock）

# 其他
sleep_until_time = sleep_until  # 休眠直到指定的时间
wait_until = sleep_until  # 等待直到指定时间（同sleep_until_time）
tz_convert = convert_timezone  # 时区转换
change_timezone = convert_timezone  # 时区转换（同tz_convert）
