Skip to content

Commit dacd0ce

Browse files
committed
fix(windows,linux): convert AM/PM pattern from 'tt' to 'a' (#27)
1 parent 7c30d3e commit dacd0ce

File tree

2 files changed

+104
-90
lines changed

2 files changed

+104
-90
lines changed

linux/system_date_time_format_plugin.cc

Lines changed: 68 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -36,120 +36,101 @@ char* trim(char* s) {
3636
char* format_date(const char* date) {
3737
const int BUFFER_LENGTH = strlen(date) * 3 + 1;
3838
char* formatted_date = (char*)malloc(BUFFER_LENGTH);
39-
memset(formatted_date, 0, BUFFER_LENGTH);
40-
39+
if (!formatted_date) return nullptr;
40+
41+
int pos = 0;
4142
int i = 0;
42-
while (date[i] != '\0') {
43-
if (date[i] == '%') {
43+
while (date[i] != '\0' && pos < BUFFER_LENGTH - 11) {
44+
if (date[i] == '%' && date[i + 1] != '\0') {
4445
char specifier = date[i + 1];
46+
const char* replacement = nullptr;
4547
switch (specifier) {
46-
case 'a': strcat(formatted_date, "ddd"); break;
47-
case 'A': strcat(formatted_date, "dddd"); break;
48+
case 'a': replacement = "ddd"; break;
49+
case 'A': replacement = "dddd"; break;
4850
case 'b':
49-
case 'h': strcat(formatted_date, "MMM"); break;
50-
case 'B': strcat(formatted_date, "MMMM"); break;
51-
case 'c': strcat(formatted_date, ""); break;
52-
case 'C': strcat(formatted_date, "yy"); break;
53-
case 'd': strcat(formatted_date, "dd"); break;
54-
case 'D': strcat(formatted_date, "MM/dd/yy"); break;
55-
case 'e': strcat(formatted_date, "d"); break;
56-
case 'F': strcat(formatted_date, "yyyy-MM-dd"); break;
57-
case 'g': strcat(formatted_date, "yy"); break;
58-
case 'G': strcat(formatted_date, "yyyy"); break;
59-
case 'H':
60-
case 'I':
61-
case 'j': strcat(formatted_date, "DDD"); break;
62-
case 'm': strcat(formatted_date, "MM"); break;
63-
case 'M':
64-
case 'n':
65-
case 'p':
66-
case 'r':
67-
case 'R':
68-
case 'S':
69-
case 't':
70-
case 'T':
71-
case 'u':
72-
case 'U':
73-
case 'V':
74-
case 'w':
75-
case 'W':
76-
case 'x':
77-
case 'X': strcat(formatted_date, ""); break;
78-
case 'y': strcat(formatted_date, "yy"); break;
79-
case 'Y': strcat(formatted_date, "yyyy"); break;
80-
case 'z':
81-
case 'Z':
82-
case '%': strcat(formatted_date, ""); break;
83-
default: formatted_date[strlen(formatted_date)] = date[i + 1]; break;
51+
case 'h': replacement = "MMM"; break;
52+
case 'B': replacement = "MMMM"; break;
53+
case 'C': replacement = "yy"; break;
54+
case 'd': replacement = "dd"; break;
55+
case 'D': replacement = "MM/dd/yy"; break;
56+
case 'e': replacement = "d"; break;
57+
case 'F': replacement = "yyyy-MM-dd"; break;
58+
case 'g': replacement = "yy"; break;
59+
case 'G': replacement = "yyyy"; break;
60+
case 'j': replacement = "DDD"; break;
61+
case 'm': replacement = "MM"; break;
62+
case 'y': replacement = "yy"; break;
63+
case 'Y': replacement = "yyyy"; break;
64+
case '%':
65+
formatted_date[pos++] = '%';
66+
break;
67+
default:
68+
formatted_date[pos++] = date[i + 1];
69+
break;
70+
}
71+
if (replacement) {
72+
int len = strlen(replacement);
73+
if (pos + len < BUFFER_LENGTH) {
74+
memcpy(formatted_date + pos, replacement, len);
75+
pos += len;
76+
}
8477
}
8578
i += 2;
8679
}
8780
else {
88-
formatted_date[strlen(formatted_date)] = date[i];
81+
formatted_date[pos++] = date[i];
8982
i++;
9083
}
9184
}
92-
formatted_date[strlen(formatted_date)] = '\0';
85+
formatted_date[pos] = '\0';
9386
return trim(formatted_date);
9487
}
9588

9689
char* format_time(const char* time) {
9790
const int BUFFER_LENGTH = strlen(time) * 3 + 1;
9891
char* formatted_time = (char*)malloc(BUFFER_LENGTH);
99-
memset(formatted_time, 0, BUFFER_LENGTH);
100-
92+
if (!formatted_time) return nullptr;
93+
94+
const int MAX_REPLACEMENT_LENGTH = 10; // "hh:mm:ss a" is the longest
95+
int pos = 0;
10196
int i = 0;
102-
while (time[i] != '\0') {
103-
if (time[i] == '%') {
97+
while (time[i] != '\0' && (time[i] != '%' || time[i + 1] != '\0') && pos < BUFFER_LENGTH - MAX_REPLACEMENT_LENGTH) {
98+
if (time[i] == '%' && time[i + 1] != '\0') {
10499
char specifier = time[i + 1];
100+
const char* replacement = nullptr;
105101
switch (specifier) {
106-
case 'a':
107-
case 'A':
108-
case 'b':
109-
case 'h':
110-
case 'B':
111-
case 'c':
112-
case 'C':
113-
case 'd':
114-
case 'D':
115-
case 'e':
116-
case 'F':
117-
case 'g':
118-
case 'G': strcat(formatted_time, ""); break;
119-
case 'H': strcat(formatted_time, "HH"); break;
120-
case 'I': strcat(formatted_time, "hh"); break;
121-
case 'j':
122-
case 'm': strcat(formatted_time, ""); break;
123-
case 'M': strcat(formatted_time, "mm"); break;
124-
case 'n': strcat(formatted_time, "\n"); break;
125-
case 'p': strcat(formatted_time, "tt"); break;
126-
case 'r': strcat(formatted_time, "hh:mm:ss tt"); break;
127-
case 'R': strcat(formatted_time, "HH:mm"); break;
128-
case 'S': strcat(formatted_time, "ss"); break;
129-
case 't': strcat(formatted_time, "\t"); break;
130-
case 'T': strcat(formatted_time, "HH:mm:ss"); break;
131-
case 'u':
132-
case 'U':
133-
case 'V':
134-
case 'w':
135-
case 'W':
136-
case 'x':
137-
case 'X':
138-
case 'y':
139-
case 'Y':
140-
case 'z':
141-
case 'Z':
142-
case '%': strcat(formatted_time, ""); break;
143-
default: formatted_time[strlen(formatted_time)] = time[i + 1]; break;
102+
case 'H': replacement = "HH"; break;
103+
case 'I': replacement = "hh"; break;
104+
case 'M': replacement = "mm"; break;
105+
case 'n': replacement = "\n"; break;
106+
case 'p': replacement = "a"; break;
107+
case 'r': replacement = "hh:mm:ss a"; break;
108+
case 'R': replacement = "HH:mm"; break;
109+
case 'S': replacement = "ss"; break;
110+
case 't': replacement = "\t"; break;
111+
case 'T': replacement = "HH:mm:ss"; break;
112+
case '%':
113+
formatted_time[pos++] = '%';
114+
break;
115+
default:
116+
formatted_time[pos++] = time[i + 1];
117+
break;
118+
}
119+
if (replacement) {
120+
int len = strlen(replacement);
121+
if (pos + len < BUFFER_LENGTH) {
122+
memcpy(formatted_time + pos, replacement, len);
123+
pos += len;
124+
}
144125
}
145126
i += 2;
146127
}
147128
else {
148-
formatted_time[strlen(formatted_time)] = time[i];
129+
formatted_time[pos++] = time[i];
149130
i++;
150131
}
151132
}
152-
formatted_time[strlen(formatted_time)] = '\0';
133+
formatted_time[pos] = '\0';
153134
return trim(formatted_time);
154135
}
155136

windows/system_date_time_format_plugin.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,45 @@ namespace system_date_time_format {
7979
}
8080

8181
string SystemDateTimeFormatPlugin::getFormat(LCTYPE infoType) {
82-
TCHAR buffer[80];
83-
GetLocaleInfo(LOCALE_USER_DEFAULT, infoType, buffer, 80);
82+
// First, get the required buffer size
83+
int bufferSize = GetLocaleInfo(LOCALE_USER_DEFAULT, infoType, nullptr, 0);
84+
if (bufferSize == 0) {
85+
return "";
86+
}
87+
88+
// Allocate buffer with the required size
89+
TCHAR* buffer = new (std::nothrow) TCHAR[bufferSize];
90+
if (!buffer) {
91+
return "";
92+
}
93+
94+
int result_size = GetLocaleInfo(LOCALE_USER_DEFAULT, infoType, buffer, bufferSize);
95+
if (result_size == 0) {
96+
delete[] buffer;
97+
return "";
98+
}
8499

100+
// Convert to UTF-8
85101
int size = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, nullptr, 0, nullptr, nullptr);
102+
if (size == 0) {
103+
delete[] buffer;
104+
return "";
105+
}
86106
string result(size - 1, 0); // subtract 1 to remove the null terminator
87-
WideCharToMultiByte(CP_UTF8, 0, buffer, -1, &result[0], size, nullptr, nullptr);
107+
int actual_size = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, &result[0], size, nullptr, nullptr);
108+
if (actual_size == 0) {
109+
delete[] buffer;
110+
return "";
111+
}
112+
113+
delete[] buffer;
114+
115+
// Convert Windows 'tt' (A.M./P.M.) pattern to standard 'a' pattern
116+
size_t pos = 0;
117+
while ((pos = result.find("tt", pos)) != string::npos) {
118+
result.replace(pos, 2, "a");
119+
pos += 1;
120+
}
88121

89122
return result;
90123
}

0 commit comments

Comments
 (0)