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;
}
*/
#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;
}
*/
相关文章推荐
- 产品经理该如何和工程师沟通?
- Source RPMs for Broadcom drivers
- 腾讯产品总监蒋宁:对产品经理的深入理解及建议
- PMC Flashtec + Memblaze PBlaze 4 = 性能惊人的NVM Express SSD!
- 使用 JMX 接口来编写 PMI 应用程序
- Chrome development tools学习笔记(5)
- 运维自动化_rpmbulid 线上服务rpm打包
- ubuntu安装rpm的方法
- rpm包管理
- Set up start development environment on ubuntu-12.04.1
- 电脑自动访问g.ceipmsn.com
- [转]加快npm的下载速度
- 软件包管理rpm_yum
- rpm 笔记
- jbpm6 开发环境搭建
- 安装rrdtool报错:Can't locate ExtUtils/MakeMaker.pm in @INC
- npm设置代理提高下载速度
- npm install 加速,解决github在国内访问缓慢的问题。
- PMC 任命Edward Sharp为首席战略及技术官
- 测试驱动开发 - Test-Driven Development