none
日付形式のローカライズ RRS feed

  • 質問

  • お世話になります。

    日付データをCOleDateTimeクラスを利用しています。

    このデータをローカライズした形式に変換したいと思っているですが、
    もっというと、地域と言語で設定されている日付形式で取得したいともっています。
    どのような方法がありますでしょうか。

    現在、日本語OSの環境ですが、

    dtToday.Format(_T("%x"));の戻り値は、"10/21/14" となります。

    dtTodya.Format(VAR_DATEVALUEONLY);の戻り値は、2014/10/21となります。
    この戻り値は、地域と言語の「日付(短い形式)」と連動しています。

    が、「日付(長い形式)」などとの連動する方法がわかりません。


    2014年10月21日 2:10

回答

  • まずとっちゃんさんの提案されたGetDateFormat / GetTimeFormatは古く、Windows Vista以降を動作対象とするのであればGetDateFormatEx / GetTimeFormatExが推奨されています。使い方としてはGetLocaleInfoEx(GetLocaleInfo)で書式を取得しそれを第4引数lpFormatに与えるわけです。

    その上で短い時刻はWindows 7で導入されたものです。GetLocaleInfoEx()に与えるLCTypeとしてはLOCALE_SSHORTTIMEとなります。ここで説明されているように短い時刻とは主に秒を省いたものとなるとのことです。

    以上を踏まえて

    // Windows Vista以前も意識して秒を省く
    TCHAR shortTime[80];
    GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, nullptr, nullptr, shortTime, _countof(shortTime));
    
    // Windows 7以降を対象に短い時刻を取得する
    wchar_t shortTimeFormat[80];
    GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SSHORTTIME, shortTimeFormat, _countof(shortTimeFormat));
    wchar_t shortTime[80];
    GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, nullptr, shortTimeFormat, shortTime, _countof(shortTime));

    といったところでしょうか。

    GetThreadLocale()についてはWindows APIのロケール状態が得られるものです。対してstrftime()はCRT; C RunTime libraryですので調べる相手が異なります。また日本語の翻訳は変ですがsetlocale()の英語ページには

    At program startup, the equivalent of the following statement is executed:
    setlocale( LC_ALL, "C" );

    と書かれています。setlocale()すべきでしょう。

    • 回答としてマーク Brillia 2014年10月22日 0:39
    2014年10月21日 7:53

