/***************************************************************************************** * * * OpenSpace * * * * Copyright (c) 2014-2020 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * * without restriction, including without limitation the rights to use, copy, modify, * * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to the following * * conditions: * * * * The above copyright notice and this permission notice shall be included in all copies * * or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ #ifndef __OPENSPACE_CORE___TIMECONVERSION___H__ #define __OPENSPACE_CORE___TIMECONVERSION___H__ #include #include #include #include #include namespace openspace { constexpr double SecondsPerYear = 31556952; // seconds in average Gregorian year constexpr double SecondsPerMonth = SecondsPerYear / 12; constexpr double SecondsPerDay = static_cast( std::chrono::seconds(std::chrono::hours(24)).count() ); constexpr double SecondsPerHour = static_cast( std::chrono::seconds(std::chrono::hours(1)).count() ); constexpr double SecondsPerMinute = static_cast( std::chrono::seconds(std::chrono::minutes(1)).count() ); // Assumption: static_cast(TimeUnit) == position in the list enum class TimeUnit { Nanosecond = 0, Microsecond, Millisecond, Second, Minute, Hour, Day, Month, Year }; // Assumption: Unit names are sequential in memory constexpr const char* TimeUnitNanosecond = "nanosecond"; constexpr const char* TimeUnitMicrosecond = "microsecond"; constexpr const char* TimeUnitMillisecond = "millisecond"; constexpr const char* TimeUnitSecond = "second"; constexpr const char* TimeUnitMinute = "minute"; constexpr const char* TimeUnitHour = "hour"; constexpr const char* TimeUnitDay = "day"; constexpr const char* TimeUnitMonth = "month"; constexpr const char* TimeUnitYear = "year"; // Assumption: Unit names are sequential in memory constexpr const char* TimeUnitNanoseconds = "nanoseconds"; constexpr const char* TimeUnitMicroseconds = "microseconds"; constexpr const char* TimeUnitMilliseconds = "milliseconds"; constexpr const char* TimeUnitSeconds = "seconds"; constexpr const char* TimeUnitMinutes = "minutes"; constexpr const char* TimeUnitHours = "hours"; constexpr const char* TimeUnitDays = "days"; constexpr const char* TimeUnitMonths = "months"; constexpr const char* TimeUnitYears = "years"; constexpr const std::array(TimeUnit::Year) + 1> TimeUnits = { TimeUnit::Nanosecond, TimeUnit::Microsecond, TimeUnit::Millisecond, TimeUnit::Second, TimeUnit::Minute, TimeUnit::Hour, TimeUnit::Day, TimeUnit::Month, TimeUnit::Year }; constexpr const std::array(TimeUnit::Year) + 1> TimeUnitNamesSingular = { TimeUnitNanosecond, TimeUnitMicrosecond, TimeUnitMillisecond, TimeUnitSecond, TimeUnitMinute, TimeUnitHour, TimeUnitDay, TimeUnitMonth, TimeUnitYear }; constexpr const std::array(TimeUnit::Year) + 1> TimeUnitNamesPlural = { TimeUnitNanoseconds, TimeUnitMicroseconds, TimeUnitMilliseconds, TimeUnitSeconds, TimeUnitMinutes, TimeUnitHours, TimeUnitDays, TimeUnitMonths, TimeUnitYears }; constexpr bool isValidTimeUnitName(const char* name) { int i = 0; for (const char* val : TimeUnitNamesSingular) { if (ghoul::equal(name, val)) { return true; } ++i; } i = 0; for (const char* val : TimeUnitNamesPlural) { if (ghoul::equal(name, val)) { return true; } ++i; } return false; } constexpr const char* nameForTimeUnit(TimeUnit unit, bool pluralForm = false) { switch (unit) { case TimeUnit::Nanosecond: case TimeUnit::Microsecond: case TimeUnit::Millisecond: case TimeUnit::Second: case TimeUnit::Minute: case TimeUnit::Hour: case TimeUnit::Day: case TimeUnit::Month: case TimeUnit::Year: if (pluralForm) { return TimeUnitNamesPlural[static_cast(unit)]; } else { return TimeUnitNamesSingular[static_cast(unit)]; } default: throw ghoul::MissingCaseException(); } } constexpr TimeUnit timeUnitFromString(const char* unitName) { int found = -1; int i = 0; for (const char* val : TimeUnitNamesSingular) { if (ghoul::equal(unitName, val)) { found = i; break; } ++i; } i = 0; for (const char* val : TimeUnitNamesPlural) { if (ghoul::equal(unitName, val)) { found = i; break; } ++i; } if (found != -1) { return static_cast(found); } else { throw ghoul::MissingCaseException(); } } std::pair simplifyTime(double seconds, bool forceSingularForm = false); constexpr double convertTime(double t, TimeUnit sourceUnit, TimeUnit destinationUnit) { double seconds = t; switch (sourceUnit) { case TimeUnit::Nanosecond: seconds = t * 1e-9; break; case TimeUnit::Microsecond: seconds = t * 1e-6; break; case TimeUnit::Millisecond: seconds = t * 1e-3; break; case TimeUnit::Minute: seconds = t * SecondsPerMinute; break; case TimeUnit::Hour: seconds = t * SecondsPerHour; break; case TimeUnit::Day: seconds = t * SecondsPerDay; break; case TimeUnit::Month: seconds = t * SecondsPerMonth; break; case TimeUnit::Year: seconds = t * SecondsPerYear; break; default: ; } switch (destinationUnit) { case TimeUnit::Nanosecond: return seconds / 1e-9; case TimeUnit::Microsecond: return seconds / 1e-6; case TimeUnit::Millisecond: return seconds / 1e-3; case TimeUnit::Second: return seconds; case TimeUnit::Minute: return seconds / SecondsPerMinute; case TimeUnit::Hour: return seconds / SecondsPerHour; case TimeUnit::Day: return seconds / SecondsPerDay; case TimeUnit::Month: return seconds / SecondsPerMonth; case TimeUnit::Year: return seconds / SecondsPerYear; default: throw ghoul::MissingCaseException(); } } } // namespace openspace #endif // __OPENSPACE_CORE___TIMECONVERSION___H__