#include "stdafx.h"
|
#include "ToolUnits.h"
|
#include <chrono>
|
#include <memory>
|
#include <sstream>
|
|
|
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<std::chrono::milliseconds>(now);
|
return static_cast<ULONGLONG>(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<CString> CToolUnits::GetFileNamesInDirectory(const CString& strFolderPath, const CString& strExtension)
|
{
|
std::vector<CString> fileNames;
|
|
// È·±£Ä¿Â¼Â·¾¶×îºóÓз´Ð±¸Ü
|
CString strSearchPath = strFolderPath;
|
if (strSearchPath[strSearchPath.GetLength() - 1] != '\\') {
|
strSearchPath += '\\';
|
}
|
|
CString finalExtension = strExtension;
|
if (finalExtension.Find('.') == -1) {
|
finalExtension = '.' + finalExtension;
|
}
|
strSearchPath += "*" + finalExtension;
|
|
std::unique_ptr<CFileFind> finder = std::make_unique<CFileFind>();
|
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<CDateTimeCtrl&>(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<CDateTimeCtrl&>(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<CDateTimeCtrl&>(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<std::chrono::system_clock::time_point,
|
std::chrono::system_clock::time_point>
|
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 };
|
}
|