获取COleDateTime :: Format以返回波兰月份“ January”的“ stycznia”而不是“styczeń”

时间:2018-12-09 20:51:34

标签: mfc locale polish coledatetime

我有这种方法可以将语言环境设置为波兰语:

void CMeetingScheduleAssistantApp::SetLocale()
{
    // https://www.microsoft.com/resources/msdn/goglobal/default.mspx#ISO2
    CString strLang[NUM_LANGUAGES] =
    {
        _T("plk")
        // Add more languages here
    };

    _tsetlocale(LC_ALL, strLang[m_eLanguage - LANGUAGE_ENGLISH]);
}

为简洁起见,我删去了其他语言。现在,当我格式化COleDateTime对象并显示月份(例如1月)时,它显示为:

  

styczeń

但是我想显示为:

  

stycznia

是否有语言环境设置来调整COleDateTime::Format方法或语言环境返回的月份值?

否则,我将不得不添加一些手册来覆盖。

我想返回的月份是:

  1. stycznia
  2. lutego
  3. marca
  4. 乌克兰
  5. maja
  6. czerwca
  7. lipca
  8. 塞尔维亚
  9. września
  10. października
  11. listopada
  12. 格鲁迪亚

更新

根据here,它指出:

  

某些语言(例如芬兰语,德语,波兰语和俄语)具有   几种名词形式。如果您打算使用由   系统,请进行语言检查,以确保您在   正确的环境。 Windows既包含主格形式又包含格格形式   波兰和俄罗斯月份的名称; 表格根据   字符串中相对于日期名称的月份名称位置。   Windows以单个字符串返回两种形式,并以null分隔   值。 系统每个月的名称或日期仅包含一种形式   所有其他语言的名称

现在,这就是我实际格式化日期字符串的方式(因为我支持40多种语言,所以有点棘手。所以,(对于英语)我从以下格式字符串开始:

%1 %2!d!-%3!d!
  1. %1
  2. %2!d!第一天的值。
  3. %3!d!第二天值。

如果我的约会需要满足两个月以上的时间,我可以:

%1 %2!d!–%3 %4!d!
  1. %1月份的值。
  2. %2!d!第一天的值。
  3. %3第二个月的值。
  4. %3!d!第二天值。

上面的用法是这样的:

if (datThisMonday.GetMonth() == datEndOfWeek.GetMonth())
{
    strDate.FormatMessage(IDS_STR_TPL_OCLM_WEEK,
            datThisMonday.Format(_T("%B")), datThisMonday.GetDay(), datEndOfWeek.GetDay());
}
else
{
    strDate.FormatMessage(IDS_STR_TPL_OCLM_WEEK2,
            datThisMonday.Format(_T("%B")), datThisMonday.GetDay(),
            datEndOfWeek.Format(_T("%B")), datEndOfWeek.GetDay());
}

对于波兰语,我各自的格式字符串为:

%2!d!-%3!d! %1
%2!d! %1–%4!d! %3

因此,我可以看到,因为我正在使用FormatMessage格式化日期字符串,而仅使用COleDateTime::Format方法来解析 month ,这可能是问题的原因。

由于我在日期字符串中有两个日期,所以我不能只使用一个Date格式化API调用(因为我的日期字符串代表一个星期跨度)。

所以我检查了:

strDate = datThisMonday.Format(_T("%d %B"));

这没什么区别。因此,我尝试了以下方法:

SYSTEMTIME sTime;
datThisMonday.GetAsSystemTime(sTime);
GetDateFormat(GetThreadLocale(), 
              DATE_LONGDATE, 
              &sTime, _T("d MMMM"), 
              strDate.GetBuffer(_MAX_PATH), _MAX_PATH);

没什么区别。它仍然以与以前相同的方式显示日期。即使它正确显示了日期,也不会考虑两个COleDateTime对象的日期范围

困惑。

更新2:

也尝试过:

TCHAR szDate[100] = _T("");
GetDateFormatEx(_T("pl"), NULL, &sTime, _T("ddd MMMM"), szDate, 100, NULL);
AfxMessageBox(szDate);

仅不会显示变体。

更新3

我要显示正确日期的唯一方法是:

GetDateFormatEx(_T("pl"), DATE_LONGDATE, &sTime, NULL, szDate, 100, NULL);

则该月正确。现在我在文章中提到它指出:

  

Windows在单个字符串中返回两种形式,并以null分隔   值。

我什至不知道如何访问它。

2 个答案:

答案 0 :(得分:1)

我遇到了其他问题,但它们与该问题不同,因此我仍将在此处提供答案。

首先,我发现一个document,其中指出您必须在日期中输入d才能显示月份的正确版本。

由于我要显示日期范围,因此我从以下内容开始:

波兰语

模板:%1-%2 日期1:d 日期2:d MMMM

然后我格式化日期:

SYSTEMTIME sysTime;
ENSURE(rDate.GetAsSystemTime(sysTime));
GetDateFormatEx(_T("pl"),
    NULL,
    &sysTime, 
    strDateFormat, 
    strDate.GetBuffer(_MAX_PATH), _MAX_PATH, nullptr);

可以正确显示。如果日期范围跨越两个月,我有:

模板:%1-%2 日期1:d MMMM 日期2:d MMMM

效果很好。

答案 1 :(得分:1)

从 Windows 7 开始,您还可以使用 LOCALE_RETURN_GENITIVE_NAMES 返回月份的所有格名称。运行这个:

const wchar_t localeName[] = L"pl-PL";
for (LCTYPE m = LOCALE_SMONTHNAME1; m <= LOCALE_SMONTHNAME12; ++m) {
  wchar_t buf[1024];
  GetLocaleInfoEx(localeName, m | LOCALE_RETURN_GENITIVE_NAMES, buf, sizeof(buf) / sizeof(*buf));
  std::cout << to_utf8(buf) << '\n';
}

给出以下结果:

stycznia
lutego
marca
kwietnia
maja
czerwca
lipca
sierpnia
września
października
listopada
grudnia

这确实是波兰语中月份的专有属格名称。