#include "stdafx.h" #include "ToolUnits.h" #include #include #include #include #include #include #include CToolUnits::CToolUnits() { } CToolUnits::~CToolUnits() { } std::string CToolUnits::timeToString(ULONGLONG time) { ULONGLONG time1, time2; time1 = time / 1000000000; time2 = time % 1000000000; char buffer1[256], buffer[128]; struct tm timeinfo; time_t t = time_t(time1); localtime_s(&timeinfo, &t); strftime(buffer, 128, "%Y-%m-%d %H:%M:%S", &timeinfo); sprintf_s(buffer1, 256, "%s.%lld", buffer, time2); return std::string(buffer1); } std::string CToolUnits::timeToString2(ULONGLONG time) { ULONGLONG time1; time1 = time / 1000; char buffer[256]; struct tm timeinfo; time_t t = time_t(time1); localtime_s(&timeinfo, &t); strftime(buffer, 128, "%Y-%m-%d %H:%M:%S", &timeinfo); return std::string(buffer); } std::string CToolUnits::timeToString3(ULONGLONG time) { ULONGLONG time1; int ms; time1 = time / 1000; ms = time % 1000; char buffer1[256], buffer[128]; struct tm timeinfo; time_t t = time_t(time1); localtime_s(&timeinfo, &t); strftime(buffer, 128, "%Y-%m-%d %H:%M:%S", &timeinfo); sprintf_s(buffer1, 256, "%s.%03d", buffer, ms); return std::string(buffer1); } ULONGLONG CToolUnits::stringToTime(const char* pszTime) { struct tm tm; memset(&tm, 0, sizeof(tm)); sscanf_s(pszTime, "%d-%d-%d %d:%d:%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec); tm.tm_year -= 1900; tm.tm_mon--; return mktime(&tm) * 1000; } ULONGLONG CToolUnits::getTimestamp() { // ·µ»ØºÁÃëÊýµÄ°æ±¾ auto now = std::chrono::system_clock::now(); auto ms = std::chrono::time_point_cast(now); return static_cast(ms.time_since_epoch().count()); } time_t CToolUnits::getUnixTimestamp() { // ·µ»ØÃëÊýµÄ°æ±¾ auto now = std::chrono::system_clock::now(); return std::chrono::system_clock::to_time_t(now); } void CToolUnits::createDir(const char* pszDir) { if (isDirectory(std::string(pszDir))) { return; } CString strDir = pszDir; int lastIndex = 0; int index = strDir.Find(_T("\\"), lastIndex); while (index > 0) { CString strTempDir = strDir.Left(index); CreateDirectory(strTempDir, NULL); lastIndex = index + 1; index = strDir.Find(_T("\\"), lastIndex); } CreateDirectory(strDir, NULL); } CString& CToolUnits::floatToString1(float value, CString& strOut) { strOut.Format(_T("%.1f"), value); return strOut; } CString& CToolUnits::floatToString3(float value, CString& strOut) { strOut.Format(_T("%.3f"), value); return strOut; } BOOL CToolUnits::copyTextToClipboard(CWnd* pWnd, const CString& strText) { if (OpenClipboard(pWnd->GetSafeHwnd())) { EmptyClipboard(); HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (strText.GetLength() + 1) * sizeof(TCHAR)); if (hglbCopy == NULL) { CloseClipboard(); return FALSE; } LPTSTR lptstrCopy = (LPTSTR)GlobalLock(hglbCopy); strcpy_s(lptstrCopy, strText.GetLength()+1, strText); GlobalUnlock(hglbCopy); SetClipboardData(CF_TEXT, hglbCopy); CloseClipboard(); GlobalFree(hglbCopy); return TRUE; } return FALSE; } std::string CToolUnits::getCurrentExePath() { char path[MAX_PATH]; GetModuleFileName(NULL, path, MAX_PATH); std::string exePath(path); return exePath.substr(0, exePath.find_last_of("\\/")); } bool CToolUnits::isFile(const std::string& path) { DWORD attributes = GetFileAttributes(path.c_str()); return (attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY)); } bool CToolUnits::isDirectory(const std::string& path) { DWORD attributes = GetFileAttributes(path.c_str()); return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY)); } int CToolUnits::toInt32(const char* pBuffer) { return (pBuffer[0] & 0xff) | ((pBuffer[1] & 0xff) << 8) | ((pBuffer[2] & 0xff) << 16) | ((pBuffer[3] & 0xff) << 24); } int CToolUnits::toInt16(const char* pBuffer) { return (pBuffer[0] & 0xff) | (pBuffer[1] & 0xff) << 8; } BOOL CToolUnits::getBit(const char c, int index) { switch (index) { case 0: return c & 0x01; break; case 1: return c & 0x02; break; case 2: return c & 0x04; break; case 3: return c & 0x08; break; case 4: return c & 0x10; break; case 5: return c & 0x20; break; case 6: return c & 0x40; break; case 7: return c & 0x80; break; default: break; } return FALSE; } void CToolUnits::setBit(char* p, int index) { int byteIndex = 0; byte b = 0; if (index >= 8) byteIndex = 1; switch (index) { case 0: case 8: b = 0x1; break; case 1: case 9: b = 0x2; break; case 2: case 0xA: b = 0x4; break; case 3: case 0xB: b = 0x8; break; case 4: case 0xC: b = 0x10; break; case 5: case 0xD: b = 0x20; break; case 6: case 0xE: b = 0x40; break; case 7: case 0xF: b = 0x80; break; default: break; } p[byteIndex] = b; } void CToolUnits::setDlgItemDouble(CWnd* pWnd, int nCtrlId, double value) { CString strText; strText.Format(_T("%.03f"), value); pWnd->SetDlgItemText(nCtrlId, strText); } std::vector CToolUnits::GetFileNamesInDirectory(const CString& strFolderPath, const CString& strExtension) { std::vector fileNames; // È·±£Ä¿Â¼Â·¾¶×îºóÓз´Ð±¸Ü CString strSearchPath = strFolderPath; if (strSearchPath[strSearchPath.GetLength() - 1] != '\\') { strSearchPath += '\\'; } CString finalExtension = strExtension; if (finalExtension.Find('.') == -1) { finalExtension = '.' + finalExtension; } strSearchPath += "*" + finalExtension; std::unique_ptr finder = std::make_unique(); BOOL bWorking = finder->FindFile(strSearchPath); // ±éÀúÎļþ¼Ð while (bWorking) { bWorking = finder->FindNextFile(); if (!finder->IsDirectory()) { CString fileName = finder->GetFileName(); int dotPos = fileName.ReverseFind('.'); if (dotPos != -1) { fileName = fileName.Left(dotPos); } fileNames.push_back(fileName); } } return fileNames; } std::string CToolUnits::getRecipePath() { return getCurrentExePath() + "\\Recipe"; } std::string CToolUnits::getCurrentTimeString() { struct tm ltm; time_t now = time(0); localtime_s(<m, &now); // ʹÓð²È«µÄ localtime_s º¯Êý char buffer[256]; sprintf_s(buffer, sizeof(buffer), "%04d-%02d-%02d %02d:%02d:%02d", ltm.tm_year + 1900, ltm.tm_mon + 1, ltm.tm_mday, ltm.tm_hour, ltm.tm_min, ltm.tm_sec); return std::string(buffer); } bool CToolUnits::startsWith(const std::string& str, const std::string& prefix) { return str.size() >= prefix.size() && str.compare(0, prefix.size(), prefix) == 0; } std::string& CToolUnits::toHexString(int value, std::string& strOut) { std::stringstream ss; ss << std::hex << value; strOut = ss.str(); return strOut; } void CToolUnits::convertString(const char* pszBuffer, int size, std::string& strOut) { strOut.clear(); int nLength = 0; for (int i = 0; i < size; i++) { if (pszBuffer[i] == '\0') break; nLength++; } if (nLength > 0) { strOut = std::string(pszBuffer, nLength); } } // FILETIME(UTC) -> time_point std::chrono::system_clock::time_point CToolUnits::FileTimeToTimePointUTC(const FILETIME& ftUtc) { ULARGE_INTEGER ull; ull.LowPart = ftUtc.dwLowDateTime; ull.HighPart = ftUtc.dwHighDateTime; // 1601-01-01 µ½ 1970-01-01 µÄ 100ns tick constexpr unsigned long long EPOCH_DIFF_100NS = 116444736000000000ULL; unsigned long long t100 = ull.QuadPart - EPOCH_DIFF_100NS; // 1970ÒÔÀ´ 100ns // ±ÜÃâÒç³ö£º100ns -> us unsigned long long us = t100 / 10ULL; return std::chrono::system_clock::time_point(std::chrono::microseconds(us)); } // ´Ó CDateTimeCtrl È¡±¾µØÊ±¼ä²¢×ªÎª UTC time_point // ·µ»Ø false ±íʾ¿Ø¼þÊÇ¡°ÎÞÖµ¡±(DTS_SHOWNONE / GDT_NONE) »òת»»Ê§°Ü bool CToolUnits::GetCtrlTimeUtc(const CDateTimeCtrl& ctrl, std::chrono::system_clock::time_point& outUtc) { SYSTEMTIME stLocal{}; DWORD rc = const_cast(ctrl).GetTime(&stLocal); // MFC Ô­ÐÍÐèÒª·Çconst if (rc != GDT_VALID) return false; // GDT_NONE SYSTEMTIME stUtc{}; if (!TzSpecificLocalTimeToSystemTime(nullptr, &stLocal, &stUtc)) return false; FILETIME ftUtc{}; if (!SystemTimeToFileTime(&stUtc, &ftUtc)) return false; outUtc = FileTimeToTimePointUTC(ftUtc); return true; } // ÈôÄãµÄÈÕÆÚ¿Ø¼þÖ»ÏÔʾ¡°ÈÕÆÚ²»ÏÔʾʱ¼ä¡±£¬Ïë°Ñ From µ÷Õûµ½ 00:00:00 / To µ÷Õûµ½ 23:59:59.999£º bool CToolUnits::GetCtrlDateRangeUtc_StartOfDay(const CDateTimeCtrl& ctrl, std::chrono::system_clock::time_point& outUtc) { SYSTEMTIME st{}; DWORD rc = const_cast(ctrl).GetTime(&st); if (rc != GDT_VALID) return false; st.wHour = 0; st.wMinute = 0; st.wSecond = 0; st.wMilliseconds = 0; SYSTEMTIME stUtc{}; if (!TzSpecificLocalTimeToSystemTime(nullptr, &st, &stUtc)) return false; FILETIME ftUtc{}; if (!SystemTimeToFileTime(&stUtc, &ftUtc)) return false; outUtc = FileTimeToTimePointUTC(ftUtc); return true; } bool CToolUnits::GetCtrlDateRangeUtc_EndOfDay(const CDateTimeCtrl& ctrl, std::chrono::system_clock::time_point& outUtc) { SYSTEMTIME st{}; DWORD rc = const_cast(ctrl).GetTime(&st); if (rc != GDT_VALID) return false; st.wHour = 23; st.wMinute = 59; st.wSecond = 59; st.wMilliseconds = 999; SYSTEMTIME stUtc{}; if (!TzSpecificLocalTimeToSystemTime(nullptr, &st, &stUtc)) return false; FILETIME ftUtc{}; if (!SystemTimeToFileTime(&stUtc, &ftUtc)) return false; outUtc = FileTimeToTimePointUTC(ftUtc); return true; } // ---------- ±¾µØ SYSTEMTIME -> UTC time_point ---------- std::chrono::system_clock::time_point CToolUnits::LocalSTtoUtcTP(const SYSTEMTIME& stLocal) { SYSTEMTIME stUtc{}; if (!TzSpecificLocalTimeToSystemTime(nullptr, &stLocal, &stUtc)) throw std::runtime_error("TzSpecificLocalTimeToSystemTime failed"); FILETIME ftUtc{}; if (!SystemTimeToFileTime(&stUtc, &ftUtc)) throw std::runtime_error("SystemTimeToFileTime failed"); return FileTimeToTimePointUTC(ftUtc); } // Éú³É±¾µØ SYSTEMTIME SYSTEMTIME CToolUnits::MakeLocalST(int y, int m, int d, int hh, int mi, int ss, int ms) { SYSTEMTIME st{}; st.wYear = (WORD)y; st.wMonth = (WORD)m; st.wDay = (WORD)d; st.wHour = (WORD)hh; st.wMinute = (WORD)mi; st.wSecond = (WORD)ss; st.wMilliseconds = (WORD)ms; return st; } // ÈòÄê / ÔÂÌìÊý bool CToolUnits::IsLeap(int y) { return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0); } int CToolUnits::DaysInMonth(int y, int m) { static const int d[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; return (m == 2) ? d[m] + (IsLeap(y) ? 1 : 0) : d[m]; } // ±¾µØ¡°½ñÌ족µÄÄêÔÂÈÕ void CToolUnits::GetTodayYMD_Local(int& y, int& m, int& d) { SYSTEMTIME now{}; GetLocalTime(&now); y = now.wYear; m = now.wMonth; d = now.wDay; } // ±¾µØÈÕÀúÉϼõ n Ì죨ÈÔÊDZ¾µØ Y/M/D£© void CToolUnits::LocalCalendarMinusDays(int& y, int& m, int& d, int nDays) { std::tm t{}; t.tm_year = y - 1900; t.tm_mon = m - 1; t.tm_mday = d; t.tm_hour = 0; t.tm_min = 0; t.tm_sec = 0; t.tm_mday -= nDays; (void)std::mktime(&t); // °´±¾µØÊ±Çø¹éÒ»»¯ y = t.tm_year + 1900; m = t.tm_mon + 1; d = t.tm_mday; } // ====== ºËÐÄ£º¼ÆËãÔ¤ÉèÇø¼äµÄ UTC [from, to] ====== // ÓïÒ壺 // - Today : ±¾µØ¡°½ñÌ족00:00:00.000 ¡« ½ñÌì 23:59:59.999 // - Last7Days : ±¾µØ¡°6 Ììǰ¡±00:00:00.000 ¡« ½ñÌì 23:59:59.999£¨¹² 7 ¸ö×ÔÈ»ÈÕ£¬º¬½ñÌ죩 // - ThisMonth : ±¾µØ¡°µ±Ô 1 ºÅ¡±00:00:00.000 ¡« ±¾ÔÂÄ© 23:59:59.999 // - ThisYear : ±¾µØ¡°µ±Äê 1/1¡±00:00:00.000 ¡« µ±ÄêÄ© 23:59:59.999 std::pair CToolUnits::CalcQuickRangeUtc(QuickRange r) { int y, m, d; GetTodayYMD_Local(y, m, d); SYSTEMTIME stFromLocal{}, stToLocal{}; switch (r) { case QuickRange::Today: stFromLocal = MakeLocalST(y, m, d, 0, 0, 0, 0); stToLocal = MakeLocalST(y, m, d, 23, 59, 59, 999); break; case QuickRange::Last7Days: { int y2 = y, m2 = m, d2 = d; LocalCalendarMinusDays(y2, m2, d2, 6); stFromLocal = MakeLocalST(y2, m2, d2, 0, 0, 0, 0); stToLocal = MakeLocalST(y, m, d, 23, 59, 59, 999); break; } case QuickRange::ThisMonth: { int lastDay = DaysInMonth(y, m); stFromLocal = MakeLocalST(y, m, 1, 0, 0, 0, 0); stToLocal = MakeLocalST(y, m, lastDay, 23, 59, 59, 999); break; } case QuickRange::ThisYear: stFromLocal = MakeLocalST(y, 1, 1, 0, 0, 0, 0); stToLocal = MakeLocalST(y, 12, DaysInMonth(y, 12), 23, 59, 59, 999); break; default: throw std::invalid_argument("CalcQuickRangeUtc: unsupported range"); } auto fromUtc = LocalSTtoUtcTP(stFromLocal); auto toUtc = LocalSTtoUtcTP(stToLocal); return { fromUtc, toUtc }; } // С¹¤¾ß£ºASCII ²»Çø·Ö´óСд°üº¬£¨ÖÐÎÄµÈ·Ç ASCII ²»ÊÜÓ°Ï죬µ«Ò²²»ÐèÒª´óСдת»»£© bool CToolUnits::containsCI(const std::string& hay, const std::string& needle) { if (needle.empty()) return true; auto toLower = [](std::string s) { std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return (char)std::tolower(c); }); return s; }; std::string h = toLower(hay), n = toLower(needle); return h.find(n) != std::string::npos; } // ------- ±¾µØÊ±¼ä ------- std::string CToolUnits::TimePointToLocalString(const std::optional& tp, const char* fmt/* = "%Y-%m-%d %H:%M:%S"*/) { if (!tp) return {}; std::time_t t = std::chrono::system_clock::to_time_t(*tp); std::tm tm{}; #if defined(_WIN32) localtime_s(&tm, &t); #else localtime_r(&t, &tm); #endif char buf[64]{}; std::strftime(buf, sizeof(buf), fmt, &tm); return buf; } // ------- UTC ʱ¼ä ------- std::string CToolUnits::TimePointToUtcString(const std::optional& tp, const char* fmt/* = "%Y-%m-%d %H:%M:%S"*/) { if (!tp) return {}; std::time_t t = std::chrono::system_clock::to_time_t(*tp); std::tm tm{}; #if defined(_WIN32) gmtime_s(&tm, &t); #else gmtime_r(&t, &tm); #endif char buf[64]{}; std::strftime(buf, sizeof(buf), fmt, &tm); return buf; } std::string CToolUnits::TimePointToLocalStringMs(const std::optional& tp) { if (!tp) return {}; using namespace std::chrono; auto ms_since_epoch = duration_cast(tp->time_since_epoch()); auto ms = static_cast(ms_since_epoch.count() % 1000); std::time_t t = system_clock::to_time_t(*tp); std::tm tm{}; #if defined(_WIN32) localtime_s(&tm, &t); #else localtime_r(&t, &tm); #endif char date[32]{}; std::strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", &tm); char out[40]{}; std::snprintf(out, sizeof(out), "%s.%03d", date, ms); return out; } std::string CToolUnits::NowStrSec() { using namespace std::chrono; auto now = system_clock::now(); std::time_t t = system_clock::to_time_t(now); std::tm tm{}; #ifdef _WIN32 localtime_s(&tm, &t); // ±¾µØÊ±¼ä£¨Windows Ḭ̈߳²È«£© #else localtime_r(&t, &tm); // ±¾µØÊ±¼ä£¨POSIX Ḭ̈߳²È«£© #endif std::ostringstream oss; oss << std::put_time(&tm, "%Y%m%d%H%M%S"); // Àý£º2025-09-15 08:23:07 return oss.str(); } std::wstring CToolUnits::AnsiToWString(const std::string& str) { if (str.empty()) return std::wstring(); int len = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, nullptr, 0); if (len <= 0) return std::wstring(); std::wstring ws; ws.resize(len - 1); ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, &ws[0], len); return ws; } std::string CToolUnits::WStringToAnsi(const std::wstring& wstr) { if (wstr.empty()) return std::string(); int len = ::WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr); if (len <= 0) return std::string(); std::string str; str.resize(len - 1); ::WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &str[0], len, nullptr, nullptr); return str; }