SmartOS/Core/DateTime.cpp

407 lines
8.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "_Core.h"
#include "SString.h"
#include "DateTime.h"
/************************************************ DateTime ************************************************/
// 我们的时间起点是 1/1/1970 00:00:00.000 在公历里面1/1/1970是星期四
#define BASE_YEAR 1970
// 截止基本年已过去的闰年数。1969 / 4 - 1969 / 100 + 1969 / 400 = 492 - 19 + 4 = 477
#define BASE_YEAR_LEAPYEAR_ADJUST (((BASE_YEAR - 1) / 4) - ((BASE_YEAR - 1) / 100) + ((BASE_YEAR - 1) / 400))
#define BASE_YEAR_DAYOFWEEK_SHIFT 4 // 星期偏移
// 基本年的秒数
#define BASE_YEAR_SECONDS 62135596800UL
const int CummulativeDaysForMonth[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
#define IS_LEAP_YEAR(y) (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
// 基于基本年的闰年数,不包含当年
#define NUMBER_OF_LEAP_YEARS(y) ((((y - 1) / 4) - ((y - 1) / 100) + ((y - 1) / 400)) - BASE_YEAR_LEAPYEAR_ADJUST)
#define NUMBER_OF_YEARS(y) (y - BASE_YEAR)
#define YEARS_TO_DAYS(y) ((NUMBER_OF_YEARS(y) * 365) + NUMBER_OF_LEAP_YEARS(y))
#define MONTH_TO_DAYS(y, m) (CummulativeDaysForMonth[m - 1] + ((IS_LEAP_YEAR(y) && (m > 2)) ? 1 : 0))
DateTime& DateTime::Parse(uint seconds)
{
auto& st = *this;
//if(seconds >= BASE_YEAR_SECONDS) seconds -= BASE_YEAR_SECONDS;
// 分别计算毫秒、秒、分、时,剩下天数
uint time = seconds;
st.Second = time % 60;
time /= 60;
st.Minute = time % 60;
time /= 60;
st.Hour = time % 24;
time /= 24;
if(time) ParseDays(time);
Ms = 0;
return st;
}
DateTime& DateTime::ParseMs(UInt64 ms)
{
Parse(ms / 1000ULL);
Ms = ms % 1000ULL;
return *this;
}
DateTime& DateTime::ParseDays(uint days)
{
// 基本年的一天不一定是星期天需要偏移BASE_YEAR_DAYOFWEEK_SHIFT
//DayOfWeek = (days + BASE_YEAR_DAYOFWEEK_SHIFT) % 7;
Year = (ushort)(days / 365);
if(Year < 136) Year += BASE_YEAR;
// 按最小每年365天估算如果不满当年总天数年份减一
int ytd = YEARS_TO_DAYS(Year);
if (ytd > days)
{
Year--;
ytd = YEARS_TO_DAYS(Year);
}
// 减去年份的天数
days -= ytd;
// 按最大每月31天估算如果超过当月总天数月份加一
Month = (ushort)(days / 31 + 1);
int mtd = MONTH_TO_DAYS(Year, Month + 1);
if (days >= mtd) Month++;
// 计算月份表示的天数
mtd = MONTH_TO_DAYS(Year, Month);
// 今年总天数减去月份天数,得到该月第几天
Day = (ushort)(days - mtd + 1);
return *this;
}
DateTime::DateTime()
{
Init();
}
DateTime::DateTime(ushort year, byte month, byte day)
{
Year = year;
Month = month;
Day = day;
Hour = 0;
Minute = 0;
Second = 0;
Ms = 0;
}
DateTime::DateTime(uint seconds)
{
//if(seconds == 0)
// Buffer(&Year, &Ms - &Year + sizeof(Ms)).Clear();
//else
Parse(seconds);
}
DateTime::DateTime(const DateTime& value)
{
*this = value;
}
DateTime::DateTime(DateTime&& value)
{
// 拷贝对方数据,把对方初始化为默认值
auto bs = ToArray();
bs = value.ToArray();
// 对方反正不用了,就不要浪费时间做初始化啦,反正没有需要释放的资源
//value.Init();
}
void DateTime::Init()
{
//Buffer(&Year, &Ms - &Year + sizeof(Ms)).Clear();
Year = BASE_YEAR;
Month = 1;
Day = 1;
Hour = 0;
Minute = 0;
Second = 0;
Ms = 0;
}
Buffer DateTime::ToArray()
{
return Buffer(&Year, &Ms - &Year + sizeof(Ms));
}
// 重载等号运算符
DateTime& DateTime::operator=(uint seconds)
{
Parse(seconds);
return *this;
}
DateTime& DateTime::operator=(const DateTime& value)
{
// 避免自己拷贝自己
if(this != &value)
{
// 拷贝对方数据
auto bs = ToArray();
bs = ((DateTime&)value).ToArray();
}
return *this;
}
uint DateTime::TotalDays() const
{
return YEARS_TO_DAYS(Year) + MONTH_TO_DAYS(Year, Month) + Day - 1;
}
uint DateTime::TotalSeconds() const
{
uint s = TotalDays() * 24 + Hour;
s = s * 60 + Minute;
s = s * 60 + Second;
return s;
}
UInt64 DateTime::TotalMs() const
{
UInt64 sec = (UInt64)TotalSeconds();
return sec * 1000UL + (UInt64)Ms;
}
// 获取星期
byte DateTime::DayOfWeek() const
{
uint days = YEARS_TO_DAYS(Year) + MONTH_TO_DAYS(Year, Month) + Day - 1;
return (days + BASE_YEAR_DAYOFWEEK_SHIFT) % 7;
}
// 取时间日期的日期部分
DateTime DateTime::Date() const
{
return DateTime(Year, Month, Day);
}
DateTime DateTime::AddYears(int value) const
{
auto dt = *this;
dt.Year += value;
return dt;
}
DateTime DateTime::AddMonths(int value) const
{
value += Month;
int ys = value / 12;
int ms = value % 12;
// 可能上下溢出,需要修正
if(ms <= 0)
{
ys--;
ms += 12;
}
auto dt = *this;
dt.Year += ys;
dt.Month = ms;
return dt;
}
DateTime DateTime::AddDays(int value) const
{
DateTime dt;
dt.ParseDays(TotalDays() + value);
return dt;
}
DateTime DateTime::AddHours(int value) const
{
/*value += Hour;
int days = value / 24;
int hour = value % 24;
// 可能上下溢出,需要修正
if(hour < 0)
{
days--;
hour += 24;
}
auto dt = AddDays(days);
dt.Hour = hour;
return dt;*/
return AddSeconds(value * 3600);
}
DateTime DateTime::AddMinutes(int value) const
{
/*value += Minute;
int hours = value / 60;
int mins = value % 60;
// 可能上下溢出,需要修正
if(mins < 0)
{
hours--;
mins += 60;
}
auto dt = AddHours(hours);
dt.Minute = mins;
return dt;*/
return AddSeconds(value * 60);
}
DateTime DateTime::AddSeconds(int value) const
{
DateTime dt;
dt.Parse(TotalSeconds() + value);
return dt;
}
DateTime DateTime::AddMilliseconds(Int64 value) const
{
DateTime dt;
dt.ParseMs(TotalMs() + value);
return dt;
}
int DateTime::CompareTo(const DateTime& value) const
{
int n = (int)Year - value.Year;
if(n) return n;
n = (int)Month - value.Month;
if(n) return n;
n = (int)Day - value.Day;
if(n) return n;
n = (int)Hour - value.Hour;
if(n) return n;
n = (int)Minute - value.Minute;
if(n) return n;
n = (int)Second - value.Second;
if(n) return n;
n = (int)Ms - value.Ms;
if(n) return n;
return 0;
}
bool operator== (const DateTime& left, const DateTime& right) { return left.CompareTo(right) == 0; }
bool operator!= (const DateTime& left, const DateTime& right) { return left.CompareTo(right) != 0; }
bool operator> (const DateTime& left, const DateTime& right) { return left.CompareTo(right) > 0; }
bool operator< (const DateTime& left, const DateTime& right) { return left.CompareTo(right) < 0; }
bool operator>= (const DateTime& left, const DateTime& right) { return left.CompareTo(right) >= 0; }
bool operator<= (const DateTime& left, const DateTime& right) { return left.CompareTo(right) <= 0; }
String& DateTime::ToStr(String& str) const
{
// F长全部 yyyy-MM-dd HH:mm:ss
/*str.Concat(Year, 10, 4);
str += '-';
str.Concat(Month, 10, 2);
str += '-';
str.Concat(Day, 10, 2);
str += ' ';
str.Concat(Hour, 10, 2);
str += ':';
str.Concat(Minute, 10, 2);
str += ':';
str.Concat(Second, 10, 2);*/
//str = str + Year + '-' + Month + '-' + Day + ' ' + Hour + ':' + Minute + ':' + Second;
str = str + Year + '-';
if(Month < 10) str += '0';
str = str + Month + '-';
if(Day < 10) str += '0';
str = str + Day + ' ';
if(Hour < 10) str += '0';
str = str + Hour + ':';
if(Minute < 10) str += '0';
str = str + Minute + ':';
if(Second < 10) str += '0';
str = str + Second;
/*char cs[20];
sprintf(cs, "%04d-%02d-%02d %02d:%02d:%02d", Year, Month, Day, Hour, Minute, Second);
str += cs;*/
return str;
}
// 默认格式化时间为yyyy-MM-dd HH:mm:ss
/*
d短日期 M/d/yy
D长日期 yyyy-MM-dd
t短时间 mm:ss
T长时间 HH:mm:ss
f短全部 M/d/yy HH:mm
F长全部 yyyy-MM-dd HH:mm:ss
*/
cstring DateTime::GetString(byte kind, char* str)
{
//assert_param(str);
//if(!str) str = _Str;
auto& st = *this;
switch(kind)
{
case 'd':
sprintf(str, "%d/%d/%02d", st.Month, st.Day, st.Year % 100);
break;
case 'D':
sprintf(str, "%04d-%02d-%02d", st.Year, st.Month, st.Day);
break;
case 't':
sprintf(str, "%02d:%02d", st.Hour, st.Minute);
break;
case 'T':
sprintf(str, "%02d:%02d:%02d", st.Hour, st.Minute, st.Second);
break;
case 'f':
sprintf(str, "%d/%d/%02d %02d:%02d", st.Month, st.Day, st.Year % 100, st.Hour, st.Minute);
break;
case 'F':
sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d", st.Year, st.Month, st.Day, st.Hour, st.Minute, st.Second);
break;
default:
//assert_param(false);
break;
}
return str;
}