@@ -633,7 +633,8 @@ static void __parse_tzdata(tzdb& __db, __tz::__rules_storage_type& __rules, istr
633633}
634634
635635// This function parses the leap-seconds "binary file" compiled from the .list file
636- // by the zic compiler. That format is what's provided on some platforms like Darwin.
636+ // by the zic compiler. That format is widely available as it comes by default with
637+ // the IANA Time Zone Database.
637638//
638639// The format looks like:
639640//
@@ -642,8 +643,7 @@ static void __parse_tzdata(tzdb& __db, __tz::__rules_storage_type& __rules, istr
642643// Leap 1972 Dec 31 23:59:60 + S
643644// Leap 1973 Dec 31 23:59:60 + S
644645//
645- inline vector<leap_second> __parse_leap_seconds_binary (istream&& __input) {
646- vector<leap_second> __result;
646+ static void __parse_leap_seconds (vector<leap_second>& __leap_seconds, istream&& __input) {
647647 [&] {
648648 while (true ) {
649649 switch (__input.peek ()) {
@@ -699,86 +699,12 @@ inline vector<leap_second> __parse_leap_seconds_binary(istream&& __input) {
699699
700700 chrono::__skip_line (__input);
701701
702- __result .emplace_back (std::__private_constructor_tag{}, __timestamp, __value);
702+ __leap_seconds .emplace_back (std::__private_constructor_tag{}, __timestamp, __value);
703703 }
704704 }();
705705
706706 // Ensure the leap seconds are sorted properly.
707- ranges::sort (__result, {}, &leap_second::date);
708-
709- return __result;
710- }
711-
712- // This function parses leap-seconds.list file as can be found at
713- // https://hpiers.obspm.fr/iers/bul/bulc/ntp/leap-seconds.list
714- //
715- // The format looks like
716- //
717- // #NTP Time DTAI Day Month Year
718- // #
719- // 2272060800 10 # 1 Jan 1972
720- // 2287785600 11 # 1 Jul 1972
721- // 2303683200 12 # 1 Jan 1973
722- //
723- // Where the timestamps are expressed as a number of seconds since 1 January 1900, 00:00:00.
724- inline vector<leap_second> __parse_leap_seconds_list (istream&& __input) {
725- // The file stores dates since 1 January 1900, 00:00:00, we want
726- // seconds since 1 January 1970.
727- constexpr auto __offset = sys_days{1970y / January / 1 } - sys_days{1900y / January / 1 };
728-
729- struct __entry {
730- sys_seconds __timestamp;
731- seconds __value;
732- };
733- vector<__entry> __entries;
734- [&] {
735- while (true ) {
736- switch (__input.peek ()) {
737- case istream::traits_type::eof ():
738- return ;
739-
740- case ' ' :
741- case ' \t ' :
742- case ' \n ' :
743- __input.get ();
744- continue ;
745-
746- case ' #' :
747- chrono::__skip_line (__input);
748- continue ;
749- }
750-
751- sys_seconds __date = sys_seconds{seconds{chrono::__parse_integral (__input, false )}} - __offset;
752- chrono::__skip_mandatory_whitespace (__input);
753- seconds __value{chrono::__parse_integral (__input, false )};
754- chrono::__skip_line (__input);
755-
756- __entries.emplace_back (__date, __value);
757- }
758- }();
759- // The Standard requires the leap seconds to be sorted. The file
760- // leap-seconds.list usually provides them in sorted order, but that is not
761- // guaranteed so we ensure it here.
762- ranges::sort (__entries, {}, &__entry::__timestamp);
763-
764- // The database should contain the number of seconds inserted by a leap
765- // second (1 or -1). So the difference between the two elements is stored.
766- // std::ranges::views::adjacent has not been implemented yet.
767- vector<leap_second> __result;
768- (void )ranges::adjacent_find (__entries, [&](const __entry& __first, const __entry& __second) {
769- __result.emplace_back (std::__private_constructor_tag{}, __second.__timestamp , __second.__value - __first.__value );
770- return false ;
771- });
772- return __result;
773- }
774-
775- // Parse leap seconds from the appropriate location based on the platform.
776- static void __parse_leap_seconds (vector<leap_second>& __leap_seconds, filesystem::path const & __tzdb_directory) {
777- #if defined(__APPLE__)
778- __leap_seconds.append_range (chrono::__parse_leap_seconds_binary (ifstream{__tzdb_directory / " leapseconds" }));
779- #else
780- __leap_seconds.append_range (chrono::__parse_leap_seconds_list (ifstream{__tzdb_directory / " leap-seconds.list" }));
781- #endif
707+ ranges::sort (__leap_seconds, {}, &leap_second::date);
782708}
783709
784710void __init_tzdb (tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
@@ -790,7 +716,7 @@ void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
790716 ranges::sort (__tzdb.zones );
791717 ranges::sort (__tzdb.links );
792718 ranges::sort (__rules, {}, [](const auto & p) { return p.first ; });
793- chrono::__parse_leap_seconds (__tzdb.leap_seconds , __root);
719+ chrono::__parse_leap_seconds (__tzdb.leap_seconds , ifstream{ __root / " leapseconds " } );
794720}
795721
796722#ifdef _WIN32
0 commit comments