Merge pull request #320 from tomaz82/date_time

Replaced boost::posix_time with Utils::Time
This commit is contained in:
John Rassa 2017-12-05 08:16:26 -05:00 committed by GitHub
commit 4a70796814
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 415 additions and 88 deletions

View file

@ -1,5 +1,6 @@
#include "FileData.h" #include "FileData.h"
#include "utils/TimeUtil.h"
#include "AudioManager.h" #include "AudioManager.h"
#include "CollectionSystemManager.h" #include "CollectionSystemManager.h"
#include "FileFilterIndex.h" #include "FileFilterIndex.h"
@ -11,7 +12,6 @@
#include "VolumeControl.h" #include "VolumeControl.h"
#include "Window.h" #include "Window.h"
#include <boost/algorithm/string/trim.hpp> #include <boost/algorithm/string/trim.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
@ -285,8 +285,7 @@ void FileData::launchGame(Window* window)
gameToUpdate->metadata.set("playcount", std::to_string(static_cast<long long>(timesPlayed))); gameToUpdate->metadata.set("playcount", std::to_string(static_cast<long long>(timesPlayed)));
//update last played time //update last played time
boost::posix_time::ptime time = boost::posix_time::second_clock::universal_time(); gameToUpdate->metadata.set("lastplayed", Utils::Time::DateTime(Utils::Time::now()));
gameToUpdate->metadata.setTime("lastplayed", time);
CollectionSystemManager::get()->refreshCollectionSystems(gameToUpdate); CollectionSystemManager::get()->refreshCollectionSystems(gameToUpdate);
} }

View file

@ -65,17 +65,11 @@ namespace FileSorts
bool compareLastPlayed(const FileData* file1, const FileData* file2) bool compareLastPlayed(const FileData* file1, const FileData* file2)
{ {
//only games have lastplayed metadata // since it's stored as an ISO string (YYYYMMDDTHHMMSS), we can compare as a string
// since it's stored as a POSIX string (YYYYMMDDTHHMMSS,fffffffff), we can compare as a string
// as it's a lot faster than the time casts and then time comparisons // as it's a lot faster than the time casts and then time comparisons
if(file1->metadata.getType() == GAME_METADATA && file2->metadata.getType() == GAME_METADATA)
{
return (file1)->metadata.get("lastplayed") < (file2)->metadata.get("lastplayed"); return (file1)->metadata.get("lastplayed") < (file2)->metadata.get("lastplayed");
} }
return false;
}
bool compareNumPlayers(const FileData* file1, const FileData* file2) bool compareNumPlayers(const FileData* file1, const FileData* file2)
{ {
return (file1)->metadata.getInt("players") < (file2)->metadata.getInt("players"); return (file1)->metadata.getInt("players") < (file2)->metadata.getInt("players");
@ -83,7 +77,9 @@ namespace FileSorts
bool compareReleaseDate(const FileData* file1, const FileData* file2) bool compareReleaseDate(const FileData* file1, const FileData* file2)
{ {
return (file1)->metadata.getTime("releasedate") < (file2)->metadata.getTime("releasedate"); // since it's stored as an ISO string (YYYYMMDDTHHMMSS), we can compare as a string
// as it's a lot faster than the time casts and then time comparisons
return (file1)->metadata.get("releasedate") < (file2)->metadata.get("releasedate");
} }
bool compareGenre(const FileData* file1, const FileData* file2) bool compareGenre(const FileData* file1, const FileData* file2)

View file

@ -2,7 +2,6 @@
#include "Log.h" #include "Log.h"
#include "Util.h" #include "Util.h"
#include <boost/date_time/posix_time/time_formatters.hpp>
#include <pugixml/src/pugixml.hpp> #include <pugixml/src/pugixml.hpp>
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
@ -126,11 +125,6 @@ void MetaDataList::set(const std::string& key, const std::string& value)
mWasChanged = true; mWasChanged = true;
} }
void MetaDataList::setTime(const std::string& key, const boost::posix_time::ptime& time)
{
set(key, boost::posix_time::to_iso_string(time));
}
const std::string& MetaDataList::get(const std::string& key) const const std::string& MetaDataList::get(const std::string& key) const
{ {
return mMap.at(key); return mMap.at(key);
@ -146,11 +140,6 @@ float MetaDataList::getFloat(const std::string& key) const
return (float)atof(get(key).c_str()); return (float)atof(get(key).c_str());
} }
boost::posix_time::ptime MetaDataList::getTime(const std::string& key) const
{
return string_to_ptime(get(key), "%Y%m%dT%H%M%S%F%q");
}
bool MetaDataList::isDefault() bool MetaDataList::isDefault()
{ {
const std::vector<MetaDataDecl>& mdd = getMDD(); const std::vector<MetaDataDecl>& mdd = getMDD();

View file

@ -2,8 +2,8 @@
#ifndef ES_APP_META_DATA_H #ifndef ES_APP_META_DATA_H
#define ES_APP_META_DATA_H #define ES_APP_META_DATA_H
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <map>
namespace pugi { class xml_node; } namespace pugi { class xml_node; }
@ -50,12 +50,10 @@ public:
MetaDataList(MetaDataListType type); MetaDataList(MetaDataListType type);
void set(const std::string& key, const std::string& value); void set(const std::string& key, const std::string& value);
void setTime(const std::string& key, const boost::posix_time::ptime& time); //times are internally stored as ISO strings (e.g. boost::posix_time::to_iso_string(ptime))
const std::string& get(const std::string& key) const; const std::string& get(const std::string& key) const;
int getInt(const std::string& key) const; int getInt(const std::string& key) const;
float getFloat(const std::string& key) const; float getFloat(const std::string& key) const;
boost::posix_time::ptime getTime(const std::string& key) const;
bool isDefault(); bool isDefault();

View file

@ -1,5 +1,6 @@
#include "scrapers/GamesDBScraper.h" #include "scrapers/GamesDBScraper.h"
#include "utils/TimeUtil.h"
#include "FileData.h" #include "FileData.h"
#include "Log.h" #include "Log.h"
#include "PlatformId.h" #include "PlatformId.h"
@ -156,10 +157,7 @@ void TheGamesDBRequest::processGame(const pugi::xml_document& xmldoc, std::vecto
result.mdl.set("name", game.child("GameTitle").text().get()); result.mdl.set("name", game.child("GameTitle").text().get());
result.mdl.set("desc", game.child("Overview").text().get()); result.mdl.set("desc", game.child("Overview").text().get());
result.mdl.set("releasedate", Utils::Time::DateTime(Utils::Time::stringToTime(game.child("ReleaseDate").text().get(), "%m/%d/%Y")));
boost::posix_time::ptime rd = string_to_ptime(game.child("ReleaseDate").text().get(), "%m/%d/%Y");
result.mdl.setTime("releasedate", rd);
result.mdl.set("developer", game.child("Developer").text().get()); result.mdl.set("developer", game.child("Developer").text().get());
result.mdl.set("publisher", game.child("Publisher").text().get()); result.mdl.set("publisher", game.child("Publisher").text().get());
result.mdl.set("genre", game.child("Genres").first_child().text().get()); result.mdl.set("genre", game.child("Genres").first_child().text().get());

View file

@ -72,6 +72,7 @@ set(CORE_HEADERS
# Utils # Utils
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/FileSystemUtil.h ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/FileSystemUtil.h
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/StringUtil.h ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/StringUtil.h
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/TimeUtil.h
# Embedded assets (needed by ResourceManager) # Embedded assets (needed by ResourceManager)
${emulationstation-all_SOURCE_DIR}/data/Resources.h ${emulationstation-all_SOURCE_DIR}/data/Resources.h
@ -144,6 +145,7 @@ set(CORE_SOURCES
# Utils # Utils
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/FileSystemUtil.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/FileSystemUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/StringUtil.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/StringUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/utils/TimeUtil.cpp
) )
set(EMBEDDED_ASSET_SOURCES set(EMBEDDED_ASSET_SOURCES

View file

@ -3,7 +3,6 @@
#include "platform.h" #include "platform.h"
#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
@ -164,16 +163,6 @@ fs::path makeRelativePath(const fs::path& path, const fs::path& relativeTo, bool
return path; return path;
} }
boost::posix_time::ptime string_to_ptime(const std::string& str, const std::string& fmt)
{
std::istringstream ss(str);
ss.imbue(std::locale(std::locale::classic(), new boost::posix_time::time_input_facet(fmt))); //std::locale handles deleting the facet
boost::posix_time::ptime time;
ss >> time;
return time;
}
std::string strreplace(std::string str, const std::string& replace, const std::string& with) std::string strreplace(std::string str, const std::string& replace, const std::string& with)
{ {
size_t pos; size_t pos;

View file

@ -2,7 +2,6 @@
#ifndef ES_CORE_UTIL_H #ifndef ES_CORE_UTIL_H
#define ES_CORE_UTIL_H #define ES_CORE_UTIL_H
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
std::string strToUpper(const char* from); std::string strToUpper(const char* from);
@ -23,8 +22,6 @@ boost::filesystem::path makeRelativePath(const boost::filesystem::path& path, co
// if allowHome is true, also expands "~/my/path.sfc" to "/home/pi/my/path.sfc" // if allowHome is true, also expands "~/my/path.sfc" to "/home/pi/my/path.sfc"
boost::filesystem::path resolvePath(const boost::filesystem::path& path, const boost::filesystem::path& relativeTo, bool allowHome); boost::filesystem::path resolvePath(const boost::filesystem::path& path, const boost::filesystem::path& relativeTo, bool allowHome);
boost::posix_time::ptime string_to_ptime(const std::string& str, const std::string& fmt = "%Y%m%dT%H%M%S%F%q");
std::string escapePath(const boost::filesystem::path& path); std::string escapePath(const boost::filesystem::path& path);
std::string strreplace(std::string str, const std::string& replace, const std::string& with); std::string strreplace(std::string str, const std::string& replace, const std::string& with);

View file

@ -3,7 +3,6 @@
#include "resources/Font.h" #include "resources/Font.h"
#include "Renderer.h" #include "Renderer.h"
#include "Util.h" #include "Util.h"
#include <boost/date_time.hpp>
DateTimeComponent::DateTimeComponent(Window* window, DisplayMode dispMode) : GuiComponent(window), DateTimeComponent::DateTimeComponent(Window* window, DisplayMode dispMode) : GuiComponent(window),
mEditing(false), mEditIndex(0), mDisplayMode(dispMode), mRelativeUpdateAccumulator(0), mEditing(false), mEditIndex(0), mDisplayMode(dispMode), mRelativeUpdateAccumulator(0),
@ -34,9 +33,9 @@ bool DateTimeComponent::input(InputConfig* config, Input input)
mTimeBeforeEdit = mTime; mTimeBeforeEdit = mTime;
//initialize to now if unset //initialize to now if unset
if(mTime == boost::posix_time::not_a_date_time) if(mTime.getTime() == Utils::Time::NOT_A_DATE_TIME)
{ {
mTime = boost::posix_time::ptime(boost::gregorian::day_clock::local_day()); mTime = Utils::Time::now();
updateTextCache(); updateTextCache();
} }
} }
@ -62,39 +61,43 @@ bool DateTimeComponent::input(InputConfig* config, Input input)
if(incDir != 0) if(incDir != 0)
{ {
tm new_tm = boost::posix_time::to_tm(mTime); tm new_tm = mTime;
if(mEditIndex == 0) if(mEditIndex == 0)
{ {
new_tm.tm_mon += incDir; new_tm.tm_mon += incDir;
if(new_tm.tm_mon > 11) if(new_tm.tm_mon > 11)
new_tm.tm_mon = 11;
else if(new_tm.tm_mon < 0)
new_tm.tm_mon = 0; new_tm.tm_mon = 0;
else if(new_tm.tm_mon < 0)
new_tm.tm_mon = 11;
}else if(mEditIndex == 1) }
else if(mEditIndex == 1)
{ {
const int days_in_month = Utils::Time::daysInMonth(new_tm.tm_year + 1900, new_tm.tm_mon + 1);
new_tm.tm_mday += incDir; new_tm.tm_mday += incDir;
int days_in_month = mTime.date().end_of_month().day().as_number();
if(new_tm.tm_mday > days_in_month)
new_tm.tm_mday = days_in_month;
else if(new_tm.tm_mday < 1)
new_tm.tm_mday = 1;
}else if(mEditIndex == 2) if(new_tm.tm_mday > days_in_month)
new_tm.tm_mday = 1;
else if(new_tm.tm_mday < 1)
new_tm.tm_mday = days_in_month;
}
else if(mEditIndex == 2)
{ {
new_tm.tm_year += incDir; new_tm.tm_year += incDir;
if(new_tm.tm_year < 0) if(new_tm.tm_year < 0)
new_tm.tm_year = 0; new_tm.tm_year = 0;
} }
//validate day //validate day
int days_in_month = boost::gregorian::date((unsigned short)new_tm.tm_year + 1900, (unsigned short)new_tm.tm_mon + 1, 1).end_of_month().day().as_number(); const int days_in_month = Utils::Time::daysInMonth(new_tm.tm_year + 1900, new_tm.tm_mon + 1);
if(new_tm.tm_mday > days_in_month) if(new_tm.tm_mday > days_in_month)
new_tm.tm_mday = days_in_month; new_tm.tm_mday = days_in_month;
mTime = boost::posix_time::ptime_from_tm(new_tm); mTime = new_tm;
updateTextCache(); updateTextCache();
return true; return true;
@ -166,13 +169,13 @@ void DateTimeComponent::render(const Transform4x4f& parentTrans)
void DateTimeComponent::setValue(const std::string& val) void DateTimeComponent::setValue(const std::string& val)
{ {
mTime = string_to_ptime(val); mTime = val;
updateTextCache(); updateTextCache();
} }
std::string DateTimeComponent::getValue() const std::string DateTimeComponent::getValue() const
{ {
return boost::posix_time::to_iso_string(mTime); return mTime;
} }
DateTimeComponent::DisplayMode DateTimeComponent::getCurrentDisplayMode() const DateTimeComponent::DisplayMode DateTimeComponent::getCurrentDisplayMode() const
@ -203,40 +206,32 @@ std::string DateTimeComponent::getDisplayString(DisplayMode mode) const
case DISP_RELATIVE_TO_NOW: case DISP_RELATIVE_TO_NOW:
{ {
//relative time //relative time
using namespace boost::posix_time; if(mTime.getTime() == 0)
if(mTime == not_a_date_time)
return "never"; return "never";
ptime now = second_clock::universal_time(); Utils::Time::DateTime now(Utils::Time::now());
time_duration dur = now - mTime; Utils::Time::Duration dur(now.getTime() - mTime.getTime());
if(dur < seconds(2)) char buf[64];
return "just now";
if(dur < seconds(60))
return std::to_string((long long)dur.seconds()) + " secs ago";
if(dur < minutes(60))
return std::to_string((long long)dur.minutes()) + " min" + (dur < minutes(2) ? "" : "s") + " ago";
if(dur < hours(24))
return std::to_string((long long)dur.hours()) + " hour" + (dur < hours(2) ? "" : "s") + " ago";
long long days = (long long)(dur.hours() / 24); if(dur.getDays() > 0)
return std::to_string(days) + " day" + (days < 2 ? "" : "s") + " ago"; sprintf(buf, "%d day%s ago", dur.getDays(), (dur.getDays() > 1) ? "s" : "");
else if(dur.getHours() > 0)
sprintf(buf, "%d hour%s ago", dur.getHours(), (dur.getHours() > 1) ? "s" : "");
else if(dur.getMinutes() > 0)
sprintf(buf, "%d minute%s ago", dur.getMinutes(), (dur.getMinutes() > 1) ? "s" : "");
else
sprintf(buf, "%d second%s ago", dur.getSeconds(), (dur.getSeconds() > 1) ? "s" : "");
return std::string(buf);
} }
break; break;
} }
if(mTime == boost::posix_time::not_a_date_time) if(mTime.getTime() == 0)
return "unknown"; return "unknown";
boost::posix_time::time_facet* facet = new boost::posix_time::time_facet(); return Utils::Time::timeToString(mTime, fmt);
facet->format(fmt.c_str());
std::locale loc(std::locale::classic(), facet);
std::stringstream ss;
ss.imbue(loc);
ss << mTime;
return ss.str();
} }
std::shared_ptr<Font> DateTimeComponent::getFont() const std::shared_ptr<Font> DateTimeComponent::getFont() const

View file

@ -2,8 +2,8 @@
#ifndef ES_CORE_COMPONENTS_DATE_TIME_COMPONENT_H #ifndef ES_CORE_COMPONENTS_DATE_TIME_COMPONENT_H
#define ES_CORE_COMPONENTS_DATE_TIME_COMPONENT_H #define ES_CORE_COMPONENTS_DATE_TIME_COMPONENT_H
#include "utils/TimeUtil.h"
#include "GuiComponent.h" #include "GuiComponent.h"
#include <boost/date_time/posix_time/ptime.hpp>
class TextCache; class TextCache;
@ -49,8 +49,8 @@ private:
void updateTextCache(); void updateTextCache();
boost::posix_time::ptime mTime; Utils::Time::DateTime mTime;
boost::posix_time::ptime mTimeBeforeEdit; Utils::Time::DateTime mTimeBeforeEdit;
bool mEditing; bool mEditing;
int mEditIndex; int mEditIndex;

View file

@ -0,0 +1,286 @@
#include "utils/TimeUtil.h"
#include <time.h>
namespace Utils
{
namespace Time
{
DateTime::DateTime()
{
mTime = 0;
mTimeStruct = { 0, 0, 0, 1, 0, 0, 0, 0, -1 };
mIsoString = "00000000T000000";
} // Time
DateTime::DateTime(const time_t& _time)
{
setTime(_time);
} // Time
DateTime::DateTime(const tm& _timeStruct)
{
setTimeStruct(_timeStruct);
} // Time
DateTime::DateTime(const std::string& _isoString)
{
setIsoString(_isoString);
} // Time
DateTime::~DateTime()
{
} // ~Time
void DateTime::setTime(const time_t& _time)
{
if(_time < 0) mTime = 0;
else mTime = _time;
mTimeStruct = *localtime(&mTime);
mIsoString = timeToString(mTime);
} // setTime
void DateTime::setTimeStruct(const tm& _timeStruct)
{
setTime(mktime((tm*)&_timeStruct));
} // setTimeStruct
void DateTime::setIsoString(const std::string& _isoString)
{
setTime(stringToTime(_isoString));
} // setIsoString
Duration::Duration(const time_t& _time)
{
mTotalSeconds = (unsigned int)_time;
mDays = (mTotalSeconds - (mTotalSeconds % (60*60*24))) / (60*60*24);
mHours = ((mTotalSeconds % (60*60*24)) - (mTotalSeconds % (60*60))) / (60*60);
mMinutes = ((mTotalSeconds % (60*60)) - (mTotalSeconds % (60))) / 60;
mSeconds = mTotalSeconds % 60;
} // Duration
Duration::~Duration()
{
} // ~Duration
time_t now()
{
time_t time;
::time(&time);
return time;
} // now
time_t stringToTime(const std::string& _string, const std::string& _format)
{
const char* s = _string.c_str();
const char* f = _format.c_str();
tm timeStruct = { 0, 0, 0, 1, 0, 0, 0, 0, -1 };
int parsedChars = 0;
if(_string == "not-a-date-time")
return mktime(&timeStruct);
while(*f && (parsedChars < _string.length()))
{
if(*f == '%')
{
++f;
switch(*f++)
{
case 'Y': // The year [1970,xxxx]
{
if((parsedChars + 4) <= _string.length())
{
timeStruct.tm_year = (*s++ - '0') * 1000;
timeStruct.tm_year += (*s++ - '0') * 100;
timeStruct.tm_year += (*s++ - '0') * 10;
timeStruct.tm_year += (*s++ - '0');
if(timeStruct.tm_year >= 1900)
timeStruct.tm_year -= 1900;
}
parsedChars += 4;
}
break;
case 'm': // The month number [01,12]
{
if((parsedChars + 2) <= _string.length())
{
timeStruct.tm_mon = (*s++ - '0') * 10;
timeStruct.tm_mon += (*s++ - '0');
if(timeStruct.tm_mon >= 1)
timeStruct.tm_mon -= 1;
}
parsedChars += 2;
}
break;
case 'd': // The day of the month [01,31]
{
if((parsedChars + 2) <= _string.length())
{
timeStruct.tm_mday = (*s++ - '0') * 10;
timeStruct.tm_mday += (*s++ - '0');
}
parsedChars += 2;
}
break;
case 'H': // The hour (24-hour clock) [00,23]
{
if((parsedChars + 2) <= _string.length())
{
timeStruct.tm_hour = (*s++ - '0') * 10;
timeStruct.tm_hour += (*s++ - '0');
}
parsedChars += 2;
}
break;
case 'M': // The minute [00,59]
{
if((parsedChars + 2) <= _string.length())
{
timeStruct.tm_min = (*s++ - '0') * 10;
timeStruct.tm_min += (*s++ - '0');
}
parsedChars += 2;
}
break;
case 'S': // The second [00,59]
{
if((parsedChars + 2) <= _string.length())
{
timeStruct.tm_sec = (*s++ - '0') * 10;
timeStruct.tm_sec += (*s++ - '0');
}
parsedChars += 2;
}
break;
}
}
else
{
++s;
++f;
}
}
return mktime(&timeStruct);
} // stringToTime
std::string timeToString(const time_t& _time, const std::string& _format)
{
const char* f = _format.c_str();
const tm timeStruct = *localtime(&_time);
char buf[256] = { '\0' };
char* s = buf;
while(*f)
{
if(*f == '%')
{
++f;
switch(*f++)
{
case 'Y': // The year, including the century (1900)
{
const int year = timeStruct.tm_year + 1900;
*s++ = (char)((year - (year % 1000)) / 1000) + '0';
*s++ = (char)(((year % 1000) - (year % 100)) / 100) + '0';
*s++ = (char)(((year % 100) - (year % 10)) / 10) + '0';
*s++ = (char)(year % 10) + '0';
}
break;
case 'm': // The month number [00,11]
{
const int mon = timeStruct.tm_mon + 1;
*s++ = (char)(mon / 10) + '0';
*s++ = (char)(mon % 10) + '0';
}
break;
case 'd': // The day of the month [01,31]
{
*s++ = (char)(timeStruct.tm_mday / 10) + '0';
*s++ = (char)(timeStruct.tm_mday % 10) + '0';
}
break;
case 'H': // The hour (24-hour clock) [00,23]
{
*s++ = (char)(timeStruct.tm_hour / 10) + '0';
*s++ = (char)(timeStruct.tm_hour % 10) + '0';
}
break;
case 'M': // The minute [00,59]
{
*s++ = (char)(timeStruct.tm_min / 10) + '0';
*s++ = (char)(timeStruct.tm_min % 10) + '0';
}
break;
case 'S': // The second [00,59]
{
*s++ = (char)(timeStruct.tm_sec / 10) + '0';
*s++ = (char)(timeStruct.tm_sec % 10) + '0';
}
break;
}
}
else
{
*s++ = *f++;
}
*s = '\0';
}
return std::string(buf);
} // timeToString
int daysInMonth(const int _year, const int _month)
{
tm timeStruct = { 0, 0, 0, 0, _month, _year - 1900, 0, 0, -1 };
mktime(&timeStruct);
return timeStruct.tm_mday;
} // daysInMonth
int daysInYear(const int _year)
{
tm timeStruct = { 0, 0, 0, 0, 0, _year - 1900 + 1, 0, 0, -1 };
mktime(&timeStruct);
return timeStruct.tm_yday + 1;
} // daysInYear
} // Time::
} // Utils::

View file

@ -0,0 +1,78 @@
#pragma once
#ifndef ES_CORE_UTILS_TIME_UTIL_H
#define ES_CORE_UTILS_TIME_UTIL_H
#include <string>
namespace Utils
{
namespace Time
{
static int NOT_A_DATE_TIME = 0;
class DateTime
{
public:
DateTime();
DateTime(const time_t& _time);
DateTime(const tm& _timeStruct);
DateTime(const std::string& _isoString);
~DateTime();
const bool operator< (const DateTime& _other) const { return (mTime < _other.mTime); }
const bool operator<= (const DateTime& _other) const { return (mTime <= _other.mTime); }
const bool operator> (const DateTime& _other) const { return (mTime > _other.mTime); }
const bool operator>= (const DateTime& _other) const { return (mTime >= _other.mTime); }
operator time_t () const { return mTime; }
operator tm () const { return mTimeStruct; }
operator std::string() const { return mIsoString; }
void setTime (const time_t& _time);
const time_t& getTime () const { return mTime; }
void setTimeStruct(const tm& _timeStruct);
const tm& getTimeStruct() const { return mTimeStruct; }
void setIsoString (const std::string& _isoString);
const std::string& getIsoString () const { return mIsoString; }
private:
time_t mTime;
tm mTimeStruct;
std::string mIsoString;
}; // DateTime
class Duration
{
public:
Duration(const time_t& _time);
~Duration();
unsigned int getDays () const { return mDays; }
unsigned int getHours () const { return mHours; }
unsigned int getMinutes() const { return mMinutes; }
unsigned int getSeconds() const { return mSeconds; }
private:
unsigned int mTotalSeconds;
unsigned int mDays;
unsigned int mHours;
unsigned int mMinutes;
unsigned int mSeconds;
}; // Duration
time_t now ();
time_t stringToTime(const std::string& _string, const std::string& _format = "%Y%m%dT%H%M%S");
std::string timeToString(const time_t& _time, const std::string& _format = "%Y%m%dT%H%M%S");
int daysInMonth (const int _year, const int _month);
int daysInYear (const int _year);
} // Time::
} // Utils::
#endif // ES_CORE_UTILS_TIME_UTIL_H