diff options
author | anastasy888 <anastasy888@yandex-team.ru> | 2022-02-10 16:45:55 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:55 +0300 |
commit | 3a7a498715ef1b66f5054455421b845e45e3a653 (patch) | |
tree | 1a2c5ffcf89eb53ecd79dbc9bc0a195c27404d0c /contrib/restricted/abseil-cpp-tstring/y_absl/time | |
parent | 49f765d71da452ea93138a25559dfa68dd76c7f3 (diff) | |
download | ydb-3a7a498715ef1b66f5054455421b845e45e3a653.tar.gz |
Restoring authorship annotation for <anastasy888@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/restricted/abseil-cpp-tstring/y_absl/time')
36 files changed, 9050 insertions, 9050 deletions
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time.cc index c26166935d..f24bac91e8 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time.cc @@ -1,173 +1,173 @@ -// Copyright 2018 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "y_absl/time/civil_time.h" - -#include <cstdlib> + +#include <cstdlib> #include <util/generic/string.h> - + #include "y_absl/strings/str_cat.h" #include "y_absl/time/time.h" - + namespace y_absl { ABSL_NAMESPACE_BEGIN - -namespace { - + +namespace { + // Since a civil time has a larger year range than y_absl::Time (64-bit years vs -// 64-bit seconds, respectively) we normalize years to roughly +/- 400 years -// around the year 2400, which will produce an equivalent year in a range that +// 64-bit seconds, respectively) we normalize years to roughly +/- 400 years +// around the year 2400, which will produce an equivalent year in a range that // y_absl::Time can handle. -inline civil_year_t NormalizeYear(civil_year_t year) { - return 2400 + year % 400; -} - -// Formats the given CivilSecond according to the given format. +inline civil_year_t NormalizeYear(civil_year_t year) { + return 2400 + year % 400; +} + +// Formats the given CivilSecond according to the given format. TString FormatYearAnd(string_view fmt, CivilSecond cs) { - const CivilSecond ncs(NormalizeYear(cs.year()), cs.month(), cs.day(), - cs.hour(), cs.minute(), cs.second()); - const TimeZone utc = UTCTimeZone(); + const CivilSecond ncs(NormalizeYear(cs.year()), cs.month(), cs.day(), + cs.hour(), cs.minute(), cs.second()); + const TimeZone utc = UTCTimeZone(); return StrCat(cs.year(), FormatTime(fmt, FromCivil(ncs, utc), utc)); -} - -template <typename CivilT> -bool ParseYearAnd(string_view fmt, string_view s, CivilT* c) { +} + +template <typename CivilT> +bool ParseYearAnd(string_view fmt, string_view s, CivilT* c) { // Civil times support a larger year range than y_absl::Time, so we need to // parse the year separately, normalize it, then use y_absl::ParseTime on the // normalized string. const TString ss = TString(s); // TODO(y_absl-team): Avoid conversion. - const char* const np = ss.c_str(); - char* endp; - errno = 0; - const civil_year_t y = - std::strtoll(np, &endp, 10); // NOLINT(runtime/deprecated_fn) - if (endp == np || errno == ERANGE) return false; + const char* const np = ss.c_str(); + char* endp; + errno = 0; + const civil_year_t y = + std::strtoll(np, &endp, 10); // NOLINT(runtime/deprecated_fn) + if (endp == np || errno == ERANGE) return false; const TString norm = StrCat(NormalizeYear(y), endp); - - const TimeZone utc = UTCTimeZone(); - Time t; - if (ParseTime(StrCat("%Y", fmt), norm, utc, &t, nullptr)) { - const auto cs = ToCivilSecond(t, utc); - *c = CivilT(y, cs.month(), cs.day(), cs.hour(), cs.minute(), cs.second()); - return true; - } - - return false; -} - -// Tries to parse the type as a CivilT1, but then assigns the result to the -// argument of type CivilT2. -template <typename CivilT1, typename CivilT2> -bool ParseAs(string_view s, CivilT2* c) { - CivilT1 t1; - if (ParseCivilTime(s, &t1)) { - *c = CivilT2(t1); - return true; - } - return false; -} - -template <typename CivilT> -bool ParseLenient(string_view s, CivilT* c) { + + const TimeZone utc = UTCTimeZone(); + Time t; + if (ParseTime(StrCat("%Y", fmt), norm, utc, &t, nullptr)) { + const auto cs = ToCivilSecond(t, utc); + *c = CivilT(y, cs.month(), cs.day(), cs.hour(), cs.minute(), cs.second()); + return true; + } + + return false; +} + +// Tries to parse the type as a CivilT1, but then assigns the result to the +// argument of type CivilT2. +template <typename CivilT1, typename CivilT2> +bool ParseAs(string_view s, CivilT2* c) { + CivilT1 t1; + if (ParseCivilTime(s, &t1)) { + *c = CivilT2(t1); + return true; + } + return false; +} + +template <typename CivilT> +bool ParseLenient(string_view s, CivilT* c) { // A fastpath for when the given string data parses exactly into the given - // type T (e.g., s="YYYY-MM-DD" and CivilT=CivilDay). - if (ParseCivilTime(s, c)) return true; - // Try parsing as each of the 6 types, trying the most common types first - // (based on csearch results). - if (ParseAs<CivilDay>(s, c)) return true; - if (ParseAs<CivilSecond>(s, c)) return true; - if (ParseAs<CivilHour>(s, c)) return true; - if (ParseAs<CivilMonth>(s, c)) return true; - if (ParseAs<CivilMinute>(s, c)) return true; - if (ParseAs<CivilYear>(s, c)) return true; - return false; -} -} // namespace - + // type T (e.g., s="YYYY-MM-DD" and CivilT=CivilDay). + if (ParseCivilTime(s, c)) return true; + // Try parsing as each of the 6 types, trying the most common types first + // (based on csearch results). + if (ParseAs<CivilDay>(s, c)) return true; + if (ParseAs<CivilSecond>(s, c)) return true; + if (ParseAs<CivilHour>(s, c)) return true; + if (ParseAs<CivilMonth>(s, c)) return true; + if (ParseAs<CivilMinute>(s, c)) return true; + if (ParseAs<CivilYear>(s, c)) return true; + return false; +} +} // namespace + TString FormatCivilTime(CivilSecond c) { return FormatYearAnd("-%m-%d%ET%H:%M:%S", c); -} +} TString FormatCivilTime(CivilMinute c) { return FormatYearAnd("-%m-%d%ET%H:%M", c); -} +} TString FormatCivilTime(CivilHour c) { return FormatYearAnd("-%m-%d%ET%H", c); -} +} TString FormatCivilTime(CivilDay c) { return FormatYearAnd("-%m-%d", c); } TString FormatCivilTime(CivilMonth c) { return FormatYearAnd("-%m", c); } TString FormatCivilTime(CivilYear c) { return FormatYearAnd("", c); } - -bool ParseCivilTime(string_view s, CivilSecond* c) { + +bool ParseCivilTime(string_view s, CivilSecond* c) { return ParseYearAnd("-%m-%d%ET%H:%M:%S", s, c); -} -bool ParseCivilTime(string_view s, CivilMinute* c) { +} +bool ParseCivilTime(string_view s, CivilMinute* c) { return ParseYearAnd("-%m-%d%ET%H:%M", s, c); -} -bool ParseCivilTime(string_view s, CivilHour* c) { +} +bool ParseCivilTime(string_view s, CivilHour* c) { return ParseYearAnd("-%m-%d%ET%H", s, c); -} -bool ParseCivilTime(string_view s, CivilDay* c) { - return ParseYearAnd("-%m-%d", s, c); -} -bool ParseCivilTime(string_view s, CivilMonth* c) { - return ParseYearAnd("-%m", s, c); -} -bool ParseCivilTime(string_view s, CivilYear* c) { - return ParseYearAnd("", s, c); -} - -bool ParseLenientCivilTime(string_view s, CivilSecond* c) { - return ParseLenient(s, c); -} -bool ParseLenientCivilTime(string_view s, CivilMinute* c) { - return ParseLenient(s, c); -} -bool ParseLenientCivilTime(string_view s, CivilHour* c) { - return ParseLenient(s, c); -} -bool ParseLenientCivilTime(string_view s, CivilDay* c) { - return ParseLenient(s, c); -} -bool ParseLenientCivilTime(string_view s, CivilMonth* c) { - return ParseLenient(s, c); -} -bool ParseLenientCivilTime(string_view s, CivilYear* c) { - return ParseLenient(s, c); -} - -namespace time_internal { - -std::ostream& operator<<(std::ostream& os, CivilYear y) { - return os << FormatCivilTime(y); -} -std::ostream& operator<<(std::ostream& os, CivilMonth m) { - return os << FormatCivilTime(m); -} -std::ostream& operator<<(std::ostream& os, CivilDay d) { - return os << FormatCivilTime(d); -} -std::ostream& operator<<(std::ostream& os, CivilHour h) { - return os << FormatCivilTime(h); -} -std::ostream& operator<<(std::ostream& os, CivilMinute m) { - return os << FormatCivilTime(m); -} -std::ostream& operator<<(std::ostream& os, CivilSecond s) { - return os << FormatCivilTime(s); -} - -} // namespace time_internal - +} +bool ParseCivilTime(string_view s, CivilDay* c) { + return ParseYearAnd("-%m-%d", s, c); +} +bool ParseCivilTime(string_view s, CivilMonth* c) { + return ParseYearAnd("-%m", s, c); +} +bool ParseCivilTime(string_view s, CivilYear* c) { + return ParseYearAnd("", s, c); +} + +bool ParseLenientCivilTime(string_view s, CivilSecond* c) { + return ParseLenient(s, c); +} +bool ParseLenientCivilTime(string_view s, CivilMinute* c) { + return ParseLenient(s, c); +} +bool ParseLenientCivilTime(string_view s, CivilHour* c) { + return ParseLenient(s, c); +} +bool ParseLenientCivilTime(string_view s, CivilDay* c) { + return ParseLenient(s, c); +} +bool ParseLenientCivilTime(string_view s, CivilMonth* c) { + return ParseLenient(s, c); +} +bool ParseLenientCivilTime(string_view s, CivilYear* c) { + return ParseLenient(s, c); +} + +namespace time_internal { + +std::ostream& operator<<(std::ostream& os, CivilYear y) { + return os << FormatCivilTime(y); +} +std::ostream& operator<<(std::ostream& os, CivilMonth m) { + return os << FormatCivilTime(m); +} +std::ostream& operator<<(std::ostream& os, CivilDay d) { + return os << FormatCivilTime(d); +} +std::ostream& operator<<(std::ostream& os, CivilHour h) { + return os << FormatCivilTime(h); +} +std::ostream& operator<<(std::ostream& os, CivilMinute m) { + return os << FormatCivilTime(m); +} +std::ostream& operator<<(std::ostream& os, CivilSecond s) { + return os << FormatCivilTime(s); +} + +} // namespace time_internal + ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time.h index 8c38deaefb..64fb6da494 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time.h @@ -1,538 +1,538 @@ -// Copyright 2018 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// File: civil_time.h -// ----------------------------------------------------------------------------- -// -// This header file defines abstractions for computing with "civil time". -// The term "civil time" refers to the legally recognized human-scale time -// that is represented by the six fields `YYYY-MM-DD hh:mm:ss`. A "date" -// is perhaps the most common example of a civil time (represented here as +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: civil_time.h +// ----------------------------------------------------------------------------- +// +// This header file defines abstractions for computing with "civil time". +// The term "civil time" refers to the legally recognized human-scale time +// that is represented by the six fields `YYYY-MM-DD hh:mm:ss`. A "date" +// is perhaps the most common example of a civil time (represented here as // an `y_absl::CivilDay`). -// -// Modern-day civil time follows the Gregorian Calendar and is a -// time-zone-independent concept: a civil time of "2015-06-01 12:00:00", for -// example, is not tied to a time zone. Put another way, a civil time does not -// map to a unique point in time; a civil time must be mapped to an absolute -// time *through* a time zone. -// -// Because a civil time is what most people think of as "time," it is common to -// map absolute times to civil times to present to users. -// -// Time zones define the relationship between absolute and civil times. Given an -// absolute or civil time and a time zone, you can compute the other time: -// -// Civil Time = F(Absolute Time, Time Zone) -// Absolute Time = G(Civil Time, Time Zone) -// -// The Abseil time library allows you to construct such civil times from -// absolute times; consult time.h for such functionality. -// -// This library provides six classes for constructing civil-time objects, and -// provides several helper functions for rounding, iterating, and performing -// arithmetic on civil-time objects, while avoiding complications like -// daylight-saving time (DST): -// +// +// Modern-day civil time follows the Gregorian Calendar and is a +// time-zone-independent concept: a civil time of "2015-06-01 12:00:00", for +// example, is not tied to a time zone. Put another way, a civil time does not +// map to a unique point in time; a civil time must be mapped to an absolute +// time *through* a time zone. +// +// Because a civil time is what most people think of as "time," it is common to +// map absolute times to civil times to present to users. +// +// Time zones define the relationship between absolute and civil times. Given an +// absolute or civil time and a time zone, you can compute the other time: +// +// Civil Time = F(Absolute Time, Time Zone) +// Absolute Time = G(Civil Time, Time Zone) +// +// The Abseil time library allows you to construct such civil times from +// absolute times; consult time.h for such functionality. +// +// This library provides six classes for constructing civil-time objects, and +// provides several helper functions for rounding, iterating, and performing +// arithmetic on civil-time objects, while avoiding complications like +// daylight-saving time (DST): +// // * `y_absl::CivilSecond` // * `y_absl::CivilMinute` // * `y_absl::CivilHour` // * `y_absl::CivilDay` // * `y_absl::CivilMonth` // * `y_absl::CivilYear` -// -// Example: -// -// // Construct a civil-time object for a specific day +// +// Example: +// +// // Construct a civil-time object for a specific day // const y_absl::CivilDay cd(1969, 07, 20); -// -// // Construct a civil-time object for a specific second +// +// // Construct a civil-time object for a specific second // const y_absl::CivilSecond cd(2018, 8, 1, 12, 0, 1); -// -// Note: In C++14 and later, this library is usable in a constexpr context. -// -// Example: -// -// // Valid in C++14 +// +// Note: In C++14 and later, this library is usable in a constexpr context. +// +// Example: +// +// // Valid in C++14 // constexpr y_absl::CivilDay cd(1969, 07, 20); - -#ifndef ABSL_TIME_CIVIL_TIME_H_ -#define ABSL_TIME_CIVIL_TIME_H_ - + +#ifndef ABSL_TIME_CIVIL_TIME_H_ +#define ABSL_TIME_CIVIL_TIME_H_ + #include <util/generic/string.h> - + #include "y_absl/strings/string_view.h" #include "y_absl/time/internal/cctz/include/cctz/civil_time.h" - + namespace y_absl { ABSL_NAMESPACE_BEGIN - -namespace time_internal { -struct second_tag : cctz::detail::second_tag {}; -struct minute_tag : second_tag, cctz::detail::minute_tag {}; -struct hour_tag : minute_tag, cctz::detail::hour_tag {}; -struct day_tag : hour_tag, cctz::detail::day_tag {}; -struct month_tag : day_tag, cctz::detail::month_tag {}; -struct year_tag : month_tag, cctz::detail::year_tag {}; -} // namespace time_internal - -// ----------------------------------------------------------------------------- -// CivilSecond, CivilMinute, CivilHour, CivilDay, CivilMonth, CivilYear -// ----------------------------------------------------------------------------- -// -// Each of these civil-time types is a simple value type with the same -// interface for construction and the same six accessors for each of the civil -// time fields (year, month, day, hour, minute, and second, aka YMDHMS). These -// classes differ only in their alignment, which is indicated by the type name -// and specifies the field on which arithmetic operates. -// -// CONSTRUCTION -// -// Each of the civil-time types can be constructed in two ways: by directly -// passing to the constructor up to six integers representing the YMDHMS fields, -// or by copying the YMDHMS fields from a differently aligned civil-time type. -// Omitted fields are assigned their minimum valid value. Hours, minutes, and -// seconds will be set to 0, month and day will be set to 1. Since there is no -// minimum year, the default is 1970. -// -// Examples: -// + +namespace time_internal { +struct second_tag : cctz::detail::second_tag {}; +struct minute_tag : second_tag, cctz::detail::minute_tag {}; +struct hour_tag : minute_tag, cctz::detail::hour_tag {}; +struct day_tag : hour_tag, cctz::detail::day_tag {}; +struct month_tag : day_tag, cctz::detail::month_tag {}; +struct year_tag : month_tag, cctz::detail::year_tag {}; +} // namespace time_internal + +// ----------------------------------------------------------------------------- +// CivilSecond, CivilMinute, CivilHour, CivilDay, CivilMonth, CivilYear +// ----------------------------------------------------------------------------- +// +// Each of these civil-time types is a simple value type with the same +// interface for construction and the same six accessors for each of the civil +// time fields (year, month, day, hour, minute, and second, aka YMDHMS). These +// classes differ only in their alignment, which is indicated by the type name +// and specifies the field on which arithmetic operates. +// +// CONSTRUCTION +// +// Each of the civil-time types can be constructed in two ways: by directly +// passing to the constructor up to six integers representing the YMDHMS fields, +// or by copying the YMDHMS fields from a differently aligned civil-time type. +// Omitted fields are assigned their minimum valid value. Hours, minutes, and +// seconds will be set to 0, month and day will be set to 1. Since there is no +// minimum year, the default is 1970. +// +// Examples: +// // y_absl::CivilDay default_value; // 1970-01-01 00:00:00 -// +// // y_absl::CivilDay a(2015, 2, 3); // 2015-02-03 00:00:00 // y_absl::CivilDay b(2015, 2, 3, 4, 5, 6); // 2015-02-03 00:00:00 // y_absl::CivilDay c(2015); // 2015-01-01 00:00:00 -// +// // y_absl::CivilSecond ss(2015, 2, 3, 4, 5, 6); // 2015-02-03 04:05:06 // y_absl::CivilMinute mm(ss); // 2015-02-03 04:05:00 // y_absl::CivilHour hh(mm); // 2015-02-03 04:00:00 // y_absl::CivilDay d(hh); // 2015-02-03 00:00:00 // y_absl::CivilMonth m(d); // 2015-02-01 00:00:00 // y_absl::CivilYear y(m); // 2015-01-01 00:00:00 -// +// // m = y_absl::CivilMonth(y); // 2015-01-01 00:00:00 // d = y_absl::CivilDay(m); // 2015-01-01 00:00:00 // hh = y_absl::CivilHour(d); // 2015-01-01 00:00:00 // mm = y_absl::CivilMinute(hh); // 2015-01-01 00:00:00 // ss = y_absl::CivilSecond(mm); // 2015-01-01 00:00:00 -// -// Each civil-time class is aligned to the civil-time field indicated in the -// class's name after normalization. Alignment is performed by setting all the -// inferior fields to their minimum valid value (as described above). The -// following are examples of how each of the six types would align the fields -// representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the -// string format used here is not important; it's just a shorthand way of -// showing the six YMDHMS fields.) -// +// +// Each civil-time class is aligned to the civil-time field indicated in the +// class's name after normalization. Alignment is performed by setting all the +// inferior fields to their minimum valid value (as described above). The +// following are examples of how each of the six types would align the fields +// representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the +// string format used here is not important; it's just a shorthand way of +// showing the six YMDHMS fields.) +// // y_absl::CivilSecond : 2015-11-22 12:34:56 // y_absl::CivilMinute : 2015-11-22 12:34:00 // y_absl::CivilHour : 2015-11-22 12:00:00 // y_absl::CivilDay : 2015-11-22 00:00:00 // y_absl::CivilMonth : 2015-11-01 00:00:00 // y_absl::CivilYear : 2015-01-01 00:00:00 -// -// Each civil-time type performs arithmetic on the field to which it is +// +// Each civil-time type performs arithmetic on the field to which it is // aligned. This means that adding 1 to an y_absl::CivilDay increments the day // field (normalizing as necessary), and subtracting 7 from an y_absl::CivilMonth -// operates on the month field (normalizing as necessary). All arithmetic -// produces a valid civil time. Difference requires two similarly aligned -// civil-time objects and returns the scalar answer in units of the objects' +// operates on the month field (normalizing as necessary). All arithmetic +// produces a valid civil time. Difference requires two similarly aligned +// civil-time objects and returns the scalar answer in units of the objects' // alignment. For example, the difference between two y_absl::CivilHour objects -// will give an answer in units of civil hours. -// -// ALIGNMENT CONVERSION -// -// The alignment of a civil-time object cannot change, but the object may be -// used to construct a new object with a different alignment. This is referred -// to as "realigning". When realigning to a type with the same or more +// will give an answer in units of civil hours. +// +// ALIGNMENT CONVERSION +// +// The alignment of a civil-time object cannot change, but the object may be +// used to construct a new object with a different alignment. This is referred +// to as "realigning". When realigning to a type with the same or more // precision (e.g., y_absl::CivilDay -> y_absl::CivilSecond), the conversion may be -// performed implicitly since no information is lost. However, if information -// could be discarded (e.g., CivilSecond -> CivilDay), the conversion must -// be explicit at the call site. -// -// Examples: -// +// performed implicitly since no information is lost. However, if information +// could be discarded (e.g., CivilSecond -> CivilDay), the conversion must +// be explicit at the call site. +// +// Examples: +// // void UseDay(y_absl::CivilDay day); -// +// // y_absl::CivilSecond cs; -// UseDay(cs); // Won't compile because data may be discarded +// UseDay(cs); // Won't compile because data may be discarded // UseDay(y_absl::CivilDay(cs)); // OK: explicit conversion -// +// // y_absl::CivilDay cd; -// UseDay(cd); // OK: no conversion needed -// +// UseDay(cd); // OK: no conversion needed +// // y_absl::CivilMonth cm; // UseDay(cm); // OK: implicit conversion to y_absl::CivilDay -// -// NORMALIZATION -// -// Normalization takes invalid values and adjusts them to produce valid values. -// Within the civil-time library, integer arguments passed to the Civil* -// constructors may be out-of-range, in which case they are normalized by -// carrying overflow into a field of courser granularity to produce valid -// civil-time objects. This normalization enables natural arithmetic on -// constructor arguments without worrying about the field's range. -// -// Examples: -// -// // Out-of-range; normalized to 2016-11-01 +// +// NORMALIZATION +// +// Normalization takes invalid values and adjusts them to produce valid values. +// Within the civil-time library, integer arguments passed to the Civil* +// constructors may be out-of-range, in which case they are normalized by +// carrying overflow into a field of courser granularity to produce valid +// civil-time objects. This normalization enables natural arithmetic on +// constructor arguments without worrying about the field's range. +// +// Examples: +// +// // Out-of-range; normalized to 2016-11-01 // y_absl::CivilDay d(2016, 10, 32); -// // Out-of-range, negative: normalized to 2016-10-30T23 +// // Out-of-range, negative: normalized to 2016-10-30T23 // y_absl::CivilHour h1(2016, 10, 31, -1); -// // Normalization is cumulative: normalized to 2016-10-30T23 +// // Normalization is cumulative: normalized to 2016-10-30T23 // y_absl::CivilHour h2(2016, 10, 32, -25); -// -// Note: If normalization is undesired, you can signal an error by comparing -// the constructor arguments to the normalized values returned by the YMDHMS -// properties. -// -// COMPARISON -// -// Comparison between civil-time objects considers all six YMDHMS fields, -// regardless of the type's alignment. Comparison between differently aligned -// civil-time types is allowed. -// -// Examples: -// +// +// Note: If normalization is undesired, you can signal an error by comparing +// the constructor arguments to the normalized values returned by the YMDHMS +// properties. +// +// COMPARISON +// +// Comparison between civil-time objects considers all six YMDHMS fields, +// regardless of the type's alignment. Comparison between differently aligned +// civil-time types is allowed. +// +// Examples: +// // y_absl::CivilDay feb_3(2015, 2, 3); // 2015-02-03 00:00:00 // y_absl::CivilDay mar_4(2015, 3, 4); // 2015-03-04 00:00:00 -// // feb_3 < mar_4 +// // feb_3 < mar_4 // // y_absl::CivilYear(feb_3) == y_absl::CivilYear(mar_4) -// +// // y_absl::CivilSecond feb_3_noon(2015, 2, 3, 12, 0, 0); // 2015-02-03 12:00:00 -// // feb_3 < feb_3_noon +// // feb_3 < feb_3_noon // // feb_3 == y_absl::CivilDay(feb_3_noon) -// -// // Iterates all the days of February 2015. +// +// // Iterates all the days of February 2015. // for (y_absl::CivilDay d(2015, 2, 1); d < y_absl::CivilMonth(2015, 3); ++d) { -// // ... -// } -// -// ARITHMETIC -// -// Civil-time types support natural arithmetic operators such as addition, -// subtraction, and difference. Arithmetic operates on the civil-time field -// indicated in the type's name. Difference operators require arguments with -// the same alignment and return the answer in units of the alignment. -// -// Example: -// +// // ... +// } +// +// ARITHMETIC +// +// Civil-time types support natural arithmetic operators such as addition, +// subtraction, and difference. Arithmetic operates on the civil-time field +// indicated in the type's name. Difference operators require arguments with +// the same alignment and return the answer in units of the alignment. +// +// Example: +// // y_absl::CivilDay a(2015, 2, 3); -// ++a; // 2015-02-04 00:00:00 -// --a; // 2015-02-03 00:00:00 +// ++a; // 2015-02-04 00:00:00 +// --a; // 2015-02-03 00:00:00 // y_absl::CivilDay b = a + 1; // 2015-02-04 00:00:00 // y_absl::CivilDay c = 1 + b; // 2015-02-05 00:00:00 -// int n = c - a; // n = 2 (civil days) +// int n = c - a; // n = 2 (civil days) // int m = c - y_absl::CivilMonth(c); // Won't compile: different types. -// -// ACCESSORS -// -// Each civil-time type has accessors for all six of the civil-time fields: -// year, month, day, hour, minute, and second. -// -// civil_year_t year() -// int month() -// int day() -// int hour() -// int minute() -// int second() -// -// Recall that fields inferior to the type's alignment will be set to their -// minimum valid value. -// -// Example: -// +// +// ACCESSORS +// +// Each civil-time type has accessors for all six of the civil-time fields: +// year, month, day, hour, minute, and second. +// +// civil_year_t year() +// int month() +// int day() +// int hour() +// int minute() +// int second() +// +// Recall that fields inferior to the type's alignment will be set to their +// minimum valid value. +// +// Example: +// // y_absl::CivilDay d(2015, 6, 28); -// // d.year() == 2015 -// // d.month() == 6 -// // d.day() == 28 -// // d.hour() == 0 -// // d.minute() == 0 -// // d.second() == 0 -// -// CASE STUDY: Adding a month to January 31. -// -// One of the classic questions that arises when considering a civil time -// library (or a date library or a date/time library) is this: -// "What is the result of adding a month to January 31?" -// This is an interesting question because it is unclear what is meant by a -// "month", and several different answers are possible, depending on context: -// -// 1. March 3 (or 2 if a leap year), if "add a month" means to add a month to -// the current month, and adjust the date to overflow the extra days into -// March. In this case the result of "February 31" would be normalized as -// within the civil-time library. -// 2. February 28 (or 29 if a leap year), if "add a month" means to add a -// month, and adjust the date while holding the resulting month constant. -// In this case, the result of "February 31" would be truncated to the last -// day in February. -// 3. An error. The caller may get some error, an exception, an invalid date -// object, or perhaps return `false`. This may make sense because there is -// no single unambiguously correct answer to the question. -// -// Practically speaking, any answer that is not what the programmer intended -// is the wrong answer. -// -// The Abseil time library avoids this problem by making it impossible to -// ask ambiguous questions. All civil-time objects are aligned to a particular -// civil-field boundary (such as aligned to a year, month, day, hour, minute, -// or second), and arithmetic operates on the field to which the object is -// aligned. This means that in order to "add a month" the object must first be -// aligned to a month boundary, which is equivalent to the first day of that -// month. -// -// Of course, there are ways to compute an answer the question at hand using -// this Abseil time library, but they require the programmer to be explicit -// about the answer they expect. To illustrate, let's see how to compute all -// three of the above possible answers to the question of "Jan 31 plus 1 -// month": -// -// Example: -// +// // d.year() == 2015 +// // d.month() == 6 +// // d.day() == 28 +// // d.hour() == 0 +// // d.minute() == 0 +// // d.second() == 0 +// +// CASE STUDY: Adding a month to January 31. +// +// One of the classic questions that arises when considering a civil time +// library (or a date library or a date/time library) is this: +// "What is the result of adding a month to January 31?" +// This is an interesting question because it is unclear what is meant by a +// "month", and several different answers are possible, depending on context: +// +// 1. March 3 (or 2 if a leap year), if "add a month" means to add a month to +// the current month, and adjust the date to overflow the extra days into +// March. In this case the result of "February 31" would be normalized as +// within the civil-time library. +// 2. February 28 (or 29 if a leap year), if "add a month" means to add a +// month, and adjust the date while holding the resulting month constant. +// In this case, the result of "February 31" would be truncated to the last +// day in February. +// 3. An error. The caller may get some error, an exception, an invalid date +// object, or perhaps return `false`. This may make sense because there is +// no single unambiguously correct answer to the question. +// +// Practically speaking, any answer that is not what the programmer intended +// is the wrong answer. +// +// The Abseil time library avoids this problem by making it impossible to +// ask ambiguous questions. All civil-time objects are aligned to a particular +// civil-field boundary (such as aligned to a year, month, day, hour, minute, +// or second), and arithmetic operates on the field to which the object is +// aligned. This means that in order to "add a month" the object must first be +// aligned to a month boundary, which is equivalent to the first day of that +// month. +// +// Of course, there are ways to compute an answer the question at hand using +// this Abseil time library, but they require the programmer to be explicit +// about the answer they expect. To illustrate, let's see how to compute all +// three of the above possible answers to the question of "Jan 31 plus 1 +// month": +// +// Example: +// // const y_absl::CivilDay d(2015, 1, 31); -// -// // Answer 1: -// // Add 1 to the month field in the constructor, and rely on normalization. +// +// // Answer 1: +// // Add 1 to the month field in the constructor, and rely on normalization. // const auto normalized = y_absl::CivilDay(d.year(), d.month() + 1, d.day()); -// // normalized == 2015-03-03 (aka Feb 31) -// -// // Answer 2: -// // Add 1 to month field, capping to the end of next month. +// // normalized == 2015-03-03 (aka Feb 31) +// +// // Answer 2: +// // Add 1 to month field, capping to the end of next month. // const auto next_month = y_absl::CivilMonth(d) + 1; // const auto last_day_of_next_month = y_absl::CivilDay(next_month + 1) - 1; -// const auto capped = std::min(normalized, last_day_of_next_month); -// // capped == 2015-02-28 -// -// // Answer 3: -// // Signal an error if the normalized answer is not in next month. +// const auto capped = std::min(normalized, last_day_of_next_month); +// // capped == 2015-02-28 +// +// // Answer 3: +// // Signal an error if the normalized answer is not in next month. // if (y_absl::CivilMonth(normalized) != next_month) { -// // error, month overflow -// } -// -using CivilSecond = - time_internal::cctz::detail::civil_time<time_internal::second_tag>; -using CivilMinute = - time_internal::cctz::detail::civil_time<time_internal::minute_tag>; -using CivilHour = - time_internal::cctz::detail::civil_time<time_internal::hour_tag>; -using CivilDay = - time_internal::cctz::detail::civil_time<time_internal::day_tag>; -using CivilMonth = - time_internal::cctz::detail::civil_time<time_internal::month_tag>; -using CivilYear = - time_internal::cctz::detail::civil_time<time_internal::year_tag>; - -// civil_year_t -// -// Type alias of a civil-time year value. This type is guaranteed to (at least) -// support any year value supported by `time_t`. -// -// Example: -// +// // error, month overflow +// } +// +using CivilSecond = + time_internal::cctz::detail::civil_time<time_internal::second_tag>; +using CivilMinute = + time_internal::cctz::detail::civil_time<time_internal::minute_tag>; +using CivilHour = + time_internal::cctz::detail::civil_time<time_internal::hour_tag>; +using CivilDay = + time_internal::cctz::detail::civil_time<time_internal::day_tag>; +using CivilMonth = + time_internal::cctz::detail::civil_time<time_internal::month_tag>; +using CivilYear = + time_internal::cctz::detail::civil_time<time_internal::year_tag>; + +// civil_year_t +// +// Type alias of a civil-time year value. This type is guaranteed to (at least) +// support any year value supported by `time_t`. +// +// Example: +// // y_absl::CivilSecond cs = ...; // y_absl::civil_year_t y = cs.year(); // cs = y_absl::CivilSecond(y, 1, 1, 0, 0, 0); // CivilSecond(CivilYear(cs)) -// -using civil_year_t = time_internal::cctz::year_t; - -// civil_diff_t -// -// Type alias of the difference between two civil-time values. -// This type is used to indicate arguments that are not -// normalized (such as parameters to the civil-time constructors), the results -// of civil-time subtraction, or the operand to civil-time addition. -// -// Example: -// +// +using civil_year_t = time_internal::cctz::year_t; + +// civil_diff_t +// +// Type alias of the difference between two civil-time values. +// This type is used to indicate arguments that are not +// normalized (such as parameters to the civil-time constructors), the results +// of civil-time subtraction, or the operand to civil-time addition. +// +// Example: +// // y_absl::civil_diff_t n_sec = cs1 - cs2; // cs1 == cs2 + n_sec; -// -using civil_diff_t = time_internal::cctz::diff_t; - -// Weekday::monday, Weekday::tuesday, Weekday::wednesday, Weekday::thursday, -// Weekday::friday, Weekday::saturday, Weekday::sunday -// -// The Weekday enum class represents the civil-time concept of a "weekday" with -// members for all days of the week. -// +// +using civil_diff_t = time_internal::cctz::diff_t; + +// Weekday::monday, Weekday::tuesday, Weekday::wednesday, Weekday::thursday, +// Weekday::friday, Weekday::saturday, Weekday::sunday +// +// The Weekday enum class represents the civil-time concept of a "weekday" with +// members for all days of the week. +// // y_absl::Weekday wd = y_absl::Weekday::thursday; -// -using Weekday = time_internal::cctz::weekday; - -// GetWeekday() -// +// +using Weekday = time_internal::cctz::weekday; + +// GetWeekday() +// // Returns the y_absl::Weekday for the given (realigned) civil-time value. -// -// Example: -// +// +// Example: +// // y_absl::CivilDay a(2015, 8, 13); // y_absl::Weekday wd = y_absl::GetWeekday(a); // wd == y_absl::Weekday::thursday -// -inline Weekday GetWeekday(CivilSecond cs) { - return time_internal::cctz::get_weekday(cs); -} - -// NextWeekday() -// PrevWeekday() -// +// +inline Weekday GetWeekday(CivilSecond cs) { + return time_internal::cctz::get_weekday(cs); +} + +// NextWeekday() +// PrevWeekday() +// // Returns the y_absl::CivilDay that strictly follows or precedes a given // y_absl::CivilDay, and that falls on the given y_absl::Weekday. -// -// Example, given the following month: -// -// August 2015 -// Su Mo Tu We Th Fr Sa -// 1 -// 2 3 4 5 6 7 8 -// 9 10 11 12 13 14 15 -// 16 17 18 19 20 21 22 -// 23 24 25 26 27 28 29 -// 30 31 -// +// +// Example, given the following month: +// +// August 2015 +// Su Mo Tu We Th Fr Sa +// 1 +// 2 3 4 5 6 7 8 +// 9 10 11 12 13 14 15 +// 16 17 18 19 20 21 22 +// 23 24 25 26 27 28 29 +// 30 31 +// // y_absl::CivilDay a(2015, 8, 13); // // y_absl::GetWeekday(a) == y_absl::Weekday::thursday // y_absl::CivilDay b = y_absl::NextWeekday(a, y_absl::Weekday::thursday); -// // b = 2015-08-20 +// // b = 2015-08-20 // y_absl::CivilDay c = y_absl::PrevWeekday(a, y_absl::Weekday::thursday); -// // c = 2015-08-06 -// +// // c = 2015-08-06 +// // y_absl::CivilDay d = ... -// // Gets the following Thursday if d is not already Thursday +// // Gets the following Thursday if d is not already Thursday // y_absl::CivilDay thurs1 = y_absl::NextWeekday(d - 1, y_absl::Weekday::thursday); -// // Gets the previous Thursday if d is not already Thursday +// // Gets the previous Thursday if d is not already Thursday // y_absl::CivilDay thurs2 = y_absl::PrevWeekday(d + 1, y_absl::Weekday::thursday); -// -inline CivilDay NextWeekday(CivilDay cd, Weekday wd) { - return CivilDay(time_internal::cctz::next_weekday(cd, wd)); -} -inline CivilDay PrevWeekday(CivilDay cd, Weekday wd) { - return CivilDay(time_internal::cctz::prev_weekday(cd, wd)); -} - -// GetYearDay() -// -// Returns the day-of-year for the given (realigned) civil-time value. -// -// Example: -// +// +inline CivilDay NextWeekday(CivilDay cd, Weekday wd) { + return CivilDay(time_internal::cctz::next_weekday(cd, wd)); +} +inline CivilDay PrevWeekday(CivilDay cd, Weekday wd) { + return CivilDay(time_internal::cctz::prev_weekday(cd, wd)); +} + +// GetYearDay() +// +// Returns the day-of-year for the given (realigned) civil-time value. +// +// Example: +// // y_absl::CivilDay a(2015, 1, 1); // int yd_jan_1 = y_absl::GetYearDay(a); // yd_jan_1 = 1 // y_absl::CivilDay b(2015, 12, 31); // int yd_dec_31 = y_absl::GetYearDay(b); // yd_dec_31 = 365 -// -inline int GetYearDay(CivilSecond cs) { - return time_internal::cctz::get_yearday(cs); -} - -// FormatCivilTime() -// -// Formats the given civil-time value into a string value of the following -// format: -// -// Type | Format -// --------------------------------- -// CivilSecond | YYYY-MM-DDTHH:MM:SS -// CivilMinute | YYYY-MM-DDTHH:MM -// CivilHour | YYYY-MM-DDTHH -// CivilDay | YYYY-MM-DD -// CivilMonth | YYYY-MM -// CivilYear | YYYY -// -// Example: -// +// +inline int GetYearDay(CivilSecond cs) { + return time_internal::cctz::get_yearday(cs); +} + +// FormatCivilTime() +// +// Formats the given civil-time value into a string value of the following +// format: +// +// Type | Format +// --------------------------------- +// CivilSecond | YYYY-MM-DDTHH:MM:SS +// CivilMinute | YYYY-MM-DDTHH:MM +// CivilHour | YYYY-MM-DDTHH +// CivilDay | YYYY-MM-DD +// CivilMonth | YYYY-MM +// CivilYear | YYYY +// +// Example: +// // y_absl::CivilDay d = y_absl::CivilDay(1969, 7, 20); // TString day_string = y_absl::FormatCivilTime(d); // "1969-07-20" -// +// TString FormatCivilTime(CivilSecond c); TString FormatCivilTime(CivilMinute c); TString FormatCivilTime(CivilHour c); TString FormatCivilTime(CivilDay c); TString FormatCivilTime(CivilMonth c); TString FormatCivilTime(CivilYear c); - + // y_absl::ParseCivilTime() -// +// // Parses a civil-time value from the specified `y_absl::string_view` into the -// passed output parameter. Returns `true` upon successful parsing. -// -// The expected form of the input string is as follows: -// -// Type | Format -// --------------------------------- -// CivilSecond | YYYY-MM-DDTHH:MM:SS -// CivilMinute | YYYY-MM-DDTHH:MM -// CivilHour | YYYY-MM-DDTHH -// CivilDay | YYYY-MM-DD -// CivilMonth | YYYY-MM -// CivilYear | YYYY -// -// Example: -// +// passed output parameter. Returns `true` upon successful parsing. +// +// The expected form of the input string is as follows: +// +// Type | Format +// --------------------------------- +// CivilSecond | YYYY-MM-DDTHH:MM:SS +// CivilMinute | YYYY-MM-DDTHH:MM +// CivilHour | YYYY-MM-DDTHH +// CivilDay | YYYY-MM-DD +// CivilMonth | YYYY-MM +// CivilYear | YYYY +// +// Example: +// // y_absl::CivilDay d; // bool ok = y_absl::ParseCivilTime("2018-01-02", &d); // OK -// -// Note that parsing will fail if the string's format does not match the -// expected type exactly. `ParseLenientCivilTime()` below is more lenient. -// +// +// Note that parsing will fail if the string's format does not match the +// expected type exactly. `ParseLenientCivilTime()` below is more lenient. +// bool ParseCivilTime(y_absl::string_view s, CivilSecond* c); bool ParseCivilTime(y_absl::string_view s, CivilMinute* c); bool ParseCivilTime(y_absl::string_view s, CivilHour* c); bool ParseCivilTime(y_absl::string_view s, CivilDay* c); bool ParseCivilTime(y_absl::string_view s, CivilMonth* c); bool ParseCivilTime(y_absl::string_view s, CivilYear* c); - -// ParseLenientCivilTime() -// + +// ParseLenientCivilTime() +// // Parses any of the formats accepted by `y_absl::ParseCivilTime()`, but is more -// lenient if the format of the string does not exactly match the associated -// type. -// -// Example: -// +// lenient if the format of the string does not exactly match the associated +// type. +// +// Example: +// // y_absl::CivilDay d; // bool ok = y_absl::ParseLenientCivilTime("1969-07-20", &d); // OK // ok = y_absl::ParseLenientCivilTime("1969-07-20T10", &d); // OK: T10 floored // ok = y_absl::ParseLenientCivilTime("1969-07", &d); // OK: day defaults to 1 -// +// bool ParseLenientCivilTime(y_absl::string_view s, CivilSecond* c); bool ParseLenientCivilTime(y_absl::string_view s, CivilMinute* c); bool ParseLenientCivilTime(y_absl::string_view s, CivilHour* c); bool ParseLenientCivilTime(y_absl::string_view s, CivilDay* c); bool ParseLenientCivilTime(y_absl::string_view s, CivilMonth* c); bool ParseLenientCivilTime(y_absl::string_view s, CivilYear* c); - -namespace time_internal { // For functions found via ADL on civil-time tags. - -// Streaming Operators -// -// Each civil-time type may be sent to an output stream using operator<<(). -// The result matches the string produced by `FormatCivilTime()`. -// -// Example: -// + +namespace time_internal { // For functions found via ADL on civil-time tags. + +// Streaming Operators +// +// Each civil-time type may be sent to an output stream using operator<<(). +// The result matches the string produced by `FormatCivilTime()`. +// +// Example: +// // y_absl::CivilDay d = y_absl::CivilDay(1969, 7, 20); -// std::cout << "Date is: " << d << "\n"; -// -std::ostream& operator<<(std::ostream& os, CivilYear y); -std::ostream& operator<<(std::ostream& os, CivilMonth m); -std::ostream& operator<<(std::ostream& os, CivilDay d); -std::ostream& operator<<(std::ostream& os, CivilHour h); -std::ostream& operator<<(std::ostream& os, CivilMinute m); -std::ostream& operator<<(std::ostream& os, CivilSecond s); - -} // namespace time_internal - +// std::cout << "Date is: " << d << "\n"; +// +std::ostream& operator<<(std::ostream& os, CivilYear y); +std::ostream& operator<<(std::ostream& os, CivilMonth m); +std::ostream& operator<<(std::ostream& os, CivilDay d); +std::ostream& operator<<(std::ostream& os, CivilHour h); +std::ostream& operator<<(std::ostream& os, CivilMinute m); +std::ostream& operator<<(std::ostream& os, CivilSecond s); + +} // namespace time_internal + ABSL_NAMESPACE_END } // namespace y_absl - -#endif // ABSL_TIME_CIVIL_TIME_H_ + +#endif // ABSL_TIME_CIVIL_TIME_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time/ya.make index ac600f852c..919773f619 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time/ya.make +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time/ya.make @@ -1,26 +1,26 @@ -# Generated by devtools/yamaker. - -LIBRARY() - +# Generated by devtools/yamaker. + +LIBRARY() + WITHOUT_LICENSE_TEXTS() - + OWNER( somov g:cpp-contrib ) -LICENSE(Apache-2.0) - +LICENSE(Apache-2.0) + ADDINCL( GLOBAL contrib/restricted/abseil-cpp-tstring ) - -NO_COMPILER_WARNINGS() - + +NO_COMPILER_WARNINGS() + SRCDIR(contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src) - -SRCS( - civil_time_detail.cc -) - -END() + +SRCS( + civil_time_detail.cc +) + +END() diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/clock.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/clock.cc index d29b8e89d0..dcc12b5633 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/clock.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/clock.cc @@ -1,178 +1,178 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "y_absl/time/clock.h" - + #include "y_absl/base/attributes.h" #include "y_absl/base/optimization.h" - -#ifdef _WIN32 -#include <windows.h> -#endif - -#include <algorithm> -#include <atomic> -#include <cerrno> -#include <cstdint> -#include <ctime> -#include <limits> - + +#ifdef _WIN32 +#include <windows.h> +#endif + +#include <algorithm> +#include <atomic> +#include <cerrno> +#include <cstdint> +#include <ctime> +#include <limits> + #include "y_absl/base/internal/spinlock.h" #include "y_absl/base/internal/unscaledcycleclock.h" #include "y_absl/base/macros.h" #include "y_absl/base/port.h" #include "y_absl/base/thread_annotations.h" - + namespace y_absl { ABSL_NAMESPACE_BEGIN -Time Now() { - // TODO(bww): Get a timespec instead so we don't have to divide. +Time Now() { + // TODO(bww): Get a timespec instead so we don't have to divide. int64_t n = y_absl::GetCurrentTimeNanos(); - if (n >= 0) { - return time_internal::FromUnixDuration( - time_internal::MakeDuration(n / 1000000000, n % 1000000000 * 4)); - } + if (n >= 0) { + return time_internal::FromUnixDuration( + time_internal::MakeDuration(n / 1000000000, n % 1000000000 * 4)); + } return time_internal::FromUnixDuration(y_absl::Nanoseconds(n)); -} +} ABSL_NAMESPACE_END } // namespace y_absl - -// Decide if we should use the fast GetCurrentTimeNanos() algorithm -// based on the cyclecounter, otherwise just get the time directly -// from the OS on every call. This can be chosen at compile-time via -// -DABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS=[0|1] -#ifndef ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS -#if ABSL_USE_UNSCALED_CYCLECLOCK -#define ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS 1 -#else -#define ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS 0 -#endif -#endif - -#if defined(__APPLE__) || defined(_WIN32) + +// Decide if we should use the fast GetCurrentTimeNanos() algorithm +// based on the cyclecounter, otherwise just get the time directly +// from the OS on every call. This can be chosen at compile-time via +// -DABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS=[0|1] +#ifndef ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS +#if ABSL_USE_UNSCALED_CYCLECLOCK +#define ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS 1 +#else +#define ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS 0 +#endif +#endif + +#if defined(__APPLE__) || defined(_WIN32) #include "y_absl/time/internal/get_current_time_chrono.inc" -#else +#else #include "y_absl/time/internal/get_current_time_posix.inc" -#endif - -// Allows override by test. -#ifndef GET_CURRENT_TIME_NANOS_FROM_SYSTEM -#define GET_CURRENT_TIME_NANOS_FROM_SYSTEM() \ +#endif + +// Allows override by test. +#ifndef GET_CURRENT_TIME_NANOS_FROM_SYSTEM +#define GET_CURRENT_TIME_NANOS_FROM_SYSTEM() \ ::y_absl::time_internal::GetCurrentTimeNanosFromSystem() -#endif - -#if !ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS +#endif + +#if !ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS namespace y_absl { ABSL_NAMESPACE_BEGIN int64_t GetCurrentTimeNanos() { return GET_CURRENT_TIME_NANOS_FROM_SYSTEM(); } ABSL_NAMESPACE_END } // namespace y_absl -#else // Use the cyclecounter-based implementation below. - -// Allows override by test. -#ifndef GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW -#define GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW() \ +#else // Use the cyclecounter-based implementation below. + +// Allows override by test. +#ifndef GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW +#define GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW() \ ::y_absl::time_internal::UnscaledCycleClockWrapperForGetCurrentTime::Now() -#endif - +#endif + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -// This is a friend wrapper around UnscaledCycleClock::Now() -// (needed to access UnscaledCycleClock). -class UnscaledCycleClockWrapperForGetCurrentTime { - public: - static int64_t Now() { return base_internal::UnscaledCycleClock::Now(); } -}; -} // namespace time_internal - -// uint64_t is used in this module to provide an extra bit in multiplications - -// --------------------------------------------------------------------- -// An implementation of reader-write locks that use no atomic ops in the read -// case. This is a generalization of Lamport's method for reading a multiword -// clock. Increment a word on each write acquisition, using the low-order bit -// as a spinlock; the word is the high word of the "clock". Readers read the -// high word, then all other data, then the high word again, and repeat the -// read if the reads of the high words yields different answers, or an odd -// value (either case suggests possible interference from a writer). -// Here we use a spinlock to ensure only one writer at a time, rather than -// spinning on the bottom bit of the word to benefit from SpinLock -// spin-delay tuning. - -// Acquire seqlock (*seq) and return the value to be written to unlock. -static inline uint64_t SeqAcquire(std::atomic<uint64_t> *seq) { - uint64_t x = seq->fetch_add(1, std::memory_order_relaxed); - - // We put a release fence between update to *seq and writes to shared data. - // Thus all stores to shared data are effectively release operations and - // update to *seq above cannot be re-ordered past any of them. Note that - // this barrier is not for the fetch_add above. A release barrier for the - // fetch_add would be before it, not after. - std::atomic_thread_fence(std::memory_order_release); - - return x + 2; // original word plus 2 -} - -// Release seqlock (*seq) by writing x to it---a value previously returned by -// SeqAcquire. -static inline void SeqRelease(std::atomic<uint64_t> *seq, uint64_t x) { - // The unlock store to *seq must have release ordering so that all - // updates to shared data must finish before this store. - seq->store(x, std::memory_order_release); // release lock for readers -} - -// --------------------------------------------------------------------- - -// "nsscaled" is unit of time equal to a (2**kScale)th of a nanosecond. -enum { kScale = 30 }; - -// The minimum interval between samples of the time base. -// We pick enough time to amortize the cost of the sample, -// to get a reasonably accurate cycle counter rate reading, -// and not so much that calculations will overflow 64-bits. -static const uint64_t kMinNSBetweenSamples = 2000 << 20; - -// We require that kMinNSBetweenSamples shifted by kScale -// have at least a bit left over for 64-bit calculations. -static_assert(((kMinNSBetweenSamples << (kScale + 1)) >> (kScale + 1)) == - kMinNSBetweenSamples, - "cannot represent kMaxBetweenSamplesNSScaled"); - -// data from a sample of the kernel's time value -struct TimeSampleAtomic { +namespace time_internal { +// This is a friend wrapper around UnscaledCycleClock::Now() +// (needed to access UnscaledCycleClock). +class UnscaledCycleClockWrapperForGetCurrentTime { + public: + static int64_t Now() { return base_internal::UnscaledCycleClock::Now(); } +}; +} // namespace time_internal + +// uint64_t is used in this module to provide an extra bit in multiplications + +// --------------------------------------------------------------------- +// An implementation of reader-write locks that use no atomic ops in the read +// case. This is a generalization of Lamport's method for reading a multiword +// clock. Increment a word on each write acquisition, using the low-order bit +// as a spinlock; the word is the high word of the "clock". Readers read the +// high word, then all other data, then the high word again, and repeat the +// read if the reads of the high words yields different answers, or an odd +// value (either case suggests possible interference from a writer). +// Here we use a spinlock to ensure only one writer at a time, rather than +// spinning on the bottom bit of the word to benefit from SpinLock +// spin-delay tuning. + +// Acquire seqlock (*seq) and return the value to be written to unlock. +static inline uint64_t SeqAcquire(std::atomic<uint64_t> *seq) { + uint64_t x = seq->fetch_add(1, std::memory_order_relaxed); + + // We put a release fence between update to *seq and writes to shared data. + // Thus all stores to shared data are effectively release operations and + // update to *seq above cannot be re-ordered past any of them. Note that + // this barrier is not for the fetch_add above. A release barrier for the + // fetch_add would be before it, not after. + std::atomic_thread_fence(std::memory_order_release); + + return x + 2; // original word plus 2 +} + +// Release seqlock (*seq) by writing x to it---a value previously returned by +// SeqAcquire. +static inline void SeqRelease(std::atomic<uint64_t> *seq, uint64_t x) { + // The unlock store to *seq must have release ordering so that all + // updates to shared data must finish before this store. + seq->store(x, std::memory_order_release); // release lock for readers +} + +// --------------------------------------------------------------------- + +// "nsscaled" is unit of time equal to a (2**kScale)th of a nanosecond. +enum { kScale = 30 }; + +// The minimum interval between samples of the time base. +// We pick enough time to amortize the cost of the sample, +// to get a reasonably accurate cycle counter rate reading, +// and not so much that calculations will overflow 64-bits. +static const uint64_t kMinNSBetweenSamples = 2000 << 20; + +// We require that kMinNSBetweenSamples shifted by kScale +// have at least a bit left over for 64-bit calculations. +static_assert(((kMinNSBetweenSamples << (kScale + 1)) >> (kScale + 1)) == + kMinNSBetweenSamples, + "cannot represent kMaxBetweenSamplesNSScaled"); + +// data from a sample of the kernel's time value +struct TimeSampleAtomic { std::atomic<uint64_t> raw_ns{0}; // raw kernel time std::atomic<uint64_t> base_ns{0}; // our estimate of time std::atomic<uint64_t> base_cycles{0}; // cycle counter reading std::atomic<uint64_t> nsscaled_per_cycle{0}; // cycle period - // cycles before we'll sample again (a scaled reciprocal of the period, - // to avoid a division on the fast path). + // cycles before we'll sample again (a scaled reciprocal of the period, + // to avoid a division on the fast path). std::atomic<uint64_t> min_cycles_per_sample{0}; -}; -// Same again, but with non-atomic types -struct TimeSample { +}; +// Same again, but with non-atomic types +struct TimeSample { uint64_t raw_ns = 0; // raw kernel time uint64_t base_ns = 0; // our estimate of time uint64_t base_cycles = 0; // cycle counter reading uint64_t nsscaled_per_cycle = 0; // cycle period uint64_t min_cycles_per_sample = 0; // approx cycles before next sample -}; - +}; + struct ABSL_CACHELINE_ALIGNED TimeState { std::atomic<uint64_t> seq{0}; TimeSampleAtomic last_sample; // the last sample; under seq - + // The following counters are used only by the test code. int64_t stats_initializations{0}; int64_t stats_reinitializations{0}; @@ -255,205 +255,205 @@ static int64_t GetCurrentTimeNanosFromKernel(uint64_t last_cycleclock, return current_time_nanos_from_system; } -static int64_t GetCurrentTimeNanosSlowPath() ABSL_ATTRIBUTE_COLD; - -// Read the contents of *atomic into *sample. -// Each field is read atomically, but to maintain atomicity between fields, -// the access must be done under a lock. -static void ReadTimeSampleAtomic(const struct TimeSampleAtomic *atomic, - struct TimeSample *sample) { - sample->base_ns = atomic->base_ns.load(std::memory_order_relaxed); - sample->base_cycles = atomic->base_cycles.load(std::memory_order_relaxed); - sample->nsscaled_per_cycle = - atomic->nsscaled_per_cycle.load(std::memory_order_relaxed); - sample->min_cycles_per_sample = - atomic->min_cycles_per_sample.load(std::memory_order_relaxed); - sample->raw_ns = atomic->raw_ns.load(std::memory_order_relaxed); -} - -// Public routine. -// Algorithm: We wish to compute real time from a cycle counter. In normal -// operation, we construct a piecewise linear approximation to the kernel time -// source, using the cycle counter value. The start of each line segment is at -// the same point as the end of the last, but may have a different slope (that -// is, a different idea of the cycle counter frequency). Every couple of -// seconds, the kernel time source is sampled and compared with the current -// approximation. A new slope is chosen that, if followed for another couple -// of seconds, will correct the error at the current position. The information -// for a sample is in the "last_sample" struct. The linear approximation is -// estimated_time = last_sample.base_ns + -// last_sample.ns_per_cycle * (counter_reading - last_sample.base_cycles) -// (ns_per_cycle is actually stored in different units and scaled, to avoid -// overflow). The base_ns of the next linear approximation is the -// estimated_time using the last approximation; the base_cycles is the cycle -// counter value at that time; the ns_per_cycle is the number of ns per cycle -// measured since the last sample, but adjusted so that most of the difference -// between the estimated_time and the kernel time will be corrected by the -// estimated time to the next sample. In normal operation, this algorithm -// relies on: -// - the cycle counter and kernel time rates not changing a lot in a few -// seconds. -// - the client calling into the code often compared to a couple of seconds, so -// the time to the next correction can be estimated. -// Any time ns_per_cycle is not known, a major error is detected, or the -// assumption about frequent calls is violated, the implementation returns the -// kernel time. It records sufficient data that a linear approximation can -// resume a little later. - -int64_t GetCurrentTimeNanos() { - // read the data from the "last_sample" struct (but don't need raw_ns yet) - // The reads of "seq" and test of the values emulate a reader lock. - uint64_t base_ns; - uint64_t base_cycles; - uint64_t nsscaled_per_cycle; - uint64_t min_cycles_per_sample; - uint64_t seq_read0; - uint64_t seq_read1; - - // If we have enough information to interpolate, the value returned will be - // derived from this cycleclock-derived time estimate. On some platforms - // (POWER) the function to retrieve this value has enough complexity to - // contribute to register pressure - reading it early before initializing - // the other pieces of the calculation minimizes spill/restore instructions, - // minimizing icache cost. - uint64_t now_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW(); - - // Acquire pairs with the barrier in SeqRelease - if this load sees that - // store, the shared-data reads necessarily see that SeqRelease's updates - // to the same shared data. +static int64_t GetCurrentTimeNanosSlowPath() ABSL_ATTRIBUTE_COLD; + +// Read the contents of *atomic into *sample. +// Each field is read atomically, but to maintain atomicity between fields, +// the access must be done under a lock. +static void ReadTimeSampleAtomic(const struct TimeSampleAtomic *atomic, + struct TimeSample *sample) { + sample->base_ns = atomic->base_ns.load(std::memory_order_relaxed); + sample->base_cycles = atomic->base_cycles.load(std::memory_order_relaxed); + sample->nsscaled_per_cycle = + atomic->nsscaled_per_cycle.load(std::memory_order_relaxed); + sample->min_cycles_per_sample = + atomic->min_cycles_per_sample.load(std::memory_order_relaxed); + sample->raw_ns = atomic->raw_ns.load(std::memory_order_relaxed); +} + +// Public routine. +// Algorithm: We wish to compute real time from a cycle counter. In normal +// operation, we construct a piecewise linear approximation to the kernel time +// source, using the cycle counter value. The start of each line segment is at +// the same point as the end of the last, but may have a different slope (that +// is, a different idea of the cycle counter frequency). Every couple of +// seconds, the kernel time source is sampled and compared with the current +// approximation. A new slope is chosen that, if followed for another couple +// of seconds, will correct the error at the current position. The information +// for a sample is in the "last_sample" struct. The linear approximation is +// estimated_time = last_sample.base_ns + +// last_sample.ns_per_cycle * (counter_reading - last_sample.base_cycles) +// (ns_per_cycle is actually stored in different units and scaled, to avoid +// overflow). The base_ns of the next linear approximation is the +// estimated_time using the last approximation; the base_cycles is the cycle +// counter value at that time; the ns_per_cycle is the number of ns per cycle +// measured since the last sample, but adjusted so that most of the difference +// between the estimated_time and the kernel time will be corrected by the +// estimated time to the next sample. In normal operation, this algorithm +// relies on: +// - the cycle counter and kernel time rates not changing a lot in a few +// seconds. +// - the client calling into the code often compared to a couple of seconds, so +// the time to the next correction can be estimated. +// Any time ns_per_cycle is not known, a major error is detected, or the +// assumption about frequent calls is violated, the implementation returns the +// kernel time. It records sufficient data that a linear approximation can +// resume a little later. + +int64_t GetCurrentTimeNanos() { + // read the data from the "last_sample" struct (but don't need raw_ns yet) + // The reads of "seq" and test of the values emulate a reader lock. + uint64_t base_ns; + uint64_t base_cycles; + uint64_t nsscaled_per_cycle; + uint64_t min_cycles_per_sample; + uint64_t seq_read0; + uint64_t seq_read1; + + // If we have enough information to interpolate, the value returned will be + // derived from this cycleclock-derived time estimate. On some platforms + // (POWER) the function to retrieve this value has enough complexity to + // contribute to register pressure - reading it early before initializing + // the other pieces of the calculation minimizes spill/restore instructions, + // minimizing icache cost. + uint64_t now_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW(); + + // Acquire pairs with the barrier in SeqRelease - if this load sees that + // store, the shared-data reads necessarily see that SeqRelease's updates + // to the same shared data. seq_read0 = time_state.seq.load(std::memory_order_acquire); - + base_ns = time_state.last_sample.base_ns.load(std::memory_order_relaxed); base_cycles = time_state.last_sample.base_cycles.load(std::memory_order_relaxed); - nsscaled_per_cycle = + nsscaled_per_cycle = time_state.last_sample.nsscaled_per_cycle.load(std::memory_order_relaxed); min_cycles_per_sample = time_state.last_sample.min_cycles_per_sample.load( std::memory_order_relaxed); - - // This acquire fence pairs with the release fence in SeqAcquire. Since it - // is sequenced between reads of shared data and seq_read1, the reads of - // shared data are effectively acquiring. - std::atomic_thread_fence(std::memory_order_acquire); - - // The shared-data reads are effectively acquire ordered, and the - // shared-data writes are effectively release ordered. Therefore if our - // shared-data reads see any of a particular update's shared-data writes, - // seq_read1 is guaranteed to see that update's SeqAcquire. + + // This acquire fence pairs with the release fence in SeqAcquire. Since it + // is sequenced between reads of shared data and seq_read1, the reads of + // shared data are effectively acquiring. + std::atomic_thread_fence(std::memory_order_acquire); + + // The shared-data reads are effectively acquire ordered, and the + // shared-data writes are effectively release ordered. Therefore if our + // shared-data reads see any of a particular update's shared-data writes, + // seq_read1 is guaranteed to see that update's SeqAcquire. seq_read1 = time_state.seq.load(std::memory_order_relaxed); - - // Fast path. Return if min_cycles_per_sample has not yet elapsed since the - // last sample, and we read a consistent sample. The fast path activates - // only when min_cycles_per_sample is non-zero, which happens when we get an - // estimate for the cycle time. The predicate will fail if now_cycles < - // base_cycles, or if some other thread is in the slow path. - // - // Since we now read now_cycles before base_ns, it is possible for now_cycles - // to be less than base_cycles (if we were interrupted between those loads and - // last_sample was updated). This is harmless, because delta_cycles will wrap - // and report a time much much bigger than min_cycles_per_sample. In that case - // we will take the slow path. + + // Fast path. Return if min_cycles_per_sample has not yet elapsed since the + // last sample, and we read a consistent sample. The fast path activates + // only when min_cycles_per_sample is non-zero, which happens when we get an + // estimate for the cycle time. The predicate will fail if now_cycles < + // base_cycles, or if some other thread is in the slow path. + // + // Since we now read now_cycles before base_ns, it is possible for now_cycles + // to be less than base_cycles (if we were interrupted between those loads and + // last_sample was updated). This is harmless, because delta_cycles will wrap + // and report a time much much bigger than min_cycles_per_sample. In that case + // we will take the slow path. uint64_t delta_cycles; - if (seq_read0 == seq_read1 && (seq_read0 & 1) == 0 && + if (seq_read0 == seq_read1 && (seq_read0 & 1) == 0 && (delta_cycles = now_cycles - base_cycles) < min_cycles_per_sample) { - return base_ns + ((delta_cycles * nsscaled_per_cycle) >> kScale); - } - return GetCurrentTimeNanosSlowPath(); -} - -// Return (a << kScale)/b. -// Zero is returned if b==0. Scaling is performed internally to -// preserve precision without overflow. -static uint64_t SafeDivideAndScale(uint64_t a, uint64_t b) { - // Find maximum safe_shift so that - // 0 <= safe_shift <= kScale and (a << safe_shift) does not overflow. - int safe_shift = kScale; - while (((a << safe_shift) >> safe_shift) != a) { - safe_shift--; - } - uint64_t scaled_b = b >> (kScale - safe_shift); - uint64_t quotient = 0; - if (scaled_b != 0) { - quotient = (a << safe_shift) / scaled_b; - } - return quotient; -} - -static uint64_t UpdateLastSample( - uint64_t now_cycles, uint64_t now_ns, uint64_t delta_cycles, - const struct TimeSample *sample) ABSL_ATTRIBUTE_COLD; - -// The slow path of GetCurrentTimeNanos(). This is taken while gathering -// initial samples, when enough time has elapsed since the last sample, and if -// any other thread is writing to last_sample. -// -// Manually mark this 'noinline' to minimize stack frame size of the fast -// path. Without this, sometimes a compiler may inline this big block of code -// into the fast path. That causes lots of register spills and reloads that -// are unnecessary unless the slow path is taken. -// + return base_ns + ((delta_cycles * nsscaled_per_cycle) >> kScale); + } + return GetCurrentTimeNanosSlowPath(); +} + +// Return (a << kScale)/b. +// Zero is returned if b==0. Scaling is performed internally to +// preserve precision without overflow. +static uint64_t SafeDivideAndScale(uint64_t a, uint64_t b) { + // Find maximum safe_shift so that + // 0 <= safe_shift <= kScale and (a << safe_shift) does not overflow. + int safe_shift = kScale; + while (((a << safe_shift) >> safe_shift) != a) { + safe_shift--; + } + uint64_t scaled_b = b >> (kScale - safe_shift); + uint64_t quotient = 0; + if (scaled_b != 0) { + quotient = (a << safe_shift) / scaled_b; + } + return quotient; +} + +static uint64_t UpdateLastSample( + uint64_t now_cycles, uint64_t now_ns, uint64_t delta_cycles, + const struct TimeSample *sample) ABSL_ATTRIBUTE_COLD; + +// The slow path of GetCurrentTimeNanos(). This is taken while gathering +// initial samples, when enough time has elapsed since the last sample, and if +// any other thread is writing to last_sample. +// +// Manually mark this 'noinline' to minimize stack frame size of the fast +// path. Without this, sometimes a compiler may inline this big block of code +// into the fast path. That causes lots of register spills and reloads that +// are unnecessary unless the slow path is taken. +// // TODO(y_absl-team): Remove this attribute when our compiler is smart enough -// to do the right thing. -ABSL_ATTRIBUTE_NOINLINE +// to do the right thing. +ABSL_ATTRIBUTE_NOINLINE static int64_t GetCurrentTimeNanosSlowPath() ABSL_LOCKS_EXCLUDED(time_state.lock) { - // Serialize access to slow-path. Fast-path readers are not blocked yet, and - // code below must not modify last_sample until the seqlock is acquired. + // Serialize access to slow-path. Fast-path readers are not blocked yet, and + // code below must not modify last_sample until the seqlock is acquired. time_state.lock.Lock(); - - // Sample the kernel time base. This is the definition of - // "now" if we take the slow path. - uint64_t now_cycles; + + // Sample the kernel time base. This is the definition of + // "now" if we take the slow path. + uint64_t now_cycles; uint64_t now_ns = GetCurrentTimeNanosFromKernel(time_state.last_now_cycles, &now_cycles); time_state.last_now_cycles = now_cycles; - - uint64_t estimated_base_ns; - - // ---------- - // Read the "last_sample" values again; this time holding the write lock. - struct TimeSample sample; + + uint64_t estimated_base_ns; + + // ---------- + // Read the "last_sample" values again; this time holding the write lock. + struct TimeSample sample; ReadTimeSampleAtomic(&time_state.last_sample, &sample); - - // ---------- - // Try running the fast path again; another thread may have updated the - // sample between our run of the fast path and the sample we just read. - uint64_t delta_cycles = now_cycles - sample.base_cycles; - if (delta_cycles < sample.min_cycles_per_sample) { - // Another thread updated the sample. This path does not take the seqlock - // so that blocked readers can make progress without blocking new readers. - estimated_base_ns = sample.base_ns + - ((delta_cycles * sample.nsscaled_per_cycle) >> kScale); + + // ---------- + // Try running the fast path again; another thread may have updated the + // sample between our run of the fast path and the sample we just read. + uint64_t delta_cycles = now_cycles - sample.base_cycles; + if (delta_cycles < sample.min_cycles_per_sample) { + // Another thread updated the sample. This path does not take the seqlock + // so that blocked readers can make progress without blocking new readers. + estimated_base_ns = sample.base_ns + + ((delta_cycles * sample.nsscaled_per_cycle) >> kScale); time_state.stats_fast_slow_paths++; - } else { - estimated_base_ns = - UpdateLastSample(now_cycles, now_ns, delta_cycles, &sample); - } - + } else { + estimated_base_ns = + UpdateLastSample(now_cycles, now_ns, delta_cycles, &sample); + } + time_state.lock.Unlock(); - - return estimated_base_ns; -} - -// Main part of the algorithm. Locks out readers, updates the approximation -// using the new sample from the kernel, and stores the result in last_sample -// for readers. Returns the new estimated time. -static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns, - uint64_t delta_cycles, - const struct TimeSample *sample) + + return estimated_base_ns; +} + +// Main part of the algorithm. Locks out readers, updates the approximation +// using the new sample from the kernel, and stores the result in last_sample +// for readers. Returns the new estimated time. +static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns, + uint64_t delta_cycles, + const struct TimeSample *sample) ABSL_EXCLUSIVE_LOCKS_REQUIRED(time_state.lock) { - uint64_t estimated_base_ns = now_ns; + uint64_t estimated_base_ns = now_ns; uint64_t lock_value = SeqAcquire(&time_state.seq); // acquire seqlock to block readers - - // The 5s in the next if-statement limits the time for which we will trust - // the cycle counter and our last sample to give a reasonable result. - // Errors in the rate of the source clock can be multiplied by the ratio - // between this limit and kMinNSBetweenSamples. - if (sample->raw_ns == 0 || // no recent sample, or clock went backwards - sample->raw_ns + static_cast<uint64_t>(5) * 1000 * 1000 * 1000 < now_ns || - now_ns < sample->raw_ns || now_cycles < sample->base_cycles) { - // record this sample, and forget any previously known slope. + + // The 5s in the next if-statement limits the time for which we will trust + // the cycle counter and our last sample to give a reasonable result. + // Errors in the rate of the source clock can be multiplied by the ratio + // between this limit and kMinNSBetweenSamples. + if (sample->raw_ns == 0 || // no recent sample, or clock went backwards + sample->raw_ns + static_cast<uint64_t>(5) * 1000 * 1000 * 1000 < now_ns || + now_ns < sample->raw_ns || now_cycles < sample->base_cycles) { + // record this sample, and forget any previously known slope. time_state.last_sample.raw_ns.store(now_ns, std::memory_order_relaxed); time_state.last_sample.base_ns.store(estimated_base_ns, std::memory_order_relaxed); @@ -464,122 +464,122 @@ static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns, time_state.last_sample.min_cycles_per_sample.store( 0, std::memory_order_relaxed); time_state.stats_initializations++; - } else if (sample->raw_ns + 500 * 1000 * 1000 < now_ns && - sample->base_cycles + 50 < now_cycles) { - // Enough time has passed to compute the cycle time. - if (sample->nsscaled_per_cycle != 0) { // Have a cycle time estimate. - // Compute time from counter reading, but avoiding overflow - // delta_cycles may be larger than on the fast path. - uint64_t estimated_scaled_ns; - int s = -1; - do { - s++; - estimated_scaled_ns = (delta_cycles >> s) * sample->nsscaled_per_cycle; - } while (estimated_scaled_ns / sample->nsscaled_per_cycle != - (delta_cycles >> s)); - estimated_base_ns = sample->base_ns + - (estimated_scaled_ns >> (kScale - s)); - } - - // Compute the assumed cycle time kMinNSBetweenSamples ns into the future - // assuming the cycle counter rate stays the same as the last interval. - uint64_t ns = now_ns - sample->raw_ns; - uint64_t measured_nsscaled_per_cycle = SafeDivideAndScale(ns, delta_cycles); - - uint64_t assumed_next_sample_delta_cycles = - SafeDivideAndScale(kMinNSBetweenSamples, measured_nsscaled_per_cycle); - - int64_t diff_ns = now_ns - estimated_base_ns; // estimate low by this much - - // We want to set nsscaled_per_cycle so that our estimate of the ns time - // at the assumed cycle time is the assumed ns time. - // That is, we want to set nsscaled_per_cycle so: - // kMinNSBetweenSamples + diff_ns == - // (assumed_next_sample_delta_cycles * nsscaled_per_cycle) >> kScale - // But we wish to damp oscillations, so instead correct only most - // of our current error, by solving: - // kMinNSBetweenSamples + diff_ns - (diff_ns / 16) == - // (assumed_next_sample_delta_cycles * nsscaled_per_cycle) >> kScale - ns = kMinNSBetweenSamples + diff_ns - (diff_ns / 16); - uint64_t new_nsscaled_per_cycle = - SafeDivideAndScale(ns, assumed_next_sample_delta_cycles); - if (new_nsscaled_per_cycle != 0 && - diff_ns < 100 * 1000 * 1000 && -diff_ns < 100 * 1000 * 1000) { - // record the cycle time measurement + } else if (sample->raw_ns + 500 * 1000 * 1000 < now_ns && + sample->base_cycles + 50 < now_cycles) { + // Enough time has passed to compute the cycle time. + if (sample->nsscaled_per_cycle != 0) { // Have a cycle time estimate. + // Compute time from counter reading, but avoiding overflow + // delta_cycles may be larger than on the fast path. + uint64_t estimated_scaled_ns; + int s = -1; + do { + s++; + estimated_scaled_ns = (delta_cycles >> s) * sample->nsscaled_per_cycle; + } while (estimated_scaled_ns / sample->nsscaled_per_cycle != + (delta_cycles >> s)); + estimated_base_ns = sample->base_ns + + (estimated_scaled_ns >> (kScale - s)); + } + + // Compute the assumed cycle time kMinNSBetweenSamples ns into the future + // assuming the cycle counter rate stays the same as the last interval. + uint64_t ns = now_ns - sample->raw_ns; + uint64_t measured_nsscaled_per_cycle = SafeDivideAndScale(ns, delta_cycles); + + uint64_t assumed_next_sample_delta_cycles = + SafeDivideAndScale(kMinNSBetweenSamples, measured_nsscaled_per_cycle); + + int64_t diff_ns = now_ns - estimated_base_ns; // estimate low by this much + + // We want to set nsscaled_per_cycle so that our estimate of the ns time + // at the assumed cycle time is the assumed ns time. + // That is, we want to set nsscaled_per_cycle so: + // kMinNSBetweenSamples + diff_ns == + // (assumed_next_sample_delta_cycles * nsscaled_per_cycle) >> kScale + // But we wish to damp oscillations, so instead correct only most + // of our current error, by solving: + // kMinNSBetweenSamples + diff_ns - (diff_ns / 16) == + // (assumed_next_sample_delta_cycles * nsscaled_per_cycle) >> kScale + ns = kMinNSBetweenSamples + diff_ns - (diff_ns / 16); + uint64_t new_nsscaled_per_cycle = + SafeDivideAndScale(ns, assumed_next_sample_delta_cycles); + if (new_nsscaled_per_cycle != 0 && + diff_ns < 100 * 1000 * 1000 && -diff_ns < 100 * 1000 * 1000) { + // record the cycle time measurement time_state.last_sample.nsscaled_per_cycle.store( - new_nsscaled_per_cycle, std::memory_order_relaxed); - uint64_t new_min_cycles_per_sample = - SafeDivideAndScale(kMinNSBetweenSamples, new_nsscaled_per_cycle); + new_nsscaled_per_cycle, std::memory_order_relaxed); + uint64_t new_min_cycles_per_sample = + SafeDivideAndScale(kMinNSBetweenSamples, new_nsscaled_per_cycle); time_state.last_sample.min_cycles_per_sample.store( - new_min_cycles_per_sample, std::memory_order_relaxed); + new_min_cycles_per_sample, std::memory_order_relaxed); time_state.stats_calibrations++; - } else { // something went wrong; forget the slope + } else { // something went wrong; forget the slope time_state.last_sample.nsscaled_per_cycle.store( 0, std::memory_order_relaxed); time_state.last_sample.min_cycles_per_sample.store( 0, std::memory_order_relaxed); - estimated_base_ns = now_ns; + estimated_base_ns = now_ns; time_state.stats_reinitializations++; - } + } time_state.last_sample.raw_ns.store(now_ns, std::memory_order_relaxed); time_state.last_sample.base_ns.store(estimated_base_ns, std::memory_order_relaxed); time_state.last_sample.base_cycles.store(now_cycles, std::memory_order_relaxed); - } else { - // have a sample, but no slope; waiting for enough time for a calibration + } else { + // have a sample, but no slope; waiting for enough time for a calibration time_state.stats_slow_paths++; - } - + } + SeqRelease(&time_state.seq, lock_value); // release the readers - - return estimated_base_ns; -} + + return estimated_base_ns; +} ABSL_NAMESPACE_END } // namespace y_absl -#endif // ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS - +#endif // ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace { - -// Returns the maximum duration that SleepOnce() can sleep for. +namespace { + +// Returns the maximum duration that SleepOnce() can sleep for. constexpr y_absl::Duration MaxSleep() { -#ifdef _WIN32 - // Windows Sleep() takes unsigned long argument in milliseconds. +#ifdef _WIN32 + // Windows Sleep() takes unsigned long argument in milliseconds. return y_absl::Milliseconds( - std::numeric_limits<unsigned long>::max()); // NOLINT(runtime/int) -#else + std::numeric_limits<unsigned long>::max()); // NOLINT(runtime/int) +#else return y_absl::Seconds(std::numeric_limits<time_t>::max()); -#endif -} - -// Sleeps for the given duration. -// REQUIRES: to_sleep <= MaxSleep(). +#endif +} + +// Sleeps for the given duration. +// REQUIRES: to_sleep <= MaxSleep(). void SleepOnce(y_absl::Duration to_sleep) { -#ifdef _WIN32 +#ifdef _WIN32 Sleep(to_sleep / y_absl::Milliseconds(1)); -#else +#else struct timespec sleep_time = y_absl::ToTimespec(to_sleep); - while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) { - // Ignore signals and wait for the full interval to elapse. - } -#endif -} - -} // namespace + while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) { + // Ignore signals and wait for the full interval to elapse. + } +#endif +} + +} // namespace ABSL_NAMESPACE_END } // namespace y_absl - -extern "C" { - + +extern "C" { + ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)( y_absl::Duration duration) { while (duration > y_absl::ZeroDuration()) { y_absl::Duration to_sleep = std::min(duration, y_absl::MaxSleep()); y_absl::SleepOnce(to_sleep); - duration -= to_sleep; - } -} - -} // extern "C" + duration -= to_sleep; + } +} + +} // extern "C" diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/clock.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/clock.h index d2d9b721e0..178b96d828 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/clock.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/clock.h @@ -1,74 +1,74 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// File: clock.h -// ----------------------------------------------------------------------------- -// -// This header file contains utility functions for working with the system-wide -// realtime clock. For descriptions of the main time abstractions used within -// this header file, consult the time.h header file. -#ifndef ABSL_TIME_CLOCK_H_ -#define ABSL_TIME_CLOCK_H_ - +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: clock.h +// ----------------------------------------------------------------------------- +// +// This header file contains utility functions for working with the system-wide +// realtime clock. For descriptions of the main time abstractions used within +// this header file, consult the time.h header file. +#ifndef ABSL_TIME_CLOCK_H_ +#define ABSL_TIME_CLOCK_H_ + #include "y_absl/base/macros.h" #include "y_absl/time/time.h" - + namespace y_absl { ABSL_NAMESPACE_BEGIN - -// Now() -// + +// Now() +// // Returns the current time, expressed as an `y_absl::Time` absolute time value. y_absl::Time Now(); - -// GetCurrentTimeNanos() -// -// Returns the current time, expressed as a count of nanoseconds since the Unix + +// GetCurrentTimeNanos() +// +// Returns the current time, expressed as a count of nanoseconds since the Unix // Epoch (https://en.wikipedia.org/wiki/Unix_time). Prefer `y_absl::Now()` instead -// for all but the most performance-sensitive cases (i.e. when you are calling -// this function hundreds of thousands of times per second). -int64_t GetCurrentTimeNanos(); - -// SleepFor() -// +// for all but the most performance-sensitive cases (i.e. when you are calling +// this function hundreds of thousands of times per second). +int64_t GetCurrentTimeNanos(); + +// SleepFor() +// // Sleeps for the specified duration, expressed as an `y_absl::Duration`. -// -// Notes: -// * Signal interruptions will not reduce the sleep duration. -// * Returns immediately when passed a nonpositive duration. +// +// Notes: +// * Signal interruptions will not reduce the sleep duration. +// * Returns immediately when passed a nonpositive duration. void SleepFor(y_absl::Duration duration); - + ABSL_NAMESPACE_END } // namespace y_absl - -// ----------------------------------------------------------------------------- -// Implementation Details -// ----------------------------------------------------------------------------- - -// In some build configurations we pass --detect-odr-violations to the -// gold linker. This causes it to flag weak symbol overrides as ODR -// violations. Because ODR only applies to C++ and not C, -// --detect-odr-violations ignores symbols not mangled with C++ names. -// By changing our extension points to be extern "C", we dodge this -// check. -extern "C" { + +// ----------------------------------------------------------------------------- +// Implementation Details +// ----------------------------------------------------------------------------- + +// In some build configurations we pass --detect-odr-violations to the +// gold linker. This causes it to flag weak symbol overrides as ODR +// violations. Because ODR only applies to C++ and not C, +// --detect-odr-violations ignores symbols not mangled with C++ names. +// By changing our extension points to be extern "C", we dodge this +// check. +extern "C" { void ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(y_absl::Duration duration); -} // extern "C" - +} // extern "C" + inline void y_absl::SleepFor(y_absl::Duration duration) { ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(duration); -} - -#endif // ABSL_TIME_CLOCK_H_ +} + +#endif // ABSL_TIME_CLOCK_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/duration.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/duration.cc index 308098673f..d4914556e6 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/duration.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/duration.cc @@ -1,720 +1,720 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // The implementation of the y_absl::Duration class, which is declared in // //y_absl/time.h. This class behaves like a numeric type; it has no public -// methods and is used only through the operators defined here. -// -// Implementation notes: -// +// methods and is used only through the operators defined here. +// +// Implementation notes: +// // An y_absl::Duration is represented as -// -// rep_hi_ : (int64_t) Whole seconds -// rep_lo_ : (uint32_t) Fractions of a second -// -// The seconds value (rep_hi_) may be positive or negative as appropriate. -// The fractional seconds (rep_lo_) is always a positive offset from rep_hi_. -// The API for Duration guarantees at least nanosecond resolution, which -// means rep_lo_ could have a max value of 1B - 1 if it stored nanoseconds. -// However, to utilize more of the available 32 bits of space in rep_lo_, -// we instead store quarters of a nanosecond in rep_lo_ resulting in a max -// value of 4B - 1. This allows us to correctly handle calculations like -// 0.5 nanos + 0.5 nanos = 1 nano. The following example shows the actual -// Duration rep using quarters of a nanosecond. -// -// 2.5 sec = {rep_hi_=2, rep_lo_=2000000000} // lo = 4 * 500000000 -// -2.5 sec = {rep_hi_=-3, rep_lo_=2000000000} -// -// Infinite durations are represented as Durations with the rep_lo_ field set -// to all 1s. -// -// +InfiniteDuration: -// rep_hi_ : kint64max -// rep_lo_ : ~0U -// -// -InfiniteDuration: -// rep_hi_ : kint64min -// rep_lo_ : ~0U -// -// Arithmetic overflows/underflows to +/- infinity and saturates. - -#if defined(_MSC_VER) -#include <winsock2.h> // for timeval -#endif - -#include <algorithm> -#include <cassert> -#include <cctype> -#include <cerrno> -#include <cmath> -#include <cstdint> -#include <cstdlib> -#include <cstring> -#include <ctime> -#include <functional> -#include <limits> +// +// rep_hi_ : (int64_t) Whole seconds +// rep_lo_ : (uint32_t) Fractions of a second +// +// The seconds value (rep_hi_) may be positive or negative as appropriate. +// The fractional seconds (rep_lo_) is always a positive offset from rep_hi_. +// The API for Duration guarantees at least nanosecond resolution, which +// means rep_lo_ could have a max value of 1B - 1 if it stored nanoseconds. +// However, to utilize more of the available 32 bits of space in rep_lo_, +// we instead store quarters of a nanosecond in rep_lo_ resulting in a max +// value of 4B - 1. This allows us to correctly handle calculations like +// 0.5 nanos + 0.5 nanos = 1 nano. The following example shows the actual +// Duration rep using quarters of a nanosecond. +// +// 2.5 sec = {rep_hi_=2, rep_lo_=2000000000} // lo = 4 * 500000000 +// -2.5 sec = {rep_hi_=-3, rep_lo_=2000000000} +// +// Infinite durations are represented as Durations with the rep_lo_ field set +// to all 1s. +// +// +InfiniteDuration: +// rep_hi_ : kint64max +// rep_lo_ : ~0U +// +// -InfiniteDuration: +// rep_hi_ : kint64min +// rep_lo_ : ~0U +// +// Arithmetic overflows/underflows to +/- infinity and saturates. + +#if defined(_MSC_VER) +#include <winsock2.h> // for timeval +#endif + +#include <algorithm> +#include <cassert> +#include <cctype> +#include <cerrno> +#include <cmath> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <ctime> +#include <functional> +#include <limits> #include <util/generic/string.h> - + #include "y_absl/base/casts.h" #include "y_absl/base/macros.h" #include "y_absl/numeric/int128.h" #include "y_absl/strings/string_view.h" #include "y_absl/strings/strip.h" #include "y_absl/time/time.h" - + namespace y_absl { ABSL_NAMESPACE_BEGIN - -namespace { - -using time_internal::kTicksPerNanosecond; -using time_internal::kTicksPerSecond; - -constexpr int64_t kint64max = std::numeric_limits<int64_t>::max(); -constexpr int64_t kint64min = std::numeric_limits<int64_t>::min(); - -// Can't use std::isinfinite() because it doesn't exist on windows. -inline bool IsFinite(double d) { - if (std::isnan(d)) return false; - return d != std::numeric_limits<double>::infinity() && - d != -std::numeric_limits<double>::infinity(); -} - -inline bool IsValidDivisor(double d) { - if (std::isnan(d)) return false; - return d != 0.0; -} - -// Can't use std::round() because it is only available in C++11. -// Note that we ignore the possibility of floating-point over/underflow. -template <typename Double> -inline double Round(Double d) { - return d < 0 ? std::ceil(d - 0.5) : std::floor(d + 0.5); -} - -// *sec may be positive or negative. *ticks must be in the range -// -kTicksPerSecond < *ticks < kTicksPerSecond. If *ticks is negative it -// will be normalized to a positive value by adjusting *sec accordingly. -inline void NormalizeTicks(int64_t* sec, int64_t* ticks) { - if (*ticks < 0) { - --*sec; - *ticks += kTicksPerSecond; - } -} - -// Makes a uint128 from the absolute value of the given scalar. -inline uint128 MakeU128(int64_t a) { - uint128 u128 = 0; - if (a < 0) { - ++u128; - ++a; // Makes it safe to negate 'a' - a = -a; - } - u128 += static_cast<uint64_t>(a); - return u128; -} - -// Makes a uint128 count of ticks out of the absolute value of the Duration. -inline uint128 MakeU128Ticks(Duration d) { - int64_t rep_hi = time_internal::GetRepHi(d); - uint32_t rep_lo = time_internal::GetRepLo(d); - if (rep_hi < 0) { - ++rep_hi; - rep_hi = -rep_hi; - rep_lo = kTicksPerSecond - rep_lo; - } - uint128 u128 = static_cast<uint64_t>(rep_hi); - u128 *= static_cast<uint64_t>(kTicksPerSecond); - u128 += rep_lo; - return u128; -} - -// Breaks a uint128 of ticks into a Duration. -inline Duration MakeDurationFromU128(uint128 u128, bool is_neg) { - int64_t rep_hi; - uint32_t rep_lo; - const uint64_t h64 = Uint128High64(u128); - const uint64_t l64 = Uint128Low64(u128); - if (h64 == 0) { // fastpath - const uint64_t hi = l64 / kTicksPerSecond; - rep_hi = static_cast<int64_t>(hi); - rep_lo = static_cast<uint32_t>(l64 - hi * kTicksPerSecond); - } else { - // kMaxRepHi64 is the high 64 bits of (2^63 * kTicksPerSecond). - // Any positive tick count whose high 64 bits are >= kMaxRepHi64 - // is not representable as a Duration. A negative tick count can - // have its high 64 bits == kMaxRepHi64 but only when the low 64 - // bits are all zero, otherwise it is not representable either. - const uint64_t kMaxRepHi64 = 0x77359400UL; - if (h64 >= kMaxRepHi64) { - if (is_neg && h64 == kMaxRepHi64 && l64 == 0) { - // Avoid trying to represent -kint64min below. - return time_internal::MakeDuration(kint64min); - } - return is_neg ? -InfiniteDuration() : InfiniteDuration(); - } - const uint128 kTicksPerSecond128 = static_cast<uint64_t>(kTicksPerSecond); - const uint128 hi = u128 / kTicksPerSecond128; - rep_hi = static_cast<int64_t>(Uint128Low64(hi)); - rep_lo = - static_cast<uint32_t>(Uint128Low64(u128 - hi * kTicksPerSecond128)); - } - if (is_neg) { - rep_hi = -rep_hi; - if (rep_lo != 0) { - --rep_hi; - rep_lo = kTicksPerSecond - rep_lo; - } - } - return time_internal::MakeDuration(rep_hi, rep_lo); -} - -// Convert between int64_t and uint64_t, preserving representation. This -// allows us to do arithmetic in the unsigned domain, where overflow has -// well-defined behavior. See operator+=() and operator-=(). -// -// C99 7.20.1.1.1, as referenced by C++11 18.4.1.2, says, "The typedef -// name intN_t designates a signed integer type with width N, no padding -// bits, and a two's complement representation." So, we can convert to -// and from the corresponding uint64_t value using a bit cast. -inline uint64_t EncodeTwosComp(int64_t v) { + +namespace { + +using time_internal::kTicksPerNanosecond; +using time_internal::kTicksPerSecond; + +constexpr int64_t kint64max = std::numeric_limits<int64_t>::max(); +constexpr int64_t kint64min = std::numeric_limits<int64_t>::min(); + +// Can't use std::isinfinite() because it doesn't exist on windows. +inline bool IsFinite(double d) { + if (std::isnan(d)) return false; + return d != std::numeric_limits<double>::infinity() && + d != -std::numeric_limits<double>::infinity(); +} + +inline bool IsValidDivisor(double d) { + if (std::isnan(d)) return false; + return d != 0.0; +} + +// Can't use std::round() because it is only available in C++11. +// Note that we ignore the possibility of floating-point over/underflow. +template <typename Double> +inline double Round(Double d) { + return d < 0 ? std::ceil(d - 0.5) : std::floor(d + 0.5); +} + +// *sec may be positive or negative. *ticks must be in the range +// -kTicksPerSecond < *ticks < kTicksPerSecond. If *ticks is negative it +// will be normalized to a positive value by adjusting *sec accordingly. +inline void NormalizeTicks(int64_t* sec, int64_t* ticks) { + if (*ticks < 0) { + --*sec; + *ticks += kTicksPerSecond; + } +} + +// Makes a uint128 from the absolute value of the given scalar. +inline uint128 MakeU128(int64_t a) { + uint128 u128 = 0; + if (a < 0) { + ++u128; + ++a; // Makes it safe to negate 'a' + a = -a; + } + u128 += static_cast<uint64_t>(a); + return u128; +} + +// Makes a uint128 count of ticks out of the absolute value of the Duration. +inline uint128 MakeU128Ticks(Duration d) { + int64_t rep_hi = time_internal::GetRepHi(d); + uint32_t rep_lo = time_internal::GetRepLo(d); + if (rep_hi < 0) { + ++rep_hi; + rep_hi = -rep_hi; + rep_lo = kTicksPerSecond - rep_lo; + } + uint128 u128 = static_cast<uint64_t>(rep_hi); + u128 *= static_cast<uint64_t>(kTicksPerSecond); + u128 += rep_lo; + return u128; +} + +// Breaks a uint128 of ticks into a Duration. +inline Duration MakeDurationFromU128(uint128 u128, bool is_neg) { + int64_t rep_hi; + uint32_t rep_lo; + const uint64_t h64 = Uint128High64(u128); + const uint64_t l64 = Uint128Low64(u128); + if (h64 == 0) { // fastpath + const uint64_t hi = l64 / kTicksPerSecond; + rep_hi = static_cast<int64_t>(hi); + rep_lo = static_cast<uint32_t>(l64 - hi * kTicksPerSecond); + } else { + // kMaxRepHi64 is the high 64 bits of (2^63 * kTicksPerSecond). + // Any positive tick count whose high 64 bits are >= kMaxRepHi64 + // is not representable as a Duration. A negative tick count can + // have its high 64 bits == kMaxRepHi64 but only when the low 64 + // bits are all zero, otherwise it is not representable either. + const uint64_t kMaxRepHi64 = 0x77359400UL; + if (h64 >= kMaxRepHi64) { + if (is_neg && h64 == kMaxRepHi64 && l64 == 0) { + // Avoid trying to represent -kint64min below. + return time_internal::MakeDuration(kint64min); + } + return is_neg ? -InfiniteDuration() : InfiniteDuration(); + } + const uint128 kTicksPerSecond128 = static_cast<uint64_t>(kTicksPerSecond); + const uint128 hi = u128 / kTicksPerSecond128; + rep_hi = static_cast<int64_t>(Uint128Low64(hi)); + rep_lo = + static_cast<uint32_t>(Uint128Low64(u128 - hi * kTicksPerSecond128)); + } + if (is_neg) { + rep_hi = -rep_hi; + if (rep_lo != 0) { + --rep_hi; + rep_lo = kTicksPerSecond - rep_lo; + } + } + return time_internal::MakeDuration(rep_hi, rep_lo); +} + +// Convert between int64_t and uint64_t, preserving representation. This +// allows us to do arithmetic in the unsigned domain, where overflow has +// well-defined behavior. See operator+=() and operator-=(). +// +// C99 7.20.1.1.1, as referenced by C++11 18.4.1.2, says, "The typedef +// name intN_t designates a signed integer type with width N, no padding +// bits, and a two's complement representation." So, we can convert to +// and from the corresponding uint64_t value using a bit cast. +inline uint64_t EncodeTwosComp(int64_t v) { return y_absl::bit_cast<uint64_t>(v); -} +} inline int64_t DecodeTwosComp(uint64_t v) { return y_absl::bit_cast<int64_t>(v); } - -// Note: The overflow detection in this function is done using greater/less *or -// equal* because kint64max/min is too large to be represented exactly in a -// double (which only has 53 bits of precision). In order to avoid assigning to -// rep->hi a double value that is too large for an int64_t (and therefore is -// undefined), we must consider computations that equal kint64max/min as a -// double as overflow cases. -inline bool SafeAddRepHi(double a_hi, double b_hi, Duration* d) { - double c = a_hi + b_hi; - if (c >= static_cast<double>(kint64max)) { - *d = InfiniteDuration(); - return false; - } - if (c <= static_cast<double>(kint64min)) { - *d = -InfiniteDuration(); - return false; - } - *d = time_internal::MakeDuration(c, time_internal::GetRepLo(*d)); - return true; -} - -// A functor that's similar to std::multiplies<T>, except this returns the max -// T value instead of overflowing. This is only defined for uint128. -template <typename Ignored> -struct SafeMultiply { - uint128 operator()(uint128 a, uint128 b) const { - // b hi is always zero because it originated as an int64_t. - assert(Uint128High64(b) == 0); - // Fastpath to avoid the expensive overflow check with division. - if (Uint128High64(a) == 0) { - return (((Uint128Low64(a) | Uint128Low64(b)) >> 32) == 0) - ? static_cast<uint128>(Uint128Low64(a) * Uint128Low64(b)) - : a * b; - } - return b == 0 ? b : (a > kuint128max / b) ? kuint128max : a * b; - } -}; - -// Scales (i.e., multiplies or divides, depending on the Operation template) -// the Duration d by the int64_t r. -template <template <typename> class Operation> -inline Duration ScaleFixed(Duration d, int64_t r) { - const uint128 a = MakeU128Ticks(d); - const uint128 b = MakeU128(r); - const uint128 q = Operation<uint128>()(a, b); - const bool is_neg = (time_internal::GetRepHi(d) < 0) != (r < 0); - return MakeDurationFromU128(q, is_neg); -} - -// Scales (i.e., multiplies or divides, depending on the Operation template) -// the Duration d by the double r. -template <template <typename> class Operation> -inline Duration ScaleDouble(Duration d, double r) { - Operation<double> op; - double hi_doub = op(time_internal::GetRepHi(d), r); - double lo_doub = op(time_internal::GetRepLo(d), r); - - double hi_int = 0; - double hi_frac = std::modf(hi_doub, &hi_int); - - // Moves hi's fractional bits to lo. - lo_doub /= kTicksPerSecond; - lo_doub += hi_frac; - - double lo_int = 0; - double lo_frac = std::modf(lo_doub, &lo_int); - - // Rolls lo into hi if necessary. - int64_t lo64 = Round(lo_frac * kTicksPerSecond); - - Duration ans; - if (!SafeAddRepHi(hi_int, lo_int, &ans)) return ans; - int64_t hi64 = time_internal::GetRepHi(ans); - if (!SafeAddRepHi(hi64, lo64 / kTicksPerSecond, &ans)) return ans; - hi64 = time_internal::GetRepHi(ans); - lo64 %= kTicksPerSecond; - NormalizeTicks(&hi64, &lo64); - return time_internal::MakeDuration(hi64, lo64); -} - -// Tries to divide num by den as fast as possible by looking for common, easy -// cases. If the division was done, the quotient is in *q and the remainder is -// in *rem and true will be returned. -inline bool IDivFastPath(const Duration num, const Duration den, int64_t* q, - Duration* rem) { - // Bail if num or den is an infinity. - if (time_internal::IsInfiniteDuration(num) || - time_internal::IsInfiniteDuration(den)) - return false; - - int64_t num_hi = time_internal::GetRepHi(num); - uint32_t num_lo = time_internal::GetRepLo(num); - int64_t den_hi = time_internal::GetRepHi(den); - uint32_t den_lo = time_internal::GetRepLo(den); - - if (den_hi == 0 && den_lo == kTicksPerNanosecond) { - // Dividing by 1ns - if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000000) { - *q = num_hi * 1000000000 + num_lo / kTicksPerNanosecond; - *rem = time_internal::MakeDuration(0, num_lo % den_lo); - return true; - } - } else if (den_hi == 0 && den_lo == 100 * kTicksPerNanosecond) { - // Dividing by 100ns (common when converting to Universal time) - if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 10000000) { - *q = num_hi * 10000000 + num_lo / (100 * kTicksPerNanosecond); - *rem = time_internal::MakeDuration(0, num_lo % den_lo); - return true; - } - } else if (den_hi == 0 && den_lo == 1000 * kTicksPerNanosecond) { - // Dividing by 1us - if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000) { - *q = num_hi * 1000000 + num_lo / (1000 * kTicksPerNanosecond); - *rem = time_internal::MakeDuration(0, num_lo % den_lo); - return true; - } - } else if (den_hi == 0 && den_lo == 1000000 * kTicksPerNanosecond) { - // Dividing by 1ms - if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000) { - *q = num_hi * 1000 + num_lo / (1000000 * kTicksPerNanosecond); - *rem = time_internal::MakeDuration(0, num_lo % den_lo); - return true; - } - } else if (den_hi > 0 && den_lo == 0) { - // Dividing by positive multiple of 1s - if (num_hi >= 0) { - if (den_hi == 1) { - *q = num_hi; - *rem = time_internal::MakeDuration(0, num_lo); - return true; - } - *q = num_hi / den_hi; - *rem = time_internal::MakeDuration(num_hi % den_hi, num_lo); - return true; - } - if (num_lo != 0) { - num_hi += 1; - } - int64_t quotient = num_hi / den_hi; - int64_t rem_sec = num_hi % den_hi; - if (rem_sec > 0) { - rem_sec -= den_hi; - quotient += 1; - } - if (num_lo != 0) { - rem_sec -= 1; - } - *q = quotient; - *rem = time_internal::MakeDuration(rem_sec, num_lo); - return true; - } - - return false; -} - -} // namespace - -namespace time_internal { - -// The 'satq' argument indicates whether the quotient should saturate at the -// bounds of int64_t. If it does saturate, the difference will spill over to -// the remainder. If it does not saturate, the remainder remain accurate, -// but the returned quotient will over/underflow int64_t and should not be used. -int64_t IDivDuration(bool satq, const Duration num, const Duration den, + +// Note: The overflow detection in this function is done using greater/less *or +// equal* because kint64max/min is too large to be represented exactly in a +// double (which only has 53 bits of precision). In order to avoid assigning to +// rep->hi a double value that is too large for an int64_t (and therefore is +// undefined), we must consider computations that equal kint64max/min as a +// double as overflow cases. +inline bool SafeAddRepHi(double a_hi, double b_hi, Duration* d) { + double c = a_hi + b_hi; + if (c >= static_cast<double>(kint64max)) { + *d = InfiniteDuration(); + return false; + } + if (c <= static_cast<double>(kint64min)) { + *d = -InfiniteDuration(); + return false; + } + *d = time_internal::MakeDuration(c, time_internal::GetRepLo(*d)); + return true; +} + +// A functor that's similar to std::multiplies<T>, except this returns the max +// T value instead of overflowing. This is only defined for uint128. +template <typename Ignored> +struct SafeMultiply { + uint128 operator()(uint128 a, uint128 b) const { + // b hi is always zero because it originated as an int64_t. + assert(Uint128High64(b) == 0); + // Fastpath to avoid the expensive overflow check with division. + if (Uint128High64(a) == 0) { + return (((Uint128Low64(a) | Uint128Low64(b)) >> 32) == 0) + ? static_cast<uint128>(Uint128Low64(a) * Uint128Low64(b)) + : a * b; + } + return b == 0 ? b : (a > kuint128max / b) ? kuint128max : a * b; + } +}; + +// Scales (i.e., multiplies or divides, depending on the Operation template) +// the Duration d by the int64_t r. +template <template <typename> class Operation> +inline Duration ScaleFixed(Duration d, int64_t r) { + const uint128 a = MakeU128Ticks(d); + const uint128 b = MakeU128(r); + const uint128 q = Operation<uint128>()(a, b); + const bool is_neg = (time_internal::GetRepHi(d) < 0) != (r < 0); + return MakeDurationFromU128(q, is_neg); +} + +// Scales (i.e., multiplies or divides, depending on the Operation template) +// the Duration d by the double r. +template <template <typename> class Operation> +inline Duration ScaleDouble(Duration d, double r) { + Operation<double> op; + double hi_doub = op(time_internal::GetRepHi(d), r); + double lo_doub = op(time_internal::GetRepLo(d), r); + + double hi_int = 0; + double hi_frac = std::modf(hi_doub, &hi_int); + + // Moves hi's fractional bits to lo. + lo_doub /= kTicksPerSecond; + lo_doub += hi_frac; + + double lo_int = 0; + double lo_frac = std::modf(lo_doub, &lo_int); + + // Rolls lo into hi if necessary. + int64_t lo64 = Round(lo_frac * kTicksPerSecond); + + Duration ans; + if (!SafeAddRepHi(hi_int, lo_int, &ans)) return ans; + int64_t hi64 = time_internal::GetRepHi(ans); + if (!SafeAddRepHi(hi64, lo64 / kTicksPerSecond, &ans)) return ans; + hi64 = time_internal::GetRepHi(ans); + lo64 %= kTicksPerSecond; + NormalizeTicks(&hi64, &lo64); + return time_internal::MakeDuration(hi64, lo64); +} + +// Tries to divide num by den as fast as possible by looking for common, easy +// cases. If the division was done, the quotient is in *q and the remainder is +// in *rem and true will be returned. +inline bool IDivFastPath(const Duration num, const Duration den, int64_t* q, + Duration* rem) { + // Bail if num or den is an infinity. + if (time_internal::IsInfiniteDuration(num) || + time_internal::IsInfiniteDuration(den)) + return false; + + int64_t num_hi = time_internal::GetRepHi(num); + uint32_t num_lo = time_internal::GetRepLo(num); + int64_t den_hi = time_internal::GetRepHi(den); + uint32_t den_lo = time_internal::GetRepLo(den); + + if (den_hi == 0 && den_lo == kTicksPerNanosecond) { + // Dividing by 1ns + if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000000) { + *q = num_hi * 1000000000 + num_lo / kTicksPerNanosecond; + *rem = time_internal::MakeDuration(0, num_lo % den_lo); + return true; + } + } else if (den_hi == 0 && den_lo == 100 * kTicksPerNanosecond) { + // Dividing by 100ns (common when converting to Universal time) + if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 10000000) { + *q = num_hi * 10000000 + num_lo / (100 * kTicksPerNanosecond); + *rem = time_internal::MakeDuration(0, num_lo % den_lo); + return true; + } + } else if (den_hi == 0 && den_lo == 1000 * kTicksPerNanosecond) { + // Dividing by 1us + if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000000) { + *q = num_hi * 1000000 + num_lo / (1000 * kTicksPerNanosecond); + *rem = time_internal::MakeDuration(0, num_lo % den_lo); + return true; + } + } else if (den_hi == 0 && den_lo == 1000000 * kTicksPerNanosecond) { + // Dividing by 1ms + if (num_hi >= 0 && num_hi < (kint64max - kTicksPerSecond) / 1000) { + *q = num_hi * 1000 + num_lo / (1000000 * kTicksPerNanosecond); + *rem = time_internal::MakeDuration(0, num_lo % den_lo); + return true; + } + } else if (den_hi > 0 && den_lo == 0) { + // Dividing by positive multiple of 1s + if (num_hi >= 0) { + if (den_hi == 1) { + *q = num_hi; + *rem = time_internal::MakeDuration(0, num_lo); + return true; + } + *q = num_hi / den_hi; + *rem = time_internal::MakeDuration(num_hi % den_hi, num_lo); + return true; + } + if (num_lo != 0) { + num_hi += 1; + } + int64_t quotient = num_hi / den_hi; + int64_t rem_sec = num_hi % den_hi; + if (rem_sec > 0) { + rem_sec -= den_hi; + quotient += 1; + } + if (num_lo != 0) { + rem_sec -= 1; + } + *q = quotient; + *rem = time_internal::MakeDuration(rem_sec, num_lo); + return true; + } + + return false; +} + +} // namespace + +namespace time_internal { + +// The 'satq' argument indicates whether the quotient should saturate at the +// bounds of int64_t. If it does saturate, the difference will spill over to +// the remainder. If it does not saturate, the remainder remain accurate, +// but the returned quotient will over/underflow int64_t and should not be used. +int64_t IDivDuration(bool satq, const Duration num, const Duration den, Duration* rem) { - int64_t q = 0; - if (IDivFastPath(num, den, &q, rem)) { - return q; - } - - const bool num_neg = num < ZeroDuration(); - const bool den_neg = den < ZeroDuration(); - const bool quotient_neg = num_neg != den_neg; - - if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) { - *rem = num_neg ? -InfiniteDuration() : InfiniteDuration(); - return quotient_neg ? kint64min : kint64max; - } - if (time_internal::IsInfiniteDuration(den)) { - *rem = num; - return 0; - } - - const uint128 a = MakeU128Ticks(num); - const uint128 b = MakeU128Ticks(den); - uint128 quotient128 = a / b; - - if (satq) { - // Limits the quotient to the range of int64_t. - if (quotient128 > uint128(static_cast<uint64_t>(kint64max))) { - quotient128 = quotient_neg ? uint128(static_cast<uint64_t>(kint64min)) - : uint128(static_cast<uint64_t>(kint64max)); - } - } - - const uint128 remainder128 = a - quotient128 * b; - *rem = MakeDurationFromU128(remainder128, num_neg); - - if (!quotient_neg || quotient128 == 0) { - return Uint128Low64(quotient128) & kint64max; - } - // The quotient needs to be negated, but we need to carefully handle - // quotient128s with the top bit on. - return -static_cast<int64_t>(Uint128Low64(quotient128 - 1) & kint64max) - 1; -} - -} // namespace time_internal - -// -// Additive operators. -// - -Duration& Duration::operator+=(Duration rhs) { - if (time_internal::IsInfiniteDuration(*this)) return *this; - if (time_internal::IsInfiniteDuration(rhs)) return *this = rhs; - const int64_t orig_rep_hi = rep_hi_; - rep_hi_ = - DecodeTwosComp(EncodeTwosComp(rep_hi_) + EncodeTwosComp(rhs.rep_hi_)); - if (rep_lo_ >= kTicksPerSecond - rhs.rep_lo_) { - rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_) + 1); - rep_lo_ -= kTicksPerSecond; - } - rep_lo_ += rhs.rep_lo_; - if (rhs.rep_hi_ < 0 ? rep_hi_ > orig_rep_hi : rep_hi_ < orig_rep_hi) { - return *this = rhs.rep_hi_ < 0 ? -InfiniteDuration() : InfiniteDuration(); - } - return *this; -} - -Duration& Duration::operator-=(Duration rhs) { - if (time_internal::IsInfiniteDuration(*this)) return *this; - if (time_internal::IsInfiniteDuration(rhs)) { - return *this = rhs.rep_hi_ >= 0 ? -InfiniteDuration() : InfiniteDuration(); - } - const int64_t orig_rep_hi = rep_hi_; - rep_hi_ = - DecodeTwosComp(EncodeTwosComp(rep_hi_) - EncodeTwosComp(rhs.rep_hi_)); - if (rep_lo_ < rhs.rep_lo_) { - rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_) - 1); - rep_lo_ += kTicksPerSecond; - } - rep_lo_ -= rhs.rep_lo_; - if (rhs.rep_hi_ < 0 ? rep_hi_ < orig_rep_hi : rep_hi_ > orig_rep_hi) { - return *this = rhs.rep_hi_ >= 0 ? -InfiniteDuration() : InfiniteDuration(); - } - return *this; -} - -// -// Multiplicative operators. -// - -Duration& Duration::operator*=(int64_t r) { - if (time_internal::IsInfiniteDuration(*this)) { - const bool is_neg = (r < 0) != (rep_hi_ < 0); - return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); - } - return *this = ScaleFixed<SafeMultiply>(*this, r); -} - -Duration& Duration::operator*=(double r) { - if (time_internal::IsInfiniteDuration(*this) || !IsFinite(r)) { - const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0); - return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); - } - return *this = ScaleDouble<std::multiplies>(*this, r); -} - -Duration& Duration::operator/=(int64_t r) { - if (time_internal::IsInfiniteDuration(*this) || r == 0) { - const bool is_neg = (r < 0) != (rep_hi_ < 0); - return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); - } - return *this = ScaleFixed<std::divides>(*this, r); -} - -Duration& Duration::operator/=(double r) { - if (time_internal::IsInfiniteDuration(*this) || !IsValidDivisor(r)) { - const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0); - return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); - } - return *this = ScaleDouble<std::divides>(*this, r); -} - -Duration& Duration::operator%=(Duration rhs) { - time_internal::IDivDuration(false, *this, rhs, this); - return *this; -} - -double FDivDuration(Duration num, Duration den) { - // Arithmetic with infinity is sticky. - if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) { - return (num < ZeroDuration()) == (den < ZeroDuration()) - ? std::numeric_limits<double>::infinity() - : -std::numeric_limits<double>::infinity(); - } - if (time_internal::IsInfiniteDuration(den)) return 0.0; - - double a = - static_cast<double>(time_internal::GetRepHi(num)) * kTicksPerSecond + - time_internal::GetRepLo(num); - double b = - static_cast<double>(time_internal::GetRepHi(den)) * kTicksPerSecond + - time_internal::GetRepLo(den); - return a / b; -} - -// -// Trunc/Floor/Ceil. -// - -Duration Trunc(Duration d, Duration unit) { - return d - (d % unit); -} - -Duration Floor(const Duration d, const Duration unit) { + int64_t q = 0; + if (IDivFastPath(num, den, &q, rem)) { + return q; + } + + const bool num_neg = num < ZeroDuration(); + const bool den_neg = den < ZeroDuration(); + const bool quotient_neg = num_neg != den_neg; + + if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) { + *rem = num_neg ? -InfiniteDuration() : InfiniteDuration(); + return quotient_neg ? kint64min : kint64max; + } + if (time_internal::IsInfiniteDuration(den)) { + *rem = num; + return 0; + } + + const uint128 a = MakeU128Ticks(num); + const uint128 b = MakeU128Ticks(den); + uint128 quotient128 = a / b; + + if (satq) { + // Limits the quotient to the range of int64_t. + if (quotient128 > uint128(static_cast<uint64_t>(kint64max))) { + quotient128 = quotient_neg ? uint128(static_cast<uint64_t>(kint64min)) + : uint128(static_cast<uint64_t>(kint64max)); + } + } + + const uint128 remainder128 = a - quotient128 * b; + *rem = MakeDurationFromU128(remainder128, num_neg); + + if (!quotient_neg || quotient128 == 0) { + return Uint128Low64(quotient128) & kint64max; + } + // The quotient needs to be negated, but we need to carefully handle + // quotient128s with the top bit on. + return -static_cast<int64_t>(Uint128Low64(quotient128 - 1) & kint64max) - 1; +} + +} // namespace time_internal + +// +// Additive operators. +// + +Duration& Duration::operator+=(Duration rhs) { + if (time_internal::IsInfiniteDuration(*this)) return *this; + if (time_internal::IsInfiniteDuration(rhs)) return *this = rhs; + const int64_t orig_rep_hi = rep_hi_; + rep_hi_ = + DecodeTwosComp(EncodeTwosComp(rep_hi_) + EncodeTwosComp(rhs.rep_hi_)); + if (rep_lo_ >= kTicksPerSecond - rhs.rep_lo_) { + rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_) + 1); + rep_lo_ -= kTicksPerSecond; + } + rep_lo_ += rhs.rep_lo_; + if (rhs.rep_hi_ < 0 ? rep_hi_ > orig_rep_hi : rep_hi_ < orig_rep_hi) { + return *this = rhs.rep_hi_ < 0 ? -InfiniteDuration() : InfiniteDuration(); + } + return *this; +} + +Duration& Duration::operator-=(Duration rhs) { + if (time_internal::IsInfiniteDuration(*this)) return *this; + if (time_internal::IsInfiniteDuration(rhs)) { + return *this = rhs.rep_hi_ >= 0 ? -InfiniteDuration() : InfiniteDuration(); + } + const int64_t orig_rep_hi = rep_hi_; + rep_hi_ = + DecodeTwosComp(EncodeTwosComp(rep_hi_) - EncodeTwosComp(rhs.rep_hi_)); + if (rep_lo_ < rhs.rep_lo_) { + rep_hi_ = DecodeTwosComp(EncodeTwosComp(rep_hi_) - 1); + rep_lo_ += kTicksPerSecond; + } + rep_lo_ -= rhs.rep_lo_; + if (rhs.rep_hi_ < 0 ? rep_hi_ < orig_rep_hi : rep_hi_ > orig_rep_hi) { + return *this = rhs.rep_hi_ >= 0 ? -InfiniteDuration() : InfiniteDuration(); + } + return *this; +} + +// +// Multiplicative operators. +// + +Duration& Duration::operator*=(int64_t r) { + if (time_internal::IsInfiniteDuration(*this)) { + const bool is_neg = (r < 0) != (rep_hi_ < 0); + return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); + } + return *this = ScaleFixed<SafeMultiply>(*this, r); +} + +Duration& Duration::operator*=(double r) { + if (time_internal::IsInfiniteDuration(*this) || !IsFinite(r)) { + const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0); + return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); + } + return *this = ScaleDouble<std::multiplies>(*this, r); +} + +Duration& Duration::operator/=(int64_t r) { + if (time_internal::IsInfiniteDuration(*this) || r == 0) { + const bool is_neg = (r < 0) != (rep_hi_ < 0); + return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); + } + return *this = ScaleFixed<std::divides>(*this, r); +} + +Duration& Duration::operator/=(double r) { + if (time_internal::IsInfiniteDuration(*this) || !IsValidDivisor(r)) { + const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0); + return *this = is_neg ? -InfiniteDuration() : InfiniteDuration(); + } + return *this = ScaleDouble<std::divides>(*this, r); +} + +Duration& Duration::operator%=(Duration rhs) { + time_internal::IDivDuration(false, *this, rhs, this); + return *this; +} + +double FDivDuration(Duration num, Duration den) { + // Arithmetic with infinity is sticky. + if (time_internal::IsInfiniteDuration(num) || den == ZeroDuration()) { + return (num < ZeroDuration()) == (den < ZeroDuration()) + ? std::numeric_limits<double>::infinity() + : -std::numeric_limits<double>::infinity(); + } + if (time_internal::IsInfiniteDuration(den)) return 0.0; + + double a = + static_cast<double>(time_internal::GetRepHi(num)) * kTicksPerSecond + + time_internal::GetRepLo(num); + double b = + static_cast<double>(time_internal::GetRepHi(den)) * kTicksPerSecond + + time_internal::GetRepLo(den); + return a / b; +} + +// +// Trunc/Floor/Ceil. +// + +Duration Trunc(Duration d, Duration unit) { + return d - (d % unit); +} + +Duration Floor(const Duration d, const Duration unit) { const y_absl::Duration td = Trunc(d, unit); - return td <= d ? td : td - AbsDuration(unit); -} - -Duration Ceil(const Duration d, const Duration unit) { + return td <= d ? td : td - AbsDuration(unit); +} + +Duration Ceil(const Duration d, const Duration unit) { const y_absl::Duration td = Trunc(d, unit); - return td >= d ? td : td + AbsDuration(unit); -} - -// -// Factory functions. -// - -Duration DurationFromTimespec(timespec ts) { - if (static_cast<uint64_t>(ts.tv_nsec) < 1000 * 1000 * 1000) { - int64_t ticks = ts.tv_nsec * kTicksPerNanosecond; - return time_internal::MakeDuration(ts.tv_sec, ticks); - } - return Seconds(ts.tv_sec) + Nanoseconds(ts.tv_nsec); -} - -Duration DurationFromTimeval(timeval tv) { - if (static_cast<uint64_t>(tv.tv_usec) < 1000 * 1000) { - int64_t ticks = tv.tv_usec * 1000 * kTicksPerNanosecond; - return time_internal::MakeDuration(tv.tv_sec, ticks); - } - return Seconds(tv.tv_sec) + Microseconds(tv.tv_usec); -} - -// -// Conversion to other duration types. -// - -int64_t ToInt64Nanoseconds(Duration d) { - if (time_internal::GetRepHi(d) >= 0 && - time_internal::GetRepHi(d) >> 33 == 0) { - return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) + - (time_internal::GetRepLo(d) / kTicksPerNanosecond); - } - return d / Nanoseconds(1); -} -int64_t ToInt64Microseconds(Duration d) { - if (time_internal::GetRepHi(d) >= 0 && - time_internal::GetRepHi(d) >> 43 == 0) { - return (time_internal::GetRepHi(d) * 1000 * 1000) + - (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000)); - } - return d / Microseconds(1); -} -int64_t ToInt64Milliseconds(Duration d) { - if (time_internal::GetRepHi(d) >= 0 && - time_internal::GetRepHi(d) >> 53 == 0) { - return (time_internal::GetRepHi(d) * 1000) + - (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000 * 1000)); - } - return d / Milliseconds(1); -} -int64_t ToInt64Seconds(Duration d) { - int64_t hi = time_internal::GetRepHi(d); - if (time_internal::IsInfiniteDuration(d)) return hi; - if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; - return hi; -} -int64_t ToInt64Minutes(Duration d) { - int64_t hi = time_internal::GetRepHi(d); - if (time_internal::IsInfiniteDuration(d)) return hi; - if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; - return hi / 60; -} -int64_t ToInt64Hours(Duration d) { - int64_t hi = time_internal::GetRepHi(d); - if (time_internal::IsInfiniteDuration(d)) return hi; - if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; - return hi / (60 * 60); -} - -double ToDoubleNanoseconds(Duration d) { - return FDivDuration(d, Nanoseconds(1)); -} -double ToDoubleMicroseconds(Duration d) { - return FDivDuration(d, Microseconds(1)); -} -double ToDoubleMilliseconds(Duration d) { - return FDivDuration(d, Milliseconds(1)); -} -double ToDoubleSeconds(Duration d) { - return FDivDuration(d, Seconds(1)); -} -double ToDoubleMinutes(Duration d) { - return FDivDuration(d, Minutes(1)); -} -double ToDoubleHours(Duration d) { - return FDivDuration(d, Hours(1)); -} - -timespec ToTimespec(Duration d) { - timespec ts; - if (!time_internal::IsInfiniteDuration(d)) { - int64_t rep_hi = time_internal::GetRepHi(d); - uint32_t rep_lo = time_internal::GetRepLo(d); - if (rep_hi < 0) { - // Tweak the fields so that unsigned division of rep_lo - // maps to truncation (towards zero) for the timespec. - rep_lo += kTicksPerNanosecond - 1; - if (rep_lo >= kTicksPerSecond) { - rep_hi += 1; - rep_lo -= kTicksPerSecond; - } - } - ts.tv_sec = rep_hi; - if (ts.tv_sec == rep_hi) { // no time_t narrowing - ts.tv_nsec = rep_lo / kTicksPerNanosecond; - return ts; - } - } - if (d >= ZeroDuration()) { - ts.tv_sec = std::numeric_limits<time_t>::max(); - ts.tv_nsec = 1000 * 1000 * 1000 - 1; - } else { - ts.tv_sec = std::numeric_limits<time_t>::min(); - ts.tv_nsec = 0; - } - return ts; -} - -timeval ToTimeval(Duration d) { - timeval tv; - timespec ts = ToTimespec(d); - if (ts.tv_sec < 0) { - // Tweak the fields so that positive division of tv_nsec - // maps to truncation (towards zero) for the timeval. - ts.tv_nsec += 1000 - 1; - if (ts.tv_nsec >= 1000 * 1000 * 1000) { - ts.tv_sec += 1; - ts.tv_nsec -= 1000 * 1000 * 1000; - } - } - tv.tv_sec = ts.tv_sec; - if (tv.tv_sec != ts.tv_sec) { // narrowing - if (ts.tv_sec < 0) { - tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min(); - tv.tv_usec = 0; - } else { - tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max(); - tv.tv_usec = 1000 * 1000 - 1; - } - return tv; - } - tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000); // suseconds_t - return tv; -} - -std::chrono::nanoseconds ToChronoNanoseconds(Duration d) { - return time_internal::ToChronoDuration<std::chrono::nanoseconds>(d); -} -std::chrono::microseconds ToChronoMicroseconds(Duration d) { - return time_internal::ToChronoDuration<std::chrono::microseconds>(d); -} -std::chrono::milliseconds ToChronoMilliseconds(Duration d) { - return time_internal::ToChronoDuration<std::chrono::milliseconds>(d); -} -std::chrono::seconds ToChronoSeconds(Duration d) { - return time_internal::ToChronoDuration<std::chrono::seconds>(d); -} -std::chrono::minutes ToChronoMinutes(Duration d) { - return time_internal::ToChronoDuration<std::chrono::minutes>(d); -} -std::chrono::hours ToChronoHours(Duration d) { - return time_internal::ToChronoDuration<std::chrono::hours>(d); -} - -// -// To/From string formatting. -// - -namespace { - -// Formats a positive 64-bit integer in the given field width. Note that -// it is up to the caller of Format64() to ensure that there is sufficient -// space before ep to hold the conversion. -char* Format64(char* ep, int width, int64_t v) { - do { - --width; - *--ep = '0' + (v % 10); // contiguous digits - } while (v /= 10); - while (--width >= 0) *--ep = '0'; // zero pad - return ep; -} - -// Helpers for FormatDuration() that format 'n' and append it to 'out' -// followed by the given 'unit'. If 'n' formats to "0", nothing is -// appended (not even the unit). - -// A type that encapsulates how to display a value of a particular unit. For -// values that are displayed with fractional parts, the precision indicates -// where to round the value. The precision varies with the display unit because -// a Duration can hold only quarters of a nanosecond, so displaying information -// beyond that is just noise. -// -// For example, a microsecond value of 42.00025xxxxx should not display beyond 5 -// fractional digits, because it is in the noise of what a Duration can -// represent. -struct DisplayUnit { + return td >= d ? td : td + AbsDuration(unit); +} + +// +// Factory functions. +// + +Duration DurationFromTimespec(timespec ts) { + if (static_cast<uint64_t>(ts.tv_nsec) < 1000 * 1000 * 1000) { + int64_t ticks = ts.tv_nsec * kTicksPerNanosecond; + return time_internal::MakeDuration(ts.tv_sec, ticks); + } + return Seconds(ts.tv_sec) + Nanoseconds(ts.tv_nsec); +} + +Duration DurationFromTimeval(timeval tv) { + if (static_cast<uint64_t>(tv.tv_usec) < 1000 * 1000) { + int64_t ticks = tv.tv_usec * 1000 * kTicksPerNanosecond; + return time_internal::MakeDuration(tv.tv_sec, ticks); + } + return Seconds(tv.tv_sec) + Microseconds(tv.tv_usec); +} + +// +// Conversion to other duration types. +// + +int64_t ToInt64Nanoseconds(Duration d) { + if (time_internal::GetRepHi(d) >= 0 && + time_internal::GetRepHi(d) >> 33 == 0) { + return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) + + (time_internal::GetRepLo(d) / kTicksPerNanosecond); + } + return d / Nanoseconds(1); +} +int64_t ToInt64Microseconds(Duration d) { + if (time_internal::GetRepHi(d) >= 0 && + time_internal::GetRepHi(d) >> 43 == 0) { + return (time_internal::GetRepHi(d) * 1000 * 1000) + + (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000)); + } + return d / Microseconds(1); +} +int64_t ToInt64Milliseconds(Duration d) { + if (time_internal::GetRepHi(d) >= 0 && + time_internal::GetRepHi(d) >> 53 == 0) { + return (time_internal::GetRepHi(d) * 1000) + + (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000 * 1000)); + } + return d / Milliseconds(1); +} +int64_t ToInt64Seconds(Duration d) { + int64_t hi = time_internal::GetRepHi(d); + if (time_internal::IsInfiniteDuration(d)) return hi; + if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; + return hi; +} +int64_t ToInt64Minutes(Duration d) { + int64_t hi = time_internal::GetRepHi(d); + if (time_internal::IsInfiniteDuration(d)) return hi; + if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; + return hi / 60; +} +int64_t ToInt64Hours(Duration d) { + int64_t hi = time_internal::GetRepHi(d); + if (time_internal::IsInfiniteDuration(d)) return hi; + if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi; + return hi / (60 * 60); +} + +double ToDoubleNanoseconds(Duration d) { + return FDivDuration(d, Nanoseconds(1)); +} +double ToDoubleMicroseconds(Duration d) { + return FDivDuration(d, Microseconds(1)); +} +double ToDoubleMilliseconds(Duration d) { + return FDivDuration(d, Milliseconds(1)); +} +double ToDoubleSeconds(Duration d) { + return FDivDuration(d, Seconds(1)); +} +double ToDoubleMinutes(Duration d) { + return FDivDuration(d, Minutes(1)); +} +double ToDoubleHours(Duration d) { + return FDivDuration(d, Hours(1)); +} + +timespec ToTimespec(Duration d) { + timespec ts; + if (!time_internal::IsInfiniteDuration(d)) { + int64_t rep_hi = time_internal::GetRepHi(d); + uint32_t rep_lo = time_internal::GetRepLo(d); + if (rep_hi < 0) { + // Tweak the fields so that unsigned division of rep_lo + // maps to truncation (towards zero) for the timespec. + rep_lo += kTicksPerNanosecond - 1; + if (rep_lo >= kTicksPerSecond) { + rep_hi += 1; + rep_lo -= kTicksPerSecond; + } + } + ts.tv_sec = rep_hi; + if (ts.tv_sec == rep_hi) { // no time_t narrowing + ts.tv_nsec = rep_lo / kTicksPerNanosecond; + return ts; + } + } + if (d >= ZeroDuration()) { + ts.tv_sec = std::numeric_limits<time_t>::max(); + ts.tv_nsec = 1000 * 1000 * 1000 - 1; + } else { + ts.tv_sec = std::numeric_limits<time_t>::min(); + ts.tv_nsec = 0; + } + return ts; +} + +timeval ToTimeval(Duration d) { + timeval tv; + timespec ts = ToTimespec(d); + if (ts.tv_sec < 0) { + // Tweak the fields so that positive division of tv_nsec + // maps to truncation (towards zero) for the timeval. + ts.tv_nsec += 1000 - 1; + if (ts.tv_nsec >= 1000 * 1000 * 1000) { + ts.tv_sec += 1; + ts.tv_nsec -= 1000 * 1000 * 1000; + } + } + tv.tv_sec = ts.tv_sec; + if (tv.tv_sec != ts.tv_sec) { // narrowing + if (ts.tv_sec < 0) { + tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min(); + tv.tv_usec = 0; + } else { + tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max(); + tv.tv_usec = 1000 * 1000 - 1; + } + return tv; + } + tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000); // suseconds_t + return tv; +} + +std::chrono::nanoseconds ToChronoNanoseconds(Duration d) { + return time_internal::ToChronoDuration<std::chrono::nanoseconds>(d); +} +std::chrono::microseconds ToChronoMicroseconds(Duration d) { + return time_internal::ToChronoDuration<std::chrono::microseconds>(d); +} +std::chrono::milliseconds ToChronoMilliseconds(Duration d) { + return time_internal::ToChronoDuration<std::chrono::milliseconds>(d); +} +std::chrono::seconds ToChronoSeconds(Duration d) { + return time_internal::ToChronoDuration<std::chrono::seconds>(d); +} +std::chrono::minutes ToChronoMinutes(Duration d) { + return time_internal::ToChronoDuration<std::chrono::minutes>(d); +} +std::chrono::hours ToChronoHours(Duration d) { + return time_internal::ToChronoDuration<std::chrono::hours>(d); +} + +// +// To/From string formatting. +// + +namespace { + +// Formats a positive 64-bit integer in the given field width. Note that +// it is up to the caller of Format64() to ensure that there is sufficient +// space before ep to hold the conversion. +char* Format64(char* ep, int width, int64_t v) { + do { + --width; + *--ep = '0' + (v % 10); // contiguous digits + } while (v /= 10); + while (--width >= 0) *--ep = '0'; // zero pad + return ep; +} + +// Helpers for FormatDuration() that format 'n' and append it to 'out' +// followed by the given 'unit'. If 'n' formats to "0", nothing is +// appended (not even the unit). + +// A type that encapsulates how to display a value of a particular unit. For +// values that are displayed with fractional parts, the precision indicates +// where to round the value. The precision varies with the display unit because +// a Duration can hold only quarters of a nanosecond, so displaying information +// beyond that is just noise. +// +// For example, a microsecond value of 42.00025xxxxx should not display beyond 5 +// fractional digits, because it is in the noise of what a Duration can +// represent. +struct DisplayUnit { y_absl::string_view abbr; - int prec; - double pow10; -}; + int prec; + double pow10; +}; ABSL_CONST_INIT const DisplayUnit kDisplayNano = {"ns", 2, 1e2}; ABSL_CONST_INIT const DisplayUnit kDisplayMicro = {"us", 5, 1e5}; ABSL_CONST_INIT const DisplayUnit kDisplayMilli = {"ms", 8, 1e8}; @@ -722,123 +722,123 @@ ABSL_CONST_INIT const DisplayUnit kDisplaySec = {"s", 11, 1e11}; ABSL_CONST_INIT const DisplayUnit kDisplayMin = {"m", -1, 0.0}; // prec ignored ABSL_CONST_INIT const DisplayUnit kDisplayHour = {"h", -1, 0.0}; // prec ignored - + void AppendNumberUnit(TString* out, int64_t n, DisplayUnit unit) { - char buf[sizeof("2562047788015216")]; // hours in max duration - char* const ep = buf + sizeof(buf); - char* bp = Format64(ep, 0, n); - if (*bp != '0' || bp + 1 != ep) { - out->append(bp, ep - bp); + char buf[sizeof("2562047788015216")]; // hours in max duration + char* const ep = buf + sizeof(buf); + char* bp = Format64(ep, 0, n); + if (*bp != '0' || bp + 1 != ep) { + out->append(bp, ep - bp); out->append(unit.abbr.data(), unit.abbr.size()); - } -} - -// Note: unit.prec is limited to double's digits10 value (typically 15) so it -// always fits in buf[]. + } +} + +// Note: unit.prec is limited to double's digits10 value (typically 15) so it +// always fits in buf[]. void AppendNumberUnit(TString* out, double n, DisplayUnit unit) { constexpr int kBufferSize = std::numeric_limits<double>::digits10; const int prec = std::min(kBufferSize, unit.prec); char buf[kBufferSize]; // also large enough to hold integer part - char* ep = buf + sizeof(buf); - double d = 0; - int64_t frac_part = Round(std::modf(n, &d) * unit.pow10); - int64_t int_part = d; - if (int_part != 0 || frac_part != 0) { - char* bp = Format64(ep, 0, int_part); // always < 1000 - out->append(bp, ep - bp); - if (frac_part != 0) { - out->push_back('.'); - bp = Format64(ep, prec, frac_part); - while (ep[-1] == '0') --ep; - out->append(bp, ep - bp); - } + char* ep = buf + sizeof(buf); + double d = 0; + int64_t frac_part = Round(std::modf(n, &d) * unit.pow10); + int64_t int_part = d; + if (int_part != 0 || frac_part != 0) { + char* bp = Format64(ep, 0, int_part); // always < 1000 + out->append(bp, ep - bp); + if (frac_part != 0) { + out->push_back('.'); + bp = Format64(ep, prec, frac_part); + while (ep[-1] == '0') --ep; + out->append(bp, ep - bp); + } out->append(unit.abbr.data(), unit.abbr.size()); - } -} - -} // namespace - -// From Go's doc at https://golang.org/pkg/time/#Duration.String -// [FormatDuration] returns a string representing the duration in the -// form "72h3m0.5s". Leading zero units are omitted. As a special -// case, durations less than one second format use a smaller unit -// (milli-, micro-, or nanoseconds) to ensure that the leading digit + } +} + +} // namespace + +// From Go's doc at https://golang.org/pkg/time/#Duration.String +// [FormatDuration] returns a string representing the duration in the +// form "72h3m0.5s". Leading zero units are omitted. As a special +// case, durations less than one second format use a smaller unit +// (milli-, micro-, or nanoseconds) to ensure that the leading digit // is non-zero. // Unlike Go, we format the zero duration as 0, with no unit. TString FormatDuration(Duration d) { - const Duration min_duration = Seconds(kint64min); - if (d == min_duration) { - // Avoid needing to negate kint64min by directly returning what the - // following code should produce in that case. - return "-2562047788015215h30m8s"; - } + const Duration min_duration = Seconds(kint64min); + if (d == min_duration) { + // Avoid needing to negate kint64min by directly returning what the + // following code should produce in that case. + return "-2562047788015215h30m8s"; + } TString s; - if (d < ZeroDuration()) { - s.append("-"); - d = -d; - } - if (d == InfiniteDuration()) { - s.append("inf"); - } else if (d < Seconds(1)) { - // Special case for durations with a magnitude < 1 second. The duration - // is printed as a fraction of a single unit, e.g., "1.2ms". - if (d < Microseconds(1)) { - AppendNumberUnit(&s, FDivDuration(d, Nanoseconds(1)), kDisplayNano); - } else if (d < Milliseconds(1)) { - AppendNumberUnit(&s, FDivDuration(d, Microseconds(1)), kDisplayMicro); - } else { - AppendNumberUnit(&s, FDivDuration(d, Milliseconds(1)), kDisplayMilli); - } - } else { - AppendNumberUnit(&s, IDivDuration(d, Hours(1), &d), kDisplayHour); - AppendNumberUnit(&s, IDivDuration(d, Minutes(1), &d), kDisplayMin); - AppendNumberUnit(&s, FDivDuration(d, Seconds(1)), kDisplaySec); - } - if (s.empty() || s == "-") { - s = "0"; - } - return s; -} - -namespace { - -// A helper for ParseDuration() that parses a leading number from the given -// string and stores the result in *int_part/*frac_part/*frac_scale. The -// given string pointer is modified to point to the first unconsumed char. + if (d < ZeroDuration()) { + s.append("-"); + d = -d; + } + if (d == InfiniteDuration()) { + s.append("inf"); + } else if (d < Seconds(1)) { + // Special case for durations with a magnitude < 1 second. The duration + // is printed as a fraction of a single unit, e.g., "1.2ms". + if (d < Microseconds(1)) { + AppendNumberUnit(&s, FDivDuration(d, Nanoseconds(1)), kDisplayNano); + } else if (d < Milliseconds(1)) { + AppendNumberUnit(&s, FDivDuration(d, Microseconds(1)), kDisplayMicro); + } else { + AppendNumberUnit(&s, FDivDuration(d, Milliseconds(1)), kDisplayMilli); + } + } else { + AppendNumberUnit(&s, IDivDuration(d, Hours(1), &d), kDisplayHour); + AppendNumberUnit(&s, IDivDuration(d, Minutes(1), &d), kDisplayMin); + AppendNumberUnit(&s, FDivDuration(d, Seconds(1)), kDisplaySec); + } + if (s.empty() || s == "-") { + s = "0"; + } + return s; +} + +namespace { + +// A helper for ParseDuration() that parses a leading number from the given +// string and stores the result in *int_part/*frac_part/*frac_scale. The +// given string pointer is modified to point to the first unconsumed char. bool ConsumeDurationNumber(const char** dpp, const char* ep, int64_t* int_part, - int64_t* frac_part, int64_t* frac_scale) { - *int_part = 0; - *frac_part = 0; - *frac_scale = 1; // invariant: *frac_part < *frac_scale - const char* start = *dpp; + int64_t* frac_part, int64_t* frac_scale) { + *int_part = 0; + *frac_part = 0; + *frac_scale = 1; // invariant: *frac_part < *frac_scale + const char* start = *dpp; for (; *dpp != ep; *dpp += 1) { - const int d = **dpp - '0'; // contiguous digits + const int d = **dpp - '0'; // contiguous digits if (d < 0 || 10 <= d) break; - if (*int_part > kint64max / 10) return false; - *int_part *= 10; - if (*int_part > kint64max - d) return false; - *int_part += d; - } - const bool int_part_empty = (*dpp == start); + if (*int_part > kint64max / 10) return false; + *int_part *= 10; + if (*int_part > kint64max - d) return false; + *int_part += d; + } + const bool int_part_empty = (*dpp == start); if (*dpp == ep || **dpp != '.') return !int_part_empty; for (*dpp += 1; *dpp != ep; *dpp += 1) { - const int d = **dpp - '0'; // contiguous digits + const int d = **dpp - '0'; // contiguous digits if (d < 0 || 10 <= d) break; - if (*frac_scale <= kint64max / 10) { - *frac_part *= 10; - *frac_part += d; - *frac_scale *= 10; - } - } - return !int_part_empty || *frac_scale != 1; -} - -// A helper for ParseDuration() that parses a leading unit designator (e.g., -// ns, us, ms, s, m, h) from the given string and stores the resulting unit -// in "*unit". The given string pointer is modified to point to the first -// unconsumed char. + if (*frac_scale <= kint64max / 10) { + *frac_part *= 10; + *frac_part += d; + *frac_scale *= 10; + } + } + return !int_part_empty || *frac_scale != 1; +} + +// A helper for ParseDuration() that parses a leading unit designator (e.g., +// ns, us, ms, s, m, h) from the given string and stores the resulting unit +// in "*unit". The given string pointer is modified to point to the first +// unconsumed char. bool ConsumeDurationUnit(const char** start, const char* end, Duration* unit) { size_t size = end - *start; switch (size) { @@ -888,67 +888,67 @@ bool ConsumeDurationUnit(const char** start, const char* end, Duration* unit) { default: return false; } - } -} - -} // namespace - -// From Go's doc at https://golang.org/pkg/time/#ParseDuration -// [ParseDuration] parses a duration string. A duration string is -// a possibly signed sequence of decimal numbers, each with optional -// fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". -// Valid time units are "ns", "us" "ms", "s", "m", "h". + } +} + +} // namespace + +// From Go's doc at https://golang.org/pkg/time/#ParseDuration +// [ParseDuration] parses a duration string. A duration string is +// a possibly signed sequence of decimal numbers, each with optional +// fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". +// Valid time units are "ns", "us" "ms", "s", "m", "h". bool ParseDuration(y_absl::string_view dur_sv, Duration* d) { - int sign = 1; + int sign = 1; if (y_absl::ConsumePrefix(&dur_sv, "-")) { sign = -1; } else { y_absl::ConsumePrefix(&dur_sv, "+"); - } + } if (dur_sv.empty()) return false; - + // Special case for a string of "0". if (dur_sv == "0") { - *d = ZeroDuration(); - return true; - } - + *d = ZeroDuration(); + return true; + } + if (dur_sv == "inf") { - *d = sign * InfiniteDuration(); - return true; - } - + *d = sign * InfiniteDuration(); + return true; + } + const char* start = dur_sv.data(); const char* end = start + dur_sv.size(); - Duration dur; + Duration dur; while (start != end) { - int64_t int_part; - int64_t frac_part; - int64_t frac_scale; - Duration unit; + int64_t int_part; + int64_t frac_part; + int64_t frac_scale; + Duration unit; if (!ConsumeDurationNumber(&start, end, &int_part, &frac_part, &frac_scale) || !ConsumeDurationUnit(&start, end, &unit)) { - return false; - } - if (int_part != 0) dur += sign * int_part * unit; - if (frac_part != 0) dur += sign * frac_part * unit / frac_scale; - } - *d = dur; - return true; -} - + return false; + } + if (int_part != 0) dur += sign * int_part * unit; + if (frac_part != 0) dur += sign * frac_part * unit / frac_scale; + } + *d = dur; + return true; +} + bool AbslParseFlag(y_absl::string_view text, Duration* dst, TString*) { return ParseDuration(text, dst); -} - +} + TString AbslUnparseFlag(Duration d) { return FormatDuration(d); } bool ParseFlag(const TString& text, Duration* dst, TString* ) { - return ParseDuration(text, dst); -} - + return ParseDuration(text, dst); +} + TString UnparseFlag(Duration d) { return FormatDuration(d); } - + ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/format.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/format.cc index 39c0191963..c75e4ec21a 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/format.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/format.cc @@ -1,109 +1,109 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include <string.h> - -#include <cctype> -#include <cstdint> - +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <string.h> + +#include <cctype> +#include <cstdint> + #include "y_absl/strings/match.h" #include "y_absl/strings/string_view.h" #include "y_absl/time/internal/cctz/include/cctz/time_zone.h" #include "y_absl/time/time.h" - + namespace cctz = y_absl::time_internal::cctz; - + namespace y_absl { ABSL_NAMESPACE_BEGIN - + ABSL_DLL extern const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez"; ABSL_DLL extern const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez"; - + ABSL_DLL extern const char RFC1123_full[] = "%a, %d %b %E4Y %H:%M:%S %z"; ABSL_DLL extern const char RFC1123_no_wday[] = "%d %b %E4Y %H:%M:%S %z"; - -namespace { - -const char kInfiniteFutureStr[] = "infinite-future"; -const char kInfinitePastStr[] = "infinite-past"; - -struct cctz_parts { - cctz::time_point<cctz::seconds> sec; - cctz::detail::femtoseconds fem; -}; - -inline cctz::time_point<cctz::seconds> unix_epoch() { - return std::chrono::time_point_cast<cctz::seconds>( - std::chrono::system_clock::from_time_t(0)); -} - -// Splits a Time into seconds and femtoseconds, which can be used with CCTZ. -// Requires that 't' is finite. See duration.cc for details about rep_hi and -// rep_lo. + +namespace { + +const char kInfiniteFutureStr[] = "infinite-future"; +const char kInfinitePastStr[] = "infinite-past"; + +struct cctz_parts { + cctz::time_point<cctz::seconds> sec; + cctz::detail::femtoseconds fem; +}; + +inline cctz::time_point<cctz::seconds> unix_epoch() { + return std::chrono::time_point_cast<cctz::seconds>( + std::chrono::system_clock::from_time_t(0)); +} + +// Splits a Time into seconds and femtoseconds, which can be used with CCTZ. +// Requires that 't' is finite. See duration.cc for details about rep_hi and +// rep_lo. cctz_parts Split(y_absl::Time t) { - const auto d = time_internal::ToUnixDuration(t); - const int64_t rep_hi = time_internal::GetRepHi(d); - const int64_t rep_lo = time_internal::GetRepLo(d); - const auto sec = unix_epoch() + cctz::seconds(rep_hi); - const auto fem = cctz::detail::femtoseconds(rep_lo * (1000 * 1000 / 4)); - return {sec, fem}; -} - -// Joins the given seconds and femtoseconds into a Time. See duration.cc for -// details about rep_hi and rep_lo. + const auto d = time_internal::ToUnixDuration(t); + const int64_t rep_hi = time_internal::GetRepHi(d); + const int64_t rep_lo = time_internal::GetRepLo(d); + const auto sec = unix_epoch() + cctz::seconds(rep_hi); + const auto fem = cctz::detail::femtoseconds(rep_lo * (1000 * 1000 / 4)); + return {sec, fem}; +} + +// Joins the given seconds and femtoseconds into a Time. See duration.cc for +// details about rep_hi and rep_lo. y_absl::Time Join(const cctz_parts& parts) { - const int64_t rep_hi = (parts.sec - unix_epoch()).count(); - const uint32_t rep_lo = parts.fem.count() / (1000 * 1000 / 4); - const auto d = time_internal::MakeDuration(rep_hi, rep_lo); - return time_internal::FromUnixDuration(d); -} - -} // namespace - + const int64_t rep_hi = (parts.sec - unix_epoch()).count(); + const uint32_t rep_lo = parts.fem.count() / (1000 * 1000 / 4); + const auto d = time_internal::MakeDuration(rep_hi, rep_lo); + return time_internal::FromUnixDuration(d); +} + +} // namespace + TString FormatTime(y_absl::string_view format, y_absl::Time t, y_absl::TimeZone tz) { if (t == y_absl::InfiniteFuture()) return TString(kInfiniteFutureStr); if (t == y_absl::InfinitePast()) return TString(kInfinitePastStr); - const auto parts = Split(t); + const auto parts = Split(t); return cctz::detail::format(TString(format), parts.sec, parts.fem, - cctz::time_zone(tz)); -} - + cctz::time_zone(tz)); +} + TString FormatTime(y_absl::Time t, y_absl::TimeZone tz) { - return FormatTime(RFC3339_full, t, tz); -} - + return FormatTime(RFC3339_full, t, tz); +} + TString FormatTime(y_absl::Time t) { return y_absl::FormatTime(RFC3339_full, t, y_absl::LocalTimeZone()); -} - +} + bool ParseTime(y_absl::string_view format, y_absl::string_view input, y_absl::Time* time, TString* err) { return y_absl::ParseTime(format, input, y_absl::UTCTimeZone(), time, err); -} - -// If the input string does not contain an explicit UTC offset, interpret -// the fields with respect to the given TimeZone. +} + +// If the input string does not contain an explicit UTC offset, interpret +// the fields with respect to the given TimeZone. bool ParseTime(y_absl::string_view format, y_absl::string_view input, y_absl::TimeZone tz, y_absl::Time* time, TString* err) { auto strip_leading_space = [](y_absl::string_view* sv) { while (!sv->empty()) { if (!std::isspace(sv->front())) return; sv->remove_prefix(1); - } + } }; - + // Portable toolchains means we don't get nice constexpr here. struct Literal { const char* name; @@ -124,37 +124,37 @@ bool ParseTime(y_absl::string_view format, y_absl::string_view input, *time = lit.value; return true; } - } - } - + } + } + TString error; - cctz_parts parts; + cctz_parts parts; const bool b = cctz::detail::parse(TString(format), TString(input), cctz::time_zone(tz), &parts.sec, &parts.fem, &error); - if (b) { - *time = Join(parts); - } else if (err != nullptr) { - *err = error; - } - return b; -} - + if (b) { + *time = Join(parts); + } else if (err != nullptr) { + *err = error; + } + return b; +} + // Functions required to support y_absl::Time flags. bool AbslParseFlag(y_absl::string_view text, y_absl::Time* t, TString* error) { return y_absl::ParseTime(RFC3339_full, text, y_absl::UTCTimeZone(), t, error); -} - +} + TString AbslUnparseFlag(y_absl::Time t) { return y_absl::FormatTime(RFC3339_full, t, y_absl::UTCTimeZone()); -} +} bool ParseFlag(const TString& text, y_absl::Time* t, TString* error) { return y_absl::ParseTime(RFC3339_full, text, y_absl::UTCTimeZone(), t, error); -} - +} + TString UnparseFlag(y_absl::Time t) { return y_absl::FormatTime(RFC3339_full, t, y_absl::UTCTimeZone()); -} - +} + ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/civil_time.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/civil_time.h index 9382ecc231..be60a54dbe 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/civil_time.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/civil_time.h @@ -1,332 +1,332 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ -#define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ - +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ +#define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ + #include "y_absl/base/config.h" #include "y_absl/time/internal/cctz/include/cctz/civil_time_detail.h" - + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// The term "civil time" refers to the legally recognized human-scale time -// that is represented by the six fields YYYY-MM-DD hh:mm:ss. Modern-day civil -// time follows the Gregorian Calendar and is a time-zone-independent concept. -// A "date" is perhaps the most common example of a civil time (represented in -// this library as cctz::civil_day). This library provides six classes and a -// handful of functions that help with rounding, iterating, and arithmetic on -// civil times while avoiding complications like daylight-saving time (DST). -// -// The following six classes form the core of this civil-time library: -// -// * civil_second -// * civil_minute -// * civil_hour -// * civil_day -// * civil_month -// * civil_year -// -// Each class is a simple value type with the same interface for construction -// and the same six accessors for each of the civil fields (year, month, day, -// hour, minute, and second, aka YMDHMS). These classes differ only in their -// alignment, which is indicated by the type name and specifies the field on -// which arithmetic operates. -// -// Each class can be constructed by passing up to six optional integer -// arguments representing the YMDHMS fields (in that order) to the -// constructor. Omitted fields are assigned their minimum valid value. Hours, -// minutes, and seconds will be set to 0, month and day will be set to 1, and -// since there is no minimum valid year, it will be set to 1970. So, a -// default-constructed civil-time object will have YMDHMS fields representing -// "1970-01-01 00:00:00". Fields that are out-of-range are normalized (e.g., -// October 32 -> November 1) so that all civil-time objects represent valid -// values. -// -// Each civil-time class is aligned to the civil-time field indicated in the -// class's name after normalization. Alignment is performed by setting all the -// inferior fields to their minimum valid value (as described above). The -// following are examples of how each of the six types would align the fields -// representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the -// string format used here is not important; it's just a shorthand way of -// showing the six YMDHMS fields.) -// -// civil_second 2015-11-22 12:34:56 -// civil_minute 2015-11-22 12:34:00 -// civil_hour 2015-11-22 12:00:00 -// civil_day 2015-11-22 00:00:00 -// civil_month 2015-11-01 00:00:00 -// civil_year 2015-01-01 00:00:00 -// -// Each civil-time type performs arithmetic on the field to which it is -// aligned. This means that adding 1 to a civil_day increments the day field -// (normalizing as necessary), and subtracting 7 from a civil_month operates -// on the month field (normalizing as necessary). All arithmetic produces a -// valid civil time. Difference requires two similarly aligned civil-time -// objects and returns the scalar answer in units of the objects' alignment. -// For example, the difference between two civil_hour objects will give an -// answer in units of civil hours. -// -// In addition to the six civil-time types just described, there are -// a handful of helper functions and algorithms for performing common -// calculations. These are described below. -// -// Note: In C++14 and later, this library is usable in a constexpr context. -// -// CONSTRUCTION: -// -// Each of the civil-time types can be constructed in two ways: by directly -// passing to the constructor up to six (optional) integers representing the -// YMDHMS fields, or by copying the YMDHMS fields from a differently aligned -// civil-time type. -// -// civil_day default_value; // 1970-01-01 00:00:00 -// -// civil_day a(2015, 2, 3); // 2015-02-03 00:00:00 -// civil_day b(2015, 2, 3, 4, 5, 6); // 2015-02-03 00:00:00 -// civil_day c(2015); // 2015-01-01 00:00:00 -// -// civil_second ss(2015, 2, 3, 4, 5, 6); // 2015-02-03 04:05:06 -// civil_minute mm(ss); // 2015-02-03 04:05:00 -// civil_hour hh(mm); // 2015-02-03 04:00:00 -// civil_day d(hh); // 2015-02-03 00:00:00 -// civil_month m(d); // 2015-02-01 00:00:00 -// civil_year y(m); // 2015-01-01 00:00:00 -// -// m = civil_month(y); // 2015-01-01 00:00:00 -// d = civil_day(m); // 2015-01-01 00:00:00 -// hh = civil_hour(d); // 2015-01-01 00:00:00 -// mm = civil_minute(hh); // 2015-01-01 00:00:00 -// ss = civil_second(mm); // 2015-01-01 00:00:00 -// -// ALIGNMENT CONVERSION: -// -// The alignment of a civil-time object cannot change, but the object may be -// used to construct a new object with a different alignment. This is referred -// to as "realigning". When realigning to a type with the same or more -// precision (e.g., civil_day -> civil_second), the conversion may be -// performed implicitly since no information is lost. However, if information -// could be discarded (e.g., civil_second -> civil_day), the conversion must -// be explicit at the call site. -// -// void fun(const civil_day& day); -// -// civil_second cs; -// fun(cs); // Won't compile because data may be discarded -// fun(civil_day(cs)); // OK: explicit conversion -// -// civil_day cd; -// fun(cd); // OK: no conversion needed -// -// civil_month cm; -// fun(cm); // OK: implicit conversion to civil_day -// -// NORMALIZATION: -// -// Integer arguments passed to the constructor may be out-of-range, in which -// case they are normalized to produce a valid civil-time object. This enables -// natural arithmetic on constructor arguments without worrying about the -// field's range. Normalization guarantees that there are no invalid -// civil-time objects. -// -// civil_day d(2016, 10, 32); // Out-of-range day; normalized to 2016-11-01 -// -// Note: If normalization is undesired, you can signal an error by comparing -// the constructor arguments to the normalized values returned by the YMDHMS -// properties. -// -// PROPERTIES: -// -// All civil-time types have accessors for all six of the civil-time fields: -// year, month, day, hour, minute, and second. Recall that fields inferior to -// the type's alignment will be set to their minimum valid value. -// -// civil_day d(2015, 6, 28); -// // d.year() == 2015 -// // d.month() == 6 -// // d.day() == 28 -// // d.hour() == 0 -// // d.minute() == 0 -// // d.second() == 0 -// -// COMPARISON: -// -// Comparison always considers all six YMDHMS fields, regardless of the type's -// alignment. Comparison between differently aligned civil-time types is -// allowed. -// -// civil_day feb_3(2015, 2, 3); // 2015-02-03 00:00:00 -// civil_day mar_4(2015, 3, 4); // 2015-03-04 00:00:00 -// // feb_3 < mar_4 -// // civil_year(feb_3) == civil_year(mar_4) -// -// civil_second feb_3_noon(2015, 2, 3, 12, 0, 0); // 2015-02-03 12:00:00 -// // feb_3 < feb_3_noon -// // feb_3 == civil_day(feb_3_noon) -// -// // Iterates all the days of February 2015. -// for (civil_day d(2015, 2, 1); d < civil_month(2015, 3); ++d) { -// // ... -// } -// -// STREAMING: -// -// Each civil-time type may be sent to an output stream using operator<<(). -// The output format follows the pattern "YYYY-MM-DDThh:mm:ss" where fields -// inferior to the type's alignment are omitted. -// -// civil_second cs(2015, 2, 3, 4, 5, 6); -// std::cout << cs << "\n"; // Outputs: 2015-02-03T04:05:06 -// -// civil_day cd(cs); -// std::cout << cd << "\n"; // Outputs: 2015-02-03 -// -// civil_year cy(cs); -// std::cout << cy << "\n"; // Outputs: 2015 -// -// ARITHMETIC: -// -// Civil-time types support natural arithmetic operators such as addition, -// subtraction, and difference. Arithmetic operates on the civil-time field -// indicated in the type's name. Difference requires arguments with the same -// alignment and returns the answer in units of the alignment. -// -// civil_day a(2015, 2, 3); -// ++a; // 2015-02-04 00:00:00 -// --a; // 2015-02-03 00:00:00 -// civil_day b = a + 1; // 2015-02-04 00:00:00 -// civil_day c = 1 + b; // 2015-02-05 00:00:00 -// int n = c - a; // n = 2 (civil days) -// int m = c - civil_month(c); // Won't compile: different types. -// -// EXAMPLE: Adding a month to January 31. -// -// One of the classic questions that arises when considering a civil-time -// library (or a date library or a date/time library) is this: "What happens -// when you add a month to January 31?" This is an interesting question -// because there could be a number of possible answers: -// -// 1. March 3 (or 2 if a leap year). This may make sense if the operation -// wants the equivalent of February 31. -// 2. February 28 (or 29 if a leap year). This may make sense if the operation -// wants the last day of January to go to the last day of February. -// 3. Error. The caller may get some error, an exception, an invalid date -// object, or maybe false is returned. This may make sense because there is -// no single unambiguously correct answer to the question. -// -// Practically speaking, any answer that is not what the programmer intended -// is the wrong answer. -// -// This civil-time library avoids the problem by making it impossible to ask -// ambiguous questions. All civil-time objects are aligned to a particular -// civil-field boundary (such as aligned to a year, month, day, hour, minute, -// or second), and arithmetic operates on the field to which the object is -// aligned. This means that in order to "add a month" the object must first be -// aligned to a month boundary, which is equivalent to the first day of that -// month. -// -// Of course, there are ways to compute an answer the question at hand using -// this civil-time library, but they require the programmer to be explicit -// about the answer they expect. To illustrate, let's see how to compute all -// three of the above possible answers to the question of "Jan 31 plus 1 -// month": -// -// const civil_day d(2015, 1, 31); -// -// // Answer 1: -// // Add 1 to the month field in the constructor, and rely on normalization. -// const auto ans_normalized = civil_day(d.year(), d.month() + 1, d.day()); -// // ans_normalized == 2015-03-03 (aka Feb 31) -// -// // Answer 2: -// // Add 1 to month field, capping to the end of next month. -// const auto next_month = civil_month(d) + 1; -// const auto last_day_of_next_month = civil_day(next_month + 1) - 1; -// const auto ans_capped = std::min(ans_normalized, last_day_of_next_month); -// // ans_capped == 2015-02-28 -// -// // Answer 3: -// // Signal an error if the normalized answer is not in next month. -// if (civil_month(ans_normalized) != next_month) { -// // error, month overflow -// } -// -using civil_year = detail::civil_year; -using civil_month = detail::civil_month; -using civil_day = detail::civil_day; -using civil_hour = detail::civil_hour; -using civil_minute = detail::civil_minute; -using civil_second = detail::civil_second; - -// An enum class with members monday, tuesday, wednesday, thursday, friday, -// saturday, and sunday. These enum values may be sent to an output stream -// using operator<<(). The result is the full weekday name in English with a -// leading capital letter. -// -// weekday wd = weekday::thursday; -// std::cout << wd << "\n"; // Outputs: Thursday -// -using detail::weekday; - -// Returns the weekday for the given civil-time value. -// -// civil_day a(2015, 8, 13); -// weekday wd = get_weekday(a); // wd == weekday::thursday -// -using detail::get_weekday; - -// Returns the civil_day that strictly follows or precedes the given -// civil_day, and that falls on the given weekday. -// -// For example, given: -// -// August 2015 -// Su Mo Tu We Th Fr Sa -// 1 -// 2 3 4 5 6 7 8 -// 9 10 11 12 13 14 15 -// 16 17 18 19 20 21 22 -// 23 24 25 26 27 28 29 -// 30 31 -// -// civil_day a(2015, 8, 13); // get_weekday(a) == weekday::thursday -// civil_day b = next_weekday(a, weekday::thursday); // b = 2015-08-20 -// civil_day c = prev_weekday(a, weekday::thursday); // c = 2015-08-06 -// -// civil_day d = ... -// // Gets the following Thursday if d is not already Thursday -// civil_day thurs1 = next_weekday(d - 1, weekday::thursday); -// // Gets the previous Thursday if d is not already Thursday -// civil_day thurs2 = prev_weekday(d + 1, weekday::thursday); -// -using detail::next_weekday; -using detail::prev_weekday; - -// Returns the day-of-year for the given civil-time value. -// -// civil_day a(2015, 1, 1); -// int yd_jan_1 = get_yearday(a); // yd_jan_1 = 1 -// civil_day b(2015, 12, 31); -// int yd_dec_31 = get_yearday(b); // yd_dec_31 = 365 -// -using detail::get_yearday; - -} // namespace cctz -} // namespace time_internal +namespace time_internal { +namespace cctz { + +// The term "civil time" refers to the legally recognized human-scale time +// that is represented by the six fields YYYY-MM-DD hh:mm:ss. Modern-day civil +// time follows the Gregorian Calendar and is a time-zone-independent concept. +// A "date" is perhaps the most common example of a civil time (represented in +// this library as cctz::civil_day). This library provides six classes and a +// handful of functions that help with rounding, iterating, and arithmetic on +// civil times while avoiding complications like daylight-saving time (DST). +// +// The following six classes form the core of this civil-time library: +// +// * civil_second +// * civil_minute +// * civil_hour +// * civil_day +// * civil_month +// * civil_year +// +// Each class is a simple value type with the same interface for construction +// and the same six accessors for each of the civil fields (year, month, day, +// hour, minute, and second, aka YMDHMS). These classes differ only in their +// alignment, which is indicated by the type name and specifies the field on +// which arithmetic operates. +// +// Each class can be constructed by passing up to six optional integer +// arguments representing the YMDHMS fields (in that order) to the +// constructor. Omitted fields are assigned their minimum valid value. Hours, +// minutes, and seconds will be set to 0, month and day will be set to 1, and +// since there is no minimum valid year, it will be set to 1970. So, a +// default-constructed civil-time object will have YMDHMS fields representing +// "1970-01-01 00:00:00". Fields that are out-of-range are normalized (e.g., +// October 32 -> November 1) so that all civil-time objects represent valid +// values. +// +// Each civil-time class is aligned to the civil-time field indicated in the +// class's name after normalization. Alignment is performed by setting all the +// inferior fields to their minimum valid value (as described above). The +// following are examples of how each of the six types would align the fields +// representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the +// string format used here is not important; it's just a shorthand way of +// showing the six YMDHMS fields.) +// +// civil_second 2015-11-22 12:34:56 +// civil_minute 2015-11-22 12:34:00 +// civil_hour 2015-11-22 12:00:00 +// civil_day 2015-11-22 00:00:00 +// civil_month 2015-11-01 00:00:00 +// civil_year 2015-01-01 00:00:00 +// +// Each civil-time type performs arithmetic on the field to which it is +// aligned. This means that adding 1 to a civil_day increments the day field +// (normalizing as necessary), and subtracting 7 from a civil_month operates +// on the month field (normalizing as necessary). All arithmetic produces a +// valid civil time. Difference requires two similarly aligned civil-time +// objects and returns the scalar answer in units of the objects' alignment. +// For example, the difference between two civil_hour objects will give an +// answer in units of civil hours. +// +// In addition to the six civil-time types just described, there are +// a handful of helper functions and algorithms for performing common +// calculations. These are described below. +// +// Note: In C++14 and later, this library is usable in a constexpr context. +// +// CONSTRUCTION: +// +// Each of the civil-time types can be constructed in two ways: by directly +// passing to the constructor up to six (optional) integers representing the +// YMDHMS fields, or by copying the YMDHMS fields from a differently aligned +// civil-time type. +// +// civil_day default_value; // 1970-01-01 00:00:00 +// +// civil_day a(2015, 2, 3); // 2015-02-03 00:00:00 +// civil_day b(2015, 2, 3, 4, 5, 6); // 2015-02-03 00:00:00 +// civil_day c(2015); // 2015-01-01 00:00:00 +// +// civil_second ss(2015, 2, 3, 4, 5, 6); // 2015-02-03 04:05:06 +// civil_minute mm(ss); // 2015-02-03 04:05:00 +// civil_hour hh(mm); // 2015-02-03 04:00:00 +// civil_day d(hh); // 2015-02-03 00:00:00 +// civil_month m(d); // 2015-02-01 00:00:00 +// civil_year y(m); // 2015-01-01 00:00:00 +// +// m = civil_month(y); // 2015-01-01 00:00:00 +// d = civil_day(m); // 2015-01-01 00:00:00 +// hh = civil_hour(d); // 2015-01-01 00:00:00 +// mm = civil_minute(hh); // 2015-01-01 00:00:00 +// ss = civil_second(mm); // 2015-01-01 00:00:00 +// +// ALIGNMENT CONVERSION: +// +// The alignment of a civil-time object cannot change, but the object may be +// used to construct a new object with a different alignment. This is referred +// to as "realigning". When realigning to a type with the same or more +// precision (e.g., civil_day -> civil_second), the conversion may be +// performed implicitly since no information is lost. However, if information +// could be discarded (e.g., civil_second -> civil_day), the conversion must +// be explicit at the call site. +// +// void fun(const civil_day& day); +// +// civil_second cs; +// fun(cs); // Won't compile because data may be discarded +// fun(civil_day(cs)); // OK: explicit conversion +// +// civil_day cd; +// fun(cd); // OK: no conversion needed +// +// civil_month cm; +// fun(cm); // OK: implicit conversion to civil_day +// +// NORMALIZATION: +// +// Integer arguments passed to the constructor may be out-of-range, in which +// case they are normalized to produce a valid civil-time object. This enables +// natural arithmetic on constructor arguments without worrying about the +// field's range. Normalization guarantees that there are no invalid +// civil-time objects. +// +// civil_day d(2016, 10, 32); // Out-of-range day; normalized to 2016-11-01 +// +// Note: If normalization is undesired, you can signal an error by comparing +// the constructor arguments to the normalized values returned by the YMDHMS +// properties. +// +// PROPERTIES: +// +// All civil-time types have accessors for all six of the civil-time fields: +// year, month, day, hour, minute, and second. Recall that fields inferior to +// the type's alignment will be set to their minimum valid value. +// +// civil_day d(2015, 6, 28); +// // d.year() == 2015 +// // d.month() == 6 +// // d.day() == 28 +// // d.hour() == 0 +// // d.minute() == 0 +// // d.second() == 0 +// +// COMPARISON: +// +// Comparison always considers all six YMDHMS fields, regardless of the type's +// alignment. Comparison between differently aligned civil-time types is +// allowed. +// +// civil_day feb_3(2015, 2, 3); // 2015-02-03 00:00:00 +// civil_day mar_4(2015, 3, 4); // 2015-03-04 00:00:00 +// // feb_3 < mar_4 +// // civil_year(feb_3) == civil_year(mar_4) +// +// civil_second feb_3_noon(2015, 2, 3, 12, 0, 0); // 2015-02-03 12:00:00 +// // feb_3 < feb_3_noon +// // feb_3 == civil_day(feb_3_noon) +// +// // Iterates all the days of February 2015. +// for (civil_day d(2015, 2, 1); d < civil_month(2015, 3); ++d) { +// // ... +// } +// +// STREAMING: +// +// Each civil-time type may be sent to an output stream using operator<<(). +// The output format follows the pattern "YYYY-MM-DDThh:mm:ss" where fields +// inferior to the type's alignment are omitted. +// +// civil_second cs(2015, 2, 3, 4, 5, 6); +// std::cout << cs << "\n"; // Outputs: 2015-02-03T04:05:06 +// +// civil_day cd(cs); +// std::cout << cd << "\n"; // Outputs: 2015-02-03 +// +// civil_year cy(cs); +// std::cout << cy << "\n"; // Outputs: 2015 +// +// ARITHMETIC: +// +// Civil-time types support natural arithmetic operators such as addition, +// subtraction, and difference. Arithmetic operates on the civil-time field +// indicated in the type's name. Difference requires arguments with the same +// alignment and returns the answer in units of the alignment. +// +// civil_day a(2015, 2, 3); +// ++a; // 2015-02-04 00:00:00 +// --a; // 2015-02-03 00:00:00 +// civil_day b = a + 1; // 2015-02-04 00:00:00 +// civil_day c = 1 + b; // 2015-02-05 00:00:00 +// int n = c - a; // n = 2 (civil days) +// int m = c - civil_month(c); // Won't compile: different types. +// +// EXAMPLE: Adding a month to January 31. +// +// One of the classic questions that arises when considering a civil-time +// library (or a date library or a date/time library) is this: "What happens +// when you add a month to January 31?" This is an interesting question +// because there could be a number of possible answers: +// +// 1. March 3 (or 2 if a leap year). This may make sense if the operation +// wants the equivalent of February 31. +// 2. February 28 (or 29 if a leap year). This may make sense if the operation +// wants the last day of January to go to the last day of February. +// 3. Error. The caller may get some error, an exception, an invalid date +// object, or maybe false is returned. This may make sense because there is +// no single unambiguously correct answer to the question. +// +// Practically speaking, any answer that is not what the programmer intended +// is the wrong answer. +// +// This civil-time library avoids the problem by making it impossible to ask +// ambiguous questions. All civil-time objects are aligned to a particular +// civil-field boundary (such as aligned to a year, month, day, hour, minute, +// or second), and arithmetic operates on the field to which the object is +// aligned. This means that in order to "add a month" the object must first be +// aligned to a month boundary, which is equivalent to the first day of that +// month. +// +// Of course, there are ways to compute an answer the question at hand using +// this civil-time library, but they require the programmer to be explicit +// about the answer they expect. To illustrate, let's see how to compute all +// three of the above possible answers to the question of "Jan 31 plus 1 +// month": +// +// const civil_day d(2015, 1, 31); +// +// // Answer 1: +// // Add 1 to the month field in the constructor, and rely on normalization. +// const auto ans_normalized = civil_day(d.year(), d.month() + 1, d.day()); +// // ans_normalized == 2015-03-03 (aka Feb 31) +// +// // Answer 2: +// // Add 1 to month field, capping to the end of next month. +// const auto next_month = civil_month(d) + 1; +// const auto last_day_of_next_month = civil_day(next_month + 1) - 1; +// const auto ans_capped = std::min(ans_normalized, last_day_of_next_month); +// // ans_capped == 2015-02-28 +// +// // Answer 3: +// // Signal an error if the normalized answer is not in next month. +// if (civil_month(ans_normalized) != next_month) { +// // error, month overflow +// } +// +using civil_year = detail::civil_year; +using civil_month = detail::civil_month; +using civil_day = detail::civil_day; +using civil_hour = detail::civil_hour; +using civil_minute = detail::civil_minute; +using civil_second = detail::civil_second; + +// An enum class with members monday, tuesday, wednesday, thursday, friday, +// saturday, and sunday. These enum values may be sent to an output stream +// using operator<<(). The result is the full weekday name in English with a +// leading capital letter. +// +// weekday wd = weekday::thursday; +// std::cout << wd << "\n"; // Outputs: Thursday +// +using detail::weekday; + +// Returns the weekday for the given civil-time value. +// +// civil_day a(2015, 8, 13); +// weekday wd = get_weekday(a); // wd == weekday::thursday +// +using detail::get_weekday; + +// Returns the civil_day that strictly follows or precedes the given +// civil_day, and that falls on the given weekday. +// +// For example, given: +// +// August 2015 +// Su Mo Tu We Th Fr Sa +// 1 +// 2 3 4 5 6 7 8 +// 9 10 11 12 13 14 15 +// 16 17 18 19 20 21 22 +// 23 24 25 26 27 28 29 +// 30 31 +// +// civil_day a(2015, 8, 13); // get_weekday(a) == weekday::thursday +// civil_day b = next_weekday(a, weekday::thursday); // b = 2015-08-20 +// civil_day c = prev_weekday(a, weekday::thursday); // c = 2015-08-06 +// +// civil_day d = ... +// // Gets the following Thursday if d is not already Thursday +// civil_day thurs1 = next_weekday(d - 1, weekday::thursday); +// // Gets the previous Thursday if d is not already Thursday +// civil_day thurs2 = prev_weekday(d + 1, weekday::thursday); +// +using detail::next_weekday; +using detail::prev_weekday; + +// Returns the day-of-year for the given civil-time value. +// +// civil_day a(2015, 1, 1); +// int yd_jan_1 = get_yearday(a); // yd_jan_1 = 1 +// civil_day b(2015, 12, 31); +// int yd_dec_31 = get_yearday(b); // yd_dec_31 = 365 +// +using detail::get_yearday; + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ + +#endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/civil_time_detail.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/civil_time_detail.h index d8b4e1ac1c..0e71a7cd33 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/civil_time_detail.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/civil_time_detail.h @@ -1,491 +1,491 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_ -#define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_ - -#include <cstdint> -#include <limits> -#include <ostream> -#include <type_traits> - +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_ +#define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_ + +#include <cstdint> +#include <limits> +#include <ostream> +#include <type_traits> + #include "y_absl/base/config.h" -// Disable constexpr support unless we are in C++14 mode. -#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) -#define CONSTEXPR_D constexpr // data -#define CONSTEXPR_F constexpr // function -#define CONSTEXPR_M constexpr // member -#else -#define CONSTEXPR_D const -#define CONSTEXPR_F inline -#define CONSTEXPR_M -#endif - +// Disable constexpr support unless we are in C++14 mode. +#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) +#define CONSTEXPR_D constexpr // data +#define CONSTEXPR_F constexpr // function +#define CONSTEXPR_M constexpr // member +#else +#define CONSTEXPR_D const +#define CONSTEXPR_F inline +#define CONSTEXPR_M +#endif + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// Support years that at least span the range of 64-bit time_t values. -using year_t = std::int_fast64_t; - -// Type alias that indicates an argument is not normalized (e.g., the -// constructor parameters and operands/results of addition/subtraction). -using diff_t = std::int_fast64_t; - -namespace detail { - -// Type aliases that indicate normalized argument values. -using month_t = std::int_fast8_t; // [1:12] -using day_t = std::int_fast8_t; // [1:31] -using hour_t = std::int_fast8_t; // [0:23] -using minute_t = std::int_fast8_t; // [0:59] -using second_t = std::int_fast8_t; // [0:59] - -// Normalized civil-time fields: Y-M-D HH:MM:SS. -struct fields { +namespace time_internal { +namespace cctz { + +// Support years that at least span the range of 64-bit time_t values. +using year_t = std::int_fast64_t; + +// Type alias that indicates an argument is not normalized (e.g., the +// constructor parameters and operands/results of addition/subtraction). +using diff_t = std::int_fast64_t; + +namespace detail { + +// Type aliases that indicate normalized argument values. +using month_t = std::int_fast8_t; // [1:12] +using day_t = std::int_fast8_t; // [1:31] +using hour_t = std::int_fast8_t; // [0:23] +using minute_t = std::int_fast8_t; // [0:59] +using second_t = std::int_fast8_t; // [0:59] + +// Normalized civil-time fields: Y-M-D HH:MM:SS. +struct fields { CONSTEXPR_M fields(year_t year, month_t month, day_t day, hour_t hour, minute_t minute, second_t second) - : y(year), m(month), d(day), hh(hour), mm(minute), ss(second) {} - std::int_least64_t y; - std::int_least8_t m; - std::int_least8_t d; - std::int_least8_t hh; - std::int_least8_t mm; - std::int_least8_t ss; -}; - -struct second_tag {}; -struct minute_tag : second_tag {}; -struct hour_tag : minute_tag {}; -struct day_tag : hour_tag {}; -struct month_tag : day_tag {}; -struct year_tag : month_tag {}; - -//////////////////////////////////////////////////////////////////////// - -// Field normalization (without avoidable overflow). - -namespace impl { - -CONSTEXPR_F bool is_leap_year(year_t y) noexcept { - return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0); -} -CONSTEXPR_F int year_index(year_t y, month_t m) noexcept { - return (static_cast<int>((y + (m > 2)) % 400) + 400) % 400; -} -CONSTEXPR_F int days_per_century(year_t y, month_t m) noexcept { - const int yi = year_index(y, m); - return 36524 + (yi == 0 || yi > 300); -} -CONSTEXPR_F int days_per_4years(year_t y, month_t m) noexcept { - const int yi = year_index(y, m); - return 1460 + (yi == 0 || yi > 300 || (yi - 1) % 100 < 96); -} -CONSTEXPR_F int days_per_year(year_t y, month_t m) noexcept { - return is_leap_year(y + (m > 2)) ? 366 : 365; -} -CONSTEXPR_F int days_per_month(year_t y, month_t m) noexcept { - CONSTEXPR_D int k_days_per_month[1 + 12] = { - -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 // non leap year - }; - return k_days_per_month[m] + (m == 2 && is_leap_year(y)); -} - + : y(year), m(month), d(day), hh(hour), mm(minute), ss(second) {} + std::int_least64_t y; + std::int_least8_t m; + std::int_least8_t d; + std::int_least8_t hh; + std::int_least8_t mm; + std::int_least8_t ss; +}; + +struct second_tag {}; +struct minute_tag : second_tag {}; +struct hour_tag : minute_tag {}; +struct day_tag : hour_tag {}; +struct month_tag : day_tag {}; +struct year_tag : month_tag {}; + +//////////////////////////////////////////////////////////////////////// + +// Field normalization (without avoidable overflow). + +namespace impl { + +CONSTEXPR_F bool is_leap_year(year_t y) noexcept { + return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0); +} +CONSTEXPR_F int year_index(year_t y, month_t m) noexcept { + return (static_cast<int>((y + (m > 2)) % 400) + 400) % 400; +} +CONSTEXPR_F int days_per_century(year_t y, month_t m) noexcept { + const int yi = year_index(y, m); + return 36524 + (yi == 0 || yi > 300); +} +CONSTEXPR_F int days_per_4years(year_t y, month_t m) noexcept { + const int yi = year_index(y, m); + return 1460 + (yi == 0 || yi > 300 || (yi - 1) % 100 < 96); +} +CONSTEXPR_F int days_per_year(year_t y, month_t m) noexcept { + return is_leap_year(y + (m > 2)) ? 366 : 365; +} +CONSTEXPR_F int days_per_month(year_t y, month_t m) noexcept { + CONSTEXPR_D int k_days_per_month[1 + 12] = { + -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 // non leap year + }; + return k_days_per_month[m] + (m == 2 && is_leap_year(y)); +} + CONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd, hour_t hh, minute_t mm, second_t ss) noexcept { year_t ey = y % 400; const year_t oey = ey; ey += (cd / 146097) * 400; - cd %= 146097; - if (cd < 0) { + cd %= 146097; + if (cd < 0) { ey -= 400; - cd += 146097; - } + cd += 146097; + } ey += (d / 146097) * 400; - d = d % 146097 + cd; - if (d > 0) { - if (d > 146097) { + d = d % 146097 + cd; + if (d > 0) { + if (d > 146097) { ey += 400; - d -= 146097; - } - } else { - if (d > -365) { - // We often hit the previous year when stepping a civil time backwards, - // so special case it to avoid counting up by 100/4/1-year chunks. + d -= 146097; + } + } else { + if (d > -365) { + // We often hit the previous year when stepping a civil time backwards, + // so special case it to avoid counting up by 100/4/1-year chunks. ey -= 1; d += days_per_year(ey, m); - } else { + } else { ey -= 400; - d += 146097; - } - } - if (d > 365) { + d += 146097; + } + } + if (d > 365) { for (;;) { int n = days_per_century(ey, m); if (d <= n) break; - d -= n; + d -= n; ey += 100; - } + } for (;;) { int n = days_per_4years(ey, m); if (d <= n) break; - d -= n; + d -= n; ey += 4; - } + } for (;;) { int n = days_per_year(ey, m); if (d <= n) break; - d -= n; + d -= n; ++ey; - } - } - if (d > 28) { + } + } + if (d > 28) { for (;;) { int n = days_per_month(ey, m); if (d <= n) break; - d -= n; - if (++m > 12) { + d -= n; + if (++m > 12) { ++ey; - m = 1; - } - } - } + m = 1; + } + } + } return fields(y + (ey - oey), m, static_cast<day_t>(d), hh, mm, ss); -} +} CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd, hour_t hh, minute_t mm, second_t ss) noexcept { - if (m != 12) { - y += m / 12; - m %= 12; - if (m <= 0) { - y -= 1; - m += 12; - } - } - return n_day(y, static_cast<month_t>(m), d, cd, hh, mm, ss); -} + if (m != 12) { + y += m / 12; + m %= 12; + if (m <= 0) { + y -= 1; + m += 12; + } + } + return n_day(y, static_cast<month_t>(m), d, cd, hh, mm, ss); +} CONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd, diff_t hh, minute_t mm, second_t ss) noexcept { - cd += hh / 24; - hh %= 24; - if (hh < 0) { - cd -= 1; - hh += 24; - } - return n_mon(y, m, d, cd, static_cast<hour_t>(hh), mm, ss); -} -CONSTEXPR_F fields n_min(year_t y, diff_t m, diff_t d, diff_t hh, diff_t ch, - diff_t mm, second_t ss) noexcept { - ch += mm / 60; - mm %= 60; - if (mm < 0) { - ch -= 1; - mm += 60; - } - return n_hour(y, m, d, hh / 24 + ch / 24, hh % 24 + ch % 24, - static_cast<minute_t>(mm), ss); -} -CONSTEXPR_F fields n_sec(year_t y, diff_t m, diff_t d, diff_t hh, diff_t mm, - diff_t ss) noexcept { - // Optimization for when (non-constexpr) fields are already normalized. - if (0 <= ss && ss < 60) { - const second_t nss = static_cast<second_t>(ss); - if (0 <= mm && mm < 60) { - const minute_t nmm = static_cast<minute_t>(mm); - if (0 <= hh && hh < 24) { - const hour_t nhh = static_cast<hour_t>(hh); - if (1 <= d && d <= 28 && 1 <= m && m <= 12) { - const day_t nd = static_cast<day_t>(d); - const month_t nm = static_cast<month_t>(m); - return fields(y, nm, nd, nhh, nmm, nss); - } - return n_mon(y, m, d, 0, nhh, nmm, nss); - } - return n_hour(y, m, d, hh / 24, hh % 24, nmm, nss); - } - return n_min(y, m, d, hh, mm / 60, mm % 60, nss); - } - diff_t cm = ss / 60; - ss %= 60; - if (ss < 0) { - cm -= 1; - ss += 60; - } - return n_min(y, m, d, hh, mm / 60 + cm / 60, mm % 60 + cm % 60, - static_cast<second_t>(ss)); -} - -} // namespace impl - -//////////////////////////////////////////////////////////////////////// - -// Increments the indicated (normalized) field by "n". -CONSTEXPR_F fields step(second_tag, fields f, diff_t n) noexcept { - return impl::n_sec(f.y, f.m, f.d, f.hh, f.mm + n / 60, f.ss + n % 60); -} -CONSTEXPR_F fields step(minute_tag, fields f, diff_t n) noexcept { - return impl::n_min(f.y, f.m, f.d, f.hh + n / 60, 0, f.mm + n % 60, f.ss); -} -CONSTEXPR_F fields step(hour_tag, fields f, diff_t n) noexcept { - return impl::n_hour(f.y, f.m, f.d + n / 24, 0, f.hh + n % 24, f.mm, f.ss); -} -CONSTEXPR_F fields step(day_tag, fields f, diff_t n) noexcept { - return impl::n_day(f.y, f.m, f.d, n, f.hh, f.mm, f.ss); -} -CONSTEXPR_F fields step(month_tag, fields f, diff_t n) noexcept { - return impl::n_mon(f.y + n / 12, f.m + n % 12, f.d, 0, f.hh, f.mm, f.ss); -} -CONSTEXPR_F fields step(year_tag, fields f, diff_t n) noexcept { - return fields(f.y + n, f.m, f.d, f.hh, f.mm, f.ss); -} - -//////////////////////////////////////////////////////////////////////// - -namespace impl { - -// Returns (v * f + a) but avoiding intermediate overflow when possible. -CONSTEXPR_F diff_t scale_add(diff_t v, diff_t f, diff_t a) noexcept { - return (v < 0) ? ((v + 1) * f + a) - f : ((v - 1) * f + a) + f; -} - -// Map a (normalized) Y/M/D to the number of days before/after 1970-01-01. -// Probably overflows for years outside [-292277022656:292277026595]. -CONSTEXPR_F diff_t ymd_ord(year_t y, month_t m, day_t d) noexcept { - const diff_t eyear = (m <= 2) ? y - 1 : y; - const diff_t era = (eyear >= 0 ? eyear : eyear - 399) / 400; - const diff_t yoe = eyear - era * 400; - const diff_t doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; - const diff_t doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; - return era * 146097 + doe - 719468; -} - -// Returns the difference in days between two normalized Y-M-D tuples. -// ymd_ord() will encounter integer overflow given extreme year values, -// yet the difference between two such extreme values may actually be -// small, so we take a little care to avoid overflow when possible by -// exploiting the 146097-day cycle. + cd += hh / 24; + hh %= 24; + if (hh < 0) { + cd -= 1; + hh += 24; + } + return n_mon(y, m, d, cd, static_cast<hour_t>(hh), mm, ss); +} +CONSTEXPR_F fields n_min(year_t y, diff_t m, diff_t d, diff_t hh, diff_t ch, + diff_t mm, second_t ss) noexcept { + ch += mm / 60; + mm %= 60; + if (mm < 0) { + ch -= 1; + mm += 60; + } + return n_hour(y, m, d, hh / 24 + ch / 24, hh % 24 + ch % 24, + static_cast<minute_t>(mm), ss); +} +CONSTEXPR_F fields n_sec(year_t y, diff_t m, diff_t d, diff_t hh, diff_t mm, + diff_t ss) noexcept { + // Optimization for when (non-constexpr) fields are already normalized. + if (0 <= ss && ss < 60) { + const second_t nss = static_cast<second_t>(ss); + if (0 <= mm && mm < 60) { + const minute_t nmm = static_cast<minute_t>(mm); + if (0 <= hh && hh < 24) { + const hour_t nhh = static_cast<hour_t>(hh); + if (1 <= d && d <= 28 && 1 <= m && m <= 12) { + const day_t nd = static_cast<day_t>(d); + const month_t nm = static_cast<month_t>(m); + return fields(y, nm, nd, nhh, nmm, nss); + } + return n_mon(y, m, d, 0, nhh, nmm, nss); + } + return n_hour(y, m, d, hh / 24, hh % 24, nmm, nss); + } + return n_min(y, m, d, hh, mm / 60, mm % 60, nss); + } + diff_t cm = ss / 60; + ss %= 60; + if (ss < 0) { + cm -= 1; + ss += 60; + } + return n_min(y, m, d, hh, mm / 60 + cm / 60, mm % 60 + cm % 60, + static_cast<second_t>(ss)); +} + +} // namespace impl + +//////////////////////////////////////////////////////////////////////// + +// Increments the indicated (normalized) field by "n". +CONSTEXPR_F fields step(second_tag, fields f, diff_t n) noexcept { + return impl::n_sec(f.y, f.m, f.d, f.hh, f.mm + n / 60, f.ss + n % 60); +} +CONSTEXPR_F fields step(minute_tag, fields f, diff_t n) noexcept { + return impl::n_min(f.y, f.m, f.d, f.hh + n / 60, 0, f.mm + n % 60, f.ss); +} +CONSTEXPR_F fields step(hour_tag, fields f, diff_t n) noexcept { + return impl::n_hour(f.y, f.m, f.d + n / 24, 0, f.hh + n % 24, f.mm, f.ss); +} +CONSTEXPR_F fields step(day_tag, fields f, diff_t n) noexcept { + return impl::n_day(f.y, f.m, f.d, n, f.hh, f.mm, f.ss); +} +CONSTEXPR_F fields step(month_tag, fields f, diff_t n) noexcept { + return impl::n_mon(f.y + n / 12, f.m + n % 12, f.d, 0, f.hh, f.mm, f.ss); +} +CONSTEXPR_F fields step(year_tag, fields f, diff_t n) noexcept { + return fields(f.y + n, f.m, f.d, f.hh, f.mm, f.ss); +} + +//////////////////////////////////////////////////////////////////////// + +namespace impl { + +// Returns (v * f + a) but avoiding intermediate overflow when possible. +CONSTEXPR_F diff_t scale_add(diff_t v, diff_t f, diff_t a) noexcept { + return (v < 0) ? ((v + 1) * f + a) - f : ((v - 1) * f + a) + f; +} + +// Map a (normalized) Y/M/D to the number of days before/after 1970-01-01. +// Probably overflows for years outside [-292277022656:292277026595]. +CONSTEXPR_F diff_t ymd_ord(year_t y, month_t m, day_t d) noexcept { + const diff_t eyear = (m <= 2) ? y - 1 : y; + const diff_t era = (eyear >= 0 ? eyear : eyear - 399) / 400; + const diff_t yoe = eyear - era * 400; + const diff_t doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; + const diff_t doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; + return era * 146097 + doe - 719468; +} + +// Returns the difference in days between two normalized Y-M-D tuples. +// ymd_ord() will encounter integer overflow given extreme year values, +// yet the difference between two such extreme values may actually be +// small, so we take a little care to avoid overflow when possible by +// exploiting the 146097-day cycle. CONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1, year_t y2, month_t m2, day_t d2) noexcept { - const diff_t a_c4_off = y1 % 400; - const diff_t b_c4_off = y2 % 400; - diff_t c4_diff = (y1 - a_c4_off) - (y2 - b_c4_off); - diff_t delta = ymd_ord(a_c4_off, m1, d1) - ymd_ord(b_c4_off, m2, d2); - if (c4_diff > 0 && delta < 0) { - delta += 2 * 146097; - c4_diff -= 2 * 400; - } else if (c4_diff < 0 && delta > 0) { - delta -= 2 * 146097; - c4_diff += 2 * 400; - } - return (c4_diff / 400 * 146097) + delta; -} - -} // namespace impl - -// Returns the difference between fields structs using the indicated unit. -CONSTEXPR_F diff_t difference(year_tag, fields f1, fields f2) noexcept { - return f1.y - f2.y; -} -CONSTEXPR_F diff_t difference(month_tag, fields f1, fields f2) noexcept { - return impl::scale_add(difference(year_tag{}, f1, f2), 12, (f1.m - f2.m)); -} -CONSTEXPR_F diff_t difference(day_tag, fields f1, fields f2) noexcept { - return impl::day_difference(f1.y, f1.m, f1.d, f2.y, f2.m, f2.d); -} -CONSTEXPR_F diff_t difference(hour_tag, fields f1, fields f2) noexcept { - return impl::scale_add(difference(day_tag{}, f1, f2), 24, (f1.hh - f2.hh)); -} -CONSTEXPR_F diff_t difference(minute_tag, fields f1, fields f2) noexcept { - return impl::scale_add(difference(hour_tag{}, f1, f2), 60, (f1.mm - f2.mm)); -} -CONSTEXPR_F diff_t difference(second_tag, fields f1, fields f2) noexcept { - return impl::scale_add(difference(minute_tag{}, f1, f2), 60, f1.ss - f2.ss); -} - -//////////////////////////////////////////////////////////////////////// - -// Aligns the (normalized) fields struct to the indicated field. + const diff_t a_c4_off = y1 % 400; + const diff_t b_c4_off = y2 % 400; + diff_t c4_diff = (y1 - a_c4_off) - (y2 - b_c4_off); + diff_t delta = ymd_ord(a_c4_off, m1, d1) - ymd_ord(b_c4_off, m2, d2); + if (c4_diff > 0 && delta < 0) { + delta += 2 * 146097; + c4_diff -= 2 * 400; + } else if (c4_diff < 0 && delta > 0) { + delta -= 2 * 146097; + c4_diff += 2 * 400; + } + return (c4_diff / 400 * 146097) + delta; +} + +} // namespace impl + +// Returns the difference between fields structs using the indicated unit. +CONSTEXPR_F diff_t difference(year_tag, fields f1, fields f2) noexcept { + return f1.y - f2.y; +} +CONSTEXPR_F diff_t difference(month_tag, fields f1, fields f2) noexcept { + return impl::scale_add(difference(year_tag{}, f1, f2), 12, (f1.m - f2.m)); +} +CONSTEXPR_F diff_t difference(day_tag, fields f1, fields f2) noexcept { + return impl::day_difference(f1.y, f1.m, f1.d, f2.y, f2.m, f2.d); +} +CONSTEXPR_F diff_t difference(hour_tag, fields f1, fields f2) noexcept { + return impl::scale_add(difference(day_tag{}, f1, f2), 24, (f1.hh - f2.hh)); +} +CONSTEXPR_F diff_t difference(minute_tag, fields f1, fields f2) noexcept { + return impl::scale_add(difference(hour_tag{}, f1, f2), 60, (f1.mm - f2.mm)); +} +CONSTEXPR_F diff_t difference(second_tag, fields f1, fields f2) noexcept { + return impl::scale_add(difference(minute_tag{}, f1, f2), 60, f1.ss - f2.ss); +} + +//////////////////////////////////////////////////////////////////////// + +// Aligns the (normalized) fields struct to the indicated field. CONSTEXPR_F fields align(second_tag, fields f) noexcept { return f; } -CONSTEXPR_F fields align(minute_tag, fields f) noexcept { - return fields{f.y, f.m, f.d, f.hh, f.mm, 0}; -} -CONSTEXPR_F fields align(hour_tag, fields f) noexcept { - return fields{f.y, f.m, f.d, f.hh, 0, 0}; -} -CONSTEXPR_F fields align(day_tag, fields f) noexcept { - return fields{f.y, f.m, f.d, 0, 0, 0}; -} -CONSTEXPR_F fields align(month_tag, fields f) noexcept { - return fields{f.y, f.m, 1, 0, 0, 0}; -} -CONSTEXPR_F fields align(year_tag, fields f) noexcept { - return fields{f.y, 1, 1, 0, 0, 0}; -} - -//////////////////////////////////////////////////////////////////////// - -namespace impl { - -template <typename H> -H AbslHashValueImpl(second_tag, H h, fields f) { - return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm, f.ss); -} -template <typename H> -H AbslHashValueImpl(minute_tag, H h, fields f) { - return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm); -} -template <typename H> -H AbslHashValueImpl(hour_tag, H h, fields f) { - return H::combine(std::move(h), f.y, f.m, f.d, f.hh); -} -template <typename H> -H AbslHashValueImpl(day_tag, H h, fields f) { - return H::combine(std::move(h), f.y, f.m, f.d); -} -template <typename H> -H AbslHashValueImpl(month_tag, H h, fields f) { - return H::combine(std::move(h), f.y, f.m); -} -template <typename H> -H AbslHashValueImpl(year_tag, H h, fields f) { - return H::combine(std::move(h), f.y); -} - -} // namespace impl - -//////////////////////////////////////////////////////////////////////// - -template <typename T> -class civil_time { - public: - explicit CONSTEXPR_M civil_time(year_t y, diff_t m = 1, diff_t d = 1, - diff_t hh = 0, diff_t mm = 0, - diff_t ss = 0) noexcept - : civil_time(impl::n_sec(y, m, d, hh, mm, ss)) {} - - CONSTEXPR_M civil_time() noexcept : f_{1970, 1, 1, 0, 0, 0} {} - civil_time(const civil_time&) = default; - civil_time& operator=(const civil_time&) = default; - - // Conversion between civil times of different alignment. Conversion to - // a more precise alignment is allowed implicitly (e.g., day -> hour), - // but conversion where information is discarded must be explicit - // (e.g., second -> minute). - template <typename U, typename S> - using preserves_data = - typename std::enable_if<std::is_base_of<U, S>::value>::type; - template <typename U> - CONSTEXPR_M civil_time(const civil_time<U>& ct, - preserves_data<T, U>* = nullptr) noexcept - : civil_time(ct.f_) {} - template <typename U> - explicit CONSTEXPR_M civil_time(const civil_time<U>& ct, - preserves_data<U, T>* = nullptr) noexcept - : civil_time(ct.f_) {} - - // Factories for the maximum/minimum representable civil_time. +CONSTEXPR_F fields align(minute_tag, fields f) noexcept { + return fields{f.y, f.m, f.d, f.hh, f.mm, 0}; +} +CONSTEXPR_F fields align(hour_tag, fields f) noexcept { + return fields{f.y, f.m, f.d, f.hh, 0, 0}; +} +CONSTEXPR_F fields align(day_tag, fields f) noexcept { + return fields{f.y, f.m, f.d, 0, 0, 0}; +} +CONSTEXPR_F fields align(month_tag, fields f) noexcept { + return fields{f.y, f.m, 1, 0, 0, 0}; +} +CONSTEXPR_F fields align(year_tag, fields f) noexcept { + return fields{f.y, 1, 1, 0, 0, 0}; +} + +//////////////////////////////////////////////////////////////////////// + +namespace impl { + +template <typename H> +H AbslHashValueImpl(second_tag, H h, fields f) { + return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm, f.ss); +} +template <typename H> +H AbslHashValueImpl(minute_tag, H h, fields f) { + return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm); +} +template <typename H> +H AbslHashValueImpl(hour_tag, H h, fields f) { + return H::combine(std::move(h), f.y, f.m, f.d, f.hh); +} +template <typename H> +H AbslHashValueImpl(day_tag, H h, fields f) { + return H::combine(std::move(h), f.y, f.m, f.d); +} +template <typename H> +H AbslHashValueImpl(month_tag, H h, fields f) { + return H::combine(std::move(h), f.y, f.m); +} +template <typename H> +H AbslHashValueImpl(year_tag, H h, fields f) { + return H::combine(std::move(h), f.y); +} + +} // namespace impl + +//////////////////////////////////////////////////////////////////////// + +template <typename T> +class civil_time { + public: + explicit CONSTEXPR_M civil_time(year_t y, diff_t m = 1, diff_t d = 1, + diff_t hh = 0, diff_t mm = 0, + diff_t ss = 0) noexcept + : civil_time(impl::n_sec(y, m, d, hh, mm, ss)) {} + + CONSTEXPR_M civil_time() noexcept : f_{1970, 1, 1, 0, 0, 0} {} + civil_time(const civil_time&) = default; + civil_time& operator=(const civil_time&) = default; + + // Conversion between civil times of different alignment. Conversion to + // a more precise alignment is allowed implicitly (e.g., day -> hour), + // but conversion where information is discarded must be explicit + // (e.g., second -> minute). + template <typename U, typename S> + using preserves_data = + typename std::enable_if<std::is_base_of<U, S>::value>::type; + template <typename U> + CONSTEXPR_M civil_time(const civil_time<U>& ct, + preserves_data<T, U>* = nullptr) noexcept + : civil_time(ct.f_) {} + template <typename U> + explicit CONSTEXPR_M civil_time(const civil_time<U>& ct, + preserves_data<U, T>* = nullptr) noexcept + : civil_time(ct.f_) {} + + // Factories for the maximum/minimum representable civil_time. static CONSTEXPR_F civil_time(max)() { - const auto max_year = (std::numeric_limits<std::int_least64_t>::max)(); - return civil_time(max_year, 12, 31, 23, 59, 59); - } + const auto max_year = (std::numeric_limits<std::int_least64_t>::max)(); + return civil_time(max_year, 12, 31, 23, 59, 59); + } static CONSTEXPR_F civil_time(min)() { - const auto min_year = (std::numeric_limits<std::int_least64_t>::min)(); - return civil_time(min_year, 1, 1, 0, 0, 0); - } - - // Field accessors. Note: All but year() return an int. - CONSTEXPR_M year_t year() const noexcept { return f_.y; } - CONSTEXPR_M int month() const noexcept { return f_.m; } - CONSTEXPR_M int day() const noexcept { return f_.d; } - CONSTEXPR_M int hour() const noexcept { return f_.hh; } - CONSTEXPR_M int minute() const noexcept { return f_.mm; } - CONSTEXPR_M int second() const noexcept { return f_.ss; } - - // Assigning arithmetic. - CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept { + const auto min_year = (std::numeric_limits<std::int_least64_t>::min)(); + return civil_time(min_year, 1, 1, 0, 0, 0); + } + + // Field accessors. Note: All but year() return an int. + CONSTEXPR_M year_t year() const noexcept { return f_.y; } + CONSTEXPR_M int month() const noexcept { return f_.m; } + CONSTEXPR_M int day() const noexcept { return f_.d; } + CONSTEXPR_M int hour() const noexcept { return f_.hh; } + CONSTEXPR_M int minute() const noexcept { return f_.mm; } + CONSTEXPR_M int second() const noexcept { return f_.ss; } + + // Assigning arithmetic. + CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept { return *this = *this + n; - } - CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept { + } + CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept { return *this = *this - n; - } + } CONSTEXPR_M civil_time& operator++() noexcept { return *this += 1; } - CONSTEXPR_M civil_time operator++(int) noexcept { - const civil_time a = *this; - ++*this; - return a; - } + CONSTEXPR_M civil_time operator++(int) noexcept { + const civil_time a = *this; + ++*this; + return a; + } CONSTEXPR_M civil_time& operator--() noexcept { return *this -= 1; } - CONSTEXPR_M civil_time operator--(int) noexcept { - const civil_time a = *this; - --*this; - return a; - } - - // Binary arithmetic operators. - friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept { + CONSTEXPR_M civil_time operator--(int) noexcept { + const civil_time a = *this; + --*this; + return a; + } + + // Binary arithmetic operators. + friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept { return civil_time(step(T{}, a.f_, n)); - } - friend CONSTEXPR_F civil_time operator+(diff_t n, civil_time a) noexcept { + } + friend CONSTEXPR_F civil_time operator+(diff_t n, civil_time a) noexcept { return a + n; - } - friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept { + } + friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept { return n != (std::numeric_limits<diff_t>::min)() ? civil_time(step(T{}, a.f_, -n)) : civil_time(step(T{}, step(T{}, a.f_, -(n + 1)), 1)); - } - friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept { - return difference(T{}, lhs.f_, rhs.f_); - } - - template <typename H> - friend H AbslHashValue(H h, civil_time a) { - return impl::AbslHashValueImpl(T{}, std::move(h), a.f_); - } - - private: - // All instantiations of this template are allowed to call the following - // private constructor and access the private fields member. - template <typename U> - friend class civil_time; - - // The designated constructor that all others eventually call. - explicit CONSTEXPR_M civil_time(fields f) noexcept : f_(align(T{}, f)) {} - - fields f_; -}; - -// Disallows difference between differently aligned types. -// auto n = civil_day(...) - civil_hour(...); // would be confusing. -template <typename T, typename U> -CONSTEXPR_F diff_t operator-(civil_time<T>, civil_time<U>) = delete; - -using civil_year = civil_time<year_tag>; -using civil_month = civil_time<month_tag>; -using civil_day = civil_time<day_tag>; -using civil_hour = civil_time<hour_tag>; -using civil_minute = civil_time<minute_tag>; -using civil_second = civil_time<second_tag>; - -//////////////////////////////////////////////////////////////////////// - -// Relational operators that work with differently aligned objects. -// Always compares all six fields. -template <typename T1, typename T2> -CONSTEXPR_F bool operator<(const civil_time<T1>& lhs, - const civil_time<T2>& rhs) noexcept { + } + friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept { + return difference(T{}, lhs.f_, rhs.f_); + } + + template <typename H> + friend H AbslHashValue(H h, civil_time a) { + return impl::AbslHashValueImpl(T{}, std::move(h), a.f_); + } + + private: + // All instantiations of this template are allowed to call the following + // private constructor and access the private fields member. + template <typename U> + friend class civil_time; + + // The designated constructor that all others eventually call. + explicit CONSTEXPR_M civil_time(fields f) noexcept : f_(align(T{}, f)) {} + + fields f_; +}; + +// Disallows difference between differently aligned types. +// auto n = civil_day(...) - civil_hour(...); // would be confusing. +template <typename T, typename U> +CONSTEXPR_F diff_t operator-(civil_time<T>, civil_time<U>) = delete; + +using civil_year = civil_time<year_tag>; +using civil_month = civil_time<month_tag>; +using civil_day = civil_time<day_tag>; +using civil_hour = civil_time<hour_tag>; +using civil_minute = civil_time<minute_tag>; +using civil_second = civil_time<second_tag>; + +//////////////////////////////////////////////////////////////////////// + +// Relational operators that work with differently aligned objects. +// Always compares all six fields. +template <typename T1, typename T2> +CONSTEXPR_F bool operator<(const civil_time<T1>& lhs, + const civil_time<T2>& rhs) noexcept { return ( lhs.year() < rhs.year() || (lhs.year() == rhs.year() && @@ -497,132 +497,132 @@ CONSTEXPR_F bool operator<(const civil_time<T1>& lhs, (lhs.minute() < rhs.minute() || (lhs.minute() == rhs.minute() && (lhs.second() < rhs.second()))))))))))); -} -template <typename T1, typename T2> -CONSTEXPR_F bool operator<=(const civil_time<T1>& lhs, - const civil_time<T2>& rhs) noexcept { - return !(rhs < lhs); -} -template <typename T1, typename T2> -CONSTEXPR_F bool operator>=(const civil_time<T1>& lhs, - const civil_time<T2>& rhs) noexcept { - return !(lhs < rhs); -} -template <typename T1, typename T2> -CONSTEXPR_F bool operator>(const civil_time<T1>& lhs, - const civil_time<T2>& rhs) noexcept { - return rhs < lhs; -} -template <typename T1, typename T2> -CONSTEXPR_F bool operator==(const civil_time<T1>& lhs, - const civil_time<T2>& rhs) noexcept { - return lhs.year() == rhs.year() && lhs.month() == rhs.month() && - lhs.day() == rhs.day() && lhs.hour() == rhs.hour() && - lhs.minute() == rhs.minute() && lhs.second() == rhs.second(); -} -template <typename T1, typename T2> -CONSTEXPR_F bool operator!=(const civil_time<T1>& lhs, - const civil_time<T2>& rhs) noexcept { - return !(lhs == rhs); -} - -//////////////////////////////////////////////////////////////////////// - -enum class weekday { - monday, - tuesday, - wednesday, - thursday, - friday, - saturday, - sunday, -}; - -CONSTEXPR_F weekday get_weekday(const civil_second& cs) noexcept { - CONSTEXPR_D weekday k_weekday_by_mon_off[13] = { - weekday::monday, weekday::tuesday, weekday::wednesday, - weekday::thursday, weekday::friday, weekday::saturday, - weekday::sunday, weekday::monday, weekday::tuesday, - weekday::wednesday, weekday::thursday, weekday::friday, - weekday::saturday, - }; - CONSTEXPR_D int k_weekday_offsets[1 + 12] = { - -1, 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4, - }; - year_t wd = 2400 + (cs.year() % 400) - (cs.month() < 3); - wd += wd / 4 - wd / 100 + wd / 400; - wd += k_weekday_offsets[cs.month()] + cs.day(); - return k_weekday_by_mon_off[wd % 7 + 6]; -} - -//////////////////////////////////////////////////////////////////////// - -CONSTEXPR_F civil_day next_weekday(civil_day cd, weekday wd) noexcept { - CONSTEXPR_D weekday k_weekdays_forw[14] = { - weekday::monday, weekday::tuesday, weekday::wednesday, - weekday::thursday, weekday::friday, weekday::saturday, - weekday::sunday, weekday::monday, weekday::tuesday, - weekday::wednesday, weekday::thursday, weekday::friday, - weekday::saturday, weekday::sunday, - }; - weekday base = get_weekday(cd); - for (int i = 0;; ++i) { - if (base == k_weekdays_forw[i]) { - for (int j = i + 1;; ++j) { - if (wd == k_weekdays_forw[j]) { - return cd + (j - i); - } - } - } - } -} - -CONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept { - CONSTEXPR_D weekday k_weekdays_back[14] = { - weekday::sunday, weekday::saturday, weekday::friday, - weekday::thursday, weekday::wednesday, weekday::tuesday, - weekday::monday, weekday::sunday, weekday::saturday, - weekday::friday, weekday::thursday, weekday::wednesday, - weekday::tuesday, weekday::monday, - }; - weekday base = get_weekday(cd); - for (int i = 0;; ++i) { - if (base == k_weekdays_back[i]) { - for (int j = i + 1;; ++j) { - if (wd == k_weekdays_back[j]) { - return cd - (j - i); - } - } - } - } -} - -CONSTEXPR_F int get_yearday(const civil_second& cs) noexcept { - CONSTEXPR_D int k_month_offsets[1 + 12] = { - -1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, - }; - const int feb29 = (cs.month() > 2 && impl::is_leap_year(cs.year())); - return k_month_offsets[cs.month()] + feb29 + cs.day(); -} - -//////////////////////////////////////////////////////////////////////// - -std::ostream& operator<<(std::ostream& os, const civil_year& y); -std::ostream& operator<<(std::ostream& os, const civil_month& m); -std::ostream& operator<<(std::ostream& os, const civil_day& d); -std::ostream& operator<<(std::ostream& os, const civil_hour& h); -std::ostream& operator<<(std::ostream& os, const civil_minute& m); -std::ostream& operator<<(std::ostream& os, const civil_second& s); -std::ostream& operator<<(std::ostream& os, weekday wd); - -} // namespace detail -} // namespace cctz -} // namespace time_internal +} +template <typename T1, typename T2> +CONSTEXPR_F bool operator<=(const civil_time<T1>& lhs, + const civil_time<T2>& rhs) noexcept { + return !(rhs < lhs); +} +template <typename T1, typename T2> +CONSTEXPR_F bool operator>=(const civil_time<T1>& lhs, + const civil_time<T2>& rhs) noexcept { + return !(lhs < rhs); +} +template <typename T1, typename T2> +CONSTEXPR_F bool operator>(const civil_time<T1>& lhs, + const civil_time<T2>& rhs) noexcept { + return rhs < lhs; +} +template <typename T1, typename T2> +CONSTEXPR_F bool operator==(const civil_time<T1>& lhs, + const civil_time<T2>& rhs) noexcept { + return lhs.year() == rhs.year() && lhs.month() == rhs.month() && + lhs.day() == rhs.day() && lhs.hour() == rhs.hour() && + lhs.minute() == rhs.minute() && lhs.second() == rhs.second(); +} +template <typename T1, typename T2> +CONSTEXPR_F bool operator!=(const civil_time<T1>& lhs, + const civil_time<T2>& rhs) noexcept { + return !(lhs == rhs); +} + +//////////////////////////////////////////////////////////////////////// + +enum class weekday { + monday, + tuesday, + wednesday, + thursday, + friday, + saturday, + sunday, +}; + +CONSTEXPR_F weekday get_weekday(const civil_second& cs) noexcept { + CONSTEXPR_D weekday k_weekday_by_mon_off[13] = { + weekday::monday, weekday::tuesday, weekday::wednesday, + weekday::thursday, weekday::friday, weekday::saturday, + weekday::sunday, weekday::monday, weekday::tuesday, + weekday::wednesday, weekday::thursday, weekday::friday, + weekday::saturday, + }; + CONSTEXPR_D int k_weekday_offsets[1 + 12] = { + -1, 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4, + }; + year_t wd = 2400 + (cs.year() % 400) - (cs.month() < 3); + wd += wd / 4 - wd / 100 + wd / 400; + wd += k_weekday_offsets[cs.month()] + cs.day(); + return k_weekday_by_mon_off[wd % 7 + 6]; +} + +//////////////////////////////////////////////////////////////////////// + +CONSTEXPR_F civil_day next_weekday(civil_day cd, weekday wd) noexcept { + CONSTEXPR_D weekday k_weekdays_forw[14] = { + weekday::monday, weekday::tuesday, weekday::wednesday, + weekday::thursday, weekday::friday, weekday::saturday, + weekday::sunday, weekday::monday, weekday::tuesday, + weekday::wednesday, weekday::thursday, weekday::friday, + weekday::saturday, weekday::sunday, + }; + weekday base = get_weekday(cd); + for (int i = 0;; ++i) { + if (base == k_weekdays_forw[i]) { + for (int j = i + 1;; ++j) { + if (wd == k_weekdays_forw[j]) { + return cd + (j - i); + } + } + } + } +} + +CONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept { + CONSTEXPR_D weekday k_weekdays_back[14] = { + weekday::sunday, weekday::saturday, weekday::friday, + weekday::thursday, weekday::wednesday, weekday::tuesday, + weekday::monday, weekday::sunday, weekday::saturday, + weekday::friday, weekday::thursday, weekday::wednesday, + weekday::tuesday, weekday::monday, + }; + weekday base = get_weekday(cd); + for (int i = 0;; ++i) { + if (base == k_weekdays_back[i]) { + for (int j = i + 1;; ++j) { + if (wd == k_weekdays_back[j]) { + return cd - (j - i); + } + } + } + } +} + +CONSTEXPR_F int get_yearday(const civil_second& cs) noexcept { + CONSTEXPR_D int k_month_offsets[1 + 12] = { + -1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, + }; + const int feb29 = (cs.month() > 2 && impl::is_leap_year(cs.year())); + return k_month_offsets[cs.month()] + feb29 + cs.day(); +} + +//////////////////////////////////////////////////////////////////////// + +std::ostream& operator<<(std::ostream& os, const civil_year& y); +std::ostream& operator<<(std::ostream& os, const civil_month& m); +std::ostream& operator<<(std::ostream& os, const civil_day& d); +std::ostream& operator<<(std::ostream& os, const civil_hour& h); +std::ostream& operator<<(std::ostream& os, const civil_minute& m); +std::ostream& operator<<(std::ostream& os, const civil_second& s); +std::ostream& operator<<(std::ostream& os, weekday wd); + +} // namespace detail +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - -#undef CONSTEXPR_M -#undef CONSTEXPR_F -#undef CONSTEXPR_D - -#endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_ + +#undef CONSTEXPR_M +#undef CONSTEXPR_F +#undef CONSTEXPR_D + +#endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/time_zone.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/time_zone.h index 8026041c62..524654df4b 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/time_zone.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/time_zone.h @@ -1,272 +1,272 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// A library for translating between absolute times (represented by -// std::chrono::time_points of the std::chrono::system_clock) and civil -// times (represented by cctz::civil_second) using the rules defined by -// a time zone (cctz::time_zone). - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ - -#include <chrono> -#include <cstdint> +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// A library for translating between absolute times (represented by +// std::chrono::time_points of the std::chrono::system_clock) and civil +// times (represented by cctz::civil_second) using the rules defined by +// a time zone (cctz::time_zone). + +#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ +#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ + +#include <chrono> +#include <cstdint> #include <limits> #include <util/generic/string.h> -#include <utility> - +#include <utility> + #include "y_absl/base/config.h" #include "y_absl/time/internal/cctz/include/cctz/civil_time.h" - + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// Convenience aliases. Not intended as public API points. -template <typename D> -using time_point = std::chrono::time_point<std::chrono::system_clock, D>; -using seconds = std::chrono::duration<std::int_fast64_t>; -using sys_seconds = seconds; // Deprecated. Use cctz::seconds instead. - -namespace detail { -template <typename D> +namespace time_internal { +namespace cctz { + +// Convenience aliases. Not intended as public API points. +template <typename D> +using time_point = std::chrono::time_point<std::chrono::system_clock, D>; +using seconds = std::chrono::duration<std::int_fast64_t>; +using sys_seconds = seconds; // Deprecated. Use cctz::seconds instead. + +namespace detail { +template <typename D> std::pair<time_point<seconds>, D> split_seconds(const time_point<D>& tp); std::pair<time_point<seconds>, seconds> split_seconds( const time_point<seconds>& tp); -} // namespace detail - -// cctz::time_zone is an opaque, small, value-type class representing a -// geo-political region within which particular rules are used for mapping -// between absolute and civil times. Time zones are named using the TZ -// identifiers from the IANA Time Zone Database, such as "America/Los_Angeles" -// or "Australia/Sydney". Time zones are created from factory functions such -// as load_time_zone(). Note: strings like "PST" and "EDT" are not valid TZ -// identifiers. -// -// Example: -// cctz::time_zone utc = cctz::utc_time_zone(); -// cctz::time_zone pst = cctz::fixed_time_zone(std::chrono::hours(-8)); -// cctz::time_zone loc = cctz::local_time_zone(); -// cctz::time_zone lax; -// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } -// -// See also: -// - http://www.iana.org/time-zones -// - https://en.wikipedia.org/wiki/Zoneinfo -class time_zone { - public: - time_zone() : time_zone(nullptr) {} // Equivalent to UTC - time_zone(const time_zone&) = default; - time_zone& operator=(const time_zone&) = default; - +} // namespace detail + +// cctz::time_zone is an opaque, small, value-type class representing a +// geo-political region within which particular rules are used for mapping +// between absolute and civil times. Time zones are named using the TZ +// identifiers from the IANA Time Zone Database, such as "America/Los_Angeles" +// or "Australia/Sydney". Time zones are created from factory functions such +// as load_time_zone(). Note: strings like "PST" and "EDT" are not valid TZ +// identifiers. +// +// Example: +// cctz::time_zone utc = cctz::utc_time_zone(); +// cctz::time_zone pst = cctz::fixed_time_zone(std::chrono::hours(-8)); +// cctz::time_zone loc = cctz::local_time_zone(); +// cctz::time_zone lax; +// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } +// +// See also: +// - http://www.iana.org/time-zones +// - https://en.wikipedia.org/wiki/Zoneinfo +class time_zone { + public: + time_zone() : time_zone(nullptr) {} // Equivalent to UTC + time_zone(const time_zone&) = default; + time_zone& operator=(const time_zone&) = default; + TString name() const; - - // An absolute_lookup represents the civil time (cctz::civil_second) within - // this time_zone at the given absolute time (time_point). There are - // additionally a few other fields that may be useful when working with - // older APIs, such as std::tm. - // - // Example: - // const cctz::time_zone tz = ... - // const auto tp = std::chrono::system_clock::now(); - // const cctz::time_zone::absolute_lookup al = tz.lookup(tp); - struct absolute_lookup { - civil_second cs; - // Note: The following fields exist for backward compatibility with older - // APIs. Accessing these fields directly is a sign of imprudent logic in - // the calling code. Modern time-related code should only access this data - // indirectly by way of cctz::format(). - int offset; // civil seconds east of UTC - bool is_dst; // is offset non-standard? - const char* abbr; // time-zone abbreviation (e.g., "PST") - }; - absolute_lookup lookup(const time_point<seconds>& tp) const; - template <typename D> - absolute_lookup lookup(const time_point<D>& tp) const { - return lookup(detail::split_seconds(tp).first); - } - - // A civil_lookup represents the absolute time(s) (time_point) that - // correspond to the given civil time (cctz::civil_second) within this - // time_zone. Usually the given civil time represents a unique instant - // in time, in which case the conversion is unambiguous. However, - // within this time zone, the given civil time may be skipped (e.g., - // during a positive UTC offset shift), or repeated (e.g., during a - // negative UTC offset shift). To account for these possibilities, - // civil_lookup is richer than just a single time_point. - // - // In all cases the civil_lookup::kind enum will indicate the nature - // of the given civil-time argument, and the pre, trans, and post - // members will give the absolute time answers using the pre-transition - // offset, the transition point itself, and the post-transition offset, - // respectively (all three times are equal if kind == UNIQUE). If any - // of these three absolute times is outside the representable range of a - // time_point<seconds> the field is set to its maximum/minimum value. - // - // Example: - // cctz::time_zone lax; - // if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } - // - // // A unique civil time. - // auto jan01 = lax.lookup(cctz::civil_second(2011, 1, 1, 0, 0, 0)); - // // jan01.kind == cctz::time_zone::civil_lookup::UNIQUE - // // jan01.pre is 2011/01/01 00:00:00 -0800 - // // jan01.trans is 2011/01/01 00:00:00 -0800 - // // jan01.post is 2011/01/01 00:00:00 -0800 - // - // // A Spring DST transition, when there is a gap in civil time. - // auto mar13 = lax.lookup(cctz::civil_second(2011, 3, 13, 2, 15, 0)); - // // mar13.kind == cctz::time_zone::civil_lookup::SKIPPED - // // mar13.pre is 2011/03/13 03:15:00 -0700 - // // mar13.trans is 2011/03/13 03:00:00 -0700 - // // mar13.post is 2011/03/13 01:15:00 -0800 - // - // // A Fall DST transition, when civil times are repeated. - // auto nov06 = lax.lookup(cctz::civil_second(2011, 11, 6, 1, 15, 0)); - // // nov06.kind == cctz::time_zone::civil_lookup::REPEATED - // // nov06.pre is 2011/11/06 01:15:00 -0700 - // // nov06.trans is 2011/11/06 01:00:00 -0800 - // // nov06.post is 2011/11/06 01:15:00 -0800 - struct civil_lookup { - enum civil_kind { - UNIQUE, // the civil time was singular (pre == trans == post) - SKIPPED, // the civil time did not exist (pre >= trans > post) - REPEATED, // the civil time was ambiguous (pre < trans <= post) - } kind; - time_point<seconds> pre; // uses the pre-transition offset - time_point<seconds> trans; // instant of civil-offset change - time_point<seconds> post; // uses the post-transition offset - }; - civil_lookup lookup(const civil_second& cs) const; - - // Finds the time of the next/previous offset change in this time zone. - // - // By definition, next_transition(tp, &trans) returns false when tp has - // its maximum value, and prev_transition(tp, &trans) returns false - // when tp has its minimum value. If the zone has no transitions, the - // result will also be false no matter what the argument. - // - // Otherwise, when tp has its minimum value, next_transition(tp, &trans) - // returns true and sets trans to the first recorded transition. Chains - // of calls to next_transition()/prev_transition() will eventually return - // false, but it is unspecified exactly when next_transition(tp, &trans) - // jumps to false, or what time is set by prev_transition(tp, &trans) for - // a very distant tp. - // - // Note: Enumeration of time-zone transitions is for informational purposes - // only. Modern time-related code should not care about when offset changes - // occur. - // - // Example: - // cctz::time_zone nyc; - // if (!cctz::load_time_zone("America/New_York", &nyc)) { ... } - // const auto now = std::chrono::system_clock::now(); - // auto tp = cctz::time_point<cctz::seconds>::min(); - // cctz::time_zone::civil_transition trans; - // while (tp <= now && nyc.next_transition(tp, &trans)) { - // // transition: trans.from -> trans.to - // tp = nyc.lookup(trans.to).trans; - // } - struct civil_transition { - civil_second from; // the civil time we jump from - civil_second to; // the civil time we jump to - }; - bool next_transition(const time_point<seconds>& tp, - civil_transition* trans) const; - template <typename D> + + // An absolute_lookup represents the civil time (cctz::civil_second) within + // this time_zone at the given absolute time (time_point). There are + // additionally a few other fields that may be useful when working with + // older APIs, such as std::tm. + // + // Example: + // const cctz::time_zone tz = ... + // const auto tp = std::chrono::system_clock::now(); + // const cctz::time_zone::absolute_lookup al = tz.lookup(tp); + struct absolute_lookup { + civil_second cs; + // Note: The following fields exist for backward compatibility with older + // APIs. Accessing these fields directly is a sign of imprudent logic in + // the calling code. Modern time-related code should only access this data + // indirectly by way of cctz::format(). + int offset; // civil seconds east of UTC + bool is_dst; // is offset non-standard? + const char* abbr; // time-zone abbreviation (e.g., "PST") + }; + absolute_lookup lookup(const time_point<seconds>& tp) const; + template <typename D> + absolute_lookup lookup(const time_point<D>& tp) const { + return lookup(detail::split_seconds(tp).first); + } + + // A civil_lookup represents the absolute time(s) (time_point) that + // correspond to the given civil time (cctz::civil_second) within this + // time_zone. Usually the given civil time represents a unique instant + // in time, in which case the conversion is unambiguous. However, + // within this time zone, the given civil time may be skipped (e.g., + // during a positive UTC offset shift), or repeated (e.g., during a + // negative UTC offset shift). To account for these possibilities, + // civil_lookup is richer than just a single time_point. + // + // In all cases the civil_lookup::kind enum will indicate the nature + // of the given civil-time argument, and the pre, trans, and post + // members will give the absolute time answers using the pre-transition + // offset, the transition point itself, and the post-transition offset, + // respectively (all three times are equal if kind == UNIQUE). If any + // of these three absolute times is outside the representable range of a + // time_point<seconds> the field is set to its maximum/minimum value. + // + // Example: + // cctz::time_zone lax; + // if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } + // + // // A unique civil time. + // auto jan01 = lax.lookup(cctz::civil_second(2011, 1, 1, 0, 0, 0)); + // // jan01.kind == cctz::time_zone::civil_lookup::UNIQUE + // // jan01.pre is 2011/01/01 00:00:00 -0800 + // // jan01.trans is 2011/01/01 00:00:00 -0800 + // // jan01.post is 2011/01/01 00:00:00 -0800 + // + // // A Spring DST transition, when there is a gap in civil time. + // auto mar13 = lax.lookup(cctz::civil_second(2011, 3, 13, 2, 15, 0)); + // // mar13.kind == cctz::time_zone::civil_lookup::SKIPPED + // // mar13.pre is 2011/03/13 03:15:00 -0700 + // // mar13.trans is 2011/03/13 03:00:00 -0700 + // // mar13.post is 2011/03/13 01:15:00 -0800 + // + // // A Fall DST transition, when civil times are repeated. + // auto nov06 = lax.lookup(cctz::civil_second(2011, 11, 6, 1, 15, 0)); + // // nov06.kind == cctz::time_zone::civil_lookup::REPEATED + // // nov06.pre is 2011/11/06 01:15:00 -0700 + // // nov06.trans is 2011/11/06 01:00:00 -0800 + // // nov06.post is 2011/11/06 01:15:00 -0800 + struct civil_lookup { + enum civil_kind { + UNIQUE, // the civil time was singular (pre == trans == post) + SKIPPED, // the civil time did not exist (pre >= trans > post) + REPEATED, // the civil time was ambiguous (pre < trans <= post) + } kind; + time_point<seconds> pre; // uses the pre-transition offset + time_point<seconds> trans; // instant of civil-offset change + time_point<seconds> post; // uses the post-transition offset + }; + civil_lookup lookup(const civil_second& cs) const; + + // Finds the time of the next/previous offset change in this time zone. + // + // By definition, next_transition(tp, &trans) returns false when tp has + // its maximum value, and prev_transition(tp, &trans) returns false + // when tp has its minimum value. If the zone has no transitions, the + // result will also be false no matter what the argument. + // + // Otherwise, when tp has its minimum value, next_transition(tp, &trans) + // returns true and sets trans to the first recorded transition. Chains + // of calls to next_transition()/prev_transition() will eventually return + // false, but it is unspecified exactly when next_transition(tp, &trans) + // jumps to false, or what time is set by prev_transition(tp, &trans) for + // a very distant tp. + // + // Note: Enumeration of time-zone transitions is for informational purposes + // only. Modern time-related code should not care about when offset changes + // occur. + // + // Example: + // cctz::time_zone nyc; + // if (!cctz::load_time_zone("America/New_York", &nyc)) { ... } + // const auto now = std::chrono::system_clock::now(); + // auto tp = cctz::time_point<cctz::seconds>::min(); + // cctz::time_zone::civil_transition trans; + // while (tp <= now && nyc.next_transition(tp, &trans)) { + // // transition: trans.from -> trans.to + // tp = nyc.lookup(trans.to).trans; + // } + struct civil_transition { + civil_second from; // the civil time we jump from + civil_second to; // the civil time we jump to + }; + bool next_transition(const time_point<seconds>& tp, + civil_transition* trans) const; + template <typename D> bool next_transition(const time_point<D>& tp, civil_transition* trans) const { - return next_transition(detail::split_seconds(tp).first, trans); - } - bool prev_transition(const time_point<seconds>& tp, - civil_transition* trans) const; - template <typename D> + return next_transition(detail::split_seconds(tp).first, trans); + } + bool prev_transition(const time_point<seconds>& tp, + civil_transition* trans) const; + template <typename D> bool prev_transition(const time_point<D>& tp, civil_transition* trans) const { - return prev_transition(detail::split_seconds(tp).first, trans); - } - - // version() and description() provide additional information about the - // time zone. The content of each of the returned strings is unspecified, - // however, when the IANA Time Zone Database is the underlying data source + return prev_transition(detail::split_seconds(tp).first, trans); + } + + // version() and description() provide additional information about the + // time zone. The content of each of the returned strings is unspecified, + // however, when the IANA Time Zone Database is the underlying data source // the version() string will be in the familar form (e.g, "2018e") or - // empty when unavailable. - // - // Note: These functions are for informational or testing purposes only. + // empty when unavailable. + // + // Note: These functions are for informational or testing purposes only. TString version() const; // empty when unknown TString description() const; - - // Relational operators. - friend bool operator==(time_zone lhs, time_zone rhs) { - return &lhs.effective_impl() == &rhs.effective_impl(); - } + + // Relational operators. + friend bool operator==(time_zone lhs, time_zone rhs) { + return &lhs.effective_impl() == &rhs.effective_impl(); + } friend bool operator!=(time_zone lhs, time_zone rhs) { return !(lhs == rhs); } - - template <typename H> - friend H AbslHashValue(H h, time_zone tz) { - return H::combine(std::move(h), &tz.effective_impl()); - } - - class Impl; - - private: - explicit time_zone(const Impl* impl) : impl_(impl) {} - const Impl& effective_impl() const; // handles implicit UTC - const Impl* impl_; -}; - -// Loads the named time zone. May perform I/O on the initial load. -// If the name is invalid, or some other kind of error occurs, returns -// false and "*tz" is set to the UTC time zone. + + template <typename H> + friend H AbslHashValue(H h, time_zone tz) { + return H::combine(std::move(h), &tz.effective_impl()); + } + + class Impl; + + private: + explicit time_zone(const Impl* impl) : impl_(impl) {} + const Impl& effective_impl() const; // handles implicit UTC + const Impl* impl_; +}; + +// Loads the named time zone. May perform I/O on the initial load. +// If the name is invalid, or some other kind of error occurs, returns +// false and "*tz" is set to the UTC time zone. bool load_time_zone(const TString& name, time_zone* tz); - -// Returns a time_zone representing UTC. Cannot fail. -time_zone utc_time_zone(); - -// Returns a time zone that is a fixed offset (seconds east) from UTC. -// Note: If the absolute value of the offset is greater than 24 hours -// you'll get UTC (i.e., zero offset) instead. -time_zone fixed_time_zone(const seconds& offset); - -// Returns a time zone representing the local time zone. Falls back to UTC. -// Note: local_time_zone.name() may only be something like "localtime". -time_zone local_time_zone(); - -// Returns the civil time (cctz::civil_second) within the given time zone at -// the given absolute time (time_point). Since the additional fields provided -// by the time_zone::absolute_lookup struct should rarely be needed in modern -// code, this convert() function is simpler and should be preferred. -template <typename D> -inline civil_second convert(const time_point<D>& tp, const time_zone& tz) { - return tz.lookup(tp).cs; -} - -// Returns the absolute time (time_point) that corresponds to the given civil -// time within the given time zone. If the civil time is not unique (i.e., if -// it was either repeated or non-existent), then the returned time_point is -// the best estimate that preserves relative order. That is, this function -// guarantees that if cs1 < cs2, then convert(cs1, tz) <= convert(cs2, tz). -inline time_point<seconds> convert(const civil_second& cs, - const time_zone& tz) { - const time_zone::civil_lookup cl = tz.lookup(cs); - if (cl.kind == time_zone::civil_lookup::SKIPPED) return cl.trans; - return cl.pre; -} - -namespace detail { -using femtoseconds = std::chrono::duration<std::int_fast64_t, std::femto>; + +// Returns a time_zone representing UTC. Cannot fail. +time_zone utc_time_zone(); + +// Returns a time zone that is a fixed offset (seconds east) from UTC. +// Note: If the absolute value of the offset is greater than 24 hours +// you'll get UTC (i.e., zero offset) instead. +time_zone fixed_time_zone(const seconds& offset); + +// Returns a time zone representing the local time zone. Falls back to UTC. +// Note: local_time_zone.name() may only be something like "localtime". +time_zone local_time_zone(); + +// Returns the civil time (cctz::civil_second) within the given time zone at +// the given absolute time (time_point). Since the additional fields provided +// by the time_zone::absolute_lookup struct should rarely be needed in modern +// code, this convert() function is simpler and should be preferred. +template <typename D> +inline civil_second convert(const time_point<D>& tp, const time_zone& tz) { + return tz.lookup(tp).cs; +} + +// Returns the absolute time (time_point) that corresponds to the given civil +// time within the given time zone. If the civil time is not unique (i.e., if +// it was either repeated or non-existent), then the returned time_point is +// the best estimate that preserves relative order. That is, this function +// guarantees that if cs1 < cs2, then convert(cs1, tz) <= convert(cs2, tz). +inline time_point<seconds> convert(const civil_second& cs, + const time_zone& tz) { + const time_zone::civil_lookup cl = tz.lookup(cs); + if (cl.kind == time_zone::civil_lookup::SKIPPED) return cl.trans; + return cl.pre; +} + +namespace detail { +using femtoseconds = std::chrono::duration<std::int_fast64_t, std::femto>; TString format(const TString&, const time_point<seconds>&, - const femtoseconds&, const time_zone&); + const femtoseconds&, const time_zone&); bool parse(const TString&, const TString&, const time_zone&, time_point<seconds>*, femtoseconds*, TString* err = nullptr); template <typename Rep, std::intmax_t Denom> @@ -283,96 +283,96 @@ bool join_seconds( time_point<std::chrono::duration<Rep, std::ratio<1, 1>>>* tpp); bool join_seconds(const time_point<seconds>& sec, const femtoseconds&, time_point<seconds>* tpp); -} // namespace detail - -// Formats the given time_point in the given cctz::time_zone according to -// the provided format string. Uses strftime()-like formatting options, -// with the following extensions: -// -// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm) -// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss) -// - %E#S - Seconds with # digits of fractional precision -// - %E*S - Seconds with full fractional precision (a literal '*') -// - %E#f - Fractional seconds with # digits of precision -// - %E*f - Fractional seconds with full precision (a literal '*') -// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999) +} // namespace detail + +// Formats the given time_point in the given cctz::time_zone according to +// the provided format string. Uses strftime()-like formatting options, +// with the following extensions: +// +// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm) +// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss) +// - %E#S - Seconds with # digits of fractional precision +// - %E*S - Seconds with full fractional precision (a literal '*') +// - %E#f - Fractional seconds with # digits of precision +// - %E*f - Fractional seconds with full precision (a literal '*') +// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999) // - %ET - The RFC3339 "date-time" separator "T" -// -// Note that %E0S behaves like %S, and %E0f produces no characters. In -// contrast %E*f always produces at least one digit, which may be '0'. -// -// Note that %Y produces as many characters as it takes to fully render the -// year. A year outside of [-999:9999] when formatted with %E4Y will produce -// more than four characters, just like %Y. -// -// Tip: Format strings should include the UTC offset (e.g., %z, %Ez, or %E*z) -// so that the resulting string uniquely identifies an absolute time. -// -// Example: -// cctz::time_zone lax; -// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } -// auto tp = cctz::convert(cctz::civil_second(2013, 1, 2, 3, 4, 5), lax); +// +// Note that %E0S behaves like %S, and %E0f produces no characters. In +// contrast %E*f always produces at least one digit, which may be '0'. +// +// Note that %Y produces as many characters as it takes to fully render the +// year. A year outside of [-999:9999] when formatted with %E4Y will produce +// more than four characters, just like %Y. +// +// Tip: Format strings should include the UTC offset (e.g., %z, %Ez, or %E*z) +// so that the resulting string uniquely identifies an absolute time. +// +// Example: +// cctz::time_zone lax; +// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... } +// auto tp = cctz::convert(cctz::civil_second(2013, 1, 2, 3, 4, 5), lax); // TString f = cctz::format("%H:%M:%S", tp, lax); // "03:04:05" -// f = cctz::format("%H:%M:%E3S", tp, lax); // "03:04:05.000" -template <typename D> +// f = cctz::format("%H:%M:%E3S", tp, lax); // "03:04:05.000" +template <typename D> inline TString format(const TString& fmt, const time_point<D>& tp, - const time_zone& tz) { - const auto p = detail::split_seconds(tp); - const auto n = std::chrono::duration_cast<detail::femtoseconds>(p.second); - return detail::format(fmt, p.first, n, tz); -} - -// Parses an input string according to the provided format string and -// returns the corresponding time_point. Uses strftime()-like formatting -// options, with the same extensions as cctz::format(), but with the -// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez + const time_zone& tz) { + const auto p = detail::split_seconds(tp); + const auto n = std::chrono::duration_cast<detail::femtoseconds>(p.second); + return detail::format(fmt, p.first, n, tz); +} + +// Parses an input string according to the provided format string and +// returns the corresponding time_point. Uses strftime()-like formatting +// options, with the same extensions as cctz::format(), but with the +// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez // and %E*z also accept the same inputs, which (along with %z) includes // 'z' and 'Z' as synonyms for +00:00. %ET accepts either 'T' or 't'. -// -// %Y consumes as many numeric characters as it can, so the matching data -// should always be terminated with a non-numeric. %E4Y always consumes -// exactly four characters, including any sign. -// -// Unspecified fields are taken from the default date and time of ... -// -// "1970-01-01 00:00:00.0 +0000" -// -// For example, parsing a string of "15:45" (%H:%M) will return a time_point -// that represents "1970-01-01 15:45:00.0 +0000". -// -// Note that parse() returns time instants, so it makes most sense to parse -// fully-specified date/time strings that include a UTC offset (%z, %Ez, or -// %E*z). -// -// Note also that parse() only heeds the fields year, month, day, hour, -// minute, (fractional) second, and UTC offset. Other fields, like weekday (%a -// or %A), while parsed for syntactic validity, are ignored in the conversion. -// -// Date and time fields that are out-of-range will be treated as errors rather -// than normalizing them like cctz::civil_second() would do. For example, it -// is an error to parse the date "Oct 32, 2013" because 32 is out of range. -// -// A second of ":60" is normalized to ":00" of the following minute with -// fractional seconds discarded. The following table shows how the given -// seconds and subseconds will be parsed: -// -// "59.x" -> 59.x // exact -// "60.x" -> 00.0 // normalized -// "00.x" -> 00.x // exact -// -// Errors are indicated by returning false. -// -// Example: -// const cctz::time_zone tz = ... -// std::chrono::system_clock::time_point tp; -// if (cctz::parse("%Y-%m-%d", "2015-10-09", tz, &tp)) { -// ... -// } -template <typename D> +// +// %Y consumes as many numeric characters as it can, so the matching data +// should always be terminated with a non-numeric. %E4Y always consumes +// exactly four characters, including any sign. +// +// Unspecified fields are taken from the default date and time of ... +// +// "1970-01-01 00:00:00.0 +0000" +// +// For example, parsing a string of "15:45" (%H:%M) will return a time_point +// that represents "1970-01-01 15:45:00.0 +0000". +// +// Note that parse() returns time instants, so it makes most sense to parse +// fully-specified date/time strings that include a UTC offset (%z, %Ez, or +// %E*z). +// +// Note also that parse() only heeds the fields year, month, day, hour, +// minute, (fractional) second, and UTC offset. Other fields, like weekday (%a +// or %A), while parsed for syntactic validity, are ignored in the conversion. +// +// Date and time fields that are out-of-range will be treated as errors rather +// than normalizing them like cctz::civil_second() would do. For example, it +// is an error to parse the date "Oct 32, 2013" because 32 is out of range. +// +// A second of ":60" is normalized to ":00" of the following minute with +// fractional seconds discarded. The following table shows how the given +// seconds and subseconds will be parsed: +// +// "59.x" -> 59.x // exact +// "60.x" -> 00.0 // normalized +// "00.x" -> 00.x // exact +// +// Errors are indicated by returning false. +// +// Example: +// const cctz::time_zone tz = ... +// std::chrono::system_clock::time_point tp; +// if (cctz::parse("%Y-%m-%d", "2015-10-09", tz, &tp)) { +// ... +// } +template <typename D> inline bool parse(const TString& fmt, const TString& input, - const time_zone& tz, time_point<D>* tpp) { - time_point<seconds> sec; - detail::femtoseconds fs; + const time_zone& tz, time_point<D>* tpp) { + time_point<seconds> sec; + detail::femtoseconds fs; return detail::parse(fmt, input, tz, &sec, &fs) && detail::join_seconds(sec, fs, tpp); } @@ -391,10 +391,10 @@ std::pair<time_point<seconds>, D> split_seconds(const time_point<D>& tp) { if (sub.count() < 0) { sec -= seconds(1); sub += seconds(1); - } + } return {sec, std::chrono::duration_cast<D>(sub)}; -} - +} + inline std::pair<time_point<seconds>, seconds> split_seconds( const time_point<seconds>& tp) { return {tp, seconds::zero()}; @@ -451,9 +451,9 @@ inline bool join_seconds(const time_point<seconds>& sec, const femtoseconds&, } } // namespace detail -} // namespace cctz -} // namespace time_internal +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ + +#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/zone_info_source.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/zone_info_source.h index 1786370bc3..fd6dc4bbb0 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/zone_info_source.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/include/cctz/zone_info_source.h @@ -1,102 +1,102 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_ -#define ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_ - -#include <cstddef> -#include <functional> -#include <memory> +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_ +#define ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_ + +#include <cstddef> +#include <functional> +#include <memory> #include <util/generic/string.h> #include "y_absl/base/config.h" namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// A stdio-like interface for providing zoneinfo data for a particular zone. -class ZoneInfoSource { - public: - virtual ~ZoneInfoSource(); - - virtual std::size_t Read(void* ptr, std::size_t size) = 0; // like fread() +namespace time_internal { +namespace cctz { + +// A stdio-like interface for providing zoneinfo data for a particular zone. +class ZoneInfoSource { + public: + virtual ~ZoneInfoSource(); + + virtual std::size_t Read(void* ptr, std::size_t size) = 0; // like fread() virtual int Skip(std::size_t offset) = 0; // like fseek() - - // Until the zoneinfo data supports versioning information, we provide - // a way for a ZoneInfoSource to indicate it out-of-band. The default + + // Until the zoneinfo data supports versioning information, we provide + // a way for a ZoneInfoSource to indicate it out-of-band. The default // implementation returns an empty string. virtual TString Version() const; -}; - -} // namespace cctz -} // namespace time_internal +}; + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz_extension { - -// A function-pointer type for a factory that returns a ZoneInfoSource -// given the name of a time zone and a fallback factory. Returns null -// when the data for the named zone cannot be found. -using ZoneInfoSourceFactory = +namespace time_internal { +namespace cctz_extension { + +// A function-pointer type for a factory that returns a ZoneInfoSource +// given the name of a time zone and a fallback factory. Returns null +// when the data for the named zone cannot be found. +using ZoneInfoSourceFactory = std::unique_ptr<y_absl::time_internal::cctz::ZoneInfoSource> (*)( const TString&, const std::function<std::unique_ptr< y_absl::time_internal::cctz::ZoneInfoSource>(const TString&)>&); - -// The user can control the mapping of zone names to zoneinfo data by -// providing a definition for cctz_extension::zone_info_source_factory. -// For example, given functions my_factory() and my_other_factory() that -// can return a ZoneInfoSource for a named zone, we could inject them into -// cctz::load_time_zone() with: -// -// namespace cctz_extension { -// namespace { -// std::unique_ptr<cctz::ZoneInfoSource> CustomFactory( + +// The user can control the mapping of zone names to zoneinfo data by +// providing a definition for cctz_extension::zone_info_source_factory. +// For example, given functions my_factory() and my_other_factory() that +// can return a ZoneInfoSource for a named zone, we could inject them into +// cctz::load_time_zone() with: +// +// namespace cctz_extension { +// namespace { +// std::unique_ptr<cctz::ZoneInfoSource> CustomFactory( // const TString& name, -// const std::function<std::unique_ptr<cctz::ZoneInfoSource>( +// const std::function<std::unique_ptr<cctz::ZoneInfoSource>( // const TString& name)>& fallback_factory) { -// if (auto zip = my_factory(name)) return zip; -// if (auto zip = fallback_factory(name)) return zip; -// if (auto zip = my_other_factory(name)) return zip; -// return nullptr; -// } -// } // namespace -// ZoneInfoSourceFactory zone_info_source_factory = CustomFactory; -// } // namespace cctz_extension -// -// This might be used, say, to use zoneinfo data embedded in the program, -// or read from a (possibly compressed) file archive, or both. -// -// cctz_extension::zone_info_source_factory() will be called: -// (1) from the same thread as the cctz::load_time_zone() call, -// (2) only once for any zone name, and -// (3) serially (i.e., no concurrent execution). -// -// The fallback factory obtains zoneinfo data by reading files in ${TZDIR}, -// and it is used automatically when no zone_info_source_factory definition -// is linked into the program. -extern ZoneInfoSourceFactory zone_info_source_factory; - -} // namespace cctz_extension -} // namespace time_internal +// if (auto zip = my_factory(name)) return zip; +// if (auto zip = fallback_factory(name)) return zip; +// if (auto zip = my_other_factory(name)) return zip; +// return nullptr; +// } +// } // namespace +// ZoneInfoSourceFactory zone_info_source_factory = CustomFactory; +// } // namespace cctz_extension +// +// This might be used, say, to use zoneinfo data embedded in the program, +// or read from a (possibly compressed) file archive, or both. +// +// cctz_extension::zone_info_source_factory() will be called: +// (1) from the same thread as the cctz::load_time_zone() call, +// (2) only once for any zone name, and +// (3) serially (i.e., no concurrent execution). +// +// The fallback factory obtains zoneinfo data by reading files in ${TZDIR}, +// and it is used automatically when no zone_info_source_factory definition +// is linked into the program. +extern ZoneInfoSourceFactory zone_info_source_factory; + +} // namespace cctz_extension +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_ + +#endif // ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/civil_time_detail.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/civil_time_detail.cc index 74c48f005c..61dbfc96ab 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/civil_time_detail.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/civil_time_detail.cc @@ -1,94 +1,94 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "y_absl/time/internal/cctz/include/cctz/civil_time_detail.h" - -#include <iomanip> -#include <ostream> -#include <sstream> - + +#include <iomanip> +#include <ostream> +#include <sstream> + #include "y_absl/base/config.h" namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { -namespace detail { - -// Output stream operators output a format matching YYYY-MM-DDThh:mm:ss, -// while omitting fields inferior to the type's alignment. For example, -// civil_day is formatted only as YYYY-MM-DD. -std::ostream& operator<<(std::ostream& os, const civil_year& y) { - std::stringstream ss; - ss << y.year(); // No padding. - return os << ss.str(); -} -std::ostream& operator<<(std::ostream& os, const civil_month& m) { - std::stringstream ss; - ss << civil_year(m) << '-'; - ss << std::setfill('0') << std::setw(2) << m.month(); - return os << ss.str(); -} -std::ostream& operator<<(std::ostream& os, const civil_day& d) { - std::stringstream ss; - ss << civil_month(d) << '-'; - ss << std::setfill('0') << std::setw(2) << d.day(); - return os << ss.str(); -} -std::ostream& operator<<(std::ostream& os, const civil_hour& h) { - std::stringstream ss; - ss << civil_day(h) << 'T'; - ss << std::setfill('0') << std::setw(2) << h.hour(); - return os << ss.str(); -} -std::ostream& operator<<(std::ostream& os, const civil_minute& m) { - std::stringstream ss; - ss << civil_hour(m) << ':'; - ss << std::setfill('0') << std::setw(2) << m.minute(); - return os << ss.str(); -} -std::ostream& operator<<(std::ostream& os, const civil_second& s) { - std::stringstream ss; - ss << civil_minute(s) << ':'; - ss << std::setfill('0') << std::setw(2) << s.second(); - return os << ss.str(); -} - -//////////////////////////////////////////////////////////////////////// - -std::ostream& operator<<(std::ostream& os, weekday wd) { - switch (wd) { - case weekday::monday: - return os << "Monday"; - case weekday::tuesday: - return os << "Tuesday"; - case weekday::wednesday: - return os << "Wednesday"; - case weekday::thursday: - return os << "Thursday"; - case weekday::friday: - return os << "Friday"; - case weekday::saturday: - return os << "Saturday"; - case weekday::sunday: - return os << "Sunday"; - } - return os; // Should never get here, but -Wreturn-type may warn without this. -} - -} // namespace detail -} // namespace cctz -} // namespace time_internal +namespace time_internal { +namespace cctz { +namespace detail { + +// Output stream operators output a format matching YYYY-MM-DDThh:mm:ss, +// while omitting fields inferior to the type's alignment. For example, +// civil_day is formatted only as YYYY-MM-DD. +std::ostream& operator<<(std::ostream& os, const civil_year& y) { + std::stringstream ss; + ss << y.year(); // No padding. + return os << ss.str(); +} +std::ostream& operator<<(std::ostream& os, const civil_month& m) { + std::stringstream ss; + ss << civil_year(m) << '-'; + ss << std::setfill('0') << std::setw(2) << m.month(); + return os << ss.str(); +} +std::ostream& operator<<(std::ostream& os, const civil_day& d) { + std::stringstream ss; + ss << civil_month(d) << '-'; + ss << std::setfill('0') << std::setw(2) << d.day(); + return os << ss.str(); +} +std::ostream& operator<<(std::ostream& os, const civil_hour& h) { + std::stringstream ss; + ss << civil_day(h) << 'T'; + ss << std::setfill('0') << std::setw(2) << h.hour(); + return os << ss.str(); +} +std::ostream& operator<<(std::ostream& os, const civil_minute& m) { + std::stringstream ss; + ss << civil_hour(m) << ':'; + ss << std::setfill('0') << std::setw(2) << m.minute(); + return os << ss.str(); +} +std::ostream& operator<<(std::ostream& os, const civil_second& s) { + std::stringstream ss; + ss << civil_minute(s) << ':'; + ss << std::setfill('0') << std::setw(2) << s.second(); + return os << ss.str(); +} + +//////////////////////////////////////////////////////////////////////// + +std::ostream& operator<<(std::ostream& os, weekday wd) { + switch (wd) { + case weekday::monday: + return os << "Monday"; + case weekday::tuesday: + return os << "Tuesday"; + case weekday::wednesday: + return os << "Wednesday"; + case weekday::thursday: + return os << "Thursday"; + case weekday::friday: + return os << "Friday"; + case weekday::saturday: + return os << "Saturday"; + case weekday::sunday: + return os << "Sunday"; + } + return os; // Should never get here, but -Wreturn-type may warn without this. +} + +} // namespace detail +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_fixed.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_fixed.cc index 74c77e4dba..3a22cbea1d 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_fixed.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_fixed.cc @@ -1,140 +1,140 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "time_zone_fixed.h" - -#include <algorithm> -#include <cassert> -#include <chrono> -#include <cstring> +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "time_zone_fixed.h" + +#include <algorithm> +#include <cassert> +#include <chrono> +#include <cstring> #include <util/generic/string.h> - + #include "y_absl/base/config.h" namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -// The prefix used for the internal names of fixed-offset zones. -const char kFixedZonePrefix[] = "Fixed/UTC"; - -const char kDigits[] = "0123456789"; - -char* Format02d(char* p, int v) { - *p++ = kDigits[(v / 10) % 10]; - *p++ = kDigits[v % 10]; - return p; -} - -int Parse02d(const char* p) { - if (const char* ap = std::strchr(kDigits, *p)) { - int v = static_cast<int>(ap - kDigits); - if (const char* bp = std::strchr(kDigits, *++p)) { - return (v * 10) + static_cast<int>(bp - kDigits); - } - } - return -1; -} - -} // namespace - +namespace time_internal { +namespace cctz { + +namespace { + +// The prefix used for the internal names of fixed-offset zones. +const char kFixedZonePrefix[] = "Fixed/UTC"; + +const char kDigits[] = "0123456789"; + +char* Format02d(char* p, int v) { + *p++ = kDigits[(v / 10) % 10]; + *p++ = kDigits[v % 10]; + return p; +} + +int Parse02d(const char* p) { + if (const char* ap = std::strchr(kDigits, *p)) { + int v = static_cast<int>(ap - kDigits); + if (const char* bp = std::strchr(kDigits, *++p)) { + return (v * 10) + static_cast<int>(bp - kDigits); + } + } + return -1; +} + +} // namespace + bool FixedOffsetFromName(const TString& name, seconds* offset) { if (name == "UTC" || name == "UTC0") { - *offset = seconds::zero(); - return true; - } - - const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; - const char* const ep = kFixedZonePrefix + prefix_len; - if (name.size() != prefix_len + 9) // <prefix>+99:99:99 - return false; + *offset = seconds::zero(); + return true; + } + + const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; + const char* const ep = kFixedZonePrefix + prefix_len; + if (name.size() != prefix_len + 9) // <prefix>+99:99:99 + return false; if (!std::equal(kFixedZonePrefix, ep, name.begin())) return false; - const char* np = name.data() + prefix_len; + const char* np = name.data() + prefix_len; if (np[0] != '+' && np[0] != '-') return false; - if (np[3] != ':' || np[6] != ':') // see note below about large offsets - return false; - - int hours = Parse02d(np + 1); - if (hours == -1) return false; - int mins = Parse02d(np + 4); - if (mins == -1) return false; - int secs = Parse02d(np + 7); - if (secs == -1) return false; - - secs += ((hours * 60) + mins) * 60; - if (secs > 24 * 60 * 60) return false; // outside supported offset range - *offset = seconds(secs * (np[0] == '-' ? -1 : 1)); // "-" means west - return true; -} - + if (np[3] != ':' || np[6] != ':') // see note below about large offsets + return false; + + int hours = Parse02d(np + 1); + if (hours == -1) return false; + int mins = Parse02d(np + 4); + if (mins == -1) return false; + int secs = Parse02d(np + 7); + if (secs == -1) return false; + + secs += ((hours * 60) + mins) * 60; + if (secs > 24 * 60 * 60) return false; // outside supported offset range + *offset = seconds(secs * (np[0] == '-' ? -1 : 1)); // "-" means west + return true; +} + TString FixedOffsetToName(const seconds& offset) { - if (offset == seconds::zero()) return "UTC"; - if (offset < std::chrono::hours(-24) || offset > std::chrono::hours(24)) { - // We don't support fixed-offset zones more than 24 hours - // away from UTC to avoid complications in rendering such - // offsets and to (somewhat) limit the total number of zones. - return "UTC"; - } + if (offset == seconds::zero()) return "UTC"; + if (offset < std::chrono::hours(-24) || offset > std::chrono::hours(24)) { + // We don't support fixed-offset zones more than 24 hours + // away from UTC to avoid complications in rendering such + // offsets and to (somewhat) limit the total number of zones. + return "UTC"; + } int offset_seconds = static_cast<int>(offset.count()); const char sign = (offset_seconds < 0 ? '-' : '+'); int offset_minutes = offset_seconds / 60; offset_seconds %= 60; - if (sign == '-') { + if (sign == '-') { if (offset_seconds > 0) { offset_seconds -= 60; offset_minutes += 1; - } + } offset_seconds = -offset_seconds; offset_minutes = -offset_minutes; - } + } int offset_hours = offset_minutes / 60; offset_minutes %= 60; - const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; - char buf[prefix_len + sizeof("-24:00:00")]; - char* ep = std::copy(kFixedZonePrefix, kFixedZonePrefix + prefix_len, buf); - *ep++ = sign; + const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; + char buf[prefix_len + sizeof("-24:00:00")]; + char* ep = std::copy(kFixedZonePrefix, kFixedZonePrefix + prefix_len, buf); + *ep++ = sign; ep = Format02d(ep, offset_hours); - *ep++ = ':'; + *ep++ = ':'; ep = Format02d(ep, offset_minutes); - *ep++ = ':'; + *ep++ = ':'; ep = Format02d(ep, offset_seconds); - *ep++ = '\0'; - assert(ep == buf + sizeof(buf)); - return buf; -} - + *ep++ = '\0'; + assert(ep == buf + sizeof(buf)); + return buf; +} + TString FixedOffsetToAbbr(const seconds& offset) { TString abbr = FixedOffsetToName(offset); - const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; - if (abbr.size() == prefix_len + 9) { // <prefix>+99:99:99 - abbr.erase(0, prefix_len); // +99:99:99 - abbr.erase(6, 1); // +99:9999 - abbr.erase(3, 1); // +999999 - if (abbr[5] == '0' && abbr[6] == '0') { // +999900 - abbr.erase(5, 2); // +9999 - if (abbr[3] == '0' && abbr[4] == '0') { // +9900 - abbr.erase(3, 2); // +99 - } - } - } - return abbr; -} - -} // namespace cctz -} // namespace time_internal + const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1; + if (abbr.size() == prefix_len + 9) { // <prefix>+99:99:99 + abbr.erase(0, prefix_len); // +99:99:99 + abbr.erase(6, 1); // +99:9999 + abbr.erase(3, 1); // +999999 + if (abbr[5] == '0' && abbr[6] == '0') { // +999900 + abbr.erase(5, 2); // +9999 + if (abbr[3] == '0' && abbr[4] == '0') { // +9900 + abbr.erase(3, 2); // +99 + } + } + } + return abbr; +} + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_fixed.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_fixed.h index 5f8065e902..39b24e5a32 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_fixed.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_fixed.h @@ -1,52 +1,52 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_ - +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_ +#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_ + #include <util/generic/string.h> - + #include "y_absl/base/config.h" #include "y_absl/time/internal/cctz/include/cctz/time_zone.h" - + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// Helper functions for dealing with the names and abbreviations -// of time zones that are a fixed offset (seconds east) from UTC. -// FixedOffsetFromName() extracts the offset from a valid fixed-offset -// name, while FixedOffsetToName() and FixedOffsetToAbbr() generate -// the canonical zone name and abbreviation respectively for the given -// offset. -// -// A fixed-offset name looks like "Fixed/UTC<+-><hours>:<mins>:<secs>". -// Its abbreviation is of the form "UTC(<+->H?H(MM(SS)?)?)?" where the -// optional pieces are omitted when their values are zero. (Note that -// the sign is the opposite of that used in a POSIX TZ specification.) -// -// Note: FixedOffsetFromName() fails on syntax errors or when the parsed -// offset exceeds 24 hours. FixedOffsetToName() and FixedOffsetToAbbr() -// both produce "UTC" when the argument offset exceeds 24 hours. +namespace time_internal { +namespace cctz { + +// Helper functions for dealing with the names and abbreviations +// of time zones that are a fixed offset (seconds east) from UTC. +// FixedOffsetFromName() extracts the offset from a valid fixed-offset +// name, while FixedOffsetToName() and FixedOffsetToAbbr() generate +// the canonical zone name and abbreviation respectively for the given +// offset. +// +// A fixed-offset name looks like "Fixed/UTC<+-><hours>:<mins>:<secs>". +// Its abbreviation is of the form "UTC(<+->H?H(MM(SS)?)?)?" where the +// optional pieces are omitted when their values are zero. (Note that +// the sign is the opposite of that used in a POSIX TZ specification.) +// +// Note: FixedOffsetFromName() fails on syntax errors or when the parsed +// offset exceeds 24 hours. FixedOffsetToName() and FixedOffsetToAbbr() +// both produce "UTC" when the argument offset exceeds 24 hours. bool FixedOffsetFromName(const TString& name, seconds* offset); TString FixedOffsetToName(const seconds& offset); TString FixedOffsetToAbbr(const seconds& offset); - -} // namespace cctz -} // namespace time_internal + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_ + +#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_format.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_format.cc index 2dbff0e03d..2f9597018b 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_format.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_format.cc @@ -1,72 +1,72 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if !defined(HAS_STRPTIME) +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#if !defined(HAS_STRPTIME) #if !defined(_MSC_VER) && !defined(__MINGW32__) #define HAS_STRPTIME 1 // assume everyone has strptime() except windows -#endif #endif - -#if defined(HAS_STRPTIME) && HAS_STRPTIME +#endif + +#if defined(HAS_STRPTIME) && HAS_STRPTIME #if !defined(_XOPEN_SOURCE) #define _XOPEN_SOURCE // Definedness suffices for strptime. -#endif #endif - +#endif + #include "y_absl/base/config.h" #include "y_absl/time/internal/cctz/include/cctz/time_zone.h" - -// Include time.h directly since, by C++ standards, ctime doesn't have to -// declare strptime. -#include <time.h> - -#include <cctype> -#include <chrono> -#include <cstddef> -#include <cstdint> -#include <cstring> -#include <ctime> -#include <limits> + +// Include time.h directly since, by C++ standards, ctime doesn't have to +// declare strptime. +#include <time.h> + +#include <cctype> +#include <chrono> +#include <cstddef> +#include <cstdint> +#include <cstring> +#include <ctime> +#include <limits> #include <util/generic/string.h> -#include <vector> -#if !HAS_STRPTIME -#include <iomanip> -#include <sstream> -#endif - +#include <vector> +#if !HAS_STRPTIME +#include <iomanip> +#include <sstream> +#endif + #include "y_absl/time/internal/cctz/include/cctz/civil_time.h" -#include "time_zone_if.h" - +#include "time_zone_if.h" + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { -namespace detail { - -namespace { - -#if !HAS_STRPTIME -// Build a strptime() using C++11's std::get_time(). -char* strptime(const char* s, const char* fmt, std::tm* tm) { - std::istringstream input(s); - input >> std::get_time(tm, fmt); - if (input.fail()) return nullptr; - return const_cast<char*>(s) + - (input.eof() ? strlen(s) : static_cast<std::size_t>(input.tellg())); -} -#endif - +namespace time_internal { +namespace cctz { +namespace detail { + +namespace { + +#if !HAS_STRPTIME +// Build a strptime() using C++11's std::get_time(). +char* strptime(const char* s, const char* fmt, std::tm* tm) { + std::istringstream input(s); + input >> std::get_time(tm, fmt); + if (input.fail()) return nullptr; + return const_cast<char*>(s) + + (input.eof() ? strlen(s) : static_cast<std::size_t>(input.tellg())); +} +#endif + // Convert a cctz::weekday to a tm_wday value (0-6, Sunday = 0). int ToTmWday(weekday wd) { switch (wd) { @@ -109,29 +109,29 @@ weekday FromTmWday(int tm_wday) { return weekday::sunday; /*NOTREACHED*/ } -std::tm ToTM(const time_zone::absolute_lookup& al) { - std::tm tm{}; - tm.tm_sec = al.cs.second(); - tm.tm_min = al.cs.minute(); - tm.tm_hour = al.cs.hour(); - tm.tm_mday = al.cs.day(); - tm.tm_mon = al.cs.month() - 1; - - // Saturate tm.tm_year is cases of over/underflow. - if (al.cs.year() < std::numeric_limits<int>::min() + 1900) { - tm.tm_year = std::numeric_limits<int>::min(); - } else if (al.cs.year() - 1900 > std::numeric_limits<int>::max()) { - tm.tm_year = std::numeric_limits<int>::max(); - } else { - tm.tm_year = static_cast<int>(al.cs.year() - 1900); - } - +std::tm ToTM(const time_zone::absolute_lookup& al) { + std::tm tm{}; + tm.tm_sec = al.cs.second(); + tm.tm_min = al.cs.minute(); + tm.tm_hour = al.cs.hour(); + tm.tm_mday = al.cs.day(); + tm.tm_mon = al.cs.month() - 1; + + // Saturate tm.tm_year is cases of over/underflow. + if (al.cs.year() < std::numeric_limits<int>::min() + 1900) { + tm.tm_year = std::numeric_limits<int>::min(); + } else if (al.cs.year() - 1900 > std::numeric_limits<int>::max()) { + tm.tm_year = std::numeric_limits<int>::max(); + } else { + tm.tm_year = static_cast<int>(al.cs.year() - 1900); + } + tm.tm_wday = ToTmWday(get_weekday(al.cs)); - tm.tm_yday = get_yearday(al.cs) - 1; - tm.tm_isdst = al.is_dst ? 1 : 0; - return tm; -} - + tm.tm_yday = get_yearday(al.cs) - 1; + tm.tm_isdst = al.is_dst ? 1 : 0; + return tm; +} + // Returns the week of the year [0:53] given a civil day and the day on // which weeks are defined to start. int ToWeek(const civil_day& cd, weekday week_start) { @@ -139,270 +139,270 @@ int ToWeek(const civil_day& cd, weekday week_start) { return static_cast<int>((d - prev_weekday(civil_year(d), week_start)) / 7); } -const char kDigits[] = "0123456789"; - -// Formats a 64-bit integer in the given field width. Note that it is up -// to the caller of Format64() [and Format02d()/FormatOffset()] to ensure -// that there is sufficient space before ep to hold the conversion. -char* Format64(char* ep, int width, std::int_fast64_t v) { - bool neg = false; - if (v < 0) { - --width; - neg = true; - if (v == std::numeric_limits<std::int_fast64_t>::min()) { - // Avoid negating minimum value. - std::int_fast64_t last_digit = -(v % 10); - v /= 10; - if (last_digit < 0) { - ++v; - last_digit += 10; - } - --width; - *--ep = kDigits[last_digit]; - } - v = -v; - } - do { - --width; - *--ep = kDigits[v % 10]; - } while (v /= 10); - while (--width >= 0) *--ep = '0'; // zero pad - if (neg) *--ep = '-'; - return ep; -} - -// Formats [0 .. 99] as %02d. -char* Format02d(char* ep, int v) { - *--ep = kDigits[v % 10]; - *--ep = kDigits[(v / 10) % 10]; - return ep; -} - -// Formats a UTC offset, like +00:00. -char* FormatOffset(char* ep, int offset, const char* mode) { - // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and - // generate a "negative zero" when we're formatting a zero offset - // as the result of a failed load_time_zone(). - char sign = '+'; - if (offset < 0) { - offset = -offset; // bounded by 24h so no overflow - sign = '-'; - } - const int seconds = offset % 60; - const int minutes = (offset /= 60) % 60; - const int hours = offset /= 60; - const char sep = mode[0]; - const bool ext = (sep != '\0' && mode[1] == '*'); - const bool ccc = (ext && mode[2] == ':'); - if (ext && (!ccc || seconds != 0)) { - ep = Format02d(ep, seconds); - *--ep = sep; - } else { - // If we're not rendering seconds, sub-minute negative offsets - // should get a positive sign (e.g., offset=-10s => "+00:00"). - if (hours == 0 && minutes == 0) sign = '+'; - } - if (!ccc || minutes != 0 || seconds != 0) { - ep = Format02d(ep, minutes); - if (sep != '\0') *--ep = sep; - } - ep = Format02d(ep, hours); - *--ep = sign; - return ep; -} - -// Formats a std::tm using strftime(3). +const char kDigits[] = "0123456789"; + +// Formats a 64-bit integer in the given field width. Note that it is up +// to the caller of Format64() [and Format02d()/FormatOffset()] to ensure +// that there is sufficient space before ep to hold the conversion. +char* Format64(char* ep, int width, std::int_fast64_t v) { + bool neg = false; + if (v < 0) { + --width; + neg = true; + if (v == std::numeric_limits<std::int_fast64_t>::min()) { + // Avoid negating minimum value. + std::int_fast64_t last_digit = -(v % 10); + v /= 10; + if (last_digit < 0) { + ++v; + last_digit += 10; + } + --width; + *--ep = kDigits[last_digit]; + } + v = -v; + } + do { + --width; + *--ep = kDigits[v % 10]; + } while (v /= 10); + while (--width >= 0) *--ep = '0'; // zero pad + if (neg) *--ep = '-'; + return ep; +} + +// Formats [0 .. 99] as %02d. +char* Format02d(char* ep, int v) { + *--ep = kDigits[v % 10]; + *--ep = kDigits[(v / 10) % 10]; + return ep; +} + +// Formats a UTC offset, like +00:00. +char* FormatOffset(char* ep, int offset, const char* mode) { + // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and + // generate a "negative zero" when we're formatting a zero offset + // as the result of a failed load_time_zone(). + char sign = '+'; + if (offset < 0) { + offset = -offset; // bounded by 24h so no overflow + sign = '-'; + } + const int seconds = offset % 60; + const int minutes = (offset /= 60) % 60; + const int hours = offset /= 60; + const char sep = mode[0]; + const bool ext = (sep != '\0' && mode[1] == '*'); + const bool ccc = (ext && mode[2] == ':'); + if (ext && (!ccc || seconds != 0)) { + ep = Format02d(ep, seconds); + *--ep = sep; + } else { + // If we're not rendering seconds, sub-minute negative offsets + // should get a positive sign (e.g., offset=-10s => "+00:00"). + if (hours == 0 && minutes == 0) sign = '+'; + } + if (!ccc || minutes != 0 || seconds != 0) { + ep = Format02d(ep, minutes); + if (sep != '\0') *--ep = sep; + } + ep = Format02d(ep, hours); + *--ep = sign; + return ep; +} + +// Formats a std::tm using strftime(3). void FormatTM(TString* out, const TString& fmt, const std::tm& tm) { - // strftime(3) returns the number of characters placed in the output - // array (which may be 0 characters). It also returns 0 to indicate - // an error, like the array wasn't large enough. To accommodate this, + // strftime(3) returns the number of characters placed in the output + // array (which may be 0 characters). It also returns 0 to indicate + // an error, like the array wasn't large enough. To accommodate this, // the following code grows the buffer size from 2x the format string - // length up to 32x. - for (std::size_t i = 2; i != 32; i *= 2) { - std::size_t buf_size = fmt.size() * i; - std::vector<char> buf(buf_size); - if (std::size_t len = strftime(&buf[0], buf_size, fmt.c_str(), &tm)) { - out->append(&buf[0], len); - return; - } - } -} - -// Used for %E#S/%E#f specifiers and for data values in parse(). -template <typename T> -const char* ParseInt(const char* dp, int width, T min, T max, T* vp) { - if (dp != nullptr) { - const T kmin = std::numeric_limits<T>::min(); - bool erange = false; - bool neg = false; - T value = 0; - if (*dp == '-') { - neg = true; - if (width <= 0 || --width != 0) { - ++dp; - } else { - dp = nullptr; // width was 1 - } - } - if (const char* const bp = dp) { - while (const char* cp = strchr(kDigits, *dp)) { - int d = static_cast<int>(cp - kDigits); - if (d >= 10) break; - if (value < kmin / 10) { - erange = true; - break; - } - value *= 10; - if (value < kmin + d) { - erange = true; - break; - } - value -= d; - dp += 1; - if (width > 0 && --width == 0) break; - } - if (dp != bp && !erange && (neg || value != kmin)) { - if (!neg || value != 0) { - if (!neg) value = -value; // make positive - if (min <= value && value <= max) { - *vp = value; - } else { - dp = nullptr; - } - } else { - dp = nullptr; - } - } else { - dp = nullptr; - } - } - } - return dp; -} - -// The number of base-10 digits that can be represented by a signed 64-bit -// integer. That is, 10^kDigits10_64 <= 2^63 - 1 < 10^(kDigits10_64 + 1). -const int kDigits10_64 = 18; - -// 10^n for everything that can be represented by a signed 64-bit integer. -const std::int_fast64_t kExp10[kDigits10_64 + 1] = { - 1, - 10, - 100, - 1000, - 10000, - 100000, - 1000000, - 10000000, - 100000000, - 1000000000, - 10000000000, - 100000000000, - 1000000000000, - 10000000000000, - 100000000000000, - 1000000000000000, - 10000000000000000, - 100000000000000000, - 1000000000000000000, -}; - -} // namespace - -// Uses strftime(3) to format the given Time. The following extended format -// specifiers are also supported: -// -// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm) -// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss) -// - %E#S - Seconds with # digits of fractional precision -// - %E*S - Seconds with full fractional precision (a literal '*') -// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999) + // length up to 32x. + for (std::size_t i = 2; i != 32; i *= 2) { + std::size_t buf_size = fmt.size() * i; + std::vector<char> buf(buf_size); + if (std::size_t len = strftime(&buf[0], buf_size, fmt.c_str(), &tm)) { + out->append(&buf[0], len); + return; + } + } +} + +// Used for %E#S/%E#f specifiers and for data values in parse(). +template <typename T> +const char* ParseInt(const char* dp, int width, T min, T max, T* vp) { + if (dp != nullptr) { + const T kmin = std::numeric_limits<T>::min(); + bool erange = false; + bool neg = false; + T value = 0; + if (*dp == '-') { + neg = true; + if (width <= 0 || --width != 0) { + ++dp; + } else { + dp = nullptr; // width was 1 + } + } + if (const char* const bp = dp) { + while (const char* cp = strchr(kDigits, *dp)) { + int d = static_cast<int>(cp - kDigits); + if (d >= 10) break; + if (value < kmin / 10) { + erange = true; + break; + } + value *= 10; + if (value < kmin + d) { + erange = true; + break; + } + value -= d; + dp += 1; + if (width > 0 && --width == 0) break; + } + if (dp != bp && !erange && (neg || value != kmin)) { + if (!neg || value != 0) { + if (!neg) value = -value; // make positive + if (min <= value && value <= max) { + *vp = value; + } else { + dp = nullptr; + } + } else { + dp = nullptr; + } + } else { + dp = nullptr; + } + } + } + return dp; +} + +// The number of base-10 digits that can be represented by a signed 64-bit +// integer. That is, 10^kDigits10_64 <= 2^63 - 1 < 10^(kDigits10_64 + 1). +const int kDigits10_64 = 18; + +// 10^n for everything that can be represented by a signed 64-bit integer. +const std::int_fast64_t kExp10[kDigits10_64 + 1] = { + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000, + 100000000000, + 1000000000000, + 10000000000000, + 100000000000000, + 1000000000000000, + 10000000000000000, + 100000000000000000, + 1000000000000000000, +}; + +} // namespace + +// Uses strftime(3) to format the given Time. The following extended format +// specifiers are also supported: +// +// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm) +// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss) +// - %E#S - Seconds with # digits of fractional precision +// - %E*S - Seconds with full fractional precision (a literal '*') +// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999) // - %ET - The RFC3339 "date-time" separator "T" -// -// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are -// handled internally for performance reasons. strftime(3) is slow due to -// a POSIX requirement to respect changes to ${TZ}. -// -// The TZ/GNU %s extension is handled internally because strftime() has -// to use mktime() to generate it, and that assumes the local time zone. -// -// We also handle the %z and %Z specifiers to accommodate platforms that do -// not support the tm_gmtoff and tm_zone extensions to std::tm. -// -// Requires that zero() <= fs < seconds(1). +// +// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are +// handled internally for performance reasons. strftime(3) is slow due to +// a POSIX requirement to respect changes to ${TZ}. +// +// The TZ/GNU %s extension is handled internally because strftime() has +// to use mktime() to generate it, and that assumes the local time zone. +// +// We also handle the %z and %Z specifiers to accommodate platforms that do +// not support the tm_gmtoff and tm_zone extensions to std::tm. +// +// Requires that zero() <= fs < seconds(1). TString format(const TString& format, const time_point<seconds>& tp, - const detail::femtoseconds& fs, const time_zone& tz) { + const detail::femtoseconds& fs, const time_zone& tz) { TString result; - result.reserve(format.size()); // A reasonable guess for the result size. - const time_zone::absolute_lookup al = tz.lookup(tp); - const std::tm tm = ToTM(al); - - // Scratch buffer for internal conversions. - char buf[3 + kDigits10_64]; // enough for longest conversion - char* const ep = buf + sizeof(buf); - char* bp; // works back from ep - - // Maintain three, disjoint subsequences that span format. - // [format.begin() ... pending) : already formatted into result - // [pending ... cur) : formatting pending, but no special cases - // [cur ... format.end()) : unexamined - // Initially, everything is in the unexamined part. - const char* pending = format.c_str(); // NUL terminated - const char* cur = pending; - const char* end = pending + format.length(); - - while (cur != end) { // while something is unexamined - // Moves cur to the next percent sign. - const char* start = cur; - while (cur != end && *cur != '%') ++cur; - - // If the new pending text is all ordinary, copy it out. - if (cur != start && pending == start) { - result.append(pending, static_cast<std::size_t>(cur - pending)); - pending = start = cur; - } - - // Span the sequential percent signs. - const char* percent = cur; - while (cur != end && *cur == '%') ++cur; - - // If the new pending text is all percents, copy out one - // percent for every matched pair, then skip those pairs. - if (cur != start && pending == start) { - std::size_t escaped = static_cast<std::size_t>(cur - pending) / 2; - result.append(pending, escaped); - pending += escaped * 2; - // Also copy out a single trailing percent. - if (pending != cur && cur == end) { - result.push_back(*pending++); - } - } - - // Loop unless we have an unescaped percent. - if (cur == end || (cur - percent) % 2 == 0) continue; - - // Simple specifiers that we handle ourselves. + result.reserve(format.size()); // A reasonable guess for the result size. + const time_zone::absolute_lookup al = tz.lookup(tp); + const std::tm tm = ToTM(al); + + // Scratch buffer for internal conversions. + char buf[3 + kDigits10_64]; // enough for longest conversion + char* const ep = buf + sizeof(buf); + char* bp; // works back from ep + + // Maintain three, disjoint subsequences that span format. + // [format.begin() ... pending) : already formatted into result + // [pending ... cur) : formatting pending, but no special cases + // [cur ... format.end()) : unexamined + // Initially, everything is in the unexamined part. + const char* pending = format.c_str(); // NUL terminated + const char* cur = pending; + const char* end = pending + format.length(); + + while (cur != end) { // while something is unexamined + // Moves cur to the next percent sign. + const char* start = cur; + while (cur != end && *cur != '%') ++cur; + + // If the new pending text is all ordinary, copy it out. + if (cur != start && pending == start) { + result.append(pending, static_cast<std::size_t>(cur - pending)); + pending = start = cur; + } + + // Span the sequential percent signs. + const char* percent = cur; + while (cur != end && *cur == '%') ++cur; + + // If the new pending text is all percents, copy out one + // percent for every matched pair, then skip those pairs. + if (cur != start && pending == start) { + std::size_t escaped = static_cast<std::size_t>(cur - pending) / 2; + result.append(pending, escaped); + pending += escaped * 2; + // Also copy out a single trailing percent. + if (pending != cur && cur == end) { + result.push_back(*pending++); + } + } + + // Loop unless we have an unescaped percent. + if (cur == end || (cur - percent) % 2 == 0) continue; + + // Simple specifiers that we handle ourselves. if (strchr("YmdeUuWwHMSzZs%", *cur)) { - if (cur - 1 != pending) { + if (cur - 1 != pending) { FormatTM(&result, TString(pending, cur - 1), tm); - } - switch (*cur) { - case 'Y': - // This avoids the tm.tm_year overflow problem for %Y, however - // tm.tm_year will still be used by other specifiers like %D. - bp = Format64(ep, 0, al.cs.year()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case 'm': - bp = Format02d(ep, al.cs.month()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case 'd': - case 'e': - bp = Format02d(ep, al.cs.day()); - if (*cur == 'e' && *bp == '0') *bp = ' '; // for Windows - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; + } + switch (*cur) { + case 'Y': + // This avoids the tm.tm_year overflow problem for %Y, however + // tm.tm_year will still be used by other specifiers like %D. + bp = Format64(ep, 0, al.cs.year()); + result.append(bp, static_cast<std::size_t>(ep - bp)); + break; + case 'm': + bp = Format02d(ep, al.cs.month()); + result.append(bp, static_cast<std::size_t>(ep - bp)); + break; + case 'd': + case 'e': + bp = Format02d(ep, al.cs.day()); + if (*cur == 'e' && *bp == '0') *bp = ' '; // for Windows + result.append(bp, static_cast<std::size_t>(ep - bp)); + break; case 'U': bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::sunday)); result.append(bp, static_cast<std::size_t>(ep - bp)); @@ -419,79 +419,79 @@ TString format(const TString& format, const time_point<seconds>& tp, bp = Format64(ep, 0, tm.tm_wday); result.append(bp, static_cast<std::size_t>(ep - bp)); break; - case 'H': - bp = Format02d(ep, al.cs.hour()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case 'M': - bp = Format02d(ep, al.cs.minute()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case 'S': - bp = Format02d(ep, al.cs.second()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case 'z': - bp = FormatOffset(ep, al.offset, ""); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case 'Z': - result.append(al.abbr); - break; - case 's': - bp = Format64(ep, 0, ToUnixSeconds(tp)); - result.append(bp, static_cast<std::size_t>(ep - bp)); - break; - case '%': - result.push_back('%'); - break; - } - pending = ++cur; - continue; - } - - // More complex specifiers that we handle ourselves. - if (*cur == ':' && cur + 1 != end) { - if (*(cur + 1) == 'z') { - // Formats %:z. - if (cur - 1 != pending) { + case 'H': + bp = Format02d(ep, al.cs.hour()); + result.append(bp, static_cast<std::size_t>(ep - bp)); + break; + case 'M': + bp = Format02d(ep, al.cs.minute()); + result.append(bp, static_cast<std::size_t>(ep - bp)); + break; + case 'S': + bp = Format02d(ep, al.cs.second()); + result.append(bp, static_cast<std::size_t>(ep - bp)); + break; + case 'z': + bp = FormatOffset(ep, al.offset, ""); + result.append(bp, static_cast<std::size_t>(ep - bp)); + break; + case 'Z': + result.append(al.abbr); + break; + case 's': + bp = Format64(ep, 0, ToUnixSeconds(tp)); + result.append(bp, static_cast<std::size_t>(ep - bp)); + break; + case '%': + result.push_back('%'); + break; + } + pending = ++cur; + continue; + } + + // More complex specifiers that we handle ourselves. + if (*cur == ':' && cur + 1 != end) { + if (*(cur + 1) == 'z') { + // Formats %:z. + if (cur - 1 != pending) { FormatTM(&result, TString(pending, cur - 1), tm); - } - bp = FormatOffset(ep, al.offset, ":"); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = cur += 2; - continue; - } - if (*(cur + 1) == ':' && cur + 2 != end) { - if (*(cur + 2) == 'z') { - // Formats %::z. - if (cur - 1 != pending) { + } + bp = FormatOffset(ep, al.offset, ":"); + result.append(bp, static_cast<std::size_t>(ep - bp)); + pending = cur += 2; + continue; + } + if (*(cur + 1) == ':' && cur + 2 != end) { + if (*(cur + 2) == 'z') { + // Formats %::z. + if (cur - 1 != pending) { FormatTM(&result, TString(pending, cur - 1), tm); - } - bp = FormatOffset(ep, al.offset, ":*"); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = cur += 3; - continue; - } - if (*(cur + 2) == ':' && cur + 3 != end) { - if (*(cur + 3) == 'z') { - // Formats %:::z. - if (cur - 1 != pending) { + } + bp = FormatOffset(ep, al.offset, ":*"); + result.append(bp, static_cast<std::size_t>(ep - bp)); + pending = cur += 3; + continue; + } + if (*(cur + 2) == ':' && cur + 3 != end) { + if (*(cur + 3) == 'z') { + // Formats %:::z. + if (cur - 1 != pending) { FormatTM(&result, TString(pending, cur - 1), tm); - } - bp = FormatOffset(ep, al.offset, ":*:"); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = cur += 4; - continue; - } - } - } - } - - // Loop if there is no E modifier. - if (*cur != 'E' || ++cur == end) continue; - - // Format our extensions. + } + bp = FormatOffset(ep, al.offset, ":*:"); + result.append(bp, static_cast<std::size_t>(ep - bp)); + pending = cur += 4; + continue; + } + } + } + } + + // Loop if there is no E modifier. + if (*cur != 'E' || ++cur == end) continue; + + // Format our extensions. if (*cur == 'T') { // Formats %ET. if (cur - 2 != pending) { @@ -500,159 +500,159 @@ TString format(const TString& format, const time_point<seconds>& tp, result.append("T"); pending = ++cur; } else if (*cur == 'z') { - // Formats %Ez. - if (cur - 2 != pending) { + // Formats %Ez. + if (cur - 2 != pending) { FormatTM(&result, TString(pending, cur - 2), tm); - } - bp = FormatOffset(ep, al.offset, ":"); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = ++cur; - } else if (*cur == '*' && cur + 1 != end && *(cur + 1) == 'z') { - // Formats %E*z. - if (cur - 2 != pending) { + } + bp = FormatOffset(ep, al.offset, ":"); + result.append(bp, static_cast<std::size_t>(ep - bp)); + pending = ++cur; + } else if (*cur == '*' && cur + 1 != end && *(cur + 1) == 'z') { + // Formats %E*z. + if (cur - 2 != pending) { FormatTM(&result, TString(pending, cur - 2), tm); - } - bp = FormatOffset(ep, al.offset, ":*"); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = cur += 2; - } else if (*cur == '*' && cur + 1 != end && - (*(cur + 1) == 'S' || *(cur + 1) == 'f')) { - // Formats %E*S or %E*F. - if (cur - 2 != pending) { + } + bp = FormatOffset(ep, al.offset, ":*"); + result.append(bp, static_cast<std::size_t>(ep - bp)); + pending = cur += 2; + } else if (*cur == '*' && cur + 1 != end && + (*(cur + 1) == 'S' || *(cur + 1) == 'f')) { + // Formats %E*S or %E*F. + if (cur - 2 != pending) { FormatTM(&result, TString(pending, cur - 2), tm); - } - char* cp = ep; - bp = Format64(cp, 15, fs.count()); - while (cp != bp && cp[-1] == '0') --cp; - switch (*(cur + 1)) { - case 'S': - if (cp != bp) *--bp = '.'; - bp = Format02d(bp, al.cs.second()); - break; - case 'f': - if (cp == bp) *--bp = '0'; - break; - } - result.append(bp, static_cast<std::size_t>(cp - bp)); - pending = cur += 2; - } else if (*cur == '4' && cur + 1 != end && *(cur + 1) == 'Y') { - // Formats %E4Y. - if (cur - 2 != pending) { + } + char* cp = ep; + bp = Format64(cp, 15, fs.count()); + while (cp != bp && cp[-1] == '0') --cp; + switch (*(cur + 1)) { + case 'S': + if (cp != bp) *--bp = '.'; + bp = Format02d(bp, al.cs.second()); + break; + case 'f': + if (cp == bp) *--bp = '0'; + break; + } + result.append(bp, static_cast<std::size_t>(cp - bp)); + pending = cur += 2; + } else if (*cur == '4' && cur + 1 != end && *(cur + 1) == 'Y') { + // Formats %E4Y. + if (cur - 2 != pending) { FormatTM(&result, TString(pending, cur - 2), tm); - } - bp = Format64(ep, 4, al.cs.year()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = cur += 2; - } else if (std::isdigit(*cur)) { - // Possibly found %E#S or %E#f. - int n = 0; - if (const char* np = ParseInt(cur, 0, 0, 1024, &n)) { - if (*np == 'S' || *np == 'f') { - // Formats %E#S or %E#f. - if (cur - 2 != pending) { + } + bp = Format64(ep, 4, al.cs.year()); + result.append(bp, static_cast<std::size_t>(ep - bp)); + pending = cur += 2; + } else if (std::isdigit(*cur)) { + // Possibly found %E#S or %E#f. + int n = 0; + if (const char* np = ParseInt(cur, 0, 0, 1024, &n)) { + if (*np == 'S' || *np == 'f') { + // Formats %E#S or %E#f. + if (cur - 2 != pending) { FormatTM(&result, TString(pending, cur - 2), tm); - } - bp = ep; - if (n > 0) { - if (n > kDigits10_64) n = kDigits10_64; + } + bp = ep; + if (n > 0) { + if (n > kDigits10_64) n = kDigits10_64; bp = Format64(bp, n, (n > 15) ? fs.count() * kExp10[n - 15] : fs.count() / kExp10[15 - n]); - if (*np == 'S') *--bp = '.'; - } - if (*np == 'S') bp = Format02d(bp, al.cs.second()); - result.append(bp, static_cast<std::size_t>(ep - bp)); - pending = cur = ++np; - } - } - } - } - - // Formats any remaining data. - if (end != pending) { + if (*np == 'S') *--bp = '.'; + } + if (*np == 'S') bp = Format02d(bp, al.cs.second()); + result.append(bp, static_cast<std::size_t>(ep - bp)); + pending = cur = ++np; + } + } + } + } + + // Formats any remaining data. + if (end != pending) { FormatTM(&result, TString(pending, end), tm); - } - - return result; -} - -namespace { - -const char* ParseOffset(const char* dp, const char* mode, int* offset) { - if (dp != nullptr) { - const char first = *dp++; - if (first == '+' || first == '-') { - char sep = mode[0]; - int hours = 0; - int minutes = 0; - int seconds = 0; - const char* ap = ParseInt(dp, 2, 0, 23, &hours); - if (ap != nullptr && ap - dp == 2) { - dp = ap; - if (sep != '\0' && *ap == sep) ++ap; - const char* bp = ParseInt(ap, 2, 0, 59, &minutes); - if (bp != nullptr && bp - ap == 2) { - dp = bp; - if (sep != '\0' && *bp == sep) ++bp; - const char* cp = ParseInt(bp, 2, 0, 59, &seconds); - if (cp != nullptr && cp - bp == 2) dp = cp; - } - *offset = ((hours * 60 + minutes) * 60) + seconds; - if (first == '-') *offset = -*offset; - } else { - dp = nullptr; - } + } + + return result; +} + +namespace { + +const char* ParseOffset(const char* dp, const char* mode, int* offset) { + if (dp != nullptr) { + const char first = *dp++; + if (first == '+' || first == '-') { + char sep = mode[0]; + int hours = 0; + int minutes = 0; + int seconds = 0; + const char* ap = ParseInt(dp, 2, 0, 23, &hours); + if (ap != nullptr && ap - dp == 2) { + dp = ap; + if (sep != '\0' && *ap == sep) ++ap; + const char* bp = ParseInt(ap, 2, 0, 59, &minutes); + if (bp != nullptr && bp - ap == 2) { + dp = bp; + if (sep != '\0' && *bp == sep) ++bp; + const char* cp = ParseInt(bp, 2, 0, 59, &seconds); + if (cp != nullptr && cp - bp == 2) dp = cp; + } + *offset = ((hours * 60 + minutes) * 60) + seconds; + if (first == '-') *offset = -*offset; + } else { + dp = nullptr; + } } else if (first == 'Z' || first == 'z') { // Zulu - *offset = 0; - } else { - dp = nullptr; - } - } - return dp; -} - + *offset = 0; + } else { + dp = nullptr; + } + } + return dp; +} + const char* ParseZone(const char* dp, TString* zone) { - zone->clear(); - if (dp != nullptr) { - while (*dp != '\0' && !std::isspace(*dp)) zone->push_back(*dp++); - if (zone->empty()) dp = nullptr; - } - return dp; -} - -const char* ParseSubSeconds(const char* dp, detail::femtoseconds* subseconds) { - if (dp != nullptr) { - std::int_fast64_t v = 0; - std::int_fast64_t exp = 0; - const char* const bp = dp; - while (const char* cp = strchr(kDigits, *dp)) { - int d = static_cast<int>(cp - kDigits); - if (d >= 10) break; - if (exp < 15) { - exp += 1; - v *= 10; - v += d; - } - ++dp; - } - if (dp != bp) { - v *= kExp10[15 - exp]; - *subseconds = detail::femtoseconds(v); - } else { - dp = nullptr; - } - } - return dp; -} - -// Parses a string into a std::tm using strptime(3). -const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) { - if (dp != nullptr) { - dp = strptime(dp, fmt, tm); - } - return dp; -} - + zone->clear(); + if (dp != nullptr) { + while (*dp != '\0' && !std::isspace(*dp)) zone->push_back(*dp++); + if (zone->empty()) dp = nullptr; + } + return dp; +} + +const char* ParseSubSeconds(const char* dp, detail::femtoseconds* subseconds) { + if (dp != nullptr) { + std::int_fast64_t v = 0; + std::int_fast64_t exp = 0; + const char* const bp = dp; + while (const char* cp = strchr(kDigits, *dp)) { + int d = static_cast<int>(cp - kDigits); + if (d >= 10) break; + if (exp < 15) { + exp += 1; + v *= 10; + v += d; + } + ++dp; + } + if (dp != bp) { + v *= kExp10[15 - exp]; + *subseconds = detail::femtoseconds(v); + } else { + dp = nullptr; + } + } + return dp; +} + +// Parses a string into a std::tm using strptime(3). +const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) { + if (dp != nullptr) { + dp = strptime(dp, fmt, tm); + } + return dp; +} + // Sets year, tm_mon and tm_mday given the year, week_num, and tm_wday, // and the day on which weeks are defined to start. Returns false if year // would need to move outside its bounds. @@ -673,102 +673,102 @@ bool FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) { return true; } -} // namespace - -// Uses strptime(3) to parse the given input. Supports the same extended -// format specifiers as format(), although %E#S and %E*S are treated -// identically (and similarly for %E#f and %E*f). %Ez and %E*z also accept +} // namespace + +// Uses strptime(3) to parse the given input. Supports the same extended +// format specifiers as format(), although %E#S and %E*S are treated +// identically (and similarly for %E#f and %E*f). %Ez and %E*z also accept // the same inputs. %ET accepts either 'T' or 't'. -// -// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are -// handled internally so that we can normally avoid strptime() altogether -// (which is particularly helpful when the native implementation is broken). -// -// The TZ/GNU %s extension is handled internally because strptime() has to -// use localtime_r() to generate it, and that assumes the local time zone. -// -// We also handle the %z specifier to accommodate platforms that do not -// support the tm_gmtoff extension to std::tm. %Z is parsed but ignored. +// +// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are +// handled internally so that we can normally avoid strptime() altogether +// (which is particularly helpful when the native implementation is broken). +// +// The TZ/GNU %s extension is handled internally because strptime() has to +// use localtime_r() to generate it, and that assumes the local time zone. +// +// We also handle the %z specifier to accommodate platforms that do not +// support the tm_gmtoff extension to std::tm. %Z is parsed but ignored. bool parse(const TString& format, const TString& input, - const time_zone& tz, time_point<seconds>* sec, + const time_zone& tz, time_point<seconds>* sec, detail::femtoseconds* fs, TString* err) { - // The unparsed input. - const char* data = input.c_str(); // NUL terminated - - // Skips leading whitespace. - while (std::isspace(*data)) ++data; - - const year_t kyearmax = std::numeric_limits<year_t>::max(); - const year_t kyearmin = std::numeric_limits<year_t>::min(); - - // Sets default values for unspecified fields. - bool saw_year = false; - year_t year = 1970; - std::tm tm{}; - tm.tm_year = 1970 - 1900; - tm.tm_mon = 1 - 1; // Jan - tm.tm_mday = 1; - tm.tm_hour = 0; - tm.tm_min = 0; - tm.tm_sec = 0; - tm.tm_wday = 4; // Thu - tm.tm_yday = 0; - tm.tm_isdst = 0; - auto subseconds = detail::femtoseconds::zero(); - bool saw_offset = false; - int offset = 0; // No offset from passed tz. + // The unparsed input. + const char* data = input.c_str(); // NUL terminated + + // Skips leading whitespace. + while (std::isspace(*data)) ++data; + + const year_t kyearmax = std::numeric_limits<year_t>::max(); + const year_t kyearmin = std::numeric_limits<year_t>::min(); + + // Sets default values for unspecified fields. + bool saw_year = false; + year_t year = 1970; + std::tm tm{}; + tm.tm_year = 1970 - 1900; + tm.tm_mon = 1 - 1; // Jan + tm.tm_mday = 1; + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_wday = 4; // Thu + tm.tm_yday = 0; + tm.tm_isdst = 0; + auto subseconds = detail::femtoseconds::zero(); + bool saw_offset = false; + int offset = 0; // No offset from passed tz. TString zone = "UTC"; - - const char* fmt = format.c_str(); // NUL terminated - bool twelve_hour = false; - bool afternoon = false; + + const char* fmt = format.c_str(); // NUL terminated + bool twelve_hour = false; + bool afternoon = false; int week_num = -1; weekday week_start = weekday::sunday; - - bool saw_percent_s = false; - std::int_fast64_t percent_s = 0; - - // Steps through format, one specifier at a time. - while (data != nullptr && *fmt != '\0') { - if (std::isspace(*fmt)) { - while (std::isspace(*data)) ++data; - while (std::isspace(*++fmt)) continue; - continue; - } - - if (*fmt != '%') { - if (*data == *fmt) { - ++data; - ++fmt; - } else { - data = nullptr; - } - continue; - } - - const char* percent = fmt; - if (*++fmt == '\0') { - data = nullptr; - continue; - } - switch (*fmt++) { - case 'Y': - // Symmetrically with FormatTime(), directly handing %Y avoids the - // tm.tm_year overflow problem. However, tm.tm_year will still be - // used by other specifiers like %D. - data = ParseInt(data, 0, kyearmin, kyearmax, &year); - if (data != nullptr) saw_year = true; - continue; - case 'm': - data = ParseInt(data, 2, 1, 12, &tm.tm_mon); - if (data != nullptr) tm.tm_mon -= 1; + + bool saw_percent_s = false; + std::int_fast64_t percent_s = 0; + + // Steps through format, one specifier at a time. + while (data != nullptr && *fmt != '\0') { + if (std::isspace(*fmt)) { + while (std::isspace(*data)) ++data; + while (std::isspace(*++fmt)) continue; + continue; + } + + if (*fmt != '%') { + if (*data == *fmt) { + ++data; + ++fmt; + } else { + data = nullptr; + } + continue; + } + + const char* percent = fmt; + if (*++fmt == '\0') { + data = nullptr; + continue; + } + switch (*fmt++) { + case 'Y': + // Symmetrically with FormatTime(), directly handing %Y avoids the + // tm.tm_year overflow problem. However, tm.tm_year will still be + // used by other specifiers like %D. + data = ParseInt(data, 0, kyearmin, kyearmax, &year); + if (data != nullptr) saw_year = true; + continue; + case 'm': + data = ParseInt(data, 2, 1, 12, &tm.tm_mon); + if (data != nullptr) tm.tm_mon -= 1; week_num = -1; - continue; - case 'd': - case 'e': - data = ParseInt(data, 2, 1, 31, &tm.tm_mday); + continue; + case 'd': + case 'e': + data = ParseInt(data, 2, 1, 31, &tm.tm_mday); week_num = -1; - continue; + continue; case 'U': data = ParseInt(data, 0, 0, 53, &week_num); week_start = weekday::sunday; @@ -784,54 +784,54 @@ bool parse(const TString& format, const TString& input, case 'w': data = ParseInt(data, 0, 0, 6, &tm.tm_wday); continue; - case 'H': - data = ParseInt(data, 2, 0, 23, &tm.tm_hour); - twelve_hour = false; - continue; - case 'M': - data = ParseInt(data, 2, 0, 59, &tm.tm_min); - continue; - case 'S': - data = ParseInt(data, 2, 0, 60, &tm.tm_sec); - continue; - case 'I': - case 'l': - case 'r': // probably uses %I - twelve_hour = true; - break; - case 'R': // uses %H - case 'T': // uses %H - case 'c': // probably uses %H - case 'X': // probably uses %H - twelve_hour = false; - break; - case 'z': - data = ParseOffset(data, "", &offset); - if (data != nullptr) saw_offset = true; - continue; - case 'Z': // ignored; zone abbreviations are ambiguous - data = ParseZone(data, &zone); - continue; - case 's': + case 'H': + data = ParseInt(data, 2, 0, 23, &tm.tm_hour); + twelve_hour = false; + continue; + case 'M': + data = ParseInt(data, 2, 0, 59, &tm.tm_min); + continue; + case 'S': + data = ParseInt(data, 2, 0, 60, &tm.tm_sec); + continue; + case 'I': + case 'l': + case 'r': // probably uses %I + twelve_hour = true; + break; + case 'R': // uses %H + case 'T': // uses %H + case 'c': // probably uses %H + case 'X': // probably uses %H + twelve_hour = false; + break; + case 'z': + data = ParseOffset(data, "", &offset); + if (data != nullptr) saw_offset = true; + continue; + case 'Z': // ignored; zone abbreviations are ambiguous + data = ParseZone(data, &zone); + continue; + case 's': data = ParseInt(data, 0, std::numeric_limits<std::int_fast64_t>::min(), std::numeric_limits<std::int_fast64_t>::max(), &percent_s); - if (data != nullptr) saw_percent_s = true; - continue; - case ':': - if (fmt[0] == 'z' || - (fmt[0] == ':' && - (fmt[1] == 'z' || (fmt[1] == ':' && fmt[2] == 'z')))) { - data = ParseOffset(data, ":", &offset); - if (data != nullptr) saw_offset = true; - fmt += (fmt[0] == 'z') ? 1 : (fmt[1] == 'z') ? 2 : 3; - continue; - } - break; - case '%': - data = (*data == '%' ? data + 1 : nullptr); - continue; - case 'E': + if (data != nullptr) saw_percent_s = true; + continue; + case ':': + if (fmt[0] == 'z' || + (fmt[0] == ':' && + (fmt[1] == 'z' || (fmt[1] == ':' && fmt[2] == 'z')))) { + data = ParseOffset(data, ":", &offset); + if (data != nullptr) saw_offset = true; + fmt += (fmt[0] == 'z') ? 1 : (fmt[1] == 'z') ? 2 : 3; + continue; + } + break; + case '%': + data = (*data == '%' ? data + 1 : nullptr); + continue; + case 'E': if (fmt[0] == 'T') { if (*data == 'T' || *data == 't') { ++data; @@ -841,138 +841,138 @@ bool parse(const TString& format, const TString& input, } continue; } - if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) { - data = ParseOffset(data, ":", &offset); - if (data != nullptr) saw_offset = true; - fmt += (fmt[0] == 'z') ? 1 : 2; - continue; - } - if (fmt[0] == '*' && fmt[1] == 'S') { - data = ParseInt(data, 2, 0, 60, &tm.tm_sec); - if (data != nullptr && *data == '.') { - data = ParseSubSeconds(data + 1, &subseconds); - } - fmt += 2; - continue; - } - if (fmt[0] == '*' && fmt[1] == 'f') { - if (data != nullptr && std::isdigit(*data)) { - data = ParseSubSeconds(data, &subseconds); - } - fmt += 2; - continue; - } - if (fmt[0] == '4' && fmt[1] == 'Y') { - const char* bp = data; - data = ParseInt(data, 4, year_t{-999}, year_t{9999}, &year); - if (data != nullptr) { - if (data - bp == 4) { - saw_year = true; - } else { - data = nullptr; // stopped too soon - } - } - fmt += 2; - continue; - } - if (std::isdigit(*fmt)) { - int n = 0; // value ignored - if (const char* np = ParseInt(fmt, 0, 0, 1024, &n)) { - if (*np == 'S') { - data = ParseInt(data, 2, 0, 60, &tm.tm_sec); - if (data != nullptr && *data == '.') { - data = ParseSubSeconds(data + 1, &subseconds); - } - fmt = ++np; - continue; - } - if (*np == 'f') { - if (data != nullptr && std::isdigit(*data)) { - data = ParseSubSeconds(data, &subseconds); - } - fmt = ++np; - continue; - } - } - } - if (*fmt == 'c') twelve_hour = false; // probably uses %H - if (*fmt == 'X') twelve_hour = false; // probably uses %H - if (*fmt != '\0') ++fmt; - break; - case 'O': - if (*fmt == 'H') twelve_hour = false; - if (*fmt == 'I') twelve_hour = true; - if (*fmt != '\0') ++fmt; - break; - } - - // Parses the current specifier. - const char* orig_data = data; + if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) { + data = ParseOffset(data, ":", &offset); + if (data != nullptr) saw_offset = true; + fmt += (fmt[0] == 'z') ? 1 : 2; + continue; + } + if (fmt[0] == '*' && fmt[1] == 'S') { + data = ParseInt(data, 2, 0, 60, &tm.tm_sec); + if (data != nullptr && *data == '.') { + data = ParseSubSeconds(data + 1, &subseconds); + } + fmt += 2; + continue; + } + if (fmt[0] == '*' && fmt[1] == 'f') { + if (data != nullptr && std::isdigit(*data)) { + data = ParseSubSeconds(data, &subseconds); + } + fmt += 2; + continue; + } + if (fmt[0] == '4' && fmt[1] == 'Y') { + const char* bp = data; + data = ParseInt(data, 4, year_t{-999}, year_t{9999}, &year); + if (data != nullptr) { + if (data - bp == 4) { + saw_year = true; + } else { + data = nullptr; // stopped too soon + } + } + fmt += 2; + continue; + } + if (std::isdigit(*fmt)) { + int n = 0; // value ignored + if (const char* np = ParseInt(fmt, 0, 0, 1024, &n)) { + if (*np == 'S') { + data = ParseInt(data, 2, 0, 60, &tm.tm_sec); + if (data != nullptr && *data == '.') { + data = ParseSubSeconds(data + 1, &subseconds); + } + fmt = ++np; + continue; + } + if (*np == 'f') { + if (data != nullptr && std::isdigit(*data)) { + data = ParseSubSeconds(data, &subseconds); + } + fmt = ++np; + continue; + } + } + } + if (*fmt == 'c') twelve_hour = false; // probably uses %H + if (*fmt == 'X') twelve_hour = false; // probably uses %H + if (*fmt != '\0') ++fmt; + break; + case 'O': + if (*fmt == 'H') twelve_hour = false; + if (*fmt == 'I') twelve_hour = true; + if (*fmt != '\0') ++fmt; + break; + } + + // Parses the current specifier. + const char* orig_data = data; TString spec(percent, static_cast<std::size_t>(fmt - percent)); - data = ParseTM(data, spec.c_str(), &tm); - - // If we successfully parsed %p we need to remember whether the result - // was AM or PM so that we can adjust tm_hour before time_zone::lookup(). - // So reparse the input with a known AM hour, and check if it is shifted - // to a PM hour. - if (spec == "%p" && data != nullptr) { + data = ParseTM(data, spec.c_str(), &tm); + + // If we successfully parsed %p we need to remember whether the result + // was AM or PM so that we can adjust tm_hour before time_zone::lookup(). + // So reparse the input with a known AM hour, and check if it is shifted + // to a PM hour. + if (spec == "%p" && data != nullptr) { TString test_input = "1"; - test_input.append(orig_data, static_cast<std::size_t>(data - orig_data)); - const char* test_data = test_input.c_str(); - std::tm tmp{}; - ParseTM(test_data, "%I%p", &tmp); - afternoon = (tmp.tm_hour == 13); - } - } - - // Adjust a 12-hour tm_hour value if it should be in the afternoon. - if (twelve_hour && afternoon && tm.tm_hour < 12) { - tm.tm_hour += 12; - } - - if (data == nullptr) { - if (err != nullptr) *err = "Failed to parse input"; - return false; - } - - // Skip any remaining whitespace. - while (std::isspace(*data)) ++data; - + test_input.append(orig_data, static_cast<std::size_t>(data - orig_data)); + const char* test_data = test_input.c_str(); + std::tm tmp{}; + ParseTM(test_data, "%I%p", &tmp); + afternoon = (tmp.tm_hour == 13); + } + } + + // Adjust a 12-hour tm_hour value if it should be in the afternoon. + if (twelve_hour && afternoon && tm.tm_hour < 12) { + tm.tm_hour += 12; + } + + if (data == nullptr) { + if (err != nullptr) *err = "Failed to parse input"; + return false; + } + + // Skip any remaining whitespace. + while (std::isspace(*data)) ++data; + // parse() must consume the entire input string. - if (*data != '\0') { - if (err != nullptr) *err = "Illegal trailing data in input string"; - return false; - } - - // If we saw %s then we ignore anything else and return that time. - if (saw_percent_s) { - *sec = FromUnixSeconds(percent_s); - *fs = detail::femtoseconds::zero(); - return true; - } - - // If we saw %z, %Ez, or %E*z then we want to interpret the parsed fields - // in UTC and then shift by that offset. Otherwise we want to interpret - // the fields directly in the passed time_zone. - time_zone ptz = saw_offset ? utc_time_zone() : tz; - - // Allows a leap second of 60 to normalize forward to the following ":00". - if (tm.tm_sec == 60) { - tm.tm_sec -= 1; - offset -= 1; - subseconds = detail::femtoseconds::zero(); - } - - if (!saw_year) { - year = year_t{tm.tm_year}; - if (year > kyearmax - 1900) { - // Platform-dependent, maybe unreachable. - if (err != nullptr) *err = "Out-of-range year"; - return false; - } - year += 1900; - } - + if (*data != '\0') { + if (err != nullptr) *err = "Illegal trailing data in input string"; + return false; + } + + // If we saw %s then we ignore anything else and return that time. + if (saw_percent_s) { + *sec = FromUnixSeconds(percent_s); + *fs = detail::femtoseconds::zero(); + return true; + } + + // If we saw %z, %Ez, or %E*z then we want to interpret the parsed fields + // in UTC and then shift by that offset. Otherwise we want to interpret + // the fields directly in the passed time_zone. + time_zone ptz = saw_offset ? utc_time_zone() : tz; + + // Allows a leap second of 60 to normalize forward to the following ":00". + if (tm.tm_sec == 60) { + tm.tm_sec -= 1; + offset -= 1; + subseconds = detail::femtoseconds::zero(); + } + + if (!saw_year) { + year = year_t{tm.tm_year}; + if (year > kyearmax - 1900) { + // Platform-dependent, maybe unreachable. + if (err != nullptr) *err = "Out-of-range year"; + return false; + } + year += 1900; + } + // Compute year, tm.tm_mon and tm.tm_mday if we parsed a week number. if (week_num != -1) { if (!FromWeek(week_num, week_start, &year, &tm)) { @@ -981,49 +981,49 @@ bool parse(const TString& format, const TString& input, } } - const int month = tm.tm_mon + 1; - civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); - - // parse() should not allow normalization. Due to the restricted field - // ranges above (see ParseInt()), the only possibility is for days to roll - // into months. That is, parsing "Sep 31" should not produce "Oct 1". - if (cs.month() != month || cs.day() != tm.tm_mday) { - if (err != nullptr) *err = "Out-of-range field"; - return false; - } - - // Accounts for the offset adjustment before converting to absolute time. - if ((offset < 0 && cs > civil_second::max() + offset) || - (offset > 0 && cs < civil_second::min() + offset)) { - if (err != nullptr) *err = "Out-of-range field"; - return false; - } - cs -= offset; - - const auto tp = ptz.lookup(cs).pre; - // Checks for overflow/underflow and returns an error as necessary. - if (tp == time_point<seconds>::max()) { - const auto al = ptz.lookup(time_point<seconds>::max()); - if (cs > al.cs) { - if (err != nullptr) *err = "Out-of-range field"; - return false; - } - } - if (tp == time_point<seconds>::min()) { - const auto al = ptz.lookup(time_point<seconds>::min()); - if (cs < al.cs) { - if (err != nullptr) *err = "Out-of-range field"; - return false; - } - } - - *sec = tp; - *fs = subseconds; - return true; -} - -} // namespace detail -} // namespace cctz -} // namespace time_internal + const int month = tm.tm_mon + 1; + civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + + // parse() should not allow normalization. Due to the restricted field + // ranges above (see ParseInt()), the only possibility is for days to roll + // into months. That is, parsing "Sep 31" should not produce "Oct 1". + if (cs.month() != month || cs.day() != tm.tm_mday) { + if (err != nullptr) *err = "Out-of-range field"; + return false; + } + + // Accounts for the offset adjustment before converting to absolute time. + if ((offset < 0 && cs > civil_second::max() + offset) || + (offset > 0 && cs < civil_second::min() + offset)) { + if (err != nullptr) *err = "Out-of-range field"; + return false; + } + cs -= offset; + + const auto tp = ptz.lookup(cs).pre; + // Checks for overflow/underflow and returns an error as necessary. + if (tp == time_point<seconds>::max()) { + const auto al = ptz.lookup(time_point<seconds>::max()); + if (cs > al.cs) { + if (err != nullptr) *err = "Out-of-range field"; + return false; + } + } + if (tp == time_point<seconds>::min()) { + const auto al = ptz.lookup(time_point<seconds>::min()); + if (cs < al.cs) { + if (err != nullptr) *err = "Out-of-range field"; + return false; + } + } + + *sec = tp; + *fs = subseconds; + return true; +} + +} // namespace detail +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_if.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_if.cc index c4df17f050..2fe6d23c71 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_if.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_if.cc @@ -1,45 +1,45 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "time_zone_if.h" +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "time_zone_if.h" #include "y_absl/base/config.h" -#include "time_zone_info.h" -#include "time_zone_libc.h" - +#include "time_zone_info.h" +#include "time_zone_libc.h" + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - +namespace time_internal { +namespace cctz { + std::unique_ptr<TimeZoneIf> TimeZoneIf::Load(const TString& name) { - // Support "libc:localtime" and "libc:*" to access the legacy - // localtime and UTC support respectively from the C library. - if (name.compare(0, 5, "libc:") == 0) { - return std::unique_ptr<TimeZoneIf>(new TimeZoneLibC(name.substr(5))); - } - - // Otherwise use the "zoneinfo" implementation by default. - std::unique_ptr<TimeZoneInfo> tz(new TimeZoneInfo); - if (!tz->Load(name)) tz.reset(); - return std::unique_ptr<TimeZoneIf>(tz.release()); -} - -// Defined out-of-line to avoid emitting a weak vtable in all TUs. -TimeZoneIf::~TimeZoneIf() {} - -} // namespace cctz -} // namespace time_internal + // Support "libc:localtime" and "libc:*" to access the legacy + // localtime and UTC support respectively from the C library. + if (name.compare(0, 5, "libc:") == 0) { + return std::unique_ptr<TimeZoneIf>(new TimeZoneLibC(name.substr(5))); + } + + // Otherwise use the "zoneinfo" implementation by default. + std::unique_ptr<TimeZoneInfo> tz(new TimeZoneInfo); + if (!tz->Load(name)) tz.reset(); + return std::unique_ptr<TimeZoneIf>(tz.release()); +} + +// Defined out-of-line to avoid emitting a weak vtable in all TUs. +TimeZoneIf::~TimeZoneIf() {} + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_if.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_if.h index 639891e772..10312badc2 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_if.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_if.h @@ -1,77 +1,77 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_ - -#include <chrono> -#include <cstdint> -#include <memory> +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_ +#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_ + +#include <chrono> +#include <cstdint> +#include <memory> #include <util/generic/string.h> - + #include "y_absl/base/config.h" #include "y_absl/time/internal/cctz/include/cctz/civil_time.h" #include "y_absl/time/internal/cctz/include/cctz/time_zone.h" - + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// A simple interface used to hide time-zone complexities from time_zone::Impl. -// Subclasses implement the functions for civil-time conversions in the zone. -class TimeZoneIf { - public: - // A factory function for TimeZoneIf implementations. +namespace time_internal { +namespace cctz { + +// A simple interface used to hide time-zone complexities from time_zone::Impl. +// Subclasses implement the functions for civil-time conversions in the zone. +class TimeZoneIf { + public: + // A factory function for TimeZoneIf implementations. static std::unique_ptr<TimeZoneIf> Load(const TString& name); - - virtual ~TimeZoneIf(); - - virtual time_zone::absolute_lookup BreakTime( - const time_point<seconds>& tp) const = 0; + + virtual ~TimeZoneIf(); + + virtual time_zone::absolute_lookup BreakTime( + const time_point<seconds>& tp) const = 0; virtual time_zone::civil_lookup MakeTime(const civil_second& cs) const = 0; - - virtual bool NextTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const = 0; - virtual bool PrevTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const = 0; - + + virtual bool NextTransition(const time_point<seconds>& tp, + time_zone::civil_transition* trans) const = 0; + virtual bool PrevTransition(const time_point<seconds>& tp, + time_zone::civil_transition* trans) const = 0; + virtual TString Version() const = 0; virtual TString Description() const = 0; - - protected: - TimeZoneIf() {} -}; - -// Convert between time_point<seconds> and a count of seconds since the -// Unix epoch. We assume that the std::chrono::system_clock and the + + protected: + TimeZoneIf() {} +}; + +// Convert between time_point<seconds> and a count of seconds since the +// Unix epoch. We assume that the std::chrono::system_clock and the // Unix clock are second aligned, and that the results are representable. // (That is, that they share an epoch, which is required since C++20.) -inline std::int_fast64_t ToUnixSeconds(const time_point<seconds>& tp) { - return (tp - std::chrono::time_point_cast<seconds>( +inline std::int_fast64_t ToUnixSeconds(const time_point<seconds>& tp) { + return (tp - std::chrono::time_point_cast<seconds>( std::chrono::system_clock::from_time_t(0))) .count(); -} -inline time_point<seconds> FromUnixSeconds(std::int_fast64_t t) { - return std::chrono::time_point_cast<seconds>( +} +inline time_point<seconds> FromUnixSeconds(std::int_fast64_t t) { + return std::chrono::time_point_cast<seconds>( std::chrono::system_clock::from_time_t(0)) + seconds(t); -} - -} // namespace cctz -} // namespace time_internal +} + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_ + +#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_impl.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_impl.cc index 02a1e1a17e..3810defe3c 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_impl.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_impl.cc @@ -1,113 +1,113 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "time_zone_impl.h" - -#include <deque> +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "time_zone_impl.h" + +#include <deque> #include <memory> -#include <mutex> +#include <mutex> #include <util/generic/string.h> -#include <unordered_map> -#include <utility> - +#include <unordered_map> +#include <utility> + #include "y_absl/base/config.h" -#include "time_zone_fixed.h" - +#include "time_zone_fixed.h" + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -// time_zone::Impls are linked into a map to support fast lookup by name. -using TimeZoneImplByName = +namespace time_internal { +namespace cctz { + +namespace { + +// time_zone::Impls are linked into a map to support fast lookup by name. +using TimeZoneImplByName = std::unordered_map<TString, const time_zone::Impl*>; -TimeZoneImplByName* time_zone_map = nullptr; - -// Mutual exclusion for time_zone_map. -std::mutex& TimeZoneMutex() { - // This mutex is intentionally "leaked" to avoid the static deinitialization - // order fiasco (std::mutex's destructor is not trivial on many platforms). - static std::mutex* time_zone_mutex = new std::mutex; - return *time_zone_mutex; -} - -} // namespace - +TimeZoneImplByName* time_zone_map = nullptr; + +// Mutual exclusion for time_zone_map. +std::mutex& TimeZoneMutex() { + // This mutex is intentionally "leaked" to avoid the static deinitialization + // order fiasco (std::mutex's destructor is not trivial on many platforms). + static std::mutex* time_zone_mutex = new std::mutex; + return *time_zone_mutex; +} + +} // namespace + time_zone time_zone::Impl::UTC() { return time_zone(UTCImpl()); } - + bool time_zone::Impl::LoadTimeZone(const TString& name, time_zone* tz) { const Impl* const utc_impl = UTCImpl(); - + // Check for UTC (which is never a key in time_zone_map). - auto offset = seconds::zero(); - if (FixedOffsetFromName(name, &offset) && offset == seconds::zero()) { - *tz = time_zone(utc_impl); - return true; - } - + auto offset = seconds::zero(); + if (FixedOffsetFromName(name, &offset) && offset == seconds::zero()) { + *tz = time_zone(utc_impl); + return true; + } + // Check whether the time zone has already been loaded. - { - std::lock_guard<std::mutex> lock(TimeZoneMutex()); - if (time_zone_map != nullptr) { - TimeZoneImplByName::const_iterator itr = time_zone_map->find(name); - if (itr != time_zone_map->end()) { - *tz = time_zone(itr->second); - return itr->second != utc_impl; - } - } - } - + { + std::lock_guard<std::mutex> lock(TimeZoneMutex()); + if (time_zone_map != nullptr) { + TimeZoneImplByName::const_iterator itr = time_zone_map->find(name); + if (itr != time_zone_map->end()) { + *tz = time_zone(itr->second); + return itr->second != utc_impl; + } + } + } + // Load the new time zone (outside the lock). std::unique_ptr<const Impl> new_impl(new Impl(name)); // Add the new time zone to the map. - std::lock_guard<std::mutex> lock(TimeZoneMutex()); - if (time_zone_map == nullptr) time_zone_map = new TimeZoneImplByName; - const Impl*& impl = (*time_zone_map)[name]; + std::lock_guard<std::mutex> lock(TimeZoneMutex()); + if (time_zone_map == nullptr) time_zone_map = new TimeZoneImplByName; + const Impl*& impl = (*time_zone_map)[name]; if (impl == nullptr) { // this thread won any load race impl = new_impl->zone_ ? new_impl.release() : utc_impl; - } - *tz = time_zone(impl); - return impl != utc_impl; -} - -void time_zone::Impl::ClearTimeZoneMapTestOnly() { - std::lock_guard<std::mutex> lock(TimeZoneMutex()); - if (time_zone_map != nullptr) { - // Existing time_zone::Impl* entries are in the wild, so we can't delete - // them. Instead, we move them to a private container, where they are - // logically unreachable but not "leaked". Future requests will result - // in reloading the data. - static auto* cleared = new std::deque<const time_zone::Impl*>; - for (const auto& element : *time_zone_map) { - cleared->push_back(element.second); - } - time_zone_map->clear(); - } -} - + } + *tz = time_zone(impl); + return impl != utc_impl; +} + +void time_zone::Impl::ClearTimeZoneMapTestOnly() { + std::lock_guard<std::mutex> lock(TimeZoneMutex()); + if (time_zone_map != nullptr) { + // Existing time_zone::Impl* entries are in the wild, so we can't delete + // them. Instead, we move them to a private container, where they are + // logically unreachable but not "leaked". Future requests will result + // in reloading the data. + static auto* cleared = new std::deque<const time_zone::Impl*>; + for (const auto& element : *time_zone_map) { + cleared->push_back(element.second); + } + time_zone_map->clear(); + } +} + time_zone::Impl::Impl(const TString& name) : name_(name), zone_(TimeZoneIf::Load(name_)) {} - -const time_zone::Impl* time_zone::Impl::UTCImpl() { + +const time_zone::Impl* time_zone::Impl::UTCImpl() { static const Impl* utc_impl = new Impl("UTC"); // never fails - return utc_impl; -} - -} // namespace cctz -} // namespace time_internal + return utc_impl; +} + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_impl.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_impl.h index 1a18623e3c..c014ab41df 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_impl.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_impl.h @@ -1,93 +1,93 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_ - -#include <memory> +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_ +#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_ + +#include <memory> #include <util/generic/string.h> - + #include "y_absl/base/config.h" #include "y_absl/time/internal/cctz/include/cctz/civil_time.h" #include "y_absl/time/internal/cctz/include/cctz/time_zone.h" -#include "time_zone_if.h" -#include "time_zone_info.h" - +#include "time_zone_if.h" +#include "time_zone_info.h" + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// time_zone::Impl is the internal object referenced by a cctz::time_zone. -class time_zone::Impl { - public: - // The UTC time zone. Also used for other time zones that fail to load. - static time_zone UTC(); - - // Load a named time zone. Returns false if the name is invalid, or if - // some other kind of error occurs. Note that loading "UTC" never fails. +namespace time_internal { +namespace cctz { + +// time_zone::Impl is the internal object referenced by a cctz::time_zone. +class time_zone::Impl { + public: + // The UTC time zone. Also used for other time zones that fail to load. + static time_zone UTC(); + + // Load a named time zone. Returns false if the name is invalid, or if + // some other kind of error occurs. Note that loading "UTC" never fails. static bool LoadTimeZone(const TString& name, time_zone* tz); - - // Clears the map of cached time zones. Primarily for use in benchmarks - // that gauge the performance of loading/parsing the time-zone data. - static void ClearTimeZoneMapTestOnly(); - - // The primary key is the time-zone ID (e.g., "America/New_York"). + + // Clears the map of cached time zones. Primarily for use in benchmarks + // that gauge the performance of loading/parsing the time-zone data. + static void ClearTimeZoneMapTestOnly(); + + // The primary key is the time-zone ID (e.g., "America/New_York"). const TString& Name() const { - // TODO: It would nice if the zoneinfo data included the zone name. - return name_; - } - - // Breaks a time_point down to civil-time components in this time zone. - time_zone::absolute_lookup BreakTime(const time_point<seconds>& tp) const { - return zone_->BreakTime(tp); - } - - // Converts the civil-time components in this time zone into a time_point. - // That is, the opposite of BreakTime(). The requested civil time may be - // ambiguous or illegal due to a change of UTC offset. - time_zone::civil_lookup MakeTime(const civil_second& cs) const { - return zone_->MakeTime(cs); - } - - // Finds the time of the next/previous offset change in this time zone. - bool NextTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const { - return zone_->NextTransition(tp, trans); - } - bool PrevTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const { - return zone_->PrevTransition(tp, trans); - } - + // TODO: It would nice if the zoneinfo data included the zone name. + return name_; + } + + // Breaks a time_point down to civil-time components in this time zone. + time_zone::absolute_lookup BreakTime(const time_point<seconds>& tp) const { + return zone_->BreakTime(tp); + } + + // Converts the civil-time components in this time zone into a time_point. + // That is, the opposite of BreakTime(). The requested civil time may be + // ambiguous or illegal due to a change of UTC offset. + time_zone::civil_lookup MakeTime(const civil_second& cs) const { + return zone_->MakeTime(cs); + } + + // Finds the time of the next/previous offset change in this time zone. + bool NextTransition(const time_point<seconds>& tp, + time_zone::civil_transition* trans) const { + return zone_->NextTransition(tp, trans); + } + bool PrevTransition(const time_point<seconds>& tp, + time_zone::civil_transition* trans) const { + return zone_->PrevTransition(tp, trans); + } + // Returns an implementation-defined version string for this time zone. TString Version() const { return zone_->Version(); } - - // Returns an implementation-defined description of this time zone. + + // Returns an implementation-defined description of this time zone. TString Description() const { return zone_->Description(); } - - private: + + private: explicit Impl(const TString& name); - static const Impl* UTCImpl(); - + static const Impl* UTCImpl(); + const TString name_; - std::unique_ptr<TimeZoneIf> zone_; -}; - -} // namespace cctz -} // namespace time_internal + std::unique_ptr<TimeZoneIf> zone_; +}; + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_ + +#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_info.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_info.cc index 1e04f60b49..72f7bdc3ca 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_info.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_info.cc @@ -1,89 +1,89 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file implements the TimeZoneIf interface using the "zoneinfo" -// data provided by the IANA Time Zone Database (i.e., the only real game -// in town). -// -// TimeZoneInfo represents the history of UTC-offset changes within a time -// zone. Most changes are due to daylight-saving rules, but occasionally -// shifts are made to the time-zone's base offset. The database only attempts -// to be definitive for times since 1970, so be wary of local-time conversions -// before that. Also, rule and zone-boundary changes are made at the whim -// of governments, so the conversion of future times needs to be taken with -// a grain of salt. -// -// For more information see tzfile(5), http://www.iana.org/time-zones, or -// https://en.wikipedia.org/wiki/Zoneinfo. -// -// Note that we assume the proleptic Gregorian calendar and 60-second -// minutes throughout. - -#include "time_zone_info.h" - -#include <algorithm> -#include <cassert> -#include <chrono> -#include <cstdint> -#include <cstdio> -#include <cstdlib> -#include <cstring> +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This file implements the TimeZoneIf interface using the "zoneinfo" +// data provided by the IANA Time Zone Database (i.e., the only real game +// in town). +// +// TimeZoneInfo represents the history of UTC-offset changes within a time +// zone. Most changes are due to daylight-saving rules, but occasionally +// shifts are made to the time-zone's base offset. The database only attempts +// to be definitive for times since 1970, so be wary of local-time conversions +// before that. Also, rule and zone-boundary changes are made at the whim +// of governments, so the conversion of future times needs to be taken with +// a grain of salt. +// +// For more information see tzfile(5), http://www.iana.org/time-zones, or +// https://en.wikipedia.org/wiki/Zoneinfo. +// +// Note that we assume the proleptic Gregorian calendar and 60-second +// minutes throughout. + +#include "time_zone_info.h" + +#include <algorithm> +#include <cassert> +#include <chrono> +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> #include <fstream> -#include <functional> -#include <memory> -#include <sstream> +#include <functional> +#include <memory> +#include <sstream> #include <util/generic/string.h> #include <utility> - + #include "y_absl/base/config.h" #include "y_absl/time/internal/cctz/include/cctz/civil_time.h" -#include "time_zone_fixed.h" -#include "time_zone_posix.h" - +#include "time_zone_fixed.h" +#include "time_zone_posix.h" + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -inline bool IsLeap(year_t year) { - return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0); -} - -// The number of days in non-leap and leap years respectively. -const std::int_least32_t kDaysPerYear[2] = {365, 366}; - -// The day offsets of the beginning of each (1-based) month in non-leap and -// leap years respectively (e.g., 335 days before December in a leap year). -const std::int_least16_t kMonthOffsets[2][1 + 12 + 1] = { +namespace time_internal { +namespace cctz { + +namespace { + +inline bool IsLeap(year_t year) { + return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0); +} + +// The number of days in non-leap and leap years respectively. +const std::int_least32_t kDaysPerYear[2] = {365, 366}; + +// The day offsets of the beginning of each (1-based) month in non-leap and +// leap years respectively (e.g., 335 days before December in a leap year). +const std::int_least16_t kMonthOffsets[2][1 + 12 + 1] = { {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}, -}; - -// We reject leap-second encoded zoneinfo and so assume 60-second minutes. -const std::int_least32_t kSecsPerDay = 24 * 60 * 60; - -// 400-year chunks always have 146097 days (20871 weeks). -const std::int_least64_t kSecsPer400Years = 146097LL * kSecsPerDay; - -// Like kDaysPerYear[] but scaled up by a factor of kSecsPerDay. -const std::int_least32_t kSecsPerYear[2] = { +}; + +// We reject leap-second encoded zoneinfo and so assume 60-second minutes. +const std::int_least32_t kSecsPerDay = 24 * 60 * 60; + +// 400-year chunks always have 146097 days (20871 weeks). +const std::int_least64_t kSecsPer400Years = 146097LL * kSecsPerDay; + +// Like kDaysPerYear[] but scaled up by a factor of kSecsPerDay. +const std::int_least32_t kSecsPerYear[2] = { 365 * kSecsPerDay, 366 * kSecsPerDay, -}; - +}; + // Convert a cctz::weekday to a POSIX TZ weekday number (0==Sun, ..., 6=Sat). inline int ToPosixWeekday(weekday wd) { switch (wd) { @@ -105,195 +105,195 @@ inline int ToPosixWeekday(weekday wd) { return 0; /*NOTREACHED*/ } -// Single-byte, unsigned numeric values are encoded directly. -inline std::uint_fast8_t Decode8(const char* cp) { - return static_cast<std::uint_fast8_t>(*cp) & 0xff; -} - -// Multi-byte, numeric values are encoded using a MSB first, -// twos-complement representation. These helpers decode, from -// the given address, 4-byte and 8-byte values respectively. -// Note: If int_fastXX_t == intXX_t and this machine is not -// twos complement, then there will be at least one input value -// we cannot represent. -std::int_fast32_t Decode32(const char* cp) { - std::uint_fast32_t v = 0; - for (int i = 0; i != (32 / 8); ++i) v = (v << 8) | Decode8(cp++); - const std::int_fast32_t s32max = 0x7fffffff; - const auto s32maxU = static_cast<std::uint_fast32_t>(s32max); - if (v <= s32maxU) return static_cast<std::int_fast32_t>(v); - return static_cast<std::int_fast32_t>(v - s32maxU - 1) - s32max - 1; -} - -std::int_fast64_t Decode64(const char* cp) { - std::uint_fast64_t v = 0; - for (int i = 0; i != (64 / 8); ++i) v = (v << 8) | Decode8(cp++); - const std::int_fast64_t s64max = 0x7fffffffffffffff; - const auto s64maxU = static_cast<std::uint_fast64_t>(s64max); - if (v <= s64maxU) return static_cast<std::int_fast64_t>(v); - return static_cast<std::int_fast64_t>(v - s64maxU - 1) - s64max - 1; -} - -// Generate a year-relative offset for a PosixTransition. -std::int_fast64_t TransOffset(bool leap_year, int jan1_weekday, - const PosixTransition& pt) { - std::int_fast64_t days = 0; - switch (pt.date.fmt) { - case PosixTransition::J: { - days = pt.date.j.day; - if (!leap_year || days < kMonthOffsets[1][3]) days -= 1; - break; - } - case PosixTransition::N: { - days = pt.date.n.day; - break; - } - case PosixTransition::M: { - const bool last_week = (pt.date.m.week == 5); - days = kMonthOffsets[leap_year][pt.date.m.month + last_week]; - const std::int_fast64_t weekday = (jan1_weekday + days) % 7; - if (last_week) { - days -= (weekday + 7 - 1 - pt.date.m.weekday) % 7 + 1; - } else { - days += (pt.date.m.weekday + 7 - weekday) % 7; - days += (pt.date.m.week - 1) * 7; - } - break; - } - } - return (days * kSecsPerDay) + pt.time.offset; -} - -inline time_zone::civil_lookup MakeUnique(const time_point<seconds>& tp) { - time_zone::civil_lookup cl; - cl.kind = time_zone::civil_lookup::UNIQUE; - cl.pre = cl.trans = cl.post = tp; - return cl; -} - -inline time_zone::civil_lookup MakeUnique(std::int_fast64_t unix_time) { - return MakeUnique(FromUnixSeconds(unix_time)); -} - -inline time_zone::civil_lookup MakeSkipped(const Transition& tr, - const civil_second& cs) { - time_zone::civil_lookup cl; - cl.kind = time_zone::civil_lookup::SKIPPED; - cl.pre = FromUnixSeconds(tr.unix_time - 1 + (cs - tr.prev_civil_sec)); - cl.trans = FromUnixSeconds(tr.unix_time); - cl.post = FromUnixSeconds(tr.unix_time - (tr.civil_sec - cs)); - return cl; -} - -inline time_zone::civil_lookup MakeRepeated(const Transition& tr, - const civil_second& cs) { - time_zone::civil_lookup cl; - cl.kind = time_zone::civil_lookup::REPEATED; - cl.pre = FromUnixSeconds(tr.unix_time - 1 - (tr.prev_civil_sec - cs)); - cl.trans = FromUnixSeconds(tr.unix_time); - cl.post = FromUnixSeconds(tr.unix_time + (cs - tr.civil_sec)); - return cl; -} - -inline civil_second YearShift(const civil_second& cs, year_t shift) { +// Single-byte, unsigned numeric values are encoded directly. +inline std::uint_fast8_t Decode8(const char* cp) { + return static_cast<std::uint_fast8_t>(*cp) & 0xff; +} + +// Multi-byte, numeric values are encoded using a MSB first, +// twos-complement representation. These helpers decode, from +// the given address, 4-byte and 8-byte values respectively. +// Note: If int_fastXX_t == intXX_t and this machine is not +// twos complement, then there will be at least one input value +// we cannot represent. +std::int_fast32_t Decode32(const char* cp) { + std::uint_fast32_t v = 0; + for (int i = 0; i != (32 / 8); ++i) v = (v << 8) | Decode8(cp++); + const std::int_fast32_t s32max = 0x7fffffff; + const auto s32maxU = static_cast<std::uint_fast32_t>(s32max); + if (v <= s32maxU) return static_cast<std::int_fast32_t>(v); + return static_cast<std::int_fast32_t>(v - s32maxU - 1) - s32max - 1; +} + +std::int_fast64_t Decode64(const char* cp) { + std::uint_fast64_t v = 0; + for (int i = 0; i != (64 / 8); ++i) v = (v << 8) | Decode8(cp++); + const std::int_fast64_t s64max = 0x7fffffffffffffff; + const auto s64maxU = static_cast<std::uint_fast64_t>(s64max); + if (v <= s64maxU) return static_cast<std::int_fast64_t>(v); + return static_cast<std::int_fast64_t>(v - s64maxU - 1) - s64max - 1; +} + +// Generate a year-relative offset for a PosixTransition. +std::int_fast64_t TransOffset(bool leap_year, int jan1_weekday, + const PosixTransition& pt) { + std::int_fast64_t days = 0; + switch (pt.date.fmt) { + case PosixTransition::J: { + days = pt.date.j.day; + if (!leap_year || days < kMonthOffsets[1][3]) days -= 1; + break; + } + case PosixTransition::N: { + days = pt.date.n.day; + break; + } + case PosixTransition::M: { + const bool last_week = (pt.date.m.week == 5); + days = kMonthOffsets[leap_year][pt.date.m.month + last_week]; + const std::int_fast64_t weekday = (jan1_weekday + days) % 7; + if (last_week) { + days -= (weekday + 7 - 1 - pt.date.m.weekday) % 7 + 1; + } else { + days += (pt.date.m.weekday + 7 - weekday) % 7; + days += (pt.date.m.week - 1) * 7; + } + break; + } + } + return (days * kSecsPerDay) + pt.time.offset; +} + +inline time_zone::civil_lookup MakeUnique(const time_point<seconds>& tp) { + time_zone::civil_lookup cl; + cl.kind = time_zone::civil_lookup::UNIQUE; + cl.pre = cl.trans = cl.post = tp; + return cl; +} + +inline time_zone::civil_lookup MakeUnique(std::int_fast64_t unix_time) { + return MakeUnique(FromUnixSeconds(unix_time)); +} + +inline time_zone::civil_lookup MakeSkipped(const Transition& tr, + const civil_second& cs) { + time_zone::civil_lookup cl; + cl.kind = time_zone::civil_lookup::SKIPPED; + cl.pre = FromUnixSeconds(tr.unix_time - 1 + (cs - tr.prev_civil_sec)); + cl.trans = FromUnixSeconds(tr.unix_time); + cl.post = FromUnixSeconds(tr.unix_time - (tr.civil_sec - cs)); + return cl; +} + +inline time_zone::civil_lookup MakeRepeated(const Transition& tr, + const civil_second& cs) { + time_zone::civil_lookup cl; + cl.kind = time_zone::civil_lookup::REPEATED; + cl.pre = FromUnixSeconds(tr.unix_time - 1 - (tr.prev_civil_sec - cs)); + cl.trans = FromUnixSeconds(tr.unix_time); + cl.post = FromUnixSeconds(tr.unix_time + (cs - tr.civil_sec)); + return cl; +} + +inline civil_second YearShift(const civil_second& cs, year_t shift) { return civil_second(cs.year() + shift, cs.month(), cs.day(), cs.hour(), cs.minute(), cs.second()); -} - -} // namespace - -// What (no leap-seconds) UTC+seconds zoneinfo would look like. -bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { - transition_types_.resize(1); - TransitionType& tt(transition_types_.back()); - tt.utc_offset = static_cast<std::int_least32_t>(offset.count()); - tt.is_dst = false; - tt.abbr_index = 0; - +} + +} // namespace + +// What (no leap-seconds) UTC+seconds zoneinfo would look like. +bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { + transition_types_.resize(1); + TransitionType& tt(transition_types_.back()); + tt.utc_offset = static_cast<std::int_least32_t>(offset.count()); + tt.is_dst = false; + tt.abbr_index = 0; + // We temporarily add some redundant, contemporary (2015 through 2025) - // transitions for performance reasons. See TimeZoneInfo::LocalTime(). - // TODO: Fix the performance issue and remove the extra transitions. - transitions_.clear(); - transitions_.reserve(12); - for (const std::int_fast64_t unix_time : { + // transitions for performance reasons. See TimeZoneInfo::LocalTime(). + // TODO: Fix the performance issue and remove the extra transitions. + transitions_.clear(); + transitions_.reserve(12); + for (const std::int_fast64_t unix_time : { -(1LL << 59), // a "first half" transition - 1420070400LL, // 2015-01-01T00:00:00+00:00 - 1451606400LL, // 2016-01-01T00:00:00+00:00 - 1483228800LL, // 2017-01-01T00:00:00+00:00 - 1514764800LL, // 2018-01-01T00:00:00+00:00 - 1546300800LL, // 2019-01-01T00:00:00+00:00 - 1577836800LL, // 2020-01-01T00:00:00+00:00 - 1609459200LL, // 2021-01-01T00:00:00+00:00 - 1640995200LL, // 2022-01-01T00:00:00+00:00 - 1672531200LL, // 2023-01-01T00:00:00+00:00 + 1420070400LL, // 2015-01-01T00:00:00+00:00 + 1451606400LL, // 2016-01-01T00:00:00+00:00 + 1483228800LL, // 2017-01-01T00:00:00+00:00 + 1514764800LL, // 2018-01-01T00:00:00+00:00 + 1546300800LL, // 2019-01-01T00:00:00+00:00 + 1577836800LL, // 2020-01-01T00:00:00+00:00 + 1609459200LL, // 2021-01-01T00:00:00+00:00 + 1640995200LL, // 2022-01-01T00:00:00+00:00 + 1672531200LL, // 2023-01-01T00:00:00+00:00 1704067200LL, // 2024-01-01T00:00:00+00:00 1735689600LL, // 2025-01-01T00:00:00+00:00 - }) { - Transition& tr(*transitions_.emplace(transitions_.end())); - tr.unix_time = unix_time; - tr.type_index = 0; - tr.civil_sec = LocalTime(tr.unix_time, tt).cs; - tr.prev_civil_sec = tr.civil_sec - 1; - } - - default_transition_type_ = 0; - abbreviations_ = FixedOffsetToAbbr(offset); + }) { + Transition& tr(*transitions_.emplace(transitions_.end())); + tr.unix_time = unix_time; + tr.type_index = 0; + tr.civil_sec = LocalTime(tr.unix_time, tt).cs; + tr.prev_civil_sec = tr.civil_sec - 1; + } + + default_transition_type_ = 0; + abbreviations_ = FixedOffsetToAbbr(offset); abbreviations_.append(1, '\0'); future_spec_.clear(); // never needed for a fixed-offset zone - extended_ = false; - - tt.civil_max = LocalTime(seconds::max().count(), tt).cs; - tt.civil_min = LocalTime(seconds::min().count(), tt).cs; - - transitions_.shrink_to_fit(); - return true; -} - -// Builds the in-memory header using the raw bytes from the file. -bool TimeZoneInfo::Header::Build(const tzhead& tzh) { - std::int_fast32_t v; - if ((v = Decode32(tzh.tzh_timecnt)) < 0) return false; - timecnt = static_cast<std::size_t>(v); - if ((v = Decode32(tzh.tzh_typecnt)) < 0) return false; - typecnt = static_cast<std::size_t>(v); - if ((v = Decode32(tzh.tzh_charcnt)) < 0) return false; - charcnt = static_cast<std::size_t>(v); - if ((v = Decode32(tzh.tzh_leapcnt)) < 0) return false; - leapcnt = static_cast<std::size_t>(v); - if ((v = Decode32(tzh.tzh_ttisstdcnt)) < 0) return false; - ttisstdcnt = static_cast<std::size_t>(v); - if ((v = Decode32(tzh.tzh_ttisutcnt)) < 0) return false; - ttisutcnt = static_cast<std::size_t>(v); - return true; -} - -// How many bytes of data are associated with this header. The result -// depends upon whether this is a section with 4-byte or 8-byte times. -std::size_t TimeZoneInfo::Header::DataLength(std::size_t time_len) const { - std::size_t len = 0; - len += (time_len + 1) * timecnt; // unix_time + type_index - len += (4 + 1 + 1) * typecnt; // utc_offset + is_dst + abbr_index - len += 1 * charcnt; // abbreviations - len += (time_len + 4) * leapcnt; // leap-time + TAI-UTC - len += 1 * ttisstdcnt; // UTC/local indicators - len += 1 * ttisutcnt; // standard/wall indicators - return len; -} - -// zic(8) can generate no-op transitions when a zone changes rules at an -// instant when there is actually no discontinuity. So we check whether -// two transitions have equivalent types (same offset/is_dst/abbr). -bool TimeZoneInfo::EquivTransitions(std::uint_fast8_t tt1_index, - std::uint_fast8_t tt2_index) const { - if (tt1_index == tt2_index) return true; - const TransitionType& tt1(transition_types_[tt1_index]); - const TransitionType& tt2(transition_types_[tt2_index]); + extended_ = false; + + tt.civil_max = LocalTime(seconds::max().count(), tt).cs; + tt.civil_min = LocalTime(seconds::min().count(), tt).cs; + + transitions_.shrink_to_fit(); + return true; +} + +// Builds the in-memory header using the raw bytes from the file. +bool TimeZoneInfo::Header::Build(const tzhead& tzh) { + std::int_fast32_t v; + if ((v = Decode32(tzh.tzh_timecnt)) < 0) return false; + timecnt = static_cast<std::size_t>(v); + if ((v = Decode32(tzh.tzh_typecnt)) < 0) return false; + typecnt = static_cast<std::size_t>(v); + if ((v = Decode32(tzh.tzh_charcnt)) < 0) return false; + charcnt = static_cast<std::size_t>(v); + if ((v = Decode32(tzh.tzh_leapcnt)) < 0) return false; + leapcnt = static_cast<std::size_t>(v); + if ((v = Decode32(tzh.tzh_ttisstdcnt)) < 0) return false; + ttisstdcnt = static_cast<std::size_t>(v); + if ((v = Decode32(tzh.tzh_ttisutcnt)) < 0) return false; + ttisutcnt = static_cast<std::size_t>(v); + return true; +} + +// How many bytes of data are associated with this header. The result +// depends upon whether this is a section with 4-byte or 8-byte times. +std::size_t TimeZoneInfo::Header::DataLength(std::size_t time_len) const { + std::size_t len = 0; + len += (time_len + 1) * timecnt; // unix_time + type_index + len += (4 + 1 + 1) * typecnt; // utc_offset + is_dst + abbr_index + len += 1 * charcnt; // abbreviations + len += (time_len + 4) * leapcnt; // leap-time + TAI-UTC + len += 1 * ttisstdcnt; // UTC/local indicators + len += 1 * ttisutcnt; // standard/wall indicators + return len; +} + +// zic(8) can generate no-op transitions when a zone changes rules at an +// instant when there is actually no discontinuity. So we check whether +// two transitions have equivalent types (same offset/is_dst/abbr). +bool TimeZoneInfo::EquivTransitions(std::uint_fast8_t tt1_index, + std::uint_fast8_t tt2_index) const { + if (tt1_index == tt2_index) return true; + const TransitionType& tt1(transition_types_[tt1_index]); + const TransitionType& tt2(transition_types_[tt2_index]); if (tt1.utc_offset != tt2.utc_offset) return false; - if (tt1.is_dst != tt2.is_dst) return false; - if (tt1.abbr_index != tt2.abbr_index) return false; - return true; -} - + if (tt1.is_dst != tt2.is_dst) return false; + if (tt1.abbr_index != tt2.abbr_index) return false; + return true; +} + // Find/make a transition type with these attributes. bool TimeZoneInfo::GetTransitionType(std::int_fast32_t utc_offset, bool is_dst, const TString& abbr, @@ -326,38 +326,38 @@ bool TimeZoneInfo::GetTransitionType(std::int_fast32_t utc_offset, bool is_dst, return true; } -// Use the POSIX-TZ-environment-variable-style string to handle times -// in years after the last transition stored in the zoneinfo data. +// Use the POSIX-TZ-environment-variable-style string to handle times +// in years after the last transition stored in the zoneinfo data. bool TimeZoneInfo::ExtendTransitions() { - extended_ = false; + extended_ = false; if (future_spec_.empty()) return true; // last transition prevails - - PosixTimeZone posix; + + PosixTimeZone posix; if (!ParsePosixSpec(future_spec_, &posix)) return false; - + // Find transition type for the future std specification. std::uint_least8_t std_ti; if (!GetTransitionType(posix.std_offset, false, posix.std_abbr, &std_ti)) return false; - + if (posix.dst_abbr.empty()) { // std only // The future specification should match the last transition, and // that means that handling the future will fall out naturally. return EquivTransitions(transitions_.back().type_index, std_ti); - } - + } + // Find transition type for the future dst specification. std::uint_least8_t dst_ti; if (!GetTransitionType(posix.dst_offset, true, posix.dst_abbr, &dst_ti)) return false; - - // Extend the transitions for an additional 400 years using the - // future specification. Years beyond those can be handled by - // mapping back to a cycle-equivalent year within that range. + + // Extend the transitions for an additional 400 years using the + // future specification. Years beyond those can be handled by + // mapping back to a cycle-equivalent year within that range. // We may need two additional transitions for the current year. transitions_.reserve(transitions_.size() + 400 * 2 + 2); - extended_ = true; - + extended_ = true; + const Transition& last(transitions_.back()); const std::int_fast64_t last_time = last.unix_time; const TransitionType& last_tt(transition_types_[last.type_index]); @@ -366,7 +366,7 @@ bool TimeZoneInfo::ExtendTransitions() { const civil_second jan1(last_year_); std::int_fast64_t jan1_time = jan1 - civil_second(); int jan1_weekday = ToPosixWeekday(get_weekday(jan1)); - + Transition dst = {0, dst_ti, civil_second(), civil_second()}; Transition std = {0, std_ti, civil_second(), civil_second()}; for (const year_t limit = last_year_ + 400;; ++last_year_) { @@ -381,161 +381,161 @@ bool TimeZoneInfo::ExtendTransitions() { transitions_.push_back(*tb); } if (last_year_ == limit) break; - jan1_time += kSecsPerYear[leap_year]; - jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7; + jan1_time += kSecsPerYear[leap_year]; + jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7; leap_year = !leap_year && IsLeap(last_year_ + 1); - } + } return true; -} - +} + bool TimeZoneInfo::Load(ZoneInfoSource* zip) { - // Read and validate the header. - tzhead tzh; + // Read and validate the header. + tzhead tzh; if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false; - if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0) - return false; - Header hdr; + if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0) + return false; + Header hdr; if (!hdr.Build(tzh)) return false; - std::size_t time_len = 4; - if (tzh.tzh_version[0] != '\0') { - // Skip the 4-byte data. + std::size_t time_len = 4; + if (tzh.tzh_version[0] != '\0') { + // Skip the 4-byte data. if (zip->Skip(hdr.DataLength(time_len)) != 0) return false; - // Read and validate the header for the 8-byte data. + // Read and validate the header for the 8-byte data. if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false; - if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0) - return false; + if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0) + return false; if (tzh.tzh_version[0] == '\0') return false; if (!hdr.Build(tzh)) return false; - time_len = 8; - } + time_len = 8; + } if (hdr.typecnt == 0) return false; - if (hdr.leapcnt != 0) { - // This code assumes 60-second minutes so we do not want - // the leap-second encoded zoneinfo. We could reverse the - // compensation, but the "right" encoding is rarely used - // so currently we simply reject such data. - return false; - } + if (hdr.leapcnt != 0) { + // This code assumes 60-second minutes so we do not want + // the leap-second encoded zoneinfo. We could reverse the + // compensation, but the "right" encoding is rarely used + // so currently we simply reject such data. + return false; + } if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt) return false; if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt) return false; - - // Read the data into a local buffer. - std::size_t len = hdr.DataLength(time_len); - std::vector<char> tbuf(len); + + // Read the data into a local buffer. + std::size_t len = hdr.DataLength(time_len); + std::vector<char> tbuf(len); if (zip->Read(tbuf.data(), len) != len) return false; - const char* bp = tbuf.data(); - - // Decode and validate the transitions. + const char* bp = tbuf.data(); + + // Decode and validate the transitions. transitions_.reserve(hdr.timecnt + 2); - transitions_.resize(hdr.timecnt); - for (std::size_t i = 0; i != hdr.timecnt; ++i) { - transitions_[i].unix_time = (time_len == 4) ? Decode32(bp) : Decode64(bp); - bp += time_len; - if (i != 0) { - // Check that the transitions are ordered by time (as zic guarantees). - if (!Transition::ByUnixTime()(transitions_[i - 1], transitions_[i])) - return false; // out of order - } - } - bool seen_type_0 = false; - for (std::size_t i = 0; i != hdr.timecnt; ++i) { - transitions_[i].type_index = Decode8(bp++); + transitions_.resize(hdr.timecnt); + for (std::size_t i = 0; i != hdr.timecnt; ++i) { + transitions_[i].unix_time = (time_len == 4) ? Decode32(bp) : Decode64(bp); + bp += time_len; + if (i != 0) { + // Check that the transitions are ordered by time (as zic guarantees). + if (!Transition::ByUnixTime()(transitions_[i - 1], transitions_[i])) + return false; // out of order + } + } + bool seen_type_0 = false; + for (std::size_t i = 0; i != hdr.timecnt; ++i) { + transitions_[i].type_index = Decode8(bp++); if (transitions_[i].type_index >= hdr.typecnt) return false; if (transitions_[i].type_index == 0) seen_type_0 = true; - } - - // Decode and validate the transition types. + } + + // Decode and validate the transition types. transition_types_.reserve(hdr.typecnt + 2); - transition_types_.resize(hdr.typecnt); - for (std::size_t i = 0; i != hdr.typecnt; ++i) { - transition_types_[i].utc_offset = - static_cast<std::int_least32_t>(Decode32(bp)); - if (transition_types_[i].utc_offset >= kSecsPerDay || - transition_types_[i].utc_offset <= -kSecsPerDay) - return false; - bp += 4; - transition_types_[i].is_dst = (Decode8(bp++) != 0); - transition_types_[i].abbr_index = Decode8(bp++); + transition_types_.resize(hdr.typecnt); + for (std::size_t i = 0; i != hdr.typecnt; ++i) { + transition_types_[i].utc_offset = + static_cast<std::int_least32_t>(Decode32(bp)); + if (transition_types_[i].utc_offset >= kSecsPerDay || + transition_types_[i].utc_offset <= -kSecsPerDay) + return false; + bp += 4; + transition_types_[i].is_dst = (Decode8(bp++) != 0); + transition_types_[i].abbr_index = Decode8(bp++); if (transition_types_[i].abbr_index >= hdr.charcnt) return false; - } - - // Determine the before-first-transition type. - default_transition_type_ = 0; - if (seen_type_0 && hdr.timecnt != 0) { - std::uint_fast8_t index = 0; - if (transition_types_[0].is_dst) { - index = transitions_[0].type_index; + } + + // Determine the before-first-transition type. + default_transition_type_ = 0; + if (seen_type_0 && hdr.timecnt != 0) { + std::uint_fast8_t index = 0; + if (transition_types_[0].is_dst) { + index = transitions_[0].type_index; while (index != 0 && transition_types_[index].is_dst) --index; - } + } while (index != hdr.typecnt && transition_types_[index].is_dst) ++index; if (index != hdr.typecnt) default_transition_type_ = index; - } - - // Copy all the abbreviations. + } + + // Copy all the abbreviations. abbreviations_.reserve(hdr.charcnt + 10); - abbreviations_.assign(bp, hdr.charcnt); - bp += hdr.charcnt; - - // Skip the unused portions. We've already dispensed with leap-second - // encoded zoneinfo. The ttisstd/ttisgmt indicators only apply when - // interpreting a POSIX spec that does not include start/end rules, and - // that isn't the case here (see "zic -p"). - bp += (8 + 4) * hdr.leapcnt; // leap-time + TAI-UTC - bp += 1 * hdr.ttisstdcnt; // UTC/local indicators - bp += 1 * hdr.ttisutcnt; // standard/wall indicators - assert(bp == tbuf.data() + tbuf.size()); - - future_spec_.clear(); - if (tzh.tzh_version[0] != '\0') { - // Snarf up the NL-enclosed future POSIX spec. Note - // that version '3' files utilize an extended format. - auto get_char = [](ZoneInfoSource* azip) -> int { - unsigned char ch; // all non-EOF results are positive - return (azip->Read(&ch, 1) == 1) ? ch : EOF; - }; + abbreviations_.assign(bp, hdr.charcnt); + bp += hdr.charcnt; + + // Skip the unused portions. We've already dispensed with leap-second + // encoded zoneinfo. The ttisstd/ttisgmt indicators only apply when + // interpreting a POSIX spec that does not include start/end rules, and + // that isn't the case here (see "zic -p"). + bp += (8 + 4) * hdr.leapcnt; // leap-time + TAI-UTC + bp += 1 * hdr.ttisstdcnt; // UTC/local indicators + bp += 1 * hdr.ttisutcnt; // standard/wall indicators + assert(bp == tbuf.data() + tbuf.size()); + + future_spec_.clear(); + if (tzh.tzh_version[0] != '\0') { + // Snarf up the NL-enclosed future POSIX spec. Note + // that version '3' files utilize an extended format. + auto get_char = [](ZoneInfoSource* azip) -> int { + unsigned char ch; // all non-EOF results are positive + return (azip->Read(&ch, 1) == 1) ? ch : EOF; + }; if (get_char(zip) != '\n') return false; - for (int c = get_char(zip); c != '\n'; c = get_char(zip)) { + for (int c = get_char(zip); c != '\n'; c = get_char(zip)) { if (c == EOF) return false; - future_spec_.push_back(static_cast<char>(c)); - } - } - - // We don't check for EOF so that we're forwards compatible. - - // If we did not find version information during the standard loading - // process (as of tzh_version '3' that is unsupported), then ask the + future_spec_.push_back(static_cast<char>(c)); + } + } + + // We don't check for EOF so that we're forwards compatible. + + // If we did not find version information during the standard loading + // process (as of tzh_version '3' that is unsupported), then ask the // ZoneInfoSource for any out-of-bound version string it may be privy to. - if (version_.empty()) { - version_ = zip->Version(); - } - - // Trim redundant transitions. zic may have added these to work around - // differences between the glibc and reference implementations (see - // zic.c:dontmerge) and the Qt library (see zic.c:WORK_AROUND_QTBUG_53071). - // For us, they just get in the way when we do future_spec_ extension. - while (hdr.timecnt > 1) { - if (!EquivTransitions(transitions_[hdr.timecnt - 1].type_index, - transitions_[hdr.timecnt - 2].type_index)) { - break; - } - hdr.timecnt -= 1; - } - transitions_.resize(hdr.timecnt); - - // Ensure that there is always a transition in the first half of the + if (version_.empty()) { + version_ = zip->Version(); + } + + // Trim redundant transitions. zic may have added these to work around + // differences between the glibc and reference implementations (see + // zic.c:dontmerge) and the Qt library (see zic.c:WORK_AROUND_QTBUG_53071). + // For us, they just get in the way when we do future_spec_ extension. + while (hdr.timecnt > 1) { + if (!EquivTransitions(transitions_[hdr.timecnt - 1].type_index, + transitions_[hdr.timecnt - 2].type_index)) { + break; + } + hdr.timecnt -= 1; + } + transitions_.resize(hdr.timecnt); + + // Ensure that there is always a transition in the first half of the // time line (the second half is handled below) so that the signed // difference between a civil_second and the civil_second of its // previous transition is always representable, without overflow. - if (transitions_.empty() || transitions_.front().unix_time >= 0) { - Transition& tr(*transitions_.emplace(transitions_.begin())); + if (transitions_.empty() || transitions_.front().unix_time >= 0) { + Transition& tr(*transitions_.emplace(transitions_.begin())); tr.unix_time = -(1LL << 59); // -18267312070-10-26T17:01:52+00:00 - tr.type_index = default_transition_type_; - } - - // Extend the transitions using the future specification. + tr.type_index = default_transition_type_; + } + + // Extend the transitions using the future specification. if (!ExtendTransitions()) return false; - + // Ensure that there is always a transition in the second half of the // time line (the first half is handled above) so that the signed // difference between a civil_second and the civil_second of its @@ -548,167 +548,167 @@ bool TimeZoneInfo::Load(ZoneInfoSource* zip) { tr.type_index = type_index; } - // Compute the local civil time for each transition and the preceding - // second. These will be used for reverse conversions in MakeTime(). - const TransitionType* ttp = &transition_types_[default_transition_type_]; - for (std::size_t i = 0; i != transitions_.size(); ++i) { - Transition& tr(transitions_[i]); - tr.prev_civil_sec = LocalTime(tr.unix_time, *ttp).cs - 1; - ttp = &transition_types_[tr.type_index]; - tr.civil_sec = LocalTime(tr.unix_time, *ttp).cs; - if (i != 0) { - // Check that the transitions are ordered by civil time. Essentially - // this means that an offset change cannot cross another such change. - // No one does this in practice, and we depend on it in MakeTime(). - if (!Transition::ByCivilTime()(transitions_[i - 1], tr)) - return false; // out of order - } - } - - // Compute the maximum/minimum civil times that can be converted to a - // time_point<seconds> for each of the zone's transition types. - for (auto& tt : transition_types_) { - tt.civil_max = LocalTime(seconds::max().count(), tt).cs; - tt.civil_min = LocalTime(seconds::min().count(), tt).cs; - } - - transitions_.shrink_to_fit(); - return true; -} - -namespace { - + // Compute the local civil time for each transition and the preceding + // second. These will be used for reverse conversions in MakeTime(). + const TransitionType* ttp = &transition_types_[default_transition_type_]; + for (std::size_t i = 0; i != transitions_.size(); ++i) { + Transition& tr(transitions_[i]); + tr.prev_civil_sec = LocalTime(tr.unix_time, *ttp).cs - 1; + ttp = &transition_types_[tr.type_index]; + tr.civil_sec = LocalTime(tr.unix_time, *ttp).cs; + if (i != 0) { + // Check that the transitions are ordered by civil time. Essentially + // this means that an offset change cannot cross another such change. + // No one does this in practice, and we depend on it in MakeTime(). + if (!Transition::ByCivilTime()(transitions_[i - 1], tr)) + return false; // out of order + } + } + + // Compute the maximum/minimum civil times that can be converted to a + // time_point<seconds> for each of the zone's transition types. + for (auto& tt : transition_types_) { + tt.civil_max = LocalTime(seconds::max().count(), tt).cs; + tt.civil_min = LocalTime(seconds::min().count(), tt).cs; + } + + transitions_.shrink_to_fit(); + return true; +} + +namespace { + using FilePtr = std::unique_ptr<FILE, int (*)(FILE*)>; -// fopen(3) adaptor. +// fopen(3) adaptor. inline FilePtr FOpen(const char* path, const char* mode) { -#if defined(_MSC_VER) - FILE* fp; - if (fopen_s(&fp, path, mode) != 0) fp = nullptr; +#if defined(_MSC_VER) + FILE* fp; + if (fopen_s(&fp, path, mode) != 0) fp = nullptr; return FilePtr(fp, fclose); -#else +#else // TODO: Enable the close-on-exec flag. return FilePtr(fopen(path, mode), fclose); -#endif -} - -// A stdio(3)-backed implementation of ZoneInfoSource. -class FileZoneInfoSource : public ZoneInfoSource { - public: +#endif +} + +// A stdio(3)-backed implementation of ZoneInfoSource. +class FileZoneInfoSource : public ZoneInfoSource { + public: static std::unique_ptr<ZoneInfoSource> Open(const TString& name); - - std::size_t Read(void* ptr, std::size_t size) override { - size = std::min(size, len_); - std::size_t nread = fread(ptr, 1, size, fp_.get()); - len_ -= nread; - return nread; - } - int Skip(std::size_t offset) override { - offset = std::min(offset, len_); - int rc = fseek(fp_.get(), static_cast<long>(offset), SEEK_CUR); - if (rc == 0) len_ -= offset; - return rc; - } + + std::size_t Read(void* ptr, std::size_t size) override { + size = std::min(size, len_); + std::size_t nread = fread(ptr, 1, size, fp_.get()); + len_ -= nread; + return nread; + } + int Skip(std::size_t offset) override { + offset = std::min(offset, len_); + int rc = fseek(fp_.get(), static_cast<long>(offset), SEEK_CUR); + if (rc == 0) len_ -= offset; + return rc; + } TString Version() const override { - // TODO: It would nice if the zoneinfo data included the tzdb version. + // TODO: It would nice if the zoneinfo data included the tzdb version. return TString(); - } - - protected: - explicit FileZoneInfoSource( + } + + protected: + explicit FileZoneInfoSource( FilePtr fp, std::size_t len = std::numeric_limits<std::size_t>::max()) : fp_(std::move(fp)), len_(len) {} - - private: + + private: FilePtr fp_; - std::size_t len_; -}; - -std::unique_ptr<ZoneInfoSource> FileZoneInfoSource::Open( + std::size_t len_; +}; + +std::unique_ptr<ZoneInfoSource> FileZoneInfoSource::Open( const TString& name) { - // Use of the "file:" prefix is intended for testing purposes only. - const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0; - - // Map the time-zone name to a path name. + // Use of the "file:" prefix is intended for testing purposes only. + const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0; + + // Map the time-zone name to a path name. TString path; - if (pos == name.size() || name[pos] != '/') { - const char* tzdir = "/usr/share/zoneinfo"; - char* tzdir_env = nullptr; -#if defined(_MSC_VER) - _dupenv_s(&tzdir_env, nullptr, "TZDIR"); -#else - tzdir_env = std::getenv("TZDIR"); -#endif - if (tzdir_env && *tzdir_env) tzdir = tzdir_env; - path += tzdir; - path += '/'; -#if defined(_MSC_VER) - free(tzdir_env); -#endif - } + if (pos == name.size() || name[pos] != '/') { + const char* tzdir = "/usr/share/zoneinfo"; + char* tzdir_env = nullptr; +#if defined(_MSC_VER) + _dupenv_s(&tzdir_env, nullptr, "TZDIR"); +#else + tzdir_env = std::getenv("TZDIR"); +#endif + if (tzdir_env && *tzdir_env) tzdir = tzdir_env; + path += tzdir; + path += '/'; +#if defined(_MSC_VER) + free(tzdir_env); +#endif + } path.append(name, pos, TString::npos); - - // Open the zoneinfo file. + + // Open the zoneinfo file. auto fp = FOpen(path.c_str(), "rb"); - if (fp == nullptr) return nullptr; + if (fp == nullptr) return nullptr; return std::unique_ptr<ZoneInfoSource>(new FileZoneInfoSource(std::move(fp))); -} - -class AndroidZoneInfoSource : public FileZoneInfoSource { - public: +} + +class AndroidZoneInfoSource : public FileZoneInfoSource { + public: static std::unique_ptr<ZoneInfoSource> Open(const TString& name); TString Version() const override { return version_; } - - private: + + private: explicit AndroidZoneInfoSource(FilePtr fp, std::size_t len, TString version) : FileZoneInfoSource(std::move(fp), len), version_(std::move(version)) {} TString version_; -}; - -std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open( +}; + +std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open( const TString& name) { - // Use of the "file:" prefix is intended for testing purposes only. - const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0; - - // See Android's libc/tzcode/bionic.cpp for additional information. - for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata", - "/system/usr/share/zoneinfo/tzdata"}) { + // Use of the "file:" prefix is intended for testing purposes only. + const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0; + + // See Android's libc/tzcode/bionic.cpp for additional information. + for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata", + "/system/usr/share/zoneinfo/tzdata"}) { auto fp = FOpen(tzdata, "rb"); if (fp == nullptr) continue; - - char hbuf[24]; // covers header.zonetab_offset too - if (fread(hbuf, 1, sizeof(hbuf), fp.get()) != sizeof(hbuf)) continue; - if (strncmp(hbuf, "tzdata", 6) != 0) continue; - const char* vers = (hbuf[11] == '\0') ? hbuf + 6 : ""; - const std::int_fast32_t index_offset = Decode32(hbuf + 12); - const std::int_fast32_t data_offset = Decode32(hbuf + 16); - if (index_offset < 0 || data_offset < index_offset) continue; - if (fseek(fp.get(), static_cast<long>(index_offset), SEEK_SET) != 0) - continue; - - char ebuf[52]; // covers entry.unused too - const std::size_t index_size = - static_cast<std::size_t>(data_offset - index_offset); - const std::size_t zonecnt = index_size / sizeof(ebuf); - if (zonecnt * sizeof(ebuf) != index_size) continue; - for (std::size_t i = 0; i != zonecnt; ++i) { - if (fread(ebuf, 1, sizeof(ebuf), fp.get()) != sizeof(ebuf)) break; - const std::int_fast32_t start = data_offset + Decode32(ebuf + 40); - const std::int_fast32_t length = Decode32(ebuf + 44); - if (start < 0 || length < 0) break; - ebuf[40] = '\0'; // ensure zone name is NUL terminated - if (strcmp(name.c_str() + pos, ebuf) == 0) { - if (fseek(fp.get(), static_cast<long>(start), SEEK_SET) != 0) break; - return std::unique_ptr<ZoneInfoSource>(new AndroidZoneInfoSource( + + char hbuf[24]; // covers header.zonetab_offset too + if (fread(hbuf, 1, sizeof(hbuf), fp.get()) != sizeof(hbuf)) continue; + if (strncmp(hbuf, "tzdata", 6) != 0) continue; + const char* vers = (hbuf[11] == '\0') ? hbuf + 6 : ""; + const std::int_fast32_t index_offset = Decode32(hbuf + 12); + const std::int_fast32_t data_offset = Decode32(hbuf + 16); + if (index_offset < 0 || data_offset < index_offset) continue; + if (fseek(fp.get(), static_cast<long>(index_offset), SEEK_SET) != 0) + continue; + + char ebuf[52]; // covers entry.unused too + const std::size_t index_size = + static_cast<std::size_t>(data_offset - index_offset); + const std::size_t zonecnt = index_size / sizeof(ebuf); + if (zonecnt * sizeof(ebuf) != index_size) continue; + for (std::size_t i = 0; i != zonecnt; ++i) { + if (fread(ebuf, 1, sizeof(ebuf), fp.get()) != sizeof(ebuf)) break; + const std::int_fast32_t start = data_offset + Decode32(ebuf + 40); + const std::int_fast32_t length = Decode32(ebuf + 44); + if (start < 0 || length < 0) break; + ebuf[40] = '\0'; // ensure zone name is NUL terminated + if (strcmp(name.c_str() + pos, ebuf) == 0) { + if (fseek(fp.get(), static_cast<long>(start), SEEK_SET) != 0) break; + return std::unique_ptr<ZoneInfoSource>(new AndroidZoneInfoSource( std::move(fp), static_cast<std::size_t>(length), vers)); - } - } - } - - return nullptr; -} - + } + } + } + + return nullptr; +} + // A zoneinfo source for use inside Fuchsia components. This attempts to // read zoneinfo files from one of several known paths in a component's // incoming namespace. [Config data][1] is preferred, but package-specific @@ -772,256 +772,256 @@ std::unique_ptr<ZoneInfoSource> FuchsiaZoneInfoSource::Open( return nullptr; } -} // namespace - +} // namespace + bool TimeZoneInfo::Load(const TString& name) { - // We can ensure that the loading of UTC or any other fixed-offset - // zone never fails because the simple, fixed-offset state can be - // internally generated. Note that this depends on our choice to not - // accept leap-second encoded ("right") zoneinfo. - auto offset = seconds::zero(); - if (FixedOffsetFromName(name, &offset)) { - return ResetToBuiltinUTC(offset); - } - - // Find and use a ZoneInfoSource to load the named zone. - auto zip = cctz_extension::zone_info_source_factory( + // We can ensure that the loading of UTC or any other fixed-offset + // zone never fails because the simple, fixed-offset state can be + // internally generated. Note that this depends on our choice to not + // accept leap-second encoded ("right") zoneinfo. + auto offset = seconds::zero(); + if (FixedOffsetFromName(name, &offset)) { + return ResetToBuiltinUTC(offset); + } + + // Find and use a ZoneInfoSource to load the named zone. + auto zip = cctz_extension::zone_info_source_factory( name, [](const TString& n) -> std::unique_ptr<ZoneInfoSource> { if (auto z = FileZoneInfoSource::Open(n)) return z; if (auto z = AndroidZoneInfoSource::Open(n)) return z; if (auto z = FuchsiaZoneInfoSource::Open(n)) return z; - return nullptr; - }); + return nullptr; + }); return zip != nullptr && Load(zip.get()); -} - -// BreakTime() translation for a particular transition type. -time_zone::absolute_lookup TimeZoneInfo::LocalTime( - std::int_fast64_t unix_time, const TransitionType& tt) const { - // A civil time in "+offset" looks like (time+offset) in UTC. - // Note: We perform two additions in the civil_second domain to - // sidestep the chance of overflow in (unix_time + tt.utc_offset). +} + +// BreakTime() translation for a particular transition type. +time_zone::absolute_lookup TimeZoneInfo::LocalTime( + std::int_fast64_t unix_time, const TransitionType& tt) const { + // A civil time in "+offset" looks like (time+offset) in UTC. + // Note: We perform two additions in the civil_second domain to + // sidestep the chance of overflow in (unix_time + tt.utc_offset). return {(civil_second() + unix_time) + tt.utc_offset, tt.utc_offset, tt.is_dst, &*abbreviations_.begin() + tt.abbr_index}; -} - -// BreakTime() translation for a particular transition. +} + +// BreakTime() translation for a particular transition. time_zone::absolute_lookup TimeZoneInfo::LocalTime(std::int_fast64_t unix_time, const Transition& tr) const { - const TransitionType& tt = transition_types_[tr.type_index]; - // Note: (unix_time - tr.unix_time) will never overflow as we - // have ensured that there is always a "nearby" transition. - return {tr.civil_sec + (unix_time - tr.unix_time), // TODO: Optimize. + const TransitionType& tt = transition_types_[tr.type_index]; + // Note: (unix_time - tr.unix_time) will never overflow as we + // have ensured that there is always a "nearby" transition. + return {tr.civil_sec + (unix_time - tr.unix_time), // TODO: Optimize. tt.utc_offset, tt.is_dst, &*abbreviations_.begin() + tt.abbr_index}; -} - -// MakeTime() translation with a conversion-preserving +N * 400-year shift. -time_zone::civil_lookup TimeZoneInfo::TimeLocal(const civil_second& cs, - year_t c4_shift) const { - assert(last_year_ - 400 < cs.year() && cs.year() <= last_year_); - time_zone::civil_lookup cl = MakeTime(cs); - if (c4_shift > seconds::max().count() / kSecsPer400Years) { - cl.pre = cl.trans = cl.post = time_point<seconds>::max(); - } else { - const auto offset = seconds(c4_shift * kSecsPer400Years); - const auto limit = time_point<seconds>::max() - offset; - for (auto* tp : {&cl.pre, &cl.trans, &cl.post}) { - if (*tp > limit) { - *tp = time_point<seconds>::max(); - } else { - *tp += offset; - } - } - } - return cl; -} - -time_zone::absolute_lookup TimeZoneInfo::BreakTime( - const time_point<seconds>& tp) const { - std::int_fast64_t unix_time = ToUnixSeconds(tp); - const std::size_t timecnt = transitions_.size(); - assert(timecnt != 0); // We always add a transition. - - if (unix_time < transitions_[0].unix_time) { - return LocalTime(unix_time, transition_types_[default_transition_type_]); - } - if (unix_time >= transitions_[timecnt - 1].unix_time) { - // After the last transition. If we extended the transitions using - // future_spec_, shift back to a supported year using the 400-year - // cycle of calendaric equivalence and then compensate accordingly. - if (extended_) { - const std::int_fast64_t diff = - unix_time - transitions_[timecnt - 1].unix_time; - const year_t shift = diff / kSecsPer400Years + 1; - const auto d = seconds(shift * kSecsPer400Years); - time_zone::absolute_lookup al = BreakTime(tp - d); - al.cs = YearShift(al.cs, shift * 400); - return al; - } - return LocalTime(unix_time, transitions_[timecnt - 1]); - } - - const std::size_t hint = local_time_hint_.load(std::memory_order_relaxed); - if (0 < hint && hint < timecnt) { - if (transitions_[hint - 1].unix_time <= unix_time) { - if (unix_time < transitions_[hint].unix_time) { - return LocalTime(unix_time, transitions_[hint - 1]); - } - } - } - - const Transition target = {unix_time, 0, civil_second(), civil_second()}; - const Transition* begin = &transitions_[0]; - const Transition* tr = std::upper_bound(begin, begin + timecnt, target, - Transition::ByUnixTime()); - local_time_hint_.store(static_cast<std::size_t>(tr - begin), - std::memory_order_relaxed); - return LocalTime(unix_time, *--tr); -} - -time_zone::civil_lookup TimeZoneInfo::MakeTime(const civil_second& cs) const { - const std::size_t timecnt = transitions_.size(); - assert(timecnt != 0); // We always add a transition. - - // Find the first transition after our target civil time. - const Transition* tr = nullptr; - const Transition* begin = &transitions_[0]; - const Transition* end = begin + timecnt; - if (cs < begin->civil_sec) { - tr = begin; - } else if (cs >= transitions_[timecnt - 1].civil_sec) { - tr = end; - } else { - const std::size_t hint = time_local_hint_.load(std::memory_order_relaxed); - if (0 < hint && hint < timecnt) { - if (transitions_[hint - 1].civil_sec <= cs) { - if (cs < transitions_[hint].civil_sec) { - tr = begin + hint; - } - } - } - if (tr == nullptr) { - const Transition target = {0, 0, cs, civil_second()}; - tr = std::upper_bound(begin, end, target, Transition::ByCivilTime()); - time_local_hint_.store(static_cast<std::size_t>(tr - begin), - std::memory_order_relaxed); - } - } - - if (tr == begin) { - if (tr->prev_civil_sec >= cs) { - // Before first transition, so use the default offset. - const TransitionType& tt(transition_types_[default_transition_type_]); - if (cs < tt.civil_min) return MakeUnique(time_point<seconds>::min()); - return MakeUnique(cs - (civil_second() + tt.utc_offset)); - } - // tr->prev_civil_sec < cs < tr->civil_sec - return MakeSkipped(*tr, cs); - } - - if (tr == end) { - if (cs > (--tr)->prev_civil_sec) { - // After the last transition. If we extended the transitions using - // future_spec_, shift back to a supported year using the 400-year - // cycle of calendaric equivalence and then compensate accordingly. - if (extended_ && cs.year() > last_year_) { - const year_t shift = (cs.year() - last_year_ - 1) / 400 + 1; - return TimeLocal(YearShift(cs, shift * -400), shift); - } - const TransitionType& tt(transition_types_[tr->type_index]); - if (cs > tt.civil_max) return MakeUnique(time_point<seconds>::max()); - return MakeUnique(tr->unix_time + (cs - tr->civil_sec)); - } - // tr->civil_sec <= cs <= tr->prev_civil_sec - return MakeRepeated(*tr, cs); - } - - if (tr->prev_civil_sec < cs) { - // tr->prev_civil_sec < cs < tr->civil_sec - return MakeSkipped(*tr, cs); - } - - if (cs <= (--tr)->prev_civil_sec) { - // tr->civil_sec <= cs <= tr->prev_civil_sec - return MakeRepeated(*tr, cs); - } - - // In between transitions. - return MakeUnique(tr->unix_time + (cs - tr->civil_sec)); -} - +} + +// MakeTime() translation with a conversion-preserving +N * 400-year shift. +time_zone::civil_lookup TimeZoneInfo::TimeLocal(const civil_second& cs, + year_t c4_shift) const { + assert(last_year_ - 400 < cs.year() && cs.year() <= last_year_); + time_zone::civil_lookup cl = MakeTime(cs); + if (c4_shift > seconds::max().count() / kSecsPer400Years) { + cl.pre = cl.trans = cl.post = time_point<seconds>::max(); + } else { + const auto offset = seconds(c4_shift * kSecsPer400Years); + const auto limit = time_point<seconds>::max() - offset; + for (auto* tp : {&cl.pre, &cl.trans, &cl.post}) { + if (*tp > limit) { + *tp = time_point<seconds>::max(); + } else { + *tp += offset; + } + } + } + return cl; +} + +time_zone::absolute_lookup TimeZoneInfo::BreakTime( + const time_point<seconds>& tp) const { + std::int_fast64_t unix_time = ToUnixSeconds(tp); + const std::size_t timecnt = transitions_.size(); + assert(timecnt != 0); // We always add a transition. + + if (unix_time < transitions_[0].unix_time) { + return LocalTime(unix_time, transition_types_[default_transition_type_]); + } + if (unix_time >= transitions_[timecnt - 1].unix_time) { + // After the last transition. If we extended the transitions using + // future_spec_, shift back to a supported year using the 400-year + // cycle of calendaric equivalence and then compensate accordingly. + if (extended_) { + const std::int_fast64_t diff = + unix_time - transitions_[timecnt - 1].unix_time; + const year_t shift = diff / kSecsPer400Years + 1; + const auto d = seconds(shift * kSecsPer400Years); + time_zone::absolute_lookup al = BreakTime(tp - d); + al.cs = YearShift(al.cs, shift * 400); + return al; + } + return LocalTime(unix_time, transitions_[timecnt - 1]); + } + + const std::size_t hint = local_time_hint_.load(std::memory_order_relaxed); + if (0 < hint && hint < timecnt) { + if (transitions_[hint - 1].unix_time <= unix_time) { + if (unix_time < transitions_[hint].unix_time) { + return LocalTime(unix_time, transitions_[hint - 1]); + } + } + } + + const Transition target = {unix_time, 0, civil_second(), civil_second()}; + const Transition* begin = &transitions_[0]; + const Transition* tr = std::upper_bound(begin, begin + timecnt, target, + Transition::ByUnixTime()); + local_time_hint_.store(static_cast<std::size_t>(tr - begin), + std::memory_order_relaxed); + return LocalTime(unix_time, *--tr); +} + +time_zone::civil_lookup TimeZoneInfo::MakeTime(const civil_second& cs) const { + const std::size_t timecnt = transitions_.size(); + assert(timecnt != 0); // We always add a transition. + + // Find the first transition after our target civil time. + const Transition* tr = nullptr; + const Transition* begin = &transitions_[0]; + const Transition* end = begin + timecnt; + if (cs < begin->civil_sec) { + tr = begin; + } else if (cs >= transitions_[timecnt - 1].civil_sec) { + tr = end; + } else { + const std::size_t hint = time_local_hint_.load(std::memory_order_relaxed); + if (0 < hint && hint < timecnt) { + if (transitions_[hint - 1].civil_sec <= cs) { + if (cs < transitions_[hint].civil_sec) { + tr = begin + hint; + } + } + } + if (tr == nullptr) { + const Transition target = {0, 0, cs, civil_second()}; + tr = std::upper_bound(begin, end, target, Transition::ByCivilTime()); + time_local_hint_.store(static_cast<std::size_t>(tr - begin), + std::memory_order_relaxed); + } + } + + if (tr == begin) { + if (tr->prev_civil_sec >= cs) { + // Before first transition, so use the default offset. + const TransitionType& tt(transition_types_[default_transition_type_]); + if (cs < tt.civil_min) return MakeUnique(time_point<seconds>::min()); + return MakeUnique(cs - (civil_second() + tt.utc_offset)); + } + // tr->prev_civil_sec < cs < tr->civil_sec + return MakeSkipped(*tr, cs); + } + + if (tr == end) { + if (cs > (--tr)->prev_civil_sec) { + // After the last transition. If we extended the transitions using + // future_spec_, shift back to a supported year using the 400-year + // cycle of calendaric equivalence and then compensate accordingly. + if (extended_ && cs.year() > last_year_) { + const year_t shift = (cs.year() - last_year_ - 1) / 400 + 1; + return TimeLocal(YearShift(cs, shift * -400), shift); + } + const TransitionType& tt(transition_types_[tr->type_index]); + if (cs > tt.civil_max) return MakeUnique(time_point<seconds>::max()); + return MakeUnique(tr->unix_time + (cs - tr->civil_sec)); + } + // tr->civil_sec <= cs <= tr->prev_civil_sec + return MakeRepeated(*tr, cs); + } + + if (tr->prev_civil_sec < cs) { + // tr->prev_civil_sec < cs < tr->civil_sec + return MakeSkipped(*tr, cs); + } + + if (cs <= (--tr)->prev_civil_sec) { + // tr->civil_sec <= cs <= tr->prev_civil_sec + return MakeRepeated(*tr, cs); + } + + // In between transitions. + return MakeUnique(tr->unix_time + (cs - tr->civil_sec)); +} + TString TimeZoneInfo::Version() const { return version_; } - + TString TimeZoneInfo::Description() const { - std::ostringstream oss; - oss << "#trans=" << transitions_.size(); - oss << " #types=" << transition_types_.size(); - oss << " spec='" << future_spec_ << "'"; + std::ostringstream oss; + oss << "#trans=" << transitions_.size(); + oss << " #types=" << transition_types_.size(); + oss << " spec='" << future_spec_ << "'"; return oss.str().c_str(); -} - -bool TimeZoneInfo::NextTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const { - if (transitions_.empty()) return false; - const Transition* begin = &transitions_[0]; - const Transition* end = begin + transitions_.size(); - if (begin->unix_time <= -(1LL << 59)) { +} + +bool TimeZoneInfo::NextTransition(const time_point<seconds>& tp, + time_zone::civil_transition* trans) const { + if (transitions_.empty()) return false; + const Transition* begin = &transitions_[0]; + const Transition* end = begin + transitions_.size(); + if (begin->unix_time <= -(1LL << 59)) { // Do not report the BIG_BANG found in some zoneinfo data as it is // really a sentinel, not a transition. See pre-2018f tz/zic.c. - ++begin; - } - std::int_fast64_t unix_time = ToUnixSeconds(tp); - const Transition target = {unix_time, 0, civil_second(), civil_second()}; + ++begin; + } + std::int_fast64_t unix_time = ToUnixSeconds(tp); + const Transition target = {unix_time, 0, civil_second(), civil_second()}; const Transition* tr = std::upper_bound(begin, end, target, Transition::ByUnixTime()); - for (; tr != end; ++tr) { // skip no-op transitions - std::uint_fast8_t prev_type_index = - (tr == begin) ? default_transition_type_ : tr[-1].type_index; - if (!EquivTransitions(prev_type_index, tr[0].type_index)) break; - } - // When tr == end we return false, ignoring future_spec_. - if (tr == end) return false; - trans->from = tr->prev_civil_sec + 1; - trans->to = tr->civil_sec; - return true; -} - -bool TimeZoneInfo::PrevTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const { - if (transitions_.empty()) return false; - const Transition* begin = &transitions_[0]; - const Transition* end = begin + transitions_.size(); - if (begin->unix_time <= -(1LL << 59)) { + for (; tr != end; ++tr) { // skip no-op transitions + std::uint_fast8_t prev_type_index = + (tr == begin) ? default_transition_type_ : tr[-1].type_index; + if (!EquivTransitions(prev_type_index, tr[0].type_index)) break; + } + // When tr == end we return false, ignoring future_spec_. + if (tr == end) return false; + trans->from = tr->prev_civil_sec + 1; + trans->to = tr->civil_sec; + return true; +} + +bool TimeZoneInfo::PrevTransition(const time_point<seconds>& tp, + time_zone::civil_transition* trans) const { + if (transitions_.empty()) return false; + const Transition* begin = &transitions_[0]; + const Transition* end = begin + transitions_.size(); + if (begin->unix_time <= -(1LL << 59)) { // Do not report the BIG_BANG found in some zoneinfo data as it is // really a sentinel, not a transition. See pre-2018f tz/zic.c. - ++begin; - } - std::int_fast64_t unix_time = ToUnixSeconds(tp); - if (FromUnixSeconds(unix_time) != tp) { - if (unix_time == std::numeric_limits<std::int_fast64_t>::max()) { - if (end == begin) return false; // Ignore future_spec_. - trans->from = (--end)->prev_civil_sec + 1; - trans->to = end->civil_sec; - return true; - } - unix_time += 1; // ceils - } - const Transition target = {unix_time, 0, civil_second(), civil_second()}; + ++begin; + } + std::int_fast64_t unix_time = ToUnixSeconds(tp); + if (FromUnixSeconds(unix_time) != tp) { + if (unix_time == std::numeric_limits<std::int_fast64_t>::max()) { + if (end == begin) return false; // Ignore future_spec_. + trans->from = (--end)->prev_civil_sec + 1; + trans->to = end->civil_sec; + return true; + } + unix_time += 1; // ceils + } + const Transition target = {unix_time, 0, civil_second(), civil_second()}; const Transition* tr = std::lower_bound(begin, end, target, Transition::ByUnixTime()); - for (; tr != begin; --tr) { // skip no-op transitions - std::uint_fast8_t prev_type_index = - (tr - 1 == begin) ? default_transition_type_ : tr[-2].type_index; - if (!EquivTransitions(prev_type_index, tr[-1].type_index)) break; - } - // When tr == end we return the "last" transition, ignoring future_spec_. - if (tr == begin) return false; - trans->from = (--tr)->prev_civil_sec + 1; - trans->to = tr->civil_sec; - return true; -} - -} // namespace cctz -} // namespace time_internal + for (; tr != begin; --tr) { // skip no-op transitions + std::uint_fast8_t prev_type_index = + (tr - 1 == begin) ? default_transition_type_ : tr[-2].type_index; + if (!EquivTransitions(prev_type_index, tr[-1].type_index)) break; + } + // When tr == end we return the "last" transition, ignoring future_spec_. + if (tr == begin) return false; + trans->from = (--tr)->prev_civil_sec + 1; + trans->to = tr->civil_sec; + return true; +} + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_info.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_info.h index e8ac22d67f..e55fd51847 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_info.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_info.h @@ -1,137 +1,137 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ - -#include <atomic> -#include <cstddef> -#include <cstdint> +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ +#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ + +#include <atomic> +#include <cstddef> +#include <cstdint> #include <util/generic/string.h> -#include <vector> - +#include <vector> + #include "y_absl/base/config.h" #include "y_absl/time/internal/cctz/include/cctz/civil_time.h" #include "y_absl/time/internal/cctz/include/cctz/time_zone.h" #include "y_absl/time/internal/cctz/include/cctz/zone_info_source.h" -#include "time_zone_if.h" -#include "tzfile.h" - +#include "time_zone_if.h" +#include "tzfile.h" + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// A transition to a new UTC offset. -struct Transition { - std::int_least64_t unix_time; // the instant of this transition - std::uint_least8_t type_index; // index of the transition type - civil_second civil_sec; // local civil time of transition - civil_second prev_civil_sec; // local civil time one second earlier - - struct ByUnixTime { - inline bool operator()(const Transition& lhs, const Transition& rhs) const { - return lhs.unix_time < rhs.unix_time; - } - }; - struct ByCivilTime { - inline bool operator()(const Transition& lhs, const Transition& rhs) const { - return lhs.civil_sec < rhs.civil_sec; - } - }; -}; - -// The characteristics of a particular transition. -struct TransitionType { - std::int_least32_t utc_offset; // the new prevailing UTC offset - civil_second civil_max; // max convertible civil time for offset - civil_second civil_min; // min convertible civil time for offset - bool is_dst; // did we move into daylight-saving time - std::uint_least8_t abbr_index; // index of the new abbreviation -}; - -// A time zone backed by the IANA Time Zone Database (zoneinfo). -class TimeZoneInfo : public TimeZoneIf { - public: - TimeZoneInfo() = default; - TimeZoneInfo(const TimeZoneInfo&) = delete; - TimeZoneInfo& operator=(const TimeZoneInfo&) = delete; - - // Loads the zoneinfo for the given name, returning true if successful. +namespace time_internal { +namespace cctz { + +// A transition to a new UTC offset. +struct Transition { + std::int_least64_t unix_time; // the instant of this transition + std::uint_least8_t type_index; // index of the transition type + civil_second civil_sec; // local civil time of transition + civil_second prev_civil_sec; // local civil time one second earlier + + struct ByUnixTime { + inline bool operator()(const Transition& lhs, const Transition& rhs) const { + return lhs.unix_time < rhs.unix_time; + } + }; + struct ByCivilTime { + inline bool operator()(const Transition& lhs, const Transition& rhs) const { + return lhs.civil_sec < rhs.civil_sec; + } + }; +}; + +// The characteristics of a particular transition. +struct TransitionType { + std::int_least32_t utc_offset; // the new prevailing UTC offset + civil_second civil_max; // max convertible civil time for offset + civil_second civil_min; // min convertible civil time for offset + bool is_dst; // did we move into daylight-saving time + std::uint_least8_t abbr_index; // index of the new abbreviation +}; + +// A time zone backed by the IANA Time Zone Database (zoneinfo). +class TimeZoneInfo : public TimeZoneIf { + public: + TimeZoneInfo() = default; + TimeZoneInfo(const TimeZoneInfo&) = delete; + TimeZoneInfo& operator=(const TimeZoneInfo&) = delete; + + // Loads the zoneinfo for the given name, returning true if successful. bool Load(const TString& name); - - // TimeZoneIf implementations. - time_zone::absolute_lookup BreakTime( - const time_point<seconds>& tp) const override; + + // TimeZoneIf implementations. + time_zone::absolute_lookup BreakTime( + const time_point<seconds>& tp) const override; time_zone::civil_lookup MakeTime(const civil_second& cs) const override; - bool NextTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const override; - bool PrevTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const override; + bool NextTransition(const time_point<seconds>& tp, + time_zone::civil_transition* trans) const override; + bool PrevTransition(const time_point<seconds>& tp, + time_zone::civil_transition* trans) const override; TString Version() const override; TString Description() const override; - - private: + + private: struct Header { // counts of: - std::size_t timecnt; // transition times - std::size_t typecnt; // transition types - std::size_t charcnt; // zone abbreviation characters - std::size_t leapcnt; // leap seconds (we expect none) - std::size_t ttisstdcnt; // UTC/local indicators (unused) - std::size_t ttisutcnt; // standard/wall indicators (unused) - - bool Build(const tzhead& tzh); - std::size_t DataLength(std::size_t time_len) const; - }; - + std::size_t timecnt; // transition times + std::size_t typecnt; // transition types + std::size_t charcnt; // zone abbreviation characters + std::size_t leapcnt; // leap seconds (we expect none) + std::size_t ttisstdcnt; // UTC/local indicators (unused) + std::size_t ttisutcnt; // standard/wall indicators (unused) + + bool Build(const tzhead& tzh); + std::size_t DataLength(std::size_t time_len) const; + }; + bool GetTransitionType(std::int_fast32_t utc_offset, bool is_dst, const TString& abbr, std::uint_least8_t* index); - bool EquivTransitions(std::uint_fast8_t tt1_index, - std::uint_fast8_t tt2_index) const; + bool EquivTransitions(std::uint_fast8_t tt1_index, + std::uint_fast8_t tt2_index) const; bool ExtendTransitions(); - - bool ResetToBuiltinUTC(const seconds& offset); + + bool ResetToBuiltinUTC(const seconds& offset); bool Load(ZoneInfoSource* zip); - - // Helpers for BreakTime() and MakeTime(). - time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time, - const TransitionType& tt) const; - time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time, - const Transition& tr) const; - time_zone::civil_lookup TimeLocal(const civil_second& cs, - year_t c4_shift) const; - - std::vector<Transition> transitions_; // ordered by unix_time and civil_sec - std::vector<TransitionType> transition_types_; // distinct transition types + + // Helpers for BreakTime() and MakeTime(). + time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time, + const TransitionType& tt) const; + time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time, + const Transition& tr) const; + time_zone::civil_lookup TimeLocal(const civil_second& cs, + year_t c4_shift) const; + + std::vector<Transition> transitions_; // ordered by unix_time and civil_sec + std::vector<TransitionType> transition_types_; // distinct transition types std::uint_fast8_t default_transition_type_; // for before first transition TString abbreviations_; // all the NUL-terminated abbreviations - + TString version_; // the tzdata version if available TString future_spec_; // for after the last zic transition - bool extended_; // future_spec_ was used to generate transitions - year_t last_year_; // the final year of the generated transitions - - // We remember the transitions found during the last BreakTime() and - // MakeTime() calls. If the next request is for the same transition we - // will avoid re-searching. - mutable std::atomic<std::size_t> local_time_hint_ = {}; // BreakTime() hint - mutable std::atomic<std::size_t> time_local_hint_ = {}; // MakeTime() hint -}; - -} // namespace cctz -} // namespace time_internal + bool extended_; // future_spec_ was used to generate transitions + year_t last_year_; // the final year of the generated transitions + + // We remember the transitions found during the last BreakTime() and + // MakeTime() calls. If the next request is for the same transition we + // will avoid re-searching. + mutable std::atomic<std::size_t> local_time_hint_ = {}; // BreakTime() hint + mutable std::atomic<std::size_t> time_local_hint_ = {}; // MakeTime() hint +}; + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ + +#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_libc.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_libc.cc index 50a83453bb..a73832fc29 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_libc.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_libc.cc @@ -1,32 +1,32 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#if defined(_WIN32) || defined(_WIN64) -#define _CRT_SECURE_NO_WARNINGS 1 -#endif - -#include "time_zone_libc.h" - -#include <chrono> -#include <ctime> -#include <limits> -#include <utility> - +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#if defined(_WIN32) || defined(_WIN64) +#define _CRT_SECURE_NO_WARNINGS 1 +#endif + +#include "time_zone_libc.h" + +#include <chrono> +#include <ctime> +#include <limits> +#include <utility> + #include "y_absl/base/config.h" #include "y_absl/time/internal/cctz/include/cctz/civil_time.h" #include "y_absl/time/internal/cctz/include/cctz/time_zone.h" - + #if defined(_AIX) extern "C" { extern long altzone; @@ -35,281 +35,281 @@ extern long altzone; namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -#if defined(_WIN32) || defined(_WIN64) -// Uses the globals: '_timezone', '_dstbias' and '_tzname'. -auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + _dstbias) { - const bool is_dst = tm.tm_isdst > 0; - return _timezone + (is_dst ? _dstbias : 0); -} -auto tm_zone(const std::tm& tm) -> decltype(_tzname[0]) { - const bool is_dst = tm.tm_isdst > 0; - return _tzname[is_dst]; -} +namespace time_internal { +namespace cctz { + +namespace { + +#if defined(_WIN32) || defined(_WIN64) +// Uses the globals: '_timezone', '_dstbias' and '_tzname'. +auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + _dstbias) { + const bool is_dst = tm.tm_isdst > 0; + return _timezone + (is_dst ? _dstbias : 0); +} +auto tm_zone(const std::tm& tm) -> decltype(_tzname[0]) { + const bool is_dst = tm.tm_isdst > 0; + return _tzname[is_dst]; +} #elif defined(__sun) || defined(_AIX) -// Uses the globals: 'timezone', 'altzone' and 'tzname'. -auto tm_gmtoff(const std::tm& tm) -> decltype(timezone) { - const bool is_dst = tm.tm_isdst > 0; - return is_dst ? altzone : timezone; -} -auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { - const bool is_dst = tm.tm_isdst > 0; - return tzname[is_dst]; -} -#elif defined(__native_client__) || defined(__myriad2__) || \ - defined(__EMSCRIPTEN__) -// Uses the globals: 'timezone' and 'tzname'. -auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + 0) { - const bool is_dst = tm.tm_isdst > 0; - return _timezone + (is_dst ? 60 * 60 : 0); -} -auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { - const bool is_dst = tm.tm_isdst > 0; - return tzname[is_dst]; -} -#else -// Adapt to different spellings of the struct std::tm extension fields. -#if defined(tm_gmtoff) -auto tm_gmtoff(const std::tm& tm) -> decltype(tm.tm_gmtoff) { - return tm.tm_gmtoff; -} -#elif defined(__tm_gmtoff) -auto tm_gmtoff(const std::tm& tm) -> decltype(tm.__tm_gmtoff) { - return tm.__tm_gmtoff; -} -#else -template <typename T> -auto tm_gmtoff(const T& tm) -> decltype(tm.tm_gmtoff) { - return tm.tm_gmtoff; -} -template <typename T> -auto tm_gmtoff(const T& tm) -> decltype(tm.__tm_gmtoff) { - return tm.__tm_gmtoff; -} -#endif // tm_gmtoff -#if defined(tm_zone) +// Uses the globals: 'timezone', 'altzone' and 'tzname'. +auto tm_gmtoff(const std::tm& tm) -> decltype(timezone) { + const bool is_dst = tm.tm_isdst > 0; + return is_dst ? altzone : timezone; +} +auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { + const bool is_dst = tm.tm_isdst > 0; + return tzname[is_dst]; +} +#elif defined(__native_client__) || defined(__myriad2__) || \ + defined(__EMSCRIPTEN__) +// Uses the globals: 'timezone' and 'tzname'. +auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + 0) { + const bool is_dst = tm.tm_isdst > 0; + return _timezone + (is_dst ? 60 * 60 : 0); +} +auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) { + const bool is_dst = tm.tm_isdst > 0; + return tzname[is_dst]; +} +#else +// Adapt to different spellings of the struct std::tm extension fields. +#if defined(tm_gmtoff) +auto tm_gmtoff(const std::tm& tm) -> decltype(tm.tm_gmtoff) { + return tm.tm_gmtoff; +} +#elif defined(__tm_gmtoff) +auto tm_gmtoff(const std::tm& tm) -> decltype(tm.__tm_gmtoff) { + return tm.__tm_gmtoff; +} +#else +template <typename T> +auto tm_gmtoff(const T& tm) -> decltype(tm.tm_gmtoff) { + return tm.tm_gmtoff; +} +template <typename T> +auto tm_gmtoff(const T& tm) -> decltype(tm.__tm_gmtoff) { + return tm.__tm_gmtoff; +} +#endif // tm_gmtoff +#if defined(tm_zone) auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) { return tm.tm_zone; } -#elif defined(__tm_zone) -auto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) { - return tm.__tm_zone; -} -#else -template <typename T> -auto tm_zone(const T& tm) -> decltype(tm.tm_zone) { - return tm.tm_zone; -} -template <typename T> -auto tm_zone(const T& tm) -> decltype(tm.__tm_zone) { - return tm.__tm_zone; -} -#endif // tm_zone -#endif - +#elif defined(__tm_zone) +auto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) { + return tm.__tm_zone; +} +#else +template <typename T> +auto tm_zone(const T& tm) -> decltype(tm.tm_zone) { + return tm.tm_zone; +} +template <typename T> +auto tm_zone(const T& tm) -> decltype(tm.__tm_zone) { + return tm.__tm_zone; +} +#endif // tm_zone +#endif + inline std::tm* gm_time(const std::time_t* timep, std::tm* result) { -#if defined(_WIN32) || defined(_WIN64) +#if defined(_WIN32) || defined(_WIN64) return gmtime_s(result, timep) ? nullptr : result; -#else +#else return gmtime_r(timep, result); -#endif -} - +#endif +} + inline std::tm* local_time(const std::time_t* timep, std::tm* result) { -#if defined(_WIN32) || defined(_WIN64) +#if defined(_WIN32) || defined(_WIN64) return localtime_s(result, timep) ? nullptr : result; -#else +#else return localtime_r(timep, result); -#endif -} - -// Converts a civil second and "dst" flag into a time_t and UTC offset. -// Returns false if time_t cannot represent the requested civil second. -// Caller must have already checked that cs.year() will fit into a tm_year. -bool make_time(const civil_second& cs, int is_dst, std::time_t* t, int* off) { - std::tm tm; - tm.tm_year = static_cast<int>(cs.year() - year_t{1900}); - tm.tm_mon = cs.month() - 1; - tm.tm_mday = cs.day(); - tm.tm_hour = cs.hour(); - tm.tm_min = cs.minute(); - tm.tm_sec = cs.second(); - tm.tm_isdst = is_dst; - *t = std::mktime(&tm); - if (*t == std::time_t{-1}) { - std::tm tm2; - const std::tm* tmp = local_time(t, &tm2); - if (tmp == nullptr || tmp->tm_year != tm.tm_year || - tmp->tm_mon != tm.tm_mon || tmp->tm_mday != tm.tm_mday || - tmp->tm_hour != tm.tm_hour || tmp->tm_min != tm.tm_min || - tmp->tm_sec != tm.tm_sec) { - // A true error (not just one second before the epoch). - return false; - } - } - *off = static_cast<int>(tm_gmtoff(tm)); - return true; -} - -// Find the least time_t in [lo:hi] where local time matches offset, given: -// (1) lo doesn't match, (2) hi does, and (3) there is only one transition. -std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) { - std::tm tm; - while (lo + 1 != hi) { - const std::time_t mid = lo + (hi - lo) / 2; +#endif +} + +// Converts a civil second and "dst" flag into a time_t and UTC offset. +// Returns false if time_t cannot represent the requested civil second. +// Caller must have already checked that cs.year() will fit into a tm_year. +bool make_time(const civil_second& cs, int is_dst, std::time_t* t, int* off) { + std::tm tm; + tm.tm_year = static_cast<int>(cs.year() - year_t{1900}); + tm.tm_mon = cs.month() - 1; + tm.tm_mday = cs.day(); + tm.tm_hour = cs.hour(); + tm.tm_min = cs.minute(); + tm.tm_sec = cs.second(); + tm.tm_isdst = is_dst; + *t = std::mktime(&tm); + if (*t == std::time_t{-1}) { + std::tm tm2; + const std::tm* tmp = local_time(t, &tm2); + if (tmp == nullptr || tmp->tm_year != tm.tm_year || + tmp->tm_mon != tm.tm_mon || tmp->tm_mday != tm.tm_mday || + tmp->tm_hour != tm.tm_hour || tmp->tm_min != tm.tm_min || + tmp->tm_sec != tm.tm_sec) { + // A true error (not just one second before the epoch). + return false; + } + } + *off = static_cast<int>(tm_gmtoff(tm)); + return true; +} + +// Find the least time_t in [lo:hi] where local time matches offset, given: +// (1) lo doesn't match, (2) hi does, and (3) there is only one transition. +std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) { + std::tm tm; + while (lo + 1 != hi) { + const std::time_t mid = lo + (hi - lo) / 2; std::tm* tmp = local_time(&mid, &tm); if (tmp != nullptr) { - if (tm_gmtoff(*tmp) == offset) { - hi = mid; - } else { - lo = mid; - } - } else { - // If std::tm cannot hold some result we resort to a linear search, - // ignoring all failed conversions. Slow, but never really happens. - while (++lo != hi) { + if (tm_gmtoff(*tmp) == offset) { + hi = mid; + } else { + lo = mid; + } + } else { + // If std::tm cannot hold some result we resort to a linear search, + // ignoring all failed conversions. Slow, but never really happens. + while (++lo != hi) { tmp = local_time(&lo, &tm); if (tmp != nullptr) { - if (tm_gmtoff(*tmp) == offset) break; - } - } - return lo; - } - } - return hi; -} - -} // namespace - + if (tm_gmtoff(*tmp) == offset) break; + } + } + return lo; + } + } + return hi; +} + +} // namespace + TimeZoneLibC::TimeZoneLibC(const TString& name) - : local_(name == "localtime") {} - -time_zone::absolute_lookup TimeZoneLibC::BreakTime( - const time_point<seconds>& tp) const { - time_zone::absolute_lookup al; - al.offset = 0; - al.is_dst = false; - al.abbr = "-00"; - - const std::int_fast64_t s = ToUnixSeconds(tp); - - // If std::time_t cannot hold the input we saturate the output. - if (s < std::numeric_limits<std::time_t>::min()) { - al.cs = civil_second::min(); - return al; - } - if (s > std::numeric_limits<std::time_t>::max()) { - al.cs = civil_second::max(); - return al; - } - - const std::time_t t = static_cast<std::time_t>(s); - std::tm tm; - std::tm* tmp = local_ ? local_time(&t, &tm) : gm_time(&t, &tm); - - // If std::tm cannot hold the result we saturate the output. - if (tmp == nullptr) { - al.cs = (s < 0) ? civil_second::min() : civil_second::max(); - return al; - } - - const year_t year = tmp->tm_year + year_t{1900}; + : local_(name == "localtime") {} + +time_zone::absolute_lookup TimeZoneLibC::BreakTime( + const time_point<seconds>& tp) const { + time_zone::absolute_lookup al; + al.offset = 0; + al.is_dst = false; + al.abbr = "-00"; + + const std::int_fast64_t s = ToUnixSeconds(tp); + + // If std::time_t cannot hold the input we saturate the output. + if (s < std::numeric_limits<std::time_t>::min()) { + al.cs = civil_second::min(); + return al; + } + if (s > std::numeric_limits<std::time_t>::max()) { + al.cs = civil_second::max(); + return al; + } + + const std::time_t t = static_cast<std::time_t>(s); + std::tm tm; + std::tm* tmp = local_ ? local_time(&t, &tm) : gm_time(&t, &tm); + + // If std::tm cannot hold the result we saturate the output. + if (tmp == nullptr) { + al.cs = (s < 0) ? civil_second::min() : civil_second::max(); + return al; + } + + const year_t year = tmp->tm_year + year_t{1900}; al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); - al.offset = static_cast<int>(tm_gmtoff(*tmp)); - al.abbr = local_ ? tm_zone(*tmp) : "UTC"; // as expected by cctz - al.is_dst = tmp->tm_isdst > 0; - return al; -} - -time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const { - if (!local_) { - // If time_point<seconds> cannot hold the result we saturate. - static const civil_second min_tp_cs = - civil_second() + ToUnixSeconds(time_point<seconds>::min()); - static const civil_second max_tp_cs = - civil_second() + ToUnixSeconds(time_point<seconds>::max()); + al.offset = static_cast<int>(tm_gmtoff(*tmp)); + al.abbr = local_ ? tm_zone(*tmp) : "UTC"; // as expected by cctz + al.is_dst = tmp->tm_isdst > 0; + return al; +} + +time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const { + if (!local_) { + // If time_point<seconds> cannot hold the result we saturate. + static const civil_second min_tp_cs = + civil_second() + ToUnixSeconds(time_point<seconds>::min()); + static const civil_second max_tp_cs = + civil_second() + ToUnixSeconds(time_point<seconds>::max()); const time_point<seconds> tp = (cs < min_tp_cs) ? time_point<seconds>::min() : (cs > max_tp_cs) ? time_point<seconds>::max() : FromUnixSeconds(cs - civil_second()); - return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; - } - - // If tm_year cannot hold the requested year we saturate the result. - if (cs.year() < 0) { - if (cs.year() < std::numeric_limits<int>::min() + year_t{1900}) { - const time_point<seconds> tp = time_point<seconds>::min(); - return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; - } - } else { - if (cs.year() - year_t{1900} > std::numeric_limits<int>::max()) { - const time_point<seconds> tp = time_point<seconds>::max(); - return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; - } - } - - // We probe with "is_dst" values of 0 and 1 to try to distinguish unique - // civil seconds from skipped or repeated ones. This is not always possible - // however, as the "dst" flag does not change over some offset transitions. - // We are also subject to the vagaries of mktime() implementations. - std::time_t t0, t1; - int offset0, offset1; - if (make_time(cs, 0, &t0, &offset0) && make_time(cs, 1, &t1, &offset1)) { - if (t0 == t1) { - // The civil time was singular (pre == trans == post). - const time_point<seconds> tp = FromUnixSeconds(t0); - return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; - } - - if (t0 > t1) { - std::swap(t0, t1); - std::swap(offset0, offset1); - } - const std::time_t tt = find_trans(t0, t1, offset1); - const time_point<seconds> trans = FromUnixSeconds(tt); - - if (offset0 < offset1) { - // The civil time did not exist (pre >= trans > post). - const time_point<seconds> pre = FromUnixSeconds(t1); - const time_point<seconds> post = FromUnixSeconds(t0); - return {time_zone::civil_lookup::SKIPPED, pre, trans, post}; - } - - // The civil time was ambiguous (pre < trans <= post). - const time_point<seconds> pre = FromUnixSeconds(t0); - const time_point<seconds> post = FromUnixSeconds(t1); - return {time_zone::civil_lookup::REPEATED, pre, trans, post}; - } - - // make_time() failed somehow so we saturate the result. - const time_point<seconds> tp = (cs < civil_second()) - ? time_point<seconds>::min() - : time_point<seconds>::max(); - return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; -} - -bool TimeZoneLibC::NextTransition(const time_point<seconds>&, - time_zone::civil_transition*) const { - return false; -} - -bool TimeZoneLibC::PrevTransition(const time_point<seconds>&, - time_zone::civil_transition*) const { - return false; -} - + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } + + // If tm_year cannot hold the requested year we saturate the result. + if (cs.year() < 0) { + if (cs.year() < std::numeric_limits<int>::min() + year_t{1900}) { + const time_point<seconds> tp = time_point<seconds>::min(); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } + } else { + if (cs.year() - year_t{1900} > std::numeric_limits<int>::max()) { + const time_point<seconds> tp = time_point<seconds>::max(); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } + } + + // We probe with "is_dst" values of 0 and 1 to try to distinguish unique + // civil seconds from skipped or repeated ones. This is not always possible + // however, as the "dst" flag does not change over some offset transitions. + // We are also subject to the vagaries of mktime() implementations. + std::time_t t0, t1; + int offset0, offset1; + if (make_time(cs, 0, &t0, &offset0) && make_time(cs, 1, &t1, &offset1)) { + if (t0 == t1) { + // The civil time was singular (pre == trans == post). + const time_point<seconds> tp = FromUnixSeconds(t0); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; + } + + if (t0 > t1) { + std::swap(t0, t1); + std::swap(offset0, offset1); + } + const std::time_t tt = find_trans(t0, t1, offset1); + const time_point<seconds> trans = FromUnixSeconds(tt); + + if (offset0 < offset1) { + // The civil time did not exist (pre >= trans > post). + const time_point<seconds> pre = FromUnixSeconds(t1); + const time_point<seconds> post = FromUnixSeconds(t0); + return {time_zone::civil_lookup::SKIPPED, pre, trans, post}; + } + + // The civil time was ambiguous (pre < trans <= post). + const time_point<seconds> pre = FromUnixSeconds(t0); + const time_point<seconds> post = FromUnixSeconds(t1); + return {time_zone::civil_lookup::REPEATED, pre, trans, post}; + } + + // make_time() failed somehow so we saturate the result. + const time_point<seconds> tp = (cs < civil_second()) + ? time_point<seconds>::min() + : time_point<seconds>::max(); + return {time_zone::civil_lookup::UNIQUE, tp, tp, tp}; +} + +bool TimeZoneLibC::NextTransition(const time_point<seconds>&, + time_zone::civil_transition*) const { + return false; +} + +bool TimeZoneLibC::PrevTransition(const time_point<seconds>&, + time_zone::civil_transition*) const { + return false; +} + TString TimeZoneLibC::Version() const { return TString(); // unknown -} - +} + TString TimeZoneLibC::Description() const { - return local_ ? "localtime" : "UTC"; -} - -} // namespace cctz -} // namespace time_internal + return local_ ? "localtime" : "UTC"; +} + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_libc.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_libc.h index 724cdac939..fc926fecf7 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_libc.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_libc.h @@ -1,55 +1,55 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_ - +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_ +#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_ + #include <util/generic/string.h> - + #include "y_absl/base/config.h" -#include "time_zone_if.h" - +#include "time_zone_if.h" + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// A time zone backed by gmtime_r(3), localtime_r(3), and mktime(3), -// and which therefore only supports UTC and the local time zone. -// TODO: Add support for fixed offsets from UTC. -class TimeZoneLibC : public TimeZoneIf { - public: +namespace time_internal { +namespace cctz { + +// A time zone backed by gmtime_r(3), localtime_r(3), and mktime(3), +// and which therefore only supports UTC and the local time zone. +// TODO: Add support for fixed offsets from UTC. +class TimeZoneLibC : public TimeZoneIf { + public: explicit TimeZoneLibC(const TString& name); - - // TimeZoneIf implementations. - time_zone::absolute_lookup BreakTime( - const time_point<seconds>& tp) const override; + + // TimeZoneIf implementations. + time_zone::absolute_lookup BreakTime( + const time_point<seconds>& tp) const override; time_zone::civil_lookup MakeTime(const civil_second& cs) const override; - bool NextTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const override; - bool PrevTransition(const time_point<seconds>& tp, - time_zone::civil_transition* trans) const override; + bool NextTransition(const time_point<seconds>& tp, + time_zone::civil_transition* trans) const override; + bool PrevTransition(const time_point<seconds>& tp, + time_zone::civil_transition* trans) const override; TString Version() const override; TString Description() const override; - - private: - const bool local_; // localtime or UTC -}; - -} // namespace cctz -} // namespace time_internal + + private: + const bool local_; // localtime or UTC +}; + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_ + +#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_lookup.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_lookup.cc index c62dfb5f2d..92c9208d6d 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_lookup.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_lookup.cc @@ -1,33 +1,33 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "y_absl/base/config.h" #include "y_absl/time/internal/cctz/include/cctz/time_zone.h" - -#if defined(__ANDROID__) -#include <sys/system_properties.h> -#if defined(__ANDROID_API__) && __ANDROID_API__ >= 21 -#include <dlfcn.h> -#endif -#endif - -#if defined(__APPLE__) -#include <CoreFoundation/CFTimeZone.h> - -#include <vector> -#endif - + +#if defined(__ANDROID__) +#include <sys/system_properties.h> +#if defined(__ANDROID_API__) && __ANDROID_API__ >= 21 +#include <dlfcn.h> +#endif +#endif + +#if defined(__APPLE__) +#include <CoreFoundation/CFTimeZone.h> + +#include <vector> +#endif + #if defined(__Fuchsia__) #error #include <fuchsia/intl/cpp/fidl.h> #error #include <lib/async-loop/cpp/loop.h> @@ -35,125 +35,125 @@ #error #include <zircon/types.h> #endif -#include <cstdlib> -#include <cstring> +#include <cstdlib> +#include <cstring> #include <util/generic/string.h> - -#include "time_zone_fixed.h" -#include "time_zone_impl.h" - + +#include "time_zone_fixed.h" +#include "time_zone_impl.h" + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -#if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21 -namespace { -// Android 'L' removes __system_property_get() from the NDK, however -// it is still a hidden symbol in libc so we use dlsym() to access it. -// See Chromium's base/sys_info_android.cc for a similar example. - -using property_get_func = int (*)(const char*, char*); - -property_get_func LoadSystemPropertyGet() { - int flag = RTLD_LAZY | RTLD_GLOBAL; -#if defined(RTLD_NOLOAD) - flag |= RTLD_NOLOAD; // libc.so should already be resident -#endif - if (void* handle = dlopen("libc.so", flag)) { - void* sym = dlsym(handle, "__system_property_get"); - dlclose(handle); - return reinterpret_cast<property_get_func>(sym); - } - return nullptr; -} - -int __system_property_get(const char* name, char* value) { - static property_get_func system_property_get = LoadSystemPropertyGet(); - return system_property_get ? system_property_get(name, value) : -1; -} - -} // namespace -#endif - +namespace time_internal { +namespace cctz { + +#if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21 +namespace { +// Android 'L' removes __system_property_get() from the NDK, however +// it is still a hidden symbol in libc so we use dlsym() to access it. +// See Chromium's base/sys_info_android.cc for a similar example. + +using property_get_func = int (*)(const char*, char*); + +property_get_func LoadSystemPropertyGet() { + int flag = RTLD_LAZY | RTLD_GLOBAL; +#if defined(RTLD_NOLOAD) + flag |= RTLD_NOLOAD; // libc.so should already be resident +#endif + if (void* handle = dlopen("libc.so", flag)) { + void* sym = dlsym(handle, "__system_property_get"); + dlclose(handle); + return reinterpret_cast<property_get_func>(sym); + } + return nullptr; +} + +int __system_property_get(const char* name, char* value) { + static property_get_func system_property_get = LoadSystemPropertyGet(); + return system_property_get ? system_property_get(name, value) : -1; +} + +} // namespace +#endif + TString time_zone::name() const { return effective_impl().Name(); } - -time_zone::absolute_lookup time_zone::lookup( - const time_point<seconds>& tp) const { - return effective_impl().BreakTime(tp); -} - -time_zone::civil_lookup time_zone::lookup(const civil_second& cs) const { - return effective_impl().MakeTime(cs); -} - -bool time_zone::next_transition(const time_point<seconds>& tp, - civil_transition* trans) const { - return effective_impl().NextTransition(tp, trans); -} - -bool time_zone::prev_transition(const time_point<seconds>& tp, - civil_transition* trans) const { - return effective_impl().PrevTransition(tp, trans); -} - + +time_zone::absolute_lookup time_zone::lookup( + const time_point<seconds>& tp) const { + return effective_impl().BreakTime(tp); +} + +time_zone::civil_lookup time_zone::lookup(const civil_second& cs) const { + return effective_impl().MakeTime(cs); +} + +bool time_zone::next_transition(const time_point<seconds>& tp, + civil_transition* trans) const { + return effective_impl().NextTransition(tp, trans); +} + +bool time_zone::prev_transition(const time_point<seconds>& tp, + civil_transition* trans) const { + return effective_impl().PrevTransition(tp, trans); +} + TString time_zone::version() const { return effective_impl().Version(); } - + TString time_zone::description() const { - return effective_impl().Description(); -} - -const time_zone::Impl& time_zone::effective_impl() const { - if (impl_ == nullptr) { - // Dereferencing an implicit-UTC time_zone is expected to be - // rare, so we don't mind paying a small synchronization cost. - return *time_zone::Impl::UTC().impl_; - } - return *impl_; -} - + return effective_impl().Description(); +} + +const time_zone::Impl& time_zone::effective_impl() const { + if (impl_ == nullptr) { + // Dereferencing an implicit-UTC time_zone is expected to be + // rare, so we don't mind paying a small synchronization cost. + return *time_zone::Impl::UTC().impl_; + } + return *impl_; +} + bool load_time_zone(const TString& name, time_zone* tz) { - return time_zone::Impl::LoadTimeZone(name, tz); -} - -time_zone utc_time_zone() { - return time_zone::Impl::UTC(); // avoid name lookup -} - -time_zone fixed_time_zone(const seconds& offset) { - time_zone tz; - load_time_zone(FixedOffsetToName(offset), &tz); - return tz; -} - -time_zone local_time_zone() { - const char* zone = ":localtime"; -#if defined(__ANDROID__) - char sysprop[PROP_VALUE_MAX]; - if (__system_property_get("persist.sys.timezone", sysprop) > 0) { - zone = sysprop; - } -#endif -#if defined(__APPLE__) - std::vector<char> buffer; - CFTimeZoneRef tz_default = CFTimeZoneCopyDefault(); - if (CFStringRef tz_name = CFTimeZoneGetName(tz_default)) { - CFStringEncoding encoding = kCFStringEncodingUTF8; - CFIndex length = CFStringGetLength(tz_name); - buffer.resize(CFStringGetMaximumSizeForEncoding(length, encoding) + 1); - if (CFStringGetCString(tz_name, &buffer[0], buffer.size(), encoding)) { - zone = &buffer[0]; - } - } - CFRelease(tz_default); -#endif + return time_zone::Impl::LoadTimeZone(name, tz); +} + +time_zone utc_time_zone() { + return time_zone::Impl::UTC(); // avoid name lookup +} + +time_zone fixed_time_zone(const seconds& offset) { + time_zone tz; + load_time_zone(FixedOffsetToName(offset), &tz); + return tz; +} + +time_zone local_time_zone() { + const char* zone = ":localtime"; +#if defined(__ANDROID__) + char sysprop[PROP_VALUE_MAX]; + if (__system_property_get("persist.sys.timezone", sysprop) > 0) { + zone = sysprop; + } +#endif +#if defined(__APPLE__) + std::vector<char> buffer; + CFTimeZoneRef tz_default = CFTimeZoneCopyDefault(); + if (CFStringRef tz_name = CFTimeZoneGetName(tz_default)) { + CFStringEncoding encoding = kCFStringEncodingUTF8; + CFIndex length = CFStringGetLength(tz_name); + buffer.resize(CFStringGetMaximumSizeForEncoding(length, encoding) + 1); + if (CFStringGetCString(tz_name, &buffer[0], buffer.size(), encoding)) { + zone = &buffer[0]; + } + } + CFRelease(tz_default); +#endif #if defined(__Fuchsia__) TString primary_tz; [&]() { // Note: We can't use the synchronous FIDL API here because it doesn't // allow timeouts; if the FIDL call failed, local_time_zone() would never // return. - + const zx::duration kTimeout = zx::msec(500); // Don't attach to the thread because otherwise the thread's dispatcher @@ -190,47 +190,47 @@ time_zone local_time_zone() { } #endif - // Allow ${TZ} to override to default zone. - char* tz_env = nullptr; -#if defined(_MSC_VER) - _dupenv_s(&tz_env, nullptr, "TZ"); -#else - tz_env = std::getenv("TZ"); -#endif - if (tz_env) zone = tz_env; - - // We only support the "[:]<zone-name>" form. - if (*zone == ':') ++zone; - - // Map "localtime" to a system-specific name, but - // allow ${LOCALTIME} to override the default name. - char* localtime_env = nullptr; - if (strcmp(zone, "localtime") == 0) { -#if defined(_MSC_VER) - // System-specific default is just "localtime". - _dupenv_s(&localtime_env, nullptr, "LOCALTIME"); -#else - zone = "/etc/localtime"; // System-specific default. - localtime_env = std::getenv("LOCALTIME"); -#endif - if (localtime_env) zone = localtime_env; - } - + // Allow ${TZ} to override to default zone. + char* tz_env = nullptr; +#if defined(_MSC_VER) + _dupenv_s(&tz_env, nullptr, "TZ"); +#else + tz_env = std::getenv("TZ"); +#endif + if (tz_env) zone = tz_env; + + // We only support the "[:]<zone-name>" form. + if (*zone == ':') ++zone; + + // Map "localtime" to a system-specific name, but + // allow ${LOCALTIME} to override the default name. + char* localtime_env = nullptr; + if (strcmp(zone, "localtime") == 0) { +#if defined(_MSC_VER) + // System-specific default is just "localtime". + _dupenv_s(&localtime_env, nullptr, "LOCALTIME"); +#else + zone = "/etc/localtime"; // System-specific default. + localtime_env = std::getenv("LOCALTIME"); +#endif + if (localtime_env) zone = localtime_env; + } + const TString name = zone; -#if defined(_MSC_VER) - free(localtime_env); - free(tz_env); -#endif - - time_zone tz; - load_time_zone(name, &tz); // Falls back to UTC. - // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and - // arrange for %z to generate "-0000" when we don't know the local - // offset because the load_time_zone() failed and we're using UTC. - return tz; -} - -} // namespace cctz -} // namespace time_internal +#if defined(_MSC_VER) + free(localtime_env); + free(tz_env); +#endif + + time_zone tz; + load_time_zone(name, &tz); // Falls back to UTC. + // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and + // arrange for %z to generate "-0000" when we don't know the local + // offset because the load_time_zone() failed and we're using UTC. + return tz; +} + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_posix.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_posix.cc index 5da69c47e2..4096503915 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_posix.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_posix.cc @@ -1,159 +1,159 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "time_zone_posix.h" - -#include <cstddef> -#include <cstring> -#include <limits> +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "time_zone_posix.h" + +#include <cstddef> +#include <cstring> +#include <limits> #include <util/generic/string.h> - + #include "y_absl/base/config.h" namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -namespace { - -const char kDigits[] = "0123456789"; - -const char* ParseInt(const char* p, int min, int max, int* vp) { - int value = 0; - const char* op = p; - const int kMaxInt = std::numeric_limits<int>::max(); - for (; const char* dp = strchr(kDigits, *p); ++p) { - int d = static_cast<int>(dp - kDigits); - if (d >= 10) break; // '\0' - if (value > kMaxInt / 10) return nullptr; - value *= 10; - if (value > kMaxInt - d) return nullptr; - value += d; - } - if (p == op || value < min || value > max) return nullptr; - *vp = value; - return p; -} - -// abbr = <.*?> | [^-+,\d]{3,} +namespace time_internal { +namespace cctz { + +namespace { + +const char kDigits[] = "0123456789"; + +const char* ParseInt(const char* p, int min, int max, int* vp) { + int value = 0; + const char* op = p; + const int kMaxInt = std::numeric_limits<int>::max(); + for (; const char* dp = strchr(kDigits, *p); ++p) { + int d = static_cast<int>(dp - kDigits); + if (d >= 10) break; // '\0' + if (value > kMaxInt / 10) return nullptr; + value *= 10; + if (value > kMaxInt - d) return nullptr; + value += d; + } + if (p == op || value < min || value > max) return nullptr; + *vp = value; + return p; +} + +// abbr = <.*?> | [^-+,\d]{3,} const char* ParseAbbr(const char* p, TString* abbr) { - const char* op = p; - if (*p == '<') { // special zoneinfo <...> form - while (*++p != '>') { - if (*p == '\0') return nullptr; - } - abbr->assign(op + 1, static_cast<std::size_t>(p - op) - 1); - return ++p; - } - while (*p != '\0') { - if (strchr("-+,", *p)) break; - if (strchr(kDigits, *p)) break; - ++p; - } - if (p - op < 3) return nullptr; - abbr->assign(op, static_cast<std::size_t>(p - op)); - return p; -} - -// offset = [+|-]hh[:mm[:ss]] (aggregated into single seconds value) -const char* ParseOffset(const char* p, int min_hour, int max_hour, int sign, - std::int_fast32_t* offset) { - if (p == nullptr) return nullptr; - if (*p == '+' || *p == '-') { - if (*p++ == '-') sign = -sign; - } - int hours = 0; - int minutes = 0; - int seconds = 0; - - p = ParseInt(p, min_hour, max_hour, &hours); - if (p == nullptr) return nullptr; - if (*p == ':') { - p = ParseInt(p + 1, 0, 59, &minutes); - if (p == nullptr) return nullptr; - if (*p == ':') { - p = ParseInt(p + 1, 0, 59, &seconds); - if (p == nullptr) return nullptr; - } - } - *offset = sign * ((((hours * 60) + minutes) * 60) + seconds); - return p; -} - -// datetime = ( Jn | n | Mm.w.d ) [ / offset ] -const char* ParseDateTime(const char* p, PosixTransition* res) { - if (p != nullptr && *p == ',') { - if (*++p == 'M') { - int month = 0; - if ((p = ParseInt(p + 1, 1, 12, &month)) != nullptr && *p == '.') { - int week = 0; - if ((p = ParseInt(p + 1, 1, 5, &week)) != nullptr && *p == '.') { - int weekday = 0; - if ((p = ParseInt(p + 1, 0, 6, &weekday)) != nullptr) { - res->date.fmt = PosixTransition::M; - res->date.m.month = static_cast<std::int_fast8_t>(month); - res->date.m.week = static_cast<std::int_fast8_t>(week); - res->date.m.weekday = static_cast<std::int_fast8_t>(weekday); - } - } - } - } else if (*p == 'J') { - int day = 0; - if ((p = ParseInt(p + 1, 1, 365, &day)) != nullptr) { - res->date.fmt = PosixTransition::J; - res->date.j.day = static_cast<std::int_fast16_t>(day); - } - } else { - int day = 0; - if ((p = ParseInt(p, 0, 365, &day)) != nullptr) { - res->date.fmt = PosixTransition::N; - res->date.n.day = static_cast<std::int_fast16_t>(day); - } - } - } - if (p != nullptr) { - res->time.offset = 2 * 60 * 60; // default offset is 02:00:00 - if (*p == '/') p = ParseOffset(p + 1, -167, 167, 1, &res->time.offset); - } - return p; -} - -} // namespace - -// spec = std offset [ dst [ offset ] , datetime , datetime ] + const char* op = p; + if (*p == '<') { // special zoneinfo <...> form + while (*++p != '>') { + if (*p == '\0') return nullptr; + } + abbr->assign(op + 1, static_cast<std::size_t>(p - op) - 1); + return ++p; + } + while (*p != '\0') { + if (strchr("-+,", *p)) break; + if (strchr(kDigits, *p)) break; + ++p; + } + if (p - op < 3) return nullptr; + abbr->assign(op, static_cast<std::size_t>(p - op)); + return p; +} + +// offset = [+|-]hh[:mm[:ss]] (aggregated into single seconds value) +const char* ParseOffset(const char* p, int min_hour, int max_hour, int sign, + std::int_fast32_t* offset) { + if (p == nullptr) return nullptr; + if (*p == '+' || *p == '-') { + if (*p++ == '-') sign = -sign; + } + int hours = 0; + int minutes = 0; + int seconds = 0; + + p = ParseInt(p, min_hour, max_hour, &hours); + if (p == nullptr) return nullptr; + if (*p == ':') { + p = ParseInt(p + 1, 0, 59, &minutes); + if (p == nullptr) return nullptr; + if (*p == ':') { + p = ParseInt(p + 1, 0, 59, &seconds); + if (p == nullptr) return nullptr; + } + } + *offset = sign * ((((hours * 60) + minutes) * 60) + seconds); + return p; +} + +// datetime = ( Jn | n | Mm.w.d ) [ / offset ] +const char* ParseDateTime(const char* p, PosixTransition* res) { + if (p != nullptr && *p == ',') { + if (*++p == 'M') { + int month = 0; + if ((p = ParseInt(p + 1, 1, 12, &month)) != nullptr && *p == '.') { + int week = 0; + if ((p = ParseInt(p + 1, 1, 5, &week)) != nullptr && *p == '.') { + int weekday = 0; + if ((p = ParseInt(p + 1, 0, 6, &weekday)) != nullptr) { + res->date.fmt = PosixTransition::M; + res->date.m.month = static_cast<std::int_fast8_t>(month); + res->date.m.week = static_cast<std::int_fast8_t>(week); + res->date.m.weekday = static_cast<std::int_fast8_t>(weekday); + } + } + } + } else if (*p == 'J') { + int day = 0; + if ((p = ParseInt(p + 1, 1, 365, &day)) != nullptr) { + res->date.fmt = PosixTransition::J; + res->date.j.day = static_cast<std::int_fast16_t>(day); + } + } else { + int day = 0; + if ((p = ParseInt(p, 0, 365, &day)) != nullptr) { + res->date.fmt = PosixTransition::N; + res->date.n.day = static_cast<std::int_fast16_t>(day); + } + } + } + if (p != nullptr) { + res->time.offset = 2 * 60 * 60; // default offset is 02:00:00 + if (*p == '/') p = ParseOffset(p + 1, -167, 167, 1, &res->time.offset); + } + return p; +} + +} // namespace + +// spec = std offset [ dst [ offset ] , datetime , datetime ] bool ParsePosixSpec(const TString& spec, PosixTimeZone* res) { - const char* p = spec.c_str(); - if (*p == ':') return false; - - p = ParseAbbr(p, &res->std_abbr); - p = ParseOffset(p, 0, 24, -1, &res->std_offset); - if (p == nullptr) return false; - if (*p == '\0') return true; - - p = ParseAbbr(p, &res->dst_abbr); - if (p == nullptr) return false; - res->dst_offset = res->std_offset + (60 * 60); // default - if (*p != ',') p = ParseOffset(p, 0, 24, -1, &res->dst_offset); - - p = ParseDateTime(p, &res->dst_start); - p = ParseDateTime(p, &res->dst_end); - - return p != nullptr && *p == '\0'; -} - -} // namespace cctz -} // namespace time_internal + const char* p = spec.c_str(); + if (*p == ':') return false; + + p = ParseAbbr(p, &res->std_abbr); + p = ParseOffset(p, 0, 24, -1, &res->std_offset); + if (p == nullptr) return false; + if (*p == '\0') return true; + + p = ParseAbbr(p, &res->dst_abbr); + if (p == nullptr) return false; + res->dst_offset = res->std_offset + (60 * 60); // default + if (*p != ',') p = ParseOffset(p, 0, 24, -1, &res->dst_offset); + + p = ParseDateTime(p, &res->dst_start); + p = ParseDateTime(p, &res->dst_end); + + return p != nullptr && *p == '\0'; +} + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_posix.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_posix.h index f136435930..e9de2b77ad 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_posix.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/time_zone_posix.h @@ -1,132 +1,132 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Parsing of a POSIX zone spec as described in the TZ part of section 8.3 in -// http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html. -// -// The current POSIX spec for America/Los_Angeles is "PST8PDT,M3.2.0,M11.1.0", -// which would be broken down as ... -// -// PosixTimeZone { -// std_abbr = "PST" -// std_offset = -28800 -// dst_abbr = "PDT" -// dst_offset = -25200 -// dst_start = PosixTransition { -// date { -// m { -// month = 3 -// week = 2 -// weekday = 0 -// } -// } -// time { -// offset = 7200 -// } -// } -// dst_end = PosixTransition { -// date { -// m { -// month = 11 -// week = 1 -// weekday = 0 -// } -// } -// time { -// offset = 7200 -// } -// } -// } - -#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ -#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ - -#include <cstdint> +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Parsing of a POSIX zone spec as described in the TZ part of section 8.3 in +// http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html. +// +// The current POSIX spec for America/Los_Angeles is "PST8PDT,M3.2.0,M11.1.0", +// which would be broken down as ... +// +// PosixTimeZone { +// std_abbr = "PST" +// std_offset = -28800 +// dst_abbr = "PDT" +// dst_offset = -25200 +// dst_start = PosixTransition { +// date { +// m { +// month = 3 +// week = 2 +// weekday = 0 +// } +// } +// time { +// offset = 7200 +// } +// } +// dst_end = PosixTransition { +// date { +// m { +// month = 11 +// week = 1 +// weekday = 0 +// } +// } +// time { +// offset = 7200 +// } +// } +// } + +#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ +#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ + +#include <cstdint> #include <util/generic/string.h> #include "y_absl/base/config.h" namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// The date/time of the transition. The date is specified as either: -// (J) the Nth day of the year (1 <= N <= 365), excluding leap days, or -// (N) the Nth day of the year (0 <= N <= 365), including leap days, or -// (M) the Nth weekday of a month (e.g., the 2nd Sunday in March). -// The time, specified as a day offset, identifies the particular moment -// of the transition, and may be negative or >= 24h, and in which case -// it would take us to another day, and perhaps week, or even month. -struct PosixTransition { - enum DateFormat { J, N, M }; - - struct Date { - struct NonLeapDay { - std::int_fast16_t day; // day of non-leap year [1:365] - }; - struct Day { - std::int_fast16_t day; // day of year [0:365] - }; - struct MonthWeekWeekday { - std::int_fast8_t month; // month of year [1:12] - std::int_fast8_t week; // week of month [1:5] (5==last) - std::int_fast8_t weekday; // 0==Sun, ..., 6=Sat - }; - - DateFormat fmt; - - union { - NonLeapDay j; - Day n; - MonthWeekWeekday m; - }; - }; - - struct Time { - std::int_fast32_t offset; // seconds before/after 00:00:00 - }; - - Date date; - Time time; -}; - -// The entirety of a POSIX-string specified time-zone rule. The standard -// abbreviation and offset are always given. If the time zone includes -// daylight saving, then the daylight abbrevation is non-empty and the -// remaining fields are also valid. Note that the start/end transitions -// are not ordered---in the southern hemisphere the transition to end -// daylight time occurs first in any particular year. -struct PosixTimeZone { +namespace time_internal { +namespace cctz { + +// The date/time of the transition. The date is specified as either: +// (J) the Nth day of the year (1 <= N <= 365), excluding leap days, or +// (N) the Nth day of the year (0 <= N <= 365), including leap days, or +// (M) the Nth weekday of a month (e.g., the 2nd Sunday in March). +// The time, specified as a day offset, identifies the particular moment +// of the transition, and may be negative or >= 24h, and in which case +// it would take us to another day, and perhaps week, or even month. +struct PosixTransition { + enum DateFormat { J, N, M }; + + struct Date { + struct NonLeapDay { + std::int_fast16_t day; // day of non-leap year [1:365] + }; + struct Day { + std::int_fast16_t day; // day of year [0:365] + }; + struct MonthWeekWeekday { + std::int_fast8_t month; // month of year [1:12] + std::int_fast8_t week; // week of month [1:5] (5==last) + std::int_fast8_t weekday; // 0==Sun, ..., 6=Sat + }; + + DateFormat fmt; + + union { + NonLeapDay j; + Day n; + MonthWeekWeekday m; + }; + }; + + struct Time { + std::int_fast32_t offset; // seconds before/after 00:00:00 + }; + + Date date; + Time time; +}; + +// The entirety of a POSIX-string specified time-zone rule. The standard +// abbreviation and offset are always given. If the time zone includes +// daylight saving, then the daylight abbrevation is non-empty and the +// remaining fields are also valid. Note that the start/end transitions +// are not ordered---in the southern hemisphere the transition to end +// daylight time occurs first in any particular year. +struct PosixTimeZone { TString std_abbr; - std::int_fast32_t std_offset; - + std::int_fast32_t std_offset; + TString dst_abbr; - std::int_fast32_t dst_offset; - PosixTransition dst_start; - PosixTransition dst_end; -}; - -// Breaks down a POSIX time-zone specification into its constituent pieces, -// filling in any missing values (DST offset, or start/end transition times) -// with the standard-defined defaults. Returns false if the specification -// could not be parsed (although some fields of *res may have been altered). + std::int_fast32_t dst_offset; + PosixTransition dst_start; + PosixTransition dst_end; +}; + +// Breaks down a POSIX time-zone specification into its constituent pieces, +// filling in any missing values (DST offset, or start/end transition times) +// with the standard-defined defaults. Returns false if the specification +// could not be parsed (although some fields of *res may have been altered). bool ParsePosixSpec(const TString& spec, PosixTimeZone* res); - -} // namespace cctz -} // namespace time_internal + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - -#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ + +#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/tzfile.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/tzfile.h index 1683a698cb..31e8598257 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/tzfile.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/tzfile.h @@ -1,47 +1,47 @@ -/* Layout and location of TZif files. */ - -#ifndef TZFILE_H - -#define TZFILE_H - -/* -** This file is in the public domain, so clarified as of -** 1996-06-05 by Arthur David Olson. -*/ - -/* -** This header is for use ONLY with the time conversion code. -** There is no guarantee that it will remain unchanged, -** or that it will remain at all. -** Do NOT copy it to any system include directory. -** Thank you! -*/ - -/* -** Information about time zone files. -*/ - -#ifndef TZDIR +/* Layout and location of TZif files. */ + +#ifndef TZFILE_H + +#define TZFILE_H + +/* +** This file is in the public domain, so clarified as of +** 1996-06-05 by Arthur David Olson. +*/ + +/* +** This header is for use ONLY with the time conversion code. +** There is no guarantee that it will remain unchanged, +** or that it will remain at all. +** Do NOT copy it to any system include directory. +** Thank you! +*/ + +/* +** Information about time zone files. +*/ + +#ifndef TZDIR #define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */ #endif /* !defined TZDIR */ - -#ifndef TZDEFAULT + +#ifndef TZDEFAULT #define TZDEFAULT "/etc/localtime" -#endif /* !defined TZDEFAULT */ - -#ifndef TZDEFRULES +#endif /* !defined TZDEFAULT */ + +#ifndef TZDEFRULES #define TZDEFRULES "posixrules" -#endif /* !defined TZDEFRULES */ - -/* See Internet RFC 8536 for more details about the following format. */ - -/* -** Each file begins with. . . -*/ - +#endif /* !defined TZDEFRULES */ + +/* See Internet RFC 8536 for more details about the following format. */ + +/* +** Each file begins with. . . +*/ + #define TZ_MAGIC "TZif" - -struct tzhead { + +struct tzhead { char tzh_magic[4]; /* TZ_MAGIC */ char tzh_version[1]; /* '\0' or '2'-'4' as of 2021 */ char tzh_reserved[15]; /* reserved; must be zero */ @@ -51,72 +51,72 @@ struct tzhead { char tzh_timecnt[4]; /* coded number of transition times */ char tzh_typecnt[4]; /* coded number of local time types */ char tzh_charcnt[4]; /* coded number of abbr. chars */ -}; - -/* -** . . .followed by. . . -** -** tzh_timecnt (char [4])s coded transition times a la time(2) -** tzh_timecnt (unsigned char)s types of local time starting at above -** tzh_typecnt repetitions of -** one (char [4]) coded UT offset in seconds -** one (unsigned char) used to set tm_isdst -** one (unsigned char) that's an abbreviation list index -** tzh_charcnt (char)s '\0'-terminated zone abbreviations -** tzh_leapcnt repetitions of -** one (char [4]) coded leap second transition times -** one (char [4]) total correction after above -** tzh_ttisstdcnt (char)s indexed by type; if 1, transition -** time is standard time, if 0, -** transition time is local (wall clock) -** time; if absent, transition times are -** assumed to be local time -** tzh_ttisutcnt (char)s indexed by type; if 1, transition -** time is UT, if 0, transition time is -** local time; if absent, transition -** times are assumed to be local time. -** When this is 1, the corresponding -** std/wall indicator must also be 1. -*/ - -/* -** If tzh_version is '2' or greater, the above is followed by a second instance -** of tzhead and a second instance of the data in which each coded transition -** time uses 8 rather than 4 chars, +}; + +/* +** . . .followed by. . . +** +** tzh_timecnt (char [4])s coded transition times a la time(2) +** tzh_timecnt (unsigned char)s types of local time starting at above +** tzh_typecnt repetitions of +** one (char [4]) coded UT offset in seconds +** one (unsigned char) used to set tm_isdst +** one (unsigned char) that's an abbreviation list index +** tzh_charcnt (char)s '\0'-terminated zone abbreviations +** tzh_leapcnt repetitions of +** one (char [4]) coded leap second transition times +** one (char [4]) total correction after above +** tzh_ttisstdcnt (char)s indexed by type; if 1, transition +** time is standard time, if 0, +** transition time is local (wall clock) +** time; if absent, transition times are +** assumed to be local time +** tzh_ttisutcnt (char)s indexed by type; if 1, transition +** time is UT, if 0, transition time is +** local time; if absent, transition +** times are assumed to be local time. +** When this is 1, the corresponding +** std/wall indicator must also be 1. +*/ + +/* +** If tzh_version is '2' or greater, the above is followed by a second instance +** of tzhead and a second instance of the data in which each coded transition +** time uses 8 rather than 4 chars, ** then a POSIX-TZ-environment-variable-style string for use in handling -** instants after the last transition time stored in the file -** (with nothing between the newlines if there is no POSIX representation for -** such instants). -** -** If tz_version is '3' or greater, the above is extended as follows. +** instants after the last transition time stored in the file +** (with nothing between the newlines if there is no POSIX representation for +** such instants). +** +** If tz_version is '3' or greater, the above is extended as follows. ** First, the POSIX TZ string's hour offset may range from -167 -** through 167 as compared to the POSIX-required 0 through 24. -** Second, its DST start time may be January 1 at 00:00 and its stop -** time December 31 at 24:00 plus the difference between DST and -** standard time, indicating DST all year. -*/ - -/* -** In the current implementation, "tzset()" refuses to deal with files that -** exceed any of the limits below. -*/ - -#ifndef TZ_MAX_TIMES +** through 167 as compared to the POSIX-required 0 through 24. +** Second, its DST start time may be January 1 at 00:00 and its stop +** time December 31 at 24:00 plus the difference between DST and +** standard time, indicating DST all year. +*/ + +/* +** In the current implementation, "tzset()" refuses to deal with files that +** exceed any of the limits below. +*/ + +#ifndef TZ_MAX_TIMES #define TZ_MAX_TIMES 2000 -#endif /* !defined TZ_MAX_TIMES */ - -#ifndef TZ_MAX_TYPES -/* This must be at least 17 for Europe/Samara and Europe/Vilnius. */ +#endif /* !defined TZ_MAX_TIMES */ + +#ifndef TZ_MAX_TYPES +/* This must be at least 17 for Europe/Samara and Europe/Vilnius. */ #define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ #endif /* !defined TZ_MAX_TYPES */ - -#ifndef TZ_MAX_CHARS + +#ifndef TZ_MAX_CHARS #define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */ /* (limited by what unsigned chars can hold) */ #endif /* !defined TZ_MAX_CHARS */ - -#ifndef TZ_MAX_LEAPS + +#ifndef TZ_MAX_LEAPS #define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ #endif /* !defined TZ_MAX_LEAPS */ - -#endif /* !defined TZFILE_H */ + +#endif /* !defined TZFILE_H */ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/zone_info_source.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/zone_info_source.cc index 1b65bd6090..be58c20fb3 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/zone_info_source.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src/zone_info_source.cc @@ -1,70 +1,70 @@ -// Copyright 2016 Google Inc. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "y_absl/time/internal/cctz/include/cctz/zone_info_source.h" - + #include "y_absl/base/config.h" namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz { - -// Defined out-of-line to avoid emitting a weak vtable in all TUs. -ZoneInfoSource::~ZoneInfoSource() {} +namespace time_internal { +namespace cctz { + +// Defined out-of-line to avoid emitting a weak vtable in all TUs. +ZoneInfoSource::~ZoneInfoSource() {} TString ZoneInfoSource::Version() const { return TString(); } - -} // namespace cctz -} // namespace time_internal + +} // namespace cctz +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { -namespace cctz_extension { - -namespace { - -// A default for cctz_extension::zone_info_source_factory, which simply -// defers to the fallback factory. +namespace time_internal { +namespace cctz_extension { + +namespace { + +// A default for cctz_extension::zone_info_source_factory, which simply +// defers to the fallback factory. std::unique_ptr<y_absl::time_internal::cctz::ZoneInfoSource> DefaultFactory( const TString& name, const std::function< std::unique_ptr<y_absl::time_internal::cctz::ZoneInfoSource>( const TString& name)>& fallback_factory) { - return fallback_factory(name); -} - -} // namespace - -// A "weak" definition for cctz_extension::zone_info_source_factory. -// The user may override this with their own "strong" definition (see -// zone_info_source.h). -#if !defined(__has_attribute) -#define __has_attribute(x) 0 -#endif -// MinGW is GCC on Windows, so while it asserts __has_attribute(weak), the -// Windows linker cannot handle that. Nor does the MinGW compiler know how to -// pass "#pragma comment(linker, ...)" to the Windows linker. -#if (__has_attribute(weak) || defined(__GNUC__)) && !defined(__MINGW32__) + return fallback_factory(name); +} + +} // namespace + +// A "weak" definition for cctz_extension::zone_info_source_factory. +// The user may override this with their own "strong" definition (see +// zone_info_source.h). +#if !defined(__has_attribute) +#define __has_attribute(x) 0 +#endif +// MinGW is GCC on Windows, so while it asserts __has_attribute(weak), the +// Windows linker cannot handle that. Nor does the MinGW compiler know how to +// pass "#pragma comment(linker, ...)" to the Windows linker. +#if (__has_attribute(weak) || defined(__GNUC__)) && !defined(__MINGW32__) ZoneInfoSourceFactory zone_info_source_factory __attribute__((weak)) = DefaultFactory; -#elif defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_LIBCPP_VERSION) -extern ZoneInfoSourceFactory zone_info_source_factory; -extern ZoneInfoSourceFactory default_factory; -ZoneInfoSourceFactory default_factory = DefaultFactory; +#elif defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_LIBCPP_VERSION) +extern ZoneInfoSourceFactory zone_info_source_factory; +extern ZoneInfoSourceFactory default_factory; +ZoneInfoSourceFactory default_factory = DefaultFactory; #if defined(_M_IX86) || defined(_M_ARM) #pragma comment( \ linker, \ @@ -101,15 +101,15 @@ ZoneInfoSourceFactory default_factory = DefaultFactory; "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \ "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \ "@@ZEA") -#else -#error Unsupported MSVC platform -#endif // _M_<PLATFORM> -#else -// Make it a "strong" definition if we have no other choice. -ZoneInfoSourceFactory zone_info_source_factory = DefaultFactory; -#endif - -} // namespace cctz_extension -} // namespace time_internal +#else +#error Unsupported MSVC platform +#endif // _M_<PLATFORM> +#else +// Make it a "strong" definition if we have no other choice. +ZoneInfoSourceFactory zone_info_source_factory = DefaultFactory; +#endif + +} // namespace cctz_extension +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/get_current_time_chrono.inc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/get_current_time_chrono.inc index 746fe23532..ef28e97e5a 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/get_current_time_chrono.inc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/get_current_time_chrono.inc @@ -1,31 +1,31 @@ -// Copyright 2018 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include <chrono> -#include <cstdint> - +// Copyright 2018 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <chrono> +#include <cstdint> + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { - -static int64_t GetCurrentTimeNanosFromSystem() { - return std::chrono::duration_cast<std::chrono::nanoseconds>( - std::chrono::system_clock::now() - - std::chrono::system_clock::from_time_t(0)) - .count(); -} - -} // namespace time_internal +namespace time_internal { + +static int64_t GetCurrentTimeNanosFromSystem() { + return std::chrono::duration_cast<std::chrono::nanoseconds>( + std::chrono::system_clock::now() - + std::chrono::system_clock::from_time_t(0)) + .count(); +} + +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/get_current_time_posix.inc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/get_current_time_posix.inc index 2f6ae9af03..1068fea026 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/get_current_time_posix.inc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/get_current_time_posix.inc @@ -1,24 +1,24 @@ #include "y_absl/time/clock.h" - -#include <sys/time.h> -#include <ctime> -#include <cstdint> - + +#include <sys/time.h> +#include <ctime> +#include <cstdint> + #include "y_absl/base/internal/raw_logging.h" - + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { - -static int64_t GetCurrentTimeNanosFromSystem() { - const int64_t kNanosPerSecond = 1000 * 1000 * 1000; - struct timespec ts; - ABSL_RAW_CHECK(clock_gettime(CLOCK_REALTIME, &ts) == 0, - "Failed to read real-time clock."); - return (int64_t{ts.tv_sec} * kNanosPerSecond + - int64_t{ts.tv_nsec}); -} - -} // namespace time_internal +namespace time_internal { + +static int64_t GetCurrentTimeNanosFromSystem() { + const int64_t kNanosPerSecond = 1000 * 1000 * 1000; + struct timespec ts; + ABSL_RAW_CHECK(clock_gettime(CLOCK_REALTIME, &ts) == 0, + "Failed to read real-time clock."); + return (int64_t{ts.tv_sec} * kNanosPerSecond + + int64_t{ts.tv_nsec}); +} + +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/test_util.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/test_util.h index 7432c67347..22b991b836 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/test_util.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/test_util.h @@ -1,33 +1,33 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef ABSL_TIME_INTERNAL_TEST_UTIL_H_ -#define ABSL_TIME_INTERNAL_TEST_UTIL_H_ - +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_TIME_INTERNAL_TEST_UTIL_H_ +#define ABSL_TIME_INTERNAL_TEST_UTIL_H_ + #include <util/generic/string.h> - + #include "y_absl/time/time.h" - + namespace y_absl { ABSL_NAMESPACE_BEGIN -namespace time_internal { - -// Loads the named timezone, but dies on any failure. +namespace time_internal { + +// Loads the named timezone, but dies on any failure. y_absl::TimeZone LoadTimeZone(const TString& name); - -} // namespace time_internal + +} // namespace time_internal ABSL_NAMESPACE_END } // namespace y_absl - -#endif // ABSL_TIME_INTERNAL_TEST_UTIL_H_ + +#endif // ABSL_TIME_INTERNAL_TEST_UTIL_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/zoneinfo.inc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/zoneinfo.inc index e453bb8356..bfed82990d 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/zoneinfo.inc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/zoneinfo.inc @@ -1,729 +1,729 @@ -unsigned char America_Los_Angeles[] = { - 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, - 0x9e, 0xa6, 0x48, 0xa0, 0x9f, 0xbb, 0x15, 0x90, 0xa0, 0x86, 0x2a, 0xa0, - 0xa1, 0x9a, 0xf7, 0x90, 0xcb, 0x89, 0x1a, 0xa0, 0xd2, 0x23, 0xf4, 0x70, - 0xd2, 0x61, 0x26, 0x10, 0xd6, 0xfe, 0x74, 0x5c, 0xd8, 0x80, 0xad, 0x90, - 0xda, 0xfe, 0xc3, 0x90, 0xdb, 0xc0, 0x90, 0x10, 0xdc, 0xde, 0xa5, 0x90, - 0xdd, 0xa9, 0xac, 0x90, 0xde, 0xbe, 0x87, 0x90, 0xdf, 0x89, 0x8e, 0x90, - 0xe0, 0x9e, 0x69, 0x90, 0xe1, 0x69, 0x70, 0x90, 0xe2, 0x7e, 0x4b, 0x90, - 0xe3, 0x49, 0x52, 0x90, 0xe4, 0x5e, 0x2d, 0x90, 0xe5, 0x29, 0x34, 0x90, - 0xe6, 0x47, 0x4a, 0x10, 0xe7, 0x12, 0x51, 0x10, 0xe8, 0x27, 0x2c, 0x10, - 0xe8, 0xf2, 0x33, 0x10, 0xea, 0x07, 0x0e, 0x10, 0xea, 0xd2, 0x15, 0x10, - 0xeb, 0xe6, 0xf0, 0x10, 0xec, 0xb1, 0xf7, 0x10, 0xed, 0xc6, 0xd2, 0x10, - 0xee, 0x91, 0xd9, 0x10, 0xef, 0xaf, 0xee, 0x90, 0xf0, 0x71, 0xbb, 0x10, - 0xf1, 0x8f, 0xd0, 0x90, 0xf2, 0x7f, 0xc1, 0x90, 0xf3, 0x6f, 0xb2, 0x90, - 0xf4, 0x5f, 0xa3, 0x90, 0xf5, 0x4f, 0x94, 0x90, 0xf6, 0x3f, 0x85, 0x90, - 0xf7, 0x2f, 0x76, 0x90, 0xf8, 0x28, 0xa2, 0x10, 0xf9, 0x0f, 0x58, 0x90, - 0xfa, 0x08, 0x84, 0x10, 0xfa, 0xf8, 0x83, 0x20, 0xfb, 0xe8, 0x66, 0x10, - 0xfc, 0xd8, 0x65, 0x20, 0xfd, 0xc8, 0x48, 0x10, 0xfe, 0xb8, 0x47, 0x20, - 0xff, 0xa8, 0x2a, 0x10, 0x00, 0x98, 0x29, 0x20, 0x01, 0x88, 0x0c, 0x10, - 0x02, 0x78, 0x0b, 0x20, 0x03, 0x71, 0x28, 0x90, 0x04, 0x61, 0x27, 0xa0, - 0x05, 0x51, 0x0a, 0x90, 0x06, 0x41, 0x09, 0xa0, 0x07, 0x30, 0xec, 0x90, - 0x07, 0x8d, 0x43, 0xa0, 0x09, 0x10, 0xce, 0x90, 0x09, 0xad, 0xbf, 0x20, - 0x0a, 0xf0, 0xb0, 0x90, 0x0b, 0xe0, 0xaf, 0xa0, 0x0c, 0xd9, 0xcd, 0x10, - 0x0d, 0xc0, 0x91, 0xa0, 0x0e, 0xb9, 0xaf, 0x10, 0x0f, 0xa9, 0xae, 0x20, - 0x10, 0x99, 0x91, 0x10, 0x11, 0x89, 0x90, 0x20, 0x12, 0x79, 0x73, 0x10, - 0x13, 0x69, 0x72, 0x20, 0x14, 0x59, 0x55, 0x10, 0x15, 0x49, 0x54, 0x20, - 0x16, 0x39, 0x37, 0x10, 0x17, 0x29, 0x36, 0x20, 0x18, 0x22, 0x53, 0x90, - 0x19, 0x09, 0x18, 0x20, 0x1a, 0x02, 0x35, 0x90, 0x1a, 0xf2, 0x34, 0xa0, - 0x1b, 0xe2, 0x17, 0x90, 0x1c, 0xd2, 0x16, 0xa0, 0x1d, 0xc1, 0xf9, 0x90, - 0x1e, 0xb1, 0xf8, 0xa0, 0x1f, 0xa1, 0xdb, 0x90, 0x20, 0x76, 0x2b, 0x20, - 0x21, 0x81, 0xbd, 0x90, 0x22, 0x56, 0x0d, 0x20, 0x23, 0x6a, 0xda, 0x10, - 0x24, 0x35, 0xef, 0x20, 0x25, 0x4a, 0xbc, 0x10, 0x26, 0x15, 0xd1, 0x20, - 0x27, 0x2a, 0x9e, 0x10, 0x27, 0xfe, 0xed, 0xa0, 0x29, 0x0a, 0x80, 0x10, - 0x29, 0xde, 0xcf, 0xa0, 0x2a, 0xea, 0x62, 0x10, 0x2b, 0xbe, 0xb1, 0xa0, - 0x2c, 0xd3, 0x7e, 0x90, 0x2d, 0x9e, 0x93, 0xa0, 0x2e, 0xb3, 0x60, 0x90, - 0x2f, 0x7e, 0x75, 0xa0, 0x30, 0x93, 0x42, 0x90, 0x31, 0x67, 0x92, 0x20, - 0x32, 0x73, 0x24, 0x90, 0x33, 0x47, 0x74, 0x20, 0x34, 0x53, 0x06, 0x90, - 0x35, 0x27, 0x56, 0x20, 0x36, 0x32, 0xe8, 0x90, 0x37, 0x07, 0x38, 0x20, - 0x38, 0x1c, 0x05, 0x10, 0x38, 0xe7, 0x1a, 0x20, 0x39, 0xfb, 0xe7, 0x10, - 0x3a, 0xc6, 0xfc, 0x20, 0x3b, 0xdb, 0xc9, 0x10, 0x3c, 0xb0, 0x18, 0xa0, - 0x3d, 0xbb, 0xab, 0x10, 0x3e, 0x8f, 0xfa, 0xa0, 0x3f, 0x9b, 0x8d, 0x10, - 0x40, 0x6f, 0xdc, 0xa0, 0x41, 0x84, 0xa9, 0x90, 0x42, 0x4f, 0xbe, 0xa0, - 0x43, 0x64, 0x8b, 0x90, 0x44, 0x2f, 0xa0, 0xa0, 0x45, 0x44, 0x6d, 0x90, - 0x45, 0xf3, 0xd3, 0x20, 0x47, 0x2d, 0x8a, 0x10, 0x47, 0xd3, 0xb5, 0x20, - 0x49, 0x0d, 0x6c, 0x10, 0x49, 0xb3, 0x97, 0x20, 0x4a, 0xed, 0x4e, 0x10, - 0x4b, 0x9c, 0xb3, 0xa0, 0x4c, 0xd6, 0x6a, 0x90, 0x4d, 0x7c, 0x95, 0xa0, - 0x4e, 0xb6, 0x4c, 0x90, 0x4f, 0x5c, 0x77, 0xa0, 0x50, 0x96, 0x2e, 0x90, - 0x51, 0x3c, 0x59, 0xa0, 0x52, 0x76, 0x10, 0x90, 0x53, 0x1c, 0x3b, 0xa0, - 0x54, 0x55, 0xf2, 0x90, 0x54, 0xfc, 0x1d, 0xa0, 0x56, 0x35, 0xd4, 0x90, - 0x56, 0xe5, 0x3a, 0x20, 0x58, 0x1e, 0xf1, 0x10, 0x58, 0xc5, 0x1c, 0x20, - 0x59, 0xfe, 0xd3, 0x10, 0x5a, 0xa4, 0xfe, 0x20, 0x5b, 0xde, 0xb5, 0x10, - 0x5c, 0x84, 0xe0, 0x20, 0x5d, 0xbe, 0x97, 0x10, 0x5e, 0x64, 0xc2, 0x20, - 0x5f, 0x9e, 0x79, 0x10, 0x60, 0x4d, 0xde, 0xa0, 0x61, 0x87, 0x95, 0x90, - 0x62, 0x2d, 0xc0, 0xa0, 0x63, 0x67, 0x77, 0x90, 0x64, 0x0d, 0xa2, 0xa0, - 0x65, 0x47, 0x59, 0x90, 0x65, 0xed, 0x84, 0xa0, 0x67, 0x27, 0x3b, 0x90, - 0x67, 0xcd, 0x66, 0xa0, 0x69, 0x07, 0x1d, 0x90, 0x69, 0xad, 0x48, 0xa0, - 0x6a, 0xe6, 0xff, 0x90, 0x6b, 0x96, 0x65, 0x20, 0x6c, 0xd0, 0x1c, 0x10, - 0x6d, 0x76, 0x47, 0x20, 0x6e, 0xaf, 0xfe, 0x10, 0x6f, 0x56, 0x29, 0x20, - 0x70, 0x8f, 0xe0, 0x10, 0x71, 0x36, 0x0b, 0x20, 0x72, 0x6f, 0xc2, 0x10, - 0x73, 0x15, 0xed, 0x20, 0x74, 0x4f, 0xa4, 0x10, 0x74, 0xff, 0x09, 0xa0, - 0x76, 0x38, 0xc0, 0x90, 0x76, 0xde, 0xeb, 0xa0, 0x78, 0x18, 0xa2, 0x90, - 0x78, 0xbe, 0xcd, 0xa0, 0x79, 0xf8, 0x84, 0x90, 0x7a, 0x9e, 0xaf, 0xa0, - 0x7b, 0xd8, 0x66, 0x90, 0x7c, 0x7e, 0x91, 0xa0, 0x7d, 0xb8, 0x48, 0x90, - 0x7e, 0x5e, 0x73, 0xa0, 0x7f, 0x98, 0x2a, 0x90, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0xff, 0xff, 0x91, 0x26, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x90, - 0x01, 0x04, 0xff, 0xff, 0x8f, 0x80, 0x00, 0x08, 0xff, 0xff, 0x9d, 0x90, - 0x01, 0x0c, 0xff, 0xff, 0x9d, 0x90, 0x01, 0x10, 0x4c, 0x4d, 0x54, 0x00, - 0x50, 0x44, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x57, 0x54, 0x00, - 0x50, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xbb, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0xf8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x04, - 0x1a, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xa6, 0x48, 0xa0, 0xff, 0xff, - 0xff, 0xff, 0x9f, 0xbb, 0x15, 0x90, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x86, - 0x2a, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xa1, 0x9a, 0xf7, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xcb, 0x89, 0x1a, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x23, - 0xf4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x61, 0x26, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xd6, 0xfe, 0x74, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x80, - 0xad, 0x90, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfe, 0xc3, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xdb, 0xc0, 0x90, 0x10, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xde, - 0xa5, 0x90, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xa9, 0xac, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xde, 0xbe, 0x87, 0x90, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x89, - 0x8e, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9e, 0x69, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xe1, 0x69, 0x70, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe2, 0x7e, - 0x4b, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x49, 0x52, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xe4, 0x5e, 0x2d, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe5, 0x29, - 0x34, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x47, 0x4a, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xe7, 0x12, 0x51, 0x10, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x27, - 0x2c, 0x10, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xf2, 0x33, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xea, 0x07, 0x0e, 0x10, 0xff, 0xff, 0xff, 0xff, 0xea, 0xd2, - 0x15, 0x10, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xf0, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xec, 0xb1, 0xf7, 0x10, 0xff, 0xff, 0xff, 0xff, 0xed, 0xc6, - 0xd2, 0x10, 0xff, 0xff, 0xff, 0xff, 0xee, 0x91, 0xd9, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xef, 0xaf, 0xee, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x71, - 0xbb, 0x10, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xd0, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xf2, 0x7f, 0xc1, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x6f, - 0xb2, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5f, 0xa3, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xf5, 0x4f, 0x94, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x3f, - 0x85, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x2f, 0x76, 0x90, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0x28, 0xa2, 0x10, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x0f, - 0x58, 0x90, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x84, 0x10, 0xff, 0xff, - 0xff, 0xff, 0xfa, 0xf8, 0x83, 0x20, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xe8, - 0x66, 0x10, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd8, 0x65, 0x20, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0xc8, 0x48, 0x10, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xb8, - 0x47, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa8, 0x2a, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x98, 0x29, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x88, - 0x0c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x78, 0x0b, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x71, 0x28, 0x90, 0x00, 0x00, 0x00, 0x00, 0x04, 0x61, - 0x27, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x05, 0x51, 0x0a, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x06, 0x41, 0x09, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x30, - 0xec, 0x90, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8d, 0x43, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x09, 0x10, 0xce, 0x90, 0x00, 0x00, 0x00, 0x00, 0x09, 0xad, - 0xbf, 0x20, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0xb0, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x0b, 0xe0, 0xaf, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xd9, - 0xcd, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xc0, 0x91, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x0e, 0xb9, 0xaf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xa9, - 0xae, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x99, 0x91, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x11, 0x89, 0x90, 0x20, 0x00, 0x00, 0x00, 0x00, 0x12, 0x79, - 0x73, 0x10, 0x00, 0x00, 0x00, 0x00, 0x13, 0x69, 0x72, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x14, 0x59, 0x55, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15, 0x49, - 0x54, 0x20, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x37, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x17, 0x29, 0x36, 0x20, 0x00, 0x00, 0x00, 0x00, 0x18, 0x22, - 0x53, 0x90, 0x00, 0x00, 0x00, 0x00, 0x19, 0x09, 0x18, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x1a, 0x02, 0x35, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xf2, - 0x34, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe2, 0x17, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x1c, 0xd2, 0x16, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xc1, - 0xf9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xb1, 0xf8, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x1f, 0xa1, 0xdb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x20, 0x76, - 0x2b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0xbd, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x22, 0x56, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x23, 0x6a, - 0xda, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x35, 0xef, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x25, 0x4a, 0xbc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x26, 0x15, - 0xd1, 0x20, 0x00, 0x00, 0x00, 0x00, 0x27, 0x2a, 0x9e, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x27, 0xfe, 0xed, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x29, 0x0a, - 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x29, 0xde, 0xcf, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x2a, 0xea, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00, 0x2b, 0xbe, - 0xb1, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd3, 0x7e, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x2d, 0x9e, 0x93, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xb3, - 0x60, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0x75, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x93, 0x42, 0x90, 0x00, 0x00, 0x00, 0x00, 0x31, 0x67, - 0x92, 0x20, 0x00, 0x00, 0x00, 0x00, 0x32, 0x73, 0x24, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x33, 0x47, 0x74, 0x20, 0x00, 0x00, 0x00, 0x00, 0x34, 0x53, - 0x06, 0x90, 0x00, 0x00, 0x00, 0x00, 0x35, 0x27, 0x56, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x36, 0x32, 0xe8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x37, 0x07, - 0x38, 0x20, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1c, 0x05, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x38, 0xe7, 0x1a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x39, 0xfb, - 0xe7, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xc6, 0xfc, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x3b, 0xdb, 0xc9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xb0, - 0x18, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0xab, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x3e, 0x8f, 0xfa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x9b, - 0x8d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xdc, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x41, 0x84, 0xa9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0x4f, - 0xbe, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x8b, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x44, 0x2f, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x45, 0x44, - 0x6d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf3, 0xd3, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x47, 0x2d, 0x8a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x47, 0xd3, - 0xb5, 0x20, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0d, 0x6c, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x49, 0xb3, 0x97, 0x20, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xed, - 0x4e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x9c, 0xb3, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x4c, 0xd6, 0x6a, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x7c, - 0x95, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xb6, 0x4c, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x4f, 0x5c, 0x77, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x50, 0x96, - 0x2e, 0x90, 0x00, 0x00, 0x00, 0x00, 0x51, 0x3c, 0x59, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x52, 0x76, 0x10, 0x90, 0x00, 0x00, 0x00, 0x00, 0x53, 0x1c, - 0x3b, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xf2, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x54, 0xfc, 0x1d, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x56, 0x35, - 0xd4, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56, 0xe5, 0x3a, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x58, 0x1e, 0xf1, 0x10, 0x00, 0x00, 0x00, 0x00, 0x58, 0xc5, - 0x1c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x59, 0xfe, 0xd3, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x5a, 0xa4, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xde, - 0xb5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x84, 0xe0, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x5d, 0xbe, 0x97, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x64, - 0xc2, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x9e, 0x79, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x60, 0x4d, 0xde, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x61, 0x87, - 0x95, 0x90, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2d, 0xc0, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x63, 0x67, 0x77, 0x90, 0x00, 0x00, 0x00, 0x00, 0x64, 0x0d, - 0xa2, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x59, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x65, 0xed, 0x84, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x67, 0x27, - 0x3b, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0xcd, 0x66, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x69, 0x07, 0x1d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x69, 0xad, - 0x48, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe6, 0xff, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x6b, 0x96, 0x65, 0x20, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xd0, - 0x1c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x47, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x6e, 0xaf, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x56, - 0x29, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0xe0, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x71, 0x36, 0x0b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6f, - 0xc2, 0x10, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xed, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x74, 0x4f, 0xa4, 0x10, 0x00, 0x00, 0x00, 0x00, 0x74, 0xff, - 0x09, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0xc0, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x76, 0xde, 0xeb, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x78, 0x18, - 0xa2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbe, 0xcd, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x79, 0xf8, 0x84, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x9e, - 0xaf, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xd8, 0x66, 0x90, 0x00, 0x00, - 0x00, 0x00, 0x7c, 0x7e, 0x91, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xb8, - 0x48, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5e, 0x73, 0xa0, 0x00, 0x00, - 0x00, 0x00, 0x7f, 0x98, 0x2a, 0x90, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0xff, 0xff, 0x91, 0x26, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x90, 0x01, - 0x04, 0xff, 0xff, 0x8f, 0x80, 0x00, 0x08, 0xff, 0xff, 0x9d, 0x90, 0x01, - 0x0c, 0xff, 0xff, 0x9d, 0x90, 0x01, 0x10, 0x4c, 0x4d, 0x54, 0x00, 0x50, - 0x44, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x57, 0x54, 0x00, 0x50, - 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x0a, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x2c, 0x4d, 0x33, - 0x2e, 0x32, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x31, 0x2e, 0x31, 0x2e, 0x30, - 0x0a -}; -unsigned int America_Los_Angeles_len = 2845; -unsigned char America_New_York[] = { - 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, - 0x9e, 0xa6, 0x1e, 0x70, 0x9f, 0xba, 0xeb, 0x60, 0xa0, 0x86, 0x00, 0x70, - 0xa1, 0x9a, 0xcd, 0x60, 0xa2, 0x65, 0xe2, 0x70, 0xa3, 0x83, 0xe9, 0xe0, - 0xa4, 0x6a, 0xae, 0x70, 0xa5, 0x35, 0xa7, 0x60, 0xa6, 0x53, 0xca, 0xf0, - 0xa7, 0x15, 0x89, 0x60, 0xa8, 0x33, 0xac, 0xf0, 0xa8, 0xfe, 0xa5, 0xe0, - 0xaa, 0x13, 0x8e, 0xf0, 0xaa, 0xde, 0x87, 0xe0, 0xab, 0xf3, 0x70, 0xf0, - 0xac, 0xbe, 0x69, 0xe0, 0xad, 0xd3, 0x52, 0xf0, 0xae, 0x9e, 0x4b, 0xe0, - 0xaf, 0xb3, 0x34, 0xf0, 0xb0, 0x7e, 0x2d, 0xe0, 0xb1, 0x9c, 0x51, 0x70, - 0xb2, 0x67, 0x4a, 0x60, 0xb3, 0x7c, 0x33, 0x70, 0xb4, 0x47, 0x2c, 0x60, - 0xb5, 0x5c, 0x15, 0x70, 0xb6, 0x27, 0x0e, 0x60, 0xb7, 0x3b, 0xf7, 0x70, - 0xb8, 0x06, 0xf0, 0x60, 0xb9, 0x1b, 0xd9, 0x70, 0xb9, 0xe6, 0xd2, 0x60, - 0xbb, 0x04, 0xf5, 0xf0, 0xbb, 0xc6, 0xb4, 0x60, 0xbc, 0xe4, 0xd7, 0xf0, - 0xbd, 0xaf, 0xd0, 0xe0, 0xbe, 0xc4, 0xb9, 0xf0, 0xbf, 0x8f, 0xb2, 0xe0, - 0xc0, 0xa4, 0x9b, 0xf0, 0xc1, 0x6f, 0x94, 0xe0, 0xc2, 0x84, 0x7d, 0xf0, - 0xc3, 0x4f, 0x76, 0xe0, 0xc4, 0x64, 0x5f, 0xf0, 0xc5, 0x2f, 0x58, 0xe0, - 0xc6, 0x4d, 0x7c, 0x70, 0xc7, 0x0f, 0x3a, 0xe0, 0xc8, 0x2d, 0x5e, 0x70, - 0xc8, 0xf8, 0x57, 0x60, 0xca, 0x0d, 0x40, 0x70, 0xca, 0xd8, 0x39, 0x60, - 0xcb, 0x88, 0xf0, 0x70, 0xd2, 0x23, 0xf4, 0x70, 0xd2, 0x60, 0xfb, 0xe0, - 0xd3, 0x75, 0xe4, 0xf0, 0xd4, 0x40, 0xdd, 0xe0, 0xd5, 0x55, 0xc6, 0xf0, - 0xd6, 0x20, 0xbf, 0xe0, 0xd7, 0x35, 0xa8, 0xf0, 0xd8, 0x00, 0xa1, 0xe0, - 0xd9, 0x15, 0x8a, 0xf0, 0xd9, 0xe0, 0x83, 0xe0, 0xda, 0xfe, 0xa7, 0x70, - 0xdb, 0xc0, 0x65, 0xe0, 0xdc, 0xde, 0x89, 0x70, 0xdd, 0xa9, 0x82, 0x60, - 0xde, 0xbe, 0x6b, 0x70, 0xdf, 0x89, 0x64, 0x60, 0xe0, 0x9e, 0x4d, 0x70, - 0xe1, 0x69, 0x46, 0x60, 0xe2, 0x7e, 0x2f, 0x70, 0xe3, 0x49, 0x28, 0x60, - 0xe4, 0x5e, 0x11, 0x70, 0xe5, 0x57, 0x2e, 0xe0, 0xe6, 0x47, 0x2d, 0xf0, - 0xe7, 0x37, 0x10, 0xe0, 0xe8, 0x27, 0x0f, 0xf0, 0xe9, 0x16, 0xf2, 0xe0, - 0xea, 0x06, 0xf1, 0xf0, 0xea, 0xf6, 0xd4, 0xe0, 0xeb, 0xe6, 0xd3, 0xf0, - 0xec, 0xd6, 0xb6, 0xe0, 0xed, 0xc6, 0xb5, 0xf0, 0xee, 0xbf, 0xd3, 0x60, - 0xef, 0xaf, 0xd2, 0x70, 0xf0, 0x9f, 0xb5, 0x60, 0xf1, 0x8f, 0xb4, 0x70, - 0xf2, 0x7f, 0x97, 0x60, 0xf3, 0x6f, 0x96, 0x70, 0xf4, 0x5f, 0x79, 0x60, - 0xf5, 0x4f, 0x78, 0x70, 0xf6, 0x3f, 0x5b, 0x60, 0xf7, 0x2f, 0x5a, 0x70, - 0xf8, 0x28, 0x77, 0xe0, 0xf9, 0x0f, 0x3c, 0x70, 0xfa, 0x08, 0x59, 0xe0, - 0xfa, 0xf8, 0x58, 0xf0, 0xfb, 0xe8, 0x3b, 0xe0, 0xfc, 0xd8, 0x3a, 0xf0, - 0xfd, 0xc8, 0x1d, 0xe0, 0xfe, 0xb8, 0x1c, 0xf0, 0xff, 0xa7, 0xff, 0xe0, - 0x00, 0x97, 0xfe, 0xf0, 0x01, 0x87, 0xe1, 0xe0, 0x02, 0x77, 0xe0, 0xf0, - 0x03, 0x70, 0xfe, 0x60, 0x04, 0x60, 0xfd, 0x70, 0x05, 0x50, 0xe0, 0x60, - 0x06, 0x40, 0xdf, 0x70, 0x07, 0x30, 0xc2, 0x60, 0x07, 0x8d, 0x19, 0x70, - 0x09, 0x10, 0xa4, 0x60, 0x09, 0xad, 0x94, 0xf0, 0x0a, 0xf0, 0x86, 0x60, - 0x0b, 0xe0, 0x85, 0x70, 0x0c, 0xd9, 0xa2, 0xe0, 0x0d, 0xc0, 0x67, 0x70, - 0x0e, 0xb9, 0x84, 0xe0, 0x0f, 0xa9, 0x83, 0xf0, 0x10, 0x99, 0x66, 0xe0, - 0x11, 0x89, 0x65, 0xf0, 0x12, 0x79, 0x48, 0xe0, 0x13, 0x69, 0x47, 0xf0, - 0x14, 0x59, 0x2a, 0xe0, 0x15, 0x49, 0x29, 0xf0, 0x16, 0x39, 0x0c, 0xe0, - 0x17, 0x29, 0x0b, 0xf0, 0x18, 0x22, 0x29, 0x60, 0x19, 0x08, 0xed, 0xf0, - 0x1a, 0x02, 0x0b, 0x60, 0x1a, 0xf2, 0x0a, 0x70, 0x1b, 0xe1, 0xed, 0x60, - 0x1c, 0xd1, 0xec, 0x70, 0x1d, 0xc1, 0xcf, 0x60, 0x1e, 0xb1, 0xce, 0x70, - 0x1f, 0xa1, 0xb1, 0x60, 0x20, 0x76, 0x00, 0xf0, 0x21, 0x81, 0x93, 0x60, - 0x22, 0x55, 0xe2, 0xf0, 0x23, 0x6a, 0xaf, 0xe0, 0x24, 0x35, 0xc4, 0xf0, - 0x25, 0x4a, 0x91, 0xe0, 0x26, 0x15, 0xa6, 0xf0, 0x27, 0x2a, 0x73, 0xe0, - 0x27, 0xfe, 0xc3, 0x70, 0x29, 0x0a, 0x55, 0xe0, 0x29, 0xde, 0xa5, 0x70, - 0x2a, 0xea, 0x37, 0xe0, 0x2b, 0xbe, 0x87, 0x70, 0x2c, 0xd3, 0x54, 0x60, - 0x2d, 0x9e, 0x69, 0x70, 0x2e, 0xb3, 0x36, 0x60, 0x2f, 0x7e, 0x4b, 0x70, - 0x30, 0x93, 0x18, 0x60, 0x31, 0x67, 0x67, 0xf0, 0x32, 0x72, 0xfa, 0x60, - 0x33, 0x47, 0x49, 0xf0, 0x34, 0x52, 0xdc, 0x60, 0x35, 0x27, 0x2b, 0xf0, - 0x36, 0x32, 0xbe, 0x60, 0x37, 0x07, 0x0d, 0xf0, 0x38, 0x1b, 0xda, 0xe0, - 0x38, 0xe6, 0xef, 0xf0, 0x39, 0xfb, 0xbc, 0xe0, 0x3a, 0xc6, 0xd1, 0xf0, - 0x3b, 0xdb, 0x9e, 0xe0, 0x3c, 0xaf, 0xee, 0x70, 0x3d, 0xbb, 0x80, 0xe0, - 0x3e, 0x8f, 0xd0, 0x70, 0x3f, 0x9b, 0x62, 0xe0, 0x40, 0x6f, 0xb2, 0x70, - 0x41, 0x84, 0x7f, 0x60, 0x42, 0x4f, 0x94, 0x70, 0x43, 0x64, 0x61, 0x60, - 0x44, 0x2f, 0x76, 0x70, 0x45, 0x44, 0x43, 0x60, 0x45, 0xf3, 0xa8, 0xf0, - 0x47, 0x2d, 0x5f, 0xe0, 0x47, 0xd3, 0x8a, 0xf0, 0x49, 0x0d, 0x41, 0xe0, - 0x49, 0xb3, 0x6c, 0xf0, 0x4a, 0xed, 0x23, 0xe0, 0x4b, 0x9c, 0x89, 0x70, - 0x4c, 0xd6, 0x40, 0x60, 0x4d, 0x7c, 0x6b, 0x70, 0x4e, 0xb6, 0x22, 0x60, - 0x4f, 0x5c, 0x4d, 0x70, 0x50, 0x96, 0x04, 0x60, 0x51, 0x3c, 0x2f, 0x70, - 0x52, 0x75, 0xe6, 0x60, 0x53, 0x1c, 0x11, 0x70, 0x54, 0x55, 0xc8, 0x60, - 0x54, 0xfb, 0xf3, 0x70, 0x56, 0x35, 0xaa, 0x60, 0x56, 0xe5, 0x0f, 0xf0, - 0x58, 0x1e, 0xc6, 0xe0, 0x58, 0xc4, 0xf1, 0xf0, 0x59, 0xfe, 0xa8, 0xe0, - 0x5a, 0xa4, 0xd3, 0xf0, 0x5b, 0xde, 0x8a, 0xe0, 0x5c, 0x84, 0xb5, 0xf0, - 0x5d, 0xbe, 0x6c, 0xe0, 0x5e, 0x64, 0x97, 0xf0, 0x5f, 0x9e, 0x4e, 0xe0, - 0x60, 0x4d, 0xb4, 0x70, 0x61, 0x87, 0x6b, 0x60, 0x62, 0x2d, 0x96, 0x70, - 0x63, 0x67, 0x4d, 0x60, 0x64, 0x0d, 0x78, 0x70, 0x65, 0x47, 0x2f, 0x60, - 0x65, 0xed, 0x5a, 0x70, 0x67, 0x27, 0x11, 0x60, 0x67, 0xcd, 0x3c, 0x70, - 0x69, 0x06, 0xf3, 0x60, 0x69, 0xad, 0x1e, 0x70, 0x6a, 0xe6, 0xd5, 0x60, - 0x6b, 0x96, 0x3a, 0xf0, 0x6c, 0xcf, 0xf1, 0xe0, 0x6d, 0x76, 0x1c, 0xf0, - 0x6e, 0xaf, 0xd3, 0xe0, 0x6f, 0x55, 0xfe, 0xf0, 0x70, 0x8f, 0xb5, 0xe0, - 0x71, 0x35, 0xe0, 0xf0, 0x72, 0x6f, 0x97, 0xe0, 0x73, 0x15, 0xc2, 0xf0, - 0x74, 0x4f, 0x79, 0xe0, 0x74, 0xfe, 0xdf, 0x70, 0x76, 0x38, 0x96, 0x60, - 0x76, 0xde, 0xc1, 0x70, 0x78, 0x18, 0x78, 0x60, 0x78, 0xbe, 0xa3, 0x70, - 0x79, 0xf8, 0x5a, 0x60, 0x7a, 0x9e, 0x85, 0x70, 0x7b, 0xd8, 0x3c, 0x60, - 0x7c, 0x7e, 0x67, 0x70, 0x7d, 0xb8, 0x1e, 0x60, 0x7e, 0x5e, 0x49, 0x70, - 0x7f, 0x98, 0x00, 0x60, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0xff, 0xff, 0xba, 0x9e, 0x00, 0x00, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x04, - 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x08, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x0c, - 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x10, 0x4c, 0x4d, 0x54, 0x00, 0x45, 0x44, - 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, 0x57, 0x54, 0x00, 0x45, 0x50, - 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xed, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x03, 0xf0, 0x90, - 0xff, 0xff, 0xff, 0xff, 0x9e, 0xa6, 0x1e, 0x70, 0xff, 0xff, 0xff, 0xff, - 0x9f, 0xba, 0xeb, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x86, 0x00, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xa1, 0x9a, 0xcd, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xa2, 0x65, 0xe2, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x83, 0xe9, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xa4, 0x6a, 0xae, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xa5, 0x35, 0xa7, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa6, 0x53, 0xca, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xa7, 0x15, 0x89, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xa8, 0x33, 0xac, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xa8, 0xfe, 0xa5, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xaa, 0x13, 0x8e, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xaa, 0xde, 0x87, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xf3, 0x70, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xac, 0xbe, 0x69, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xad, 0xd3, 0x52, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xae, 0x9e, 0x4b, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xaf, 0xb3, 0x34, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xb0, 0x7e, 0x2d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x9c, 0x51, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xb2, 0x67, 0x4a, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xb3, 0x7c, 0x33, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x47, 0x2c, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xb5, 0x5c, 0x15, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xb6, 0x27, 0x0e, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x3b, 0xf7, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xb8, 0x06, 0xf0, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xb9, 0x1b, 0xd9, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xe6, 0xd2, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xbb, 0x04, 0xf5, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xbb, 0xc6, 0xb4, 0x60, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe4, 0xd7, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xbd, 0xaf, 0xd0, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xbe, 0xc4, 0xb9, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x8f, 0xb2, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0xa4, 0x9b, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xc1, 0x6f, 0x94, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x84, 0x7d, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xc3, 0x4f, 0x76, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xc4, 0x64, 0x5f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc5, 0x2f, 0x58, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xc6, 0x4d, 0x7c, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xc7, 0x0f, 0x3a, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x2d, 0x5e, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xc8, 0xf8, 0x57, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xca, 0x0d, 0x40, 0x70, 0xff, 0xff, 0xff, 0xff, 0xca, 0xd8, 0x39, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xcb, 0x88, 0xf0, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xd2, 0x23, 0xf4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x60, 0xfb, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xd3, 0x75, 0xe4, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xd4, 0x40, 0xdd, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x55, 0xc6, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xd6, 0x20, 0xbf, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xd7, 0x35, 0xa8, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x00, 0xa1, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xd9, 0x15, 0x8a, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xd9, 0xe0, 0x83, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfe, 0xa7, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xdb, 0xc0, 0x65, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xdc, 0xde, 0x89, 0x70, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xa9, 0x82, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xde, 0xbe, 0x6b, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xdf, 0x89, 0x64, 0x60, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9e, 0x4d, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xe1, 0x69, 0x46, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xe2, 0x7e, 0x2f, 0x70, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x49, 0x28, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xe4, 0x5e, 0x11, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xe5, 0x57, 0x2e, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x47, 0x2d, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xe7, 0x37, 0x10, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xe8, 0x27, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x16, 0xf2, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xea, 0x06, 0xf1, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xea, 0xf6, 0xd4, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xd3, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xec, 0xd6, 0xb6, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xed, 0xc6, 0xb5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xee, 0xbf, 0xd3, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xef, 0xaf, 0xd2, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xf0, 0x9f, 0xb5, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xb4, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xf2, 0x7f, 0x97, 0x60, 0xff, 0xff, 0xff, 0xff, - 0xf3, 0x6f, 0x96, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5f, 0x79, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xf5, 0x4f, 0x78, 0x70, 0xff, 0xff, 0xff, 0xff, - 0xf6, 0x3f, 0x5b, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x2f, 0x5a, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x28, 0x77, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xf9, 0x0f, 0x3c, 0x70, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x59, 0xe0, - 0xff, 0xff, 0xff, 0xff, 0xfa, 0xf8, 0x58, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xfb, 0xe8, 0x3b, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd8, 0x3a, 0xf0, - 0xff, 0xff, 0xff, 0xff, 0xfd, 0xc8, 0x1d, 0xe0, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0xb8, 0x1c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0xff, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x87, 0xe1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x77, 0xe0, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x70, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x60, 0xfd, 0x70, 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0xe0, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x40, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x30, 0xc2, 0x60, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8d, 0x19, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x09, 0x10, 0xa4, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x09, 0xad, 0x94, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x86, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe0, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0xd9, 0xa2, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xc0, 0x67, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x0e, 0xb9, 0x84, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x0f, 0xa9, 0x83, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x99, 0x66, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x11, 0x89, 0x65, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x12, 0x79, 0x48, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x69, 0x47, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x59, 0x2a, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x15, 0x49, 0x29, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x0c, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x17, 0x29, 0x0b, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x22, 0x29, 0x60, 0x00, 0x00, 0x00, 0x00, 0x19, 0x08, 0xed, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x0b, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x1a, 0xf2, 0x0a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe1, 0xed, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x1c, 0xd1, 0xec, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x1d, 0xc1, 0xcf, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xb1, 0xce, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x1f, 0xa1, 0xb1, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x76, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0x93, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x22, 0x55, 0xe2, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x23, 0x6a, 0xaf, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x24, 0x35, 0xc4, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x25, 0x4a, 0x91, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x15, 0xa6, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x27, 0x2a, 0x73, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x27, 0xfe, 0xc3, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x29, 0x0a, 0x55, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x29, 0xde, 0xa5, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x2a, 0xea, 0x37, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x2b, 0xbe, 0x87, 0x70, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd3, 0x54, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x2d, 0x9e, 0x69, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x2e, 0xb3, 0x36, 0x60, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0x4b, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x30, 0x93, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x31, 0x67, 0x67, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xfa, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x33, 0x47, 0x49, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x34, 0x52, 0xdc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x35, 0x27, 0x2b, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x36, 0x32, 0xbe, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x37, 0x07, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0xda, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x38, 0xe6, 0xef, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x39, 0xfb, 0xbc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xc6, 0xd1, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x3b, 0xdb, 0x9e, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x3c, 0xaf, 0xee, 0x70, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x80, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x3e, 0x8f, 0xd0, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x3f, 0x9b, 0x62, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xb2, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x41, 0x84, 0x7f, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x42, 0x4f, 0x94, 0x70, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x61, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x44, 0x2f, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x45, 0x44, 0x43, 0x60, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf3, 0xa8, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x47, 0x2d, 0x5f, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x47, 0xd3, 0x8a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0d, 0x41, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x49, 0xb3, 0x6c, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x4a, 0xed, 0x23, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x9c, 0x89, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x4c, 0xd6, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x4d, 0x7c, 0x6b, 0x70, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xb6, 0x22, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x4f, 0x5c, 0x4d, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x50, 0x96, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x51, 0x3c, 0x2f, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x52, 0x75, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x53, 0x1c, 0x11, 0x70, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xc8, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x54, 0xfb, 0xf3, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x56, 0x35, 0xaa, 0x60, 0x00, 0x00, 0x00, 0x00, 0x56, 0xe5, 0x0f, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x58, 0x1e, 0xc6, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x58, 0xc4, 0xf1, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x59, 0xfe, 0xa8, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x5a, 0xa4, 0xd3, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x5b, 0xde, 0x8a, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x84, 0xb5, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x5d, 0xbe, 0x6c, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x5e, 0x64, 0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x9e, 0x4e, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x60, 0x4d, 0xb4, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x61, 0x87, 0x6b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2d, 0x96, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x63, 0x67, 0x4d, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x64, 0x0d, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x2f, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x65, 0xed, 0x5a, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x27, 0x11, 0x60, 0x00, 0x00, 0x00, 0x00, 0x67, 0xcd, 0x3c, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x69, 0x06, 0xf3, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x69, 0xad, 0x1e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe6, 0xd5, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x6b, 0x96, 0x3a, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x6c, 0xcf, 0xf1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x1c, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x6e, 0xaf, 0xd3, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x6f, 0x55, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0xb5, 0xe0, - 0x00, 0x00, 0x00, 0x00, 0x71, 0x35, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x72, 0x6f, 0x97, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xc2, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x74, 0x4f, 0x79, 0xe0, 0x00, 0x00, 0x00, 0x00, - 0x74, 0xfe, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0x96, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x76, 0xde, 0xc1, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x78, 0x18, 0x78, 0x60, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbe, 0xa3, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x79, 0xf8, 0x5a, 0x60, 0x00, 0x00, 0x00, 0x00, - 0x7a, 0x9e, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xd8, 0x3c, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7e, 0x67, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x7d, 0xb8, 0x1e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5e, 0x49, 0x70, - 0x00, 0x00, 0x00, 0x00, 0x7f, 0x98, 0x00, 0x60, 0x00, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, - 0x02, 0x01, 0x02, 0x01, 0x02, 0xff, 0xff, 0xba, 0x9e, 0x00, 0x00, 0xff, - 0xff, 0xc7, 0xc0, 0x01, 0x04, 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x08, 0xff, - 0xff, 0xc7, 0xc0, 0x01, 0x0c, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x10, 0x4c, - 0x4d, 0x54, 0x00, 0x45, 0x44, 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, - 0x57, 0x54, 0x00, 0x45, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45, 0x44, - 0x54, 0x2c, 0x4d, 0x33, 0x2e, 0x32, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x31, - 0x2e, 0x31, 0x2e, 0x30, 0x0a -}; -unsigned int America_New_York_len = 3545; -unsigned char Australia_Sydney[] = { - 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0e, 0x80, 0x00, 0x00, 0x00, - 0x9c, 0x4e, 0xa6, 0x9c, 0x9c, 0xbc, 0x20, 0xf0, 0xcb, 0x54, 0xb3, 0x00, - 0xcb, 0xc7, 0x57, 0x70, 0xcc, 0xb7, 0x56, 0x80, 0xcd, 0xa7, 0x39, 0x70, - 0xce, 0xa0, 0x73, 0x00, 0xcf, 0x87, 0x1b, 0x70, 0x03, 0x70, 0x39, 0x80, - 0x04, 0x0d, 0x1c, 0x00, 0x05, 0x50, 0x1b, 0x80, 0x05, 0xf6, 0x38, 0x80, - 0x07, 0x2f, 0xfd, 0x80, 0x07, 0xd6, 0x1a, 0x80, 0x09, 0x0f, 0xdf, 0x80, - 0x09, 0xb5, 0xfc, 0x80, 0x0a, 0xef, 0xc1, 0x80, 0x0b, 0x9f, 0x19, 0x00, - 0x0c, 0xd8, 0xde, 0x00, 0x0d, 0x7e, 0xfb, 0x00, 0x0e, 0xb8, 0xc0, 0x00, - 0x0f, 0x5e, 0xdd, 0x00, 0x10, 0x98, 0xa2, 0x00, 0x11, 0x3e, 0xbf, 0x00, - 0x12, 0x78, 0x84, 0x00, 0x13, 0x1e, 0xa1, 0x00, 0x14, 0x58, 0x66, 0x00, - 0x14, 0xfe, 0x83, 0x00, 0x16, 0x38, 0x48, 0x00, 0x17, 0x0c, 0x89, 0x80, - 0x18, 0x21, 0x64, 0x80, 0x18, 0xc7, 0x81, 0x80, 0x1a, 0x01, 0x46, 0x80, - 0x1a, 0xa7, 0x63, 0x80, 0x1b, 0xe1, 0x28, 0x80, 0x1c, 0x87, 0x45, 0x80, - 0x1d, 0xc1, 0x0a, 0x80, 0x1e, 0x79, 0x9c, 0x80, 0x1f, 0x97, 0xb2, 0x00, - 0x20, 0x59, 0x7e, 0x80, 0x21, 0x80, 0xce, 0x80, 0x22, 0x42, 0x9b, 0x00, - 0x23, 0x69, 0xeb, 0x00, 0x24, 0x22, 0x7d, 0x00, 0x25, 0x49, 0xcd, 0x00, - 0x25, 0xef, 0xea, 0x00, 0x27, 0x29, 0xaf, 0x00, 0x27, 0xcf, 0xcc, 0x00, - 0x29, 0x09, 0x91, 0x00, 0x29, 0xaf, 0xae, 0x00, 0x2a, 0xe9, 0x73, 0x00, - 0x2b, 0x98, 0xca, 0x80, 0x2c, 0xd2, 0x8f, 0x80, 0x2d, 0x78, 0xac, 0x80, - 0x2e, 0xb2, 0x71, 0x80, 0x2f, 0x58, 0x8e, 0x80, 0x30, 0x92, 0x53, 0x80, - 0x31, 0x5d, 0x5a, 0x80, 0x32, 0x72, 0x35, 0x80, 0x33, 0x3d, 0x3c, 0x80, - 0x34, 0x52, 0x17, 0x80, 0x35, 0x1d, 0x1e, 0x80, 0x36, 0x31, 0xf9, 0x80, - 0x36, 0xfd, 0x00, 0x80, 0x38, 0x1b, 0x16, 0x00, 0x38, 0xdc, 0xe2, 0x80, - 0x39, 0xa7, 0xe9, 0x80, 0x3a, 0xbc, 0xc4, 0x80, 0x3b, 0xda, 0xda, 0x00, - 0x3c, 0xa5, 0xe1, 0x00, 0x3d, 0xba, 0xbc, 0x00, 0x3e, 0x85, 0xc3, 0x00, - 0x3f, 0x9a, 0x9e, 0x00, 0x40, 0x65, 0xa5, 0x00, 0x41, 0x83, 0xba, 0x80, - 0x42, 0x45, 0x87, 0x00, 0x43, 0x63, 0x9c, 0x80, 0x44, 0x2e, 0xa3, 0x80, - 0x45, 0x43, 0x7e, 0x80, 0x46, 0x05, 0x4b, 0x00, 0x47, 0x23, 0x60, 0x80, - 0x47, 0xf7, 0xa2, 0x00, 0x48, 0xe7, 0x93, 0x00, 0x49, 0xd7, 0x84, 0x00, - 0x4a, 0xc7, 0x75, 0x00, 0x4b, 0xb7, 0x66, 0x00, 0x4c, 0xa7, 0x57, 0x00, - 0x4d, 0x97, 0x48, 0x00, 0x4e, 0x87, 0x39, 0x00, 0x4f, 0x77, 0x2a, 0x00, - 0x50, 0x70, 0x55, 0x80, 0x51, 0x60, 0x46, 0x80, 0x52, 0x50, 0x37, 0x80, - 0x53, 0x40, 0x28, 0x80, 0x54, 0x30, 0x19, 0x80, 0x55, 0x20, 0x0a, 0x80, - 0x56, 0x0f, 0xfb, 0x80, 0x56, 0xff, 0xec, 0x80, 0x57, 0xef, 0xdd, 0x80, - 0x58, 0xdf, 0xce, 0x80, 0x59, 0xcf, 0xbf, 0x80, 0x5a, 0xbf, 0xb0, 0x80, - 0x5b, 0xb8, 0xdc, 0x00, 0x5c, 0xa8, 0xcd, 0x00, 0x5d, 0x98, 0xbe, 0x00, - 0x5e, 0x88, 0xaf, 0x00, 0x5f, 0x78, 0xa0, 0x00, 0x60, 0x68, 0x91, 0x00, - 0x61, 0x58, 0x82, 0x00, 0x62, 0x48, 0x73, 0x00, 0x63, 0x38, 0x64, 0x00, - 0x64, 0x28, 0x55, 0x00, 0x65, 0x18, 0x46, 0x00, 0x66, 0x11, 0x71, 0x80, - 0x67, 0x01, 0x62, 0x80, 0x67, 0xf1, 0x53, 0x80, 0x68, 0xe1, 0x44, 0x80, - 0x69, 0xd1, 0x35, 0x80, 0x6a, 0xc1, 0x26, 0x80, 0x6b, 0xb1, 0x17, 0x80, - 0x6c, 0xa1, 0x08, 0x80, 0x6d, 0x90, 0xf9, 0x80, 0x6e, 0x80, 0xea, 0x80, - 0x6f, 0x70, 0xdb, 0x80, 0x70, 0x6a, 0x07, 0x00, 0x71, 0x59, 0xf8, 0x00, - 0x72, 0x49, 0xe9, 0x00, 0x73, 0x39, 0xda, 0x00, 0x74, 0x29, 0xcb, 0x00, - 0x75, 0x19, 0xbc, 0x00, 0x76, 0x09, 0xad, 0x00, 0x76, 0xf9, 0x9e, 0x00, - 0x77, 0xe9, 0x8f, 0x00, 0x78, 0xd9, 0x80, 0x00, 0x79, 0xc9, 0x71, 0x00, - 0x7a, 0xb9, 0x62, 0x00, 0x7b, 0xb2, 0x8d, 0x80, 0x7c, 0xa2, 0x7e, 0x80, - 0x7d, 0x92, 0x6f, 0x80, 0x7e, 0x82, 0x60, 0x80, 0x7f, 0x72, 0x51, 0x80, - 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, - 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x00, 0x00, - 0x8d, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xb0, 0x01, 0x04, 0x00, 0x00, - 0x8c, 0xa0, 0x00, 0x09, 0x00, 0x00, 0x9a, 0xb0, 0x01, 0x04, 0x00, 0x00, - 0x8c, 0xa0, 0x00, 0x09, 0x4c, 0x4d, 0x54, 0x00, 0x41, 0x45, 0x44, 0x54, - 0x00, 0x41, 0x45, 0x53, 0x54, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0e, - 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x73, 0x16, 0x7f, 0x3c, 0xff, 0xff, 0xff, 0xff, 0x9c, 0x4e, 0xa6, 0x9c, - 0xff, 0xff, 0xff, 0xff, 0x9c, 0xbc, 0x20, 0xf0, 0xff, 0xff, 0xff, 0xff, - 0xcb, 0x54, 0xb3, 0x00, 0xff, 0xff, 0xff, 0xff, 0xcb, 0xc7, 0x57, 0x70, - 0xff, 0xff, 0xff, 0xff, 0xcc, 0xb7, 0x56, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xcd, 0xa7, 0x39, 0x70, 0xff, 0xff, 0xff, 0xff, 0xce, 0xa0, 0x73, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xcf, 0x87, 0x1b, 0x70, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x70, 0x39, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0d, 0x1c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0x1b, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x05, 0xf6, 0x38, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x2f, 0xfd, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x07, 0xd6, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x0f, 0xdf, 0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xb5, 0xfc, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x0a, 0xef, 0xc1, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x0b, 0x9f, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xd8, 0xde, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0d, 0x7e, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0e, 0xb8, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x5e, 0xdd, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x98, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x3e, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x78, 0x84, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x13, 0x1e, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x14, 0x58, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xfe, 0x83, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x16, 0x38, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x17, 0x0c, 0x89, 0x80, 0x00, 0x00, 0x00, 0x00, 0x18, 0x21, 0x64, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x18, 0xc7, 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x1a, 0x01, 0x46, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xa7, 0x63, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe1, 0x28, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x1c, 0x87, 0x45, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xc1, 0x0a, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x1e, 0x79, 0x9c, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0x97, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x59, 0x7e, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x21, 0x80, 0xce, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x42, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x69, 0xeb, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x24, 0x22, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x25, 0x49, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xef, 0xea, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x27, 0x29, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x27, 0xcf, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x09, 0x91, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x29, 0xaf, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2a, 0xe9, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x98, 0xca, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd2, 0x8f, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x2d, 0x78, 0xac, 0x80, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xb2, 0x71, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x2f, 0x58, 0x8e, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x92, 0x53, 0x80, 0x00, 0x00, 0x00, 0x00, 0x31, 0x5d, 0x5a, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0x35, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x33, 0x3d, 0x3c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x34, 0x52, 0x17, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x35, 0x1d, 0x1e, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x31, 0xf9, 0x80, 0x00, 0x00, 0x00, 0x00, 0x36, 0xfd, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0xdc, 0xe2, 0x80, 0x00, 0x00, 0x00, 0x00, 0x39, 0xa7, 0xe9, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x3a, 0xbc, 0xc4, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x3b, 0xda, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xa5, 0xe1, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3d, 0xba, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3e, 0x85, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x9a, 0x9e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x65, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x41, 0x83, 0xba, 0x80, 0x00, 0x00, 0x00, 0x00, 0x42, 0x45, 0x87, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x43, 0x63, 0x9c, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x2e, 0xa3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x45, 0x43, 0x7e, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x47, 0x23, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x47, 0xf7, 0xa2, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0xe7, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x49, 0xd7, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xc7, 0x75, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4b, 0xb7, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4c, 0xa7, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x97, 0x48, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4e, 0x87, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4f, 0x77, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x70, 0x55, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x51, 0x60, 0x46, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x52, 0x50, 0x37, 0x80, 0x00, 0x00, 0x00, 0x00, 0x53, 0x40, 0x28, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x30, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x55, 0x20, 0x0a, 0x80, 0x00, 0x00, 0x00, 0x00, 0x56, 0x0f, 0xfb, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x56, 0xff, 0xec, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x57, 0xef, 0xdd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x58, 0xdf, 0xce, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x59, 0xcf, 0xbf, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x5a, 0xbf, 0xb0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xb8, 0xdc, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5c, 0xa8, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5d, 0x98, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x88, 0xaf, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5f, 0x78, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x60, 0x68, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x58, 0x82, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x62, 0x48, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x63, 0x38, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x28, 0x55, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x65, 0x18, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x66, 0x11, 0x71, 0x80, 0x00, 0x00, 0x00, 0x00, 0x67, 0x01, 0x62, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x67, 0xf1, 0x53, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x68, 0xe1, 0x44, 0x80, 0x00, 0x00, 0x00, 0x00, 0x69, 0xd1, 0x35, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x6a, 0xc1, 0x26, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x6b, 0xb1, 0x17, 0x80, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xa1, 0x08, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x6d, 0x90, 0xf9, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x6e, 0x80, 0xea, 0x80, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x70, 0xdb, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x70, 0x6a, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x71, 0x59, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x49, 0xe9, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x73, 0x39, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x74, 0x29, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x19, 0xbc, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x76, 0x09, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x76, 0xf9, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0xe9, 0x8f, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x78, 0xd9, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x79, 0xc9, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xb9, 0x62, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7b, 0xb2, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0xa2, 0x7e, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x92, 0x6f, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x7e, 0x82, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x7f, 0x72, 0x51, 0x80, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, - 0x01, 0x02, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, - 0x03, 0x04, 0x03, 0x00, 0x00, 0x8d, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x9a, - 0xb0, 0x01, 0x04, 0x00, 0x00, 0x8c, 0xa0, 0x00, 0x09, 0x00, 0x00, 0x9a, - 0xb0, 0x01, 0x04, 0x00, 0x00, 0x8c, 0xa0, 0x00, 0x09, 0x4c, 0x4d, 0x54, - 0x00, 0x41, 0x45, 0x44, 0x54, 0x00, 0x41, 0x45, 0x53, 0x54, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x41, 0x45, - 0x53, 0x54, 0x2d, 0x31, 0x30, 0x41, 0x45, 0x44, 0x54, 0x2c, 0x4d, 0x31, - 0x30, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x4d, 0x34, 0x2e, 0x31, 0x2e, 0x30, - 0x2f, 0x33, 0x0a -}; -unsigned int Australia_Sydney_len = 2223; +unsigned char America_Los_Angeles[] = { + 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, + 0x9e, 0xa6, 0x48, 0xa0, 0x9f, 0xbb, 0x15, 0x90, 0xa0, 0x86, 0x2a, 0xa0, + 0xa1, 0x9a, 0xf7, 0x90, 0xcb, 0x89, 0x1a, 0xa0, 0xd2, 0x23, 0xf4, 0x70, + 0xd2, 0x61, 0x26, 0x10, 0xd6, 0xfe, 0x74, 0x5c, 0xd8, 0x80, 0xad, 0x90, + 0xda, 0xfe, 0xc3, 0x90, 0xdb, 0xc0, 0x90, 0x10, 0xdc, 0xde, 0xa5, 0x90, + 0xdd, 0xa9, 0xac, 0x90, 0xde, 0xbe, 0x87, 0x90, 0xdf, 0x89, 0x8e, 0x90, + 0xe0, 0x9e, 0x69, 0x90, 0xe1, 0x69, 0x70, 0x90, 0xe2, 0x7e, 0x4b, 0x90, + 0xe3, 0x49, 0x52, 0x90, 0xe4, 0x5e, 0x2d, 0x90, 0xe5, 0x29, 0x34, 0x90, + 0xe6, 0x47, 0x4a, 0x10, 0xe7, 0x12, 0x51, 0x10, 0xe8, 0x27, 0x2c, 0x10, + 0xe8, 0xf2, 0x33, 0x10, 0xea, 0x07, 0x0e, 0x10, 0xea, 0xd2, 0x15, 0x10, + 0xeb, 0xe6, 0xf0, 0x10, 0xec, 0xb1, 0xf7, 0x10, 0xed, 0xc6, 0xd2, 0x10, + 0xee, 0x91, 0xd9, 0x10, 0xef, 0xaf, 0xee, 0x90, 0xf0, 0x71, 0xbb, 0x10, + 0xf1, 0x8f, 0xd0, 0x90, 0xf2, 0x7f, 0xc1, 0x90, 0xf3, 0x6f, 0xb2, 0x90, + 0xf4, 0x5f, 0xa3, 0x90, 0xf5, 0x4f, 0x94, 0x90, 0xf6, 0x3f, 0x85, 0x90, + 0xf7, 0x2f, 0x76, 0x90, 0xf8, 0x28, 0xa2, 0x10, 0xf9, 0x0f, 0x58, 0x90, + 0xfa, 0x08, 0x84, 0x10, 0xfa, 0xf8, 0x83, 0x20, 0xfb, 0xe8, 0x66, 0x10, + 0xfc, 0xd8, 0x65, 0x20, 0xfd, 0xc8, 0x48, 0x10, 0xfe, 0xb8, 0x47, 0x20, + 0xff, 0xa8, 0x2a, 0x10, 0x00, 0x98, 0x29, 0x20, 0x01, 0x88, 0x0c, 0x10, + 0x02, 0x78, 0x0b, 0x20, 0x03, 0x71, 0x28, 0x90, 0x04, 0x61, 0x27, 0xa0, + 0x05, 0x51, 0x0a, 0x90, 0x06, 0x41, 0x09, 0xa0, 0x07, 0x30, 0xec, 0x90, + 0x07, 0x8d, 0x43, 0xa0, 0x09, 0x10, 0xce, 0x90, 0x09, 0xad, 0xbf, 0x20, + 0x0a, 0xf0, 0xb0, 0x90, 0x0b, 0xe0, 0xaf, 0xa0, 0x0c, 0xd9, 0xcd, 0x10, + 0x0d, 0xc0, 0x91, 0xa0, 0x0e, 0xb9, 0xaf, 0x10, 0x0f, 0xa9, 0xae, 0x20, + 0x10, 0x99, 0x91, 0x10, 0x11, 0x89, 0x90, 0x20, 0x12, 0x79, 0x73, 0x10, + 0x13, 0x69, 0x72, 0x20, 0x14, 0x59, 0x55, 0x10, 0x15, 0x49, 0x54, 0x20, + 0x16, 0x39, 0x37, 0x10, 0x17, 0x29, 0x36, 0x20, 0x18, 0x22, 0x53, 0x90, + 0x19, 0x09, 0x18, 0x20, 0x1a, 0x02, 0x35, 0x90, 0x1a, 0xf2, 0x34, 0xa0, + 0x1b, 0xe2, 0x17, 0x90, 0x1c, 0xd2, 0x16, 0xa0, 0x1d, 0xc1, 0xf9, 0x90, + 0x1e, 0xb1, 0xf8, 0xa0, 0x1f, 0xa1, 0xdb, 0x90, 0x20, 0x76, 0x2b, 0x20, + 0x21, 0x81, 0xbd, 0x90, 0x22, 0x56, 0x0d, 0x20, 0x23, 0x6a, 0xda, 0x10, + 0x24, 0x35, 0xef, 0x20, 0x25, 0x4a, 0xbc, 0x10, 0x26, 0x15, 0xd1, 0x20, + 0x27, 0x2a, 0x9e, 0x10, 0x27, 0xfe, 0xed, 0xa0, 0x29, 0x0a, 0x80, 0x10, + 0x29, 0xde, 0xcf, 0xa0, 0x2a, 0xea, 0x62, 0x10, 0x2b, 0xbe, 0xb1, 0xa0, + 0x2c, 0xd3, 0x7e, 0x90, 0x2d, 0x9e, 0x93, 0xa0, 0x2e, 0xb3, 0x60, 0x90, + 0x2f, 0x7e, 0x75, 0xa0, 0x30, 0x93, 0x42, 0x90, 0x31, 0x67, 0x92, 0x20, + 0x32, 0x73, 0x24, 0x90, 0x33, 0x47, 0x74, 0x20, 0x34, 0x53, 0x06, 0x90, + 0x35, 0x27, 0x56, 0x20, 0x36, 0x32, 0xe8, 0x90, 0x37, 0x07, 0x38, 0x20, + 0x38, 0x1c, 0x05, 0x10, 0x38, 0xe7, 0x1a, 0x20, 0x39, 0xfb, 0xe7, 0x10, + 0x3a, 0xc6, 0xfc, 0x20, 0x3b, 0xdb, 0xc9, 0x10, 0x3c, 0xb0, 0x18, 0xa0, + 0x3d, 0xbb, 0xab, 0x10, 0x3e, 0x8f, 0xfa, 0xa0, 0x3f, 0x9b, 0x8d, 0x10, + 0x40, 0x6f, 0xdc, 0xa0, 0x41, 0x84, 0xa9, 0x90, 0x42, 0x4f, 0xbe, 0xa0, + 0x43, 0x64, 0x8b, 0x90, 0x44, 0x2f, 0xa0, 0xa0, 0x45, 0x44, 0x6d, 0x90, + 0x45, 0xf3, 0xd3, 0x20, 0x47, 0x2d, 0x8a, 0x10, 0x47, 0xd3, 0xb5, 0x20, + 0x49, 0x0d, 0x6c, 0x10, 0x49, 0xb3, 0x97, 0x20, 0x4a, 0xed, 0x4e, 0x10, + 0x4b, 0x9c, 0xb3, 0xa0, 0x4c, 0xd6, 0x6a, 0x90, 0x4d, 0x7c, 0x95, 0xa0, + 0x4e, 0xb6, 0x4c, 0x90, 0x4f, 0x5c, 0x77, 0xa0, 0x50, 0x96, 0x2e, 0x90, + 0x51, 0x3c, 0x59, 0xa0, 0x52, 0x76, 0x10, 0x90, 0x53, 0x1c, 0x3b, 0xa0, + 0x54, 0x55, 0xf2, 0x90, 0x54, 0xfc, 0x1d, 0xa0, 0x56, 0x35, 0xd4, 0x90, + 0x56, 0xe5, 0x3a, 0x20, 0x58, 0x1e, 0xf1, 0x10, 0x58, 0xc5, 0x1c, 0x20, + 0x59, 0xfe, 0xd3, 0x10, 0x5a, 0xa4, 0xfe, 0x20, 0x5b, 0xde, 0xb5, 0x10, + 0x5c, 0x84, 0xe0, 0x20, 0x5d, 0xbe, 0x97, 0x10, 0x5e, 0x64, 0xc2, 0x20, + 0x5f, 0x9e, 0x79, 0x10, 0x60, 0x4d, 0xde, 0xa0, 0x61, 0x87, 0x95, 0x90, + 0x62, 0x2d, 0xc0, 0xa0, 0x63, 0x67, 0x77, 0x90, 0x64, 0x0d, 0xa2, 0xa0, + 0x65, 0x47, 0x59, 0x90, 0x65, 0xed, 0x84, 0xa0, 0x67, 0x27, 0x3b, 0x90, + 0x67, 0xcd, 0x66, 0xa0, 0x69, 0x07, 0x1d, 0x90, 0x69, 0xad, 0x48, 0xa0, + 0x6a, 0xe6, 0xff, 0x90, 0x6b, 0x96, 0x65, 0x20, 0x6c, 0xd0, 0x1c, 0x10, + 0x6d, 0x76, 0x47, 0x20, 0x6e, 0xaf, 0xfe, 0x10, 0x6f, 0x56, 0x29, 0x20, + 0x70, 0x8f, 0xe0, 0x10, 0x71, 0x36, 0x0b, 0x20, 0x72, 0x6f, 0xc2, 0x10, + 0x73, 0x15, 0xed, 0x20, 0x74, 0x4f, 0xa4, 0x10, 0x74, 0xff, 0x09, 0xa0, + 0x76, 0x38, 0xc0, 0x90, 0x76, 0xde, 0xeb, 0xa0, 0x78, 0x18, 0xa2, 0x90, + 0x78, 0xbe, 0xcd, 0xa0, 0x79, 0xf8, 0x84, 0x90, 0x7a, 0x9e, 0xaf, 0xa0, + 0x7b, 0xd8, 0x66, 0x90, 0x7c, 0x7e, 0x91, 0xa0, 0x7d, 0xb8, 0x48, 0x90, + 0x7e, 0x5e, 0x73, 0xa0, 0x7f, 0x98, 0x2a, 0x90, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0xff, 0xff, 0x91, 0x26, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x90, + 0x01, 0x04, 0xff, 0xff, 0x8f, 0x80, 0x00, 0x08, 0xff, 0xff, 0x9d, 0x90, + 0x01, 0x0c, 0xff, 0xff, 0x9d, 0x90, 0x01, 0x10, 0x4c, 0x4d, 0x54, 0x00, + 0x50, 0x44, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x57, 0x54, 0x00, + 0x50, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xbb, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x04, + 0x1a, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xa6, 0x48, 0xa0, 0xff, 0xff, + 0xff, 0xff, 0x9f, 0xbb, 0x15, 0x90, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x86, + 0x2a, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xa1, 0x9a, 0xf7, 0x90, 0xff, 0xff, + 0xff, 0xff, 0xcb, 0x89, 0x1a, 0xa0, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x23, + 0xf4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x61, 0x26, 0x10, 0xff, 0xff, + 0xff, 0xff, 0xd6, 0xfe, 0x74, 0x5c, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x80, + 0xad, 0x90, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfe, 0xc3, 0x90, 0xff, 0xff, + 0xff, 0xff, 0xdb, 0xc0, 0x90, 0x10, 0xff, 0xff, 0xff, 0xff, 0xdc, 0xde, + 0xa5, 0x90, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xa9, 0xac, 0x90, 0xff, 0xff, + 0xff, 0xff, 0xde, 0xbe, 0x87, 0x90, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x89, + 0x8e, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9e, 0x69, 0x90, 0xff, 0xff, + 0xff, 0xff, 0xe1, 0x69, 0x70, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe2, 0x7e, + 0x4b, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x49, 0x52, 0x90, 0xff, 0xff, + 0xff, 0xff, 0xe4, 0x5e, 0x2d, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe5, 0x29, + 0x34, 0x90, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x47, 0x4a, 0x10, 0xff, 0xff, + 0xff, 0xff, 0xe7, 0x12, 0x51, 0x10, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x27, + 0x2c, 0x10, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xf2, 0x33, 0x10, 0xff, 0xff, + 0xff, 0xff, 0xea, 0x07, 0x0e, 0x10, 0xff, 0xff, 0xff, 0xff, 0xea, 0xd2, + 0x15, 0x10, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xf0, 0x10, 0xff, 0xff, + 0xff, 0xff, 0xec, 0xb1, 0xf7, 0x10, 0xff, 0xff, 0xff, 0xff, 0xed, 0xc6, + 0xd2, 0x10, 0xff, 0xff, 0xff, 0xff, 0xee, 0x91, 0xd9, 0x10, 0xff, 0xff, + 0xff, 0xff, 0xef, 0xaf, 0xee, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x71, + 0xbb, 0x10, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xd0, 0x90, 0xff, 0xff, + 0xff, 0xff, 0xf2, 0x7f, 0xc1, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x6f, + 0xb2, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5f, 0xa3, 0x90, 0xff, 0xff, + 0xff, 0xff, 0xf5, 0x4f, 0x94, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x3f, + 0x85, 0x90, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x2f, 0x76, 0x90, 0xff, 0xff, + 0xff, 0xff, 0xf8, 0x28, 0xa2, 0x10, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x0f, + 0x58, 0x90, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x84, 0x10, 0xff, 0xff, + 0xff, 0xff, 0xfa, 0xf8, 0x83, 0x20, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xe8, + 0x66, 0x10, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd8, 0x65, 0x20, 0xff, 0xff, + 0xff, 0xff, 0xfd, 0xc8, 0x48, 0x10, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xb8, + 0x47, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa8, 0x2a, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x98, 0x29, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x88, + 0x0c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x78, 0x0b, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x71, 0x28, 0x90, 0x00, 0x00, 0x00, 0x00, 0x04, 0x61, + 0x27, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x05, 0x51, 0x0a, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x41, 0x09, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x30, + 0xec, 0x90, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8d, 0x43, 0xa0, 0x00, 0x00, + 0x00, 0x00, 0x09, 0x10, 0xce, 0x90, 0x00, 0x00, 0x00, 0x00, 0x09, 0xad, + 0xbf, 0x20, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0xb0, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x0b, 0xe0, 0xaf, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xd9, + 0xcd, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xc0, 0x91, 0xa0, 0x00, 0x00, + 0x00, 0x00, 0x0e, 0xb9, 0xaf, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xa9, + 0xae, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x99, 0x91, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x11, 0x89, 0x90, 0x20, 0x00, 0x00, 0x00, 0x00, 0x12, 0x79, + 0x73, 0x10, 0x00, 0x00, 0x00, 0x00, 0x13, 0x69, 0x72, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x14, 0x59, 0x55, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15, 0x49, + 0x54, 0x20, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x37, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x17, 0x29, 0x36, 0x20, 0x00, 0x00, 0x00, 0x00, 0x18, 0x22, + 0x53, 0x90, 0x00, 0x00, 0x00, 0x00, 0x19, 0x09, 0x18, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x1a, 0x02, 0x35, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xf2, + 0x34, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe2, 0x17, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0xd2, 0x16, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xc1, + 0xf9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xb1, 0xf8, 0xa0, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0xa1, 0xdb, 0x90, 0x00, 0x00, 0x00, 0x00, 0x20, 0x76, + 0x2b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0xbd, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x22, 0x56, 0x0d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x23, 0x6a, + 0xda, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x35, 0xef, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x25, 0x4a, 0xbc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x26, 0x15, + 0xd1, 0x20, 0x00, 0x00, 0x00, 0x00, 0x27, 0x2a, 0x9e, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x27, 0xfe, 0xed, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x29, 0x0a, + 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x29, 0xde, 0xcf, 0xa0, 0x00, 0x00, + 0x00, 0x00, 0x2a, 0xea, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00, 0x2b, 0xbe, + 0xb1, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd3, 0x7e, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x2d, 0x9e, 0x93, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xb3, + 0x60, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0x75, 0xa0, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x93, 0x42, 0x90, 0x00, 0x00, 0x00, 0x00, 0x31, 0x67, + 0x92, 0x20, 0x00, 0x00, 0x00, 0x00, 0x32, 0x73, 0x24, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x33, 0x47, 0x74, 0x20, 0x00, 0x00, 0x00, 0x00, 0x34, 0x53, + 0x06, 0x90, 0x00, 0x00, 0x00, 0x00, 0x35, 0x27, 0x56, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x36, 0x32, 0xe8, 0x90, 0x00, 0x00, 0x00, 0x00, 0x37, 0x07, + 0x38, 0x20, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1c, 0x05, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x38, 0xe7, 0x1a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x39, 0xfb, + 0xe7, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xc6, 0xfc, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x3b, 0xdb, 0xc9, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xb0, + 0x18, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0xab, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x8f, 0xfa, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x9b, + 0x8d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xdc, 0xa0, 0x00, 0x00, + 0x00, 0x00, 0x41, 0x84, 0xa9, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0x4f, + 0xbe, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x8b, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x44, 0x2f, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x45, 0x44, + 0x6d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf3, 0xd3, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x47, 0x2d, 0x8a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x47, 0xd3, + 0xb5, 0x20, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0d, 0x6c, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x49, 0xb3, 0x97, 0x20, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xed, + 0x4e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x9c, 0xb3, 0xa0, 0x00, 0x00, + 0x00, 0x00, 0x4c, 0xd6, 0x6a, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x7c, + 0x95, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xb6, 0x4c, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x4f, 0x5c, 0x77, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x50, 0x96, + 0x2e, 0x90, 0x00, 0x00, 0x00, 0x00, 0x51, 0x3c, 0x59, 0xa0, 0x00, 0x00, + 0x00, 0x00, 0x52, 0x76, 0x10, 0x90, 0x00, 0x00, 0x00, 0x00, 0x53, 0x1c, + 0x3b, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xf2, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x54, 0xfc, 0x1d, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x56, 0x35, + 0xd4, 0x90, 0x00, 0x00, 0x00, 0x00, 0x56, 0xe5, 0x3a, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x58, 0x1e, 0xf1, 0x10, 0x00, 0x00, 0x00, 0x00, 0x58, 0xc5, + 0x1c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x59, 0xfe, 0xd3, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x5a, 0xa4, 0xfe, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xde, + 0xb5, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x84, 0xe0, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x5d, 0xbe, 0x97, 0x10, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x64, + 0xc2, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x9e, 0x79, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x4d, 0xde, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x61, 0x87, + 0x95, 0x90, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2d, 0xc0, 0xa0, 0x00, 0x00, + 0x00, 0x00, 0x63, 0x67, 0x77, 0x90, 0x00, 0x00, 0x00, 0x00, 0x64, 0x0d, + 0xa2, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x59, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x65, 0xed, 0x84, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x67, 0x27, + 0x3b, 0x90, 0x00, 0x00, 0x00, 0x00, 0x67, 0xcd, 0x66, 0xa0, 0x00, 0x00, + 0x00, 0x00, 0x69, 0x07, 0x1d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x69, 0xad, + 0x48, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe6, 0xff, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x6b, 0x96, 0x65, 0x20, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xd0, + 0x1c, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x47, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x6e, 0xaf, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x56, + 0x29, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0xe0, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x71, 0x36, 0x0b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6f, + 0xc2, 0x10, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xed, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x74, 0x4f, 0xa4, 0x10, 0x00, 0x00, 0x00, 0x00, 0x74, 0xff, + 0x09, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0xc0, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xde, 0xeb, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x78, 0x18, + 0xa2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbe, 0xcd, 0xa0, 0x00, 0x00, + 0x00, 0x00, 0x79, 0xf8, 0x84, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x9e, + 0xaf, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xd8, 0x66, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x7c, 0x7e, 0x91, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xb8, + 0x48, 0x90, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5e, 0x73, 0xa0, 0x00, 0x00, + 0x00, 0x00, 0x7f, 0x98, 0x2a, 0x90, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0xff, 0xff, 0x91, 0x26, 0x00, 0x00, 0xff, 0xff, 0x9d, 0x90, 0x01, + 0x04, 0xff, 0xff, 0x8f, 0x80, 0x00, 0x08, 0xff, 0xff, 0x9d, 0x90, 0x01, + 0x0c, 0xff, 0xff, 0x9d, 0x90, 0x01, 0x10, 0x4c, 0x4d, 0x54, 0x00, 0x50, + 0x44, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x57, 0x54, 0x00, 0x50, + 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x0a, 0x50, 0x53, 0x54, 0x38, 0x50, 0x44, 0x54, 0x2c, 0x4d, 0x33, + 0x2e, 0x32, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x31, 0x2e, 0x31, 0x2e, 0x30, + 0x0a +}; +unsigned int America_Los_Angeles_len = 2845; +unsigned char America_New_York[] = { + 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, + 0x9e, 0xa6, 0x1e, 0x70, 0x9f, 0xba, 0xeb, 0x60, 0xa0, 0x86, 0x00, 0x70, + 0xa1, 0x9a, 0xcd, 0x60, 0xa2, 0x65, 0xe2, 0x70, 0xa3, 0x83, 0xe9, 0xe0, + 0xa4, 0x6a, 0xae, 0x70, 0xa5, 0x35, 0xa7, 0x60, 0xa6, 0x53, 0xca, 0xf0, + 0xa7, 0x15, 0x89, 0x60, 0xa8, 0x33, 0xac, 0xf0, 0xa8, 0xfe, 0xa5, 0xe0, + 0xaa, 0x13, 0x8e, 0xf0, 0xaa, 0xde, 0x87, 0xe0, 0xab, 0xf3, 0x70, 0xf0, + 0xac, 0xbe, 0x69, 0xe0, 0xad, 0xd3, 0x52, 0xf0, 0xae, 0x9e, 0x4b, 0xe0, + 0xaf, 0xb3, 0x34, 0xf0, 0xb0, 0x7e, 0x2d, 0xe0, 0xb1, 0x9c, 0x51, 0x70, + 0xb2, 0x67, 0x4a, 0x60, 0xb3, 0x7c, 0x33, 0x70, 0xb4, 0x47, 0x2c, 0x60, + 0xb5, 0x5c, 0x15, 0x70, 0xb6, 0x27, 0x0e, 0x60, 0xb7, 0x3b, 0xf7, 0x70, + 0xb8, 0x06, 0xf0, 0x60, 0xb9, 0x1b, 0xd9, 0x70, 0xb9, 0xe6, 0xd2, 0x60, + 0xbb, 0x04, 0xf5, 0xf0, 0xbb, 0xc6, 0xb4, 0x60, 0xbc, 0xe4, 0xd7, 0xf0, + 0xbd, 0xaf, 0xd0, 0xe0, 0xbe, 0xc4, 0xb9, 0xf0, 0xbf, 0x8f, 0xb2, 0xe0, + 0xc0, 0xa4, 0x9b, 0xf0, 0xc1, 0x6f, 0x94, 0xe0, 0xc2, 0x84, 0x7d, 0xf0, + 0xc3, 0x4f, 0x76, 0xe0, 0xc4, 0x64, 0x5f, 0xf0, 0xc5, 0x2f, 0x58, 0xe0, + 0xc6, 0x4d, 0x7c, 0x70, 0xc7, 0x0f, 0x3a, 0xe0, 0xc8, 0x2d, 0x5e, 0x70, + 0xc8, 0xf8, 0x57, 0x60, 0xca, 0x0d, 0x40, 0x70, 0xca, 0xd8, 0x39, 0x60, + 0xcb, 0x88, 0xf0, 0x70, 0xd2, 0x23, 0xf4, 0x70, 0xd2, 0x60, 0xfb, 0xe0, + 0xd3, 0x75, 0xe4, 0xf0, 0xd4, 0x40, 0xdd, 0xe0, 0xd5, 0x55, 0xc6, 0xf0, + 0xd6, 0x20, 0xbf, 0xe0, 0xd7, 0x35, 0xa8, 0xf0, 0xd8, 0x00, 0xa1, 0xe0, + 0xd9, 0x15, 0x8a, 0xf0, 0xd9, 0xe0, 0x83, 0xe0, 0xda, 0xfe, 0xa7, 0x70, + 0xdb, 0xc0, 0x65, 0xe0, 0xdc, 0xde, 0x89, 0x70, 0xdd, 0xa9, 0x82, 0x60, + 0xde, 0xbe, 0x6b, 0x70, 0xdf, 0x89, 0x64, 0x60, 0xe0, 0x9e, 0x4d, 0x70, + 0xe1, 0x69, 0x46, 0x60, 0xe2, 0x7e, 0x2f, 0x70, 0xe3, 0x49, 0x28, 0x60, + 0xe4, 0x5e, 0x11, 0x70, 0xe5, 0x57, 0x2e, 0xe0, 0xe6, 0x47, 0x2d, 0xf0, + 0xe7, 0x37, 0x10, 0xe0, 0xe8, 0x27, 0x0f, 0xf0, 0xe9, 0x16, 0xf2, 0xe0, + 0xea, 0x06, 0xf1, 0xf0, 0xea, 0xf6, 0xd4, 0xe0, 0xeb, 0xe6, 0xd3, 0xf0, + 0xec, 0xd6, 0xb6, 0xe0, 0xed, 0xc6, 0xb5, 0xf0, 0xee, 0xbf, 0xd3, 0x60, + 0xef, 0xaf, 0xd2, 0x70, 0xf0, 0x9f, 0xb5, 0x60, 0xf1, 0x8f, 0xb4, 0x70, + 0xf2, 0x7f, 0x97, 0x60, 0xf3, 0x6f, 0x96, 0x70, 0xf4, 0x5f, 0x79, 0x60, + 0xf5, 0x4f, 0x78, 0x70, 0xf6, 0x3f, 0x5b, 0x60, 0xf7, 0x2f, 0x5a, 0x70, + 0xf8, 0x28, 0x77, 0xe0, 0xf9, 0x0f, 0x3c, 0x70, 0xfa, 0x08, 0x59, 0xe0, + 0xfa, 0xf8, 0x58, 0xf0, 0xfb, 0xe8, 0x3b, 0xe0, 0xfc, 0xd8, 0x3a, 0xf0, + 0xfd, 0xc8, 0x1d, 0xe0, 0xfe, 0xb8, 0x1c, 0xf0, 0xff, 0xa7, 0xff, 0xe0, + 0x00, 0x97, 0xfe, 0xf0, 0x01, 0x87, 0xe1, 0xe0, 0x02, 0x77, 0xe0, 0xf0, + 0x03, 0x70, 0xfe, 0x60, 0x04, 0x60, 0xfd, 0x70, 0x05, 0x50, 0xe0, 0x60, + 0x06, 0x40, 0xdf, 0x70, 0x07, 0x30, 0xc2, 0x60, 0x07, 0x8d, 0x19, 0x70, + 0x09, 0x10, 0xa4, 0x60, 0x09, 0xad, 0x94, 0xf0, 0x0a, 0xf0, 0x86, 0x60, + 0x0b, 0xe0, 0x85, 0x70, 0x0c, 0xd9, 0xa2, 0xe0, 0x0d, 0xc0, 0x67, 0x70, + 0x0e, 0xb9, 0x84, 0xe0, 0x0f, 0xa9, 0x83, 0xf0, 0x10, 0x99, 0x66, 0xe0, + 0x11, 0x89, 0x65, 0xf0, 0x12, 0x79, 0x48, 0xe0, 0x13, 0x69, 0x47, 0xf0, + 0x14, 0x59, 0x2a, 0xe0, 0x15, 0x49, 0x29, 0xf0, 0x16, 0x39, 0x0c, 0xe0, + 0x17, 0x29, 0x0b, 0xf0, 0x18, 0x22, 0x29, 0x60, 0x19, 0x08, 0xed, 0xf0, + 0x1a, 0x02, 0x0b, 0x60, 0x1a, 0xf2, 0x0a, 0x70, 0x1b, 0xe1, 0xed, 0x60, + 0x1c, 0xd1, 0xec, 0x70, 0x1d, 0xc1, 0xcf, 0x60, 0x1e, 0xb1, 0xce, 0x70, + 0x1f, 0xa1, 0xb1, 0x60, 0x20, 0x76, 0x00, 0xf0, 0x21, 0x81, 0x93, 0x60, + 0x22, 0x55, 0xe2, 0xf0, 0x23, 0x6a, 0xaf, 0xe0, 0x24, 0x35, 0xc4, 0xf0, + 0x25, 0x4a, 0x91, 0xe0, 0x26, 0x15, 0xa6, 0xf0, 0x27, 0x2a, 0x73, 0xe0, + 0x27, 0xfe, 0xc3, 0x70, 0x29, 0x0a, 0x55, 0xe0, 0x29, 0xde, 0xa5, 0x70, + 0x2a, 0xea, 0x37, 0xe0, 0x2b, 0xbe, 0x87, 0x70, 0x2c, 0xd3, 0x54, 0x60, + 0x2d, 0x9e, 0x69, 0x70, 0x2e, 0xb3, 0x36, 0x60, 0x2f, 0x7e, 0x4b, 0x70, + 0x30, 0x93, 0x18, 0x60, 0x31, 0x67, 0x67, 0xf0, 0x32, 0x72, 0xfa, 0x60, + 0x33, 0x47, 0x49, 0xf0, 0x34, 0x52, 0xdc, 0x60, 0x35, 0x27, 0x2b, 0xf0, + 0x36, 0x32, 0xbe, 0x60, 0x37, 0x07, 0x0d, 0xf0, 0x38, 0x1b, 0xda, 0xe0, + 0x38, 0xe6, 0xef, 0xf0, 0x39, 0xfb, 0xbc, 0xe0, 0x3a, 0xc6, 0xd1, 0xf0, + 0x3b, 0xdb, 0x9e, 0xe0, 0x3c, 0xaf, 0xee, 0x70, 0x3d, 0xbb, 0x80, 0xe0, + 0x3e, 0x8f, 0xd0, 0x70, 0x3f, 0x9b, 0x62, 0xe0, 0x40, 0x6f, 0xb2, 0x70, + 0x41, 0x84, 0x7f, 0x60, 0x42, 0x4f, 0x94, 0x70, 0x43, 0x64, 0x61, 0x60, + 0x44, 0x2f, 0x76, 0x70, 0x45, 0x44, 0x43, 0x60, 0x45, 0xf3, 0xa8, 0xf0, + 0x47, 0x2d, 0x5f, 0xe0, 0x47, 0xd3, 0x8a, 0xf0, 0x49, 0x0d, 0x41, 0xe0, + 0x49, 0xb3, 0x6c, 0xf0, 0x4a, 0xed, 0x23, 0xe0, 0x4b, 0x9c, 0x89, 0x70, + 0x4c, 0xd6, 0x40, 0x60, 0x4d, 0x7c, 0x6b, 0x70, 0x4e, 0xb6, 0x22, 0x60, + 0x4f, 0x5c, 0x4d, 0x70, 0x50, 0x96, 0x04, 0x60, 0x51, 0x3c, 0x2f, 0x70, + 0x52, 0x75, 0xe6, 0x60, 0x53, 0x1c, 0x11, 0x70, 0x54, 0x55, 0xc8, 0x60, + 0x54, 0xfb, 0xf3, 0x70, 0x56, 0x35, 0xaa, 0x60, 0x56, 0xe5, 0x0f, 0xf0, + 0x58, 0x1e, 0xc6, 0xe0, 0x58, 0xc4, 0xf1, 0xf0, 0x59, 0xfe, 0xa8, 0xe0, + 0x5a, 0xa4, 0xd3, 0xf0, 0x5b, 0xde, 0x8a, 0xe0, 0x5c, 0x84, 0xb5, 0xf0, + 0x5d, 0xbe, 0x6c, 0xe0, 0x5e, 0x64, 0x97, 0xf0, 0x5f, 0x9e, 0x4e, 0xe0, + 0x60, 0x4d, 0xb4, 0x70, 0x61, 0x87, 0x6b, 0x60, 0x62, 0x2d, 0x96, 0x70, + 0x63, 0x67, 0x4d, 0x60, 0x64, 0x0d, 0x78, 0x70, 0x65, 0x47, 0x2f, 0x60, + 0x65, 0xed, 0x5a, 0x70, 0x67, 0x27, 0x11, 0x60, 0x67, 0xcd, 0x3c, 0x70, + 0x69, 0x06, 0xf3, 0x60, 0x69, 0xad, 0x1e, 0x70, 0x6a, 0xe6, 0xd5, 0x60, + 0x6b, 0x96, 0x3a, 0xf0, 0x6c, 0xcf, 0xf1, 0xe0, 0x6d, 0x76, 0x1c, 0xf0, + 0x6e, 0xaf, 0xd3, 0xe0, 0x6f, 0x55, 0xfe, 0xf0, 0x70, 0x8f, 0xb5, 0xe0, + 0x71, 0x35, 0xe0, 0xf0, 0x72, 0x6f, 0x97, 0xe0, 0x73, 0x15, 0xc2, 0xf0, + 0x74, 0x4f, 0x79, 0xe0, 0x74, 0xfe, 0xdf, 0x70, 0x76, 0x38, 0x96, 0x60, + 0x76, 0xde, 0xc1, 0x70, 0x78, 0x18, 0x78, 0x60, 0x78, 0xbe, 0xa3, 0x70, + 0x79, 0xf8, 0x5a, 0x60, 0x7a, 0x9e, 0x85, 0x70, 0x7b, 0xd8, 0x3c, 0x60, + 0x7c, 0x7e, 0x67, 0x70, 0x7d, 0xb8, 0x1e, 0x60, 0x7e, 0x5e, 0x49, 0x70, + 0x7f, 0x98, 0x00, 0x60, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0xff, 0xff, 0xba, 0x9e, 0x00, 0x00, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x04, + 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x08, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x0c, + 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x10, 0x4c, 0x4d, 0x54, 0x00, 0x45, 0x44, + 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, 0x57, 0x54, 0x00, 0x45, 0x50, + 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xed, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x03, 0xf0, 0x90, + 0xff, 0xff, 0xff, 0xff, 0x9e, 0xa6, 0x1e, 0x70, 0xff, 0xff, 0xff, 0xff, + 0x9f, 0xba, 0xeb, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x86, 0x00, 0x70, + 0xff, 0xff, 0xff, 0xff, 0xa1, 0x9a, 0xcd, 0x60, 0xff, 0xff, 0xff, 0xff, + 0xa2, 0x65, 0xe2, 0x70, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x83, 0xe9, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xa4, 0x6a, 0xae, 0x70, 0xff, 0xff, 0xff, 0xff, + 0xa5, 0x35, 0xa7, 0x60, 0xff, 0xff, 0xff, 0xff, 0xa6, 0x53, 0xca, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xa7, 0x15, 0x89, 0x60, 0xff, 0xff, 0xff, 0xff, + 0xa8, 0x33, 0xac, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xa8, 0xfe, 0xa5, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xaa, 0x13, 0x8e, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xaa, 0xde, 0x87, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xab, 0xf3, 0x70, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xac, 0xbe, 0x69, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xad, 0xd3, 0x52, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xae, 0x9e, 0x4b, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xaf, 0xb3, 0x34, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xb0, 0x7e, 0x2d, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xb1, 0x9c, 0x51, 0x70, + 0xff, 0xff, 0xff, 0xff, 0xb2, 0x67, 0x4a, 0x60, 0xff, 0xff, 0xff, 0xff, + 0xb3, 0x7c, 0x33, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb4, 0x47, 0x2c, 0x60, + 0xff, 0xff, 0xff, 0xff, 0xb5, 0x5c, 0x15, 0x70, 0xff, 0xff, 0xff, 0xff, + 0xb6, 0x27, 0x0e, 0x60, 0xff, 0xff, 0xff, 0xff, 0xb7, 0x3b, 0xf7, 0x70, + 0xff, 0xff, 0xff, 0xff, 0xb8, 0x06, 0xf0, 0x60, 0xff, 0xff, 0xff, 0xff, + 0xb9, 0x1b, 0xd9, 0x70, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xe6, 0xd2, 0x60, + 0xff, 0xff, 0xff, 0xff, 0xbb, 0x04, 0xf5, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xbb, 0xc6, 0xb4, 0x60, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe4, 0xd7, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xbd, 0xaf, 0xd0, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xbe, 0xc4, 0xb9, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x8f, 0xb2, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xc0, 0xa4, 0x9b, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xc1, 0x6f, 0x94, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x84, 0x7d, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xc3, 0x4f, 0x76, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xc4, 0x64, 0x5f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc5, 0x2f, 0x58, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xc6, 0x4d, 0x7c, 0x70, 0xff, 0xff, 0xff, 0xff, + 0xc7, 0x0f, 0x3a, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x2d, 0x5e, 0x70, + 0xff, 0xff, 0xff, 0xff, 0xc8, 0xf8, 0x57, 0x60, 0xff, 0xff, 0xff, 0xff, + 0xca, 0x0d, 0x40, 0x70, 0xff, 0xff, 0xff, 0xff, 0xca, 0xd8, 0x39, 0x60, + 0xff, 0xff, 0xff, 0xff, 0xcb, 0x88, 0xf0, 0x70, 0xff, 0xff, 0xff, 0xff, + 0xd2, 0x23, 0xf4, 0x70, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x60, 0xfb, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xd3, 0x75, 0xe4, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xd4, 0x40, 0xdd, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x55, 0xc6, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xd6, 0x20, 0xbf, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xd7, 0x35, 0xa8, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x00, 0xa1, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xd9, 0x15, 0x8a, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xd9, 0xe0, 0x83, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xda, 0xfe, 0xa7, 0x70, + 0xff, 0xff, 0xff, 0xff, 0xdb, 0xc0, 0x65, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xdc, 0xde, 0x89, 0x70, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xa9, 0x82, 0x60, + 0xff, 0xff, 0xff, 0xff, 0xde, 0xbe, 0x6b, 0x70, 0xff, 0xff, 0xff, 0xff, + 0xdf, 0x89, 0x64, 0x60, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x9e, 0x4d, 0x70, + 0xff, 0xff, 0xff, 0xff, 0xe1, 0x69, 0x46, 0x60, 0xff, 0xff, 0xff, 0xff, + 0xe2, 0x7e, 0x2f, 0x70, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x49, 0x28, 0x60, + 0xff, 0xff, 0xff, 0xff, 0xe4, 0x5e, 0x11, 0x70, 0xff, 0xff, 0xff, 0xff, + 0xe5, 0x57, 0x2e, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe6, 0x47, 0x2d, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xe7, 0x37, 0x10, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xe8, 0x27, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x16, 0xf2, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xea, 0x06, 0xf1, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xea, 0xf6, 0xd4, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xeb, 0xe6, 0xd3, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xec, 0xd6, 0xb6, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xed, 0xc6, 0xb5, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xee, 0xbf, 0xd3, 0x60, + 0xff, 0xff, 0xff, 0xff, 0xef, 0xaf, 0xd2, 0x70, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0x9f, 0xb5, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f, 0xb4, 0x70, + 0xff, 0xff, 0xff, 0xff, 0xf2, 0x7f, 0x97, 0x60, 0xff, 0xff, 0xff, 0xff, + 0xf3, 0x6f, 0x96, 0x70, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5f, 0x79, 0x60, + 0xff, 0xff, 0xff, 0xff, 0xf5, 0x4f, 0x78, 0x70, 0xff, 0xff, 0xff, 0xff, + 0xf6, 0x3f, 0x5b, 0x60, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x2f, 0x5a, 0x70, + 0xff, 0xff, 0xff, 0xff, 0xf8, 0x28, 0x77, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xf9, 0x0f, 0x3c, 0x70, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x59, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xfa, 0xf8, 0x58, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xfb, 0xe8, 0x3b, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd8, 0x3a, 0xf0, + 0xff, 0xff, 0xff, 0xff, 0xfd, 0xc8, 0x1d, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xb8, 0x1c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, 0xff, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x87, 0xe1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x02, 0x77, 0xe0, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x70, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x60, 0xfd, 0x70, 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0xe0, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x40, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x30, 0xc2, 0x60, 0x00, 0x00, 0x00, 0x00, 0x07, 0x8d, 0x19, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x09, 0x10, 0xa4, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x09, 0xad, 0x94, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, 0x86, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0xe0, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0xd9, 0xa2, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xc0, 0x67, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0xb9, 0x84, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0xa9, 0x83, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x99, 0x66, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x11, 0x89, 0x65, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x79, 0x48, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x13, 0x69, 0x47, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x59, 0x2a, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x15, 0x49, 0x29, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x0c, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x17, 0x29, 0x0b, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x22, 0x29, 0x60, 0x00, 0x00, 0x00, 0x00, 0x19, 0x08, 0xed, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x1a, 0x02, 0x0b, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x1a, 0xf2, 0x0a, 0x70, 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe1, 0xed, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x1c, 0xd1, 0xec, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x1d, 0xc1, 0xcf, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xb1, 0xce, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xa1, 0xb1, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x76, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x21, 0x81, 0x93, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x55, 0xe2, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x23, 0x6a, 0xaf, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x24, 0x35, 0xc4, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x25, 0x4a, 0x91, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x15, 0xa6, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x27, 0x2a, 0x73, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x27, 0xfe, 0xc3, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x29, 0x0a, 0x55, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x29, 0xde, 0xa5, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x2a, 0xea, 0x37, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0xbe, 0x87, 0x70, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd3, 0x54, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x2d, 0x9e, 0x69, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x2e, 0xb3, 0x36, 0x60, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7e, 0x4b, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x93, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x31, 0x67, 0x67, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0xfa, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x33, 0x47, 0x49, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x52, 0xdc, 0x60, 0x00, 0x00, 0x00, 0x00, 0x35, 0x27, 0x2b, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x32, 0xbe, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x37, 0x07, 0x0d, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0xda, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x38, 0xe6, 0xef, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x39, 0xfb, 0xbc, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xc6, 0xd1, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x3b, 0xdb, 0x9e, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0xaf, 0xee, 0x70, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbb, 0x80, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x8f, 0xd0, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0x9b, 0x62, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6f, 0xb2, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x41, 0x84, 0x7f, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x42, 0x4f, 0x94, 0x70, 0x00, 0x00, 0x00, 0x00, 0x43, 0x64, 0x61, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x44, 0x2f, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x45, 0x44, 0x43, 0x60, 0x00, 0x00, 0x00, 0x00, 0x45, 0xf3, 0xa8, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x2d, 0x5f, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x47, 0xd3, 0x8a, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0d, 0x41, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x49, 0xb3, 0x6c, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x4a, 0xed, 0x23, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x9c, 0x89, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x4c, 0xd6, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x4d, 0x7c, 0x6b, 0x70, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xb6, 0x22, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x4f, 0x5c, 0x4d, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x96, 0x04, 0x60, 0x00, 0x00, 0x00, 0x00, 0x51, 0x3c, 0x2f, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x52, 0x75, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x53, 0x1c, 0x11, 0x70, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xc8, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x54, 0xfb, 0xf3, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x56, 0x35, 0xaa, 0x60, 0x00, 0x00, 0x00, 0x00, 0x56, 0xe5, 0x0f, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x1e, 0xc6, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x58, 0xc4, 0xf1, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x59, 0xfe, 0xa8, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x5a, 0xa4, 0xd3, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x5b, 0xde, 0x8a, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x84, 0xb5, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x5d, 0xbe, 0x6c, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x5e, 0x64, 0x97, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x9e, 0x4e, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x4d, 0xb4, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x61, 0x87, 0x6b, 0x60, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2d, 0x96, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x63, 0x67, 0x4d, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x64, 0x0d, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x2f, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x65, 0xed, 0x5a, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x67, 0x27, 0x11, 0x60, 0x00, 0x00, 0x00, 0x00, 0x67, 0xcd, 0x3c, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x69, 0x06, 0xf3, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x69, 0xad, 0x1e, 0x70, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe6, 0xd5, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x6b, 0x96, 0x3a, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x6c, 0xcf, 0xf1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x76, 0x1c, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x6e, 0xaf, 0xd3, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x6f, 0x55, 0xfe, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8f, 0xb5, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x71, 0x35, 0xe0, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x72, 0x6f, 0x97, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xc2, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x74, 0x4f, 0x79, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x74, 0xfe, 0xdf, 0x70, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0x96, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x76, 0xde, 0xc1, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x78, 0x18, 0x78, 0x60, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbe, 0xa3, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x79, 0xf8, 0x5a, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x7a, 0x9e, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xd8, 0x3c, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7e, 0x67, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x7d, 0xb8, 0x1e, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x5e, 0x49, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x7f, 0x98, 0x00, 0x60, 0x00, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, + 0x02, 0x01, 0x02, 0x01, 0x02, 0xff, 0xff, 0xba, 0x9e, 0x00, 0x00, 0xff, + 0xff, 0xc7, 0xc0, 0x01, 0x04, 0xff, 0xff, 0xb9, 0xb0, 0x00, 0x08, 0xff, + 0xff, 0xc7, 0xc0, 0x01, 0x0c, 0xff, 0xff, 0xc7, 0xc0, 0x01, 0x10, 0x4c, + 0x4d, 0x54, 0x00, 0x45, 0x44, 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, + 0x57, 0x54, 0x00, 0x45, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45, 0x44, + 0x54, 0x2c, 0x4d, 0x33, 0x2e, 0x32, 0x2e, 0x30, 0x2c, 0x4d, 0x31, 0x31, + 0x2e, 0x31, 0x2e, 0x30, 0x0a +}; +unsigned int America_New_York_len = 3545; +unsigned char Australia_Sydney[] = { + 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0e, 0x80, 0x00, 0x00, 0x00, + 0x9c, 0x4e, 0xa6, 0x9c, 0x9c, 0xbc, 0x20, 0xf0, 0xcb, 0x54, 0xb3, 0x00, + 0xcb, 0xc7, 0x57, 0x70, 0xcc, 0xb7, 0x56, 0x80, 0xcd, 0xa7, 0x39, 0x70, + 0xce, 0xa0, 0x73, 0x00, 0xcf, 0x87, 0x1b, 0x70, 0x03, 0x70, 0x39, 0x80, + 0x04, 0x0d, 0x1c, 0x00, 0x05, 0x50, 0x1b, 0x80, 0x05, 0xf6, 0x38, 0x80, + 0x07, 0x2f, 0xfd, 0x80, 0x07, 0xd6, 0x1a, 0x80, 0x09, 0x0f, 0xdf, 0x80, + 0x09, 0xb5, 0xfc, 0x80, 0x0a, 0xef, 0xc1, 0x80, 0x0b, 0x9f, 0x19, 0x00, + 0x0c, 0xd8, 0xde, 0x00, 0x0d, 0x7e, 0xfb, 0x00, 0x0e, 0xb8, 0xc0, 0x00, + 0x0f, 0x5e, 0xdd, 0x00, 0x10, 0x98, 0xa2, 0x00, 0x11, 0x3e, 0xbf, 0x00, + 0x12, 0x78, 0x84, 0x00, 0x13, 0x1e, 0xa1, 0x00, 0x14, 0x58, 0x66, 0x00, + 0x14, 0xfe, 0x83, 0x00, 0x16, 0x38, 0x48, 0x00, 0x17, 0x0c, 0x89, 0x80, + 0x18, 0x21, 0x64, 0x80, 0x18, 0xc7, 0x81, 0x80, 0x1a, 0x01, 0x46, 0x80, + 0x1a, 0xa7, 0x63, 0x80, 0x1b, 0xe1, 0x28, 0x80, 0x1c, 0x87, 0x45, 0x80, + 0x1d, 0xc1, 0x0a, 0x80, 0x1e, 0x79, 0x9c, 0x80, 0x1f, 0x97, 0xb2, 0x00, + 0x20, 0x59, 0x7e, 0x80, 0x21, 0x80, 0xce, 0x80, 0x22, 0x42, 0x9b, 0x00, + 0x23, 0x69, 0xeb, 0x00, 0x24, 0x22, 0x7d, 0x00, 0x25, 0x49, 0xcd, 0x00, + 0x25, 0xef, 0xea, 0x00, 0x27, 0x29, 0xaf, 0x00, 0x27, 0xcf, 0xcc, 0x00, + 0x29, 0x09, 0x91, 0x00, 0x29, 0xaf, 0xae, 0x00, 0x2a, 0xe9, 0x73, 0x00, + 0x2b, 0x98, 0xca, 0x80, 0x2c, 0xd2, 0x8f, 0x80, 0x2d, 0x78, 0xac, 0x80, + 0x2e, 0xb2, 0x71, 0x80, 0x2f, 0x58, 0x8e, 0x80, 0x30, 0x92, 0x53, 0x80, + 0x31, 0x5d, 0x5a, 0x80, 0x32, 0x72, 0x35, 0x80, 0x33, 0x3d, 0x3c, 0x80, + 0x34, 0x52, 0x17, 0x80, 0x35, 0x1d, 0x1e, 0x80, 0x36, 0x31, 0xf9, 0x80, + 0x36, 0xfd, 0x00, 0x80, 0x38, 0x1b, 0x16, 0x00, 0x38, 0xdc, 0xe2, 0x80, + 0x39, 0xa7, 0xe9, 0x80, 0x3a, 0xbc, 0xc4, 0x80, 0x3b, 0xda, 0xda, 0x00, + 0x3c, 0xa5, 0xe1, 0x00, 0x3d, 0xba, 0xbc, 0x00, 0x3e, 0x85, 0xc3, 0x00, + 0x3f, 0x9a, 0x9e, 0x00, 0x40, 0x65, 0xa5, 0x00, 0x41, 0x83, 0xba, 0x80, + 0x42, 0x45, 0x87, 0x00, 0x43, 0x63, 0x9c, 0x80, 0x44, 0x2e, 0xa3, 0x80, + 0x45, 0x43, 0x7e, 0x80, 0x46, 0x05, 0x4b, 0x00, 0x47, 0x23, 0x60, 0x80, + 0x47, 0xf7, 0xa2, 0x00, 0x48, 0xe7, 0x93, 0x00, 0x49, 0xd7, 0x84, 0x00, + 0x4a, 0xc7, 0x75, 0x00, 0x4b, 0xb7, 0x66, 0x00, 0x4c, 0xa7, 0x57, 0x00, + 0x4d, 0x97, 0x48, 0x00, 0x4e, 0x87, 0x39, 0x00, 0x4f, 0x77, 0x2a, 0x00, + 0x50, 0x70, 0x55, 0x80, 0x51, 0x60, 0x46, 0x80, 0x52, 0x50, 0x37, 0x80, + 0x53, 0x40, 0x28, 0x80, 0x54, 0x30, 0x19, 0x80, 0x55, 0x20, 0x0a, 0x80, + 0x56, 0x0f, 0xfb, 0x80, 0x56, 0xff, 0xec, 0x80, 0x57, 0xef, 0xdd, 0x80, + 0x58, 0xdf, 0xce, 0x80, 0x59, 0xcf, 0xbf, 0x80, 0x5a, 0xbf, 0xb0, 0x80, + 0x5b, 0xb8, 0xdc, 0x00, 0x5c, 0xa8, 0xcd, 0x00, 0x5d, 0x98, 0xbe, 0x00, + 0x5e, 0x88, 0xaf, 0x00, 0x5f, 0x78, 0xa0, 0x00, 0x60, 0x68, 0x91, 0x00, + 0x61, 0x58, 0x82, 0x00, 0x62, 0x48, 0x73, 0x00, 0x63, 0x38, 0x64, 0x00, + 0x64, 0x28, 0x55, 0x00, 0x65, 0x18, 0x46, 0x00, 0x66, 0x11, 0x71, 0x80, + 0x67, 0x01, 0x62, 0x80, 0x67, 0xf1, 0x53, 0x80, 0x68, 0xe1, 0x44, 0x80, + 0x69, 0xd1, 0x35, 0x80, 0x6a, 0xc1, 0x26, 0x80, 0x6b, 0xb1, 0x17, 0x80, + 0x6c, 0xa1, 0x08, 0x80, 0x6d, 0x90, 0xf9, 0x80, 0x6e, 0x80, 0xea, 0x80, + 0x6f, 0x70, 0xdb, 0x80, 0x70, 0x6a, 0x07, 0x00, 0x71, 0x59, 0xf8, 0x00, + 0x72, 0x49, 0xe9, 0x00, 0x73, 0x39, 0xda, 0x00, 0x74, 0x29, 0xcb, 0x00, + 0x75, 0x19, 0xbc, 0x00, 0x76, 0x09, 0xad, 0x00, 0x76, 0xf9, 0x9e, 0x00, + 0x77, 0xe9, 0x8f, 0x00, 0x78, 0xd9, 0x80, 0x00, 0x79, 0xc9, 0x71, 0x00, + 0x7a, 0xb9, 0x62, 0x00, 0x7b, 0xb2, 0x8d, 0x80, 0x7c, 0xa2, 0x7e, 0x80, + 0x7d, 0x92, 0x6f, 0x80, 0x7e, 0x82, 0x60, 0x80, 0x7f, 0x72, 0x51, 0x80, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x03, 0x04, 0x03, + 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, + 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, + 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, + 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, + 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, + 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, + 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, + 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, + 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, + 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, + 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x00, 0x00, + 0x8d, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xb0, 0x01, 0x04, 0x00, 0x00, + 0x8c, 0xa0, 0x00, 0x09, 0x00, 0x00, 0x9a, 0xb0, 0x01, 0x04, 0x00, 0x00, + 0x8c, 0xa0, 0x00, 0x09, 0x4c, 0x4d, 0x54, 0x00, 0x41, 0x45, 0x44, 0x54, + 0x00, 0x41, 0x45, 0x53, 0x54, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0e, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x73, 0x16, 0x7f, 0x3c, 0xff, 0xff, 0xff, 0xff, 0x9c, 0x4e, 0xa6, 0x9c, + 0xff, 0xff, 0xff, 0xff, 0x9c, 0xbc, 0x20, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xcb, 0x54, 0xb3, 0x00, 0xff, 0xff, 0xff, 0xff, 0xcb, 0xc7, 0x57, 0x70, + 0xff, 0xff, 0xff, 0xff, 0xcc, 0xb7, 0x56, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xcd, 0xa7, 0x39, 0x70, 0xff, 0xff, 0xff, 0xff, 0xce, 0xa0, 0x73, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xcf, 0x87, 0x1b, 0x70, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x70, 0x39, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0d, 0x1c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0x50, 0x1b, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x05, 0xf6, 0x38, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0x2f, 0xfd, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xd6, 0x1a, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x0f, 0xdf, 0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xb5, 0xfc, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0xef, 0xc1, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x9f, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xd8, 0xde, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0d, 0x7e, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0e, 0xb8, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x5e, 0xdd, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x98, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x11, 0x3e, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x78, 0x84, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x1e, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x58, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xfe, 0x83, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x16, 0x38, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x17, 0x0c, 0x89, 0x80, 0x00, 0x00, 0x00, 0x00, 0x18, 0x21, 0x64, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x18, 0xc7, 0x81, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x1a, 0x01, 0x46, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xa7, 0x63, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x1b, 0xe1, 0x28, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x1c, 0x87, 0x45, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xc1, 0x0a, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x1e, 0x79, 0x9c, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x97, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x59, 0x7e, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x21, 0x80, 0xce, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x42, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x69, 0xeb, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x22, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x25, 0x49, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xef, 0xea, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x27, 0x29, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x27, 0xcf, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x09, 0x91, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x29, 0xaf, 0xae, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0xe9, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x98, 0xca, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x2c, 0xd2, 0x8f, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x2d, 0x78, 0xac, 0x80, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xb2, 0x71, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x2f, 0x58, 0x8e, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x92, 0x53, 0x80, 0x00, 0x00, 0x00, 0x00, 0x31, 0x5d, 0x5a, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x32, 0x72, 0x35, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x33, 0x3d, 0x3c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x34, 0x52, 0x17, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x35, 0x1d, 0x1e, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x31, 0xf9, 0x80, 0x00, 0x00, 0x00, 0x00, 0x36, 0xfd, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0xdc, 0xe2, 0x80, 0x00, 0x00, 0x00, 0x00, 0x39, 0xa7, 0xe9, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x3a, 0xbc, 0xc4, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x3b, 0xda, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xa5, 0xe1, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3d, 0xba, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x85, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x9a, 0x9e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x65, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x41, 0x83, 0xba, 0x80, 0x00, 0x00, 0x00, 0x00, 0x42, 0x45, 0x87, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x43, 0x63, 0x9c, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x2e, 0xa3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x45, 0x43, 0x7e, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x23, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, 0x47, 0xf7, 0xa2, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0xe7, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x49, 0xd7, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0xc7, 0x75, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4b, 0xb7, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4c, 0xa7, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x97, 0x48, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4e, 0x87, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4f, 0x77, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x70, 0x55, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x60, 0x46, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x52, 0x50, 0x37, 0x80, 0x00, 0x00, 0x00, 0x00, 0x53, 0x40, 0x28, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x30, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x55, 0x20, 0x0a, 0x80, 0x00, 0x00, 0x00, 0x00, 0x56, 0x0f, 0xfb, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x56, 0xff, 0xec, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x57, 0xef, 0xdd, 0x80, 0x00, 0x00, 0x00, 0x00, 0x58, 0xdf, 0xce, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x59, 0xcf, 0xbf, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x5a, 0xbf, 0xb0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x5b, 0xb8, 0xdc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5c, 0xa8, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5d, 0x98, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x88, 0xaf, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5f, 0x78, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x68, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x58, 0x82, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x62, 0x48, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x63, 0x38, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x28, 0x55, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x65, 0x18, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x11, 0x71, 0x80, 0x00, 0x00, 0x00, 0x00, 0x67, 0x01, 0x62, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x67, 0xf1, 0x53, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xe1, 0x44, 0x80, 0x00, 0x00, 0x00, 0x00, 0x69, 0xd1, 0x35, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x6a, 0xc1, 0x26, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x6b, 0xb1, 0x17, 0x80, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xa1, 0x08, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x6d, 0x90, 0xf9, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x6e, 0x80, 0xea, 0x80, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x70, 0xdb, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x70, 0x6a, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x71, 0x59, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x49, 0xe9, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x73, 0x39, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x74, 0x29, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x19, 0xbc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0x09, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x76, 0xf9, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0xe9, 0x8f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0xd9, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x79, 0xc9, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xb9, 0x62, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7b, 0xb2, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x7c, 0xa2, 0x7e, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x92, 0x6f, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x82, 0x60, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0x72, 0x51, 0x80, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x01, 0x02, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, + 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, + 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, + 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, + 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, + 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, + 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, + 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, + 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, + 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, + 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, 0x03, 0x04, + 0x03, 0x04, 0x03, 0x00, 0x00, 0x8d, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x9a, + 0xb0, 0x01, 0x04, 0x00, 0x00, 0x8c, 0xa0, 0x00, 0x09, 0x00, 0x00, 0x9a, + 0xb0, 0x01, 0x04, 0x00, 0x00, 0x8c, 0xa0, 0x00, 0x09, 0x4c, 0x4d, 0x54, + 0x00, 0x41, 0x45, 0x44, 0x54, 0x00, 0x41, 0x45, 0x53, 0x54, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x41, 0x45, + 0x53, 0x54, 0x2d, 0x31, 0x30, 0x41, 0x45, 0x44, 0x54, 0x2c, 0x4d, 0x31, + 0x30, 0x2e, 0x31, 0x2e, 0x30, 0x2c, 0x4d, 0x34, 0x2e, 0x31, 0x2e, 0x30, + 0x2f, 0x33, 0x0a +}; +unsigned int Australia_Sydney_len = 2223; diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/time.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/time/time.cc index 21e5625759..441638b256 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/time.cc +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/time.cc @@ -1,62 +1,62 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // The implementation of the y_absl::Time class, which is declared in // //y_absl/time.h. -// +// // The representation for an y_absl::Time is an y_absl::Duration offset from the -// epoch. We use the traditional Unix epoch (1970-01-01 00:00:00 +0000) -// for convenience, but this is not exposed in the API and could be changed. -// -// NOTE: To keep type verbosity to a minimum, the following variable naming -// conventions are used throughout this file. -// +// epoch. We use the traditional Unix epoch (1970-01-01 00:00:00 +0000) +// for convenience, but this is not exposed in the API and could be changed. +// +// NOTE: To keep type verbosity to a minimum, the following variable naming +// conventions are used throughout this file. +// // tz: An y_absl::TimeZone // ci: An y_absl::TimeZone::CivilInfo // ti: An y_absl::TimeZone::TimeInfo // cd: An y_absl::CivilDay or a cctz::civil_day // cs: An y_absl::CivilSecond or a cctz::civil_second // bd: An y_absl::Time::Breakdown -// cl: A cctz::time_zone::civil_lookup -// al: A cctz::time_zone::absolute_lookup - +// cl: A cctz::time_zone::civil_lookup +// al: A cctz::time_zone::absolute_lookup + #include "y_absl/time/time.h" - -#if defined(_MSC_VER) -#include <winsock2.h> // for timeval -#endif - -#include <cstring> -#include <ctime> -#include <limits> - + +#if defined(_MSC_VER) +#include <winsock2.h> // for timeval +#endif + +#include <cstring> +#include <ctime> +#include <limits> + #include "y_absl/time/internal/cctz/include/cctz/civil_time.h" #include "y_absl/time/internal/cctz/include/cctz/time_zone.h" - + namespace cctz = y_absl::time_internal::cctz; - + namespace y_absl { ABSL_NAMESPACE_BEGIN - -namespace { - -inline cctz::time_point<cctz::seconds> unix_epoch() { - return std::chrono::time_point_cast<cctz::seconds>( - std::chrono::system_clock::from_time_t(0)); -} - -// Floors d to the next unit boundary closer to negative infinity. + +namespace { + +inline cctz::time_point<cctz::seconds> unix_epoch() { + return std::chrono::time_point_cast<cctz::seconds>( + std::chrono::system_clock::from_time_t(0)); +} + +// Floors d to the next unit boundary closer to negative infinity. inline int64_t FloorToUnit(y_absl::Duration d, y_absl::Duration unit) { y_absl::Duration rem; int64_t q = y_absl::IDivDuration(d, unit, &rem); @@ -64,437 +64,437 @@ inline int64_t FloorToUnit(y_absl::Duration d, y_absl::Duration unit) { q == std::numeric_limits<int64_t>::min()) ? q : q - 1; -} - +} + inline y_absl::Time::Breakdown InfiniteFutureBreakdown() { y_absl::Time::Breakdown bd; - bd.year = std::numeric_limits<int64_t>::max(); - bd.month = 12; - bd.day = 31; - bd.hour = 23; - bd.minute = 59; - bd.second = 59; + bd.year = std::numeric_limits<int64_t>::max(); + bd.month = 12; + bd.day = 31; + bd.hour = 23; + bd.minute = 59; + bd.second = 59; bd.subsecond = y_absl::InfiniteDuration(); - bd.weekday = 4; - bd.yearday = 365; - bd.offset = 0; - bd.is_dst = false; - bd.zone_abbr = "-00"; - return bd; -} - + bd.weekday = 4; + bd.yearday = 365; + bd.offset = 0; + bd.is_dst = false; + bd.zone_abbr = "-00"; + return bd; +} + inline y_absl::Time::Breakdown InfinitePastBreakdown() { - Time::Breakdown bd; - bd.year = std::numeric_limits<int64_t>::min(); - bd.month = 1; - bd.day = 1; - bd.hour = 0; - bd.minute = 0; - bd.second = 0; + Time::Breakdown bd; + bd.year = std::numeric_limits<int64_t>::min(); + bd.month = 1; + bd.day = 1; + bd.hour = 0; + bd.minute = 0; + bd.second = 0; bd.subsecond = -y_absl::InfiniteDuration(); - bd.weekday = 7; - bd.yearday = 1; - bd.offset = 0; - bd.is_dst = false; - bd.zone_abbr = "-00"; - return bd; -} - + bd.weekday = 7; + bd.yearday = 1; + bd.offset = 0; + bd.is_dst = false; + bd.zone_abbr = "-00"; + return bd; +} + inline y_absl::TimeZone::CivilInfo InfiniteFutureCivilInfo() { - TimeZone::CivilInfo ci; - ci.cs = CivilSecond::max(); - ci.subsecond = InfiniteDuration(); - ci.offset = 0; - ci.is_dst = false; - ci.zone_abbr = "-00"; - return ci; -} - + TimeZone::CivilInfo ci; + ci.cs = CivilSecond::max(); + ci.subsecond = InfiniteDuration(); + ci.offset = 0; + ci.is_dst = false; + ci.zone_abbr = "-00"; + return ci; +} + inline y_absl::TimeZone::CivilInfo InfinitePastCivilInfo() { - TimeZone::CivilInfo ci; - ci.cs = CivilSecond::min(); - ci.subsecond = -InfiniteDuration(); - ci.offset = 0; - ci.is_dst = false; - ci.zone_abbr = "-00"; - return ci; -} - + TimeZone::CivilInfo ci; + ci.cs = CivilSecond::min(); + ci.subsecond = -InfiniteDuration(); + ci.offset = 0; + ci.is_dst = false; + ci.zone_abbr = "-00"; + return ci; +} + inline y_absl::TimeConversion InfiniteFutureTimeConversion() { y_absl::TimeConversion tc; tc.pre = tc.trans = tc.post = y_absl::InfiniteFuture(); tc.kind = y_absl::TimeConversion::UNIQUE; - tc.normalized = true; - return tc; -} - -inline TimeConversion InfinitePastTimeConversion() { + tc.normalized = true; + return tc; +} + +inline TimeConversion InfinitePastTimeConversion() { y_absl::TimeConversion tc; tc.pre = tc.trans = tc.post = y_absl::InfinitePast(); tc.kind = y_absl::TimeConversion::UNIQUE; - tc.normalized = true; - return tc; -} - -// Makes a Time from sec, overflowing to InfiniteFuture/InfinitePast as -// necessary. If sec is min/max, then consult cs+tz to check for overlow. -Time MakeTimeWithOverflow(const cctz::time_point<cctz::seconds>& sec, - const cctz::civil_second& cs, - const cctz::time_zone& tz, - bool* normalized = nullptr) { - const auto max = cctz::time_point<cctz::seconds>::max(); - const auto min = cctz::time_point<cctz::seconds>::min(); - if (sec == max) { - const auto al = tz.lookup(max); - if (cs > al.cs) { - if (normalized) *normalized = true; + tc.normalized = true; + return tc; +} + +// Makes a Time from sec, overflowing to InfiniteFuture/InfinitePast as +// necessary. If sec is min/max, then consult cs+tz to check for overlow. +Time MakeTimeWithOverflow(const cctz::time_point<cctz::seconds>& sec, + const cctz::civil_second& cs, + const cctz::time_zone& tz, + bool* normalized = nullptr) { + const auto max = cctz::time_point<cctz::seconds>::max(); + const auto min = cctz::time_point<cctz::seconds>::min(); + if (sec == max) { + const auto al = tz.lookup(max); + if (cs > al.cs) { + if (normalized) *normalized = true; return y_absl::InfiniteFuture(); - } - } - if (sec == min) { - const auto al = tz.lookup(min); - if (cs < al.cs) { - if (normalized) *normalized = true; + } + } + if (sec == min) { + const auto al = tz.lookup(min); + if (cs < al.cs) { + if (normalized) *normalized = true; return y_absl::InfinitePast(); - } - } - const auto hi = (sec - unix_epoch()).count(); - return time_internal::FromUnixDuration(time_internal::MakeDuration(hi)); -} - -// Returns Mon=1..Sun=7. -inline int MapWeekday(const cctz::weekday& wd) { - switch (wd) { - case cctz::weekday::monday: - return 1; - case cctz::weekday::tuesday: - return 2; - case cctz::weekday::wednesday: - return 3; - case cctz::weekday::thursday: - return 4; - case cctz::weekday::friday: - return 5; - case cctz::weekday::saturday: - return 6; - case cctz::weekday::sunday: - return 7; - } - return 1; -} - -bool FindTransition(const cctz::time_zone& tz, - bool (cctz::time_zone::*find_transition)( - const cctz::time_point<cctz::seconds>& tp, - cctz::time_zone::civil_transition* trans) const, - Time t, TimeZone::CivilTransition* trans) { - // Transitions are second-aligned, so we can discard any fractional part. - const auto tp = unix_epoch() + cctz::seconds(ToUnixSeconds(t)); - cctz::time_zone::civil_transition tr; - if (!(tz.*find_transition)(tp, &tr)) return false; - trans->from = CivilSecond(tr.from); - trans->to = CivilSecond(tr.to); - return true; -} - -} // namespace - -// -// Time -// - + } + } + const auto hi = (sec - unix_epoch()).count(); + return time_internal::FromUnixDuration(time_internal::MakeDuration(hi)); +} + +// Returns Mon=1..Sun=7. +inline int MapWeekday(const cctz::weekday& wd) { + switch (wd) { + case cctz::weekday::monday: + return 1; + case cctz::weekday::tuesday: + return 2; + case cctz::weekday::wednesday: + return 3; + case cctz::weekday::thursday: + return 4; + case cctz::weekday::friday: + return 5; + case cctz::weekday::saturday: + return 6; + case cctz::weekday::sunday: + return 7; + } + return 1; +} + +bool FindTransition(const cctz::time_zone& tz, + bool (cctz::time_zone::*find_transition)( + const cctz::time_point<cctz::seconds>& tp, + cctz::time_zone::civil_transition* trans) const, + Time t, TimeZone::CivilTransition* trans) { + // Transitions are second-aligned, so we can discard any fractional part. + const auto tp = unix_epoch() + cctz::seconds(ToUnixSeconds(t)); + cctz::time_zone::civil_transition tr; + if (!(tz.*find_transition)(tp, &tr)) return false; + trans->from = CivilSecond(tr.from); + trans->to = CivilSecond(tr.to); + return true; +} + +} // namespace + +// +// Time +// + y_absl::Time::Breakdown Time::In(y_absl::TimeZone tz) const { if (*this == y_absl::InfiniteFuture()) return InfiniteFutureBreakdown(); if (*this == y_absl::InfinitePast()) return InfinitePastBreakdown(); - - const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(rep_)); - const auto al = cctz::time_zone(tz).lookup(tp); - const auto cs = al.cs; - const auto cd = cctz::civil_day(cs); - + + const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(rep_)); + const auto al = cctz::time_zone(tz).lookup(tp); + const auto cs = al.cs; + const auto cd = cctz::civil_day(cs); + y_absl::Time::Breakdown bd; - bd.year = cs.year(); - bd.month = cs.month(); - bd.day = cs.day(); - bd.hour = cs.hour(); - bd.minute = cs.minute(); - bd.second = cs.second(); - bd.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(rep_)); - bd.weekday = MapWeekday(cctz::get_weekday(cd)); - bd.yearday = cctz::get_yearday(cd); - bd.offset = al.offset; - bd.is_dst = al.is_dst; - bd.zone_abbr = al.abbr; - return bd; -} - -// -// Conversions from/to other time types. -// - + bd.year = cs.year(); + bd.month = cs.month(); + bd.day = cs.day(); + bd.hour = cs.hour(); + bd.minute = cs.minute(); + bd.second = cs.second(); + bd.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(rep_)); + bd.weekday = MapWeekday(cctz::get_weekday(cd)); + bd.yearday = cctz::get_yearday(cd); + bd.offset = al.offset; + bd.is_dst = al.is_dst; + bd.zone_abbr = al.abbr; + return bd; +} + +// +// Conversions from/to other time types. +// + y_absl::Time FromUDate(double udate) { return time_internal::FromUnixDuration(y_absl::Milliseconds(udate)); -} - +} + y_absl::Time FromUniversal(int64_t universal) { return y_absl::UniversalEpoch() + 100 * y_absl::Nanoseconds(universal); -} - -int64_t ToUnixNanos(Time t) { - if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 && - time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 33 == 0) { - return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * - 1000 * 1000 * 1000) + - (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4); - } +} + +int64_t ToUnixNanos(Time t) { + if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 && + time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 33 == 0) { + return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * + 1000 * 1000 * 1000) + + (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4); + } return FloorToUnit(time_internal::ToUnixDuration(t), y_absl::Nanoseconds(1)); -} - -int64_t ToUnixMicros(Time t) { - if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 && - time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 43 == 0) { - return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * - 1000 * 1000) + - (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4000); - } +} + +int64_t ToUnixMicros(Time t) { + if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 && + time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 43 == 0) { + return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * + 1000 * 1000) + + (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / 4000); + } return FloorToUnit(time_internal::ToUnixDuration(t), y_absl::Microseconds(1)); -} - -int64_t ToUnixMillis(Time t) { - if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 && - time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 53 == 0) { - return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * 1000) + - (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / - (4000 * 1000)); - } +} + +int64_t ToUnixMillis(Time t) { + if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 && + time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 53 == 0) { + return (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) * 1000) + + (time_internal::GetRepLo(time_internal::ToUnixDuration(t)) / + (4000 * 1000)); + } return FloorToUnit(time_internal::ToUnixDuration(t), y_absl::Milliseconds(1)); -} - -int64_t ToUnixSeconds(Time t) { - return time_internal::GetRepHi(time_internal::ToUnixDuration(t)); -} - +} + +int64_t ToUnixSeconds(Time t) { + return time_internal::GetRepHi(time_internal::ToUnixDuration(t)); +} + time_t ToTimeT(Time t) { return y_absl::ToTimespec(t).tv_sec; } - -double ToUDate(Time t) { + +double ToUDate(Time t) { return y_absl::FDivDuration(time_internal::ToUnixDuration(t), y_absl::Milliseconds(1)); -} - +} + int64_t ToUniversal(y_absl::Time t) { return y_absl::FloorToUnit(t - y_absl::UniversalEpoch(), y_absl::Nanoseconds(100)); -} - +} + y_absl::Time TimeFromTimespec(timespec ts) { return time_internal::FromUnixDuration(y_absl::DurationFromTimespec(ts)); -} - +} + y_absl::Time TimeFromTimeval(timeval tv) { return time_internal::FromUnixDuration(y_absl::DurationFromTimeval(tv)); -} - -timespec ToTimespec(Time t) { - timespec ts; +} + +timespec ToTimespec(Time t) { + timespec ts; y_absl::Duration d = time_internal::ToUnixDuration(t); - if (!time_internal::IsInfiniteDuration(d)) { - ts.tv_sec = time_internal::GetRepHi(d); - if (ts.tv_sec == time_internal::GetRepHi(d)) { // no time_t narrowing - ts.tv_nsec = time_internal::GetRepLo(d) / 4; // floor - return ts; - } - } + if (!time_internal::IsInfiniteDuration(d)) { + ts.tv_sec = time_internal::GetRepHi(d); + if (ts.tv_sec == time_internal::GetRepHi(d)) { // no time_t narrowing + ts.tv_nsec = time_internal::GetRepLo(d) / 4; // floor + return ts; + } + } if (d >= y_absl::ZeroDuration()) { - ts.tv_sec = std::numeric_limits<time_t>::max(); - ts.tv_nsec = 1000 * 1000 * 1000 - 1; - } else { - ts.tv_sec = std::numeric_limits<time_t>::min(); - ts.tv_nsec = 0; - } - return ts; -} - -timeval ToTimeval(Time t) { - timeval tv; + ts.tv_sec = std::numeric_limits<time_t>::max(); + ts.tv_nsec = 1000 * 1000 * 1000 - 1; + } else { + ts.tv_sec = std::numeric_limits<time_t>::min(); + ts.tv_nsec = 0; + } + return ts; +} + +timeval ToTimeval(Time t) { + timeval tv; timespec ts = y_absl::ToTimespec(t); - tv.tv_sec = ts.tv_sec; - if (tv.tv_sec != ts.tv_sec) { // narrowing - if (ts.tv_sec < 0) { - tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min(); - tv.tv_usec = 0; - } else { - tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max(); - tv.tv_usec = 1000 * 1000 - 1; - } - return tv; - } - tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000); // suseconds_t - return tv; -} - -Time FromChrono(const std::chrono::system_clock::time_point& tp) { - return time_internal::FromUnixDuration(time_internal::FromChrono( - tp - std::chrono::system_clock::from_time_t(0))); -} - + tv.tv_sec = ts.tv_sec; + if (tv.tv_sec != ts.tv_sec) { // narrowing + if (ts.tv_sec < 0) { + tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min(); + tv.tv_usec = 0; + } else { + tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::max(); + tv.tv_usec = 1000 * 1000 - 1; + } + return tv; + } + tv.tv_usec = static_cast<int>(ts.tv_nsec / 1000); // suseconds_t + return tv; +} + +Time FromChrono(const std::chrono::system_clock::time_point& tp) { + return time_internal::FromUnixDuration(time_internal::FromChrono( + tp - std::chrono::system_clock::from_time_t(0))); +} + std::chrono::system_clock::time_point ToChronoTime(y_absl::Time t) { - using D = std::chrono::system_clock::duration; - auto d = time_internal::ToUnixDuration(t); - if (d < ZeroDuration()) d = Floor(d, FromChrono(D{1})); - return std::chrono::system_clock::from_time_t(0) + - time_internal::ToChronoDuration<D>(d); -} - -// -// TimeZone -// - + using D = std::chrono::system_clock::duration; + auto d = time_internal::ToUnixDuration(t); + if (d < ZeroDuration()) d = Floor(d, FromChrono(D{1})); + return std::chrono::system_clock::from_time_t(0) + + time_internal::ToChronoDuration<D>(d); +} + +// +// TimeZone +// + y_absl::TimeZone::CivilInfo TimeZone::At(Time t) const { if (t == y_absl::InfiniteFuture()) return InfiniteFutureCivilInfo(); if (t == y_absl::InfinitePast()) return InfinitePastCivilInfo(); - - const auto ud = time_internal::ToUnixDuration(t); - const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(ud)); - const auto al = cz_.lookup(tp); - - TimeZone::CivilInfo ci; - ci.cs = CivilSecond(al.cs); - ci.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(ud)); - ci.offset = al.offset; - ci.is_dst = al.is_dst; - ci.zone_abbr = al.abbr; - return ci; -} - + + const auto ud = time_internal::ToUnixDuration(t); + const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(ud)); + const auto al = cz_.lookup(tp); + + TimeZone::CivilInfo ci; + ci.cs = CivilSecond(al.cs); + ci.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(ud)); + ci.offset = al.offset; + ci.is_dst = al.is_dst; + ci.zone_abbr = al.abbr; + return ci; +} + y_absl::TimeZone::TimeInfo TimeZone::At(CivilSecond ct) const { - const cctz::civil_second cs(ct); - const auto cl = cz_.lookup(cs); - - TimeZone::TimeInfo ti; - switch (cl.kind) { - case cctz::time_zone::civil_lookup::UNIQUE: - ti.kind = TimeZone::TimeInfo::UNIQUE; - break; - case cctz::time_zone::civil_lookup::SKIPPED: - ti.kind = TimeZone::TimeInfo::SKIPPED; - break; - case cctz::time_zone::civil_lookup::REPEATED: - ti.kind = TimeZone::TimeInfo::REPEATED; - break; - } - ti.pre = MakeTimeWithOverflow(cl.pre, cs, cz_); - ti.trans = MakeTimeWithOverflow(cl.trans, cs, cz_); - ti.post = MakeTimeWithOverflow(cl.post, cs, cz_); - return ti; -} - -bool TimeZone::NextTransition(Time t, CivilTransition* trans) const { - return FindTransition(cz_, &cctz::time_zone::next_transition, t, trans); -} - -bool TimeZone::PrevTransition(Time t, CivilTransition* trans) const { - return FindTransition(cz_, &cctz::time_zone::prev_transition, t, trans); -} - -// -// Conversions involving time zones. -// - + const cctz::civil_second cs(ct); + const auto cl = cz_.lookup(cs); + + TimeZone::TimeInfo ti; + switch (cl.kind) { + case cctz::time_zone::civil_lookup::UNIQUE: + ti.kind = TimeZone::TimeInfo::UNIQUE; + break; + case cctz::time_zone::civil_lookup::SKIPPED: + ti.kind = TimeZone::TimeInfo::SKIPPED; + break; + case cctz::time_zone::civil_lookup::REPEATED: + ti.kind = TimeZone::TimeInfo::REPEATED; + break; + } + ti.pre = MakeTimeWithOverflow(cl.pre, cs, cz_); + ti.trans = MakeTimeWithOverflow(cl.trans, cs, cz_); + ti.post = MakeTimeWithOverflow(cl.post, cs, cz_); + return ti; +} + +bool TimeZone::NextTransition(Time t, CivilTransition* trans) const { + return FindTransition(cz_, &cctz::time_zone::next_transition, t, trans); +} + +bool TimeZone::PrevTransition(Time t, CivilTransition* trans) const { + return FindTransition(cz_, &cctz::time_zone::prev_transition, t, trans); +} + +// +// Conversions involving time zones. +// + y_absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour, - int min, int sec, TimeZone tz) { - // Avoids years that are too extreme for CivilSecond to normalize. - if (year > 300000000000) return InfiniteFutureTimeConversion(); - if (year < -300000000000) return InfinitePastTimeConversion(); - - const CivilSecond cs(year, mon, day, hour, min, sec); - const auto ti = tz.At(cs); - - TimeConversion tc; - tc.pre = ti.pre; - tc.trans = ti.trans; - tc.post = ti.post; - switch (ti.kind) { - case TimeZone::TimeInfo::UNIQUE: - tc.kind = TimeConversion::UNIQUE; - break; - case TimeZone::TimeInfo::SKIPPED: - tc.kind = TimeConversion::SKIPPED; - break; - case TimeZone::TimeInfo::REPEATED: - tc.kind = TimeConversion::REPEATED; - break; - } - tc.normalized = false; - if (year != cs.year() || mon != cs.month() || day != cs.day() || - hour != cs.hour() || min != cs.minute() || sec != cs.second()) { - tc.normalized = true; - } - return tc; -} - + int min, int sec, TimeZone tz) { + // Avoids years that are too extreme for CivilSecond to normalize. + if (year > 300000000000) return InfiniteFutureTimeConversion(); + if (year < -300000000000) return InfinitePastTimeConversion(); + + const CivilSecond cs(year, mon, day, hour, min, sec); + const auto ti = tz.At(cs); + + TimeConversion tc; + tc.pre = ti.pre; + tc.trans = ti.trans; + tc.post = ti.post; + switch (ti.kind) { + case TimeZone::TimeInfo::UNIQUE: + tc.kind = TimeConversion::UNIQUE; + break; + case TimeZone::TimeInfo::SKIPPED: + tc.kind = TimeConversion::SKIPPED; + break; + case TimeZone::TimeInfo::REPEATED: + tc.kind = TimeConversion::REPEATED; + break; + } + tc.normalized = false; + if (year != cs.year() || mon != cs.month() || day != cs.day() || + hour != cs.hour() || min != cs.minute() || sec != cs.second()) { + tc.normalized = true; + } + return tc; +} + y_absl::Time FromTM(const struct tm& tm, y_absl::TimeZone tz) { - civil_year_t tm_year = tm.tm_year; - // Avoids years that are too extreme for CivilSecond to normalize. - if (tm_year > 300000000000ll) return InfiniteFuture(); - if (tm_year < -300000000000ll) return InfinitePast(); - int tm_mon = tm.tm_mon; - if (tm_mon == std::numeric_limits<int>::max()) { - tm_mon -= 12; - tm_year += 1; - } - const auto ti = tz.At(CivilSecond(tm_year + 1900, tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec)); - return tm.tm_isdst == 0 ? ti.post : ti.pre; -} - + civil_year_t tm_year = tm.tm_year; + // Avoids years that are too extreme for CivilSecond to normalize. + if (tm_year > 300000000000ll) return InfiniteFuture(); + if (tm_year < -300000000000ll) return InfinitePast(); + int tm_mon = tm.tm_mon; + if (tm_mon == std::numeric_limits<int>::max()) { + tm_mon -= 12; + tm_year += 1; + } + const auto ti = tz.At(CivilSecond(tm_year + 1900, tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec)); + return tm.tm_isdst == 0 ? ti.post : ti.pre; +} + struct tm ToTM(y_absl::Time t, y_absl::TimeZone tz) { - struct tm tm = {}; - - const auto ci = tz.At(t); - const auto& cs = ci.cs; - tm.tm_sec = cs.second(); - tm.tm_min = cs.minute(); - tm.tm_hour = cs.hour(); - tm.tm_mday = cs.day(); - tm.tm_mon = cs.month() - 1; - - // Saturates tm.tm_year in cases of over/underflow, accounting for the fact - // that tm.tm_year is years since 1900. - if (cs.year() < std::numeric_limits<int>::min() + 1900) { - tm.tm_year = std::numeric_limits<int>::min(); - } else if (cs.year() > std::numeric_limits<int>::max()) { - tm.tm_year = std::numeric_limits<int>::max() - 1900; - } else { - tm.tm_year = static_cast<int>(cs.year() - 1900); - } - - switch (GetWeekday(cs)) { - case Weekday::sunday: - tm.tm_wday = 0; - break; - case Weekday::monday: - tm.tm_wday = 1; - break; - case Weekday::tuesday: - tm.tm_wday = 2; - break; - case Weekday::wednesday: - tm.tm_wday = 3; - break; - case Weekday::thursday: - tm.tm_wday = 4; - break; - case Weekday::friday: - tm.tm_wday = 5; - break; - case Weekday::saturday: - tm.tm_wday = 6; - break; - } - tm.tm_yday = GetYearDay(cs) - 1; - tm.tm_isdst = ci.is_dst ? 1 : 0; - - return tm; -} - + struct tm tm = {}; + + const auto ci = tz.At(t); + const auto& cs = ci.cs; + tm.tm_sec = cs.second(); + tm.tm_min = cs.minute(); + tm.tm_hour = cs.hour(); + tm.tm_mday = cs.day(); + tm.tm_mon = cs.month() - 1; + + // Saturates tm.tm_year in cases of over/underflow, accounting for the fact + // that tm.tm_year is years since 1900. + if (cs.year() < std::numeric_limits<int>::min() + 1900) { + tm.tm_year = std::numeric_limits<int>::min(); + } else if (cs.year() > std::numeric_limits<int>::max()) { + tm.tm_year = std::numeric_limits<int>::max() - 1900; + } else { + tm.tm_year = static_cast<int>(cs.year() - 1900); + } + + switch (GetWeekday(cs)) { + case Weekday::sunday: + tm.tm_wday = 0; + break; + case Weekday::monday: + tm.tm_wday = 1; + break; + case Weekday::tuesday: + tm.tm_wday = 2; + break; + case Weekday::wednesday: + tm.tm_wday = 3; + break; + case Weekday::thursday: + tm.tm_wday = 4; + break; + case Weekday::friday: + tm.tm_wday = 5; + break; + case Weekday::saturday: + tm.tm_wday = 6; + break; + } + tm.tm_yday = GetYearDay(cs) - 1; + tm.tm_isdst = ci.is_dst ? 1 : 0; + + return tm; +} + ABSL_NAMESPACE_END } // namespace y_absl diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/time.h b/contrib/restricted/abseil-cpp-tstring/y_absl/time/time.h index 70980887b1..16150ad3b6 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/time.h +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/time.h @@ -1,199 +1,199 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------- -// File: time.h -// ----------------------------------------------------------------------------- -// -// This header file defines abstractions for computing with absolute points -// in time, durations of time, and formatting and parsing time within a given -// time zone. The following abstractions are defined: -// +// Copyright 2017 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------- +// File: time.h +// ----------------------------------------------------------------------------- +// +// This header file defines abstractions for computing with absolute points +// in time, durations of time, and formatting and parsing time within a given +// time zone. The following abstractions are defined: +// // * `y_absl::Time` defines an absolute, specific instance in time // * `y_absl::Duration` defines a signed, fixed-length span of time // * `y_absl::TimeZone` defines geopolitical time zone regions (as collected -// within the IANA Time Zone database (https://www.iana.org/time-zones)). -// -// Note: Absolute times are distinct from civil times, which refer to the -// human-scale time commonly represented by `YYYY-MM-DD hh:mm:ss`. The mapping -// between absolute and civil times can be specified by use of time zones +// within the IANA Time Zone database (https://www.iana.org/time-zones)). +// +// Note: Absolute times are distinct from civil times, which refer to the +// human-scale time commonly represented by `YYYY-MM-DD hh:mm:ss`. The mapping +// between absolute and civil times can be specified by use of time zones // (`y_absl::TimeZone` within this API). That is: -// -// Civil Time = F(Absolute Time, Time Zone) -// Absolute Time = G(Civil Time, Time Zone) -// -// See civil_time.h for abstractions related to constructing and manipulating -// civil time. -// -// Example: -// +// +// Civil Time = F(Absolute Time, Time Zone) +// Absolute Time = G(Civil Time, Time Zone) +// +// See civil_time.h for abstractions related to constructing and manipulating +// civil time. +// +// Example: +// // y_absl::TimeZone nyc; -// // LoadTimeZone() may fail so it's always better to check for success. +// // LoadTimeZone() may fail so it's always better to check for success. // if (!y_absl::LoadTimeZone("America/New_York", &nyc)) { -// // handle error case -// } -// -// // My flight leaves NYC on Jan 2, 2017 at 03:04:05 +// // handle error case +// } +// +// // My flight leaves NYC on Jan 2, 2017 at 03:04:05 // y_absl::CivilSecond cs(2017, 1, 2, 3, 4, 5); // y_absl::Time takeoff = y_absl::FromCivil(cs, nyc); -// +// // y_absl::Duration flight_duration = y_absl::Hours(21) + y_absl::Minutes(35); // y_absl::Time landing = takeoff + flight_duration; -// +// // y_absl::TimeZone syd; // if (!y_absl::LoadTimeZone("Australia/Sydney", &syd)) { -// // handle error case -// } +// // handle error case +// } // TString s = y_absl::FormatTime( -// "My flight will land in Sydney on %Y-%m-%d at %H:%M:%S", -// landing, syd); - -#ifndef ABSL_TIME_TIME_H_ -#define ABSL_TIME_TIME_H_ - -#if !defined(_MSC_VER) -#include <sys/time.h> -#else -// We don't include `winsock2.h` because it drags in `windows.h` and friends, -// and they define conflicting macros like OPAQUE, ERROR, and more. This has the -// potential to break Abseil users. -// -// Instead we only forward declare `timeval` and require Windows users include -// `winsock2.h` themselves. This is both inconsistent and troublesome, but so is -// including 'windows.h' so we are picking the lesser of two evils here. -struct timeval; -#endif -#include <chrono> // NOLINT(build/c++11) -#include <cmath> -#include <cstdint> -#include <ctime> -#include <ostream> +// "My flight will land in Sydney on %Y-%m-%d at %H:%M:%S", +// landing, syd); + +#ifndef ABSL_TIME_TIME_H_ +#define ABSL_TIME_TIME_H_ + +#if !defined(_MSC_VER) +#include <sys/time.h> +#else +// We don't include `winsock2.h` because it drags in `windows.h` and friends, +// and they define conflicting macros like OPAQUE, ERROR, and more. This has the +// potential to break Abseil users. +// +// Instead we only forward declare `timeval` and require Windows users include +// `winsock2.h` themselves. This is both inconsistent and troublesome, but so is +// including 'windows.h' so we are picking the lesser of two evils here. +struct timeval; +#endif +#include <chrono> // NOLINT(build/c++11) +#include <cmath> +#include <cstdint> +#include <ctime> +#include <ostream> #include <util/generic/string.h> -#include <type_traits> -#include <utility> - +#include <type_traits> +#include <utility> + #include "y_absl/base/macros.h" #include "y_absl/strings/string_view.h" #include "y_absl/time/civil_time.h" #include "y_absl/time/internal/cctz/include/cctz/time_zone.h" - + namespace y_absl { ABSL_NAMESPACE_BEGIN - -class Duration; // Defined below -class Time; // Defined below -class TimeZone; // Defined below - -namespace time_internal { -int64_t IDivDuration(bool satq, Duration num, Duration den, Duration* rem); -constexpr Time FromUnixDuration(Duration d); -constexpr Duration ToUnixDuration(Time t); -constexpr int64_t GetRepHi(Duration d); -constexpr uint32_t GetRepLo(Duration d); -constexpr Duration MakeDuration(int64_t hi, uint32_t lo); -constexpr Duration MakeDuration(int64_t hi, int64_t lo); -inline Duration MakePosDoubleDuration(double n); -constexpr int64_t kTicksPerNanosecond = 4; -constexpr int64_t kTicksPerSecond = 1000 * 1000 * 1000 * kTicksPerNanosecond; -template <std::intmax_t N> -constexpr Duration FromInt64(int64_t v, std::ratio<1, N>); -constexpr Duration FromInt64(int64_t v, std::ratio<60>); -constexpr Duration FromInt64(int64_t v, std::ratio<3600>); -template <typename T> -using EnableIfIntegral = typename std::enable_if< - std::is_integral<T>::value || std::is_enum<T>::value, int>::type; -template <typename T> -using EnableIfFloat = - typename std::enable_if<std::is_floating_point<T>::value, int>::type; -} // namespace time_internal - -// Duration -// + +class Duration; // Defined below +class Time; // Defined below +class TimeZone; // Defined below + +namespace time_internal { +int64_t IDivDuration(bool satq, Duration num, Duration den, Duration* rem); +constexpr Time FromUnixDuration(Duration d); +constexpr Duration ToUnixDuration(Time t); +constexpr int64_t GetRepHi(Duration d); +constexpr uint32_t GetRepLo(Duration d); +constexpr Duration MakeDuration(int64_t hi, uint32_t lo); +constexpr Duration MakeDuration(int64_t hi, int64_t lo); +inline Duration MakePosDoubleDuration(double n); +constexpr int64_t kTicksPerNanosecond = 4; +constexpr int64_t kTicksPerSecond = 1000 * 1000 * 1000 * kTicksPerNanosecond; +template <std::intmax_t N> +constexpr Duration FromInt64(int64_t v, std::ratio<1, N>); +constexpr Duration FromInt64(int64_t v, std::ratio<60>); +constexpr Duration FromInt64(int64_t v, std::ratio<3600>); +template <typename T> +using EnableIfIntegral = typename std::enable_if< + std::is_integral<T>::value || std::is_enum<T>::value, int>::type; +template <typename T> +using EnableIfFloat = + typename std::enable_if<std::is_floating_point<T>::value, int>::type; +} // namespace time_internal + +// Duration +// // The `y_absl::Duration` class represents a signed, fixed-length span of time. -// A `Duration` is generated using a unit-specific factory function, or is +// A `Duration` is generated using a unit-specific factory function, or is // the result of subtracting one `y_absl::Time` from another. Durations behave -// like unit-safe integers and they support all the natural integer-like -// arithmetic operations. Arithmetic overflows and saturates at +/- infinity. -// `Duration` should be passed by value rather than const reference. -// -// Factory functions `Nanoseconds()`, `Microseconds()`, `Milliseconds()`, -// `Seconds()`, `Minutes()`, `Hours()` and `InfiniteDuration()` allow for -// creation of constexpr `Duration` values -// -// Examples: -// +// like unit-safe integers and they support all the natural integer-like +// arithmetic operations. Arithmetic overflows and saturates at +/- infinity. +// `Duration` should be passed by value rather than const reference. +// +// Factory functions `Nanoseconds()`, `Microseconds()`, `Milliseconds()`, +// `Seconds()`, `Minutes()`, `Hours()` and `InfiniteDuration()` allow for +// creation of constexpr `Duration` values +// +// Examples: +// // constexpr y_absl::Duration ten_ns = y_absl::Nanoseconds(10); // constexpr y_absl::Duration min = y_absl::Minutes(1); // constexpr y_absl::Duration hour = y_absl::Hours(1); // y_absl::Duration dur = 60 * min; // dur == hour // y_absl::Duration half_sec = y_absl::Milliseconds(500); // y_absl::Duration quarter_sec = 0.25 * y_absl::Seconds(1); -// -// `Duration` values can be easily converted to an integral number of units -// using the division operator. -// -// Example: -// +// +// `Duration` values can be easily converted to an integral number of units +// using the division operator. +// +// Example: +// // constexpr y_absl::Duration dur = y_absl::Milliseconds(1500); // int64_t ns = dur / y_absl::Nanoseconds(1); // ns == 1500000000 // int64_t ms = dur / y_absl::Milliseconds(1); // ms == 1500 // int64_t sec = dur / y_absl::Seconds(1); // sec == 1 (subseconds truncated) // int64_t min = dur / y_absl::Minutes(1); // min == 0 -// -// See the `IDivDuration()` and `FDivDuration()` functions below for details on -// how to access the fractional parts of the quotient. -// -// Alternatively, conversions can be performed using helpers such as -// `ToInt64Microseconds()` and `ToDoubleSeconds()`. -class Duration { - public: - // Value semantics. - constexpr Duration() : rep_hi_(0), rep_lo_(0) {} // zero-length duration - - // Copyable. -#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1910 - // Explicitly defining the constexpr copy constructor avoids an MSVC bug. - constexpr Duration(const Duration& d) - : rep_hi_(d.rep_hi_), rep_lo_(d.rep_lo_) {} -#else - constexpr Duration(const Duration& d) = default; -#endif - Duration& operator=(const Duration& d) = default; - - // Compound assignment operators. - Duration& operator+=(Duration d); - Duration& operator-=(Duration d); - Duration& operator*=(int64_t r); - Duration& operator*=(double r); - Duration& operator/=(int64_t r); - Duration& operator/=(double r); - Duration& operator%=(Duration rhs); - - // Overloads that forward to either the int64_t or double overloads above. - // Integer operands must be representable as int64_t. +// +// See the `IDivDuration()` and `FDivDuration()` functions below for details on +// how to access the fractional parts of the quotient. +// +// Alternatively, conversions can be performed using helpers such as +// `ToInt64Microseconds()` and `ToDoubleSeconds()`. +class Duration { + public: + // Value semantics. + constexpr Duration() : rep_hi_(0), rep_lo_(0) {} // zero-length duration + + // Copyable. +#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1910 + // Explicitly defining the constexpr copy constructor avoids an MSVC bug. + constexpr Duration(const Duration& d) + : rep_hi_(d.rep_hi_), rep_lo_(d.rep_lo_) {} +#else + constexpr Duration(const Duration& d) = default; +#endif + Duration& operator=(const Duration& d) = default; + + // Compound assignment operators. + Duration& operator+=(Duration d); + Duration& operator-=(Duration d); + Duration& operator*=(int64_t r); + Duration& operator*=(double r); + Duration& operator/=(int64_t r); + Duration& operator/=(double r); + Duration& operator%=(Duration rhs); + + // Overloads that forward to either the int64_t or double overloads above. + // Integer operands must be representable as int64_t. template <typename T, time_internal::EnableIfIntegral<T> = 0> - Duration& operator*=(T r) { - int64_t x = r; - return *this *= x; - } + Duration& operator*=(T r) { + int64_t x = r; + return *this *= x; + } template <typename T, time_internal::EnableIfIntegral<T> = 0> - Duration& operator/=(T r) { - int64_t x = r; - return *this /= x; - } - + Duration& operator/=(T r) { + int64_t x = r; + return *this /= x; + } + template <typename T, time_internal::EnableIfFloat<T> = 0> Duration& operator*=(T r) { double x = r; @@ -206,201 +206,201 @@ class Duration { return *this /= x; } - template <typename H> - friend H AbslHashValue(H h, Duration d) { - return H::combine(std::move(h), d.rep_hi_, d.rep_lo_); - } - - private: - friend constexpr int64_t time_internal::GetRepHi(Duration d); - friend constexpr uint32_t time_internal::GetRepLo(Duration d); - friend constexpr Duration time_internal::MakeDuration(int64_t hi, - uint32_t lo); - constexpr Duration(int64_t hi, uint32_t lo) : rep_hi_(hi), rep_lo_(lo) {} - int64_t rep_hi_; - uint32_t rep_lo_; -}; - -// Relational Operators -constexpr bool operator<(Duration lhs, Duration rhs); -constexpr bool operator>(Duration lhs, Duration rhs) { return rhs < lhs; } -constexpr bool operator>=(Duration lhs, Duration rhs) { return !(lhs < rhs); } -constexpr bool operator<=(Duration lhs, Duration rhs) { return !(rhs < lhs); } -constexpr bool operator==(Duration lhs, Duration rhs); -constexpr bool operator!=(Duration lhs, Duration rhs) { return !(lhs == rhs); } - -// Additive Operators -constexpr Duration operator-(Duration d); -inline Duration operator+(Duration lhs, Duration rhs) { return lhs += rhs; } -inline Duration operator-(Duration lhs, Duration rhs) { return lhs -= rhs; } - -// Multiplicative Operators -// Integer operands must be representable as int64_t. -template <typename T> -Duration operator*(Duration lhs, T rhs) { - return lhs *= rhs; -} -template <typename T> -Duration operator*(T lhs, Duration rhs) { - return rhs *= lhs; -} -template <typename T> -Duration operator/(Duration lhs, T rhs) { - return lhs /= rhs; -} -inline int64_t operator/(Duration lhs, Duration rhs) { - return time_internal::IDivDuration(true, lhs, rhs, - &lhs); // trunc towards zero -} -inline Duration operator%(Duration lhs, Duration rhs) { return lhs %= rhs; } - -// IDivDuration() -// -// Divides a numerator `Duration` by a denominator `Duration`, returning the -// quotient and remainder. The remainder always has the same sign as the -// numerator. The returned quotient and remainder respect the identity: -// -// numerator = denominator * quotient + remainder -// -// Returned quotients are capped to the range of `int64_t`, with the difference -// spilling into the remainder to uphold the above identity. This means that the -// remainder returned could differ from the remainder returned by -// `Duration::operator%` for huge quotients. -// -// See also the notes on `InfiniteDuration()` below regarding the behavior of -// division involving zero and infinite durations. -// -// Example: -// + template <typename H> + friend H AbslHashValue(H h, Duration d) { + return H::combine(std::move(h), d.rep_hi_, d.rep_lo_); + } + + private: + friend constexpr int64_t time_internal::GetRepHi(Duration d); + friend constexpr uint32_t time_internal::GetRepLo(Duration d); + friend constexpr Duration time_internal::MakeDuration(int64_t hi, + uint32_t lo); + constexpr Duration(int64_t hi, uint32_t lo) : rep_hi_(hi), rep_lo_(lo) {} + int64_t rep_hi_; + uint32_t rep_lo_; +}; + +// Relational Operators +constexpr bool operator<(Duration lhs, Duration rhs); +constexpr bool operator>(Duration lhs, Duration rhs) { return rhs < lhs; } +constexpr bool operator>=(Duration lhs, Duration rhs) { return !(lhs < rhs); } +constexpr bool operator<=(Duration lhs, Duration rhs) { return !(rhs < lhs); } +constexpr bool operator==(Duration lhs, Duration rhs); +constexpr bool operator!=(Duration lhs, Duration rhs) { return !(lhs == rhs); } + +// Additive Operators +constexpr Duration operator-(Duration d); +inline Duration operator+(Duration lhs, Duration rhs) { return lhs += rhs; } +inline Duration operator-(Duration lhs, Duration rhs) { return lhs -= rhs; } + +// Multiplicative Operators +// Integer operands must be representable as int64_t. +template <typename T> +Duration operator*(Duration lhs, T rhs) { + return lhs *= rhs; +} +template <typename T> +Duration operator*(T lhs, Duration rhs) { + return rhs *= lhs; +} +template <typename T> +Duration operator/(Duration lhs, T rhs) { + return lhs /= rhs; +} +inline int64_t operator/(Duration lhs, Duration rhs) { + return time_internal::IDivDuration(true, lhs, rhs, + &lhs); // trunc towards zero +} +inline Duration operator%(Duration lhs, Duration rhs) { return lhs %= rhs; } + +// IDivDuration() +// +// Divides a numerator `Duration` by a denominator `Duration`, returning the +// quotient and remainder. The remainder always has the same sign as the +// numerator. The returned quotient and remainder respect the identity: +// +// numerator = denominator * quotient + remainder +// +// Returned quotients are capped to the range of `int64_t`, with the difference +// spilling into the remainder to uphold the above identity. This means that the +// remainder returned could differ from the remainder returned by +// `Duration::operator%` for huge quotients. +// +// See also the notes on `InfiniteDuration()` below regarding the behavior of +// division involving zero and infinite durations. +// +// Example: +// // constexpr y_absl::Duration a = // y_absl::Seconds(std::numeric_limits<int64_t>::max()); // big // constexpr y_absl::Duration b = y_absl::Nanoseconds(1); // small -// +// // y_absl::Duration rem = a % b; // // rem == y_absl::ZeroDuration() -// -// // Here, q would overflow int64_t, so rem accounts for the difference. +// +// // Here, q would overflow int64_t, so rem accounts for the difference. // int64_t q = y_absl::IDivDuration(a, b, &rem); -// // q == std::numeric_limits<int64_t>::max(), rem == a - b * q -inline int64_t IDivDuration(Duration num, Duration den, Duration* rem) { - return time_internal::IDivDuration(true, num, den, - rem); // trunc towards zero -} - -// FDivDuration() -// -// Divides a `Duration` numerator into a fractional number of units of a -// `Duration` denominator. -// -// See also the notes on `InfiniteDuration()` below regarding the behavior of -// division involving zero and infinite durations. -// -// Example: -// +// // q == std::numeric_limits<int64_t>::max(), rem == a - b * q +inline int64_t IDivDuration(Duration num, Duration den, Duration* rem) { + return time_internal::IDivDuration(true, num, den, + rem); // trunc towards zero +} + +// FDivDuration() +// +// Divides a `Duration` numerator into a fractional number of units of a +// `Duration` denominator. +// +// See also the notes on `InfiniteDuration()` below regarding the behavior of +// division involving zero and infinite durations. +// +// Example: +// // double d = y_absl::FDivDuration(y_absl::Milliseconds(1500), y_absl::Seconds(1)); -// // d == 1.5 -double FDivDuration(Duration num, Duration den); - -// ZeroDuration() -// -// Returns a zero-length duration. This function behaves just like the default -// constructor, but the name helps make the semantics clear at call sites. -constexpr Duration ZeroDuration() { return Duration(); } - -// AbsDuration() -// -// Returns the absolute value of a duration. -inline Duration AbsDuration(Duration d) { - return (d < ZeroDuration()) ? -d : d; -} - -// Trunc() -// -// Truncates a duration (toward zero) to a multiple of a non-zero unit. -// -// Example: -// +// // d == 1.5 +double FDivDuration(Duration num, Duration den); + +// ZeroDuration() +// +// Returns a zero-length duration. This function behaves just like the default +// constructor, but the name helps make the semantics clear at call sites. +constexpr Duration ZeroDuration() { return Duration(); } + +// AbsDuration() +// +// Returns the absolute value of a duration. +inline Duration AbsDuration(Duration d) { + return (d < ZeroDuration()) ? -d : d; +} + +// Trunc() +// +// Truncates a duration (toward zero) to a multiple of a non-zero unit. +// +// Example: +// // y_absl::Duration d = y_absl::Nanoseconds(123456789); // y_absl::Duration a = y_absl::Trunc(d, y_absl::Microseconds(1)); // 123456us -Duration Trunc(Duration d, Duration unit); - -// Floor() -// -// Floors a duration using the passed duration unit to its largest value not -// greater than the duration. -// -// Example: -// +Duration Trunc(Duration d, Duration unit); + +// Floor() +// +// Floors a duration using the passed duration unit to its largest value not +// greater than the duration. +// +// Example: +// // y_absl::Duration d = y_absl::Nanoseconds(123456789); // y_absl::Duration b = y_absl::Floor(d, y_absl::Microseconds(1)); // 123456us -Duration Floor(Duration d, Duration unit); - -// Ceil() -// -// Returns the ceiling of a duration using the passed duration unit to its -// smallest value not less than the duration. -// -// Example: -// +Duration Floor(Duration d, Duration unit); + +// Ceil() +// +// Returns the ceiling of a duration using the passed duration unit to its +// smallest value not less than the duration. +// +// Example: +// // y_absl::Duration d = y_absl::Nanoseconds(123456789); // y_absl::Duration c = y_absl::Ceil(d, y_absl::Microseconds(1)); // 123457us -Duration Ceil(Duration d, Duration unit); - -// InfiniteDuration() -// -// Returns an infinite `Duration`. To get a `Duration` representing negative -// infinity, use `-InfiniteDuration()`. -// -// Duration arithmetic overflows to +/- infinity and saturates. In general, -// arithmetic with `Duration` infinities is similar to IEEE 754 infinities -// except where IEEE 754 NaN would be involved, in which case +/- -// `InfiniteDuration()` is used in place of a "nan" Duration. -// -// Examples: -// +Duration Ceil(Duration d, Duration unit); + +// InfiniteDuration() +// +// Returns an infinite `Duration`. To get a `Duration` representing negative +// infinity, use `-InfiniteDuration()`. +// +// Duration arithmetic overflows to +/- infinity and saturates. In general, +// arithmetic with `Duration` infinities is similar to IEEE 754 infinities +// except where IEEE 754 NaN would be involved, in which case +/- +// `InfiniteDuration()` is used in place of a "nan" Duration. +// +// Examples: +// // constexpr y_absl::Duration inf = y_absl::InfiniteDuration(); // const y_absl::Duration d = ... any finite duration ... -// -// inf == inf + inf -// inf == inf + d -// inf == inf - inf -// -inf == d - inf -// -// inf == d * 1e100 -// inf == inf / 2 -// 0 == d / inf -// INT64_MAX == inf / d -// -// d < inf -// -inf < d -// -// // Division by zero returns infinity, or INT64_MIN/MAX where appropriate. -// inf == d / 0 +// +// inf == inf + inf +// inf == inf + d +// inf == inf - inf +// -inf == d - inf +// +// inf == d * 1e100 +// inf == inf / 2 +// 0 == d / inf +// INT64_MAX == inf / d +// +// d < inf +// -inf < d +// +// // Division by zero returns infinity, or INT64_MIN/MAX where appropriate. +// inf == d / 0 // INT64_MAX == d / y_absl::ZeroDuration() -// -// The examples involving the `/` operator above also apply to `IDivDuration()` -// and `FDivDuration()`. -constexpr Duration InfiniteDuration(); - -// Nanoseconds() -// Microseconds() -// Milliseconds() -// Seconds() -// Minutes() -// Hours() -// -// Factory functions for constructing `Duration` values from an integral number -// of the unit indicated by the factory function's name. The number must be -// representable as int64_t. -// -// NOTE: no "Days()" factory function exists because "a day" is ambiguous. -// Civil days are not always 24 hours long, and a 24-hour duration often does -// not correspond with a civil day. If a 24-hour duration is needed, use +// +// The examples involving the `/` operator above also apply to `IDivDuration()` +// and `FDivDuration()`. +constexpr Duration InfiniteDuration(); + +// Nanoseconds() +// Microseconds() +// Milliseconds() +// Seconds() +// Minutes() +// Hours() +// +// Factory functions for constructing `Duration` values from an integral number +// of the unit indicated by the factory function's name. The number must be +// representable as int64_t. +// +// NOTE: no "Days()" factory function exists because "a day" is ambiguous. +// Civil days are not always 24 hours long, and a 24-hour duration often does +// not correspond with a civil day. If a 24-hour duration is needed, use // `y_absl::Hours(24)`. If you actually want a civil day, use y_absl::CivilDay -// from civil_time.h. -// -// Example: -// +// from civil_time.h. +// +// Example: +// // y_absl::Duration a = y_absl::Seconds(60); // y_absl::Duration b = y_absl::Minutes(1); // b == a template <typename T, time_internal::EnableIfIntegral<T> = 0> @@ -427,65 +427,65 @@ template <typename T, time_internal::EnableIfIntegral<T> = 0> constexpr Duration Hours(T n) { return time_internal::FromInt64(n, std::ratio<3600>{}); } - -// Factory overloads for constructing `Duration` values from a floating-point -// number of the unit indicated by the factory function's name. These functions -// exist for convenience, but they are not as efficient as the integral -// factories, which should be preferred. -// -// Example: -// + +// Factory overloads for constructing `Duration` values from a floating-point +// number of the unit indicated by the factory function's name. These functions +// exist for convenience, but they are not as efficient as the integral +// factories, which should be preferred. +// +// Example: +// // auto a = y_absl::Seconds(1.5); // OK // auto b = y_absl::Milliseconds(1500); // BETTER -template <typename T, time_internal::EnableIfFloat<T> = 0> -Duration Nanoseconds(T n) { - return n * Nanoseconds(1); -} -template <typename T, time_internal::EnableIfFloat<T> = 0> -Duration Microseconds(T n) { - return n * Microseconds(1); -} -template <typename T, time_internal::EnableIfFloat<T> = 0> -Duration Milliseconds(T n) { - return n * Milliseconds(1); -} -template <typename T, time_internal::EnableIfFloat<T> = 0> -Duration Seconds(T n) { - if (n >= 0) { // Note: `NaN >= 0` is false. - if (n >= static_cast<T>((std::numeric_limits<int64_t>::max)())) { - return InfiniteDuration(); - } - return time_internal::MakePosDoubleDuration(n); - } else { - if (std::isnan(n)) - return std::signbit(n) ? -InfiniteDuration() : InfiniteDuration(); - if (n <= (std::numeric_limits<int64_t>::min)()) return -InfiniteDuration(); - return -time_internal::MakePosDoubleDuration(-n); - } -} -template <typename T, time_internal::EnableIfFloat<T> = 0> -Duration Minutes(T n) { - return n * Minutes(1); -} -template <typename T, time_internal::EnableIfFloat<T> = 0> -Duration Hours(T n) { - return n * Hours(1); -} - -// ToInt64Nanoseconds() -// ToInt64Microseconds() -// ToInt64Milliseconds() -// ToInt64Seconds() -// ToInt64Minutes() -// ToInt64Hours() -// -// Helper functions that convert a Duration to an integral count of the +template <typename T, time_internal::EnableIfFloat<T> = 0> +Duration Nanoseconds(T n) { + return n * Nanoseconds(1); +} +template <typename T, time_internal::EnableIfFloat<T> = 0> +Duration Microseconds(T n) { + return n * Microseconds(1); +} +template <typename T, time_internal::EnableIfFloat<T> = 0> +Duration Milliseconds(T n) { + return n * Milliseconds(1); +} +template <typename T, time_internal::EnableIfFloat<T> = 0> +Duration Seconds(T n) { + if (n >= 0) { // Note: `NaN >= 0` is false. + if (n >= static_cast<T>((std::numeric_limits<int64_t>::max)())) { + return InfiniteDuration(); + } + return time_internal::MakePosDoubleDuration(n); + } else { + if (std::isnan(n)) + return std::signbit(n) ? -InfiniteDuration() : InfiniteDuration(); + if (n <= (std::numeric_limits<int64_t>::min)()) return -InfiniteDuration(); + return -time_internal::MakePosDoubleDuration(-n); + } +} +template <typename T, time_internal::EnableIfFloat<T> = 0> +Duration Minutes(T n) { + return n * Minutes(1); +} +template <typename T, time_internal::EnableIfFloat<T> = 0> +Duration Hours(T n) { + return n * Hours(1); +} + +// ToInt64Nanoseconds() +// ToInt64Microseconds() +// ToInt64Milliseconds() +// ToInt64Seconds() +// ToInt64Minutes() +// ToInt64Hours() +// +// Helper functions that convert a Duration to an integral count of the // indicated unit. These return the same results as the `IDivDuration()` // function, though they usually do so more efficiently; see the // documentation of `IDivDuration()` for details about overflow, etc. -// -// Example: -// +// +// Example: +// // y_absl::Duration d = y_absl::Milliseconds(1500); // int64_t isec = y_absl::ToInt64Seconds(d); // isec == 1 ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Nanoseconds(Duration d); @@ -494,20 +494,20 @@ ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Milliseconds(Duration d); ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Seconds(Duration d); ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Minutes(Duration d); ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Hours(Duration d); - -// ToDoubleNanoSeconds() -// ToDoubleMicroseconds() -// ToDoubleMilliseconds() -// ToDoubleSeconds() -// ToDoubleMinutes() -// ToDoubleHours() -// -// Helper functions that convert a Duration to a floating point count of the -// indicated unit. These functions are shorthand for the `FDivDuration()` -// function above; see its documentation for details about overflow, etc. -// -// Example: -// + +// ToDoubleNanoSeconds() +// ToDoubleMicroseconds() +// ToDoubleMilliseconds() +// ToDoubleSeconds() +// ToDoubleMinutes() +// ToDoubleHours() +// +// Helper functions that convert a Duration to a floating point count of the +// indicated unit. These functions are shorthand for the `FDivDuration()` +// function above; see its documentation for details about overflow, etc. +// +// Example: +// // y_absl::Duration d = y_absl::Milliseconds(1500); // double dsec = y_absl::ToDoubleSeconds(d); // dsec == 1.5 ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleNanoseconds(Duration d); @@ -516,67 +516,67 @@ ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleMilliseconds(Duration d); ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleSeconds(Duration d); ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleMinutes(Duration d); ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleHours(Duration d); - -// FromChrono() -// + +// FromChrono() +// // Converts any of the pre-defined std::chrono durations to an y_absl::Duration. -// -// Example: -// -// std::chrono::milliseconds ms(123); +// +// Example: +// +// std::chrono::milliseconds ms(123); // y_absl::Duration d = y_absl::FromChrono(ms); -constexpr Duration FromChrono(const std::chrono::nanoseconds& d); -constexpr Duration FromChrono(const std::chrono::microseconds& d); -constexpr Duration FromChrono(const std::chrono::milliseconds& d); -constexpr Duration FromChrono(const std::chrono::seconds& d); -constexpr Duration FromChrono(const std::chrono::minutes& d); -constexpr Duration FromChrono(const std::chrono::hours& d); - -// ToChronoNanoseconds() -// ToChronoMicroseconds() -// ToChronoMilliseconds() -// ToChronoSeconds() -// ToChronoMinutes() -// ToChronoHours() -// +constexpr Duration FromChrono(const std::chrono::nanoseconds& d); +constexpr Duration FromChrono(const std::chrono::microseconds& d); +constexpr Duration FromChrono(const std::chrono::milliseconds& d); +constexpr Duration FromChrono(const std::chrono::seconds& d); +constexpr Duration FromChrono(const std::chrono::minutes& d); +constexpr Duration FromChrono(const std::chrono::hours& d); + +// ToChronoNanoseconds() +// ToChronoMicroseconds() +// ToChronoMilliseconds() +// ToChronoSeconds() +// ToChronoMinutes() +// ToChronoHours() +// // Converts an y_absl::Duration to any of the pre-defined std::chrono durations. -// If overflow would occur, the returned value will saturate at the min/max -// chrono duration value instead. -// -// Example: -// +// If overflow would occur, the returned value will saturate at the min/max +// chrono duration value instead. +// +// Example: +// // y_absl::Duration d = y_absl::Microseconds(123); // auto x = y_absl::ToChronoMicroseconds(d); // auto y = y_absl::ToChronoNanoseconds(d); // x == y // auto z = y_absl::ToChronoSeconds(y_absl::InfiniteDuration()); -// // z == std::chrono::seconds::max() -std::chrono::nanoseconds ToChronoNanoseconds(Duration d); -std::chrono::microseconds ToChronoMicroseconds(Duration d); -std::chrono::milliseconds ToChronoMilliseconds(Duration d); -std::chrono::seconds ToChronoSeconds(Duration d); -std::chrono::minutes ToChronoMinutes(Duration d); -std::chrono::hours ToChronoHours(Duration d); - -// FormatDuration() -// -// Returns a string representing the duration in the form "72h3m0.5s". -// Returns "inf" or "-inf" for +/- `InfiniteDuration()`. +// // z == std::chrono::seconds::max() +std::chrono::nanoseconds ToChronoNanoseconds(Duration d); +std::chrono::microseconds ToChronoMicroseconds(Duration d); +std::chrono::milliseconds ToChronoMilliseconds(Duration d); +std::chrono::seconds ToChronoSeconds(Duration d); +std::chrono::minutes ToChronoMinutes(Duration d); +std::chrono::hours ToChronoHours(Duration d); + +// FormatDuration() +// +// Returns a string representing the duration in the form "72h3m0.5s". +// Returns "inf" or "-inf" for +/- `InfiniteDuration()`. TString FormatDuration(Duration d); - -// Output stream operator. -inline std::ostream& operator<<(std::ostream& os, Duration d) { - return os << FormatDuration(d); -} - -// ParseDuration() -// -// Parses a duration string consisting of a possibly signed sequence of -// decimal numbers, each with an optional fractional part and a unit -// suffix. The valid suffixes are "ns", "us" "ms", "s", "m", and "h". -// Simple examples include "300ms", "-1.5h", and "2h45m". Parses "0" as -// `ZeroDuration()`. Parses "inf" and "-inf" as +/- `InfiniteDuration()`. + +// Output stream operator. +inline std::ostream& operator<<(std::ostream& os, Duration d) { + return os << FormatDuration(d); +} + +// ParseDuration() +// +// Parses a duration string consisting of a possibly signed sequence of +// decimal numbers, each with an optional fractional part and a unit +// suffix. The valid suffixes are "ns", "us" "ms", "s", "m", and "h". +// Simple examples include "300ms", "-1.5h", and "2h45m". Parses "0" as +// `ZeroDuration()`. Parses "inf" and "-inf" as +/- `InfiniteDuration()`. bool ParseDuration(y_absl::string_view dur_string, Duration* d); - + // AbslParseFlag() // // Parses a command-line flag string representation `text` into a a Duration @@ -591,280 +591,280 @@ bool AbslParseFlag(y_absl::string_view text, Duration* dst, TString* error); // the format specified by `y_absl::ParseDuration()`. TString AbslUnparseFlag(Duration d); -ABSL_DEPRECATED("Use AbslParseFlag() instead.") +ABSL_DEPRECATED("Use AbslParseFlag() instead.") bool ParseFlag(const TString& text, Duration* dst, TString* error); -ABSL_DEPRECATED("Use AbslUnparseFlag() instead.") +ABSL_DEPRECATED("Use AbslUnparseFlag() instead.") TString UnparseFlag(Duration d); - -// Time -// + +// Time +// // An `y_absl::Time` represents a specific instant in time. Arithmetic operators -// are provided for naturally expressing time calculations. Instances are +// are provided for naturally expressing time calculations. Instances are // created using `y_absl::Now()` and the `y_absl::From*()` factory functions that -// accept the gamut of other time representations. Formatting and parsing +// accept the gamut of other time representations. Formatting and parsing // functions are provided for conversion to and from strings. `y_absl::Time` -// should be passed by value rather than const reference. -// +// should be passed by value rather than const reference. +// // `y_absl::Time` assumes there are 60 seconds in a minute, which means the -// underlying time scales must be "smeared" to eliminate leap seconds. -// See https://developers.google.com/time/smear. -// +// underlying time scales must be "smeared" to eliminate leap seconds. +// See https://developers.google.com/time/smear. +// // Even though `y_absl::Time` supports a wide range of timestamps, exercise // caution when using values in the distant past. `y_absl::Time` uses the -// Proleptic Gregorian calendar, which extends the Gregorian calendar backward -// to dates before its introduction in 1582. -// See https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar -// for more information. Use the ICU calendar classes to convert a date in -// some other calendar (http://userguide.icu-project.org/datetime/calendar). -// -// Similarly, standardized time zones are a reasonably recent innovation, with -// the Greenwich prime meridian being established in 1884. The TZ database -// itself does not profess accurate offsets for timestamps prior to 1970. The -// breakdown of future timestamps is subject to the whim of regional -// governments. -// +// Proleptic Gregorian calendar, which extends the Gregorian calendar backward +// to dates before its introduction in 1582. +// See https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar +// for more information. Use the ICU calendar classes to convert a date in +// some other calendar (http://userguide.icu-project.org/datetime/calendar). +// +// Similarly, standardized time zones are a reasonably recent innovation, with +// the Greenwich prime meridian being established in 1884. The TZ database +// itself does not profess accurate offsets for timestamps prior to 1970. The +// breakdown of future timestamps is subject to the whim of regional +// governments. +// // The `y_absl::Time` class represents an instant in time as a count of clock -// ticks of some granularity (resolution) from some starting point (epoch). -// +// ticks of some granularity (resolution) from some starting point (epoch). +// // `y_absl::Time` uses a resolution that is high enough to avoid loss in -// precision, and a range that is wide enough to avoid overflow, when -// converting between tick counts in most Google time scales (i.e., resolution -// of at least one nanosecond, and range +/-100 billion years). Conversions -// between the time scales are performed by truncating (towards negative -// infinity) to the nearest representable point. -// -// Examples: -// +// precision, and a range that is wide enough to avoid overflow, when +// converting between tick counts in most Google time scales (i.e., resolution +// of at least one nanosecond, and range +/-100 billion years). Conversions +// between the time scales are performed by truncating (towards negative +// infinity) to the nearest representable point. +// +// Examples: +// // y_absl::Time t1 = ...; // y_absl::Time t2 = t1 + y_absl::Minutes(2); // y_absl::Duration d = t2 - t1; // == y_absl::Minutes(2) -// -class Time { - public: - // Value semantics. - - // Returns the Unix epoch. However, those reading your code may not know - // or expect the Unix epoch as the default value, so make your code more - // readable by explicitly initializing all instances before use. - // - // Example: +// +class Time { + public: + // Value semantics. + + // Returns the Unix epoch. However, those reading your code may not know + // or expect the Unix epoch as the default value, so make your code more + // readable by explicitly initializing all instances before use. + // + // Example: // y_absl::Time t = y_absl::UnixEpoch(); // y_absl::Time t = y_absl::Now(); // y_absl::Time t = y_absl::TimeFromTimeval(tv); // y_absl::Time t = y_absl::InfinitePast(); - constexpr Time() = default; - - // Copyable. - constexpr Time(const Time& t) = default; - Time& operator=(const Time& t) = default; - - // Assignment operators. - Time& operator+=(Duration d) { - rep_ += d; - return *this; - } - Time& operator-=(Duration d) { - rep_ -= d; - return *this; - } - - // Time::Breakdown - // - // The calendar and wall-clock (aka "civil time") components of an + constexpr Time() = default; + + // Copyable. + constexpr Time(const Time& t) = default; + Time& operator=(const Time& t) = default; + + // Assignment operators. + Time& operator+=(Duration d) { + rep_ += d; + return *this; + } + Time& operator-=(Duration d) { + rep_ -= d; + return *this; + } + + // Time::Breakdown + // + // The calendar and wall-clock (aka "civil time") components of an // `y_absl::Time` in a certain `y_absl::TimeZone`. This struct is not - // intended to represent an instant in time. So, rather than passing + // intended to represent an instant in time. So, rather than passing // a `Time::Breakdown` to a function, pass an `y_absl::Time` and an // `y_absl::TimeZone`. - // + // // Deprecated. Use `y_absl::TimeZone::CivilInfo`. - struct - Breakdown { + struct + Breakdown { int64_t year; // year (e.g., 2013) - int month; // month of year [1:12] - int day; // day of month [1:31] - int hour; // hour of day [0:23] - int minute; // minute of hour [0:59] - int second; // second of minute [0:59] - Duration subsecond; // [Seconds(0):Seconds(1)) if finite - int weekday; // 1==Mon, ..., 7=Sun - int yearday; // day of year [1:366] - - // Note: The following fields exist for backward compatibility - // with older APIs. Accessing these fields directly is a sign of - // imprudent logic in the calling code. Modern time-related code - // should only access this data indirectly by way of FormatTime(). - // These fields are undefined for InfiniteFuture() and InfinitePast(). - int offset; // seconds east of UTC - bool is_dst; // is offset non-standard? - const char* zone_abbr; // time-zone abbreviation (e.g., "PST") - }; - - // Time::In() - // - // Returns the breakdown of this instant in the given TimeZone. - // + int month; // month of year [1:12] + int day; // day of month [1:31] + int hour; // hour of day [0:23] + int minute; // minute of hour [0:59] + int second; // second of minute [0:59] + Duration subsecond; // [Seconds(0):Seconds(1)) if finite + int weekday; // 1==Mon, ..., 7=Sun + int yearday; // day of year [1:366] + + // Note: The following fields exist for backward compatibility + // with older APIs. Accessing these fields directly is a sign of + // imprudent logic in the calling code. Modern time-related code + // should only access this data indirectly by way of FormatTime(). + // These fields are undefined for InfiniteFuture() and InfinitePast(). + int offset; // seconds east of UTC + bool is_dst; // is offset non-standard? + const char* zone_abbr; // time-zone abbreviation (e.g., "PST") + }; + + // Time::In() + // + // Returns the breakdown of this instant in the given TimeZone. + // // Deprecated. Use `y_absl::TimeZone::At(Time)`. - Breakdown In(TimeZone tz) const; - - template <typename H> - friend H AbslHashValue(H h, Time t) { - return H::combine(std::move(h), t.rep_); - } - - private: - friend constexpr Time time_internal::FromUnixDuration(Duration d); - friend constexpr Duration time_internal::ToUnixDuration(Time t); - friend constexpr bool operator<(Time lhs, Time rhs); - friend constexpr bool operator==(Time lhs, Time rhs); - friend Duration operator-(Time lhs, Time rhs); - friend constexpr Time UniversalEpoch(); - friend constexpr Time InfiniteFuture(); - friend constexpr Time InfinitePast(); - constexpr explicit Time(Duration rep) : rep_(rep) {} - Duration rep_; -}; - -// Relational Operators -constexpr bool operator<(Time lhs, Time rhs) { return lhs.rep_ < rhs.rep_; } -constexpr bool operator>(Time lhs, Time rhs) { return rhs < lhs; } -constexpr bool operator>=(Time lhs, Time rhs) { return !(lhs < rhs); } -constexpr bool operator<=(Time lhs, Time rhs) { return !(rhs < lhs); } -constexpr bool operator==(Time lhs, Time rhs) { return lhs.rep_ == rhs.rep_; } -constexpr bool operator!=(Time lhs, Time rhs) { return !(lhs == rhs); } - -// Additive Operators -inline Time operator+(Time lhs, Duration rhs) { return lhs += rhs; } -inline Time operator+(Duration lhs, Time rhs) { return rhs += lhs; } -inline Time operator-(Time lhs, Duration rhs) { return lhs -= rhs; } -inline Duration operator-(Time lhs, Time rhs) { return lhs.rep_ - rhs.rep_; } - -// UnixEpoch() -// + Breakdown In(TimeZone tz) const; + + template <typename H> + friend H AbslHashValue(H h, Time t) { + return H::combine(std::move(h), t.rep_); + } + + private: + friend constexpr Time time_internal::FromUnixDuration(Duration d); + friend constexpr Duration time_internal::ToUnixDuration(Time t); + friend constexpr bool operator<(Time lhs, Time rhs); + friend constexpr bool operator==(Time lhs, Time rhs); + friend Duration operator-(Time lhs, Time rhs); + friend constexpr Time UniversalEpoch(); + friend constexpr Time InfiniteFuture(); + friend constexpr Time InfinitePast(); + constexpr explicit Time(Duration rep) : rep_(rep) {} + Duration rep_; +}; + +// Relational Operators +constexpr bool operator<(Time lhs, Time rhs) { return lhs.rep_ < rhs.rep_; } +constexpr bool operator>(Time lhs, Time rhs) { return rhs < lhs; } +constexpr bool operator>=(Time lhs, Time rhs) { return !(lhs < rhs); } +constexpr bool operator<=(Time lhs, Time rhs) { return !(rhs < lhs); } +constexpr bool operator==(Time lhs, Time rhs) { return lhs.rep_ == rhs.rep_; } +constexpr bool operator!=(Time lhs, Time rhs) { return !(lhs == rhs); } + +// Additive Operators +inline Time operator+(Time lhs, Duration rhs) { return lhs += rhs; } +inline Time operator+(Duration lhs, Time rhs) { return rhs += lhs; } +inline Time operator-(Time lhs, Duration rhs) { return lhs -= rhs; } +inline Duration operator-(Time lhs, Time rhs) { return lhs.rep_ - rhs.rep_; } + +// UnixEpoch() +// // Returns the `y_absl::Time` representing "1970-01-01 00:00:00.0 +0000". -constexpr Time UnixEpoch() { return Time(); } - -// UniversalEpoch() -// +constexpr Time UnixEpoch() { return Time(); } + +// UniversalEpoch() +// // Returns the `y_absl::Time` representing "0001-01-01 00:00:00.0 +0000", the -// epoch of the ICU Universal Time Scale. -constexpr Time UniversalEpoch() { - // 719162 is the number of days from 0001-01-01 to 1970-01-01, - // assuming the Gregorian calendar. - return Time(time_internal::MakeDuration(-24 * 719162 * int64_t{3600}, 0U)); -} - -// InfiniteFuture() -// +// epoch of the ICU Universal Time Scale. +constexpr Time UniversalEpoch() { + // 719162 is the number of days from 0001-01-01 to 1970-01-01, + // assuming the Gregorian calendar. + return Time(time_internal::MakeDuration(-24 * 719162 * int64_t{3600}, 0U)); +} + +// InfiniteFuture() +// // Returns an `y_absl::Time` that is infinitely far in the future. -constexpr Time InfiniteFuture() { - return Time( - time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(), ~0U)); -} - -// InfinitePast() -// +constexpr Time InfiniteFuture() { + return Time( + time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(), ~0U)); +} + +// InfinitePast() +// // Returns an `y_absl::Time` that is infinitely far in the past. -constexpr Time InfinitePast() { - return Time( - time_internal::MakeDuration((std::numeric_limits<int64_t>::min)(), ~0U)); -} - -// FromUnixNanos() -// FromUnixMicros() -// FromUnixMillis() -// FromUnixSeconds() -// FromTimeT() -// FromUDate() -// FromUniversal() -// +constexpr Time InfinitePast() { + return Time( + time_internal::MakeDuration((std::numeric_limits<int64_t>::min)(), ~0U)); +} + +// FromUnixNanos() +// FromUnixMicros() +// FromUnixMillis() +// FromUnixSeconds() +// FromTimeT() +// FromUDate() +// FromUniversal() +// // Creates an `y_absl::Time` from a variety of other representations. -constexpr Time FromUnixNanos(int64_t ns); -constexpr Time FromUnixMicros(int64_t us); -constexpr Time FromUnixMillis(int64_t ms); -constexpr Time FromUnixSeconds(int64_t s); -constexpr Time FromTimeT(time_t t); -Time FromUDate(double udate); -Time FromUniversal(int64_t universal); - -// ToUnixNanos() -// ToUnixMicros() -// ToUnixMillis() -// ToUnixSeconds() -// ToTimeT() -// ToUDate() -// ToUniversal() -// +constexpr Time FromUnixNanos(int64_t ns); +constexpr Time FromUnixMicros(int64_t us); +constexpr Time FromUnixMillis(int64_t ms); +constexpr Time FromUnixSeconds(int64_t s); +constexpr Time FromTimeT(time_t t); +Time FromUDate(double udate); +Time FromUniversal(int64_t universal); + +// ToUnixNanos() +// ToUnixMicros() +// ToUnixMillis() +// ToUnixSeconds() +// ToTimeT() +// ToUDate() +// ToUniversal() +// // Converts an `y_absl::Time` to a variety of other representations. Note that -// these operations round down toward negative infinity where necessary to -// adjust to the resolution of the result type. Beware of possible time_t -// over/underflow in ToTime{T,val,spec}() on 32-bit platforms. -int64_t ToUnixNanos(Time t); -int64_t ToUnixMicros(Time t); -int64_t ToUnixMillis(Time t); -int64_t ToUnixSeconds(Time t); -time_t ToTimeT(Time t); -double ToUDate(Time t); -int64_t ToUniversal(Time t); - -// DurationFromTimespec() -// DurationFromTimeval() -// ToTimespec() -// ToTimeval() -// TimeFromTimespec() -// TimeFromTimeval() -// ToTimespec() -// ToTimeval() -// -// Some APIs use a timespec or a timeval as a Duration (e.g., nanosleep(2) -// and select(2)), while others use them as a Time (e.g. clock_gettime(2) -// and gettimeofday(2)), so conversion functions are provided for both cases. -// The "to timespec/val" direction is easily handled via overloading, but -// for "from timespec/val" the desired type is part of the function name. -Duration DurationFromTimespec(timespec ts); -Duration DurationFromTimeval(timeval tv); -timespec ToTimespec(Duration d); -timeval ToTimeval(Duration d); -Time TimeFromTimespec(timespec ts); -Time TimeFromTimeval(timeval tv); -timespec ToTimespec(Time t); -timeval ToTimeval(Time t); - -// FromChrono() -// +// these operations round down toward negative infinity where necessary to +// adjust to the resolution of the result type. Beware of possible time_t +// over/underflow in ToTime{T,val,spec}() on 32-bit platforms. +int64_t ToUnixNanos(Time t); +int64_t ToUnixMicros(Time t); +int64_t ToUnixMillis(Time t); +int64_t ToUnixSeconds(Time t); +time_t ToTimeT(Time t); +double ToUDate(Time t); +int64_t ToUniversal(Time t); + +// DurationFromTimespec() +// DurationFromTimeval() +// ToTimespec() +// ToTimeval() +// TimeFromTimespec() +// TimeFromTimeval() +// ToTimespec() +// ToTimeval() +// +// Some APIs use a timespec or a timeval as a Duration (e.g., nanosleep(2) +// and select(2)), while others use them as a Time (e.g. clock_gettime(2) +// and gettimeofday(2)), so conversion functions are provided for both cases. +// The "to timespec/val" direction is easily handled via overloading, but +// for "from timespec/val" the desired type is part of the function name. +Duration DurationFromTimespec(timespec ts); +Duration DurationFromTimeval(timeval tv); +timespec ToTimespec(Duration d); +timeval ToTimeval(Duration d); +Time TimeFromTimespec(timespec ts); +Time TimeFromTimeval(timeval tv); +timespec ToTimespec(Time t); +timeval ToTimeval(Time t); + +// FromChrono() +// // Converts a std::chrono::system_clock::time_point to an y_absl::Time. -// -// Example: -// -// auto tp = std::chrono::system_clock::from_time_t(123); +// +// Example: +// +// auto tp = std::chrono::system_clock::from_time_t(123); // y_absl::Time t = y_absl::FromChrono(tp); // // t == y_absl::FromTimeT(123) -Time FromChrono(const std::chrono::system_clock::time_point& tp); - -// ToChronoTime() -// +Time FromChrono(const std::chrono::system_clock::time_point& tp); + +// ToChronoTime() +// // Converts an y_absl::Time to a std::chrono::system_clock::time_point. If -// overflow would occur, the returned value will saturate at the min/max time -// point value instead. -// -// Example: -// +// overflow would occur, the returned value will saturate at the min/max time +// point value instead. +// +// Example: +// // y_absl::Time t = y_absl::FromTimeT(123); // auto tp = y_absl::ToChronoTime(t); -// // tp == std::chrono::system_clock::from_time_t(123); -std::chrono::system_clock::time_point ToChronoTime(Time); - +// // tp == std::chrono::system_clock::from_time_t(123); +std::chrono::system_clock::time_point ToChronoTime(Time); + // AbslParseFlag() -// +// // Parses the command-line flag string representation `text` into a Time value. // Time flags must be specified in a format that matches y_absl::RFC3339_full. // // For example: // -// --start_time=2016-01-02T03:04:05.678+08:00 -// -// Note: A UTC offset (or 'Z' indicating a zero-offset from UTC) is required. -// -// Additionally, if you'd like to specify a time as a count of +// --start_time=2016-01-02T03:04:05.678+08:00 +// +// Note: A UTC offset (or 'Z' indicating a zero-offset from UTC) is required. +// +// Additionally, if you'd like to specify a time as a count of // seconds/milliseconds/etc from the Unix epoch, use an y_absl::Duration flag // and add that duration to y_absl::UnixEpoch() to get an y_absl::Time. bool AbslParseFlag(y_absl::string_view text, Time* t, TString* error); @@ -875,360 +875,360 @@ bool AbslParseFlag(y_absl::string_view text, Time* t, TString* error); // the format specified by `y_absl::ParseTime()`. TString AbslUnparseFlag(Time t); -ABSL_DEPRECATED("Use AbslParseFlag() instead.") +ABSL_DEPRECATED("Use AbslParseFlag() instead.") bool ParseFlag(const TString& text, Time* t, TString* error); -ABSL_DEPRECATED("Use AbslUnparseFlag() instead.") +ABSL_DEPRECATED("Use AbslUnparseFlag() instead.") TString UnparseFlag(Time t); - -// TimeZone -// + +// TimeZone +// // The `y_absl::TimeZone` is an opaque, small, value-type class representing a -// geo-political region within which particular rules are used for converting +// geo-political region within which particular rules are used for converting // between absolute and civil times (see https://git.io/v59Ly). `y_absl::TimeZone` -// values are named using the TZ identifiers from the IANA Time Zone Database, +// values are named using the TZ identifiers from the IANA Time Zone Database, // such as "America/Los_Angeles" or "Australia/Sydney". `y_absl::TimeZone` values // are created from factory functions such as `y_absl::LoadTimeZone()`. Note: -// strings like "PST" and "EDT" are not valid TZ identifiers. Prefer to pass by -// value rather than const reference. -// -// For more on the fundamental concepts of time zones, absolute times, and civil -// times, see https://github.com/google/cctz#fundamental-concepts -// -// Examples: -// +// strings like "PST" and "EDT" are not valid TZ identifiers. Prefer to pass by +// value rather than const reference. +// +// For more on the fundamental concepts of time zones, absolute times, and civil +// times, see https://github.com/google/cctz#fundamental-concepts +// +// Examples: +// // y_absl::TimeZone utc = y_absl::UTCTimeZone(); // y_absl::TimeZone pst = y_absl::FixedTimeZone(-8 * 60 * 60); // y_absl::TimeZone loc = y_absl::LocalTimeZone(); // y_absl::TimeZone lax; // if (!y_absl::LoadTimeZone("America/Los_Angeles", &lax)) { -// // handle error case -// } -// -// See also: -// - https://github.com/google/cctz -// - https://www.iana.org/time-zones -// - https://en.wikipedia.org/wiki/Zoneinfo -class TimeZone { - public: - explicit TimeZone(time_internal::cctz::time_zone tz) : cz_(tz) {} - TimeZone() = default; // UTC, but prefer UTCTimeZone() to be explicit. - - // Copyable. - TimeZone(const TimeZone&) = default; - TimeZone& operator=(const TimeZone&) = default; - - explicit operator time_internal::cctz::time_zone() const { return cz_; } - +// // handle error case +// } +// +// See also: +// - https://github.com/google/cctz +// - https://www.iana.org/time-zones +// - https://en.wikipedia.org/wiki/Zoneinfo +class TimeZone { + public: + explicit TimeZone(time_internal::cctz::time_zone tz) : cz_(tz) {} + TimeZone() = default; // UTC, but prefer UTCTimeZone() to be explicit. + + // Copyable. + TimeZone(const TimeZone&) = default; + TimeZone& operator=(const TimeZone&) = default; + + explicit operator time_internal::cctz::time_zone() const { return cz_; } + TString name() const { return cz_.name(); } - - // TimeZone::CivilInfo - // - // Information about the civil time corresponding to an absolute time. - // This struct is not intended to represent an instant in time. So, rather + + // TimeZone::CivilInfo + // + // Information about the civil time corresponding to an absolute time. + // This struct is not intended to represent an instant in time. So, rather // than passing a `TimeZone::CivilInfo` to a function, pass an `y_absl::Time` // and an `y_absl::TimeZone`. - struct CivilInfo { - CivilSecond cs; - Duration subsecond; - - // Note: The following fields exist for backward compatibility - // with older APIs. Accessing these fields directly is a sign of - // imprudent logic in the calling code. Modern time-related code - // should only access this data indirectly by way of FormatTime(). - // These fields are undefined for InfiniteFuture() and InfinitePast(). - int offset; // seconds east of UTC - bool is_dst; // is offset non-standard? - const char* zone_abbr; // time-zone abbreviation (e.g., "PST") - }; - - // TimeZone::At(Time) - // + struct CivilInfo { + CivilSecond cs; + Duration subsecond; + + // Note: The following fields exist for backward compatibility + // with older APIs. Accessing these fields directly is a sign of + // imprudent logic in the calling code. Modern time-related code + // should only access this data indirectly by way of FormatTime(). + // These fields are undefined for InfiniteFuture() and InfinitePast(). + int offset; // seconds east of UTC + bool is_dst; // is offset non-standard? + const char* zone_abbr; // time-zone abbreviation (e.g., "PST") + }; + + // TimeZone::At(Time) + // // Returns the civil time for this TimeZone at a certain `y_absl::Time`. - // If the input time is infinite, the output civil second will be set to - // CivilSecond::max() or min(), and the subsecond will be infinite. - // - // Example: - // + // If the input time is infinite, the output civil second will be set to + // CivilSecond::max() or min(), and the subsecond will be infinite. + // + // Example: + // // const auto epoch = lax.At(y_absl::UnixEpoch()); - // // epoch.cs == 1969-12-31 16:00:00 + // // epoch.cs == 1969-12-31 16:00:00 // // epoch.subsecond == y_absl::ZeroDuration() - // // epoch.offset == -28800 - // // epoch.is_dst == false - // // epoch.abbr == "PST" - CivilInfo At(Time t) const; - - // TimeZone::TimeInfo - // - // Information about the absolute times corresponding to a civil time. - // (Subseconds must be handled separately.) - // - // It is possible for a caller to pass a civil-time value that does - // not represent an actual or unique instant in time (due to a shift - // in UTC offset in the TimeZone, which results in a discontinuity in - // the civil-time components). For example, a daylight-saving-time - // transition skips or repeats civil times---in the United States, - // March 13, 2011 02:15 never occurred, while November 6, 2011 01:15 - // occurred twice---so requests for such times are not well-defined. + // // epoch.offset == -28800 + // // epoch.is_dst == false + // // epoch.abbr == "PST" + CivilInfo At(Time t) const; + + // TimeZone::TimeInfo + // + // Information about the absolute times corresponding to a civil time. + // (Subseconds must be handled separately.) + // + // It is possible for a caller to pass a civil-time value that does + // not represent an actual or unique instant in time (due to a shift + // in UTC offset in the TimeZone, which results in a discontinuity in + // the civil-time components). For example, a daylight-saving-time + // transition skips or repeats civil times---in the United States, + // March 13, 2011 02:15 never occurred, while November 6, 2011 01:15 + // occurred twice---so requests for such times are not well-defined. // To account for these possibilities, `y_absl::TimeZone::TimeInfo` is // richer than just a single `y_absl::Time`. - struct TimeInfo { - enum CivilKind { - UNIQUE, // the civil time was singular (pre == trans == post) - SKIPPED, // the civil time did not exist (pre >= trans > post) - REPEATED, // the civil time was ambiguous (pre < trans <= post) - } kind; - Time pre; // time calculated using the pre-transition offset - Time trans; // when the civil-time discontinuity occurred - Time post; // time calculated using the post-transition offset - }; - - // TimeZone::At(CivilSecond) - // + struct TimeInfo { + enum CivilKind { + UNIQUE, // the civil time was singular (pre == trans == post) + SKIPPED, // the civil time did not exist (pre >= trans > post) + REPEATED, // the civil time was ambiguous (pre < trans <= post) + } kind; + Time pre; // time calculated using the pre-transition offset + Time trans; // when the civil-time discontinuity occurred + Time post; // time calculated using the post-transition offset + }; + + // TimeZone::At(CivilSecond) + // // Returns an `y_absl::TimeInfo` containing the absolute time(s) for this // TimeZone at an `y_absl::CivilSecond`. When the civil time is skipped or - // repeated, returns times calculated using the pre-transition and post- - // transition UTC offsets, plus the transition time itself. - // - // Examples: - // - // // A unique civil time + // repeated, returns times calculated using the pre-transition and post- + // transition UTC offsets, plus the transition time itself. + // + // Examples: + // + // // A unique civil time // const auto jan01 = lax.At(y_absl::CivilSecond(2011, 1, 1, 0, 0, 0)); - // // jan01.kind == TimeZone::TimeInfo::UNIQUE - // // jan01.pre is 2011-01-01 00:00:00 -0800 - // // jan01.trans is 2011-01-01 00:00:00 -0800 - // // jan01.post is 2011-01-01 00:00:00 -0800 - // - // // A Spring DST transition, when there is a gap in civil time + // // jan01.kind == TimeZone::TimeInfo::UNIQUE + // // jan01.pre is 2011-01-01 00:00:00 -0800 + // // jan01.trans is 2011-01-01 00:00:00 -0800 + // // jan01.post is 2011-01-01 00:00:00 -0800 + // + // // A Spring DST transition, when there is a gap in civil time // const auto mar13 = lax.At(y_absl::CivilSecond(2011, 3, 13, 2, 15, 0)); - // // mar13.kind == TimeZone::TimeInfo::SKIPPED - // // mar13.pre is 2011-03-13 03:15:00 -0700 - // // mar13.trans is 2011-03-13 03:00:00 -0700 - // // mar13.post is 2011-03-13 01:15:00 -0800 - // - // // A Fall DST transition, when civil times are repeated + // // mar13.kind == TimeZone::TimeInfo::SKIPPED + // // mar13.pre is 2011-03-13 03:15:00 -0700 + // // mar13.trans is 2011-03-13 03:00:00 -0700 + // // mar13.post is 2011-03-13 01:15:00 -0800 + // + // // A Fall DST transition, when civil times are repeated // const auto nov06 = lax.At(y_absl::CivilSecond(2011, 11, 6, 1, 15, 0)); - // // nov06.kind == TimeZone::TimeInfo::REPEATED - // // nov06.pre is 2011-11-06 01:15:00 -0700 - // // nov06.trans is 2011-11-06 01:00:00 -0800 - // // nov06.post is 2011-11-06 01:15:00 -0800 - TimeInfo At(CivilSecond ct) const; - - // TimeZone::NextTransition() - // TimeZone::PrevTransition() - // - // Finds the time of the next/previous offset change in this time zone. - // - // By definition, `NextTransition(t, &trans)` returns false when `t` is - // `InfiniteFuture()`, and `PrevTransition(t, &trans)` returns false - // when `t` is `InfinitePast()`. If the zone has no transitions, the - // result will also be false no matter what the argument. - // - // Otherwise, when `t` is `InfinitePast()`, `NextTransition(t, &trans)` - // returns true and sets `trans` to the first recorded transition. Chains - // of calls to `NextTransition()/PrevTransition()` will eventually return - // false, but it is unspecified exactly when `NextTransition(t, &trans)` - // jumps to false, or what time is set by `PrevTransition(t, &trans)` for - // a very distant `t`. - // - // Note: Enumeration of time-zone transitions is for informational purposes - // only. Modern time-related code should not care about when offset changes - // occur. - // - // Example: + // // nov06.kind == TimeZone::TimeInfo::REPEATED + // // nov06.pre is 2011-11-06 01:15:00 -0700 + // // nov06.trans is 2011-11-06 01:00:00 -0800 + // // nov06.post is 2011-11-06 01:15:00 -0800 + TimeInfo At(CivilSecond ct) const; + + // TimeZone::NextTransition() + // TimeZone::PrevTransition() + // + // Finds the time of the next/previous offset change in this time zone. + // + // By definition, `NextTransition(t, &trans)` returns false when `t` is + // `InfiniteFuture()`, and `PrevTransition(t, &trans)` returns false + // when `t` is `InfinitePast()`. If the zone has no transitions, the + // result will also be false no matter what the argument. + // + // Otherwise, when `t` is `InfinitePast()`, `NextTransition(t, &trans)` + // returns true and sets `trans` to the first recorded transition. Chains + // of calls to `NextTransition()/PrevTransition()` will eventually return + // false, but it is unspecified exactly when `NextTransition(t, &trans)` + // jumps to false, or what time is set by `PrevTransition(t, &trans)` for + // a very distant `t`. + // + // Note: Enumeration of time-zone transitions is for informational purposes + // only. Modern time-related code should not care about when offset changes + // occur. + // + // Example: // y_absl::TimeZone nyc; // if (!y_absl::LoadTimeZone("America/New_York", &nyc)) { ... } // const auto now = y_absl::Now(); // auto t = y_absl::InfinitePast(); // y_absl::TimeZone::CivilTransition trans; - // while (t <= now && nyc.NextTransition(t, &trans)) { - // // transition: trans.from -> trans.to - // t = nyc.At(trans.to).trans; - // } - struct CivilTransition { - CivilSecond from; // the civil time we jump from - CivilSecond to; // the civil time we jump to - }; - bool NextTransition(Time t, CivilTransition* trans) const; - bool PrevTransition(Time t, CivilTransition* trans) const; - - template <typename H> - friend H AbslHashValue(H h, TimeZone tz) { - return H::combine(std::move(h), tz.cz_); - } - - private: - friend bool operator==(TimeZone a, TimeZone b) { return a.cz_ == b.cz_; } - friend bool operator!=(TimeZone a, TimeZone b) { return a.cz_ != b.cz_; } - friend std::ostream& operator<<(std::ostream& os, TimeZone tz) { - return os << tz.name(); - } - - time_internal::cctz::time_zone cz_; -}; - -// LoadTimeZone() -// -// Loads the named zone. May perform I/O on the initial load of the named -// zone. If the name is invalid, or some other kind of error occurs, returns -// `false` and `*tz` is set to the UTC time zone. + // while (t <= now && nyc.NextTransition(t, &trans)) { + // // transition: trans.from -> trans.to + // t = nyc.At(trans.to).trans; + // } + struct CivilTransition { + CivilSecond from; // the civil time we jump from + CivilSecond to; // the civil time we jump to + }; + bool NextTransition(Time t, CivilTransition* trans) const; + bool PrevTransition(Time t, CivilTransition* trans) const; + + template <typename H> + friend H AbslHashValue(H h, TimeZone tz) { + return H::combine(std::move(h), tz.cz_); + } + + private: + friend bool operator==(TimeZone a, TimeZone b) { return a.cz_ == b.cz_; } + friend bool operator!=(TimeZone a, TimeZone b) { return a.cz_ != b.cz_; } + friend std::ostream& operator<<(std::ostream& os, TimeZone tz) { + return os << tz.name(); + } + + time_internal::cctz::time_zone cz_; +}; + +// LoadTimeZone() +// +// Loads the named zone. May perform I/O on the initial load of the named +// zone. If the name is invalid, or some other kind of error occurs, returns +// `false` and `*tz` is set to the UTC time zone. inline bool LoadTimeZone(y_absl::string_view name, TimeZone* tz) { - if (name == "localtime") { - *tz = TimeZone(time_internal::cctz::local_time_zone()); - return true; - } - time_internal::cctz::time_zone cz; + if (name == "localtime") { + *tz = TimeZone(time_internal::cctz::local_time_zone()); + return true; + } + time_internal::cctz::time_zone cz; const bool b = time_internal::cctz::load_time_zone(TString(name), &cz); - *tz = TimeZone(cz); - return b; -} - -// FixedTimeZone() -// -// Returns a TimeZone that is a fixed offset (seconds east) from UTC. -// Note: If the absolute value of the offset is greater than 24 hours -// you'll get UTC (i.e., no offset) instead. -inline TimeZone FixedTimeZone(int seconds) { - return TimeZone( - time_internal::cctz::fixed_time_zone(std::chrono::seconds(seconds))); -} - -// UTCTimeZone() -// -// Convenience method returning the UTC time zone. -inline TimeZone UTCTimeZone() { - return TimeZone(time_internal::cctz::utc_time_zone()); -} - -// LocalTimeZone() -// -// Convenience method returning the local time zone, or UTC if there is -// no configured local zone. Warning: Be wary of using LocalTimeZone(), -// and particularly so in a server process, as the zone configured for the -// local machine should be irrelevant. Prefer an explicit zone name. -inline TimeZone LocalTimeZone() { - return TimeZone(time_internal::cctz::local_time_zone()); -} - -// ToCivilSecond() -// ToCivilMinute() -// ToCivilHour() -// ToCivilDay() -// ToCivilMonth() -// ToCivilYear() -// -// Helpers for TimeZone::At(Time) to return particularly aligned civil times. -// -// Example: -// + *tz = TimeZone(cz); + return b; +} + +// FixedTimeZone() +// +// Returns a TimeZone that is a fixed offset (seconds east) from UTC. +// Note: If the absolute value of the offset is greater than 24 hours +// you'll get UTC (i.e., no offset) instead. +inline TimeZone FixedTimeZone(int seconds) { + return TimeZone( + time_internal::cctz::fixed_time_zone(std::chrono::seconds(seconds))); +} + +// UTCTimeZone() +// +// Convenience method returning the UTC time zone. +inline TimeZone UTCTimeZone() { + return TimeZone(time_internal::cctz::utc_time_zone()); +} + +// LocalTimeZone() +// +// Convenience method returning the local time zone, or UTC if there is +// no configured local zone. Warning: Be wary of using LocalTimeZone(), +// and particularly so in a server process, as the zone configured for the +// local machine should be irrelevant. Prefer an explicit zone name. +inline TimeZone LocalTimeZone() { + return TimeZone(time_internal::cctz::local_time_zone()); +} + +// ToCivilSecond() +// ToCivilMinute() +// ToCivilHour() +// ToCivilDay() +// ToCivilMonth() +// ToCivilYear() +// +// Helpers for TimeZone::At(Time) to return particularly aligned civil times. +// +// Example: +// // y_absl::Time t = ...; // y_absl::TimeZone tz = ...; // const auto cd = y_absl::ToCivilDay(t, tz); -inline CivilSecond ToCivilSecond(Time t, TimeZone tz) { - return tz.At(t).cs; // already a CivilSecond -} -inline CivilMinute ToCivilMinute(Time t, TimeZone tz) { - return CivilMinute(tz.At(t).cs); -} -inline CivilHour ToCivilHour(Time t, TimeZone tz) { - return CivilHour(tz.At(t).cs); -} -inline CivilDay ToCivilDay(Time t, TimeZone tz) { - return CivilDay(tz.At(t).cs); -} -inline CivilMonth ToCivilMonth(Time t, TimeZone tz) { - return CivilMonth(tz.At(t).cs); -} -inline CivilYear ToCivilYear(Time t, TimeZone tz) { - return CivilYear(tz.At(t).cs); -} - -// FromCivil() -// -// Helper for TimeZone::At(CivilSecond) that provides "order-preserving -// semantics." If the civil time maps to a unique time, that time is -// returned. If the civil time is repeated in the given time zone, the -// time using the pre-transition offset is returned. Otherwise, the -// civil time is skipped in the given time zone, and the transition time -// is returned. This means that for any two civil times, ct1 and ct2, -// (ct1 < ct2) => (FromCivil(ct1) <= FromCivil(ct2)), the equal case -// being when two non-existent civil times map to the same transition time. -// -// Note: Accepts civil times of any alignment. -inline Time FromCivil(CivilSecond ct, TimeZone tz) { - const auto ti = tz.At(ct); - if (ti.kind == TimeZone::TimeInfo::SKIPPED) return ti.trans; - return ti.pre; -} - -// TimeConversion -// +inline CivilSecond ToCivilSecond(Time t, TimeZone tz) { + return tz.At(t).cs; // already a CivilSecond +} +inline CivilMinute ToCivilMinute(Time t, TimeZone tz) { + return CivilMinute(tz.At(t).cs); +} +inline CivilHour ToCivilHour(Time t, TimeZone tz) { + return CivilHour(tz.At(t).cs); +} +inline CivilDay ToCivilDay(Time t, TimeZone tz) { + return CivilDay(tz.At(t).cs); +} +inline CivilMonth ToCivilMonth(Time t, TimeZone tz) { + return CivilMonth(tz.At(t).cs); +} +inline CivilYear ToCivilYear(Time t, TimeZone tz) { + return CivilYear(tz.At(t).cs); +} + +// FromCivil() +// +// Helper for TimeZone::At(CivilSecond) that provides "order-preserving +// semantics." If the civil time maps to a unique time, that time is +// returned. If the civil time is repeated in the given time zone, the +// time using the pre-transition offset is returned. Otherwise, the +// civil time is skipped in the given time zone, and the transition time +// is returned. This means that for any two civil times, ct1 and ct2, +// (ct1 < ct2) => (FromCivil(ct1) <= FromCivil(ct2)), the equal case +// being when two non-existent civil times map to the same transition time. +// +// Note: Accepts civil times of any alignment. +inline Time FromCivil(CivilSecond ct, TimeZone tz) { + const auto ti = tz.At(ct); + if (ti.kind == TimeZone::TimeInfo::SKIPPED) return ti.trans; + return ti.pre; +} + +// TimeConversion +// // An `y_absl::TimeConversion` represents the conversion of year, month, day, -// hour, minute, and second values (i.e., a civil time), in a particular +// hour, minute, and second values (i.e., a civil time), in a particular // `y_absl::TimeZone`, to a time instant (an absolute time), as returned by // `y_absl::ConvertDateTime()`. Legacy version of `y_absl::TimeZone::TimeInfo`. -// +// // Deprecated. Use `y_absl::TimeZone::TimeInfo`. -struct - TimeConversion { - Time pre; // time calculated using the pre-transition offset - Time trans; // when the civil-time discontinuity occurred - Time post; // time calculated using the post-transition offset - - enum Kind { - UNIQUE, // the civil time was singular (pre == trans == post) - SKIPPED, // the civil time did not exist - REPEATED, // the civil time was ambiguous - }; - Kind kind; - - bool normalized; // input values were outside their valid ranges -}; - -// ConvertDateTime() -// +struct + TimeConversion { + Time pre; // time calculated using the pre-transition offset + Time trans; // when the civil-time discontinuity occurred + Time post; // time calculated using the post-transition offset + + enum Kind { + UNIQUE, // the civil time was singular (pre == trans == post) + SKIPPED, // the civil time did not exist + REPEATED, // the civil time was ambiguous + }; + Kind kind; + + bool normalized; // input values were outside their valid ranges +}; + +// ConvertDateTime() +// // Legacy version of `y_absl::TimeZone::At(y_absl::CivilSecond)` that takes -// the civil time as six, separate values (YMDHMS). -// -// The input month, day, hour, minute, and second values can be outside -// of their valid ranges, in which case they will be "normalized" during -// the conversion. -// -// Example: -// -// // "October 32" normalizes to "November 1". +// the civil time as six, separate values (YMDHMS). +// +// The input month, day, hour, minute, and second values can be outside +// of their valid ranges, in which case they will be "normalized" during +// the conversion. +// +// Example: +// +// // "October 32" normalizes to "November 1". // y_absl::TimeConversion tc = // y_absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, lax); -// // tc.kind == TimeConversion::UNIQUE && tc.normalized == true +// // tc.kind == TimeConversion::UNIQUE && tc.normalized == true // // y_absl::ToCivilDay(tc.pre, tz).month() == 11 // // y_absl::ToCivilDay(tc.pre, tz).day() == 1 -// +// // Deprecated. Use `y_absl::TimeZone::At(CivilSecond)`. -TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour, - int min, int sec, TimeZone tz); - -// FromDateTime() -// +TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour, + int min, int sec, TimeZone tz); + +// FromDateTime() +// // A convenience wrapper for `y_absl::ConvertDateTime()` that simply returns // the "pre" `y_absl::Time`. That is, the unique result, or the instant that -// is correct using the pre-transition offset (as if the transition never -// happened). -// -// Example: -// +// is correct using the pre-transition offset (as if the transition never +// happened). +// +// Example: +// // y_absl::Time t = y_absl::FromDateTime(2017, 9, 26, 9, 30, 0, lax); -// // t = 2017-09-26 09:30:00 -0700 -// +// // t = 2017-09-26 09:30:00 -0700 +// // Deprecated. Use `y_absl::FromCivil(CivilSecond, TimeZone)`. Note that the -// behavior of `FromCivil()` differs from `FromDateTime()` for skipped civil +// behavior of `FromCivil()` differs from `FromDateTime()` for skipped civil // times. If you care about that see `y_absl::TimeZone::At(y_absl::CivilSecond)`. -inline Time FromDateTime(int64_t year, int mon, int day, int hour, - int min, int sec, TimeZone tz) { - return ConvertDateTime(year, mon, day, hour, min, sec, tz).pre; -} - -// FromTM() -// -// Converts the `tm_year`, `tm_mon`, `tm_mday`, `tm_hour`, `tm_min`, and +inline Time FromDateTime(int64_t year, int mon, int day, int hour, + int min, int sec, TimeZone tz) { + return ConvertDateTime(year, mon, day, hour, min, sec, tz).pre; +} + +// FromTM() +// +// Converts the `tm_year`, `tm_mon`, `tm_mday`, `tm_hour`, `tm_min`, and // `tm_sec` fields to an `y_absl::Time` using the given time zone. See ctime(3) // for a description of the expected values of the tm fields. If the civil time // is unique (see `y_absl::TimeZone::At(y_absl::CivilSecond)` above), the matching @@ -1239,378 +1239,378 @@ inline Time FromDateTime(int64_t year, int mon, int day, int hour, // instant, so `tm_isdst != 0` returns the DST instant, and `tm_isdst == 0` // returns the non-DST instant, that would have matched if the transition never // happened. -Time FromTM(const struct tm& tm, TimeZone tz); - -// ToTM() -// +Time FromTM(const struct tm& tm, TimeZone tz); + +// ToTM() +// // Converts the given `y_absl::Time` to a struct tm using the given time zone. -// See ctime(3) for a description of the values of the tm fields. -struct tm ToTM(Time t, TimeZone tz); - -// RFC3339_full -// RFC3339_sec -// -// FormatTime()/ParseTime() format specifiers for RFC3339 date/time strings, -// with trailing zeros trimmed or with fractional seconds omitted altogether. -// -// Note that RFC3339_sec[] matches an ISO 8601 extended format for date and -// time with UTC offset. Also note the use of "%Y": RFC3339 mandates that -// years have exactly four digits, but we allow them to take their natural -// width. +// See ctime(3) for a description of the values of the tm fields. +struct tm ToTM(Time t, TimeZone tz); + +// RFC3339_full +// RFC3339_sec +// +// FormatTime()/ParseTime() format specifiers for RFC3339 date/time strings, +// with trailing zeros trimmed or with fractional seconds omitted altogether. +// +// Note that RFC3339_sec[] matches an ISO 8601 extended format for date and +// time with UTC offset. Also note the use of "%Y": RFC3339 mandates that +// years have exactly four digits, but we allow them to take their natural +// width. ABSL_DLL extern const char RFC3339_full[]; // %Y-%m-%d%ET%H:%M:%E*S%Ez ABSL_DLL extern const char RFC3339_sec[]; // %Y-%m-%d%ET%H:%M:%S%Ez - -// RFC1123_full -// RFC1123_no_wday -// -// FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings. + +// RFC1123_full +// RFC1123_no_wday +// +// FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings. ABSL_DLL extern const char RFC1123_full[]; // %a, %d %b %E4Y %H:%M:%S %z ABSL_DLL extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z - -// FormatTime() -// + +// FormatTime() +// // Formats the given `y_absl::Time` in the `y_absl::TimeZone` according to the -// provided format string. Uses strftime()-like formatting options, with -// the following extensions: -// -// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm) -// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss) -// - %E#S - Seconds with # digits of fractional precision -// - %E*S - Seconds with full fractional precision (a literal '*') -// - %E#f - Fractional seconds with # digits of precision -// - %E*f - Fractional seconds with full precision (a literal '*') -// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999) +// provided format string. Uses strftime()-like formatting options, with +// the following extensions: +// +// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm) +// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss) +// - %E#S - Seconds with # digits of fractional precision +// - %E*S - Seconds with full fractional precision (a literal '*') +// - %E#f - Fractional seconds with # digits of precision +// - %E*f - Fractional seconds with full precision (a literal '*') +// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999) // - %ET - The RFC3339 "date-time" separator "T" -// -// Note that %E0S behaves like %S, and %E0f produces no characters. In -// contrast %E*f always produces at least one digit, which may be '0'. -// -// Note that %Y produces as many characters as it takes to fully render the -// year. A year outside of [-999:9999] when formatted with %E4Y will produce -// more than four characters, just like %Y. -// -// We recommend that format strings include the UTC offset (%z, %Ez, or %E*z) -// so that the result uniquely identifies a time instant. -// -// Example: -// +// +// Note that %E0S behaves like %S, and %E0f produces no characters. In +// contrast %E*f always produces at least one digit, which may be '0'. +// +// Note that %Y produces as many characters as it takes to fully render the +// year. A year outside of [-999:9999] when formatted with %E4Y will produce +// more than four characters, just like %Y. +// +// We recommend that format strings include the UTC offset (%z, %Ez, or %E*z) +// so that the result uniquely identifies a time instant. +// +// Example: +// // y_absl::CivilSecond cs(2013, 1, 2, 3, 4, 5); // y_absl::Time t = y_absl::FromCivil(cs, lax); // TString f = y_absl::FormatTime("%H:%M:%S", t, lax); // "03:04:05" // f = y_absl::FormatTime("%H:%M:%E3S", t, lax); // "03:04:05.000" -// +// // Note: If the given `y_absl::Time` is `y_absl::InfiniteFuture()`, the returned // string will be exactly "infinite-future". If the given `y_absl::Time` is // `y_absl::InfinitePast()`, the returned string will be exactly "infinite-past". // In both cases the given format string and `y_absl::TimeZone` are ignored. -// +// TString FormatTime(y_absl::string_view format, Time t, TimeZone tz); - -// Convenience functions that format the given time using the RFC3339_full -// format. The first overload uses the provided TimeZone, while the second -// uses LocalTimeZone(). + +// Convenience functions that format the given time using the RFC3339_full +// format. The first overload uses the provided TimeZone, while the second +// uses LocalTimeZone(). TString FormatTime(Time t, TimeZone tz); TString FormatTime(Time t); - -// Output stream operator. -inline std::ostream& operator<<(std::ostream& os, Time t) { - return os << FormatTime(t); -} - -// ParseTime() -// -// Parses an input string according to the provided format string and + +// Output stream operator. +inline std::ostream& operator<<(std::ostream& os, Time t) { + return os << FormatTime(t); +} + +// ParseTime() +// +// Parses an input string according to the provided format string and // returns the corresponding `y_absl::Time`. Uses strftime()-like formatting -// options, with the same extensions as FormatTime(), but with the -// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez +// options, with the same extensions as FormatTime(), but with the +// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez // and %E*z also accept the same inputs, which (along with %z) includes // 'z' and 'Z' as synonyms for +00:00. %ET accepts either 'T' or 't'. -// -// %Y consumes as many numeric characters as it can, so the matching data -// should always be terminated with a non-numeric. %E4Y always consumes -// exactly four characters, including any sign. -// -// Unspecified fields are taken from the default date and time of ... -// -// "1970-01-01 00:00:00.0 +0000" -// +// +// %Y consumes as many numeric characters as it can, so the matching data +// should always be terminated with a non-numeric. %E4Y always consumes +// exactly four characters, including any sign. +// +// Unspecified fields are taken from the default date and time of ... +// +// "1970-01-01 00:00:00.0 +0000" +// // For example, parsing a string of "15:45" (%H:%M) will return an y_absl::Time -// that represents "1970-01-01 15:45:00.0 +0000". -// -// Note that since ParseTime() returns time instants, it makes the most sense -// to parse fully-specified date/time strings that include a UTC offset (%z, -// %Ez, or %E*z). -// +// that represents "1970-01-01 15:45:00.0 +0000". +// +// Note that since ParseTime() returns time instants, it makes the most sense +// to parse fully-specified date/time strings that include a UTC offset (%z, +// %Ez, or %E*z). +// // Note also that `y_absl::ParseTime()` only heeds the fields year, month, day, -// hour, minute, (fractional) second, and UTC offset. Other fields, like -// weekday (%a or %A), while parsed for syntactic validity, are ignored -// in the conversion. -// -// Date and time fields that are out-of-range will be treated as errors +// hour, minute, (fractional) second, and UTC offset. Other fields, like +// weekday (%a or %A), while parsed for syntactic validity, are ignored +// in the conversion. +// +// Date and time fields that are out-of-range will be treated as errors // rather than normalizing them like `y_absl::CivilSecond` does. For example, -// it is an error to parse the date "Oct 32, 2013" because 32 is out of range. -// -// A leap second of ":60" is normalized to ":00" of the following minute -// with fractional seconds discarded. The following table shows how the -// given seconds and subseconds will be parsed: -// -// "59.x" -> 59.x // exact -// "60.x" -> 00.0 // normalized -// "00.x" -> 00.x // exact -// -// Errors are indicated by returning false and assigning an error message -// to the "err" out param if it is non-null. -// -// Note: If the input string is exactly "infinite-future", the returned +// it is an error to parse the date "Oct 32, 2013" because 32 is out of range. +// +// A leap second of ":60" is normalized to ":00" of the following minute +// with fractional seconds discarded. The following table shows how the +// given seconds and subseconds will be parsed: +// +// "59.x" -> 59.x // exact +// "60.x" -> 00.0 // normalized +// "00.x" -> 00.x // exact +// +// Errors are indicated by returning false and assigning an error message +// to the "err" out param if it is non-null. +// +// Note: If the input string is exactly "infinite-future", the returned // `y_absl::Time` will be `y_absl::InfiniteFuture()` and `true` will be returned. // If the input string is "infinite-past", the returned `y_absl::Time` will be // `y_absl::InfinitePast()` and `true` will be returned. -// +// bool ParseTime(y_absl::string_view format, y_absl::string_view input, Time* time, TString* err); - -// Like ParseTime() above, but if the format string does not contain a UTC -// offset specification (%z/%Ez/%E*z) then the input is interpreted in the -// given TimeZone. This means that the input, by itself, does not identify a -// unique instant. Being time-zone dependent, it also admits the possibility -// of ambiguity or non-existence, in which case the "pre" time (as defined -// by TimeZone::TimeInfo) is returned. For these reasons we recommend that -// all date/time strings include a UTC offset so they're context independent. + +// Like ParseTime() above, but if the format string does not contain a UTC +// offset specification (%z/%Ez/%E*z) then the input is interpreted in the +// given TimeZone. This means that the input, by itself, does not identify a +// unique instant. Being time-zone dependent, it also admits the possibility +// of ambiguity or non-existence, in which case the "pre" time (as defined +// by TimeZone::TimeInfo) is returned. For these reasons we recommend that +// all date/time strings include a UTC offset so they're context independent. bool ParseTime(y_absl::string_view format, y_absl::string_view input, TimeZone tz, Time* time, TString* err); - -// ============================================================================ -// Implementation Details Follow -// ============================================================================ - -namespace time_internal { - -// Creates a Duration with a given representation. -// REQUIRES: hi,lo is a valid representation of a Duration as specified -// in time/duration.cc. -constexpr Duration MakeDuration(int64_t hi, uint32_t lo = 0) { - return Duration(hi, lo); -} - -constexpr Duration MakeDuration(int64_t hi, int64_t lo) { - return MakeDuration(hi, static_cast<uint32_t>(lo)); -} - -// Make a Duration value from a floating-point number, as long as that number -// is in the range [ 0 .. numeric_limits<int64_t>::max ), that is, as long as -// it's positive and can be converted to int64_t without risk of UB. -inline Duration MakePosDoubleDuration(double n) { - const int64_t int_secs = static_cast<int64_t>(n); + +// ============================================================================ +// Implementation Details Follow +// ============================================================================ + +namespace time_internal { + +// Creates a Duration with a given representation. +// REQUIRES: hi,lo is a valid representation of a Duration as specified +// in time/duration.cc. +constexpr Duration MakeDuration(int64_t hi, uint32_t lo = 0) { + return Duration(hi, lo); +} + +constexpr Duration MakeDuration(int64_t hi, int64_t lo) { + return MakeDuration(hi, static_cast<uint32_t>(lo)); +} + +// Make a Duration value from a floating-point number, as long as that number +// is in the range [ 0 .. numeric_limits<int64_t>::max ), that is, as long as +// it's positive and can be converted to int64_t without risk of UB. +inline Duration MakePosDoubleDuration(double n) { + const int64_t int_secs = static_cast<int64_t>(n); const uint32_t ticks = static_cast<uint32_t>( std::round((n - static_cast<double>(int_secs)) * kTicksPerSecond)); - return ticks < kTicksPerSecond - ? MakeDuration(int_secs, ticks) - : MakeDuration(int_secs + 1, ticks - kTicksPerSecond); -} - -// Creates a normalized Duration from an almost-normalized (sec,ticks) -// pair. sec may be positive or negative. ticks must be in the range -// -kTicksPerSecond < *ticks < kTicksPerSecond. If ticks is negative it -// will be normalized to a positive value in the resulting Duration. -constexpr Duration MakeNormalizedDuration(int64_t sec, int64_t ticks) { - return (ticks < 0) ? MakeDuration(sec - 1, ticks + kTicksPerSecond) - : MakeDuration(sec, ticks); -} - -// Provide access to the Duration representation. -constexpr int64_t GetRepHi(Duration d) { return d.rep_hi_; } -constexpr uint32_t GetRepLo(Duration d) { return d.rep_lo_; } - -// Returns true iff d is positive or negative infinity. -constexpr bool IsInfiniteDuration(Duration d) { return GetRepLo(d) == ~0U; } - -// Returns an infinite Duration with the opposite sign. -// REQUIRES: IsInfiniteDuration(d) -constexpr Duration OppositeInfinity(Duration d) { - return GetRepHi(d) < 0 - ? MakeDuration((std::numeric_limits<int64_t>::max)(), ~0U) - : MakeDuration((std::numeric_limits<int64_t>::min)(), ~0U); -} - -// Returns (-n)-1 (equivalently -(n+1)) without avoidable overflow. -constexpr int64_t NegateAndSubtractOne(int64_t n) { - // Note: Good compilers will optimize this expression to ~n when using - // a two's-complement representation (which is required for int64_t). - return (n < 0) ? -(n + 1) : (-n) - 1; -} - -// Map between a Time and a Duration since the Unix epoch. Note that these -// functions depend on the above mentioned choice of the Unix epoch for the -// Time representation (and both need to be Time friends). Without this -// knowledge, we would need to add-in/subtract-out UnixEpoch() respectively. -constexpr Time FromUnixDuration(Duration d) { return Time(d); } -constexpr Duration ToUnixDuration(Time t) { return t.rep_; } - -template <std::intmax_t N> -constexpr Duration FromInt64(int64_t v, std::ratio<1, N>) { - static_assert(0 < N && N <= 1000 * 1000 * 1000, "Unsupported ratio"); - // Subsecond ratios cannot overflow. - return MakeNormalizedDuration( - v / N, v % N * kTicksPerNanosecond * 1000 * 1000 * 1000 / N); -} -constexpr Duration FromInt64(int64_t v, std::ratio<60>) { - return (v <= (std::numeric_limits<int64_t>::max)() / 60 && - v >= (std::numeric_limits<int64_t>::min)() / 60) - ? MakeDuration(v * 60) - : v > 0 ? InfiniteDuration() : -InfiniteDuration(); -} -constexpr Duration FromInt64(int64_t v, std::ratio<3600>) { - return (v <= (std::numeric_limits<int64_t>::max)() / 3600 && - v >= (std::numeric_limits<int64_t>::min)() / 3600) - ? MakeDuration(v * 3600) - : v > 0 ? InfiniteDuration() : -InfiniteDuration(); -} - -// IsValidRep64<T>(0) is true if the expression `int64_t{std::declval<T>()}` is -// valid. That is, if a T can be assigned to an int64_t without narrowing. -template <typename T> -constexpr auto IsValidRep64(int) -> decltype(int64_t{std::declval<T>()} == 0) { - return true; -} -template <typename T> -constexpr auto IsValidRep64(char) -> bool { - return false; -} - + return ticks < kTicksPerSecond + ? MakeDuration(int_secs, ticks) + : MakeDuration(int_secs + 1, ticks - kTicksPerSecond); +} + +// Creates a normalized Duration from an almost-normalized (sec,ticks) +// pair. sec may be positive or negative. ticks must be in the range +// -kTicksPerSecond < *ticks < kTicksPerSecond. If ticks is negative it +// will be normalized to a positive value in the resulting Duration. +constexpr Duration MakeNormalizedDuration(int64_t sec, int64_t ticks) { + return (ticks < 0) ? MakeDuration(sec - 1, ticks + kTicksPerSecond) + : MakeDuration(sec, ticks); +} + +// Provide access to the Duration representation. +constexpr int64_t GetRepHi(Duration d) { return d.rep_hi_; } +constexpr uint32_t GetRepLo(Duration d) { return d.rep_lo_; } + +// Returns true iff d is positive or negative infinity. +constexpr bool IsInfiniteDuration(Duration d) { return GetRepLo(d) == ~0U; } + +// Returns an infinite Duration with the opposite sign. +// REQUIRES: IsInfiniteDuration(d) +constexpr Duration OppositeInfinity(Duration d) { + return GetRepHi(d) < 0 + ? MakeDuration((std::numeric_limits<int64_t>::max)(), ~0U) + : MakeDuration((std::numeric_limits<int64_t>::min)(), ~0U); +} + +// Returns (-n)-1 (equivalently -(n+1)) without avoidable overflow. +constexpr int64_t NegateAndSubtractOne(int64_t n) { + // Note: Good compilers will optimize this expression to ~n when using + // a two's-complement representation (which is required for int64_t). + return (n < 0) ? -(n + 1) : (-n) - 1; +} + +// Map between a Time and a Duration since the Unix epoch. Note that these +// functions depend on the above mentioned choice of the Unix epoch for the +// Time representation (and both need to be Time friends). Without this +// knowledge, we would need to add-in/subtract-out UnixEpoch() respectively. +constexpr Time FromUnixDuration(Duration d) { return Time(d); } +constexpr Duration ToUnixDuration(Time t) { return t.rep_; } + +template <std::intmax_t N> +constexpr Duration FromInt64(int64_t v, std::ratio<1, N>) { + static_assert(0 < N && N <= 1000 * 1000 * 1000, "Unsupported ratio"); + // Subsecond ratios cannot overflow. + return MakeNormalizedDuration( + v / N, v % N * kTicksPerNanosecond * 1000 * 1000 * 1000 / N); +} +constexpr Duration FromInt64(int64_t v, std::ratio<60>) { + return (v <= (std::numeric_limits<int64_t>::max)() / 60 && + v >= (std::numeric_limits<int64_t>::min)() / 60) + ? MakeDuration(v * 60) + : v > 0 ? InfiniteDuration() : -InfiniteDuration(); +} +constexpr Duration FromInt64(int64_t v, std::ratio<3600>) { + return (v <= (std::numeric_limits<int64_t>::max)() / 3600 && + v >= (std::numeric_limits<int64_t>::min)() / 3600) + ? MakeDuration(v * 3600) + : v > 0 ? InfiniteDuration() : -InfiniteDuration(); +} + +// IsValidRep64<T>(0) is true if the expression `int64_t{std::declval<T>()}` is +// valid. That is, if a T can be assigned to an int64_t without narrowing. +template <typename T> +constexpr auto IsValidRep64(int) -> decltype(int64_t{std::declval<T>()} == 0) { + return true; +} +template <typename T> +constexpr auto IsValidRep64(char) -> bool { + return false; +} + // Converts a std::chrono::duration to an y_absl::Duration. -template <typename Rep, typename Period> -constexpr Duration FromChrono(const std::chrono::duration<Rep, Period>& d) { - static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid"); - return FromInt64(int64_t{d.count()}, Period{}); -} - -template <typename Ratio> -int64_t ToInt64(Duration d, Ratio) { - // Note: This may be used on MSVC, which may have a system_clock period of - // std::ratio<1, 10 * 1000 * 1000> - return ToInt64Seconds(d * Ratio::den / Ratio::num); -} -// Fastpath implementations for the 6 common duration units. -inline int64_t ToInt64(Duration d, std::nano) { - return ToInt64Nanoseconds(d); -} -inline int64_t ToInt64(Duration d, std::micro) { - return ToInt64Microseconds(d); -} -inline int64_t ToInt64(Duration d, std::milli) { - return ToInt64Milliseconds(d); -} -inline int64_t ToInt64(Duration d, std::ratio<1>) { - return ToInt64Seconds(d); -} -inline int64_t ToInt64(Duration d, std::ratio<60>) { - return ToInt64Minutes(d); -} -inline int64_t ToInt64(Duration d, std::ratio<3600>) { - return ToInt64Hours(d); -} - +template <typename Rep, typename Period> +constexpr Duration FromChrono(const std::chrono::duration<Rep, Period>& d) { + static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid"); + return FromInt64(int64_t{d.count()}, Period{}); +} + +template <typename Ratio> +int64_t ToInt64(Duration d, Ratio) { + // Note: This may be used on MSVC, which may have a system_clock period of + // std::ratio<1, 10 * 1000 * 1000> + return ToInt64Seconds(d * Ratio::den / Ratio::num); +} +// Fastpath implementations for the 6 common duration units. +inline int64_t ToInt64(Duration d, std::nano) { + return ToInt64Nanoseconds(d); +} +inline int64_t ToInt64(Duration d, std::micro) { + return ToInt64Microseconds(d); +} +inline int64_t ToInt64(Duration d, std::milli) { + return ToInt64Milliseconds(d); +} +inline int64_t ToInt64(Duration d, std::ratio<1>) { + return ToInt64Seconds(d); +} +inline int64_t ToInt64(Duration d, std::ratio<60>) { + return ToInt64Minutes(d); +} +inline int64_t ToInt64(Duration d, std::ratio<3600>) { + return ToInt64Hours(d); +} + // Converts an y_absl::Duration to a chrono duration of type T. -template <typename T> -T ToChronoDuration(Duration d) { - using Rep = typename T::rep; - using Period = typename T::period; - static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid"); - if (time_internal::IsInfiniteDuration(d)) - return d < ZeroDuration() ? (T::min)() : (T::max)(); - const auto v = ToInt64(d, Period{}); - if (v > (std::numeric_limits<Rep>::max)()) return (T::max)(); - if (v < (std::numeric_limits<Rep>::min)()) return (T::min)(); - return T{v}; -} - -} // namespace time_internal - -constexpr bool operator<(Duration lhs, Duration rhs) { - return time_internal::GetRepHi(lhs) != time_internal::GetRepHi(rhs) - ? time_internal::GetRepHi(lhs) < time_internal::GetRepHi(rhs) +template <typename T> +T ToChronoDuration(Duration d) { + using Rep = typename T::rep; + using Period = typename T::period; + static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid"); + if (time_internal::IsInfiniteDuration(d)) + return d < ZeroDuration() ? (T::min)() : (T::max)(); + const auto v = ToInt64(d, Period{}); + if (v > (std::numeric_limits<Rep>::max)()) return (T::max)(); + if (v < (std::numeric_limits<Rep>::min)()) return (T::min)(); + return T{v}; +} + +} // namespace time_internal + +constexpr bool operator<(Duration lhs, Duration rhs) { + return time_internal::GetRepHi(lhs) != time_internal::GetRepHi(rhs) + ? time_internal::GetRepHi(lhs) < time_internal::GetRepHi(rhs) : time_internal::GetRepHi(lhs) == (std::numeric_limits<int64_t>::min)() ? time_internal::GetRepLo(lhs) + 1 < time_internal::GetRepLo(rhs) + 1 : time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs); -} - -constexpr bool operator==(Duration lhs, Duration rhs) { - return time_internal::GetRepHi(lhs) == time_internal::GetRepHi(rhs) && - time_internal::GetRepLo(lhs) == time_internal::GetRepLo(rhs); -} - -constexpr Duration operator-(Duration d) { - // This is a little interesting because of the special cases. - // - // If rep_lo_ is zero, we have it easy; it's safe to negate rep_hi_, we're - // dealing with an integral number of seconds, and the only special case is - // the maximum negative finite duration, which can't be negated. - // - // Infinities stay infinite, and just change direction. - // - // Finally we're in the case where rep_lo_ is non-zero, and we can borrow - // a second's worth of ticks and avoid overflow (as negating int64_t-min + 1 - // is safe). - return time_internal::GetRepLo(d) == 0 - ? time_internal::GetRepHi(d) == - (std::numeric_limits<int64_t>::min)() - ? InfiniteDuration() - : time_internal::MakeDuration(-time_internal::GetRepHi(d)) - : time_internal::IsInfiniteDuration(d) - ? time_internal::OppositeInfinity(d) - : time_internal::MakeDuration( - time_internal::NegateAndSubtractOne( - time_internal::GetRepHi(d)), - time_internal::kTicksPerSecond - - time_internal::GetRepLo(d)); -} - -constexpr Duration InfiniteDuration() { - return time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(), - ~0U); -} - -constexpr Duration FromChrono(const std::chrono::nanoseconds& d) { - return time_internal::FromChrono(d); -} -constexpr Duration FromChrono(const std::chrono::microseconds& d) { - return time_internal::FromChrono(d); -} -constexpr Duration FromChrono(const std::chrono::milliseconds& d) { - return time_internal::FromChrono(d); -} -constexpr Duration FromChrono(const std::chrono::seconds& d) { - return time_internal::FromChrono(d); -} -constexpr Duration FromChrono(const std::chrono::minutes& d) { - return time_internal::FromChrono(d); -} -constexpr Duration FromChrono(const std::chrono::hours& d) { - return time_internal::FromChrono(d); -} - -constexpr Time FromUnixNanos(int64_t ns) { - return time_internal::FromUnixDuration(Nanoseconds(ns)); -} - -constexpr Time FromUnixMicros(int64_t us) { - return time_internal::FromUnixDuration(Microseconds(us)); -} - -constexpr Time FromUnixMillis(int64_t ms) { - return time_internal::FromUnixDuration(Milliseconds(ms)); -} - -constexpr Time FromUnixSeconds(int64_t s) { - return time_internal::FromUnixDuration(Seconds(s)); -} - -constexpr Time FromTimeT(time_t t) { - return time_internal::FromUnixDuration(Seconds(t)); -} - +} + +constexpr bool operator==(Duration lhs, Duration rhs) { + return time_internal::GetRepHi(lhs) == time_internal::GetRepHi(rhs) && + time_internal::GetRepLo(lhs) == time_internal::GetRepLo(rhs); +} + +constexpr Duration operator-(Duration d) { + // This is a little interesting because of the special cases. + // + // If rep_lo_ is zero, we have it easy; it's safe to negate rep_hi_, we're + // dealing with an integral number of seconds, and the only special case is + // the maximum negative finite duration, which can't be negated. + // + // Infinities stay infinite, and just change direction. + // + // Finally we're in the case where rep_lo_ is non-zero, and we can borrow + // a second's worth of ticks and avoid overflow (as negating int64_t-min + 1 + // is safe). + return time_internal::GetRepLo(d) == 0 + ? time_internal::GetRepHi(d) == + (std::numeric_limits<int64_t>::min)() + ? InfiniteDuration() + : time_internal::MakeDuration(-time_internal::GetRepHi(d)) + : time_internal::IsInfiniteDuration(d) + ? time_internal::OppositeInfinity(d) + : time_internal::MakeDuration( + time_internal::NegateAndSubtractOne( + time_internal::GetRepHi(d)), + time_internal::kTicksPerSecond - + time_internal::GetRepLo(d)); +} + +constexpr Duration InfiniteDuration() { + return time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(), + ~0U); +} + +constexpr Duration FromChrono(const std::chrono::nanoseconds& d) { + return time_internal::FromChrono(d); +} +constexpr Duration FromChrono(const std::chrono::microseconds& d) { + return time_internal::FromChrono(d); +} +constexpr Duration FromChrono(const std::chrono::milliseconds& d) { + return time_internal::FromChrono(d); +} +constexpr Duration FromChrono(const std::chrono::seconds& d) { + return time_internal::FromChrono(d); +} +constexpr Duration FromChrono(const std::chrono::minutes& d) { + return time_internal::FromChrono(d); +} +constexpr Duration FromChrono(const std::chrono::hours& d) { + return time_internal::FromChrono(d); +} + +constexpr Time FromUnixNanos(int64_t ns) { + return time_internal::FromUnixDuration(Nanoseconds(ns)); +} + +constexpr Time FromUnixMicros(int64_t us) { + return time_internal::FromUnixDuration(Microseconds(us)); +} + +constexpr Time FromUnixMillis(int64_t ms) { + return time_internal::FromUnixDuration(Milliseconds(ms)); +} + +constexpr Time FromUnixSeconds(int64_t s) { + return time_internal::FromUnixDuration(Seconds(s)); +} + +constexpr Time FromTimeT(time_t t) { + return time_internal::FromUnixDuration(Seconds(t)); +} + ABSL_NAMESPACE_END } // namespace y_absl - -#endif // ABSL_TIME_TIME_H_ + +#endif // ABSL_TIME_TIME_H_ diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/time_zone/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/time/time_zone/ya.make index d2930432bd..d7e1dc0c26 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/time_zone/ya.make +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/time_zone/ya.make @@ -1,38 +1,38 @@ -# Generated by devtools/yamaker. - -LIBRARY() - +# Generated by devtools/yamaker. + +LIBRARY() + WITHOUT_LICENSE_TEXTS() - + OWNER( somov g:cpp-contrib ) -LICENSE(Apache-2.0) - +LICENSE(Apache-2.0) + ADDINCL( GLOBAL contrib/restricted/abseil-cpp-tstring ) - + IF (OS_DARWIN) EXTRALIBS("-framework CoreFoundation") ENDIF() -NO_COMPILER_WARNINGS() - +NO_COMPILER_WARNINGS() + SRCDIR(contrib/restricted/abseil-cpp-tstring/y_absl/time/internal/cctz/src) - -SRCS( - time_zone_fixed.cc - time_zone_format.cc - time_zone_if.cc - time_zone_impl.cc - time_zone_info.cc - time_zone_libc.cc - time_zone_lookup.cc - time_zone_posix.cc - zone_info_source.cc -) - -END() + +SRCS( + time_zone_fixed.cc + time_zone_format.cc + time_zone_if.cc + time_zone_impl.cc + time_zone_info.cc + time_zone_libc.cc + time_zone_lookup.cc + time_zone_posix.cc + zone_info_source.cc +) + +END() diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/time/ya.make b/contrib/restricted/abseil-cpp-tstring/y_absl/time/ya.make index 95bd98470b..37cc779265 100644 --- a/contrib/restricted/abseil-cpp-tstring/y_absl/time/ya.make +++ b/contrib/restricted/abseil-cpp-tstring/y_absl/time/ya.make @@ -1,20 +1,20 @@ -# Generated by devtools/yamaker. - -LIBRARY() - +# Generated by devtools/yamaker. + +LIBRARY() + OWNER( somov g:cpp-contrib ) - + LICENSE( Apache-2.0 AND Public-Domain ) - + LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -PEERDIR( +PEERDIR( contrib/restricted/abseil-cpp-tstring/y_absl/base contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/raw_logging contrib/restricted/abseil-cpp-tstring/y_absl/base/internal/spinlock_wait @@ -25,20 +25,20 @@ PEERDIR( contrib/restricted/abseil-cpp-tstring/y_absl/strings/internal/absl_strings_internal contrib/restricted/abseil-cpp-tstring/y_absl/time/civil_time contrib/restricted/abseil-cpp-tstring/y_absl/time/time_zone -) - +) + ADDINCL( GLOBAL contrib/restricted/abseil-cpp-tstring ) - -NO_COMPILER_WARNINGS() - -SRCS( - civil_time.cc - clock.cc - duration.cc - format.cc - time.cc -) - -END() + +NO_COMPILER_WARNINGS() + +SRCS( + civil_time.cc + clock.cc + duration.cc + format.cc + time.cc +) + +END() |