您的位置:首页 > 产品设计 > 产品经理

PmsQsDate

2015-06-30 13:13 513 查看
#ifndef PMS_QS_Date_H

#define PMS_QS_Date_H

#include <time.h>

#include <string>

#include <ostream>

#include <PmsQsBase/PmsQsUserApiDataType.h>

#include "serialization.h"

class PMS_QS_API PmsQsDate

{

private:

SERIALIZATION_INTERFACE()

{

ar & year & month & day ;

ar & days ;

ar & wday ;

ar & state;

}

protected:

unsigned year, month, day;

unsigned days;

unsigned wday;

bool state;

private:

void init(); //null date

public:

// Constructors

PmsQsDate();

PmsQsDate(unsigned y, unsigned m, unsigned d);

PmsQsDate(time_t t);

PmsQsDate(struct tm dt);

PmsQsDate(unsigned ds);

PmsQsDate(const char* dstr);

PmsQsDate(const std::string &dstr);

PmsQsDate(const PmsQsDate& dst);

PmsQsDate& operator=(const PmsQsDate& dst);

// Getters

inline unsigned GetYear() const { return year; }

inline unsigned GetMonth() const { return month; }

inline unsigned GetDay() const { return day; }

inline unsigned GetDays() const { return days; }

inline unsigned GetWday() const { return wday; }

//返回日期当月天数

unsigned GetMonthDays() const;

// Test parameters, auto correct

// unsigned TestYear(int y) const;

// unsigned TestMonth(int m) const;

// unsigned TestDay(int d) const;

static bool IsValid(int y, int m, int d);

bool IsNull() const;

bool IsValid() const;

// check leap year

static bool IsLeapYear(unsigned y);

inline bool IsLeapYear() const { return IsLeapYear(year); }

// Calculate days of date(y,m,d)

static unsigned CalcDays(unsigned y, unsigned m, unsigned d);

// Calculate weekday of date (rely on days)

static unsigned CalcWday(unsigned ds);

// Calculate weekday of date (rely on y,m,d)

static unsigned CalcWday(unsigned y, unsigned m, unsigned d);

// Calculate date of nth weekday of mth week of a certain month

static PmsQsDate NthWeekDayDate(unsigned y, unsigned m, unsigned Nth, unsigned wd);

static PmsQsDate NthWeekDayDate(const PmsQsDate &refdate, unsigned Nth, unsigned wd);

// calculate last day of the month to which the given date belongs

static PmsQsDate EndOfMonth(const PmsQsDate& d);

// test wheather a date is the last day of its month

static bool IsEndOfMonth(const PmsQsDate& d);

// today's date.

static PmsQsDate TodaysDate();

// Parse date from days

bool From(unsigned ds);

// Parse date string, like 20141020 2014-10-20 2014.10.20 2014/10/20

bool From(const char* dstr);

// Delay date, accept negative parameter

PmsQsDate DelayYear(int y) const;

PmsQsDate DelayMonth(int m, bool EOM = false) const;

PmsQsDate DelayDay(int d) const;

PmsQsDate Delay(char unit, int term) const;

// Convert

void ToString(std::string& str) const;

std::string ToString() const;

struct tm ToCTime() const;

time_t ToCTicks() const;

};

inline PmsQsDate PmsQsDate::EndOfMonth(const PmsQsDate& d)

{

return PmsQsDate(d.GetYear(), d.GetMonth(), d.GetMonthDays());

}

inline bool PmsQsDate::IsEndOfMonth(const PmsQsDate& d)

{

return (d.GetDay() == d.GetMonthDays());

}

//operators

inline std::ostream& operator<< (std::ostream& os, const PmsQsDate& d)

{

os << d.ToString();

return os;

}

inline bool operator<= (const PmsQsDate& d1, const PmsQsDate& d2)

{

return d1.GetDays() <= d2.GetDays();

}

inline bool operator< (const PmsQsDate& d1, const PmsQsDate& d2)

