You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将带时区的文本日期时间转换为ATL/MFC CTime?

嘿,我来帮你搞定这个CTime转换的问题!你遇到的ParseDateTime()失败,大概率是因为COleDateTime的这个方法对带时区偏移和缩写的格式支持不太友好,尤其是这种Sat, 13 Jan 2018 07:54:39 -0500 (EST)的标准RFC格式,咱们可以用两种靠谱的方案来解决:

方案1:用ATL的CAtlDateTimeParser(简单快捷)

ATL的CAtlDateTimeParser对各种日期时间格式支持更灵活,包括带时区偏移的情况。你只需要先清理掉字符串里的冗余部分(比如末尾的(EST)),然后指定匹配的格式字符串就能解析:

#include <atldatetime.h>

CTime DateTimeString2CTime(CString DateTimeStr) {
    // 先移除末尾的时区缩写括号部分,比如 "(EST)"
    int parenPos = DateTimeStr.Find(_T(" ("));
    if (parenPos != -1) {
        DateTimeStr = DateTimeStr.Left(parenPos).Trim();
    }

    CAtlDateTimeParser parser;
    CAtlDateTime dt;

    // 尝试匹配带星期的格式:"Sat, 13 Jan 2018 07:54:39 -0500"
    if (parser.Parse(DateTimeStr, dt, _T("%a, %d %b %Y %H:%M:%S %z"))) {
        return CTime(dt.GetYear(), dt.GetMonth(), dt.GetDay(), 
                     dt.GetHour(), dt.GetMinute(), dt.GetSecond());
    }

    // 尝试不带星期的格式:"13 Jan 2018 07:54:39 -0500"
    if (parser.Parse(DateTimeStr, dt, _T("%d %b %Y %H:%M:%S %z"))) {
        return CTime(dt.GetYear(), dt.GetMonth(), dt.GetDay(), 
                     dt.GetHour(), dt.GetMinute(), dt.GetSecond());
    }

    // 兼容GMT/UTC格式:"13 Jan 2018 07:54:39 GMT"
    if (parser.Parse(DateTimeStr, dt, _T("%d %b %Y %H:%M:%S GMT"))) {
        return CTime(dt.GetYear(), dt.GetMonth(), dt.GetDay(), 
                     dt.GetHour(), dt.GetMinute(), dt.GetSecond());
    }

    // 解析失败返回无效CTime(默认构造的CTime代表1970-01-01 00:00:00 UTC)
    return CTime();
}

方案2:手动解析字符串(兼容性拉满,不依赖ATL)

如果你的项目不想依赖ATL,手动解析是更稳妥的选择,完全可控,不受系统区域设置影响:

CTime DateTimeString2CTime(CString DateTimeStr) {
    // 1. 清理字符串:移除开头的星期和末尾的时区缩写括号
    DateTimeStr.Trim();
    int commaPos = DateTimeStr.Find(_T(","));
    if (commaPos != -1) {
        DateTimeStr = DateTimeStr.Mid(commaPos + 1).Trim();
    }
    int parenPos = DateTimeStr.Find(_T(" ("));
    if (parenPos != -1) {
        DateTimeStr = DateTimeStr.Left(parenPos).Trim();
    }

    // 2. 拆分日期时间部分和时区部分
    CString dateTimePart, tzPart;
    int lastSpacePos = DateTimeStr.ReverseFind(_T(' '));
    if (lastSpacePos != -1) {
        dateTimePart = DateTimeStr.Left(lastSpacePos).Trim();
        tzPart = DateTimeStr.Mid(lastSpacePos + 1).Trim();
    } else {
        dateTimePart = DateTimeStr;
        tzPart = _T("0000"); // 默认按UTC处理
    }

    // 3. 解析日期时间字段:"13 Jan 2018 07:54:39"
    int day, year, hour, min, sec;
    TCHAR monthAbbr[4];
    if (_stscanf_s(dateTimePart, _T("%d %3s %d %d:%d:%d"), 
                   &day, monthAbbr, _countof(monthAbbr), 
                   &year, &hour, &min, &sec) != 6) {
        return CTime(); // 解析失败返回无效时间
    }

    // 4. 月份缩写转数字
    static const struct {
        LPCTSTR abbr;
        int month;
    } monthMap[] = {
        {_T("Jan"), 1}, {_T("Feb"), 2}, {_T("Mar"), 3}, {_T("Apr"), 4},
        {_T("May"), 5}, {_T("Jun"), 6}, {_T("Jul"), 7}, {_T("Aug"), 8},
        {_T("Sep"), 9}, {_T("Oct"), 10}, {_T("Nov"), 11}, {_T("Dec"), 12}
    };
    int month = 0;
    for (int i = 0; i < _countof(monthMap); ++i) {
        if (_tcsicmp(monthAbbr, monthMap[i].abbr) == 0) {
            month = monthMap[i].month;
            break;
        }
    }
    if (month == 0) {
        return CTime();
    }

    // 5. 处理时区偏移,转换为UTC时间(如需本地时间可调用UTCToLocal())
    int tzHours = 0, tzMins = 0;
    if (tzPart.GetLength() == 5) {
        // 处理偏移格式:"-0500"或"+0800"
        TCHAR sign = tzPart[0];
        _stscanf_s(tzPart.Mid(1), _T("%2d%2d"), &tzHours, &tzMins);
        if (sign == _T('-')) {
            tzHours = -tzHours;
            tzMins = -tzMins;
        }
    } else {
        // 处理时区缩写:EST/GMT/UTC等
        static const struct {
            LPCTSTR tz;
            int offsetHours;
        } tzMap[] = {
            {_T("EST"), -5}, {_T("EDT"), -4}, {_T("CST"), -6}, {_T("CDT"), -5},
            {_T("MST"), -7}, {_T("MDT"), -6}, {_T("PST"), -8}, {_T("PDT"), -7},
            {_T("GMT"), 0}, {_T("UTC"), 0}
        };
        for (int i = 0; i < _countof(tzMap); ++i) {
            if (_tcsicmp(tzPart, tzMap[i].tz) == 0) {
                tzHours = tzMap[i].offsetHours;
                tzMins = 0;
                break;
            }
        }
    }

    // 构造时间并调整时区:原时间是带时区的,转UTC需要抵消偏移
    CTime temp(year, month, day, hour, min, sec);
    temp += CTimeSpan(tzHours, tzMins, 0, 0);

    // 如果需要转换为本地时间,取消下面注释
    // temp = temp.UTCToLocal();

    return temp;
}

注意点

  • CTime本身内部存储的是UTC时间戳,调用GetHour()等方法时会自动转换为本地时区时间(除非你用GetUTC*()方法)。
  • 如果你的需求是直接保留原字符串中的时分秒(不做时区转换),可以跳过方案2中的时区偏移调整步骤,直接返回构造的CTime(year, month, day, hour, min, sec)。

内容的提问来源于stack exchange,提问作者Michael Haephrati

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:44:03