4#include "Stroika/Foundation/StroikaPreComp.h"
14#include "Stroika/Foundation/Execution/Throw.h"
15#include "Stroika/Foundation/Linguistics/MessageUtilities.h"
22using namespace Stroika::Foundation::Memory;
23using namespace Stroika::Foundation::Time;
32Date::FormatException::FormatException ()
44 return DateTime::Now ().GetDate ();
52 wstring
wRep = rep.
As<wstring> ();
62optional<Date> Date::LocaleFreeParseQuietly_kMonthDayYearFormat_ (
const wstring& rep,
size_t* consumedCharsInStringUpTo)
68 DISABLE_COMPILER_MSC_WARNING_START (4996)
71 DISABLE_COMPILER_MSC_WARNING_END (4996)
74 Assert (
pos + 2 < rep.length ());
77 if ((1 <= m
and m <= 12)
and (1 <= d
and d <= 31)
and (year > 0)) {
80 return Date{
Year{year}, month{
static_cast<unsigned int> (m)}, day{
static_cast<unsigned int> (d)},
91optional<Date> Date::ParseQuietly_ (
const wstring& rep,
const time_get<wchar_t>& tmget,
const String& formatPattern,
size_t* consumedCharsInStringUpTo)
93 Require (
not rep.empty ());
101 ios::iostate
errState = ios::goodbit;
103 wistringstream
iss{rep};
115 return AsDate_ (
when);
122 case eCurrentLocale_WithZerosStripped: {
136 Assert (
tmp[*i] ==
'0');
138 if (*i + 1 <
tmp.length ()
and tmp[*i + 1].IsDigit ()) {
139 if (*i == 0
or not tmp[*i - 1].IsDigit ()) {
143 if (*i + 2 <
tmp.length ()) {
149 tmp =
tmp.substr (0, *i) +
tmp.substr (*i + 1);
171 return "{:04}-{:02}-{:02}"_f((
int)(this->GetYear ()), (
unsigned int)(this->GetMonth ()), (
unsigned int)(this->GetDayOfMonth ()));
187#if qCompilerAndStdLib_FormatRangeRestriction_Buggy
196Date Date::AsDate_ (const ::tm& when)
198 return Date{
Year{
when.tm_year + kTM_Year_RelativeToYear_},
212 return Add (chrono::round<days> (d));
220days Date::Since ()
const
225weekday Date::GetDayOfWeek ()
const
235 unsigned int y =
static_cast<unsigned int> (
static_cast<int> (GetYear ()));
236 auto R = [] (
unsigned int i,
unsigned int r) {
return i %
r; };
237 unsigned int weekdayOfJan1 =
R (1 + 5 *
R (y - 1, 4) + 4 *
R (y - 1, 100) + 6 *
R (y - 1, 400), 7);
240 unsigned int month0 =
static_cast<unsigned int> (GetMonth ()) -
static_cast<unsigned int> (January);
245 3, 2, 3, 2, 3, 3, 2, 3, 2, 3,
248 for (
unsigned int i = 0; i <
month0; ++i) {
251 if (
month0 > 1
and GetYear ().is_leap ()) {
275 unsigned int diff = r - l;
276 Assert (INT_MIN <= -INT_MAX);
277 if (diff >=
static_cast<unsigned int> (INT_MAX)) {
281 return -
static_cast<int> (diff);
285 unsigned int diff = l - r;
286 if (diff >=
static_cast<unsigned int> (INT_MAX)) {
290 return static_cast<int> (diff);
302int Time::YearDifference (
const Date& lhs,
const Date& rhs)
304 int diff =
static_cast<int> (lhs.GetYear ()) -
static_cast<int> (rhs.GetYear ());
305 if (lhs.GetMonth () < rhs.GetMonth () or (lhs.GetMonth () == rhs.GetMonth () and lhs.GetDayOfMonth () < rhs.GetDayOfMonth ())) {
311float Time::YearDifferenceF (
const Date& lhs,
const Date& rhs)
313 return DayDifference (lhs, rhs) / 365.25f;
321String Time::GetFormattedAge (
const optional<Date>& birthDate,
const optional<Date>& deathDate)
323 if (birthDate.has_value ()) {
324 int yearDiff = deathDate.has_value () ? YearDifference (*deathDate, *birthDate) : YearDifference (DateTime::GetToday (), *birthDate);
325 return Format (
"{}"_f, yearDiff);
337String Time::GetFormattedAgeWithUnit (
const optional<Date>& birthDate,
const optional<Date>& deathDate,
bool abbrevUnit)
339 if (birthDate.has_value ()) {
340 int yearDiff = deathDate.has_value () ? YearDifference (*deathDate, *birthDate) : YearDifference (DateTime::GetToday (), *birthDate);
341 if (yearDiff >= 0 and yearDiff < 2) {
342 float yearDiffF = deathDate.has_value () ? YearDifferenceF (*deathDate, *birthDate) : YearDifferenceF (DateTime::GetToday (), *birthDate);
343 int months = int (yearDiffF * 12.0f + 0.4999f);
344 String unitBase = abbrevUnit ?
"mo"_k :
"month"_k;
345 return Format (
"{} {}"_f, months, Linguistics::MessageUtilities::Manager::sThe.PluralizeNoun (unitBase, months));
348 String unitBase = abbrevUnit ?
"yr"_k :
"year"_k;
349 return Format (
"{} {}"_f, yearDiff, Linguistics::MessageUtilities::Manager::sThe.PluralizeNoun (unitBase, yearDiff));
#define WeakAssert(c)
A WeakAssert() is for things that aren't guaranteed to be true, but are overwhelmingly likely to be t...
#define AssertNotReached()
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
nonvirtual String Format(NonStandardPrintFormat pf=NonStandardPrintFormat::eDEFAULT) const
NonStandardPrintFormat
DisplayFormat is a representation which a date can be transformed in and out of.
nonvirtual days operator-(const Date &rhs) const
make_signed_t< JulianDayNumber > SignedJulianDayNumber
static constexpr string_view kISO8601Format
Y-M-D format - locale independent, and ISO-8601 date format standard.
static Date Now() noexcept
static days Since(Date dStart, Date dEnd)
static constexpr string_view kMonthDayYearFormat
classic (american) month-day-year format, but unlike D, this uses Y, so the 4-digit form of year
nonvirtual constexpr JulianDayNumber GetJulianRep() const
return the Julian Day Number (JDN) - corresponding to this date object (https://en....
static constexpr string_view kLocaleStandardFormat
nonvirtual Date Add(int d) const
Duration is a chrono::duration<double> (=.
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Simple wrapper on std::chrono::day, with some helpful validation properties (assures constructed 'ok'...
Simple wrapper on std::chrono::weekday, with some helpful validation properties (assures constructed ...
Simple wrapper on std::chrono::month, with some helpful validation properties (assures constructed 'o...
Simple wrapper on std::chrono::year, with some helpful validation properties (assures constructed 'ok...