{

return d1.GetDays() < d2.GetDays();

}

inline bool operator>= (const PmsQsDate& d1, const PmsQsDate& d2)

{

return d1.GetDays() >= d2.GetDays();

}

inline bool operator> (const PmsQsDate& d1, const PmsQsDate& d2)

{

return d1.GetDays() > d2.GetDays();

}

inline bool operator== (const PmsQsDate& d1, const PmsQsDate& d2)

{

return d1.GetDays() == d2.GetDays();

}

inline bool operator!= (const PmsQsDate& d1, const PmsQsDate& d2)

{

return !(d1 == d2);

}

//function to compute time difference (day) between date1 and date2

inline int fn_DiffDate(const PmsQsDate& d1, const PmsQsDate& d2)

{

int ds = d2.GetDays() - d1.GetDays();

return ds;

}

#endif

#include <stdlib.h>

#include <string.h>

#include <stdlib.h>

#include <stdio.h>

#include <PmsQsBase/PmsQsDate.h>

static log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger("server");

const static unsigned g_s_min_year = 1970;

const static unsigned g_s_max_year = 9999;

const static unsigned g_s_month_days[13] = {0,

/*1 */ 31,

/*2 */ 28,

/*3 */ 31,

/*4 */ 30,

/*5 */ 31,

/*6 */ 30,

/*7 */ 31,

/*8 */ 31,

/*9 */ 30,

/*10*/ 31,

/*11*/ 30,

/*12*/ 31,

};

const static unsigned g_s_sum_days[13] = {0,

/*1 */ 0,

/*2 */ 31,

/*3 */ 31+28,

/*4 */ 31+28+31,

/*5 */ 31+28+31+30,

/*6 */ 31+28+31+30+31,

/*7 */ 31+28+31+30+31+30,

/*8 */ 31+28+31+30+31+30+31,

/*9 */ 31+28+31+30+31+30+31+31,

/*10*/ 31+28+31+30+31+30+31+31+30,

/*11*/ 31+28+31+30+31+30+31+31+30+31,

/*12*/ 31+28+31+30+31+30+31+31+30+31+30,

};

void PmsQsDate::init()

{

year = g_s_min_year; //1970

month = 1;

day = 1;

days = 719162; //CalcDays(year, month, day);

wday = 4; //CalcWday(days);

}

PmsQsDate::PmsQsDate()

: state(false)

{ // construct a null date. Null dates are invalid

init();

}

PmsQsDate::PmsQsDate(unsigned y, unsigned m, unsigned d)

: state (false)

{

if(!IsValid(y, m, d))

{// if is invalid

init();

}

else

{

year = y;

month = m;

day = d;

days = CalcDays(year, month, day);

wday = CalcWday(days);

state = true;

}

// year = TestYear(y);

// month = TestMonth(m);

// day = TestDay(d);

// days = CalcDays(year, month, day);

// wday = CalcWday(days);

}

PmsQsDate::PmsQsDate(time_t t)

: state(false)

{

tm dt = *(localtime(&t));

year = dt.tm_year + 1900;

month = dt.tm_mon + 1;

day = dt.tm_mday;

days = CalcDays(year, month, day);

wday = CalcWday(days);

state = true;

}

PmsQsDate::PmsQsDate(struct tm dt)

: state(false)

{

year = dt.tm_year + 1900;

month = dt.tm_mon + 1;

day = dt.tm_mday;

days = CalcDays(year, month, day);

wday = CalcWday(days);

state = true;

}

PmsQsDate::PmsQsDate(unsigned ds)

: state(false)

{

if(!From(ds))

init();// default date used

else

state = true;

}

PmsQsDate::PmsQsDate(const char* dstr)

: state(false)

{

if(!(dstr && From(dstr)))

init();// default date used

else

state = true;

}

PmsQsDate::PmsQsDate(const std::string &dstr)

: state(false)

