Enhance Insert Custom Date command by using MS datetime format

Fix #10467, close #10480
pull/10559/head
mere-human 3 years ago committed by Don Ho
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;
constexpr int bufferSize = MAX_PATH;
TCHAR buffer[bufferSize] = {};
int ret = 0;
_snwprintf(buf, sizeof(buf), TEXT("%02d"), st.wDay);
dateTimeStr = stringReplace(dateTimeStr, TEXT("D"), buf);
_snwprintf(buf, sizeof(buf), TEXT("%02d"), st.wHour);
dateTimeStr = stringReplace(dateTimeStr, TEXT("h"), 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.wMinute);
dateTimeStr = stringReplace(dateTimeStr, TEXT("m"), 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);
}
_snwprintf(buf, sizeof(buf), TEXT("%02d"), st.wSecond);
dateTimeStr = stringReplace(dateTimeStr, TEXT("s"), buf);
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 dateTimeStr;
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…
Cancel
Save