关于CTime::Format在Unicode下的输出问题及解决办法

    旧有程序,在处理CTime的格式化时,经常会使用Format函数进行输出。
    普通情况下不会有问题。但最近改Bug,在旧控件中碰到一个特殊情况,发现其缺陷。

[具体状况]
    用MFC编写的OCX中,有如下简单代码:
    CTime t = CTime::GetCurrentTime();
    CString sTime = t.Format(_T("最近计算时间: %Y,%m,%d %H:%M:%S"));
    ANSI版下,上述代码执行正常,但如果是Unicode版:输出为空串,不正常。
[进一步尝试]
    将格式化串中的中文去掉,改为英文,一切正常。
[查看源码]
    查看CTime::Format的源码,发现其调用的基础函数:
    _tcsftime(szBuffer, _countof(szBuffer), pFormat, ptmTemp)
    看szBuffer和pFormat的类型:TCHAR,感觉应该支持Unicode。
[再次测试]
    另写一个OCX,用Unicode版进行测试,输出是空串。

[仔细来分析原因]
    我们来看看_tcsftime的Unicode版本,对它做个实验:
    struct tm t = { 0, 0, 12, 25, 11, 93 };
    wchar_t wsDest[255];
    wchar_t wsFormat[] = L"最近计算时间: %Y,%m,%d %H:%M:%S";
    size_t l = wcsftime(wsDest,255,wsFormat,&t);
    wsDest[l] = L'/0';
   ::MessageBoxW(NULL,wsDest,L"test",MB_OK);
    输出得到:空串。

   将格式串换成英文:
    wchar_t wsFormat[] = L"Last Time: %Y,%m,%d %H:%M:%S";
    输出:Last Time: 1993,12,25 12:00:00

[结论]
    CTime::Format 的 Unicode版居然不支持中文的格式化串。嘿。

[解决办法]
    抛弃CTime这个低级垃圾东东,换上新式武器。
    我另写了一个格式化的函数,为了与以前兼容,我仍接受CTime的输入。

CString CBaseUtil::FormatDateTime(const CTime &t)
{
    CString sRet(_T(""));
    if(!t.GetLocalTm()) return sRet;  //t未初始化,不合法。
    //或者断言 ASSERT(t.GetLocalTm())

    //格式化串的格式可参见VarFormat的帮助
    //如:最近计算时间: yyyy,mm,dd hh:nn:ss
    CString sFormat = sFormat.LoadString(格式化串); 
    COleDateTime dt(t.GetYear(),t.GetMonth(),t.GetDay(),
    t.GetHour(),t.GetMinute(),t.GetSecond());

    COleVariant var(dt);
    BSTR bstrOut = sRet.AllocSysString();
#ifdef _UNICODE
         VarFormat(var,sFormat.GetBuffer(0),0,0,0,&bstrOut);
#else
         USES_CONVERSION;
         VarFormat(var,A2W(sFormat.GetBuffer(0)),0,0,0,&bstrOut);
#endif
         sRet = bstrOut;
         ::SysFreeString(bstrOut);
         return sRet;
}

    好了,上述的做法就OK了,如果不用CTime做参数,那最好,因为CTime
范围也比较窄,可直接使用COleDateTime。

石头 于 2005-10-21

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值