4 * @brief Implementation of helper functions involving locale
10 #include <Poco/Format.h>
11 #include <Poco/Debugger.h>
12 #include <Poco/Timestamp.h>
16 using Poco::Timestamp;
21 * @brief Get numeric value from an LC_ entry in windows locale (NLS) database
23 static unsigned getLocaleUint(int lctype, int defval)
26 if (!GetLocaleInfo(LOCALE_USER_DEFAULT, lctype, buff, sizeof(buff)/sizeof(buff[0])))
33 * @brief Get numeric value for LOCALE_SGROUPING
35 static unsigned GetLocaleGrouping(int defval)
38 if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, buff, sizeof(buff)/sizeof(buff[0])))
40 // handling for Indic 3;2
41 if (!_tcscmp(buff, _T("3;2;0")))
47 * @brief Print an integer into a CString, in appropriate fashion for locale & user preferences
49 * NB: We are not converting digits from ASCII via LOCALE_SNATIVEDIGITS
50 * So we always use ASCII digits, instead of, eg, the Chinese digits
52 * @param [in] n Number to convert.
53 * @return Converted string.
55 String NumToLocaleStr(int n)
58 _ltot_s(n, numbuff, 10);
59 return GetLocaleStr(numbuff);
63 * @brief Print an integer into a CString, in appropriate fashion for locale & user preferences
65 * NB: We are not converting digits from ASCII via LOCALE_SNATIVEDIGITS
66 * So we always use ASCII digits, instead of, eg, the Chinese digits
68 * @param [in] n Number to convert.
69 * @return Converted string.
71 String NumToLocaleStr(int64_t n)
74 _i64tot_s(n, numbuff, sizeof(numbuff)/sizeof(TCHAR), 10);
75 return GetLocaleStr(numbuff);
79 * @brief Insert commas (or periods) into string, as appropriate for locale & preferences
81 * NB: We are not converting digits from ASCII via LOCALE_SNATIVEDIGITS
82 * So we always use ASCII digits, instead of, eg, the Chinese digits
84 String GetLocaleStr(const TCHAR *str, int decimalDigits)
86 // Fill in currency format with locale info
87 // except we hardcode for no decimal
89 TCHAR SepDefault[] = _T(".");
91 NUMBERFMT NumFormat = { 0 };
92 NumFormat.NumDigits = decimalDigits; // LOCALE_IDIGITS
93 NumFormat.LeadingZero = getLocaleUint(LOCALE_ILZERO, 0);
94 NumFormat.Grouping = GetLocaleGrouping(3);
95 NumFormat.lpDecimalSep = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, DecimalSep, 8) ? DecimalSep : SepDefault;
96 NumFormat.lpThousandSep = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, ThousandSep, 8) ? ThousandSep : SepDefault;
97 NumFormat.NegativeOrder = getLocaleUint(LOCALE_INEGNUMBER , 0);
100 LPTSTR outbuff = &*out.begin(); //GetBuffer(48);
101 int rt = GetNumberFormat(LOCALE_USER_DEFAULT // a predefined value for user locale
102 , 0 // operation option (allow overrides)
103 , str // input number (see MSDN for legal chars)
104 , &NumFormat // formatting specifications
105 , outbuff // output buffer
107 ); // size of output buffer
110 // rt includes terminating zero
115 Debugger::message(format("Error %d in NumToStr()\n", GetLastError()));
122 * @brief Convert unix time to string to show in the GUI.
123 * @param [in] tim Time in seconds since 1.1.1970.
124 * @return Time as a string, proper to show in the GUI.
126 String TimeString(const int64_t * tim)
128 if (tim == nullptr) return _T("---");
130 SYSTEMTIME sysTimeGlobal, sysTime;
132 Timestamp t(*tim * Timestamp::resolution());
136 t.toFileTimeNP((unsigned int&)ft.dwLowDateTime, (unsigned int&)ft.dwHighDateTime);
137 if (!FileTimeToSystemTime(&ft, &sysTimeGlobal) ||
138 !SystemTimeToTzSpecificLocalTime(nullptr, &sysTimeGlobal, &sysTime))
142 int len = GetDateFormat(LOCALE_USER_DEFAULT, 0, &sysTime, nullptr, buff, sizeof(buff)/sizeof(buff[0]));
144 GetTimeFormat(LOCALE_USER_DEFAULT, 0, &sysTime, nullptr, buff + len, sizeof(buff)/sizeof(buff[0]) - len - 1);
148 }; // namespace locality