1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-10 15:39:02 +00:00
OpenMW/apps/openmw/mwworld/timestamp.cpp
elsid 25ead80d8b
Fix hour modulo expression
Round result of std::fmod(hours, 24) to the nearest float below 24 on double to
float conversion when it is not. Add special type and conversion function along
with tests to be used in all places where such conversion happens.

To avoid producing hours equal to 24 due to double to float precision loss.
2022-12-28 00:04:04 +01:00

126 lines
2.7 KiB
C++

#include "timestamp.hpp"
#include <cmath>
#include <stdexcept>
#include <string>
#include <components/esm/defs.hpp>
#include "duration.hpp"
namespace MWWorld
{
TimeStamp::TimeStamp(float hour, int day)
: mHour(hour)
, mDay(day)
{
if (hour < 0 || hour >= 24)
throw std::runtime_error("invalid time stamp hour: " + std::to_string(hour));
}
float TimeStamp::getHour() const
{
return mHour;
}
int TimeStamp::getDay() const
{
return mDay;
}
TimeStamp& TimeStamp::operator+=(double hours)
{
if (hours < 0)
throw std::runtime_error("can't move time stamp backwards in time");
const Duration duration = Duration::fromHours(mHour + hours);
mHour = duration.getHours();
mDay += duration.getDays();
return *this;
}
bool operator==(const TimeStamp& left, const TimeStamp& right)
{
return left.getHour() == right.getHour() && left.getDay() == right.getDay();
}
bool operator!=(const TimeStamp& left, const TimeStamp& right)
{
return !(left == right);
}
bool operator<(const TimeStamp& left, const TimeStamp& right)
{
if (left.getDay() < right.getDay())
return true;
if (left.getDay() > right.getDay())
return false;
return left.getHour() < right.getHour();
}
bool operator<=(const TimeStamp& left, const TimeStamp& right)
{
return left < right || left == right;
}
bool operator>(const TimeStamp& left, const TimeStamp& right)
{
return !(left <= right);
}
bool operator>=(const TimeStamp& left, const TimeStamp& right)
{
return !(left < right);
}
TimeStamp operator+(const TimeStamp& stamp, double hours)
{
return TimeStamp(stamp) += hours;
}
TimeStamp operator+(double hours, const TimeStamp& stamp)
{
return TimeStamp(stamp) += hours;
}
double operator-(const TimeStamp& left, const TimeStamp& right)
{
if (left < right)
return -(right - left);
int days = left.getDay() - right.getDay();
double hours = 0;
if (left.getHour() < right.getHour())
{
hours = 24 - right.getHour() + left.getHour();
--days;
}
else
{
hours = left.getHour() - right.getHour();
}
return hours + 24 * days;
}
ESM::TimeStamp TimeStamp::toEsm() const
{
ESM::TimeStamp ret;
ret.mDay = mDay;
ret.mHour = mHour;
return ret;
}
TimeStamp::TimeStamp(const ESM::TimeStamp& esm)
{
mDay = esm.mDay;
mHour = esm.mHour;
}
}