{

const char* dcstr = dstr.c_str();

if(!(dcstr && From(dcstr)))

init();// default date used

else

state = true;

}

PmsQsDate::PmsQsDate(const PmsQsDate& dst):

year(dst.year), month(dst.month), day(dst.day),

days(dst.days), wday(dst.wday), state(dst.state)

{

}

PmsQsDate& PmsQsDate::operator=(const PmsQsDate& dst)

{

if(this != &dst)

{

year = dst.year;

month = dst.month;

day = dst.day;

days = dst.days;

wday = dst.wday;

state = dst.state;

}

return *this;

}

unsigned PmsQsDate::GetMonthDays() const

{

int month_days = g_s_month_days[month];

if(month==2 && IsLeapYear(year))

{

month_days += 1;

}

return month_days;

}

//unsigned PmsQsDate::TestYear(int y) const

//{

// return y<g_s_min_year ? g_s_min_year : (y>g_s_max_year ? g_s_max_year : y);

//}

//

//unsigned PmsQsDate::TestMonth(int m) const

//{

// return m<1 ? 1: (m>12 ? 12 : m);

//}

//

//unsigned PmsQsDate::TestDay(int d) const

//{

// int month_days = g_s_month_days[month];

// if(month==2 && IsLeapYear(year))

// month_days += 1;

//

// return d<1 ? 1: (d>month_days ? month_days: d);

//}

bool PmsQsDate::IsValid(int y, int m, int d)

{

if(y < g_s_min_year || y > g_s_max_year)

return false;

if(m < 1 || m > 12)

return false;

int month_days = g_s_month_days[m];

if(m==2 && IsLeapYear(y))

month_days += 1;

if(d < 1 || d > month_days)

return false;

return true;

}

bool PmsQsDate::IsNull() const

{

return state;

}

bool PmsQsDate::IsValid() const

{

return IsNull();

}

bool PmsQsDate::IsLeapYear(unsigned y)

{

//return ((y%4==0 && y%100!=0) || y%400==0);

return (((y&3)==0 && (y%100)!=0) || (y%400)==0);

// from wiki

if(y%4 != 0)

return false;

if(y%100 != 0)

return true;

if(y%400 != 0)

return false;

return true;

}

unsigned PmsQsDate::CalcDays(unsigned y, unsigned m, unsigned d)

{

unsigned ds = 0;

//Day of year

ds += 365 * (y-1) + (y-1)/4 - (y-1)/100 + (y-1)/400;

//ds += 365 * (y-1) + 97*(y-1) / 400; // why 2017 error ?

//Day of month

ds += g_s_sum_days[m];

if(m>2 && IsLeapYear(y))

ds += 1;

//Day

ds += d - 1;

return ds;

}

unsigned PmsQsDate::CalcWday(unsigned ds)

{

//W:weekday Y:year D:days of year

//W = 365 * (Y-1) + (Y-1)/4 - (Y-1)/100 + (Y-1)/400 + D;

//W = W % 7;

return (ds+1) % 7;

}

unsigned PmsQsDate::CalcWday(unsigned y, unsigned m, unsigned d)

{

return CalcWday(CalcDays(y, m, d));

}

PmsQsDate PmsQsDate::NthWeekDayDate(unsigned y, unsigned m, unsigned Nth, unsigned wd)

{

unsigned ds_tmp = CalcDays(y, m, 1);

unsigned wd_tmp = CalcWday(ds_tmp);

unsigned week_jump = Nth - ((wd >= wd_tmp) ? 1 : 0);

ds_tmp += wd + week_jump * 7 - wd_tmp;

return PmsQsDate(ds_tmp);

}

PmsQsDate PmsQsDate::NthWeekDayDate(const PmsQsDate &refdate, unsigned Nth, unsigned wd)

{

return NthWeekDayDate(refdate.GetYear(), refdate.GetMonth(), Nth, wd);

}

// today's date.

