mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-01-19 15:35:41 +00:00
267 lines
9 KiB
C++
267 lines
9 KiB
C++
// SPDX-License-Identifier: MIT
|
|
//
|
|
// EmulationStation Desktop Edition
|
|
// TimeUtil.cpp
|
|
//
|
|
// Low-level date and time functions.
|
|
// Set and get time, format to string formats, count days and months etc.
|
|
//
|
|
|
|
#include "utils/TimeUtil.h"
|
|
|
|
#include <time.h>
|
|
|
|
namespace Utils
|
|
{
|
|
namespace Time
|
|
{
|
|
DateTime::DateTime()
|
|
{
|
|
mTime = 0;
|
|
#if defined(_WIN64)
|
|
mTimeStruct = {0, 0, 0, 1, 0, 0, 0, 0, -1};
|
|
#else
|
|
mTimeStruct = {0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0};
|
|
#endif
|
|
mIsoString = "00000000T000000";
|
|
}
|
|
|
|
DateTime::DateTime(const time_t& time)
|
|
{
|
|
// Set time.
|
|
setTime(time);
|
|
}
|
|
|
|
DateTime::DateTime(const tm& timeStruct)
|
|
{
|
|
// Set time struct.
|
|
setTimeStruct(timeStruct);
|
|
}
|
|
|
|
DateTime::DateTime(const std::string& isoString)
|
|
{
|
|
// Set ISO string.
|
|
setIsoString(isoString);
|
|
}
|
|
|
|
void DateTime::setTime(const time_t& time)
|
|
{
|
|
mTime = (time < 0) ? 0 : time;
|
|
#if defined(_WIN64)
|
|
localtime_s(&mTimeStruct, &mTime);
|
|
#else
|
|
localtime_r(&mTime, &mTimeStruct);
|
|
#endif
|
|
mIsoString = timeToString(mTime);
|
|
}
|
|
|
|
void DateTime::setTimeStruct(const tm& timeStruct)
|
|
{
|
|
// Set time based on struct.
|
|
setTime(mktime(const_cast<tm*>(&timeStruct)));
|
|
}
|
|
|
|
void DateTime::setIsoString(const std::string& isoString)
|
|
{
|
|
// Set time based on ISO string.
|
|
setTime(stringToTime(isoString));
|
|
}
|
|
|
|
Duration::Duration(const time_t& time)
|
|
{
|
|
mTotalSeconds = static_cast<unsigned int>(time);
|
|
mDays = (mTotalSeconds - (mTotalSeconds % (60 * 60 * 24))) / (60 * 60 * 24);
|
|
mHours = ((mTotalSeconds % (60 * 60 * 24)) - (mTotalSeconds % (60 * 60))) / (60 * 60);
|
|
mMinutes = ((mTotalSeconds % (60 * 60)) - (mTotalSeconds % (60))) / 60;
|
|
mSeconds = mTotalSeconds % 60;
|
|
}
|
|
|
|
time_t now()
|
|
{
|
|
time_t time;
|
|
::time(&time);
|
|
return time;
|
|
}
|
|
|
|
time_t stringToTime(const std::string& string, const std::string& format)
|
|
{
|
|
const char* s = string.c_str();
|
|
const char* f = format.c_str();
|
|
#if defined(_WIN64)
|
|
tm timeStruct = {0, 0, 0, 1, 0, 0, 0, 0, -1};
|
|
#else
|
|
tm timeStruct = {0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0};
|
|
#endif
|
|
size_t parsedChars = 0;
|
|
|
|
if (string == "19700101T010000")
|
|
return mktime(&timeStruct);
|
|
|
|
while (*f && (parsedChars < string.length())) {
|
|
if (*f == '%') {
|
|
f++;
|
|
|
|
switch (*f++) {
|
|
// Year, including century [1970,xxxx]
|
|
case 'Y': {
|
|
if ((parsedChars + 4) <= string.length()) {
|
|
timeStruct.tm_year = (*s++ - '0') * 1000;
|
|
timeStruct.tm_year += (*s++ - '0') * 100;
|
|
timeStruct.tm_year += (*s++ - '0') * 10;
|
|
timeStruct.tm_year += (*s++ - '0');
|
|
if (timeStruct.tm_year >= 1900)
|
|
timeStruct.tm_year -= 1900;
|
|
}
|
|
parsedChars += 4;
|
|
} break;
|
|
|
|
// Month number [01,12]
|
|
case 'm': {
|
|
if ((parsedChars + 2) <= string.length()) {
|
|
timeStruct.tm_mon = (*s++ - '0') * 10;
|
|
timeStruct.tm_mon += (*s++ - '0');
|
|
if (timeStruct.tm_mon >= 1)
|
|
timeStruct.tm_mon -= 1;
|
|
}
|
|
parsedChars += 2;
|
|
} break;
|
|
|
|
// Day of the month [01,31]
|
|
case 'd': {
|
|
if ((parsedChars + 2) <= string.length()) {
|
|
timeStruct.tm_mday = (*s++ - '0') * 10;
|
|
timeStruct.tm_mday += (*s++ - '0');
|
|
}
|
|
parsedChars += 2;
|
|
} break;
|
|
|
|
// Hour (24-hour clock) [00,23]
|
|
case 'H': {
|
|
if ((parsedChars + 2) <= string.length()) {
|
|
timeStruct.tm_hour = (*s++ - '0') * 10;
|
|
timeStruct.tm_hour += (*s++ - '0');
|
|
}
|
|
parsedChars += 2;
|
|
} break;
|
|
|
|
// Minute [00,59]
|
|
case 'M': {
|
|
if ((parsedChars + 2) <= string.length()) {
|
|
timeStruct.tm_min = (*s++ - '0') * 10;
|
|
timeStruct.tm_min += (*s++ - '0');
|
|
}
|
|
parsedChars += 2;
|
|
} break;
|
|
|
|
// Second [00,59]
|
|
case 'S': {
|
|
if ((parsedChars + 2) <= string.length()) {
|
|
timeStruct.tm_sec = (*s++ - '0') * 10;
|
|
timeStruct.tm_sec += (*s++ - '0');
|
|
}
|
|
parsedChars += 2;
|
|
} break;
|
|
}
|
|
}
|
|
else {
|
|
s++;
|
|
f++;
|
|
}
|
|
}
|
|
return mktime(&timeStruct);
|
|
}
|
|
|
|
std::string timeToString(const time_t& time, const std::string& format)
|
|
{
|
|
const char* f = format.c_str();
|
|
tm timeStruct;
|
|
#if defined(_WIN64)
|
|
localtime_s(&timeStruct, &time);
|
|
#else
|
|
localtime_r(&time, &timeStruct);
|
|
#endif
|
|
char buf[256] = {'\0'};
|
|
char* s = buf;
|
|
|
|
while (*f) {
|
|
if (*f == '%') {
|
|
f++;
|
|
|
|
switch (*f++) {
|
|
// Year, including century [1970,xxxx]
|
|
case 'Y': {
|
|
const int year = timeStruct.tm_year + 1900;
|
|
*s++ = static_cast<char>((year - (year % 1000)) / 1000) + '0';
|
|
*s++ = static_cast<char>(((year % 1000) - (year % 100)) / 100) + '0';
|
|
*s++ = static_cast<char>(((year % 100) - (year % 10)) / 10) + '0';
|
|
*s++ = static_cast<char>(year % 10) + '0';
|
|
} break;
|
|
|
|
// Month number [00,11]
|
|
case 'm': {
|
|
const int mon = timeStruct.tm_mon + 1;
|
|
*s++ = static_cast<char>(mon / 10) + '0';
|
|
*s++ = static_cast<char>(mon % 10) + '0';
|
|
} break;
|
|
|
|
// Day of the month [01,31]
|
|
case 'd': {
|
|
*s++ = static_cast<char>(timeStruct.tm_mday / 10) + '0';
|
|
*s++ = static_cast<char>(timeStruct.tm_mday % 10) + '0';
|
|
} break;
|
|
|
|
// Hour (24-hour clock) [00,23]
|
|
case 'H': {
|
|
*s++ = static_cast<char>(timeStruct.tm_hour / 10) + '0';
|
|
*s++ = static_cast<char>(timeStruct.tm_hour % 10) + '0';
|
|
} break;
|
|
|
|
// Minute [00,59]
|
|
case 'M': {
|
|
*s++ = static_cast<char>(timeStruct.tm_min / 10) + '0';
|
|
*s++ = static_cast<char>(timeStruct.tm_min % 10) + '0';
|
|
} break;
|
|
|
|
// Second [00,59]
|
|
case 'S': {
|
|
*s++ = static_cast<char>(timeStruct.tm_sec / 10) + '0';
|
|
*s++ = static_cast<char>(timeStruct.tm_sec % 10) + '0';
|
|
} break;
|
|
}
|
|
}
|
|
else {
|
|
*s++ = *f++;
|
|
}
|
|
*s = '\0';
|
|
}
|
|
return std::string(buf);
|
|
}
|
|
|
|
int daysInMonth(const int year, const int month)
|
|
{
|
|
#if defined(_WIN64)
|
|
tm timeStruct = {0, 0, 0, 0, month, year - 1900, 0, 0, -1};
|
|
#else
|
|
tm timeStruct = {0, 0, 0, 0, month, year - 1900, 0, 0, -1, 0, 0};
|
|
#endif
|
|
mktime(&timeStruct);
|
|
|
|
return timeStruct.tm_mday;
|
|
}
|
|
|
|
int daysInYear(const int year)
|
|
{
|
|
#if defined(_WIN64)
|
|
tm timeStruct = {0, 0, 0, 0, 0, year - 1900 + 1, 0, 0, -1};
|
|
#else
|
|
tm timeStruct = {0, 0, 0, 0, 0, year - 1900 + 1, 0, 0, -1, 0, 0};
|
|
#endif
|
|
mktime(&timeStruct);
|
|
|
|
return timeStruct.tm_yday + 1;
|
|
}
|
|
|
|
} // namespace Time
|
|
|
|
} // namespace Utils
|