作者:viponedream ;来源:维恩的派论坛
 

# ----------------------------------------------------------------------
def convert_datetime(dt=None, oldtz=None, newtz=None, fmt=None, returnStr=False, withFlag=False):
    """输入一个日期,时间,返回一个新时区的datetime对象
    DateTime   可以是字符串,数字,日期,时间或者日期对象
    可能的值 (可以带时区,默认为UTC)
       20160530 10:59:59    字符 日期 时间
       20160530             字符 日期
       10:59:59             字符  时间
       1536249467.2627187   timestamp(可字符或数字)


    传入的日期或字符串日期, 如20160530 10:59:59
                     或者传入一个时间戳   时间戳没有时区概念,是GMT以来的秒数
    newtz            想要的新时区,有新时区则返回新时区,否则返回UTC时间
    oldtz            传入日期的原来时区 可选参数 CST  EST  GMT  UTC
    withFlag
    """
    """
    now(), datetime(), time()都是可以指定tzinfo信息的,而date是不行的

    """


    # 定义输出格式   '%Y%m%d %H:%M:%S'     '%Y%m%d %H:%M:%S.%f'
    if not fmt:
        fmt = '%Y%m%d %H:%M:%S.%f'

    # 定义常用时区
    utcZone = pytz.timezone('utc')  # 标准时间 UTC, GMT
    estZone = pytz.timezone('US/Eastern')  # 北美 EST 时区  US/Eastern
    cstZone = pytz.timezone('Asia/Shanghai')  # 中国时区 CST

    # 判断传入时间的时区  UTC, GMT, CST, EST
    if oldtz is not None:
        oldtz = oldtz.upper()

    if not oldtz or oldtz in ['UTC', 'GMT']:  # 没有传入默认为 UTC(GMT)
        oldtz = utcZone
    elif oldtz == 'CST':  # 传入的是中国时区
        oldtz = cstZone
    elif oldtz == 'EST':  # 传入的是北美时区
        oldtz = estZone
    else:
        print(u'传入的时区没法识别')
        return

    # 判断要转换出去的时区  UTC, GMT, CST, EST
    if newtz is not None:
        newtz = newtz.upper()
    if not newtz or newtz in ['UTC', 'GMT']:  # 没有传入默认为 UTC(GMT)
        newtz = utcZone
        dtEndStr = 'GMT'
    elif newtz == 'CST':  # 传入的是中国时区
        newtz = cstZone
        dtEndStr = 'CST'
    elif newtz == 'EST':  # 传入的是北美时区
        newtz = estZone
        dtEndStr = 'EST'
    else:
        print(u'传入的时区没法识别')
        return

    newdt = None
    # 先判断是否日期对象
    if isinstance(dt, str):
        # 2016-01-05 21:55:20
        # 如果只是导入的 21:55:20,则先在前面加上日期,
        dt = dt.replace('-', '')

    if dt is None or not dt:  # 如果dt为空或者没有传进来
        now = time.time()
        newdt = datetime.datetime.fromtimestamp( now, datetime.timezone.utc)
    elif isinstance(dt, datetime.datetime):  # 日期格式,
        newdt = dt
    elif isinstance(dt,datetime.date):       # 只有日期
        tt = datetime.time(23, 59, 59, tzinfo=oldtz)
        newdt = datetime.datetime.combine(dt, tt)
    elif isinstance(dt, datetime.time):       #只有时间
        newdt = datetime.utcnow()
        newdt = newdt.replace(hour=dt.hour, minute=dt.minute, second=dt.second, tzinfo=oldtz)
    elif isinstance(dt, (int, float)):  # 数字,就是 timestamp
        newdt = datetime.datetime.fromtimestamp(float(dt), datetime.timezone.utc)
    elif isinstance(dt, str) and len(dt) == 8:
        if ':' in dt:  # 21:55:20
            t = datetime.strptime(dt, '%H:%M:%S')
            newdt = datetime.utcnow()
            newdt = newdt.replace(hour=t.hour, minute=t.minute, second=t.second, tzinfo=utcZone)
        else:  # YYYYmmdd   20160815
            y = int(dt[0:4])
            m = int(dt[4:6])
            d = int(dt[6:8])
            tt = datetime.time(23, 59, 59, tzinfo=oldtz)
            dd = datetime.date(y, m, d)  # date没有时区信息
            newdt = datetime.datetime.combine(dd, tt)

    elif "." in dt and ':' in dt:  # 20180906 16:46:20.157940
        newdt = datetime.datetime.strptime(dt, '%Y%m%d %H:%M:%S.%f')
    elif ':' in dt and not "." in dt:  # 20180906 16:46:20
        newdt = datetime.datetime.strptime(dt, '%Y%m%d %H:%M:%S')
    elif dt.replace(".", '').isdigit():  # timestamp  1536249467.2627187    1536249467
        newdt = datetime.datetime.fromtimestamp(float(dt), datetime.timezone.utc)

    if not isinstance(newdt, datetime.datetime):  # 日期格式,
        print( f" MY_vtFunction 日期转化不对{dt}")
        return

    try:
        newdt = oldtz.localize(newdt)  # 设置时区
    except:
        pass

    utcDateTime = newdt.astimezone(utcZone)  # 再转为UTC标准时间
    newDateTime = newtz.normalize(utcDateTime)  # 转出为 newtz

    # 返回时再把时区信息去掉。
    newDateTime = newDateTime.replace(tzinfo=None)

    if returnStr:  # 返回字符串
        newDateTime = newDateTime.strftime(fmt)
        if withFlag:
            newDateTime = ' '.join([newDateTime, dtEndStr])  # 加上时区标识

    return newDateTime