PmsQsDate PmsQsDate::TodaysDate()

{

std::time_t now = std::time(NULL);

std::tm *local = std::localtime(&now);

return PmsQsDate(local->tm_year+1900, local->tm_mon+1, local->tm_mday);

}

bool PmsQsDate::From(unsigned ds)

{

unsigned remains = ds;

// 97 leap year per 400 years

unsigned n400Years = remains / (400*365 + 97); //146097

remains = remains % (400*365 + 97);

// 24 leap year per 100 years

unsigned n100Years = remains / (100*365 + 24); //36524

remains = remains % (100*365 + 24);

// Bugfix, 730483->2000.12.30 730484->2001-01-01

if(n100Years == 4)

{

n100Years = 3;

remains = 36524;

}

// 1 leap year per 4 years

unsigned n4Years = remains / (4*365 + 1); // 1461

remains = remains % (4*365 + 1);

// 365 days per year

unsigned n1Years = remains / 365;

remains = remains % 365;

// Bugfix, 734866->2012.12.30 734867->2013-01-01

if(n1Years == 4)

{

n1Years = 3;

remains = 365;

}

//Calculate Year

unsigned y = n1Years + n4Years * 4 + n100Years * 100 + n400Years * 400 + 1;

if(y<g_s_min_year || y > g_s_max_year)

return false;

year = y;

//Calculate Month

unsigned m = 1;

for(; m<=12; m++)

{

unsigned num = g_s_month_days[m];

if(m==2 && IsLeapYear(y))

num++;

if(remains < num)

break;

remains -= num;

}

// if(m > 12) // not exist

// return false;

month = m;

//Calculate Day

unsigned d = remains + 1;

day = d;

//Set days

days = ds;

wday = CalcWday(days);

return true;

}

bool PmsQsDate::From(const char* dstr)

{

if(!dstr)

return false;

int len = strlen(dstr);

if(len!=8 && len!=10)

return false;

if(!(isdigit(dstr[0]) && isdigit(dstr[1]) && isdigit(dstr[2]) && isdigit(dstr[3])))

return false;

char buffer[11];

buffer[4]='\0';

buffer[7]='\0';

buffer[10]='\0';

strncpy(buffer, dstr, 4);

//20141020

if(isdigit(dstr[4]))

{

if(!(isdigit(dstr[5]) && isdigit(dstr[6]) && isdigit(dstr[7])))

return false;

strncpy(buffer+5, dstr+4, 2);

strncpy(buffer+8, dstr+6, 2);

}

//2014-10-20 2014.10.20 2014/10/20

else if(dstr[4]=='-' || dstr[4]=='.' || dstr[4]=='/')

{

if(dstr[7] != dstr[4])

return false;

if(!(isdigit(dstr[5]) && isdigit(dstr[6]) && isdigit(dstr[8]) && isdigit(dstr[9])))

return false;

strncpy(buffer+5, dstr+5, 2);

strncpy(buffer+8, dstr+8, 2);

}

else

{

return false;

}

int y = atoi(buffer);

int m = atoi(buffer+5);

int d = atoi(buffer+8);

if(y<g_s_min_year || y>g_s_max_year)

return false;

if(m<1 || m>12)

return false;

if(d<1 || d>31)

return false;

//Check leap year

int month_days = g_s_month_days[m];

if(m==2 && IsLeapYear(y))

month_days += 1;

if(d > month_days)

return false;

year = y;

month = m;

day = d;

days = CalcDays(year, month, day);

wday = CalcWday(days);

return true;

}

PmsQsDate PmsQsDate::DelayYear(int y) const

{

int nY = year + y;

int nM = month;

int nD = day;

if(2 == nM && IsLeapYear(nY) && nD >= g_s_month_days[nM]+1)

{

nD = g_s_month_days[nM] +1;

}

else if ( nD > g_s_month_days[nM])

{

nD = g_s_month_days[nM];

}

return PmsQsDate(nY, nM, nD);

}

