306 lines
8.7 KiB
C++
306 lines
8.7 KiB
C++
#pragma once
|
||
|
||
/************************************************************************
|
||
|
||
使用32位的原子数据描述日期和时间的数据类型
|
||
|
||
由于使用32位的原子数据,导致数据的存储值范围有限,因此时间值的最小单位是秒。对于一个
|
||
时间值,本类型实际存储的就是自2010年1月1日0点到当前时间所经过的秒数!
|
||
取得两个时间对象的时间差,可以直接使用减法运算。将一个日期值增加一定的时间,可以直接
|
||
增加时间的秒数。
|
||
|
||
★实际上,数据存储的时间值使用0到30位,第31位表示此时间是否开始计时的记录标志位,例
|
||
如一个装备在产生的时候肯能带有一个使用时限,时间值表示的是该装备可以使用的时长,例如1天,
|
||
30天。而装备仅在第一次被玩家穿戴的时候才开始计时。当计时开始的时候,时间值被修改为使用
|
||
时长加当前时间值,且最高位被置位来表示这个物品的时间已经开始了计时。
|
||
|
||
★短时间类型能够描述的最大日期为2079年1月1日。
|
||
|
||
************************************************************************/
|
||
|
||
#pragma pack (push, 1)
|
||
|
||
#include <string.h>
|
||
#include "_osdef.h"
|
||
struct CMiniDateTime
|
||
{
|
||
public:
|
||
//定义短时间类型开始的年份
|
||
static const int YearBase = 2010;
|
||
//定义时间是否已经开始计时的标志位
|
||
static const unsigned int RecordFlag = 0x80000000;
|
||
//定义各种单位的时间的秒数
|
||
static const unsigned int SecOfMin = 60;
|
||
static const unsigned int SecOfHour = SecOfMin * 60;
|
||
static const unsigned int SecOfDay = SecOfHour * 24;
|
||
static const unsigned int SecOfYear[2];
|
||
static const unsigned int SecOfMonth[2][13];//以月为第二数组的下标,免去月份-1的操作!
|
||
static const unsigned int MonthDays[2][13];//以月为第二数组的下标,免去月份-1的操作!
|
||
|
||
public:
|
||
/* 从规定的日期和时间中设置短日期时间类型值
|
||
* year 公元年份,例如2012;
|
||
* month 月份,注意:1表示1月,而非0;
|
||
* day 日份,注意:1表示1号,而非0;
|
||
* hour 小时,0表示0点,23表示晚上11点;
|
||
* min 分钟,0表示0分;
|
||
* sec 秒钟,0表示0秒;
|
||
* ★★★运算函数不会改变时间的记录标志位
|
||
*/
|
||
inline CMiniDateTime& encode(const unsigned int year, const unsigned int mon, const unsigned int day,
|
||
const unsigned int hour, const unsigned int min, const unsigned int sec)
|
||
{
|
||
int i;
|
||
unsigned int v = 0;
|
||
|
||
//计算年份经过的秒数
|
||
for (i=year - 1; i>=YearBase; --i)
|
||
{
|
||
v += SecOfYear[isLeapYear(i)];
|
||
}
|
||
|
||
//计算当年1月到本月的秒数
|
||
bool boLeepYear = isLeapYear(year);
|
||
for (i=mon -1; i>=1; --i)
|
||
{
|
||
v += SecOfMonth[boLeepYear][i];
|
||
}
|
||
|
||
//计算当年1号到今天的秒数
|
||
v += (day - 1) * SecOfDay;
|
||
|
||
//计算今天0点到现在的秒数
|
||
v += hour * SecOfHour;
|
||
|
||
//计算当前小时的0分到现在的秒数
|
||
v += min * SecOfMin;
|
||
|
||
v += sec;
|
||
|
||
tv = (tv & RecordFlag) | (v & (~RecordFlag));
|
||
return *this;
|
||
}
|
||
|
||
// 从MiniDataTime转化到系统时间。暂时只精确到天。
|
||
inline void decode(SYSTEMTIME &sysTime)
|
||
{
|
||
unsigned int v = tv & (~RecordFlag);
|
||
|
||
// 年
|
||
int year = YearBase;
|
||
while (true)
|
||
{
|
||
unsigned int nSecOfCurrYear = SecOfYear[isLeapYear(year)];
|
||
if (v >= nSecOfCurrYear)
|
||
{
|
||
v -= nSecOfCurrYear;
|
||
year++;
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
|
||
// 月
|
||
bool bIsLeepYear = isLeapYear(year);
|
||
int month = 1; // index based 1 <<<<
|
||
while (true)
|
||
{
|
||
unsigned int nSecOfCurrMonth = SecOfMonth[bIsLeepYear][month];
|
||
if (v >= nSecOfCurrMonth)
|
||
{
|
||
v -= nSecOfCurrMonth;
|
||
month++;
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
|
||
// 日
|
||
int day = v / SecOfDay + 1; // index based 1 <<<<
|
||
|
||
memset(&sysTime, 0, sizeof sysTime);
|
||
sysTime.wYear = year;
|
||
sysTime.wMonth = month;
|
||
sysTime.wDay = day;
|
||
//小时、分、秒
|
||
UINT SecOfToday = v % (24 * 3600);
|
||
sysTime.wHour = SecOfToday / 3600;
|
||
sysTime.wMinute = (SecOfToday % 3600) / 60;
|
||
sysTime.wSecond = SecOfToday % 60;
|
||
}
|
||
|
||
inline bool isSameDay(const CMiniDateTime &rhs)
|
||
{
|
||
return ((tv & (~RecordFlag)) / SecOfDay) == ((rhs.tv & (~RecordFlag)) / SecOfDay) ? true : false;
|
||
}
|
||
|
||
//从SYSTEMTIME结构中设置日期时间值
|
||
inline CMiniDateTime& encode(const SYSTEMTIME& sysTime)
|
||
{
|
||
return encode(sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
|
||
}
|
||
//开始记录时间,timeOfNow参数表示当前时间的短时间类型值
|
||
inline CMiniDateTime& startRecord(const unsigned int timeOfNow)
|
||
{
|
||
if ( !(tv & RecordFlag) )
|
||
tv = RecordFlag | ((timeOfNow & (~RecordFlag)) + tv);
|
||
return *this;
|
||
}
|
||
//获取当前日期时间的短时间值
|
||
inline static unsigned int now()
|
||
{
|
||
CMiniDateTime tv;
|
||
SYSTEMTIME sysTime;
|
||
GetLocalTime(&sysTime);
|
||
tv.encode(sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
|
||
return tv.tv;
|
||
}
|
||
//获取今天凌晨的时间
|
||
inline static unsigned int today()
|
||
{
|
||
CMiniDateTime tv;
|
||
SYSTEMTIME sysTime;
|
||
GetLocalTime(&sysTime);
|
||
tv.encode(sysTime.wYear, sysTime.wMonth, sysTime.wDay, 0, 0, 0);
|
||
return tv.tv;
|
||
}
|
||
//计算明日凌晨的值
|
||
inline static unsigned int tomorrow()
|
||
{
|
||
int dayofMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
|
||
CMiniDateTime tv;
|
||
SYSTEMTIME sysTime;
|
||
GetLocalTime(&sysTime);
|
||
sysTime.wDay++;
|
||
if (sysTime.wMonth == 2 && isLeapYear(sysTime.wYear))
|
||
{
|
||
if (sysTime.wDay > 29)
|
||
{
|
||
sysTime.wMonth++;
|
||
sysTime.wDay = 1;
|
||
}
|
||
}
|
||
else if (sysTime.wDay > dayofMonth[sysTime.wMonth-1])
|
||
{
|
||
sysTime.wMonth++;
|
||
sysTime.wDay = 1;
|
||
}
|
||
if (sysTime.wMonth > 12)
|
||
{
|
||
sysTime.wYear++;
|
||
sysTime.wMonth = 1;
|
||
}
|
||
tv.encode(sysTime.wYear, sysTime.wMonth, sysTime.wDay, 0, 0, 0);
|
||
return tv.tv;
|
||
}
|
||
|
||
// 计算相对于当前MiniDateTime所指示的时间点的明天
|
||
inline unsigned int rel_tomorrow()
|
||
{
|
||
unsigned v = tv & (~RecordFlag);
|
||
v = (v + SecOfDay) / SecOfDay * SecOfDay;
|
||
return (tv & RecordFlag) | v;
|
||
}
|
||
|
||
// // 计算相对于当前MiniDateTime所指示的时间点的当前开始时间点
|
||
inline unsigned int rel_today()
|
||
{
|
||
unsigned v = tv & (~RecordFlag);
|
||
v = v / SecOfDay * SecOfDay;
|
||
return (tv & RecordFlag) | v;
|
||
}
|
||
|
||
// // 计算相对于当前MiniDateTime所指示的时间点的当前开始时间点
|
||
inline unsigned int rel_today(unsigned int hours, unsigned int mins, unsigned int seconds)
|
||
{
|
||
unsigned v = tv & (~RecordFlag);
|
||
v = v / SecOfDay * SecOfDay;
|
||
return ((tv & RecordFlag) | v) + SecOfHour*hours + SecOfMin*mins + seconds;
|
||
}
|
||
|
||
//判断是否是闰年的函数
|
||
inline static bool isLeapYear(const unsigned int year)
|
||
{
|
||
return ((year & 3) == 0) && ((year % 100 != 0) || (year % 400 == 0));
|
||
}
|
||
|
||
|
||
public:
|
||
//转换为unsigned int的类型转换运算符
|
||
inline operator unsigned int() const
|
||
{
|
||
return tv;
|
||
}
|
||
//从unsigned int复制的运算符函数
|
||
inline CMiniDateTime& operator = (const unsigned int time)
|
||
{
|
||
tv = time;
|
||
return *this;
|
||
}
|
||
//重载相等判断的运算符
|
||
inline bool operator == (const unsigned int time)
|
||
{
|
||
return tv == time;
|
||
}
|
||
//重载不等判断的运算符
|
||
inline bool operator != (const unsigned int time)
|
||
{
|
||
return tv != time;
|
||
}
|
||
inline bool operator > (const unsigned int time)
|
||
{
|
||
return (tv & (~RecordFlag)) > (time & (~RecordFlag));
|
||
}
|
||
inline bool operator >= (const unsigned int time)
|
||
{
|
||
return (tv & (~RecordFlag)) >= (time & (~RecordFlag));
|
||
}
|
||
inline bool operator < (const unsigned int time)
|
||
{
|
||
return (tv & (~RecordFlag)) < (time & (~RecordFlag));
|
||
}
|
||
inline bool operator <= (const unsigned int time)
|
||
{
|
||
return (tv & (~RecordFlag)) <= (time & (~RecordFlag));
|
||
}
|
||
//重载+运算符,避免对是否使用的标志位进行运算
|
||
inline unsigned int operator + (const unsigned int time)
|
||
{
|
||
return ((tv & (~RecordFlag)) + (time & (~RecordFlag))) & (~RecordFlag);
|
||
}
|
||
//重载-运算符,避免对是否使用的标志位进行运算
|
||
inline unsigned int operator - (const unsigned int time)
|
||
{
|
||
return ((tv & (~RecordFlag)) - (time & (~RecordFlag))) & (~RecordFlag);
|
||
}
|
||
//重载+=运算符,避免对是否使用的标志位进行运算
|
||
inline CMiniDateTime& operator += (const unsigned int time)
|
||
{
|
||
tv = (tv & RecordFlag) | (((tv & (~RecordFlag)) + (time & (~RecordFlag))) & (~RecordFlag));
|
||
return *this;
|
||
}
|
||
//重载-=运算符,避免对是否使用的标志位进行运算
|
||
inline CMiniDateTime& operator -= (const unsigned int time)
|
||
{
|
||
tv = (tv & RecordFlag) | (((tv & (~RecordFlag)) - (time & (~RecordFlag))) & (~RecordFlag));
|
||
return *this;
|
||
}
|
||
public:
|
||
CMiniDateTime()
|
||
{
|
||
tv = 0;
|
||
}
|
||
CMiniDateTime(const CMiniDateTime &mt)
|
||
{
|
||
tv = mt.tv;
|
||
}
|
||
CMiniDateTime(const unsigned int tva)
|
||
{
|
||
tv = tva;
|
||
}
|
||
public:
|
||
unsigned int tv;
|
||
};
|
||
|
||
#pragma pack (pop)
|