#ifdef _MSC_VER
#include "stdafx.h"
#else
#include "config.h"
#endif
#include "TimeRange.h"
#include "Utility.h"
namespace FIX {
TimeRange::TimeRange(const UtcTimeOnly &startTime, const UtcTimeOnly &endTime, int startDay, int endDay)
: m_startTime(startTime),
m_endTime(endTime),
m_startDay(startDay),
m_endDay(endDay),
m_useLocalTime(false) {
if (startDay > 0 && endDay > 0 && startDay == endDay && endTime > startTime) {
m_endTime = m_startTime;
}
}
TimeRange::TimeRange(const LocalTimeOnly &startTime, const LocalTimeOnly &endTime, int startDay, int endDay)
: m_startTime(startTime),
m_endTime(endTime),
m_startDay(startDay),
m_endDay(endDay),
m_useLocalTime(true) {
if (startDay > 0 && endDay > 0 && startDay == endDay && endTime > startTime) {
m_endTime = m_startTime;
}
}
int TimeRange::getRangeStartDate(const DateTime &time, int startDay, const DateTime &startTime) {
if (time.getWeekDay() > startDay) {
return time.getJulianDate() - time.getWeekDay() + startDay;
} else if (time.getWeekDay() < startDay) {
return time.getJulianDate() - time.getWeekDay() + startDay - 7;
} else {
if (UtcTimeOnly(time) >= UtcTimeOnly(startTime)) {
return time.getJulianDate();
} else {
return time.getJulianDate() - 7;
}
}
}
bool TimeRange::isInRange(const DateTime &start, const DateTime &end, const DateTime &time) {
UtcTimeOnly timeOnly(time);
if (start < end) {
return (timeOnly >= start && timeOnly <= end);
} else {
return (timeOnly >= start || timeOnly <= end);
}
}
bool TimeRange::isInRange(
const DateTime &startTime,
const DateTime &endTime,
int startDay,
int endDay,
const DateTime &time,
int day) {
UtcTimeOnly timeOnly(time);
if (startDay == endDay) {
if (day != startDay) {
return true;
}
return isInRange(startTime, endTime, time);
} else if (startDay < endDay) {
if (day < startDay || day > endDay) {
return false;
} else if (day == startDay && timeOnly < startTime) {
return false;
} else if (day == endDay && timeOnly > endTime) {
return false;
}
} else if (startDay > endDay) {
if (day < startDay && day > endDay) {
return false;
} else if (day == startDay && timeOnly < startTime) {
return false;
} else if (day == endDay && timeOnly > endTime) {
return false;
}
}
return true;
}
bool TimeRange::isInRange(
const DateTime &startTime,
const DateTime &endTime,
int startDay,
int endDay,
const DateTime &time) {
return isInRange(startTime, endTime, startDay, endDay, time, time.getWeekDay());
}
bool TimeRange::isInSameRange(
const DateTime &start,
const DateTime &end,
const DateTime &time1,
const DateTime &time2) {
if (!isInRange(start, end, time1)) {
return false;
}
if (!isInRange(start, end, time2)) {
return false;
}
if (time1 == time2) {
return true;
}
if (start < end || start == end) {
UtcDate time1Date(time1);
UtcDate time2Date(time2);
return time1Date == time2Date;
} else {
int sessionLength = DateTime::SECONDS_PER_DAY - (start - end);
if (time1 > time2) {
UtcTimeOnly time2TimeOnly = UtcTimeOnly(time2);
long delta = time2TimeOnly - start;
if (delta < 0) {
delta = DateTime::SECONDS_PER_DAY - labs(delta);
}
return (time1 - time2) < (sessionLength - delta);
} else {
return (time2 - time1) < sessionLength;
}
}
}
bool TimeRange::isInSameRange(
const DateTime &startTime,
const DateTime &endTime,
int startDay,
int endDay,
const DateTime &time1,
const DateTime &time2) {
if (!isInRange(startTime, endTime, startDay, endDay, time1, time1.getWeekDay())) {
return false;
}
if (!isInRange(startTime, endTime, startDay, endDay, time2, time2.getWeekDay())) {
return false;
}
if (startDay != endDay) {
int time1RangeStartDate = getRangeStartDate(time1, startDay, startTime);
int time2RangeStartDate = getRangeStartDate(time2, startDay, startTime);
return time1RangeStartDate == time2RangeStartDate;
} else {
int day1 = time1.getJulianDate();
int day2 = time2.getJulianDate();
if (time1.getJulianDate() == time2.getJulianDate() && startDay == time1.getWeekDay()) {
auto time1_utcTimeOnly = UtcTimeOnly(time1);
auto time2_utcTimeOnly = UtcTimeOnly(time2);
auto startTime_utcTimeOnly = UtcTimeOnly(startTime);
auto endTime_utcTimeOnly = UtcTimeOnly(endTime);
bool bothBeforeEndOfRange = time1_utcTimeOnly <= endTime_utcTimeOnly && time2_utcTimeOnly <= endTime_utcTimeOnly;
bool bothAfterStartOfRange
= time1_utcTimeOnly >= startTime_utcTimeOnly && time2_utcTimeOnly >= startTime_utcTimeOnly;
return bothBeforeEndOfRange || bothAfterStartOfRange;
}
else if (day1 == day2 && startDay != time1.getWeekDay()) {
return true;
}
else if (abs(day1 - day2) > 7) {
return false;
}
else if (abs(day1 - day2) == 7) {
if (time1.getWeekDay() != startDay) {
return false;
}
DateTime earlierTime, laterTime;
if (day2 > day1) {
earlierTime = time1;
laterTime = time2;
} else {
earlierTime = time2;
laterTime = time1;
}
return UtcTimeOnly(earlierTime) >= UtcTimeOnly(startTime) && UtcTimeOnly(laterTime) <= UtcTimeOnly(endTime);
}
else {
int time1RangeStartDate = getRangeStartDate(time1, startDay, startTime);
int time2RangeStartDate = getRangeStartDate(time2, startDay, startTime);
return time1RangeStartDate == time2RangeStartDate;
}
}
}
}