Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7046d3a

Browse files
Add ability to emit the NT epoch.
1 parent 880e535 commit 7046d3a

File tree

2 files changed

+61
-37
lines changed

2 files changed

+61
-37
lines changed

‎Release/src/utilities/asyncrt_utils.cpp

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ scoped_c_thread_locale::~scoped_c_thread_locale()
177177
}
178178
}
179179
#elif (defined(ANDROID) || defined(__ANDROID__))
180-
scoped_c_thread_locale::scoped_c_thread_locale() {}
181-
scoped_c_thread_locale::~scoped_c_thread_locale() {}
180+
scoped_c_thread_locale::scoped_c_thread_locale() {}
181+
scoped_c_thread_locale::~scoped_c_thread_locale() {}
182182
#else
183183
scoped_c_thread_locale::scoped_c_thread_locale() : m_prevLocale(nullptr)
184184
{
@@ -620,7 +620,13 @@ utf16string __cdecl conversions::to_utf16string(const std::string& value) { retu
620620

621621
static const int64_t NtToUnixOffsetSeconds = 11644473600; // diff between windows and unix epochs (seconds)
622622

623-
static bool year_is_leap_year(int year) { return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); }
623+
static bool year_is_leap_year_1601(int year)
624+
{
625+
int decimal_year = year + 1601;
626+
return (decimal_year % 4 == 0 && (decimal_year % 100 != 0 || decimal_year % 400 == 0));
627+
}
628+
629+
static bool year_is_leap_year(int year) { return year_is_leap_year_1601(year + 299); }
624630

625631
static const int SecondsInMinute = 60;
626632
static const int SecondsInHour = SecondsInMinute * 60;
@@ -639,26 +645,27 @@ static const int64_t SecondsFrom1900To2001 = INT64_C(3187296000);
639645

640646
static const int64_t NtTo1900OffsetInterval = INT64_C(0x014F373BFDE04000);
641647

642-
static int count_leap_years(constint yearsSince1900)
648+
static int count_leap_years_1601(int yearsSince1601)
643649
{
644-
int tmpYears = yearsSince1900 + 299; // shift into 1601, the first 400 year cycle including 1900
645-
646-
int year400 = tmpYears / 400;
647-
tmpYears -= year400 * 400;
650+
int year400 = yearsSince1601 / 400;
651+
yearsSince1601 -= year400 * 400;
648652
int result = year400 * 97;
649653

650-
int year100 = tmpYears / 100;
651-
tmpYears -= year100 * 100;
654+
int year100 = yearsSince1601 / 100;
655+
yearsSince1601 -= year100 * 100;
652656
result += year100 * 24;
653657

654-
result += tmpYears / 4;
655-
656-
// subtract off leap years from 1601
657-
result -= 72;
658+
result += yearsSince1601 / 4;
658659

659660
return result;
660661
}
661662

663+
static int count_leap_years(const int yearsSince1900)
664+
{
665+
// shift into 1601, the first 400 year cycle including 1900, then subtract leap years from 1601->1900
666+
return count_leap_years_1601(yearsSince1900 + 299) - 72;
667+
}
668+
662669
// The following table assumes no leap year; leap year is added separately
663670
static const unsigned short cumulative_days_to_month[12] = {
664671
0, // Jan
@@ -720,20 +727,16 @@ struct compute_year_result
720727
int secondsLeftThisYear;
721728
};
722729

723-
static const int64_t secondsFrom1601To1900 = INT64_C(9435484800);
724-
725-
static compute_year_result compute_year(int64_t secondsSince1900)
730+
static compute_year_result compute_year_1601(int64_t secondsSince1601)
726731
{
727-
int64_t secondsLeft = secondsSince1900 + secondsFrom1601To1900; // shift to start of this 400 year cycle
728-
729-
int year400 = static_cast<int>(secondsLeft / SecondsIn400Years);
730-
secondsLeft -= year400 * SecondsIn400Years;
732+
int year400 = static_cast<int>(secondsSince1601 / SecondsIn400Years);
733+
secondsSince1601 -= year400 * SecondsIn400Years;
731734

732-
int year100 = static_cast<int>(secondsLeft / SecondsIn100Years);
733-
secondsLeft -= year100 * SecondsIn100Years;
735+
int year100 = static_cast<int>(secondsSince1601 / SecondsIn100Years);
736+
secondsSince1601 -= year100 * SecondsIn100Years;
734737

735-
int year4 = static_cast<int>(secondsLeft / SecondsIn4Years);
736-
int secondsInt = static_cast<int>(secondsLeft - year4 * SecondsIn4Years);
738+
int year4 = static_cast<int>(secondsSince1601 / SecondsIn4Years);
739+
int secondsInt = static_cast<int>(secondsSince1601 - year4 * SecondsIn4Years);
737740

738741
int year1 = secondsInt / SecondsInYear;
739742
if (year1 == 4)
@@ -743,9 +746,16 @@ static compute_year_result compute_year(int64_t secondsSince1900)
743746
}
744747

745748
secondsInt -= year1 * SecondsInYear;
749+
return {year400 * 400 + year100 * 100 + year4 * 4 + year1, secondsInt};
750+
}
746751

