|
34 | 34 | #include <chrono> |
35 | 35 | #include <expected> |
36 | 36 | #include <map> |
37 | | -#include <numeric> |
38 | 37 | #include <ranges> |
39 | 38 |
|
40 | 39 | #include "include/tzdb/time_zone_private.h" |
@@ -904,152 +903,6 @@ time_zone::__get_info(sys_seconds __time) const { |
904 | 903 | std::__throw_runtime_error("tzdb: corrupt db"); |
905 | 904 | } |
906 | 905 |
|
907 | | -// Is the "__local_time" present in "__first" and "__second". If so the |
908 | | -// local_info has an ambiguous result. |
909 | | -[[nodiscard]] static bool |
910 | | -__is_ambiguous(local_seconds __local_time, const sys_info& __first, const sys_info& __second) { |
911 | | - std::chrono::local_seconds __end_first{__first.end.time_since_epoch() + __first.offset}; |
912 | | - std::chrono::local_seconds __begin_second{__second.begin.time_since_epoch() + __second.offset}; |
913 | | - |
914 | | - return __local_time < __end_first && __local_time >= __begin_second; |
915 | | -} |
916 | | - |
917 | | -// Determines the result of the "__local_time". This expects the object |
918 | | -// "__first" to be earlier in time than "__second". |
919 | | -[[nodiscard]] static local_info |
920 | | -__get_info(local_seconds __local_time, const sys_info& __first, const sys_info& __second) { |
921 | | - std::chrono::local_seconds __end_first{__first.end.time_since_epoch() + __first.offset}; |
922 | | - std::chrono::local_seconds __begin_second{__second.begin.time_since_epoch() + __second.offset}; |
923 | | - |
924 | | - if (__local_time < __end_first) { |
925 | | - if (__local_time >= __begin_second) |
926 | | - // |--------| |
927 | | - // |------| |
928 | | - // ^ |
929 | | - return {local_info::ambiguous, __first, __second}; |
930 | | - |
931 | | - // |--------| |
932 | | - // |------| |
933 | | - // ^ |
934 | | - return {local_info::unique, __first, sys_info{}}; |
935 | | - } |
936 | | - |
937 | | - if (__local_time < __begin_second) |
938 | | - // |--------| |
939 | | - // |------| |
940 | | - // ^ |
941 | | - return {local_info::nonexistent, __first, __second}; |
942 | | - |
943 | | - // |--------| |
944 | | - // |------| |
945 | | - // ^ |
946 | | - return {local_info::unique, __second, sys_info{}}; |
947 | | -} |
948 | | - |
949 | | -[[nodiscard]] _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI local_info |
950 | | -time_zone::__get_info(local_seconds __local_time) const { |
951 | | - seconds __local_seconds = __local_time.time_since_epoch(); |
952 | | - |
953 | | - /* An example of a typical year with a DST switch displayed in local time. |
954 | | - * |
955 | | - * At the first of April the time goes forward one hour. This means the |
956 | | - * time marked with ~~ is not a valid local time. This is represented by the |
957 | | - * nonexistent value in local_info.result. |
958 | | - * |
959 | | - * At the first of November the time goes backward one hour. This means the |
960 | | - * time marked with ^^ happens twice. This is represented by the ambiguous |
961 | | - * value in local_info.result. |
962 | | - * |
963 | | - * 2020.11.01 2021.04.01 2021.11.01 |
964 | | - * offset +05 offset +05 offset +05 |
965 | | - * save 0s save 1h save 0s |
966 | | - * |------------//----------| |
967 | | - * |---------//--------------| |
968 | | - * |------------- |
969 | | - * ~~ ^^ |
970 | | - * |
971 | | - * These shifts can happen due to changes in the current time zone for a |
972 | | - * location. For example, Indian/Kerguelen switched only once. In 1950 from an |
973 | | - * offset of 0 hours to an offset of +05 hours. |
974 | | - * |
975 | | - * During all these shifts the UTC time will not have gaps. |
976 | | - */ |
977 | | - |
978 | | - // The code needs to determine the system time for the local time. There is no |
979 | | - // information available. Assume the offset between system time and local time |
980 | | - // is 0s. This gives an initial estimate. |
981 | | - sys_seconds __guess{__local_seconds}; |
982 | | - sys_info __info = __get_info(__guess); |
983 | | - |
984 | | - // At this point the offset can be used to determine an estimate for the local |
985 | | - // time. Before doing that, determine the offset and validate whether the |
986 | | - // local time is the range [chrono::local_seconds::min(), |
987 | | - // chrono::local_seconds::max()). |
988 | | - if (__local_seconds < 0s && __info.offset > 0s) |
989 | | - if (__local_seconds - chrono::local_seconds::min().time_since_epoch() < __info.offset) |
990 | | - return {-1, __info, {}}; |
991 | | - |
992 | | - if (__local_seconds > 0s && __info.offset < 0s) |
993 | | - if (chrono::local_seconds::max().time_since_epoch() - __local_seconds < -__info.offset) |
994 | | - return {-2, __info, {}}; |
995 | | - |
996 | | - // Based on the information found in the sys_info, the local time can be |
997 | | - // converted to a system time. This resulting time can be in the following |
998 | | - // locations of the sys_info: |
999 | | - // |
1000 | | - // |---------//--------------| |
1001 | | - // 1 2.1 2.2 2.3 3 |
1002 | | - // |
1003 | | - // 1. The estimate is before the returned sys_info object. |
1004 | | - // The result is either non-existent or unique in the previous sys_info. |
1005 | | - // 2. The estimate is in the sys_info object |
1006 | | - // - If the sys_info begin is not sys_seconds::min(), then it might be at |
1007 | | - // 2.1 and could be ambiguous with the previous or unique. |
1008 | | - // - If sys_info end is not sys_seconds::max(), then it might be at 2.3 |
1009 | | - // and could be ambiguous with the next or unique. |
1010 | | - // - Else it is at 2.2 and always unique. This case happens when a |
1011 | | - // time zone has no transitions. For example, UTC or GMT+1. |
1012 | | - // 3. The estimate is after the returned sys_info object. |
1013 | | - // The result is either non-existent or unique in the next sys_info. |
1014 | | - // |
1015 | | - // There is no specification where the "middle" starts. Similar issues can |
1016 | | - // happen when sys_info objects are "short", then "unique in the next" could |
1017 | | - // become "ambiguous in the next and the one following". Theoretically there |
1018 | | - // is the option of the following time-line |
1019 | | - // |
1020 | | - // |------------| |
1021 | | - // |----| |
1022 | | - // |-----------------| |
1023 | | - // |
1024 | | - // However the local_info object only has 2 sys_info objects, so this option |
1025 | | - // is not tested. |
1026 | | - |
1027 | | - sys_seconds __sys_time{__local_seconds - __info.offset}; |
1028 | | - if (__sys_time < __info.begin) |
1029 | | - // Case 1 before __info |
1030 | | - return chrono::__get_info(__local_time, __get_info(__info.begin - 1s), __info); |
1031 | | - |
1032 | | - if (__sys_time >= __info.end) |
1033 | | - // Case 3 after __info |
1034 | | - return chrono::__get_info(__local_time, __info, __get_info(__info.end)); |
1035 | | - |
1036 | | - // Case 2 in __info |
1037 | | - if (__info.begin != sys_seconds::min()) { |
1038 | | - // Case 2.1 Not at the beginning, when not ambiguous the result should test |
1039 | | - // case 2.3. |
1040 | | - sys_info __prev = __get_info(__info.begin - 1s); |
1041 | | - if (__is_ambiguous(__local_time, __prev, __info)) |
1042 | | - return {local_info::ambiguous, __prev, __info}; |
1043 | | - } |
1044 | | - |
1045 | | - if (__info.end == sys_seconds::max()) |
1046 | | - // At the end so it's case 2.2 |
1047 | | - return {local_info::unique, __info, sys_info{}}; |
1048 | | - |
1049 | | - // This tests case 2.2 or case 2.3. |
1050 | | - return chrono::__get_info(__local_time, __info, __get_info(__info.end)); |
1051 | | -} |
1052 | | - |
1053 | 906 | } // namespace chrono |
1054 | 907 |
|
1055 | 908 | _LIBCPP_END_NAMESPACE_STD |
0 commit comments