简述
由于C标准库<ctime>(或者<time.h>)中,只支持1970年之后的日期。因此我自制了一个可以将日期转化为从公元1年1月1日0点0分0秒开始所经历的毫秒数,或者反过来将毫秒数转化为对应日期。
如有错漏,还望指摘。
类定义
class time_struct
{
public:
time_struct() = default;
time_struct(long long ms, int base_year = 1);
long long ms_past_since(int base_year = 1) const;
std::string print() const;
bool is_leap_year() const;
bool check_validity() const;
private:
long long ms_past_since_1() const;
void set_time_by_ms(long long ms);
public:
short int year = 1;
short int month = 1;
short int day = 1;
short int hour = 0;
short int minute = 0;
short int second = 0;
short int milisecond = 0;
};
毫秒数转日期
void time_struct::set_time_by_ms(long long ms)
{
if (ms < 0)
return;
// milisecond
milisecond = ms % 1000;
ms /= 1000;
// second
second = ms % 60;
ms /= 60;
// minute
minute = ms % 60;
ms /= 60;
// hour
hour = ms % 24;
ms /= 24;
// How many 400 years are there
year = (int)(ms / 146097) * 400;
ms %= 146097;
// How many 100 years are there
// Since the last 100 years in a 400 years period
//
int num100years = ms / 36524;
if (num100years == 4)
{
--num100years;
ms -= 36524 * 3;
}
else
{
ms %= 36524;
}
year += num100years * 100;
year += (int)(ms / 1461) * 4;
ms %= 1461;
int num1years = ms / 365;
if (num1years == 4)
{
--num1years;
ms -= 365 * 3;
}
else
{
ms %= 365;
}
year += num1years + 1;
if (ms < 31)
{
month = 1;
day = ms + 1;
}
else
{
if (is_leap_year())
{
ms = ms - 31 + 2;
month = (int)(ms * 12 / 367);
day = ms - month * 367 / 12;
day -= month ? 0 : 1;
}
else
{
ms = ms - 31 + 3;
month = (int)(ms * 12 / 367);
day = ms - month * 367 / 12;
day -= month ? 0 : 2;
}
month += 2;
}
}
以任意年为基准的毫秒数转日期
time_struct::time_struct(long long ms, int base_year)
{
time_struct base;
base.year = base_year;
set_time_by_ms(ms + base.ms_past_since_1());
}
日期转毫秒数
long long time_struct::ms_past_since_1() const
{
if (!check_validity())
{
// TODO: log
// We assume LLONG_MIN is the error code
return LLONG_MIN;
}
int temp_month = month - 2;
int temp_year = year;
if (0 >= temp_month) { /* 1..12 -> 11,12,1..10 */
temp_month += 12; /* Puts Feb last since it has leap day */
temp_year -= 1;
}
long long days = (long long)(temp_year / 4 - temp_year / 100 + temp_year / 400 + 367 * temp_month / 12 + day)
+ temp_year * 365 - 337;
return ((((
(long long)(temp_year / 4 - temp_year / 100 + temp_year / 400 + 367 * temp_month / 12 + day)
+ temp_year * 365 - 337
) * 24 + hour /* now have hours */
) * 60 + minute /* now have minutes */
) * 60 + second /* now have seconds */
) * 1000 + milisecond; /* millisecond */
}
日期转以任意年为基准的毫秒数
long long time_struct::ms_past_since(int base_year) const
{
time_struct base;
base.year = base_year;
return this->ms_past_since_1() - base.ms_past_since_1();
}
检测是否是闰年
bool time_struct::is_leap_year() const
{
return ((year % 4) || (!(year % 100) && (year % 400))) ? false : true;
}
检测日期有效性
bool time_struct::check_validity() const
{
if (year < 1)
return false;
if (day < 1)
return false;
switch (month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if (day > 31)
return false;
else
break;
case 4:
case 6:
case 9:
case 11:
if (day > 30)
return false;
else
break;
case 2:
if (day > (is_leap_year() ? 29 : 28))
return false;
else
break;
default:
return false;
}
if (hour < 0 || hour > 23)
return false;
if (minute < 0 || minute > 59)
return false;
if (second < 0 || second > 59)
return false;
if (milisecond < 0 || milisecond > 999)
return false;
return true;
}
打印日期
string time_struct::print() const
{
char buff[28];
sprintf_s(
buff,
"%04d-%02d-%02d %02d:%02d:%02d:%03d",
year,
month,
day,
hour,
minute,
second,
milisecond
);
return buff;
}