AuroraRuntime/Include/Aurora/Time/TM.hpp
2023-10-07 20:04:47 +01:00

140 lines
6.0 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: TM.hpp
Date: 2022-1-24
Author: Reece
***/
#pragma once
namespace Aurora::Time
{
// This type is intended for interoperability with ANSI c, the Aurora Epoch, and planned calendar APIs
struct tm
{
int year {}; // The absolute gregorian-calendar year
int mon {}; // Months since January
int mday {}; // Days since last month
AuOptional<int> wday {}; // Days since Monday [usually ignored]
AuOptional<int> yday {}; // Days since January [usually ignored]
int hour {}; // Hours since yesterday
int min {}; // Minutes since the hour
int sec {}; // Seconds since the minute
AuOptionalEx<bool> isdst {};
AuOptionalEx<int> knownMinutesWest {}; // Known minutes west - this is the opposite of Linux's minutes east.
// RESERVED FOR FUTURE CALENDAR API
template<typename Dest_t>
void CopyTo(Dest_t &out) const
{
out.tm_sec = sec;
out.tm_min = min;
out.tm_hour = hour;
out.tm_mday = mday + 1;
out.tm_mon = mon;
#if 0
if (year < 1900)
{
out.tm_year = 0;
}
else
#endif
{
out.tm_year = year - 1900;
}
if (wday)
{
auto cur = wday.value();
if (cur == 6) // ^1
{
out.tm_wday = 0;
}
else
{
out.tm_wday = cur + 1;
}
}
else
{
out.tm_wday = -1;
}
out.tm_yday = yday.value_or(-1);
if (!isdst.HasValue())
{
out.tm_isdst = -1;
}
else
{
out.tm_isdst = isdst.value();
}
}
template<typename In_t>
void CopyFrom(const In_t &in)
{
sec = in.tm_sec;
min = in.tm_min;
hour = in.tm_hour;
mday = in.tm_mday - 1;
mon = in.tm_mon;
year = in.tm_year + 1900;
if (in.tm_wday == 0) // ^1
{
wday = 6;
}
else
{
wday = in.tm_wday - 1;
}
if (sec > 59) // ^2
{
sec = 59;
}
yday = in.tm_yday;
isdst = in.tm_isdst; // (dont normalize -1. it's a quirk of most modern CRTs we can exploit to easily solve the [user-input + how do i guess DST] issue)
// (stupid c programs shouldn't be exploiting this anyway. assume all std::tm, ::tm, and similar types calling into us follow boolean logic)
}
inline void Update()
{ /* no-op for now. */ }
private:
friend struct TMIntlAccessor;
AuUInt64 localization_[2] {};
// reserved for uncommitted and experimental calendar APIs
// currently defined as:
// u64 uKnownAuroraEpoch
// u64 optCalendarType
//
// Where calendar types are used to convert day orders of magnitude via the JDN offset by -12 hours, and then the remaining hours added back onto the day
// If !optCalendarType && isdst.value() == true, optCalendarType = gregorian / must be normalized
// If !optCalendarType && isdst.value() == false, optCalendarType = gregorian
// optCalendarType = ECalendarType, with gregorian being 0, NULL, and default initialized
// With uKnownAuroraEpoch leaking in from relevant internal AuTime APIs, it should be possible to create perfect time-zone and duration add/substract APIs on top of this
// We just need a means to go from uKnownAuroraEpoch to mday/yday/mon/year given the days in year, days in month, and week specific attributes of the calendar
// Further locale specific detail can be provided by the instance of a generic abstract calendar
};
}
// Malding about the ANSI c defintion of ::tm
// Note (1): We don't give a single solitary fuck about what ISO 8601 says nor the intentions of braindead boomers who thought there were 61 seconds to an hour (^2)...
// Sunday is not a weekday; it's apart of the week-END. No English speaker will disagree with this once we get past the obvious gaslighting attempts from NGOs and indoctrination institutions.
// In my estimation, it's every English speaker ever born after the Stuarts (17xxs+) versus a handful of CIA boys and the International Organization for Standardization.
// In my tradition of upholding da norf, we're sticking by the 19th century industrialized understanding of time.
// [tm_]wday is now the day offset since Monday, not days since last week.
// [tm_]mday is now the day offset since the beginning of the month, not the calendar number - that's to say we deviate from other impls by asserting these members are all offsets, not whatever some CIA fuckbuddies at ANSI said it is.
// (^2): there isn't such a concept in *CIVIL* time; leap seconds are only in the concept of "academic/astronomy circlejerk time" that no sane person, language runtime, or physical clock has ever cared about, nevermind implemented properly.
// they are wholly irrelevant to the conversion between calendar systems, and there isn't any legitimate use for polling wall-time with leap-second precision. unless you are looking for an API to build your GPS transponder or an NTP library, leap seconds aren't a factor in anything.
// this is a c++ library, not a live feed to the bullshit ad-hoc announcements of the international earth rotation and reference service.