@@ -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
183183scoped_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
621621static 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
625631static const int SecondsInMinute = 60 ;
626632static const int SecondsInHour = SecondsInMinute * 60 ;
@@ -639,26 +645,27 @@ static const int64_t SecondsFrom1900To2001 = INT64_C(3187296000);
639645
640646static const int64_t NtTo1900OffsetInterval = INT64_C(0x014F373BFDE04000 );
641647
642- static int count_leap_years ( const int 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
663670static 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
751761utility::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 ]; // Thu, 01 Jan 1970 00:00:00 GMT\0
782792 // 1970-01-01T00:00:00.1234567Z\0
@@ -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 )
0 commit comments