没有外部库的任何日期的C++Int

C++ Int to Any Date Without External Library

本文关键字:任何 C++Int 日期 外部      更新时间:2023-10-16

我需要将一些integers转换为date。首先,我确实知道Boost::Gregory库,但我不能使用它,因为它不会使用Clang编译,而Clang是我的应用程序获得最佳性能的地方。

我正在分析原始数据库文件,因此性能将非常重要,因为转换将发生数十万次来表示出生日期、时间戳、约会时间等等

根据我正在分析的数据库,我有几个不同的起始日期。我使用的起始日期是:

System 1: 1706-02-24
System 2: 1840-01-01

我尝试过这种方式,但当我尝试打印它时,我得到了一个错误,timeinfo2为空:

time_t rawtime;
struct tm* timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
timeinfo->tm_year = 1706 - 1900;
timeinfo->tm_mon = 2 - 1;
timeinfo->tm_mday = 24;
timeinfo->tm_mday += 98040; // days since origin
time_t newtime;
struct tm* timeinfo2;
newtime = mktime(timeinfo);
timeinfo2 = localtime(&newtime);

结果应为:1968-08-12

以下是一个公共域算法列表,这些算法对Unix时间和ProProPropt公历进行了数百万年的时间前后建模。它们非常高效(无迭代、最小分支、最小缓存抖动(。

您可以使用这些算法编写自己的日期库,以正确处理1970年之前的日期。这些也是构成Howard Hinnant的<chrono>库的C++20预览的基础的相同算法。

我非常尊重Howard所做的一切,但我需要一些能尽快执行的东西,并且担心在我只需要intdate的时候包括整个日期库。

以下是我的想法:

string GetDateFromDaysSincePointInTime(int days)
{
int a, b, c, d, e, m, dd, mm, yyyy;
a = days + 2374475;
b = (4 * a + 3) / 146097;
c = -b * 146097 / 4 + a;
d = (4 * c + 3) / 1461;
e = -1461 * d / 4 + c;
m = (5 * e + 2) / 153;
dd = -(153 * m + 2) / 5 + e + 1;
mm = -m / 10 * 12 + m + 3;
yyyy = b * 100 + d - 4800 + m / 10;
return  to_string(yyyy) + "-" + to_string(mm) + '-' + to_string(dd);
}

要使用它,只需使用intGetDateFromDaysSincePointInTime(113908)来调用它。这会给你一个日期。假设我的起点与你的起点不同,请访问网站https://www.timeanddate.com/date/dateadd.html并从输出的日期中添加/减去您想要的日期。然后将变量a的int值更改该值,然后再次运行以获得更正的日期。

从那里开始,如果需要的话,它应该能够很容易地更改为具有前导零:

std::ostringstream month;
month << std::setw(2) << std::setfill('0') << mm;
std::ostringstream day;
day << std::setw(2) << std::setfill('0') << dd;
return  to_string(yyyy) + "-" + month.str() + '-' + day.str()

备用方式

这是另一种可读性更强的方法,而且在30000条记录上似乎没有任何真正的性能打击:

string GetDateFromInt(int days)
{
int startYear = 1600;
int year = days / 365.2421875;
float peryear = 365.2421875;
int remainder = fmod(days, peryear); // here you could add what day of the year to get a date in the middle of the year
bool leapyear= ((year & 3) == 0  && (year % 100 != 0));
int leapYearIndex = leapyear ? 1 : 0;
int daysInYear = leapYearIndex ? 366 : 365;
const unsigned short int __mon_yday[2][13] =
{
/* Normal years.  */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
/* Leap years.  */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
int dayOfYear = remainder;
if (dayOfYear >= 1 && dayOfYear <= daysInYear) {
for (int mon = 0; mon < 12; mon++) {
if (dayOfYear <= __mon_yday[leapYearIndex][mon + 1]) {
int month = mon + 1;
int dayOfMonth = dayOfYear - __mon_yday[leapYearIndex][mon];
std::ostringstream months;
months << std::setw(2) << std::setfill('0') << month;
std::ostringstream day;
day << std::setw(2) << std::setfill('0') << dayOfMonth;
return  to_string(startYear + year) + "-" + months.str() + '-' + day.str();
}
}
}
}
相关文章: