mirror of
https://github.com/CraftyBoss/SuperMarioOdysseyOnline.git
synced 2024-11-19 17:55:16 +00:00
219 lines
6.1 KiB
C++
219 lines
6.1 KiB
C++
|
#include <nn/time.h>
|
||
|
|
||
|
#include "sead/basis/seadRawPrint.h"
|
||
|
#include "sead/time/seadDateTime.h"
|
||
|
#include "sead/time/seadDateUtil.h"
|
||
|
|
||
|
namespace sead
|
||
|
{
|
||
|
namespace
|
||
|
{
|
||
|
constexpr u32 sDaysOfMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||
|
constexpr u32 sDaysSinceJan1[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
|
||
|
|
||
|
u32 convertCalendarDateToDaysSince1970(const CalendarTime::Date& date)
|
||
|
{
|
||
|
// 0-indexed day.
|
||
|
const u32 d0 = date.mDay.getValue() - 1;
|
||
|
|
||
|
const u32 m = date.mMonth.getValueOneOrigin();
|
||
|
SEAD_ASSERT_MSG(1 <= m && m <= 12, "wrong month. correct range is [1, 12]. your param %d", m);
|
||
|
|
||
|
const u32 y = date.mYear.getValue();
|
||
|
SEAD_ASSERT_MSG(y >= 1970, "wrong year. your param %d, must after 1970.", y);
|
||
|
|
||
|
const u32 days_since_jan1 = sDaysSinceJan1[m - 1];
|
||
|
|
||
|
u32 num_days = d0 + days_since_jan1;
|
||
|
if (m >= 3 && DateUtil::isLeapYear(date.mYear.getValue()))
|
||
|
num_days = d0 + days_since_jan1 + 1;
|
||
|
|
||
|
u32 num_days_since_1970 = num_days + 365 * (date.mYear.getValue() - 1970);
|
||
|
if (date.mYear.getValue() > 1970)
|
||
|
{
|
||
|
u32 year = 1970;
|
||
|
do
|
||
|
{
|
||
|
num_days_since_1970 += DateUtil::isLeapYear(year);
|
||
|
++year;
|
||
|
} while (year < date.mYear.getValue());
|
||
|
}
|
||
|
|
||
|
return num_days_since_1970;
|
||
|
}
|
||
|
|
||
|
u64 convertCalendarTimeToSeconds(const CalendarTime::Time& time)
|
||
|
{
|
||
|
return 60 * (60 * time.mHour.getValue() + time.mMinute.getValue()) + time.mSecond.getValue();
|
||
|
}
|
||
|
|
||
|
u64 convertCalendarDateTimeToSeconds(const CalendarTime::Date& date, const CalendarTime::Time& time)
|
||
|
{
|
||
|
const u32 y = date.mYear.getValue();
|
||
|
|
||
|
const s32 m = date.mMonth.getValueOneOrigin();
|
||
|
const u32 m_idx = m - 1;
|
||
|
SEAD_ASSERT_MSG(1 <= m && m <= 12, "wrong month. correct range is [1, 12]. your param %d", m);
|
||
|
|
||
|
u32 num_days;
|
||
|
if (m == 2 && DateUtil::isLeapYear(y))
|
||
|
num_days = sDaysOfMonth[m_idx] + 1;
|
||
|
else
|
||
|
num_days = sDaysOfMonth[m_idx];
|
||
|
|
||
|
const u32 d = date.mDay.getValue();
|
||
|
SEAD_ASSERT_MSG(d <= num_days, "wrong day, correct range is [1, %d] (when year %4d month %2d)",
|
||
|
num_days, y, m);
|
||
|
|
||
|
const u32 days_since_1970 = convertCalendarDateToDaysSince1970(date);
|
||
|
return 3600 * 24 * days_since_1970 + convertCalendarTimeToSeconds(time);
|
||
|
}
|
||
|
|
||
|
u32 convertDaysToYears(u32* days)
|
||
|
{
|
||
|
u32 days_to_remove;
|
||
|
u32 i = 0;
|
||
|
u32 year = 1969;
|
||
|
do
|
||
|
{
|
||
|
++year;
|
||
|
days_to_remove = i;
|
||
|
i += DateUtil::isLeapYear(year) ? 366 : 365;
|
||
|
} while (i <= *days);
|
||
|
*days -= days_to_remove;
|
||
|
return year;
|
||
|
}
|
||
|
|
||
|
s32 convertDaysToMonth(u32* days, u32 year)
|
||
|
{
|
||
|
SEAD_ASSERT_MSG(*days <= 365, "wrong days. correct range is [0, 365]. your param %d", *days);
|
||
|
u32 days_to_remove;
|
||
|
u32 month_idx = 0;
|
||
|
u32 i = 0;
|
||
|
do
|
||
|
{
|
||
|
days_to_remove = i;
|
||
|
i += (month_idx == 1 && DateUtil::isLeapYear(year)) ? 29 : sDaysOfMonth[month_idx];
|
||
|
if (*days < i)
|
||
|
break;
|
||
|
++month_idx;
|
||
|
} while (month_idx < 12);
|
||
|
*days -= days_to_remove - 1;
|
||
|
return 1 + month_idx;
|
||
|
}
|
||
|
} // namespace
|
||
|
|
||
|
bool DateTime::mIsInitialized = false;
|
||
|
|
||
|
DateTime::DateTime(u64 unix_time)
|
||
|
{
|
||
|
mUnixTime = unix_time;
|
||
|
}
|
||
|
|
||
|
DateTime::DateTime(const CalendarTime& time)
|
||
|
{
|
||
|
setUnixTime(time);
|
||
|
}
|
||
|
|
||
|
DateTime::DateTime(const CalendarTime::Year& year, const CalendarTime::Month& month,
|
||
|
const CalendarTime::Day& day, const CalendarTime::Hour& hour,
|
||
|
const CalendarTime::Minute& minute, const CalendarTime::Second& second)
|
||
|
{
|
||
|
setUnixTime(year, month, day, hour, minute, second);
|
||
|
}
|
||
|
|
||
|
u64 DateTime::setNow()
|
||
|
{
|
||
|
initializeSystemTimeModule();
|
||
|
|
||
|
nn::time::PosixTime now;
|
||
|
nn::time::CalendarTime ctime;
|
||
|
nn::time::StandardUserSystemClock::GetCurrentTime(&now);
|
||
|
nn::time::ToCalendarTime(&ctime, nullptr, now);
|
||
|
|
||
|
const auto year = CalendarTime::Year(ctime.year);
|
||
|
const auto month = CalendarTime::Month::makeFromValueOneOrigin(ctime.month);
|
||
|
const auto day = CalendarTime::Day(ctime.day);
|
||
|
const auto hour = CalendarTime::Hour(ctime.hour);
|
||
|
const auto minute = CalendarTime::Minute(ctime.minute);
|
||
|
const auto second = CalendarTime::Second(ctime.second);
|
||
|
setUnixTime(year, month, day, hour, minute, second);
|
||
|
return mUnixTime;
|
||
|
}
|
||
|
|
||
|
u64 DateTime::setUnixTime(const CalendarTime& time)
|
||
|
{
|
||
|
mUnixTime = convertCalendarDateTimeToSeconds(time.getDate(), time.getTime());
|
||
|
return mUnixTime;
|
||
|
}
|
||
|
|
||
|
u64 DateTime::setUnixTime(const CalendarTime::Year& year, const CalendarTime::Month& month,
|
||
|
const CalendarTime::Day& day, const CalendarTime::Hour& hour,
|
||
|
const CalendarTime::Minute& minute, const CalendarTime::Second& second)
|
||
|
{
|
||
|
CalendarTime::Date date(year, month, day);
|
||
|
CalendarTime::Time time(hour, minute, second);
|
||
|
mUnixTime = convertCalendarDateTimeToSeconds(date, time);
|
||
|
return mUnixTime;
|
||
|
}
|
||
|
|
||
|
void DateTime::getCalendarTime(CalendarTime* calendar) const
|
||
|
{
|
||
|
u32 d = mUnixTime / (3600 * 24);
|
||
|
const u32 y = convertDaysToYears(&d);
|
||
|
const u32 m = convertDaysToMonth(&d, y);
|
||
|
|
||
|
CalendarTime::Time time;
|
||
|
const auto reduced_time = mUnixTime % (3600 * 24);
|
||
|
time.mHour.setValue(reduced_time / 3600);
|
||
|
time.mMinute.setValue((reduced_time % 3600) / 60);
|
||
|
time.mSecond.setValue(reduced_time % 60);
|
||
|
|
||
|
if (calendar)
|
||
|
{
|
||
|
calendar->setDate(CalendarTime::Date(y, CalendarTime::Month::makeFromValueOneOrigin(m), d));
|
||
|
calendar->setTime(time);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DateSpan DateTime::diff(DateTime time) const
|
||
|
{
|
||
|
return DateSpan(mUnixTime - time.mUnixTime);
|
||
|
}
|
||
|
|
||
|
DateSpan DateTime::diffToNow() const
|
||
|
{
|
||
|
DateTime now(0);
|
||
|
now.setNow();
|
||
|
return now.diff(*this);
|
||
|
}
|
||
|
|
||
|
void DateTime::initializeSystemTimeModule()
|
||
|
{
|
||
|
if (mIsInitialized)
|
||
|
return;
|
||
|
|
||
|
#ifdef NNSDK
|
||
|
if (!nn::time::IsInitialized())
|
||
|
nn::time::Initialize();
|
||
|
#endif
|
||
|
|
||
|
mIsInitialized = true;
|
||
|
}
|
||
|
|
||
|
DateSpan operator-(DateTime lhs, DateTime rhs)
|
||
|
{
|
||
|
return DateSpan(lhs.getUnixTime() - rhs.getUnixTime());
|
||
|
}
|
||
|
|
||
|
DateTime operator-(DateTime time, DateSpan span)
|
||
|
{
|
||
|
return DateTime(time.getUnixTime() - span.getSpan());
|
||
|
}
|
||
|
|
||
|
DateTime operator+(DateTime time, DateSpan span)
|
||
|
{
|
||
|
return DateTime(time.getUnixTime() + span.getSpan());
|
||
|
}
|
||
|
} // namespace sead
|