PmsQsDate PmsQsDate::DelayMonth(int m, bool EOM) const

{

int nY = year + m / 12;

int nM = month + m % 12;

int nD = day;

//Correct 0 or negative month, over 12 months

if(nM < 1)

{

nM += 12;

nY --;

}

else if(nM > 12)

{

nM -= 12;

nY ++;

}

if(2 == nM && IsLeapYear(nY) && nD >= g_s_month_days[nM]+1)

{

nD = g_s_month_days[nM] +1;

}

else if ( nD > g_s_month_days[nM])

{

nD = g_s_month_days[nM];

}

return EOM && (IsEndOfMonth(*this)) ?

EndOfMonth(PmsQsDate(nY, nM, nD)): PmsQsDate(nY, nM, nD);

}

PmsQsDate PmsQsDate::DelayDay(int d) const

{

int ds = days + d;

return PmsQsDate((unsigned)ds);

}

PmsQsDate PmsQsDate::Delay(const char unit, int term) const

{

PmsQsDate dt;

switch(unit)

{

case 'D':

dt = DelayDay(term);

break;

case 'W':

dt = DelayDay(term * 7);

break;

case 'M':

dt = DelayMonth(term);

break;

case 'Q':

dt = DelayMonth(term * 3);

break;

case 'S':

dt = DelayMonth(term * 6);

break;

case 'Y':

dt = DelayYear(term);

break;

default:

break;

}

return dt;

}

void PmsQsDate::ToString(std::string& str) const

{

char buffer[11];

//sprintf(buffer, "%04d-%02d-%02d", year, month, day);

int y = year;

buffer[0] = '0' + y / 1000;

y = y % 1000;

buffer[1] = '0' + y / 100;

y = y % 100;

buffer[2] = '0' + y / 10;

y = y % 10;

buffer[3] = '0' + y;

buffer[4] = '-';

int m = month;

buffer[5] = '0' + m / 10;

m = m % 10;

buffer[6] = '0' + m;

buffer[7] = '-';

int d = day;

buffer[8] = '0' + d / 10;

d = d % 10;

buffer[9] = '0' + d;

buffer[10] = 0;

str = buffer;

}

std::string PmsQsDate::ToString() const

{

std::string str;

ToString(str);

return str;

}

struct tm PmsQsDate::ToCTime() const

{

struct tm dt;

dt.tm_year = year - 1900;

dt.tm_mon = month - 1;

dt.tm_mday = day;

dt.tm_hour = 0;

dt.tm_min = 0;

dt.tm_sec = 1;

dt.tm_wday = wday;

dt.tm_yday = g_s_sum_days[month] + day - 1;

if(month>2 && IsLeapYear())

dt.tm_yday ++;

dt.tm_isdst = 0;

return dt;

}

time_t PmsQsDate::ToCTicks() const

{

struct tm dt = ToCTime();

return mktime(&dt);

}

/*

std::ostream& operator<< (std::ostream& os, const PmsQsDate& d)

{

os << d.ToString();

return os;

}

bool operator<= (const PmsQsDate& d1, const PmsQsDate& d2)

{

return d1.GetDays() <= d2.GetDays();

}

bool operator< (const PmsQsDate& d1, const PmsQsDate& d2)

{

return d1.GetDays() < d2.GetDays();

}

bool operator>= (const PmsQsDate& d1, const PmsQsDate& d2)

{

return d1.GetDays() >= d2.GetDays();

}

bool operator> (const PmsQsDate& d1, const PmsQsDate& d2)

{

return d1.GetDays() > d2.GetDays();

}

bool operator== (const PmsQsDate& d1, const PmsQsDate& d2)

{

return d1.GetDays() == d2.GetDays();

}

int fn_DiffDate(const PmsQsDate& d1, const PmsQsDate& d2)

{

int ds = d2.GetDays() - d1.GetDays();

return ds;

}

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: