733 lines
20 KiB
C++
733 lines
20 KiB
C++
|
|
// Copyright (c) 2013-2015 IONU Security, Inc. All rights reserved.
|
||
|
|
//
|
||
|
|
// Time utility class
|
||
|
|
|
||
|
|
//#include <cstdio>
|
||
|
|
//#include <cstring>
|
||
|
|
//#include <ctype.h>
|
||
|
|
#include <sys/stat.h>
|
||
|
|
#ifdef WIN32
|
||
|
|
#include <Windows.h>
|
||
|
|
#else
|
||
|
|
#include <sys/time.h>
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#include "eyelog.h"
|
||
|
|
#include "eyetime.h"
|
||
|
|
#include "eyeutils.h"
|
||
|
|
|
||
|
|
using namespace sequencelogic;
|
||
|
|
|
||
|
|
static char timezones[] = {'Y','W','X','V','U','T','S','R','Q','P','O','N','Z','A','B','C','D','E','F','G','I','K','L','M','\0'};
|
||
|
|
static unsigned int monthlengths[] = {31,28,31,30,31,30,31,31,30,31,30,31};
|
||
|
|
static int monthnums[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
|
||
|
|
static int monthnumsleap[] = {6, 2, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
|
||
|
|
|
||
|
|
static bool isLeapYear(unsigned int nYear)
|
||
|
|
{
|
||
|
|
return (((nYear % 4) == 0) && (((nYear % 100) != 0) || ((nYear % 400) == 0)));
|
||
|
|
}
|
||
|
|
|
||
|
|
// Constructor that parses a date/time string
|
||
|
|
EyeTime::EyeTime (const char* timestr)
|
||
|
|
{
|
||
|
|
if (!SetTime (timestr)) {
|
||
|
|
daylight = 0;
|
||
|
|
utc = 0;
|
||
|
|
year = 0;
|
||
|
|
month = 0;
|
||
|
|
day = 0;
|
||
|
|
hour = 0;
|
||
|
|
minute = 0;
|
||
|
|
second = 0;
|
||
|
|
millisec = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Days since January 1st
|
||
|
|
void EyeTime::SetYearDay()
|
||
|
|
{
|
||
|
|
yday = day - 1; // Day of this month, but yday starts from 0
|
||
|
|
|
||
|
|
for (unsigned int i = 1; i < month; ++i)
|
||
|
|
yday += monthlengths[i-1];
|
||
|
|
|
||
|
|
// And, 1 for leap year, maybe...
|
||
|
|
if (isLeapYear(year) && (month > 2))
|
||
|
|
++yday;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Days since Sunday
|
||
|
|
void EyeTime::SetWeekDay()
|
||
|
|
{
|
||
|
|
unsigned int tmpDay = (year - 1900) / 4;
|
||
|
|
tmpDay += (year - 1900);
|
||
|
|
tmpDay += day;
|
||
|
|
if (isLeapYear(year))
|
||
|
|
tmpDay += monthnumsleap[month-1];
|
||
|
|
else
|
||
|
|
tmpDay += monthnums[month-1];
|
||
|
|
wday = tmpDay % 7;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool EyeTime::SetTimeMs (long long tMs)
|
||
|
|
{
|
||
|
|
bool bRetVal = false;
|
||
|
|
|
||
|
|
time_t timeSecs = (time_t)(tMs / 1000);
|
||
|
|
bRetVal = SetTime(timeSecs);
|
||
|
|
millisec = (unsigned int)(tMs % 1000);
|
||
|
|
|
||
|
|
return bRetVal;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool EyeTime::SetTime (time_t t)
|
||
|
|
{
|
||
|
|
struct tm tmpTime;
|
||
|
|
#ifdef WIN32
|
||
|
|
// Store in GMT...
|
||
|
|
::gmtime_s(&tmpTime, &t);
|
||
|
|
#else
|
||
|
|
gmtime_r(&t, &tmpTime);
|
||
|
|
#endif
|
||
|
|
|
||
|
|
year = tmpTime.tm_year + 1900; // tm structure has year as years since 1900
|
||
|
|
month = tmpTime.tm_mon + 1; // tm structure has Jan as month '0'
|
||
|
|
yday = tmpTime.tm_yday;
|
||
|
|
wday = tmpTime.tm_wday;
|
||
|
|
day = tmpTime.tm_mday;
|
||
|
|
hour = tmpTime.tm_hour;
|
||
|
|
minute = tmpTime.tm_min;
|
||
|
|
second = tmpTime.tm_sec;
|
||
|
|
millisec = 0;
|
||
|
|
utc = 0;
|
||
|
|
daylight = 0;
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
time_t EyeTime::GetTime()
|
||
|
|
{
|
||
|
|
struct tm tmpTime;
|
||
|
|
tmpTime.tm_year = year - 1900; // tm structure has year as years since 1900
|
||
|
|
tmpTime.tm_mon = month - 1; // tm structure has Jan as month '0'
|
||
|
|
tmpTime.tm_yday = yday;
|
||
|
|
tmpTime.tm_wday = wday;
|
||
|
|
tmpTime.tm_mday = day;
|
||
|
|
tmpTime.tm_hour = hour;
|
||
|
|
tmpTime.tm_min = minute;
|
||
|
|
tmpTime.tm_sec = second;
|
||
|
|
|
||
|
|
time_t retVal = ::mktime(&tmpTime);
|
||
|
|
return retVal;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef WIN32
|
||
|
|
bool EyeTime::SetTime (SYSTEMTIME sysTime)
|
||
|
|
{
|
||
|
|
year = sysTime.wYear;
|
||
|
|
month = sysTime.wMonth;
|
||
|
|
day = sysTime.wDay;
|
||
|
|
wday = sysTime.wDayOfWeek;
|
||
|
|
hour = sysTime.wHour;
|
||
|
|
minute = sysTime.wMinute;
|
||
|
|
second = sysTime.wSecond;
|
||
|
|
millisec = sysTime.wMilliseconds;
|
||
|
|
utc = 0;
|
||
|
|
|
||
|
|
SetYearDay();
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
SYSTEMTIME EyeTime::GetSysTime()
|
||
|
|
{
|
||
|
|
SYSTEMTIME retVal = {0};
|
||
|
|
|
||
|
|
retVal.wYear = static_cast<WORD>(year);
|
||
|
|
retVal.wMonth = static_cast<WORD>(month);
|
||
|
|
retVal.wDayOfWeek = static_cast<WORD>(wday);
|
||
|
|
retVal.wDay = static_cast<WORD>(day);
|
||
|
|
retVal.wHour = static_cast<WORD>(hour);
|
||
|
|
retVal.wMinute = static_cast<WORD>(minute);
|
||
|
|
retVal.wSecond = static_cast<WORD>(second);
|
||
|
|
retVal.wMilliseconds = static_cast<WORD>(millisec);
|
||
|
|
|
||
|
|
return retVal;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
long long EyeTime::GetTimeMs()
|
||
|
|
{
|
||
|
|
long long nRetVal = 0;
|
||
|
|
|
||
|
|
#ifdef WIN32
|
||
|
|
struct tm tmpTime = {};
|
||
|
|
#else
|
||
|
|
struct tm tmpTime = {0,0,0,0,0,0,0,0,0,0,0};
|
||
|
|
#endif
|
||
|
|
tmpTime.tm_year = year - 1900; // tm structure has year as years since 1900
|
||
|
|
tmpTime.tm_mon = month - 1; // tm structure has Jan as month '0'
|
||
|
|
tmpTime.tm_wday = yday;
|
||
|
|
tmpTime.tm_mday = day;
|
||
|
|
tmpTime.tm_hour = hour;
|
||
|
|
tmpTime.tm_min = minute;
|
||
|
|
tmpTime.tm_sec = second;
|
||
|
|
|
||
|
|
#ifdef WIN32
|
||
|
|
nRetVal = ((long long)::_mkgmtime(&tmpTime) * 1000) + millisec;
|
||
|
|
#elif defined(ANDROID)
|
||
|
|
char *pTZ = getenv("TZ");
|
||
|
|
setenv ("TZ", "", 1);
|
||
|
|
tzset();
|
||
|
|
nRetVal = ((long long)mktime(&tmpTime) * 1000) + millisec;
|
||
|
|
if (pTZ != NULL)
|
||
|
|
setenv("TZ", pTZ, 1);
|
||
|
|
else
|
||
|
|
unsetenv("TZ");
|
||
|
|
tzset();
|
||
|
|
#else
|
||
|
|
nRetVal = ((long long)::timegm(&tmpTime) * 1000) + millisec;
|
||
|
|
#endif
|
||
|
|
return nRetVal;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool EyeTime::SetTime (const char* timestr)
|
||
|
|
{
|
||
|
|
if (sequencelogic::StrLen (timestr, 8) == 0)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
daylight = 0;
|
||
|
|
utc = 0;
|
||
|
|
year = 0;
|
||
|
|
month = 0;
|
||
|
|
day = 0;
|
||
|
|
hour = 0;
|
||
|
|
minute = 0;
|
||
|
|
second = 0;
|
||
|
|
millisec = 0;
|
||
|
|
char delim = '\0';
|
||
|
|
char tdelim = '\0';
|
||
|
|
|
||
|
|
const char* ptr = timestr;
|
||
|
|
const char* token = ptr;
|
||
|
|
bool gothour = false;
|
||
|
|
bool gotmin = false;
|
||
|
|
bool gotsec = false;
|
||
|
|
bool gotmsec = false;
|
||
|
|
bool gotzone = false;
|
||
|
|
int val = 0;
|
||
|
|
int len = 0;
|
||
|
|
while (*ptr) {
|
||
|
|
switch (*ptr) {
|
||
|
|
case '-' :
|
||
|
|
case '+' :
|
||
|
|
case ':' :
|
||
|
|
case '.' :
|
||
|
|
case ' ' :
|
||
|
|
delim = tdelim;
|
||
|
|
tdelim = *ptr++;
|
||
|
|
break;
|
||
|
|
case '0' :
|
||
|
|
case '1' :
|
||
|
|
case '2' :
|
||
|
|
case '3' :
|
||
|
|
case '4' :
|
||
|
|
case '5' :
|
||
|
|
case '6' :
|
||
|
|
case '7' :
|
||
|
|
case '8' :
|
||
|
|
case '9' :
|
||
|
|
val = *ptr++ - '0';
|
||
|
|
while (*ptr) {
|
||
|
|
if (*ptr >= '0' && *ptr <='9')
|
||
|
|
val = val * 10 + (*ptr++ - '0');
|
||
|
|
else {
|
||
|
|
delim = tdelim;
|
||
|
|
tdelim = *ptr;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (year == 0) {
|
||
|
|
year = val;
|
||
|
|
if (year > 3000 || year < 1970) {
|
||
|
|
IONUDEBUG ("EyeTime::SetTime(%s) - invalid year field", timestr);
|
||
|
|
year = 2014;
|
||
|
|
month = 1;
|
||
|
|
day = 1;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (month == 0) {
|
||
|
|
month = val;
|
||
|
|
if (month > 12 || month < 1) {
|
||
|
|
IONUDEBUG ("EyeTime::SetTime(%s) - invalid month field", timestr);
|
||
|
|
month = 1;
|
||
|
|
day = 1;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (day == 0) {
|
||
|
|
day = val;
|
||
|
|
if (day < 1 || (day > monthlengths[month-1] && month != 2 && !isLeapYear(year) && day > 29)) {
|
||
|
|
IONUDEBUG ("EyeTime::SetTime(%s) - invalid day field", timestr);
|
||
|
|
day = 1;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (!gothour) {
|
||
|
|
hour = val;
|
||
|
|
gothour = true;
|
||
|
|
if (hour > 23) {
|
||
|
|
IONUDEBUG ("EyeTime::SetTime(%s) - invalid hour value %d", timestr, val);
|
||
|
|
hour = 0;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (!gotmin) {
|
||
|
|
minute = val;
|
||
|
|
gotmin = true;
|
||
|
|
if (minute > 59) {
|
||
|
|
IONUDEBUG ("EyeTime::SetTime(%s) - invalid minute value %d", timestr, val);
|
||
|
|
minute = 0;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (!gotsec) {
|
||
|
|
second = val;
|
||
|
|
gotsec = true;
|
||
|
|
if (second > 60) { // Allow for leap second
|
||
|
|
IONUDEBUG ("EyeTime::SetTime(%s) - invalid second value %d", timestr, val);
|
||
|
|
second = 0;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (delim == '.' && !gotmsec) {
|
||
|
|
millisec = val;
|
||
|
|
gotmsec = true;
|
||
|
|
if (millisec > 999) {
|
||
|
|
IONUDEBUG ("EyeTime::SetTime(%s) - invalid millisecond value %d", timestr, val);
|
||
|
|
millisec = 0;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// time value is an offset from UTC (for example, +01:00, -07:00)
|
||
|
|
else if ((delim == '-' || delim == '+') && !gotzone) {
|
||
|
|
if (val > 12) {
|
||
|
|
IONUDEBUG ("EyeTime::SetTime(%s) - invalid timezone value %d", timestr, val);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (delim == '-')
|
||
|
|
utc = -val;
|
||
|
|
else
|
||
|
|
utc = +val;
|
||
|
|
while (*ptr) ptr++; // Skip to end
|
||
|
|
gotzone = true;
|
||
|
|
ConvertToGMTime();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
IONUDEBUG ("EyeTime::SetTime(%s) - invalid numeric field %s", timestr, ptr);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
default :
|
||
|
|
while (*ptr) {
|
||
|
|
token = ptr;
|
||
|
|
if ((*ptr >= 'a' && *ptr <='z') || (*ptr >= 'A' && *ptr <='Z'))
|
||
|
|
ptr++;
|
||
|
|
else
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
len = (int)(ptr - token);
|
||
|
|
if (len >= 3) {
|
||
|
|
if (sequencelogic::StrnCmp (token, "Jan", 3) == 0) month = 1;
|
||
|
|
else if (sequencelogic::StrnCmp (token, "Feb", 3) == 0) month = 2;
|
||
|
|
else if (sequencelogic::StrnCmp (token, "Mar", 3) == 0) month = 3;
|
||
|
|
else if (sequencelogic::StrnCmp (token, "Apr", 3) == 0) month = 4;
|
||
|
|
else if (sequencelogic::StrnCmp (token, "May", 3) == 0) month = 5;
|
||
|
|
else if (sequencelogic::StrnCmp (token, "Jun", 3) == 0) month = 6;
|
||
|
|
else if (sequencelogic::StrnCmp (token, "Jul", 3) == 0) month = 7;
|
||
|
|
else if (sequencelogic::StrnCmp (token, "Aug", 3) == 0) month = 8;
|
||
|
|
else if (sequencelogic::StrnCmp (token, "Sep", 3) == 0) month = 9;
|
||
|
|
else if (sequencelogic::StrnCmp (token, "Oct", 3) == 0) month = 10;
|
||
|
|
else if (sequencelogic::StrnCmp (token, "Nov", 3) == 0) month = 11;
|
||
|
|
else if (sequencelogic::StrnCmp (token, "Dec", 3) == 0) month = 12;
|
||
|
|
}
|
||
|
|
else if (len == 1) {
|
||
|
|
for (int i = 0; i < 24; ++i) {
|
||
|
|
if (timezones[i] == *token) {
|
||
|
|
utc = i - 12;
|
||
|
|
ConvertToGMTime();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//else // Skip character and continue
|
||
|
|
// ptr++;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set the day of week and year
|
||
|
|
SetWeekDay();
|
||
|
|
SetYearDay();
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Constructor that initializes with the current time
|
||
|
|
EyeTime::EyeTime () {
|
||
|
|
utc = 0;
|
||
|
|
daylight = 0;
|
||
|
|
#ifdef WIN32
|
||
|
|
SYSTEMTIME stUTC;
|
||
|
|
GetSystemTime (&stUTC);
|
||
|
|
SetTime (stUTC);
|
||
|
|
#else
|
||
|
|
timeval tv;
|
||
|
|
gettimeofday(&tv, NULL);
|
||
|
|
struct tm tm;
|
||
|
|
gmtime_r(&(tv.tv_sec), &tm);
|
||
|
|
year = tm.tm_year + 1900;
|
||
|
|
month = tm.tm_mon + 1; // Posix starts at 0
|
||
|
|
day = tm.tm_mday;
|
||
|
|
yday = tm.tm_yday;
|
||
|
|
wday = tm.tm_wday;
|
||
|
|
hour = tm.tm_hour;
|
||
|
|
minute = tm.tm_min;
|
||
|
|
second = tm.tm_sec;
|
||
|
|
millisec = (unsigned int)(tv.tv_usec / 1000);
|
||
|
|
// Set the day of week
|
||
|
|
SetWeekDay();
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
EyeTime::~EyeTime () {
|
||
|
|
}
|
||
|
|
|
||
|
|
int EyeTime::Compare (const EyeTime* other) const
|
||
|
|
{
|
||
|
|
if (year > other->year) return 1;
|
||
|
|
if (year < other->year) return -1;
|
||
|
|
if (month > other->month) return 1;
|
||
|
|
if (month < other->month) return -1;
|
||
|
|
if (day > other->day) return 1;
|
||
|
|
if (day < other->day) return -1;
|
||
|
|
if (hour > other->hour) return 1;
|
||
|
|
if (hour < other->hour) return -1;
|
||
|
|
if (minute > other->minute) return 1;
|
||
|
|
if (minute < other->minute) return -1;
|
||
|
|
|
||
|
|
// Allow for rounding to the nearest second on one of the times
|
||
|
|
if (millisec > 0 && other->millisec == 0) {
|
||
|
|
unsigned int sec = second + (millisec > 499 ? 1 : 0);
|
||
|
|
if (sec > other->second) return 1;
|
||
|
|
if (sec < other->second) return -1;
|
||
|
|
}
|
||
|
|
else if (millisec == 0 && other->millisec > 0) {
|
||
|
|
unsigned int sec = other->second + (other->millisec > 499 ? 1 : 0);
|
||
|
|
if (second > sec) return 1;
|
||
|
|
if (second < sec) return -1;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if (second > other->second) return 1;
|
||
|
|
if (second < other->second) return -1;
|
||
|
|
if (millisec > other->millisec) return 1;
|
||
|
|
if (millisec < other->millisec) return -1;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get the creation(Windows)/modified(Unix) time from a file
|
||
|
|
bool EyeTime::GetFileTime (const std::string& path)
|
||
|
|
{
|
||
|
|
if (!sequencelogic::IsValidFilename (path))
|
||
|
|
return false;
|
||
|
|
|
||
|
|
#ifdef WIN32
|
||
|
|
HANDLE hFile = CreateFile (path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
||
|
|
return false;
|
||
|
|
else {
|
||
|
|
FILETIME ftCreate;
|
||
|
|
SYSTEMTIME stUTC;
|
||
|
|
|
||
|
|
// Retrieve the file creation time
|
||
|
|
if (!::GetFileTime (hFile, (LPFILETIME) NULL, (LPFILETIME) NULL, &ftCreate)) {
|
||
|
|
CloseHandle (hFile);
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (FileTimeToSystemTime (&ftCreate, &stUTC)) { // Convert the create time to UTC
|
||
|
|
year = stUTC.wYear + 1900;
|
||
|
|
month = stUTC.wMonth; // Windows starts at 1
|
||
|
|
day = stUTC.wDay;
|
||
|
|
wday = stUTC.wDayOfWeek;
|
||
|
|
hour = stUTC.wHour;
|
||
|
|
minute = stUTC.wMinute;
|
||
|
|
second = stUTC.wSecond;
|
||
|
|
millisec = stUTC.wMilliseconds;
|
||
|
|
SetYearDay();
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
IONUDEBUG("EyeTime::GetFileTime(%s) - FileTimeToSystemTime failed", path.c_str());
|
||
|
|
}
|
||
|
|
CloseHandle (hFile);
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
struct tm tm;
|
||
|
|
struct stat attrib;
|
||
|
|
if (stat (path.c_str(), &attrib) != 0)
|
||
|
|
return false;
|
||
|
|
gmtime_r (reinterpret_cast<const time_t *>(&(attrib.st_mtime)), &tm);
|
||
|
|
utc = 0;
|
||
|
|
year = tm.tm_year + 1900;
|
||
|
|
month = tm.tm_mon + 1; // Posix starts at 0
|
||
|
|
day = tm.tm_mday;
|
||
|
|
yday = tm.tm_yday;
|
||
|
|
wday = tm.tm_wday;
|
||
|
|
hour = tm.tm_hour;
|
||
|
|
minute = tm.tm_min;
|
||
|
|
second = tm.tm_sec;
|
||
|
|
#if defined(ANDROID)
|
||
|
|
millisec = (attrib.st_mtime_nsec / 1000000);
|
||
|
|
#elif !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
|
||
|
|
millisec = (unsigned int)(attrib.st_mtimespec.tv_nsec / 1000000);
|
||
|
|
#else
|
||
|
|
millisec = (unsigned int)(attrib.st_mtim.tv_nsec / 1000000);
|
||
|
|
#endif
|
||
|
|
SetWeekDay();
|
||
|
|
#endif
|
||
|
|
return (true);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set the creation(Windows)/modified(Unix) time of a file
|
||
|
|
bool EyeTime::SetFileTime (const std::string& path)
|
||
|
|
{
|
||
|
|
if (!sequencelogic::IsValidFilename (path))
|
||
|
|
return false;
|
||
|
|
|
||
|
|
#ifdef WIN32
|
||
|
|
SYSTEMTIME systime = GetSysTime();
|
||
|
|
FILETIME filetime;
|
||
|
|
SystemTimeToFileTime (&systime, &filetime);
|
||
|
|
|
||
|
|
// Get a handle to eyefile with file_write_attributes access
|
||
|
|
HANDLE hFile = CreateFile (path.c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||
|
|
IONUDEBUG ("EyeTime::SetFileTime(%s) failed invalid file handle", path.c_str());
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Set the file time on the file
|
||
|
|
if (!::SetFileTime (hFile, (LPFILETIME) NULL, (LPFILETIME) NULL, &filetime)) {
|
||
|
|
CloseHandle (hFile);
|
||
|
|
IONUDEBUG ("EyeTime::SetFileTime(%s) failed ::SetFileTime", path.c_str());
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
CloseHandle (hFile);
|
||
|
|
#else
|
||
|
|
struct timeval times[2];
|
||
|
|
times[0].tv_usec = millisec * 1000; // Access time
|
||
|
|
times[1].tv_usec = millisec * 1000; // Modification time
|
||
|
|
struct tm tm;
|
||
|
|
tm.tm_year = year - 1900;
|
||
|
|
tm.tm_mon = month - 1;
|
||
|
|
tm.tm_mday = day;
|
||
|
|
tm.tm_yday = yday;
|
||
|
|
tm.tm_wday = wday;
|
||
|
|
tm.tm_hour = hour;
|
||
|
|
tm.tm_min = minute;
|
||
|
|
tm.tm_sec = second;
|
||
|
|
//time_t t = mktime (&tm) Can't use this as it's localtime() inverse, need gmtime() inverse
|
||
|
|
// Compute seconds since the epoch using the POSIX formula
|
||
|
|
time_t t = tm.tm_sec + tm.tm_min*60 + tm.tm_hour*3600 + tm.tm_yday*86400 +
|
||
|
|
(tm.tm_year-70)*31536000 + ((tm.tm_year-69)/4)*86400 -
|
||
|
|
((tm.tm_year-1)/100)*86400 + ((tm.tm_year+299)/400)*86400;
|
||
|
|
if (t > 0) {
|
||
|
|
times[0].tv_sec = t;
|
||
|
|
times[1].tv_sec = t;
|
||
|
|
if (utimes (path.c_str(), times) != 0) {
|
||
|
|
IONUDEBUG ("EyeTime::SetFileTime(%s) failed utimes()", path.c_str());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
IONUDEBUG ("EyeTime::SetFileTime(%s) failed invalid time", path.c_str());
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
// If corrupted, cap to legal values
|
||
|
|
void EyeTime::Cap()
|
||
|
|
{
|
||
|
|
if (year > 3000 || year < 1970) year = 2014;
|
||
|
|
if (month < 1 || month > 12) month = 1;
|
||
|
|
if (day < 1 || (day > monthlengths[month-1] && month != 2 && !isLeapYear(year) && day > 29)) day = 1;
|
||
|
|
if (hour > 23) hour = 1;
|
||
|
|
if (minute > 60) minute = 1;
|
||
|
|
if (second > 61) second = 1;
|
||
|
|
if (millisec > 999) millisec = 1;
|
||
|
|
if (utc < -12 || utc > 11) utc = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Format time as ISO 8601 formatted string (20 characters)
|
||
|
|
const char* EyeTime::GetISO8601Time ()
|
||
|
|
{
|
||
|
|
Cap();
|
||
|
|
sprintf(_isodate, "%04u-%02u-%02uT%02u:%02u:%02uZ", year, month, day, hour, minute, second);
|
||
|
|
return _isodate;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Format time as ISO 8601 formatted string, with millisecs (24 characters)
|
||
|
|
const char* EyeTime::GetISO8601TimeMs ()
|
||
|
|
{
|
||
|
|
Cap();
|
||
|
|
sprintf(_isodate, "%04u-%02u-%02uT%02u:%02u:%02u.%03uZ", year, month, day, hour, minute, second, millisec);
|
||
|
|
return _isodate;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Format time as ISO 8601 formatted string (20 characters)
|
||
|
|
const char* EyeTime::GetLocalISO8601Time ()
|
||
|
|
{
|
||
|
|
ConvertToLocalTime();
|
||
|
|
sprintf(_isodate, "%04u-%02u-%02uT%02u:%02u:%02u%c", year, month, day, hour, minute, second, timezones[utc+12]);
|
||
|
|
ConvertToGMTime();
|
||
|
|
return _isodate;
|
||
|
|
}
|
||
|
|
|
||
|
|
void EyeTime::ConvertToLocalTime()
|
||
|
|
{
|
||
|
|
// Convert to Local as needed
|
||
|
|
int offset = utc + daylight;
|
||
|
|
if (offset != 0) {
|
||
|
|
if ((int)hour + offset > 24) {
|
||
|
|
hour = (int)hour + offset - 24;
|
||
|
|
if (++day > monthlengths[month] && !(day == 29 && month == 2 && year % 4 == 0)) {
|
||
|
|
if (month == 12) {
|
||
|
|
month = 1;
|
||
|
|
year++;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
month++;
|
||
|
|
day = 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if ((int)hour + offset < 0) {
|
||
|
|
hour = (int)hour + offset + 24;
|
||
|
|
if (--day < 1) {
|
||
|
|
if (month == 1) {
|
||
|
|
month = 12;
|
||
|
|
year--;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
month--;
|
||
|
|
if (month == 2 && year % 4 == 0)
|
||
|
|
day = 29;
|
||
|
|
else
|
||
|
|
day = monthlengths[month-1];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
hour += offset;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void EyeTime::ConvertToGMTime()
|
||
|
|
{
|
||
|
|
// Convert to GMT as needed
|
||
|
|
int offset = utc - daylight;
|
||
|
|
if (offset != 0) {
|
||
|
|
if ((int)hour - offset >= 24) {
|
||
|
|
hour = (int)hour + offset - 24;
|
||
|
|
if (++day > monthlengths[month] && !(day == 29 && month == 2 && year % 4 == 0)) {
|
||
|
|
if (month == 12) {
|
||
|
|
month = 1;
|
||
|
|
year++;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
month++;
|
||
|
|
day = 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if ((int)hour - offset < 0) {
|
||
|
|
hour = (int)hour + offset + 24;
|
||
|
|
if (--day < 1) {
|
||
|
|
if (month == 1) {
|
||
|
|
month = 12;
|
||
|
|
year--;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
month--;
|
||
|
|
if (month == 2 && year % 4 == 0)
|
||
|
|
day = 29;
|
||
|
|
else
|
||
|
|
day = monthlengths[month-1];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
hour -= offset;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Format time as a Unix timestamp, long, usually 10 digits
|
||
|
|
const char* EyeTime::GetUnixTime ()
|
||
|
|
{
|
||
|
|
double epoch = static_cast<double>(GetTimeMs()) / 1000.0;
|
||
|
|
sprintf (_isodate, "%0.0f", epoch);
|
||
|
|
return _isodate;
|
||
|
|
}
|
||
|
|
|
||
|
|
double EyeTime::SecondsFromNow ()
|
||
|
|
{
|
||
|
|
int tm_year = year - 1900;
|
||
|
|
#ifdef WIN32
|
||
|
|
SYSTEMTIME stUTC;
|
||
|
|
GetSystemTime (&stUTC);
|
||
|
|
|
||
|
|
int tm_yday = stUTC.wDay - 1; // Day of the month but yday starts at 0
|
||
|
|
int tm_nyear = stUTC.wYear - 1900;
|
||
|
|
for (int i = 0; i < 12; ++i) {
|
||
|
|
if (i + 1 < stUTC.wMonth) {
|
||
|
|
tm_yday += monthlengths[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// Account for leap years
|
||
|
|
if (stUTC.wMonth > 2 && isLeapYear (year))
|
||
|
|
tm_yday++;
|
||
|
|
|
||
|
|
double snow = stUTC.wSecond + stUTC.wMinute*60 + stUTC.wHour*3600 + tm_yday*86400 +
|
||
|
|
(tm_nyear-70)*31536000 + ((tm_nyear-69)/4)*86400 -
|
||
|
|
((tm_nyear-1)/100)*86400 + ((tm_nyear+299)/400)*86400;
|
||
|
|
#else
|
||
|
|
time_t now;
|
||
|
|
time (&now);
|
||
|
|
struct tm tm_now;
|
||
|
|
gmtime_r(&now, &tm_now);
|
||
|
|
|
||
|
|
double snow = tm_now.tm_sec + tm_now.tm_min*60 + tm_now.tm_hour*3600 + tm_now.tm_yday*86400 +
|
||
|
|
(tm_now.tm_year-70)*31536000 + ((tm_now.tm_year-69)/4)*86400 -
|
||
|
|
((tm_now.tm_year-1)/100)*86400 + ((tm_now.tm_year+299)/400)*86400;
|
||
|
|
#endif
|
||
|
|
double sthen = second + minute*60 + hour*3600 + yday*86400 +
|
||
|
|
(tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
|
||
|
|
((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400;
|
||
|
|
return (snow - sthen);
|
||
|
|
}
|
||
|
|
|
||
|
|
void EyeTime::Dump()
|
||
|
|
{
|
||
|
|
std::cout << "year=" << year << " month=" << month << " day=" << day << " wday=" << wday << " yday=" << yday;
|
||
|
|
std::cout << " hour=" << hour << " min=" << minute << " sec=" << second << " ms=" << millisec << " tz=" << utc;
|
||
|
|
std::cout << std::endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
namespace sequencelogic
|
||
|
|
{
|
||
|
|
std::ostream& operator<<(std::ostream &out, EyeTime &et)
|
||
|
|
{
|
||
|
|
out << et.GetISO8601Time();
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|