747-
// shift back to 1900 base from 1601:
748-
return {year400 * 400 + year100 * 100 + year4 * 4 + year1 - 299, secondsInt};
752+
static const int64_t secondsFrom1601To1900 = INT64_C(9435484800);
753+
static compute_year_result compute_year(int64_t secondsSince1900)
754+
{
755+
// shift to start of this 400 year cycle
756+
auto partialResult = compute_year_1601(secondsSince1900 + secondsFrom1601To1900);
757+
// shift back to 1900
758+
return {partialResult.year - 299, partialResult.secondsLeftThisYear};
749759
}
750760

751761
utility::string_t datetime::to_string(date_format format) const
@@ -755,11 +765,11 @@ utility::string_t datetime::to_string(date_format format) const
755765
throw std::out_of_range("The requested year exceeds the year 9999.");
756766
}
757767

758-
const int64_t epochAdjusted = static_cast<int64_t>(m_interval) - NtTo1900OffsetInterval;
759-
const int64_t secondsSince1900 = epochAdjusted / _secondTicks; // convert to seconds
760-
const int fracSec = static_cast<int>(epochAdjusted % _secondTicks);
768+
const int64_t interval = static_cast<int64_t>(m_interval);
769+
const int64_t secondsSince1601 = interval / _secondTicks; // convert to seconds
770+
const int fracSec = static_cast<int>(interval % _secondTicks);
761771

762-
const auto yearData = compute_year(secondsSince1900);
772+
const auto yearData = compute_year_1601(secondsSince1601);
763773
const int year = yearData.year;
764774
const int yearDay = yearData.secondsLeftThisYear / SecondsInDay;
765775
int leftover = yearData.secondsLeftThisYear % SecondsInDay;
@@ -768,15 +778,15 @@ utility::string_t datetime::to_string(date_format format) const
768778
const int minute = leftover / SecondsInMinute;
769779
leftover = leftover % SecondsInMinute;
770780

771-
const auto& monthTable = year_is_leap_year(year) ? cumulative_days_to_month_leap : cumulative_days_to_month;
781+
const auto& monthTable = year_is_leap_year_1601(year) ? cumulative_days_to_month_leap : cumulative_days_to_month;
772782
int month = 0;
773783
while (month < 11 && monthTable[month + 1] <= yearDay)
774784
{
775785
++month;
776786
}
777787

778788
const auto monthDay = yearDay - monthTable[month] + 1;
779-
const auto weekday = static_cast<int>((secondsSince1900 / SecondsInDay + 1) % 7);
789+
const auto weekday = static_cast<int>((secondsSince1601 / SecondsInDay + 1) % 7);
780790

781791
char outBuffer[38]; // 1970年1月01日 00:00:00 GMT0円
782792
// 1970年01月01日T00:00:00.1234567Z0円
@@ -791,7 +801,7 @@ utility::string_t datetime::to_string(date_format format) const
791801
dayNames + 4 * weekday,
792802
monthDay,
793803
monthNames + 4 * month,
794-
year + 1900,
804+
year + 1601,
795805
hour,
796806
minute,
797807
leftover);
@@ -801,7 +811,7 @@ utility::string_t datetime::to_string(date_format format) const
801811
dayNames + 4 * weekday,
802812
monthDay,
803813
monthNames + 4 * month,
804-
year + 1900,
814+
year + 1601,
805815
hour,
806816
minute,
807817
leftover);
@@ -815,15 +825,15 @@ utility::string_t datetime::to_string(date_format format) const
815825
sprintf_s(outCursor,
816826
20,
817827
"%04d-%02d-%02dT%02d:%02d:%02d",
818-
year + 1900,
828+
year + 1601,
819829
month + 1,
820830
monthDay,
821831
hour,
822832
minute,
823833
leftover);
824834
#else // ^^^ _MSC_VER // !_MSC_VER vvv
825835
sprintf(
826-
outCursor, "%04d-%02d-%02dT%02d:%02d:%02d", year + 1900, month + 1, monthDay, hour, minute, leftover);
836+
outCursor, "%04d-%02d-%02dT%02d:%02d:%02d", year + 1601, month + 1, monthDay, hour, minute, leftover);
827837
#endif // _MSC_VER
828838
outCursor += 19;
829839
if (fracSec != 0)

‎Release/tests/functional/utils/datetime.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,20 @@ SUITE(datetime)
502502
}
503503
}
504504

505+
TEST(can_emit_nt_epoch_zero)
506+
{
507+
// ISO 8601
508+
{
509+
auto result = utility::datetime{}.to_string(utility::datetime::RFC_1123);
510+
VERIFY_ARE_EQUAL(_XPLATSTR("1601年1月01日 00:00:00 GMT"), result);
511+
}
512+
// ISO 8601
513+
{
514+
auto result = utility::datetime{}.to_string(utility::datetime::ISO_8601);
515+
VERIFY_ARE_EQUAL(_XPLATSTR("1601年01月01日T00:00:00Z"), result);
516+
}
517+
}
518+
505519
} // SUITE(datetime)
506520

507521
} // namespace utils_tests

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /