zoukankan      html  css  js  c++  java
  • 关于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

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/tiger119/archive/2005/10/22/513526.aspx

    ==========================

    补充

    其实COleDateTime的Format也存在同样的问题,原因是

        _LocaleUpdate _loc_update(plocinfo);

        return _wcsftime_l_stat(
                wstring,
                maxsize,
                wformat,
                timeptr,
                _loc_update.GetLocaleT());

    //////

    然后会导致

    static size_t __cdecl _wcsftime_l_stat中

    //    if (_ERRCHECK_EINVAL_ERANGE(_wcstombs_s_l(NULL, format, flen * 2, wformat, flen * 2 - 1, plocinfo)) != 0)
    //    {
    //        goto done;
    //    }

    这一句会错误。

  • 相关阅读:
    MySql基础-1
    ClearSilver模板编程概述_转
    ehcache memcache redis 三大缓存男高音_转
    memcached完全剖析--1. memcached的基础 _转
    小组的创建
    现代软件工程 第7-9章作业
    现代软件工程 第3~6章作业
    现代软件工程作业 第二章 Github的使用
    现代软件工程作业-- GitHub的学习
    现代软件工程作业 GitHub的学习
  • 原文地址:https://www.cnblogs.com/kevinzhwl/p/3878973.html
Copyright © 2011-2022 走看看