| 9225 | } |
| 9226 | |
| 9227 | VarSizeType GetDateTimeBIV(LPTSTR aBuf, LPTSTR aVarName) |
| 9228 | { |
| 9229 | if (!aBuf) |
| 9230 | return 6; // Since only an estimate is needed in this mode, return the maximum length of any item. |
| 9231 | |
| 9232 | aVarName += 2; // Skip past the "A_". |
| 9233 | |
| 9234 | // The current time is refreshed only if it's been a certain number of milliseconds since |
| 9235 | // the last fetch of one of these built-in time variables. This keeps the variables in |
| 9236 | // sync with one another when they are used consecutively such as this example: |
| 9237 | // Var := A_Hour ':' A_Min ':' A_Sec |
| 9238 | // Using GetTickCount() because it's very low overhead compared to the other time functions: |
| 9239 | static DWORD sLastUpdate = 0; // Static should be thread + recursion safe in this case. |
| 9240 | static SYSTEMTIME sST = {0}; // Init to detect when it's empty. |
| 9241 | BOOL is_msec = !_tcsicmp(aVarName, _T("MSec")); // Always refresh if it's milliseconds, for better accuracy. |
| 9242 | DWORD now_tick = GetTickCount(); |
| 9243 | if (is_msec || now_tick - sLastUpdate > 50 || !sST.wYear) // See comments above. |
| 9244 | { |
| 9245 | GetLocalTime(&sST); |
| 9246 | sLastUpdate = now_tick; |
| 9247 | } |
| 9248 | |
| 9249 | if (is_msec) |
| 9250 | return _stprintf(aBuf, _T("%03d"), sST.wMilliseconds); |
| 9251 | |
| 9252 | TCHAR second_letter = ctoupper(aVarName[1]); |
| 9253 | switch(ctoupper(aVarName[0])) |
| 9254 | { |
| 9255 | case 'Y': |
| 9256 | switch(second_letter) |
| 9257 | { |
| 9258 | case 'D': // A_YDay |
| 9259 | return _stprintf(aBuf, _T("%d"), GetYDay(sST.wMonth, sST.wDay, IS_LEAP_YEAR(sST.wYear))); |
| 9260 | case 'W': // A_YWeek |
| 9261 | return GetISOWeekNumber(aBuf, sST.wYear |
| 9262 | , GetYDay(sST.wMonth, sST.wDay, IS_LEAP_YEAR(sST.wYear)) |
| 9263 | , sST.wDayOfWeek); |
| 9264 | default: // A_Year/A_YYYY |
| 9265 | return _stprintf(aBuf, _T("%d"), sST.wYear); |
| 9266 | } |
| 9267 | // No break because all cases above return: |
| 9268 | //break; |
| 9269 | case 'M': |
| 9270 | switch(second_letter) |
| 9271 | { |
| 9272 | case 'D': // A_MDay (synonymous with A_DD) |
| 9273 | return _stprintf(aBuf, _T("%02d"), sST.wDay); |
| 9274 | case 'I': // A_Min |
| 9275 | return _stprintf(aBuf, _T("%02d"), sST.wMinute); |
| 9276 | default: // A_MM and A_Mon (A_MSec was already completely handled higher above). |
| 9277 | return _stprintf(aBuf, _T("%02d"), sST.wMonth); |
| 9278 | } |
| 9279 | // No break because all cases above return: |
| 9280 | //break; |
| 9281 | case 'D': // A_DD (synonymous with A_MDay) |
| 9282 | return _stprintf(aBuf, _T("%02d"), sST.wDay); |
| 9283 | case 'W': // A_WDay |
| 9284 | return _stprintf(aBuf, _T("%d"), sST.wDayOfWeek + 1); |
no test coverage detected