from datetime import datetime, timezone, timedelta
from dateutil import parser, tz  

'''
2025-02-09T15:45:00+00:00 采用的是 ISO 8601 国际标准日期时间格式，具体特点如下：

日期部分：YYYY-MM-DD（年-月-日），例如2025-02-09表示2025年2月9日。
时间部分：HH:mm:ss（时:分:秒），例如15:45:00表示下午3点45分0秒。
分隔符：日期与时间之间用字母T连接，表明这是一个完整的时间点。
时区偏移：末尾的+00:00表示该时间基于协调世界时（UTC），即零时区。若使用Z替代+00:00（如2025-02-09T15:45:00Z），也符合ISO 8601标准，两者等价

北京时间格式
    2025-02-09T15:45:00+08:00 

'''
BG_TZ = tz.gettz('Asia/Shanghai')
UTC_TZ = tz.gettz('UTC')

def parse_utc_time(query_time: str) -> datetime:
    '''
    接受 任意格式的字符串，如果解析出来不带时区，则用 replace 添加 +00:00 时区
                         如果解析出来已经有时区，则用 astimezone 转换成UTC时间
    '''

    # 解析时间字符串
    dt: datetime = parser.parse(query_time)
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=UTC_TZ)
    else:
        dt = dt.astimezone(UTC_TZ)

    return dt
    
def parse_beijing_time(query_time: str) -> datetime:
    '''
    接受 任意格式的字符串，如果解析出来不带时区，则用 replace 添加 +08:00 时区
                         如果解析出来已经有时区，则用 astimezone 转换成北京时间

        也就是任意合法的时间字符串，最后都解析成 北京 时间

    '''

    # 解析时间字符串
    dt: datetime = parser.parse(query_time)
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=BG_TZ)
    else:
        dt = dt.astimezone(tz=BG_TZ)

    return dt


def to_utc_time(dt: datetime) -> datetime:
    '''
    将一个北京时间的时间点，转换成utc
    '''
    utc_time = dt.astimezone(UTC_TZ)
    return utc_time


def to_beijing_time(dt: datetime) -> datetime:
    '''
    将一个 utc 的时间点，转换成北京时间
    '''
    beijing_time = dt.astimezone(tz=BG_TZ)
    return beijing_time

    
def to_time_range(dt: datetime, delta: float) -> tuple[datetime, datetime]:
    '''
    将一个时间点，转换成 start/end 时间段
    有些查询按照一个时间点查不到，用时间段保证能成功
    
    delta 单位是秒
    '''
    start_time = dt - timedelta(seconds=delta)
    end_time = dt + timedelta(seconds=delta)

    return (start_time, end_time)

def parse_beijing_date_range(query_date: str) -> tuple[datetime, datetime]:
    '''
    将一个日期字符串，转换成 start/end 时间段，传进来的日期被认为是北京时间
    日期字符串格式：YYYY-MM-DD
    '''
    start_time = parse_beijing_time(query_date)
    end_time = start_time + timedelta(days=1)

    return (start_time, end_time)


def get_day_start(dt: datetime.date) -> datetime:
    '''
    获取 某一天的 00:00:00
    这一天可以是北京时间，也可以是 utc 时间
    '''
    return dt.replace(hour=0, minute=0, second=0, microsecond=0)


def get_day_end(dt: datetime.date) -> datetime:
    '''
    获取 某一天的 23:59:59
    这一天可以是北京时间，也可以是 utc 时间
    '''
    return dt.replace(hour=23, minute=59, second=59, microsecond=0)

def get_date_from_time(time: str) -> str:
    '''
    将一个时间点，转换成日期
    '''
    dt = parse_beijing_time(time)
    return str(dt.date())


def is_today(query_date: str) -> bool:
    '''
    判断一个日期是否是今天
    '''
    dt = parse_beijing_time(query_date)
    return dt.date() == datetime.now().date()


def is_yesterday(query_date: str) -> bool:
    '''
    判断一个日期是否是昨天
    '''
    dt = parse_beijing_time(query_date)
    return dt.date() == (datetime.now().date() - timedelta(days=1))

def is_tomorrow(query_date: str) -> bool:
    '''
    判断一个日期是否是明天
    '''
    dt = parse_beijing_time(query_date)
    return dt.date() == (datetime.now().date() + timedelta(days=1))

def is_today_or_future(query_date: str) -> bool:
    '''
    判断一个日期是否是今天或未来
    '''
    dt = parse_beijing_time(query_date)
    return dt.date() >= datetime.now().date()