すべての返信

  • COleDateTime(OLEのdate型) に限らず、VARIANT 型でやり取りしているデータ型は、ローカライズ書式をサポートしていません。

    ですので、画面表示のためにローカライズして表示したい場合は、COleDateTime(OLEのdate型)から、SYSTEMTIME に変換し、GetDateFormat API などを使って表示していくことになります。

    時間表示の場合は、GetTimeFormat API などを使います。


    とっちゃん@わんくま同盟, Microsoft MVP for Visual C++ (Oct 2005-) http://blogs.wankuma.com/tocchann/

    2014年10月21日 2:45
  • COleDateTime::Format()にはstrftime()が使われるためそちらを参照するように記載されています。strftime()には

    %x
    現在のロケールの日付の表現

    とあります。ではなぜ "10/21/14" となってしまうのか…簡単なことで現在のロケールが日本語に設定されていないからです。setlocale()で現在のロケールを設定することで意図通りの結果が得られます。

    _tsetlocale(LC_ALL, _T(""));

    2014年10月21日 4:29
  • ご返事ありがとうございます。

    質問が2つあります。

    1.日付、時刻のローカライズについて

     確かに、GetDateFormat、GetTimeFormat APIを使用することで、取得できました。
     が、時刻(短い形式)のパターンが取得できません。何か方法がありますか。

    2.現在のロケールについて
     WINAPIのGetThreadLocal()では、「1041」が返ってきますが、
     2-1.C++ライブラリでは、無条件でロケールが「米国」で初期化されているということなのでしょうか。
     // _tsetlocale(LC_ALL, _T(""));って、現在のシステム既定のロケールで設定しているのですよね。

     2-2.グローバリゼーションを目指すアプリケーションでは、C++ライブラリを使用する前に、_tsetlocale(LC_ALL, _T(""));を必ず実行するべきか

    教えてください

     

     

     

     

    2014年10月21日 5:07
  • 1.

    確か短い時刻は、DATE_NOSECONDS となっていた記憶がありますが、ちょっと定かではないです。。。ざっくり見たところ、ちゃんとしたやり方も見当たらなかった。。。

    で、自分はどうしているか?というと、SHFormatDateTime という、そのうち消える予定になってしまったShellAPIを使っていましたw

    2.

    GetThreadLocale は、Windows API で、現在のスレッドのロケールを取得するものです。C/C++ ランタイムのロケール設定とは無関係です。

    C/C++側をこれに合わせたい場合は、

    TCHAR localeName[MAX_PATH];
    GetLocaleInfo( GetThreadLocale(), LOCALE_SENGLANGUAGE, localeName, MAX_PATH );
    _tsetlocale( LC_ALL, localeName );
    

    という感じで、スレッドが起動したところで呪文を唱えます。コンソールで、wcout や wprintf などを使う場合も同様。
    通常は、その時のユーザー設定を反映させればよいので、GetThreadLocale() ではなく、LOCALE_USER_DEFAULT を使うことが多いと思います。


    とっちゃん@わんくま同盟, Microsoft MVP for Visual C++ (Oct 2005-) http://blogs.wankuma.com/tocchann/

    2014年10月21日 7:50
  • まずとっちゃんさんの提案されたGetDateFormat / GetTimeFormatは古く、Windows Vista以降を動作対象とするのであればGetDateFormatEx / GetTimeFormatExが推奨されています。使い方としてはGetLocaleInfoEx(GetLocaleInfo)で書式を取得しそれを第4引数lpFormatに与えるわけです。

    その上で短い時刻はWindows 7で導入されたものです。GetLocaleInfoEx()に与えるLCTypeとしてはLOCALE_SSHORTTIMEとなります。ここで説明されているように短い時刻とは主に秒を省いたものとなるとのことです。

    以上を踏まえて

    // Windows Vista以前も意識して秒を省く
    TCHAR shortTime[80];
    GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, nullptr, nullptr, shortTime, _countof(shortTime));
    
    // Windows 7以降を対象に短い時刻を取得する
    wchar_t shortTimeFormat[80];
    GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SSHORTTIME, shortTimeFormat, _countof(shortTimeFormat));
    wchar_t shortTime[80];
    GetTimeFormatEx(LOCALE_NAME_USER_DEFAULT, 0, nullptr, shortTimeFormat, shortTime, _countof(shortTime));

    といったところでしょうか。

    GetThreadLocale()についてはWindows APIのロケール状態が得られるものです。対してstrftime()はCRT; C RunTime libraryですので調べる相手が異なります。また日本語の翻訳は変ですがsetlocale()の英語ページには

    At program startup, the equivalent of the following statement is executed:
    setlocale( LC_ALL, "C" );

    と書かれています。setlocale()すべきでしょう。

    • 回答としてマーク Brillia 2014年10月22日 0:39
    2014年10月21日 7:53
  • GetLocaleInfoExで、「月/日」 のみのフォーマットが見当たりませんでした。

    GetDateFormatEx では、DATE_YEARMONTHはありますが、DATE_MONTHDAYはありません。

    何か方法がありますでしょうか。短い形式、長い形式それぞれで取得したいのですが。。。

    2014年10月21日 9:33
  • GetLocaleInfoExで、「月/日」 のみのフォーマットが見当たりませんでした。
    短い形式とは質問者さんが念じるものではなく利用者がコントロールパネルで設定するものです。日本語環境に於ける既定値は「yyyy/MM/dd」であり年号が含まれます。ちなみにLOCALE_SSHORTDATEです。
    2014年10月21日 9:46
  • ご返事ありがとうございました。

    理解できました。

    2014年10月22日 0:39