C++ で日付を扱いたかったがうまくいかず、Ruby の Date クラスのような感じで C++ を使えるようなクラスを作りました。
Boost を使えば同様のクラスを使えると聞きましたが、Boost の導入がうまく行かなかったため自作。
SH_ は SharedLibrary(共通ライブラリ)を意味しています。
想定環境
OS : Windows10
IDE : Visual Studio 2015
SH_Date.h
#ifndef SHDATE_H_
#define SHDATE_H_
#include <time.h>
#include <string>
#include <iostream>
using namespace std;
class SH_Date {
public:
SH_Date();
SH_Date(string str);
SH_Date(long lYear, long lMonth, long lDay);
virtual ~SH_Date();
bool operator==(SH_Date &rSH_Date);
bool operator!=(SH_Date &rSH_Date);
SH_Date operator=(SH_Date &rSH_Date);
SH_Date operator+(long lAdjDayNum);
SH_Date operator+=(long lAdjDayNum);
SH_Date operator++(int);
SH_Date operator-(long lAdjDayNum);
SH_Date operator-=(long lAdjDayNum);
SH_Date operator--(int);
bool operator > (SH_Date &rSH_Date);
bool operator >= (SH_Date &rSH_Date);
bool operator < (SH_Date &rSH_Date);
bool operator <= (SH_Date &rSH_Date);
SH_Date setToday();
void setStrDate(string strDate);
string toString() const;
bool getNowDateTime(tm* tm);
time_t getNowTimeStamp();
// time_t から tm* 型に変換
bool transTimeStampToDateTime(time_t timer, tm* tm);
// tm* から tiemr_t に変換
time_t transDateTimeToTimeStamp(tm* tm);
// 文字列から time_t 型に変換
// yyyy-mm-dd HH:MM:SS
time_t get_t_time_from_string(const char *timebuf);
SH_Date transTimeStampToSH_Date(time_t* timer);
SH_Date transTmToSH_Date(struct tm tm);
void print();
long getLDay() const;
long getLMonth() const;
long getLYear() const;
private:
long m_lYear;
long m_lMonth;
long m_lDay;
};
inline long SH_Date::getLDay() const {
return m_lDay;
}
inline long SH_Date::getLMonth() const {
return m_lMonth;
}
inline long SH_Date::getLYear() const {
return m_lYear;
}
#endif /* SHDATE_H_ */
SH_Date.cpp
#include "SH_Date.h"
#include <iostream>
#include <string>
#include <sstream>
#define N 20 // "yyyy/mm/dd hh:mm:ss" の表示文字数
using namespace std;
SH_Date::SH_Date()
: m_lYear(0),
m_lMonth(0),
m_lDay(0) {
}
SH_Date::SH_Date(long lYear, long lMonth, long lDay)
: m_lYear(lYear),
m_lMonth(lMonth),
m_lDay(lDay) {
if (m_lYear < 1900) {
m_lYear += 1900;
}
}
SH_Date::SH_Date(string strDate) {
// yyyy/mm/dd をそれぞれ属性に分ける
size_t lMonthPos = strDate.find("/");
size_t lDayPos = strDate.find("/", lMonthPos + 1);
string strYear = strDate.substr(0, lMonthPos);
string strMonth = strDate.substr(lMonthPos + 1, lDayPos - lMonthPos - 1);
string strDay = strDate.substr(lDayPos + 1, strDate.length() - lDayPos - 1);
cout << "strDate : " + strDate << endl;
cout << "year : " + strYear << endl;
cout << "month : " + strMonth << endl;
cout << "day : " + strDay << endl;
m_lYear = stol(strYear);
m_lMonth = stol(strMonth);
m_lDay = stol(strDay);
}
SH_Date::~SH_Date() {
}
bool SH_Date::getNowDateTime(tm* tm) {
time_t timer;
char datetime[N];
timer = time(0);
errno_t err;
err = localtime_s(tm, &timer);
strftime(datetime, N, "%Y/%m/%d %H:%M:%S", tm);
string sDateTime = datetime;
return true;
}
time_t SH_Date::getNowTimeStamp() {
time_t epoch_time;
epoch_time = time(0);
cout << "TIMESTAMP =" + to_string(epoch_time) << endl;
return epoch_time;
}
bool SH_Date::transTimeStampToDateTime(time_t timer, tm* tm) {
char datetime[N];
errno_t err;
err = localtime_s(tm, &timer);
strftime(datetime, N, "%Y/%m/%d %H:%M:%S", tm);
string sDateTime = datetime;
return true;
}
string SH_Date::toString() const {
stringstream strYear;
stringstream strMonth;
stringstream strDay;
strYear << m_lYear;
strMonth << m_lMonth;
strDay << m_lDay;
string reStr = strYear.str() + "/" + strMonth.str() + "/" + strDay.str();
return reStr;
}
time_t SH_Date::transDateTimeToTimeStamp(tm* tm) {
if (tm == 0) {
cout << "SH_Date::transDateTimeToTimeStamp tm is 0 " << endl;
}
return mktime(tm);
}
time_t SH_Date::get_t_time_from_string(const char *timebuf)
{
int res;
int year, month, day, hour, minute, second = 0;
// char wday[36];
struct tm tm;
if (strlen(timebuf)>36) {
return 0;
}
/* old version */
res = sscanf_s(timebuf, "%d-%d-%d %d:%d:%d",
&year, &month, &day,
&hour, &minute, &second);
/* format error */
if (res < 1) {
return 0;
}
tm.tm_sec = second;
tm.tm_min = minute;
tm.tm_hour = hour;
tm.tm_mday = day;
tm.tm_mon = month - 1;
tm.tm_year = year - 1900;
tm.tm_isdst = -1;
return mktime(&tm);
}
// timer から SH_Date 変換
SH_Date SH_Date::transTimeStampToSH_Date(time_t* timer)
{
struct tm tm;
// 一度 tm 型に変換
transTimeStampToDateTime(*timer, &tm);
return SH_Date(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
}
SH_Date SH_Date::transTmToSH_Date(tm tm)
{
// 直接年月日を入れると有り得ない年月日でも
// 戻してしまうため、一度mktimeで正す
time_t timer = transDateTimeToTimeStamp(&tm);
return transTimeStampToSH_Date(&timer);
}
bool SH_Date::operator==(SH_Date &rSH_Date) {
if (m_lYear != rSH_Date.getLYear()) {
return false;
}
if (m_lMonth != rSH_Date.getLMonth()) {
return false;
}
if (m_lDay != rSH_Date.getLDay()) {
return false;
}
return true;
}
bool SH_Date::operator!=(SH_Date & rSH_Date)
{
if (m_lYear != rSH_Date.getLYear()) {
return true;
}
if (m_lMonth != rSH_Date.getLMonth()) {
return true;
}
if (m_lDay != rSH_Date.getLDay()) {
return true;
}
return false;
}
SH_Date SH_Date::operator=(SH_Date &rSH_Date) {
m_lYear = rSH_Date.getLYear();
m_lMonth = rSH_Date.getLMonth();
m_lDay = rSH_Date.getLDay();
return *this;
}
SH_Date SH_Date::operator+(long lAdjDayNum)
{
// 一度 tm 型に変換
struct tm adjTm = { 0, 0, 0, m_lDay + lAdjDayNum, m_lMonth - 1, m_lYear - 1900 };
time_t adjTime = mktime(&adjTm);
SH_Date rSH_Date = transTimeStampToSH_Date(&adjTime);
return rSH_Date;
}
SH_Date SH_Date::operator+=(long lAdjDayNum)
{
*this = *this + lAdjDayNum;
return *this;
}
SH_Date SH_Date::operator++(int)
{
*this = *this + 1;
return *this;
}
SH_Date SH_Date::operator-(long lBeforeDayNum) {
// 一度 tm 型に変換
struct tm adjTm = { 0, 0, 0, m_lDay - lBeforeDayNum, m_lMonth - 1, m_lYear - 1900 };
// struct tm tomorrowStruct = { 0, 0, 0, beforeTm.tm_mday + 1, beforeTm.tm_mon, beforeTm.tm_year };
time_t adjTime = mktime(&adjTm);
// SH_Date* pSH_Date = transTmToSH_Date(beforeTm);
SH_Date rSH_Date = transTimeStampToSH_Date(&adjTime);
return rSH_Date;
}
SH_Date SH_Date::operator-=(long lAdjDayNum)
{
*this = *this - lAdjDayNum;
return *this;
}
SH_Date SH_Date::operator--(int)
{
*this = *this - 1;
return *this;
}
SH_Date SH_Date::setToday() {
struct tm now;
time_t longtime;
longtime = time(0);
localtime_s(&now, &longtime);
*this = transTmToSH_Date(now);
return transTmToSH_Date(now);
}
void SH_Date::setStrDate(string strDate)
{
size_t lMonthPos = strDate.find("/");
size_t lDayPos = strDate.find("/", lMonthPos + 1);
string strYear = strDate.substr(0, lMonthPos);
string strMonth = strDate.substr(lMonthPos + 1, lDayPos - lMonthPos - 1);
string strDay = strDate.substr(lDayPos + 1, strDate.length() - lDayPos - 1);
m_lYear = stol(strYear);
m_lMonth = stol(strMonth);
m_lDay = stol(strDay);
}
bool SH_Date::operator>(SH_Date &rSH_Date)
{
struct tm thisTm = { 0, 0, 0, m_lDay, m_lMonth - 1, m_lYear - 1900 };
struct tm compTm = { 0, 0, 0, rSH_Date.m_lDay, rSH_Date.m_lMonth - 1, rSH_Date.m_lYear - 1900 };
time_t thisTime = mktime(&thisTm);
time_t compTime = mktime(&compTm);
if (thisTime > compTime) {
return true;
}
return false;
}
bool SH_Date::operator>=(SH_Date &rSH_Date)
{
struct tm thisTm = { 0, 0, 0, m_lDay, m_lMonth - 1, m_lYear - 1900 };
struct tm compTm = { 0, 0, 0, rSH_Date.m_lDay, rSH_Date.m_lMonth - 1, rSH_Date.m_lYear - 1900 };
time_t thisTime = mktime(&thisTm);
time_t compTime = mktime(&compTm);
if (thisTime >= compTime) {
return true;
}
return false;
}
bool SH_Date::operator<(SH_Date &rSH_Date)
{
struct tm thisTm = { 0, 0, 0, m_lDay, m_lMonth - 1, m_lYear - 1900 };
struct tm compTm = { 0, 0, 0, rSH_Date.m_lDay, rSH_Date.m_lMonth - 1, rSH_Date.m_lYear - 1900 };
time_t thisTime = mktime(&thisTm);
time_t compTime = mktime(&compTm);
if (thisTime > compTime) {
return true;
}
return false;
}
bool SH_Date::operator<=(SH_Date &rSH_Date)
{
struct tm thisTm = { 0, 0, 0, m_lDay, m_lMonth - 1, m_lYear - 1900 };
struct tm compTm = { 0, 0, 0, rSH_Date.m_lDay, rSH_Date.m_lMonth - 1, rSH_Date.m_lYear - 1900 };
time_t thisTime = mktime(&thisTm);
time_t compTime = mktime(&compTm);
if (thisTime <= compTime) {
return true;
}
return false;
}
void SH_Date::print()
{
cout << "SH_Date print " + to_string(m_lYear) + "/" + to_string(m_lMonth) + "/" + to_string(m_lDay) << endl;
}
テストコード
main.cpp
#include "TestMain.h"
#include "SH_Date.h"
#include <iostream>
using namespace std;
int main() {
SH_Date rToday;
// 本日日付を設定し表示
rToday.setToday();
rToday.print();
SH_Date rTomorrow;
rTomorrow = rToday++;
if (rToday <= rTomorrow) {
cout << "rTomorrow は rToday 以降です" << endl;
}
SH_Date rYesterday;
rYesterday = rToday--;
if (rYesterday <= rToday) {
cout << "rYesterday は rToday 以前です" << endl;
}
// 10日後
(rToday + 10).print();
// 50日前
(rToday - 50).print();
long lInput;
cin >> lInput;
}
テストコード結果
SH_Date print 2018/7/7
rTomorrow は rToday 以降です
rYesterday は rToday 以前です
SH_Date print 2018/7/17
SH_Date print 2018/5/18
現場からは以上です。