Enhance Insert Custom Date command by using MS datetime format
Fix #10467, close #10480
This commit is contained in:
parent
e1e180397f
commit
0ad4912eb0
|
@ -1331,25 +1331,106 @@ int nbDigitsFromNbLines(size_t nbLines)
|
|||
return nbDigits;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr TCHAR timeFmtEscapeChar = 0x1;
|
||||
constexpr TCHAR middayFormat[] = _T("tt");
|
||||
|
||||
// Returns AM/PM string defined by the system locale for the specified time.
|
||||
// This string may be empty or customized.
|
||||
generic_string getMiddayString(const TCHAR* localeName, const SYSTEMTIME& st)
|
||||
{
|
||||
generic_string midday;
|
||||
midday.resize(MAX_PATH);
|
||||
int ret = GetTimeFormatEx(localeName, 0, &st, middayFormat, &midday[0], static_cast<int>(midday.size()));
|
||||
if (ret > 0)
|
||||
midday.resize(ret - 1); // Remove the null-terminator.
|
||||
else
|
||||
midday.clear();
|
||||
return midday;
|
||||
}
|
||||
|
||||
// Replaces conflicting time format specifiers by a special character.
|
||||
bool escapeTimeFormat(generic_string& format)
|
||||
{
|
||||
bool modified = false;
|
||||
for (auto& ch : format)
|
||||
{
|
||||
if (ch == middayFormat[0])
|
||||
{
|
||||
ch = timeFmtEscapeChar;
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
// Replaces special time format characters by actual AM/PM string.
|
||||
void unescapeTimeFormat(generic_string& format, const generic_string& midday)
|
||||
{
|
||||
if (midday.empty())
|
||||
{
|
||||
auto it = std::remove(format.begin(), format.end(), timeFmtEscapeChar);
|
||||
if (it != format.end())
|
||||
format.erase(it, format.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t i = 0;
|
||||
while ((i = format.find(timeFmtEscapeChar, i)) != generic_string::npos)
|
||||
{
|
||||
if (i + 1 < format.size() && format[i + 1] == timeFmtEscapeChar)
|
||||
{
|
||||
// 'tt' => AM/PM
|
||||
format.erase(i, std::size(middayFormat) - 1);
|
||||
format.insert(i, midday);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 't' => A/P
|
||||
format[i] = midday[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generic_string getDateTimeStrFrom(const generic_string& dateTimeFormat, const SYSTEMTIME& st)
|
||||
{
|
||||
generic_string dateTimeStr = dateTimeFormat;
|
||||
dateTimeStr = stringReplace(dateTimeStr, TEXT("Y"), std::to_wstring(st.wYear));
|
||||
wchar_t buf[3];
|
||||
_snwprintf(buf, sizeof(buf), TEXT("%02d"), st.wMonth);
|
||||
dateTimeStr = stringReplace(dateTimeStr, TEXT("M"), buf);
|
||||
const TCHAR* localeName = LOCALE_NAME_USER_DEFAULT;
|
||||
const DWORD flags = 0;
|
||||
|
||||
_snwprintf(buf, sizeof(buf), TEXT("%02d"), st.wDay);
|
||||
dateTimeStr = stringReplace(dateTimeStr, TEXT("D"), buf);
|
||||
constexpr int bufferSize = MAX_PATH;
|
||||
TCHAR buffer[bufferSize] = {};
|
||||
int ret = 0;
|
||||
|
||||
_snwprintf(buf, sizeof(buf), TEXT("%02d"), st.wHour);
|
||||
dateTimeStr = stringReplace(dateTimeStr, TEXT("h"), buf);
|
||||
|
||||
_snwprintf(buf, sizeof(buf), TEXT("%02d"), st.wMinute);
|
||||
dateTimeStr = stringReplace(dateTimeStr, TEXT("m"), buf);
|
||||
// 1. Escape 'tt' that means AM/PM or 't' that means A/P.
|
||||
// This is needed to avoid conflict with 'M' date format that stands for month.
|
||||
generic_string newFormat = dateTimeFormat;
|
||||
const bool hasMiddayFormat = escapeTimeFormat(newFormat);
|
||||
|
||||
_snwprintf(buf, sizeof(buf), TEXT("%02d"), st.wSecond);
|
||||
dateTimeStr = stringReplace(dateTimeStr, TEXT("s"), buf);
|
||||
// 2. Format the time (h/m/s/t/H).
|
||||
ret = GetTimeFormatEx(localeName, flags, &st, newFormat.c_str(), buffer, bufferSize);
|
||||
if (ret != 0)
|
||||
{
|
||||
// 3. Format the date (d/y/g/M).
|
||||
// Now use the buffer as a format string to process the format specifiers not recognized by GetTimeFormatEx().
|
||||
ret = GetDateFormatEx(localeName, flags, &st, buffer, buffer, bufferSize, nullptr);
|
||||
}
|
||||
|
||||
return dateTimeStr;
|
||||
if (ret != 0)
|
||||
{
|
||||
if (hasMiddayFormat)
|
||||
{
|
||||
// 4. Now format only the AM/PM string.
|
||||
const generic_string midday = getMiddayString(localeName, st);
|
||||
generic_string result = buffer;
|
||||
unescapeTimeFormat(result, midday);
|
||||
return result;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -784,7 +784,7 @@ struct NppGUI final
|
|||
generic_string _uriSchemes = TEXT("svn:// cvs:// git:// imap:// irc:// irc6:// ircs:// ldap:// ldaps:// news: telnet:// gopher:// ssh:// sftp:// smb:// skype: snmp:// spotify: steam:// sms: slack:// chrome:// bitcoin:");
|
||||
NewDocDefaultSettings _newDocDefaultSettings;
|
||||
|
||||
generic_string _dateTimeFormat = TEXT("Y-M-D h:m:s");
|
||||
generic_string _dateTimeFormat = TEXT("yyyy-MM-dd HH:mm:ss");
|
||||
bool _dateTimeReverseDefaultOrder = false;
|
||||
|
||||
void setTabReplacedBySpace(bool b) {_tabReplacedBySpace = b;};
|
||||
|
|
|
@ -389,8 +389,8 @@ BEGIN
|
|||
LTEXT "* The modification of this setting needs to restart Notepad++",IDD_STATIC_RESTARTNOTE,110,70,239,20
|
||||
GROUPBOX "Customize insert Date Time",IDC_DATETIMEFORMAT_GB_STATIC,90,97,268,105,BS_CENTER
|
||||
CONTROL "Reverse default date time order (short && long formats)",IDD_DATETIMEFORMAT_REVERSEORDER_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,103,113,241,10
|
||||
RTEXT "Y-M-D h:m:s\nh:m:s D/M/Y\nM D, Y h:m",IDC_STATIC,134,142,77,25
|
||||
LTEXT "1985-10-26 01:24:00\n01:24:00 26/10/1985\n10 26, 1985 01:24",IDC_STATIC,234,142,94,25
|
||||
RTEXT "yyyy-MM-dd HH:mm:ss\nHH:mm:ss dd/MM/yy\nMMM d, yyyy h:m",IDC_STATIC,134,142,77,25
|
||||
LTEXT "1985-10-26 01:24:00\n01:24:00 26/10/85\nOct 26, 1985 1:24",IDC_STATIC,234,142,94,25
|
||||
RTEXT "Custom format:",IDD_DATETIMEFORMAT_STATIC,92,172,71,8
|
||||
EDITTEXT IDC_DATETIMEFORMAT_EDIT,164,170,179,14,ES_AUTOHSCROLL
|
||||
LTEXT "",IDD_DATETIMEFORMAT_RESULT_STATIC,166,187,180,8
|
||||
|
|
Loading…
Reference in New Issue