diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/cctz | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/cctz')
428 files changed, 10970 insertions, 0 deletions
diff --git a/contrib/libs/cctz/.yandex_meta/devtools.copyrights.report b/contrib/libs/cctz/.yandex_meta/devtools.copyrights.report new file mode 100644 index 0000000000..c80a5f6538 --- /dev/null +++ b/contrib/libs/cctz/.yandex_meta/devtools.copyrights.report @@ -0,0 +1,63 @@ +# File format ($ symbol means the beginning of a line): +# +# $ # this message +# $ # ======================= +# $ # comments (all commentaries should starts with some number of spaces and # symbol) +# ${action} {license id} {license text hash} +# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make +# ${all_file_action} filename +# $ # user commentaries (many lines) +# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify) +# ${action} {license spdx} {license text hash} +# $BELONGS ./ya/make/file/relative/path/3/ya.make +# ${all_file_action} filename +# $ # user commentaries +# $ generated description +# $ ... +# +# You can modify action, all_file_action and add commentaries +# Available actions: +# keep - keep license in contrib and use in credits +# skip - skip license +# remove - remove all files with this license +# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file +# +# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory) +# We suppose that that files can contain some license info +# Available all file actions: +# FILE_IGNORE - ignore file (do nothing) +# FILE_INCLUDE - include all file data into licenses text file +# ======================= + +KEEP COPYRIGHT_SERVICE_LABEL 05bdd09fb9fdb384a61f2eb54df462d6 +BELONGS test/ya.make ya.make + License text: + // Copyright 2016 Google Inc. All Rights Reserved. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/cctz/civil_time.h [1:1] + include/cctz/civil_time_detail.h [1:1] + include/cctz/time_zone.h [1:1] + include/cctz/zone_info_source.h [1:1] + src/civil_time_detail.cc [1:1] + src/time_zone_fixed.cc [1:1] + src/time_zone_fixed.h [1:1] + src/time_zone_format.cc [1:1] + src/time_zone_if.cc [1:1] + src/time_zone_if.h [1:1] + src/time_zone_impl.cc [1:1] + src/time_zone_impl.h [1:1] + src/time_zone_info.cc [1:1] + src/time_zone_info.h [1:1] + src/time_zone_libc.cc [1:1] + src/time_zone_libc.h [1:1] + src/time_zone_lookup.cc [1:1] + src/time_zone_posix.cc [1:1] + src/time_zone_posix.h [1:1] + src/zone_info_source.cc [1:1] + test/civil_time_test.cc [1:1] + test/time_zone_format_test.cc [1:1] + test/time_zone_lookup_test.cc [1:1] diff --git a/contrib/libs/cctz/.yandex_meta/devtools.licenses.report b/contrib/libs/cctz/.yandex_meta/devtools.licenses.report new file mode 100644 index 0000000000..c37f0d98e7 --- /dev/null +++ b/contrib/libs/cctz/.yandex_meta/devtools.licenses.report @@ -0,0 +1,124 @@ +# File format ($ symbol means the beginning of a line): +# +# $ # this message +# $ # ======================= +# $ # comments (all commentaries should starts with some number of spaces and # symbol) +# ${action} {license spdx} {license text hash} +# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make +# ${all_file_action} filename +# $ # user commentaries (many lines) +# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify) +# ${action} {license spdx} {license text hash} +# $BELONGS ./ya/make/file/relative/path/3/ya.make +# ${all_file_action} filename +# $ # user commentaries +# $ generated description +# $ ... +# +# You can modify action, all_file_action and add commentaries +# Available actions: +# keep - keep license in contrib and use in credits +# skip - skip license +# remove - remove all files with this license +# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file +# +# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory) +# We suppose that that files can contain some license info +# Available all file actions: +# FILE_IGNORE - ignore file (do nothing) +# FILE_INCLUDE - include all file data into licenses text file +# ======================= + +KEEP Apache-2.0 0f66a26c8211d9f8c21369fcb6702370 +BELONGS test/ya.make ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: Apache-2.0 + Score : 100.00 + Match type : NOTICE + Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0 + Files with this license: + include/cctz/civil_time.h [3:13] + include/cctz/civil_time_detail.h [3:13] + include/cctz/time_zone.h [3:13] + include/cctz/zone_info_source.h [3:13] + src/civil_time_detail.cc [3:13] + src/time_zone_fixed.cc [3:13] + src/time_zone_fixed.h [3:13] + src/time_zone_format.cc [3:13] + src/time_zone_if.cc [3:13] + src/time_zone_if.h [3:13] + src/time_zone_impl.cc [3:13] + src/time_zone_impl.h [3:13] + src/time_zone_info.cc [3:13] + src/time_zone_info.h [3:13] + src/time_zone_libc.cc [3:13] + src/time_zone_libc.h [3:13] + src/time_zone_lookup.cc [3:13] + src/time_zone_posix.cc [3:13] + src/time_zone_posix.h [3:13] + test/civil_time_test.cc [3:13] + test/time_zone_format_test.cc [3:13] + test/time_zone_lookup_test.cc [3:13] + +KEEP Public-Domain 3a682fe6def1cddc889298ee2a043f6f +BELONGS ya.make + License text: + ** This file is in the public domain, so clarified as of + Scancode info: + Original SPDX id: LicenseRef-scancode-public-domain + Score : 100.00 + Match type : TEXT + Links : http://www.linfo.org/publicdomain.html, https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/public-domain.LICENSE + Files with this license: + src/tzfile.h [8:8] + +KEEP Apache-2.0 5c285672050d1bc5672ee878fd75afe5 +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: Apache-2.0 + Score : 100.00 + Match type : NOTICE + Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0 + Files with this license: + src/zone_info_source.cc [3:13] + +SKIP LicenseRef-scancode-generic-cla 968cc2e7110b73d14171fc11913223a6 +BELONGS ya.make + # notice about contributing, not a license + License text: + one above, the Software Grant and Corporate Contributor License Agreement. + Scancode info: + Original SPDX id: LicenseRef-scancode-generic-cla + Score : 16.00 + Match type : NOTICE + Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/generic-cla.LICENSE + Files with this license: + CONTRIBUTING.md [29:29] + +KEEP Apache-2.0 cac6cbe8ed5a3da569f7c01e4e486688 +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: Apache-2.0 + Score : 100.00 + Match type : TEXT + Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0 + Files with this license: + LICENSE.txt [2:202] + +SKIP LicenseRef-scancode-generic-cla d9d8eb54ae33584c7a97dc4e4db96874 +BELONGS ya.make + # contributor agreement + License text: + Before we can use your code, you must sign the [Google Individual Contributor + License + Agreement](https://developers.google.com/open-source/cla/individual?csw=1) + Scancode info: + Original SPDX id: LicenseRef-scancode-generic-cla + Score : 22.00 + Match type : REFERENCE + Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/generic-cla.LICENSE + Files with this license: + CONTRIBUTING.md [6:8] diff --git a/contrib/libs/cctz/.yandex_meta/licenses.list.txt b/contrib/libs/cctz/.yandex_meta/licenses.list.txt new file mode 100644 index 0000000000..ca5b830229 --- /dev/null +++ b/contrib/libs/cctz/.yandex_meta/licenses.list.txt @@ -0,0 +1,224 @@ +====================Apache-2.0==================== + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +====================Apache-2.0==================== +// 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==================== +// Copyright 2016 Google Inc. All Rights Reserved. + + +====================Public-Domain==================== +** This file is in the public domain, so clarified as of diff --git a/contrib/libs/cctz/CONTRIBUTING.md b/contrib/libs/cctz/CONTRIBUTING.md new file mode 100644 index 0000000000..cf0912ea86 --- /dev/null +++ b/contrib/libs/cctz/CONTRIBUTING.md @@ -0,0 +1,29 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute + +Before we can use your code, you must sign the [Google Individual Contributor +License +Agreement](https://developers.google.com/open-source/cla/individual?csw=1) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us +if you know that your code infringes on other people's patents. You don't have +to sign the CLA until after you've submitted your code for review and a member +has approved it, but you must do it before we can put your code into our +codebase. Before you start working on a larger contribution, you should get in +touch with us first through the issue tracker with your idea so that we can help +out and possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews + +All submissions, including submissions by project members, require review. We +use Github pull requests for this purpose. + +### The small print + +Contributions made by corporations are covered by a different agreement than the +one above, the Software Grant and Corporate Contributor License Agreement. diff --git a/contrib/libs/cctz/LICENSE.txt b/contrib/libs/cctz/LICENSE.txt new file mode 100644 index 0000000000..ccd61dcfe3 --- /dev/null +++ b/contrib/libs/cctz/LICENSE.txt @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + diff --git a/contrib/libs/cctz/README b/contrib/libs/cctz/README new file mode 100644 index 0000000000..8cdda27da8 --- /dev/null +++ b/contrib/libs/cctz/README @@ -0,0 +1,8 @@ +A Google timezone library. + +This version is based on commit 2e86a776379ec6f2a60f4a6595a3b68cd3961cb4 from https://github.com/google/cctz.git + +The following changes were made compared to the vanilla Google code: + * the Time Zone Database may optionally be compiled into the library (just add a PEERDIR() to contrib/libs/cctz/tzdata subdirectory in your code); + * some minor cleanups to avoid clang warnings; + * the tests were modified to work with library/cpp/testing/unittest. diff --git a/contrib/libs/cctz/README.md b/contrib/libs/cctz/README.md new file mode 100644 index 0000000000..b535fd65d9 --- /dev/null +++ b/contrib/libs/cctz/README.md @@ -0,0 +1,227 @@ +This is not an official Google product. + +# Overview + +CCTZ contains two libraries that cooperate with `<chrono>` to give C++ +programmers all the necessary tools for computing with dates, times, and time +zones in a simple and correct manner. The libraries in CCTZ are: + +* **The Civil-Time Library** —Â This is a header-only library that + supports computing with human-scale time, such as dates (which are + represented by the `cctz::civil_day` class). This library is declared in + [`include/cctz/civil_time.h`](https://github.com/google/cctz/blob/master/include/cctz/civil_time.h). +* **The Time-Zone Library** —Â This library uses the IANA time zone + database that is installed on the system to convert between *absolute time* + and *civil time*. This library is declared in + [`include/cctz/time_zone.h`](https://github.com/google/cctz/blob/master/include/cctz/time_zone.h). + +These libraries are currently known to work on **Linux**, **Mac OS X**, and +**Android**. + +They will also work on **Windows** if you install the zoneinfo files. We are +interested, though, in an implementation of the cctz::TimeZoneIf interface that +calls the Windows time APIs instead. Please contact us if you're interested in +contributing. + +# Getting Started + +CCTZ is best built and tested using the [Bazel](https://bazel.io) build system +and the [Google Test](https://github.com/google/googletest) framework. (There is +also a simple [`Makefile`](https://github.com/google/cctz/blob/master/Makefile) +and a +[`CMakeLists.txt`](https://github.com/google/cctz/blob/master/CMakeLists.txt) +that should work if you're unable to use Bazel.) + +1. Download/install + [Bazel](https://docs.bazel.build/versions/master/install.html) +2. Get the cctz source: `git clone https://github.com/google/cctz.git` then `cd + cctz` +3. Build cctz and run the tests: `bazel test :all` + +With CMake: + +1. Make sure you have CMake >= 2.8.12 installed. +2. Get the cctz source: `git clone https://github.com/google/cctz.git` then `cd + cctz`. +3. Build cctz so that is can be used by shared libraries and run the tests (use + `-DBUILD_TESTING=OFF` to skip the tests): + + mkdir mybuild + cd mybuild + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. + cmake --build . --config Release + ctest + cmake --build . --config Release --target install + +4. Use in your CMake-based project with: + + ```cmake + find_package(cctz REQUIRED) + add_executable(mytarget file.cc) + target_link_libraries(mytarget cctz::cctz) + ``` + +Note: When using CCTZ in your own project, you might find it easiest to compile +the sources using your existing build system. + +Next Steps: + +1. See the documentation for the libraries in CCTZ: + * Civil Time: + [`include/cctz/civil_time.h`](https://github.com/google/cctz/blob/master/include/cctz/civil_time.h) + * Time Zone: + [`include/cctz/time_zone.h`](https://github.com/google/cctz/blob/master/include/cctz/time_zone.h) +2. Look at the examples in https://github.com/google/cctz/tree/master/examples +3. Join our mailing list to ask questions and keep informed of changes: + * https://groups.google.com/forum/#!forum/cctz + +# Fundamental Concepts + +*[The concepts presented here describe general truths about the problem domain +and are library and language agnostic. An understanding of these concepts helps +the programmer correctly reason about even the most-complicated time-programming +challenges and produce the simplest possible solutions.]* + +There are two main ways to think about time in a computer program: as *absolute +time*, and as *civil time*. Both have their uses and it is important to +understand when each is appropriate. Absolute and civil times may be converted +back and forth using a *time zone* — this is the only way to correctly +convert between them. Let us now look more deeply at the three main concepts of +time programming: Absolute Time, Civil Time, and Time Zone. + +*Absolute time* uniquely and universally represents a specific instant in time. +It has no notion of calendars, or dates, or times of day. Instead, it is a +measure of the passage of real time, typically as a simple count of ticks since +some epoch. Absolute times are independent of all time zones and do not suffer +from human-imposed complexities such as daylight-saving time (DST). Many C++ +types exist to represent absolute times, classically `time_t` and more recently +`std::chrono::time_point`. + +*Civil time* is the legally recognized representation of time for ordinary +affairs (cf. https://www.merriam-webster.com/dictionary/civil). It is a +human-scale representation of time that consists of the six fields — year, +month, day, hour, minute, and second (sometimes shortened to "YMDHMS") — +and it follows the rules of the Proleptic Gregorian Calendar, with 24-hour days +divided into 60-minute hours and 60-second minutes. Like absolute times, civil +times are also independent of all time zones and their related complexities +(e.g., DST). While `std::tm` contains the six civil-time fields (YMDHMS), plus a +few more, it does not have behavior to enforce the rules of civil time. + +*Time zones* are geo-political regions within which human-defined rules are +shared to convert between the absolute-time and civil-time domains. A time +zone's rules include things like the region's offset from the UTC time standard, +daylight-saving adjustments, and short abbreviation strings. Time zones often +have a history of disparate rules that apply only for certain periods, because +the rules may change at the whim of a region's local government. For this +reason, time-zone rules are usually compiled into data snapshots that are used +at runtime to perform conversions between absolute and civil times. There is +currently no C++ standard library supporting arbitrary time zones. + +In order for programmers to reason about and program applications that correctly +deal with these concepts, they must have a library that correctly implements the +above concepts. CCTZ adds to the existing C++11 `<chrono>` library to fully +implement the above concepts. + +* Absolute time —Â This is implemented by the existing C++11 + [`<chrono>`](https://en.cppreference.com/w/cpp/chrono) library without + modification. For example, an absolute point in time is represented by a + `std::chrono::time_point`. +* Civil time —Â This is implemented by the + [`include/cctz/civil_time.h`](https://github.com/google/cctz/blob/master/include/cctz/civil_time.h) + library that is provided as part of CCTZ. For example, a "date" is + represented by a `cctz::civil_day`. +* Time zone —Â This is implemented by the + [`include/cctz/time_zone.h`](https://github.com/google/cctz/blob/master/include/cctz/time_zone.h) + library that is provided as part of CCTZ. For example, a time zone is + represented by an instance of the class `cctz::time_zone`. + +# Examples + +## Hello February 2016 + +This "hello world" example uses a for-loop to iterate the days from the first of +February until the month of March. Each day is streamed to output, and if the +day happens to be the 29th, we also output the day of the week. + +``` +#include <iostream> +#include "cctz/civil_time.h" + +int main() { + for (cctz::civil_day d(2016, 2, 1); d < cctz::civil_month(2016, 3); ++d) { + std::cout << "Hello " << d; + if (d.day() == 29) { + std::cout << " <- leap day is a " << cctz::get_weekday(d); + } + std::cout << "\n"; + } +} +``` + +The output of the above program is + +``` +Hello 2016-02-01 +Hello 2016-02-02 +Hello 2016-02-03 +[...] +Hello 2016-02-27 +Hello 2016-02-28 +Hello 2016-02-29 <- leap day is a Monday +``` + +## One giant leap + +This example shows how to use all three libraries (`<chrono>`, civil time, and +time zone) together. In this example, we know that viewers in New York watched +Neil Armstrong's first walk on the moon on July 20, 1969 at 10:56 PM. But we'd +like to see what time it was for our friend watching in Sydney, Australia. + +``` +#include <iostream> +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" + +int main() { + cctz::time_zone nyc; + cctz::load_time_zone("America/New_York", &nyc); + + // Converts the input civil time in NYC to an absolute time. + const auto moon_walk = + cctz::convert(cctz::civil_second(1969, 7, 20, 22, 56, 0), nyc); + + std::cout << "Moon walk in NYC: " + << cctz::format("%Y-%m-%d %H:%M:%S %Ez\n", moon_walk, nyc); + + cctz::time_zone syd; + if (!cctz::load_time_zone("Australia/Sydney", &syd)) return -1; + std::cout << "Moon walk in SYD: " + << cctz::format("%Y-%m-%d %H:%M:%S %Ez\n", moon_walk, syd); +} +``` + +The output of the above program is + +``` +Moon walk in NYC: 1969-07-20 22:56:00 -04:00 +Moon walk in SYD: 1969-07-21 12:56:00 +10:00 +``` + +This example shows that the absolute time (the `std::chrono::time_point`) of the +first walk on the moon is the same no matter the time zone of the viewer (the +same time point is used in both calls to `format()`). The only difference is the +time zone in which the `moon_walk` time point is rendered. And in this case we +can see that our friend in Sydney was probably eating lunch while watching that +historic event. + +# References + +* CCTZ [FAQ](https://github.com/google/cctz/wiki/FAQ) +* See also the [Time Programming Fundamentals](https://youtu.be/2rnIHsqABfM) + talk from CppCon 2015 ([slides available here](https://goo.gl/ofof4N)). This + talk mostly describes the older CCTZ v1 API, but the *concepts* are the + same. +* ISO C++ proposal to standardize the Civil-Time Library: + https://github.com/devjgm/papers/blob/master/d0215r1.md +* ISO C++ proposal to standardize the Time-Zone Library: + https://github.com/devjgm/papers/blob/master/d0216r1.md diff --git a/contrib/libs/cctz/include/cctz/civil_time.h b/contrib/libs/cctz/include/cctz/civil_time.h new file mode 100644 index 0000000000..57bd86cc06 --- /dev/null +++ b/contrib/libs/cctz/include/cctz/civil_time.h @@ -0,0 +1,325 @@ +// 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 CCTZ_CIVIL_TIME_H_ +#define CCTZ_CIVIL_TIME_H_ + +#include "cctz/civil_time_detail.h" + +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 + +#endif // CCTZ_CIVIL_TIME_H_ diff --git a/contrib/libs/cctz/include/cctz/civil_time_detail.h b/contrib/libs/cctz/include/cctz/civil_time_detail.h new file mode 100644 index 0000000000..ea1a1dc276 --- /dev/null +++ b/contrib/libs/cctz/include/cctz/civil_time_detail.h @@ -0,0 +1,590 @@ +// 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 CCTZ_CIVIL_TIME_DETAIL_H_ +#define CCTZ_CIVIL_TIME_DETAIL_H_ + +#include <cstdint> +#include <limits> +#include <ostream> +#include <type_traits> + +// 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 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)); +} + +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) { + ey -= 400; + cd += 146097; + } + ey += (d / 146097) * 400; + 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. + ey -= 1; + d += days_per_year(ey, m); + } else { + ey -= 400; + d += 146097; + } + } + if (d > 365) { + for (;;) { + int n = days_per_century(ey, m); + if (d <= n) break; + d -= n; + ey += 100; + } + for (;;) { + int n = days_per_4years(ey, m); + if (d <= n) break; + d -= n; + ey += 4; + } + for (;;) { + int n = days_per_year(ey, m); + if (d <= n) break; + d -= n; + ++ey; + } + } + if (d > 28) { + for (;;) { + int n = days_per_month(ey, m); + if (d <= n) break; + d -= n; + if (++m > 12) { + ++ey; + 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); +} +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. +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. +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}; +} + +//////////////////////////////////////////////////////////////////////// + +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); + } + 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 { + return *this = *this + n; + } + 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--() 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 { + return civil_time(step(T{}, a.f_, n)); + } + 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 { + 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_); + } + + 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() && + (lhs.month() < rhs.month() || + (lhs.month() == rhs.month() && + (lhs.day() < rhs.day() || + (lhs.day() == rhs.day() && + (lhs.hour() < rhs.hour() || + (lhs.hour() == rhs.hour() && + (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 + +#undef CONSTEXPR_M +#undef CONSTEXPR_F +#undef CONSTEXPR_D + +#endif // CCTZ_CIVIL_TIME_DETAIL_H_ diff --git a/contrib/libs/cctz/include/cctz/time_zone.h b/contrib/libs/cctz/include/cctz/time_zone.h new file mode 100644 index 0000000000..4fc1a2a24f --- /dev/null +++ b/contrib/libs/cctz/include/cctz/time_zone.h @@ -0,0 +1,382 @@ +// 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 CCTZ_TIME_ZONE_H_ +#define CCTZ_TIME_ZONE_H_ + +#include <chrono> +#include <cstdint> +#include <string> +#include <utility> + +#include "cctz/civil_time.h" + +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> +inline std::pair<time_point<seconds>, D> +split_seconds(const time_point<D>& tp) { + auto sec = std::chrono::time_point_cast<seconds>(tp); + auto sub = tp - sec; + 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()}; +} +} // 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; + + std::string 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> + 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> + 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 + // 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. + std::string version() const; // empty when unknown + std::string description() const; + + // 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); + } + + 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 std::string& 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>; +std::string format(const std::string&, const time_point<seconds>&, + const femtoseconds&, const time_zone&); +bool parse(const std::string&, const std::string&, const time_zone&, + time_point<seconds>*, femtoseconds*, std::string* err = nullptr); +} // 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); +// std::string 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> +inline std::string format(const std::string& 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 +// 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> +inline bool parse(const std::string& fmt, const std::string& input, + const time_zone& tz, time_point<D>* tpp) { + time_point<seconds> sec; + detail::femtoseconds fs; + const bool b = detail::parse(fmt, input, tz, &sec, &fs); + if (b) { + // TODO: Return false if unrepresentable as a time_point<D>. + *tpp = std::chrono::time_point_cast<D>(sec); + *tpp += std::chrono::duration_cast<D>(fs); + } + return b; +} + +// Access to convert functions which are placed in time_zone_if.h +time_point<seconds> UnixSecondsToTimePoint(std::int_fast64_t); +std::int_fast64_t TimePointToUnixSeconds(const time_point<seconds>& tp); + +} // namespace cctz + +#endif // CCTZ_TIME_ZONE_H_ diff --git a/contrib/libs/cctz/include/cctz/zone_info_source.h b/contrib/libs/cctz/include/cctz/zone_info_source.h new file mode 100644 index 0000000000..08e91b3c1f --- /dev/null +++ b/contrib/libs/cctz/include/cctz/zone_info_source.h @@ -0,0 +1,88 @@ +// 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 CCTZ_ZONE_INFO_SOURCE_H_ +#define CCTZ_ZONE_INFO_SOURCE_H_ + +#include <cstddef> +#include <functional> +#include <memory> +#include <string> + +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 + // implementation returns an empty string. + virtual std::string Version() const; +}; + +} // namespace cctz + +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<cctz::ZoneInfoSource> (*)( + const std::string&, + const std::function<std::unique_ptr<cctz::ZoneInfoSource>( + const std::string&)>&); + +// 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 std::string& name, +// const std::function<std::unique_ptr<cctz::ZoneInfoSource>( +// const std::string& 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 + +#endif // CCTZ_ZONE_INFO_SOURCE_H_ diff --git a/contrib/libs/cctz/src/civil_time_detail.cc b/contrib/libs/cctz/src/civil_time_detail.cc new file mode 100644 index 0000000000..b6856b8df4 --- /dev/null +++ b/contrib/libs/cctz/src/civil_time_detail.cc @@ -0,0 +1,86 @@ +// 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 "cctz/civil_time_detail.h" + +#include <iomanip> +#include <ostream> +#include <sstream> + +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 diff --git a/contrib/libs/cctz/src/time_zone_fixed.cc b/contrib/libs/cctz/src/time_zone_fixed.cc new file mode 100644 index 0000000000..ce79822ada --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_fixed.cc @@ -0,0 +1,134 @@ +// 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 <string> + +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 std::string& name, seconds* offset) { + if (name.compare(0, std::string::npos, "UTC", 3) == 0) { + *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; + 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; +} + +std::string 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"; + } + 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 (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; + ep = Format02d(ep, offset_hours); + *ep++ = ':'; + ep = Format02d(ep, offset_minutes); + *ep++ = ':'; + ep = Format02d(ep, offset_seconds); + *ep++ = '\0'; + assert(ep == buf + sizeof(buf)); + return buf; +} + +std::string FixedOffsetToAbbr(const seconds& offset) { + std::string 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 diff --git a/contrib/libs/cctz/src/time_zone_fixed.h b/contrib/libs/cctz/src/time_zone_fixed.h new file mode 100644 index 0000000000..f37226ff46 --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_fixed.h @@ -0,0 +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. + +#ifndef CCTZ_TIME_ZONE_FIXED_H_ +#define CCTZ_TIME_ZONE_FIXED_H_ + +#include <string> + +#include "cctz/time_zone.h" + +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 std::string& name, seconds* offset); +std::string FixedOffsetToName(const seconds& offset); +std::string FixedOffsetToAbbr(const seconds& offset); + +} // namespace cctz + +#endif // CCTZ_TIME_ZONE_FIXED_H_ diff --git a/contrib/libs/cctz/src/time_zone_format.cc b/contrib/libs/cctz/src/time_zone_format.cc new file mode 100644 index 0000000000..b57371314e --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_format.cc @@ -0,0 +1,1022 @@ +// 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 +# if !defined(_XOPEN_SOURCE) +# define _XOPEN_SOURCE // Definedness suffices for strptime. +# endif +#endif + +#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 <string> +#include <vector> +#if !HAS_STRPTIME +#include <iomanip> +#include <sstream> +#endif + +#include "cctz/civil_time.h" +#include "time_zone_if.h" + +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) { + case weekday::sunday: + return 0; + case weekday::monday: + return 1; + case weekday::tuesday: + return 2; + case weekday::wednesday: + return 3; + case weekday::thursday: + return 4; + case weekday::friday: + return 5; + case weekday::saturday: + return 6; + } + return 0; /*NOTREACHED*/ +} + +// Convert a tm_wday value (0-6, Sunday = 0) to a cctz::weekday. +weekday FromTmWday(int tm_wday) { + switch (tm_wday) { + case 0: + return weekday::sunday; + case 1: + return weekday::monday; + case 2: + return weekday::tuesday; + case 3: + return weekday::wednesday; + case 4: + return weekday::thursday; + case 5: + return weekday::friday; + case 6: + return weekday::saturday; + } + 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); + } + + 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; +} + +// 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) { + const civil_day d(cd.year() % 400, cd.month(), cd.day()); + 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). +void FormatTM(std::string* out, const std::string& 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, + // 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) +// - %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). +std::string format(const std::string& format, const time_point<seconds>& tp, + const detail::femtoseconds& fs, const time_zone& tz) { + std::string 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. + if (strchr("YmdeUuWwHMSzZs%", *cur)) { + if (cur - 1 != pending) { + FormatTM(&result, std::string(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; + case 'U': + bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::sunday)); + result.append(bp, static_cast<std::size_t>(ep - bp)); + break; + case 'u': + bp = Format64(ep, 0, tm.tm_wday ? tm.tm_wday : 7); + result.append(bp, static_cast<std::size_t>(ep - bp)); + break; + case 'W': + bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::monday)); + result.append(bp, static_cast<std::size_t>(ep - bp)); + break; + case 'w': + 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) { + FormatTM(&result, std::string(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) { + FormatTM(&result, std::string(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) { + FormatTM(&result, std::string(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. + if (*cur == 'T') { + // Formats %ET. + if (cur - 2 != pending) { + FormatTM(&result, std::string(pending, cur - 2), tm); + } + result.append("T"); + pending = ++cur; + } else if (*cur == 'z') { + // Formats %Ez. + if (cur - 2 != pending) { + FormatTM(&result, std::string(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) { + FormatTM(&result, std::string(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) { + FormatTM(&result, std::string(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) { + FormatTM(&result, std::string(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) { + FormatTM(&result, std::string(pending, cur - 2), tm); + } + 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) { + FormatTM(&result, std::string(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; + } + } else if (first == 'Z' || first == 'z') { // Zulu + *offset = 0; + } else { + dp = nullptr; + } + } + return dp; +} + +const char* ParseZone(const char* dp, std::string* 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; +} + +// 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. +bool FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) { + const civil_year y(*year % 400); + civil_day cd = prev_weekday(y, week_start); // week 0 + cd = next_weekday(cd - 1, FromTmWday(tm->tm_wday)) + (week_num * 7); + if (const year_t shift = cd.year() - y.year()) { + if (shift > 0) { + if (*year > std::numeric_limits<year_t>::max() - shift) return false; + } else { + if (*year < std::numeric_limits<year_t>::min() - shift) return false; + } + *year += shift; + } + tm->tm_mon = cd.month() - 1; + tm->tm_mday = cd.day(); + 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 +// 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. +bool parse(const std::string& format, const std::string& input, + const time_zone& tz, time_point<seconds>* sec, + detail::femtoseconds* fs, std::string* 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. + std::string zone = "UTC"; + + 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; + week_num = -1; + continue; + case 'd': + case 'e': + data = ParseInt(data, 2, 1, 31, &tm.tm_mday); + week_num = -1; + continue; + case 'U': + data = ParseInt(data, 0, 0, 53, &week_num); + week_start = weekday::sunday; + continue; + case 'W': + data = ParseInt(data, 0, 0, 53, &week_num); + week_start = weekday::monday; + continue; + case 'u': + data = ParseInt(data, 0, 1, 7, &tm.tm_wday); + if (data != nullptr) tm.tm_wday %= 7; + continue; + 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': + 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 (fmt[0] == 'T') { + if (*data == 'T' || *data == 't') { + ++data; + ++fmt; + } else { + data = nullptr; + } + 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; + std::string 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) { + std::string 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; + + // 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; + } + + // 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)) { + if (err != nullptr) *err = "Out-of-range field"; + return false; + } + } + + 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 diff --git a/contrib/libs/cctz/src/time_zone_if.cc b/contrib/libs/cctz/src/time_zone_if.cc new file mode 100644 index 0000000000..a80dbcd60d --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_if.cc @@ -0,0 +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" +#include "time_zone_info.h" +#include "time_zone_libc.h" + +namespace cctz { + +std::unique_ptr<TimeZoneIf> TimeZoneIf::Load(const std::string& 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() {} + +time_point<seconds> UnixSecondsToTimePoint(std::int_fast64_t seconds) { + return FromUnixSeconds(seconds); +} + +std::int_fast64_t TimePointToUnixSeconds(const time_point<seconds>& tp) { + return ToUnixSeconds(tp); +} + +} // namespace cctz diff --git a/contrib/libs/cctz/src/time_zone_if.h b/contrib/libs/cctz/src/time_zone_if.h new file mode 100644 index 0000000000..f925c6c55a --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_if.h @@ -0,0 +1,68 @@ +// 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 CCTZ_TIME_ZONE_IF_H_ +#define CCTZ_TIME_ZONE_IF_H_ + +#include <chrono> +#include <cstdint> +#include <memory> +#include <string> + +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" + +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 std::string& name); + + 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 std::string Version() const = 0; + virtual std::string 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 +// Unix clock are second aligned, but not that they share an epoch. +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>( + std::chrono::system_clock::from_time_t(0)) + seconds(t); +} + +} // namespace cctz + +#endif // CCTZ_TIME_ZONE_IF_H_ diff --git a/contrib/libs/cctz/src/time_zone_impl.cc b/contrib/libs/cctz/src/time_zone_impl.cc new file mode 100644 index 0000000000..6e077505c1 --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_impl.cc @@ -0,0 +1,108 @@ +// 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 <string> +#include <unordered_map> +#include <utility> + +#include "time_zone_fixed.h" + +namespace cctz { + +namespace { + +// time_zone::Impls are linked into a map to support fast lookup by name. +using TimeZoneImplByName = + std::unordered_map<std::string, 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 + +time_zone time_zone::Impl::UTC() { + return time_zone(UTCImpl()); +} + +bool time_zone::Impl::LoadTimeZone(const std::string& 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; + } + + // 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; + } + } + } + + // 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]; + 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(); + } +} + +time_zone::Impl::Impl(const std::string& name) + : name_(name), zone_(TimeZoneIf::Load(name_)) {} + +const time_zone::Impl* time_zone::Impl::UTCImpl() { + static const Impl* utc_impl = new Impl("UTC"); // never fails + return utc_impl; +} + +} // namespace cctz diff --git a/contrib/libs/cctz/src/time_zone_impl.h b/contrib/libs/cctz/src/time_zone_impl.h new file mode 100644 index 0000000000..23fcddb690 --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_impl.h @@ -0,0 +1,86 @@ +// 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 CCTZ_TIME_ZONE_IMPL_H_ +#define CCTZ_TIME_ZONE_IMPL_H_ + +#include <memory> +#include <string> + +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" +#include "time_zone_if.h" +#include "time_zone_info.h" + +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 std::string& 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"). + const std::string& 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); + } + + // Returns an implementation-defined version string for this time zone. + std::string Version() const { return zone_->Version(); } + + // Returns an implementation-defined description of this time zone. + std::string Description() const { return zone_->Description(); } + + private: + explicit Impl(const std::string& name); + static const Impl* UTCImpl(); + + const std::string name_; + std::unique_ptr<TimeZoneIf> zone_; +}; + +} // namespace cctz + +#endif // CCTZ_TIME_ZONE_IMPL_H_ diff --git a/contrib/libs/cctz/src/time_zone_info.cc b/contrib/libs/cctz/src/time_zone_info.cc new file mode 100644 index 0000000000..1b3dc15cf1 --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_info.cc @@ -0,0 +1,978 @@ +// 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 <functional> +#include <memory> +#include <sstream> +#include <string> + +#include "cctz/civil_time.h" +#include "time_zone_fixed.h" +#include "time_zone_posix.h" + +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] = { + 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) { + case weekday::sunday: + return 0; + case weekday::monday: + return 1; + case weekday::tuesday: + return 2; + case weekday::wednesday: + return 3; + case weekday::thursday: + return 4; + case weekday::friday: + return 5; + case weekday::saturday: + return 6; + } + 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) { + 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; + + // 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 : { + -(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 + 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); + 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]); + 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; +} + +// Find/make a transition type with these attributes. +bool TimeZoneInfo::GetTransitionType(std::int_fast32_t utc_offset, bool is_dst, + const std::string& abbr, + std::uint_least8_t* index) { + std::size_t type_index = 0; + std::size_t abbr_index = abbreviations_.size(); + for (; type_index != transition_types_.size(); ++type_index) { + const TransitionType& tt(transition_types_[type_index]); + const char* tt_abbr = &abbreviations_[tt.abbr_index]; + if (tt_abbr == abbr) abbr_index = tt.abbr_index; + if (tt.utc_offset == utc_offset && tt.is_dst == is_dst) { + if (abbr_index == tt.abbr_index) break; // reuse + } + } + if (type_index > 255 || abbr_index > 255) { + // No index space (8 bits) available for a new type or abbreviation. + return false; + } + if (type_index == transition_types_.size()) { + TransitionType& tt(*transition_types_.emplace(transition_types_.end())); + tt.utc_offset = static_cast<std::int_least32_t>(utc_offset); + tt.is_dst = is_dst; + if (abbr_index == abbreviations_.size()) { + abbreviations_.append(abbr); + abbreviations_.append(1, '\0'); + } + tt.abbr_index = static_cast<std::uint_least8_t>(abbr_index); + } + *index = static_cast<std::uint_least8_t>(type_index); + return true; +} + +// 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; + if (future_spec_.empty()) return true; // last transition prevails + + 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. + // We may need two additional transitions for the current year. + transitions_.reserve(transitions_.size() + 400 * 2 + 2); + 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]); + last_year_ = LocalTime(last_time, last_tt).cs.year(); + bool leap_year = IsLeap(last_year_); + 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_) { + auto dst_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_start); + auto std_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_end); + dst.unix_time = jan1_time + dst_trans_off - posix.std_offset; + std.unix_time = jan1_time + std_trans_off - posix.dst_offset; + const auto* ta = dst.unix_time < std.unix_time ? &dst : &std; + const auto* tb = dst.unix_time < std.unix_time ? &std : &dst; + if (last_time < tb->unix_time) { + if (last_time < ta->unix_time) transitions_.push_back(*ta); + transitions_.push_back(*tb); + } + if (last_year_ == limit) break; + 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; + 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 (!hdr.Build(tzh)) + return false; + 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. + 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 (tzh.tzh_version[0] == '\0') + return false; + if (!hdr.Build(tzh)) + return false; + 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.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); + if (zip->Read(tbuf.data(), len) != len) + return false; + 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++); + 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. + 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++); + 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; + 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. + 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; + }; + if (get_char(zip) != '\n') + return false; + 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 + // 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 + // 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())); + 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. + 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 + // previous transition is always representable, without overflow. + const Transition& last(transitions_.back()); + if (last.unix_time < 0) { + const std::uint_fast8_t type_index = last.type_index; + Transition& tr(*transitions_.emplace(transitions_.end())); + tr.unix_time = 2147483647; // 2038-01-19T03:14:07+00:00 + 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 { + +// fopen(3) adaptor. +inline FILE* FOpen(const char* path, const char* mode) { +#if defined(_MSC_VER) + FILE* fp; + if (fopen_s(&fp, path, mode) != 0) fp = nullptr; + return fp; +#else + return fopen(path, mode); // TODO: Enable the close-on-exec flag. +#endif +} + +// A stdio(3)-backed implementation of ZoneInfoSource. +class FileZoneInfoSource : public ZoneInfoSource { + public: + static std::unique_ptr<ZoneInfoSource> Open(const std::string& 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::string Version() const override { + // TODO: It would nice if the zoneinfo data included the tzdb version. + return std::string(); + } + + protected: + explicit FileZoneInfoSource( + FILE* fp, std::size_t len = std::numeric_limits<std::size_t>::max()) + : fp_(fp, fclose), len_(len) {} + + private: + std::unique_ptr<FILE, int(*)(FILE*)> fp_; + std::size_t len_; +}; + +std::unique_ptr<ZoneInfoSource> FileZoneInfoSource::Open( + const std::string& 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. + std::string 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 + } + path.append(name, pos, std::string::npos); + + // Open the zoneinfo file. + FILE* fp = FOpen(path.c_str(), "rb"); + if (fp == nullptr) return nullptr; + std::size_t length = 0; + if (fseek(fp, 0, SEEK_END) == 0) { + long offset = ftell(fp); + if (offset >= 0) { + length = static_cast<std::size_t>(offset); + } + rewind(fp); + } + return std::unique_ptr<ZoneInfoSource>(new FileZoneInfoSource(fp, length)); +} + +class AndroidZoneInfoSource : public FileZoneInfoSource { + public: + static std::unique_ptr<ZoneInfoSource> Open(const std::string& name); + std::string Version() const override { return version_; } + + private: + explicit AndroidZoneInfoSource(FILE* fp, std::size_t len, const char* vers) + : FileZoneInfoSource(fp, len), version_(vers) {} + std::string version_; +}; + +std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open( + const std::string& 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"}) { + std::unique_ptr<FILE, int (*)(FILE*)> fp(FOpen(tzdata, "rb"), fclose); + if (fp.get() == 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( + fp.release(), static_cast<std::size_t>(length), vers)); + } + } + } + + return nullptr; +} + +} // namespace + +bool TimeZoneInfo::Load(const std::string& 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( + name, [](const std::string& n) -> std::unique_ptr<ZoneInfoSource> { + if (auto z = FileZoneInfoSource::Open(n)) return z; + if (auto z = AndroidZoneInfoSource::Open(n)) return z; + 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). + return {(civil_second() + unix_time) + tt.utc_offset, + tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]}; +} + +// 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. + tt.utc_offset, tt.is_dst, &abbreviations_[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)); +} + +std::string TimeZoneInfo::Version() const { + return version_; +} + +std::string TimeZoneInfo::Description() const { + std::ostringstream oss; + oss << "#trans=" << transitions_.size(); + oss << " #types=" << transition_types_.size(); + oss << " spec='" << future_spec_ << "'"; + return oss.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)) { + // 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()}; + 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)) { + // 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()}; + 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 diff --git a/contrib/libs/cctz/src/time_zone_info.h b/contrib/libs/cctz/src/time_zone_info.h new file mode 100644 index 0000000000..431dc5b71b --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_info.h @@ -0,0 +1,131 @@ +// 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 CCTZ_TIME_ZONE_INFO_H_ +#define CCTZ_TIME_ZONE_INFO_H_ + +#include <atomic> +#include <cstddef> +#include <cstdint> +#include <string> +#include <vector> + +#include "cctz/civil_time.h" +#include "cctz/time_zone.h" +#include "cctz/zone_info_source.h" +#include "time_zone_if.h" +#include "tzfile.h" + +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 std::string& name); + + // 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; + std::string Version() const override; + std::string Description() const override; + + 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; + }; + + bool GetTransitionType(std::int_fast32_t utc_offset, bool is_dst, + const std::string& abbr, std::uint_least8_t* index); + bool EquivTransitions(std::uint_fast8_t tt1_index, + std::uint_fast8_t tt2_index) const; + bool ExtendTransitions(); + + 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 + std::uint_fast8_t default_transition_type_; // for before first transition + std::string abbreviations_; // all the NUL-terminated abbreviations + + std::string version_; // the tzdata version if available + std::string 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 + +#endif // CCTZ_TIME_ZONE_INFO_H_ diff --git a/contrib/libs/cctz/src/time_zone_libc.cc b/contrib/libs/cctz/src/time_zone_libc.cc new file mode 100644 index 0000000000..f185b957b6 --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_libc.cc @@ -0,0 +1,311 @@ +// 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 "cctz/civil_time.h" +#include "cctz/time_zone.h" + +#if defined(_AIX) +extern "C" { + extern long altzone; +} +#endif + +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) +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 + +inline std::tm* gm_time(const std::time_t *timep, std::tm *result) { +#if defined(_WIN32) || defined(_WIN64) + return gmtime_s(result, timep) ? nullptr : result; +#else + return gmtime_r(timep, result); +#endif +} + +inline std::tm* local_time(const std::time_t *timep, std::tm *result) { +#if defined(_WIN32) || defined(_WIN64) + return localtime_s(result, timep) ? nullptr : result; +#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; + 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) { + tmp = local_time(&lo, &tm); + if (tmp != nullptr) { + if (tm_gmtoff(*tmp) == offset) break; + } + } + return lo; + } + } + return hi; +} + +} // namespace + +TimeZoneLibC::TimeZoneLibC(const std::string& 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}; + 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()); + 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; +} + +std::string TimeZoneLibC::Version() const { + return std::string(); // unknown +} + +std::string TimeZoneLibC::Description() const { + return local_ ? "localtime" : "UTC"; +} + +} // namespace cctz diff --git a/contrib/libs/cctz/src/time_zone_libc.h b/contrib/libs/cctz/src/time_zone_libc.h new file mode 100644 index 0000000000..4cfe6dae31 --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_libc.h @@ -0,0 +1,49 @@ +// 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 CCTZ_TIME_ZONE_LIBC_H_ +#define CCTZ_TIME_ZONE_LIBC_H_ + +#include <string> + +#include "time_zone_if.h" + +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 std::string& name); + + // 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; + std::string Version() const override; + std::string Description() const override; + + private: + const bool local_; // localtime or UTC +}; + +} // namespace cctz + +#endif // CCTZ_TIME_ZONE_LIBC_H_ diff --git a/contrib/libs/cctz/src/time_zone_lookup.cc b/contrib/libs/cctz/src/time_zone_lookup.cc new file mode 100644 index 0000000000..92eb2ae763 --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_lookup.cc @@ -0,0 +1,183 @@ +// 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 "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 + +#include <cstdlib> +#include <cstring> +#include <string> + +#include "time_zone_fixed.h" +#include "time_zone_impl.h" + +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 + +std::string 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); +} + +std::string time_zone::version() const { + return effective_impl().Version(); +} + +std::string 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_; +} + +bool load_time_zone(const std::string& 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 + + // 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 std::string 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 diff --git a/contrib/libs/cctz/src/time_zone_posix.cc b/contrib/libs/cctz/src/time_zone_posix.cc new file mode 100644 index 0000000000..847db17cbc --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_posix.cc @@ -0,0 +1,151 @@ +// 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 <string> + +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, std::string* 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 ] +bool ParsePosixSpec(const std::string& 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 diff --git a/contrib/libs/cctz/src/time_zone_posix.h b/contrib/libs/cctz/src/time_zone_posix.h new file mode 100644 index 0000000000..aea93efdff --- /dev/null +++ b/contrib/libs/cctz/src/time_zone_posix.h @@ -0,0 +1,124 @@ +// 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 CCTZ_TIME_ZONE_POSIX_H_ +#define CCTZ_TIME_ZONE_POSIX_H_ + +#include <cstdint> +#include <string> + +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 { + std::string std_abbr; + std::int_fast32_t std_offset; + + std::string 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). +bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res); + +} // namespace cctz + +#endif // CCTZ_TIME_ZONE_POSIX_H_ diff --git a/contrib/libs/cctz/src/tzfile.h b/contrib/libs/cctz/src/tzfile.h new file mode 100644 index 0000000000..ee91104443 --- /dev/null +++ b/contrib/libs/cctz/src/tzfile.h @@ -0,0 +1,123 @@ +/* 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 +#define TZDEFAULT "/etc/localtime" +#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. . . +*/ + +#define TZ_MAGIC "TZif" + +struct tzhead { + char tzh_magic[4]; /* TZ_MAGIC */ + char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */ + char tzh_reserved[15]; /* reserved; must be zero */ + char tzh_ttisutcnt[4]; /* coded number of trans. time flags */ + char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ + char tzh_leapcnt[4]; /* coded number of leap seconds */ + 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, +** 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. +** 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 +#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. */ +#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */ +#endif /* !defined TZ_MAX_TYPES */ + +#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 +#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */ +#endif /* !defined TZ_MAX_LEAPS */ + +#endif /* !defined TZFILE_H */ diff --git a/contrib/libs/cctz/src/zone_info_source.cc b/contrib/libs/cctz/src/zone_info_source.cc new file mode 100644 index 0000000000..e2491da757 --- /dev/null +++ b/contrib/libs/cctz/src/zone_info_source.cc @@ -0,0 +1,73 @@ +// 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 "cctz/zone_info_source.h" + +namespace cctz { + +// Defined out-of-line to avoid emitting a weak vtable in all TUs. +ZoneInfoSource::~ZoneInfoSource() {} +std::string ZoneInfoSource::Version() const { return std::string(); } + +} // namespace cctz + +namespace cctz_extension { + +namespace { + +// A default for cctz_extension::zone_info_source_factory, which simply +// defers to the fallback factory. +std::unique_ptr<cctz::ZoneInfoSource> DefaultFactory( + const std::string& name, + const std::function<std::unique_ptr<cctz::ZoneInfoSource>( + const std::string& 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__) && !defined(_MSC_VER) +ZoneInfoSourceFactory zone_info_source_factory + __attribute__((weak)) = DefaultFactory; +#elif defined(_MSC_VER) && !defined(__MINGW32__) +extern ZoneInfoSourceFactory zone_info_source_factory; +extern ZoneInfoSourceFactory default_factory; +ZoneInfoSourceFactory default_factory = DefaultFactory; +#if defined(_M_IX86) +#pragma comment( \ + linker, \ + "/alternatename:?zone_info_source_factory@cctz_extension@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@3@@ZA=?default_factory@cctz_extension@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@3@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@3@@ZA") +#elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM) || \ + defined(_M_ARM64) +#pragma comment( \ + linker, \ + "/alternatename:?zone_info_source_factory@cctz_extension@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@__y1@std@@@__y1@std@@AEBV?$basic_string@DU?$char_traits@D@__y1@std@@V?$allocator@D@23@@34@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@__y1@std@@@__y1@std@@AEBV?$basic_string@DU?$char_traits@D@__y1@std@@V?$allocator@D@23@@23@@Z@34@@ZEA=?default_factory@cctz_extension@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@__y1@std@@@__y1@std@@AEBV?$basic_string@DU?$char_traits@D@__y1@std@@V?$allocator@D@23@@34@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@@U?$default_delete@VZoneInfoSource@cctz@@@__y1@std@@@__y1@std@@AEBV?$basic_string@DU?$char_traits@D@__y1@std@@V?$allocator@D@23@@23@@Z@34@@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 diff --git a/contrib/libs/cctz/test/.yandex_meta/licenses.list.txt b/contrib/libs/cctz/test/.yandex_meta/licenses.list.txt new file mode 100644 index 0000000000..aa1605a0ac --- /dev/null +++ b/contrib/libs/cctz/test/.yandex_meta/licenses.list.txt @@ -0,0 +1,16 @@ +====================Apache-2.0==================== +// 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==================== +// Copyright 2016 Google Inc. All Rights Reserved. diff --git a/contrib/libs/cctz/test/civil_time_test.cc b/contrib/libs/cctz/test/civil_time_test.cc new file mode 100644 index 0000000000..5ec0ca8d38 --- /dev/null +++ b/contrib/libs/cctz/test/civil_time_test.cc @@ -0,0 +1,1065 @@ +// 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 "cctz/civil_time.h" + +#include <iomanip> +#include <limits> +#include <sstream> +#include <string> +#include <type_traits> + +#include "gtest/gtest.h" + +namespace cctz { + +namespace { + +template <typename T> +std::string Format(const T& t) { + std::stringstream ss; + ss << t; + return ss.str(); +} + +} // namespace + +#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) +// Construction constexpr tests + +TEST(CivilTime, Normal) { + constexpr civil_second css(2016, 1, 28, 17, 14, 12); + static_assert(css.second() == 12, "Normal.second"); + constexpr civil_minute cmm(2016, 1, 28, 17, 14); + static_assert(cmm.minute() == 14, "Normal.minute"); + constexpr civil_hour chh(2016, 1, 28, 17); + static_assert(chh.hour() == 17, "Normal.hour"); + constexpr civil_day cd(2016, 1, 28); + static_assert(cd.day() == 28, "Normal.day"); + constexpr civil_month cm(2016, 1); + static_assert(cm.month() == 1, "Normal.month"); + constexpr civil_year cy(2016); + static_assert(cy.year() == 2016, "Normal.year"); +} + +TEST(CivilTime, Conversion) { + constexpr civil_year cy(2016); + static_assert(cy.year() == 2016, "Conversion.year"); + constexpr civil_month cm(cy); + static_assert(cm.month() == 1, "Conversion.month"); + constexpr civil_day cd(cm); + static_assert(cd.day() == 1, "Conversion.day"); + constexpr civil_hour chh(cd); + static_assert(chh.hour() == 0, "Conversion.hour"); + constexpr civil_minute cmm(chh); + static_assert(cmm.minute() == 0, "Conversion.minute"); + constexpr civil_second css(cmm); + static_assert(css.second() == 0, "Conversion.second"); +} + +// Normalization constexpr tests + +TEST(CivilTime, Normalized) { + constexpr civil_second cs(2016, 1, 28, 17, 14, 12); + static_assert(cs.year() == 2016, "Normalized.year"); + static_assert(cs.month() == 1, "Normalized.month"); + static_assert(cs.day() == 28, "Normalized.day"); + static_assert(cs.hour() == 17, "Normalized.hour"); + static_assert(cs.minute() == 14, "Normalized.minute"); + static_assert(cs.second() == 12, "Normalized.second"); +} + +TEST(CivilTime, SecondOverflow) { + constexpr civil_second cs(2016, 1, 28, 17, 14, 121); + static_assert(cs.year() == 2016, "SecondOverflow.year"); + static_assert(cs.month() == 1, "SecondOverflow.month"); + static_assert(cs.day() == 28, "SecondOverflow.day"); + static_assert(cs.hour() == 17, "SecondOverflow.hour"); + static_assert(cs.minute() == 16, "SecondOverflow.minute"); + static_assert(cs.second() == 1, "SecondOverflow.second"); +} + +TEST(CivilTime, SecondUnderflow) { + constexpr civil_second cs(2016, 1, 28, 17, 14, -121); + static_assert(cs.year() == 2016, "SecondUnderflow.year"); + static_assert(cs.month() == 1, "SecondUnderflow.month"); + static_assert(cs.day() == 28, "SecondUnderflow.day"); + static_assert(cs.hour() == 17, "SecondUnderflow.hour"); + static_assert(cs.minute() == 11, "SecondUnderflow.minute"); + static_assert(cs.second() == 59, "SecondUnderflow.second"); +} + +TEST(CivilTime, MinuteOverflow) { + constexpr civil_second cs(2016, 1, 28, 17, 121, 12); + static_assert(cs.year() == 2016, "MinuteOverflow.year"); + static_assert(cs.month() == 1, "MinuteOverflow.month"); + static_assert(cs.day() == 28, "MinuteOverflow.day"); + static_assert(cs.hour() == 19, "MinuteOverflow.hour"); + static_assert(cs.minute() == 1, "MinuteOverflow.minute"); + static_assert(cs.second() == 12, "MinuteOverflow.second"); +} + +TEST(CivilTime, MinuteUnderflow) { + constexpr civil_second cs(2016, 1, 28, 17, -121, 12); + static_assert(cs.year() == 2016, "MinuteUnderflow.year"); + static_assert(cs.month() == 1, "MinuteUnderflow.month"); + static_assert(cs.day() == 28, "MinuteUnderflow.day"); + static_assert(cs.hour() == 14, "MinuteUnderflow.hour"); + static_assert(cs.minute() == 59, "MinuteUnderflow.minute"); + static_assert(cs.second() == 12, "MinuteUnderflow.second"); +} + +TEST(CivilTime, HourOverflow) { + constexpr civil_second cs(2016, 1, 28, 49, 14, 12); + static_assert(cs.year() == 2016, "HourOverflow.year"); + static_assert(cs.month() == 1, "HourOverflow.month"); + static_assert(cs.day() == 30, "HourOverflow.day"); + static_assert(cs.hour() == 1, "HourOverflow.hour"); + static_assert(cs.minute() == 14, "HourOverflow.minute"); + static_assert(cs.second() == 12, "HourOverflow.second"); +} + +TEST(CivilTime, HourUnderflow) { + constexpr civil_second cs(2016, 1, 28, -49, 14, 12); + static_assert(cs.year() == 2016, "HourUnderflow.year"); + static_assert(cs.month() == 1, "HourUnderflow.month"); + static_assert(cs.day() == 25, "HourUnderflow.day"); + static_assert(cs.hour() == 23, "HourUnderflow.hour"); + static_assert(cs.minute() == 14, "HourUnderflow.minute"); + static_assert(cs.second() == 12, "HourUnderflow.second"); +} + +TEST(CivilTime, MonthOverflow) { + constexpr civil_second cs(2016, 25, 28, 17, 14, 12); + static_assert(cs.year() == 2018, "MonthOverflow.year"); + static_assert(cs.month() == 1, "MonthOverflow.month"); + static_assert(cs.day() == 28, "MonthOverflow.day"); + static_assert(cs.hour() == 17, "MonthOverflow.hour"); + static_assert(cs.minute() == 14, "MonthOverflow.minute"); + static_assert(cs.second() == 12, "MonthOverflow.second"); +} + +TEST(CivilTime, MonthUnderflow) { + constexpr civil_second cs(2016, -25, 28, 17, 14, 12); + static_assert(cs.year() == 2013, "MonthUnderflow.year"); + static_assert(cs.month() == 11, "MonthUnderflow.month"); + static_assert(cs.day() == 28, "MonthUnderflow.day"); + static_assert(cs.hour() == 17, "MonthUnderflow.hour"); + static_assert(cs.minute() == 14, "MonthUnderflow.minute"); + static_assert(cs.second() == 12, "MonthUnderflow.second"); +} + +TEST(CivilTime, C4Overflow) { + constexpr civil_second cs(2016, 1, 292195, 17, 14, 12); + static_assert(cs.year() == 2816, "C4Overflow.year"); + static_assert(cs.month() == 1, "C4Overflow.month"); + static_assert(cs.day() == 1, "C4Overflow.day"); + static_assert(cs.hour() == 17, "C4Overflow.hour"); + static_assert(cs.minute() == 14, "C4Overflow.minute"); + static_assert(cs.second() == 12, "C4Overflow.second"); +} + +TEST(CivilTime, C4Underflow) { + constexpr civil_second cs(2016, 1, -292195, 17, 14, 12); + static_assert(cs.year() == 1215, "C4Underflow.year"); + static_assert(cs.month() == 12, "C4Underflow.month"); + static_assert(cs.day() == 30, "C4Underflow.day"); + static_assert(cs.hour() == 17, "C4Underflow.hour"); + static_assert(cs.minute() == 14, "C4Underflow.minute"); + static_assert(cs.second() == 12, "C4Underflow.second"); +} + +TEST(CivilTime, MixedNormalization) { + constexpr civil_second cs(2016, -42, 122, 99, -147, 4949); + static_assert(cs.year() == 2012, "MixedNormalization.year"); + static_assert(cs.month() == 10, "MixedNormalization.month"); + static_assert(cs.day() == 4, "MixedNormalization.day"); + static_assert(cs.hour() == 1, "MixedNormalization.hour"); + static_assert(cs.minute() == 55, "MixedNormalization.minute"); + static_assert(cs.second() == 29, "MixedNormalization.second"); +} + +// Relational constexpr tests + +TEST(CivilTime, Less) { + constexpr civil_second cs1(2016, 1, 28, 17, 14, 12); + constexpr civil_second cs2(2016, 1, 28, 17, 14, 13); + constexpr bool less = cs1 < cs2; + static_assert(less, "Less"); +} + +// Arithmetic constexpr tests + +TEST(CivilTime, Addition) { + constexpr civil_second cs1(2016, 1, 28, 17, 14, 12); + constexpr civil_second cs2 = cs1 + 50; + static_assert(cs2.year() == 2016, "Addition.year"); + static_assert(cs2.month() == 1, "Addition.month"); + static_assert(cs2.day() == 28, "Addition.day"); + static_assert(cs2.hour() == 17, "Addition.hour"); + static_assert(cs2.minute() == 15, "Addition.minute"); + static_assert(cs2.second() == 2, "Addition.second"); +} + +TEST(CivilTime, Subtraction) { + constexpr civil_second cs1(2016, 1, 28, 17, 14, 12); + constexpr civil_second cs2 = cs1 - 50; + static_assert(cs2.year() == 2016, "Subtraction.year"); + static_assert(cs2.month() == 1, "Subtraction.month"); + static_assert(cs2.day() == 28, "Subtraction.day"); + static_assert(cs2.hour() == 17, "Subtraction.hour"); + static_assert(cs2.minute() == 13, "Subtraction.minute"); + static_assert(cs2.second() == 22, "Subtraction.second"); +} + +TEST(CivilTime, Difference) { + constexpr civil_day cd1(2016, 1, 28); + constexpr civil_day cd2(2015, 1, 28); + constexpr int diff = cd1 - cd2; + static_assert(diff == 365, "Difference"); +} + +// NOTE: Run this with --copt=-ftrapv to detect overflow problems. +TEST(CivilTime, ConstructionWithHugeYear) { + constexpr civil_hour h(-9223372036854775807, 1, 1, -1); + static_assert(h.year() == -9223372036854775807 - 1, + "ConstructionWithHugeYear"); + static_assert(h.month() == 12, "ConstructionWithHugeYear"); + static_assert(h.day() == 31, "ConstructionWithHugeYear"); + static_assert(h.hour() == 23, "ConstructionWithHugeYear"); +} + +// NOTE: Run this with --copt=-ftrapv to detect overflow problems. +TEST(CivilTime, DifferenceWithHugeYear) { + { + constexpr civil_day d1(9223372036854775807, 1, 1); + constexpr civil_day d2(9223372036854775807, 12, 31); + static_assert(d2 - d1 == 364, "DifferenceWithHugeYear"); + } + { + constexpr civil_day d1(-9223372036854775807 - 1, 1, 1); + constexpr civil_day d2(-9223372036854775807 - 1, 12, 31); + static_assert(d2 - d1 == 365, "DifferenceWithHugeYear"); + } + { + // Check the limits of the return value at the end of the year range. + constexpr civil_day d1(9223372036854775807, 1, 1); + constexpr civil_day d2(9198119301927009252, 6, 6); + static_assert(d1 - d2 == 9223372036854775807, "DifferenceWithHugeYear"); + static_assert((d2 - 1) - d1 == -9223372036854775807 - 1, + "DifferenceWithHugeYear"); + } + { + // Check the limits of the return value at the start of the year range. + constexpr civil_day d1(-9223372036854775807 - 1, 1, 1); + constexpr civil_day d2(-9198119301927009254, 7, 28); + static_assert(d2 - d1 == 9223372036854775807, "DifferenceWithHugeYear"); + static_assert(d1 - (d2 + 1) == -9223372036854775807 - 1, + "DifferenceWithHugeYear"); + } + { + // Check the limits of the return value from either side of year 0. + constexpr civil_day d1(-12626367463883278, 9, 3); + constexpr civil_day d2(12626367463883277, 3, 28); + static_assert(d2 - d1 == 9223372036854775807, "DifferenceWithHugeYear"); + static_assert(d1 - (d2 + 1) == -9223372036854775807 - 1, + "DifferenceWithHugeYear"); + } +} + +// NOTE: Run this with --copt=-ftrapv to detect overflow problems. +TEST(CivilTime, DifferenceNoIntermediateOverflow) { + { + // The difference up to the minute field would be below the minimum + // diff_t, but the 52 extra seconds brings us back to the minimum. + constexpr civil_second s1(-292277022657, 1, 27, 8, 29 - 1, 52); + constexpr civil_second s2(1970, 1, 1, 0, 0 - 1, 0); + static_assert(s1 - s2 == -9223372036854775807 - 1, + "DifferenceNoIntermediateOverflow"); + } + { + // The difference up to the minute field would be above the maximum + // diff_t, but the -53 extra seconds brings us back to the maximum. + constexpr civil_second s1(292277026596, 12, 4, 15, 30, 7 - 7); + constexpr civil_second s2(1970, 1, 1, 0, 0, 0 - 7); + static_assert(s1 - s2 == 9223372036854775807, + "DifferenceNoIntermediateOverflow"); + } +} + +// Helper constexpr tests + +TEST(CivilTime, WeekDay) { + constexpr civil_day cd(2016, 1, 28); + constexpr weekday wd = get_weekday(cd); + static_assert(wd == weekday::thursday, "Weekday"); +} + +TEST(CivilTime, NextWeekDay) { + constexpr civil_day cd(2016, 1, 28); + constexpr civil_day next = next_weekday(cd, weekday::thursday); + static_assert(next.year() == 2016, "NextWeekDay.year"); + static_assert(next.month() == 2, "NextWeekDay.month"); + static_assert(next.day() == 4, "NextWeekDay.day"); +} + +TEST(CivilTime, PrevWeekDay) { + constexpr civil_day cd(2016, 1, 28); + constexpr civil_day prev = prev_weekday(cd, weekday::thursday); + static_assert(prev.year() == 2016, "PrevWeekDay.year"); + static_assert(prev.month() == 1, "PrevWeekDay.month"); + static_assert(prev.day() == 21, "PrevWeekDay.day"); +} + +TEST(CivilTime, YearDay) { + constexpr civil_day cd(2016, 1, 28); + constexpr int yd = get_yearday(cd); + static_assert(yd == 28, "YearDay"); +} +#endif // __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) + +// The remaining tests do not use constexpr. + +TEST(CivilTime, DefaultConstruction) { + civil_second ss; + EXPECT_EQ("1970-01-01T00:00:00", Format(ss)); + + civil_minute mm; + EXPECT_EQ("1970-01-01T00:00", Format(mm)); + + civil_hour hh; + EXPECT_EQ("1970-01-01T00", Format(hh)); + + civil_day d; + EXPECT_EQ("1970-01-01", Format(d)); + + civil_month m; + EXPECT_EQ("1970-01", Format(m)); + + civil_year y; + EXPECT_EQ("1970", Format(y)); +} + +TEST(CivilTime, StructMember) { + struct S { + civil_day day; + }; + S s = {}; + EXPECT_EQ(civil_day{}, s.day); +} + +TEST(CivilTime, FieldsConstruction) { + EXPECT_EQ("2015-01-02T03:04:05", Format(civil_second(2015, 1, 2, 3, 4, 5))); + EXPECT_EQ("2015-01-02T03:04:00", Format(civil_second(2015, 1, 2, 3, 4))); + EXPECT_EQ("2015-01-02T03:00:00", Format(civil_second(2015, 1, 2, 3))); + EXPECT_EQ("2015-01-02T00:00:00", Format(civil_second(2015, 1, 2))); + EXPECT_EQ("2015-01-01T00:00:00", Format(civil_second(2015, 1))); + EXPECT_EQ("2015-01-01T00:00:00", Format(civil_second(2015))); + + EXPECT_EQ("2015-01-02T03:04", Format(civil_minute(2015, 1, 2, 3, 4, 5))); + EXPECT_EQ("2015-01-02T03:04", Format(civil_minute(2015, 1, 2, 3, 4))); + EXPECT_EQ("2015-01-02T03:00", Format(civil_minute(2015, 1, 2, 3))); + EXPECT_EQ("2015-01-02T00:00", Format(civil_minute(2015, 1, 2))); + EXPECT_EQ("2015-01-01T00:00", Format(civil_minute(2015, 1))); + EXPECT_EQ("2015-01-01T00:00", Format(civil_minute(2015))); + + EXPECT_EQ("2015-01-02T03", Format(civil_hour(2015, 1, 2, 3, 4, 5))); + EXPECT_EQ("2015-01-02T03", Format(civil_hour(2015, 1, 2, 3, 4))); + EXPECT_EQ("2015-01-02T03", Format(civil_hour(2015, 1, 2, 3))); + EXPECT_EQ("2015-01-02T00", Format(civil_hour(2015, 1, 2))); + EXPECT_EQ("2015-01-01T00", Format(civil_hour(2015, 1))); + EXPECT_EQ("2015-01-01T00", Format(civil_hour(2015))); + + EXPECT_EQ("2015-01-02", Format(civil_day(2015, 1, 2, 3, 4, 5))); + EXPECT_EQ("2015-01-02", Format(civil_day(2015, 1, 2, 3, 4))); + EXPECT_EQ("2015-01-02", Format(civil_day(2015, 1, 2, 3))); + EXPECT_EQ("2015-01-02", Format(civil_day(2015, 1, 2))); + EXPECT_EQ("2015-01-01", Format(civil_day(2015, 1))); + EXPECT_EQ("2015-01-01", Format(civil_day(2015))); + + EXPECT_EQ("2015-01", Format(civil_month(2015, 1, 2, 3, 4, 5))); + EXPECT_EQ("2015-01", Format(civil_month(2015, 1, 2, 3, 4))); + EXPECT_EQ("2015-01", Format(civil_month(2015, 1, 2, 3))); + EXPECT_EQ("2015-01", Format(civil_month(2015, 1, 2))); + EXPECT_EQ("2015-01", Format(civil_month(2015, 1))); + EXPECT_EQ("2015-01", Format(civil_month(2015))); + + EXPECT_EQ("2015", Format(civil_year(2015, 1, 2, 3, 4, 5))); + EXPECT_EQ("2015", Format(civil_year(2015, 1, 2, 3, 4))); + EXPECT_EQ("2015", Format(civil_year(2015, 1, 2, 3))); + EXPECT_EQ("2015", Format(civil_year(2015, 1, 2))); + EXPECT_EQ("2015", Format(civil_year(2015, 1))); + EXPECT_EQ("2015", Format(civil_year(2015))); +} + +TEST(CivilTime, FieldsConstructionLimits) { + const int kIntMax = std::numeric_limits<int>::max(); + EXPECT_EQ("2038-01-19T03:14:07", + Format(civil_second(1970, 1, 1, 0, 0, kIntMax))); + EXPECT_EQ("6121-02-11T05:21:07", + Format(civil_second(1970, 1, 1, 0, kIntMax, kIntMax))); + EXPECT_EQ("251104-11-20T12:21:07", + Format(civil_second(1970, 1, 1, kIntMax, kIntMax, kIntMax))); + EXPECT_EQ("6130715-05-30T12:21:07", + Format(civil_second(1970, 1, kIntMax, kIntMax, kIntMax, kIntMax))); + EXPECT_EQ( + "185087685-11-26T12:21:07", + Format(civil_second(1970, kIntMax, kIntMax, kIntMax, kIntMax, kIntMax))); + + const int kIntMin = std::numeric_limits<int>::min(); + EXPECT_EQ("1901-12-13T20:45:52", + Format(civil_second(1970, 1, 1, 0, 0, kIntMin))); + EXPECT_EQ("-2182-11-20T18:37:52", + Format(civil_second(1970, 1, 1, 0, kIntMin, kIntMin))); + EXPECT_EQ("-247165-02-11T10:37:52", + Format(civil_second(1970, 1, 1, kIntMin, kIntMin, kIntMin))); + EXPECT_EQ("-6126776-08-01T10:37:52", + Format(civil_second(1970, 1, kIntMin, kIntMin, kIntMin, kIntMin))); + EXPECT_EQ( + "-185083747-10-31T10:37:52", + Format(civil_second(1970, kIntMin, kIntMin, kIntMin, kIntMin, kIntMin))); +} + +TEST(CivilTime, ImplicitCrossAlignment) { + civil_year year(2015); + civil_month month = year; + civil_day day = month; + civil_hour hour = day; + civil_minute minute = hour; + civil_second second = minute; + + second = year; + EXPECT_EQ(second, year); + second = month; + EXPECT_EQ(second, month); + second = day; + EXPECT_EQ(second, day); + second = hour; + EXPECT_EQ(second, hour); + second = minute; + EXPECT_EQ(second, minute); + + minute = year; + EXPECT_EQ(minute, year); + minute = month; + EXPECT_EQ(minute, month); + minute = day; + EXPECT_EQ(minute, day); + minute = hour; + EXPECT_EQ(minute, hour); + + hour = year; + EXPECT_EQ(hour, year); + hour = month; + EXPECT_EQ(hour, month); + hour = day; + EXPECT_EQ(hour, day); + + day = year; + EXPECT_EQ(day, year); + day = month; + EXPECT_EQ(day, month); + + month = year; + EXPECT_EQ(month, year); + + // Ensures unsafe conversions are not allowed. + EXPECT_FALSE((std::is_convertible<civil_second, civil_minute>::value)); + EXPECT_FALSE((std::is_convertible<civil_second, civil_hour>::value)); + EXPECT_FALSE((std::is_convertible<civil_second, civil_day>::value)); + EXPECT_FALSE((std::is_convertible<civil_second, civil_month>::value)); + EXPECT_FALSE((std::is_convertible<civil_second, civil_year>::value)); + + EXPECT_FALSE((std::is_convertible<civil_minute, civil_hour>::value)); + EXPECT_FALSE((std::is_convertible<civil_minute, civil_day>::value)); + EXPECT_FALSE((std::is_convertible<civil_minute, civil_month>::value)); + EXPECT_FALSE((std::is_convertible<civil_minute, civil_year>::value)); + + EXPECT_FALSE((std::is_convertible<civil_hour, civil_day>::value)); + EXPECT_FALSE((std::is_convertible<civil_hour, civil_month>::value)); + EXPECT_FALSE((std::is_convertible<civil_hour, civil_year>::value)); + + EXPECT_FALSE((std::is_convertible<civil_day, civil_month>::value)); + EXPECT_FALSE((std::is_convertible<civil_day, civil_year>::value)); + + EXPECT_FALSE((std::is_convertible<civil_month, civil_year>::value)); +} + +TEST(CivilTime, ExplicitCrossAlignment) { + // + // Assign from smaller units -> larger units + // + + civil_second second(2015, 1, 2, 3, 4, 5); + EXPECT_EQ("2015-01-02T03:04:05", Format(second)); + + civil_minute minute(second); + EXPECT_EQ("2015-01-02T03:04", Format(minute)); + + civil_hour hour(minute); + EXPECT_EQ("2015-01-02T03", Format(hour)); + + civil_day day(hour); + EXPECT_EQ("2015-01-02", Format(day)); + + civil_month month(day); + EXPECT_EQ("2015-01", Format(month)); + + civil_year year(month); + EXPECT_EQ("2015", Format(year)); + + // + // Now assign from larger units -> smaller units + // + + month = civil_month(year); + EXPECT_EQ("2015-01", Format(month)); + + day = civil_day(month); + EXPECT_EQ("2015-01-01", Format(day)); + + hour = civil_hour(day); + EXPECT_EQ("2015-01-01T00", Format(hour)); + + minute = civil_minute(hour); + EXPECT_EQ("2015-01-01T00:00", Format(minute)); + + second = civil_second(minute); + EXPECT_EQ("2015-01-01T00:00:00", Format(second)); +} + +// Metafunction to test whether difference is allowed between two types. +template <typename T1, typename T2> +struct HasDifference { + template <typename U1, typename U2> + static std::false_type test(...); + template <typename U1, typename U2> + static std::true_type test(decltype(std::declval<U1>() - std::declval<U2>())); + static constexpr bool value = decltype(test<T1, T2>(0))::value; +}; + +TEST(CivilTime, DisallowCrossAlignedDifference) { + // Difference is allowed between types with the same alignment. + static_assert(HasDifference<civil_second, civil_second>::value, ""); + static_assert(HasDifference<civil_minute, civil_minute>::value, ""); + static_assert(HasDifference<civil_hour, civil_hour>::value, ""); + static_assert(HasDifference<civil_day, civil_day>::value, ""); + static_assert(HasDifference<civil_month, civil_month>::value, ""); + static_assert(HasDifference<civil_year, civil_year>::value, ""); + + // Difference is disallowed between types with different alignments. + static_assert(!HasDifference<civil_second, civil_minute>::value, ""); + static_assert(!HasDifference<civil_second, civil_hour>::value, ""); + static_assert(!HasDifference<civil_second, civil_day>::value, ""); + static_assert(!HasDifference<civil_second, civil_month>::value, ""); + static_assert(!HasDifference<civil_second, civil_year>::value, ""); + + static_assert(!HasDifference<civil_minute, civil_hour>::value, ""); + static_assert(!HasDifference<civil_minute, civil_day>::value, ""); + static_assert(!HasDifference<civil_minute, civil_month>::value, ""); + static_assert(!HasDifference<civil_minute, civil_year>::value, ""); + + static_assert(!HasDifference<civil_hour, civil_day>::value, ""); + static_assert(!HasDifference<civil_hour, civil_month>::value, ""); + static_assert(!HasDifference<civil_hour, civil_year>::value, ""); + + static_assert(!HasDifference<civil_day, civil_month>::value, ""); + static_assert(!HasDifference<civil_day, civil_year>::value, ""); + + static_assert(!HasDifference<civil_month, civil_year>::value, ""); +} + +TEST(CivilTime, ValueSemantics) { + const civil_hour a(2015, 1, 2, 3); + const civil_hour b = a; + const civil_hour c(b); + civil_hour d; + d = c; + EXPECT_EQ("2015-01-02T03", Format(d)); +} + +TEST(CivilTime, Relational) { + // Tests that the alignment unit is ignored in comparison. + const civil_year year(2014); + const civil_month month(year); + EXPECT_EQ(year, month); + +#define TEST_RELATIONAL(OLDER, YOUNGER) \ + do { \ + EXPECT_FALSE(OLDER < OLDER); \ + EXPECT_FALSE(OLDER > OLDER); \ + EXPECT_TRUE(OLDER >= OLDER); \ + EXPECT_TRUE(OLDER <= OLDER); \ + EXPECT_FALSE(YOUNGER < YOUNGER); \ + EXPECT_FALSE(YOUNGER > YOUNGER); \ + EXPECT_TRUE(YOUNGER >= YOUNGER); \ + EXPECT_TRUE(YOUNGER <= YOUNGER); \ + EXPECT_EQ(OLDER, OLDER); \ + EXPECT_NE(OLDER, YOUNGER); \ + EXPECT_LT(OLDER, YOUNGER); \ + EXPECT_LE(OLDER, YOUNGER); \ + EXPECT_GT(YOUNGER, OLDER); \ + EXPECT_GE(YOUNGER, OLDER); \ + } while (0) + + // Alignment is ignored in comparison (verified above), so kSecond is used + // to test comparison in all field positions. + TEST_RELATIONAL(civil_second(2014, 1, 1, 0, 0, 0), + civil_second(2015, 1, 1, 0, 0, 0)); + TEST_RELATIONAL(civil_second(2014, 1, 1, 0, 0, 0), + civil_second(2014, 2, 1, 0, 0, 0)); + TEST_RELATIONAL(civil_second(2014, 1, 1, 0, 0, 0), + civil_second(2014, 1, 2, 0, 0, 0)); + TEST_RELATIONAL(civil_second(2014, 1, 1, 0, 0, 0), + civil_second(2014, 1, 1, 1, 0, 0)); + TEST_RELATIONAL(civil_second(2014, 1, 1, 1, 0, 0), + civil_second(2014, 1, 1, 1, 1, 0)); + TEST_RELATIONAL(civil_second(2014, 1, 1, 1, 1, 0), + civil_second(2014, 1, 1, 1, 1, 1)); + + // Tests the relational operators of two different civil-time types. + TEST_RELATIONAL(civil_day(2014, 1, 1), civil_minute(2014, 1, 1, 1, 1)); + TEST_RELATIONAL(civil_day(2014, 1, 1), civil_month(2014, 2)); + +#undef TEST_RELATIONAL +} + +TEST(CivilTime, Arithmetic) { + civil_second second(2015, 1, 2, 3, 4, 5); + EXPECT_EQ("2015-01-02T03:04:06", Format(second += 1)); + EXPECT_EQ("2015-01-02T03:04:07", Format(second + 1)); + EXPECT_EQ("2015-01-02T03:04:08", Format(2 + second)); + EXPECT_EQ("2015-01-02T03:04:05", Format(second - 1)); + EXPECT_EQ("2015-01-02T03:04:05", Format(second -= 1)); + EXPECT_EQ("2015-01-02T03:04:05", Format(second++)); + EXPECT_EQ("2015-01-02T03:04:07", Format(++second)); + EXPECT_EQ("2015-01-02T03:04:07", Format(second--)); + EXPECT_EQ("2015-01-02T03:04:05", Format(--second)); + + civil_minute minute(2015, 1, 2, 3, 4); + EXPECT_EQ("2015-01-02T03:05", Format(minute += 1)); + EXPECT_EQ("2015-01-02T03:06", Format(minute + 1)); + EXPECT_EQ("2015-01-02T03:07", Format(2 + minute)); + EXPECT_EQ("2015-01-02T03:04", Format(minute - 1)); + EXPECT_EQ("2015-01-02T03:04", Format(minute -= 1)); + EXPECT_EQ("2015-01-02T03:04", Format(minute++)); + EXPECT_EQ("2015-01-02T03:06", Format(++minute)); + EXPECT_EQ("2015-01-02T03:06", Format(minute--)); + EXPECT_EQ("2015-01-02T03:04", Format(--minute)); + + civil_hour hour(2015, 1, 2, 3); + EXPECT_EQ("2015-01-02T04", Format(hour += 1)); + EXPECT_EQ("2015-01-02T05", Format(hour + 1)); + EXPECT_EQ("2015-01-02T06", Format(2 + hour)); + EXPECT_EQ("2015-01-02T03", Format(hour - 1)); + EXPECT_EQ("2015-01-02T03", Format(hour -= 1)); + EXPECT_EQ("2015-01-02T03", Format(hour++)); + EXPECT_EQ("2015-01-02T05", Format(++hour)); + EXPECT_EQ("2015-01-02T05", Format(hour--)); + EXPECT_EQ("2015-01-02T03", Format(--hour)); + + civil_day day(2015, 1, 2); + EXPECT_EQ("2015-01-03", Format(day += 1)); + EXPECT_EQ("2015-01-04", Format(day + 1)); + EXPECT_EQ("2015-01-05", Format(2 + day)); + EXPECT_EQ("2015-01-02", Format(day - 1)); + EXPECT_EQ("2015-01-02", Format(day -= 1)); + EXPECT_EQ("2015-01-02", Format(day++)); + EXPECT_EQ("2015-01-04", Format(++day)); + EXPECT_EQ("2015-01-04", Format(day--)); + EXPECT_EQ("2015-01-02", Format(--day)); + + civil_month month(2015, 1); + EXPECT_EQ("2015-02", Format(month += 1)); + EXPECT_EQ("2015-03", Format(month + 1)); + EXPECT_EQ("2015-04", Format(2 + month)); + EXPECT_EQ("2015-01", Format(month - 1)); + EXPECT_EQ("2015-01", Format(month -= 1)); + EXPECT_EQ("2015-01", Format(month++)); + EXPECT_EQ("2015-03", Format(++month)); + EXPECT_EQ("2015-03", Format(month--)); + EXPECT_EQ("2015-01", Format(--month)); + + civil_year year(2015); + EXPECT_EQ("2016", Format(year += 1)); + EXPECT_EQ("2017", Format(year + 1)); + EXPECT_EQ("2018", Format(2 + year)); + EXPECT_EQ("2015", Format(year - 1)); + EXPECT_EQ("2015", Format(year -= 1)); + EXPECT_EQ("2015", Format(year++)); + EXPECT_EQ("2017", Format(++year)); + EXPECT_EQ("2017", Format(year--)); + EXPECT_EQ("2015", Format(--year)); +} + +TEST(CivilTime, ArithmeticLimits) { + const int kIntMax = std::numeric_limits<int>::max(); + const int kIntMin = std::numeric_limits<int>::min(); + + civil_second second(1970, 1, 1, 0, 0, 0); + second += kIntMax; + EXPECT_EQ("2038-01-19T03:14:07", Format(second)); + second -= kIntMax; + EXPECT_EQ("1970-01-01T00:00:00", Format(second)); + second += kIntMin; + EXPECT_EQ("1901-12-13T20:45:52", Format(second)); + second -= kIntMin; + EXPECT_EQ("1970-01-01T00:00:00", Format(second)); + + civil_minute minute(1970, 1, 1, 0, 0); + minute += kIntMax; + EXPECT_EQ("6053-01-23T02:07", Format(minute)); + minute -= kIntMax; + EXPECT_EQ("1970-01-01T00:00", Format(minute)); + minute += kIntMin; + EXPECT_EQ("-2114-12-08T21:52", Format(minute)); + minute -= kIntMin; + EXPECT_EQ("1970-01-01T00:00", Format(minute)); + + civil_hour hour(1970, 1, 1, 0); + hour += kIntMax; + EXPECT_EQ("246953-10-09T07", Format(hour)); + hour -= kIntMax; + EXPECT_EQ("1970-01-01T00", Format(hour)); + hour += kIntMin; + EXPECT_EQ("-243014-03-24T16", Format(hour)); + hour -= kIntMin; + EXPECT_EQ("1970-01-01T00", Format(hour)); + + civil_day day(1970, 1, 1); + day += kIntMax; + EXPECT_EQ("5881580-07-11", Format(day)); + day -= kIntMax; + EXPECT_EQ("1970-01-01", Format(day)); + day += kIntMin; + EXPECT_EQ("-5877641-06-23", Format(day)); + day -= kIntMin; + EXPECT_EQ("1970-01-01", Format(day)); + + civil_month month(1970, 1); + month += kIntMax; + EXPECT_EQ("178958940-08", Format(month)); + month -= kIntMax; + EXPECT_EQ("1970-01", Format(month)); + month += kIntMin; + EXPECT_EQ("-178955001-05", Format(month)); + month -= kIntMin; + EXPECT_EQ("1970-01", Format(month)); + + civil_year year(0); + year += kIntMax; + EXPECT_EQ("2147483647", Format(year)); + year -= kIntMax; + EXPECT_EQ("0", Format(year)); + year += kIntMin; + EXPECT_EQ("-2147483648", Format(year)); + year -= kIntMin; + EXPECT_EQ("0", Format(year)); +} + +TEST(CivilTime, ArithmeticDifference) { + civil_second second(2015, 1, 2, 3, 4, 5); + EXPECT_EQ(0, second - second); + EXPECT_EQ(10, (second + 10) - second); + EXPECT_EQ(-10, (second - 10) - second); + + civil_minute minute(2015, 1, 2, 3, 4); + EXPECT_EQ(0, minute - minute); + EXPECT_EQ(10, (minute + 10) - minute); + EXPECT_EQ(-10, (minute - 10) - minute); + + civil_hour hour(2015, 1, 2, 3); + EXPECT_EQ(0, hour - hour); + EXPECT_EQ(10, (hour + 10) - hour); + EXPECT_EQ(-10, (hour - 10) - hour); + + civil_day day(2015, 1, 2); + EXPECT_EQ(0, day - day); + EXPECT_EQ(10, (day + 10) - day); + EXPECT_EQ(-10, (day - 10) - day); + + civil_month month(2015, 1); + EXPECT_EQ(0, month - month); + EXPECT_EQ(10, (month + 10) - month); + EXPECT_EQ(-10, (month - 10) - month); + + civil_year year(2015); + EXPECT_EQ(0, year - year); + EXPECT_EQ(10, (year + 10) - year); + EXPECT_EQ(-10, (year - 10) - year); +} + +TEST(CivilTime, DifferenceLimits) { + const int kIntMax = std::numeric_limits<int>::max(); + const int kIntMin = std::numeric_limits<int>::min(); + + // Check day arithmetic at the end of the year range. + const civil_day max_day(kIntMax, 12, 31); + EXPECT_EQ(1, max_day - (max_day - 1)); + EXPECT_EQ(-1, (max_day - 1) - max_day); + + // Check day arithmetic at the end of the year range. + const civil_day min_day(kIntMin, 1, 1); + EXPECT_EQ(1, (min_day + 1) - min_day); + EXPECT_EQ(-1, min_day - (min_day + 1)); + + // Check the limits of the return value. + const civil_day d1(1970, 1, 1); + const civil_day d2(5881580, 7, 11); + EXPECT_EQ(kIntMax, d2 - d1); + EXPECT_EQ(kIntMin, d1 - (d2 + 1)); +} + +TEST(CivilTime, Properties) { + civil_second ss(2015, 2, 3, 4, 5, 6); + EXPECT_EQ(2015, ss.year()); + EXPECT_EQ(2, ss.month()); + EXPECT_EQ(3, ss.day()); + EXPECT_EQ(4, ss.hour()); + EXPECT_EQ(5, ss.minute()); + EXPECT_EQ(6, ss.second()); + EXPECT_EQ(weekday::tuesday, get_weekday(ss)); + EXPECT_EQ(34, get_yearday(ss)); + + civil_minute mm(2015, 2, 3, 4, 5, 6); + EXPECT_EQ(2015, mm.year()); + EXPECT_EQ(2, mm.month()); + EXPECT_EQ(3, mm.day()); + EXPECT_EQ(4, mm.hour()); + EXPECT_EQ(5, mm.minute()); + EXPECT_EQ(0, mm.second()); + EXPECT_EQ(weekday::tuesday, get_weekday(mm)); + EXPECT_EQ(34, get_yearday(mm)); + + civil_hour hh(2015, 2, 3, 4, 5, 6); + EXPECT_EQ(2015, hh.year()); + EXPECT_EQ(2, hh.month()); + EXPECT_EQ(3, hh.day()); + EXPECT_EQ(4, hh.hour()); + EXPECT_EQ(0, hh.minute()); + EXPECT_EQ(0, hh.second()); + EXPECT_EQ(weekday::tuesday, get_weekday(hh)); + EXPECT_EQ(34, get_yearday(hh)); + + civil_day d(2015, 2, 3, 4, 5, 6); + EXPECT_EQ(2015, d.year()); + EXPECT_EQ(2, d.month()); + EXPECT_EQ(3, d.day()); + EXPECT_EQ(0, d.hour()); + EXPECT_EQ(0, d.minute()); + EXPECT_EQ(0, d.second()); + EXPECT_EQ(weekday::tuesday, get_weekday(d)); + EXPECT_EQ(34, get_yearday(d)); + + civil_month m(2015, 2, 3, 4, 5, 6); + EXPECT_EQ(2015, m.year()); + EXPECT_EQ(2, m.month()); + EXPECT_EQ(1, m.day()); + EXPECT_EQ(0, m.hour()); + EXPECT_EQ(0, m.minute()); + EXPECT_EQ(0, m.second()); + EXPECT_EQ(weekday::sunday, get_weekday(m)); + EXPECT_EQ(32, get_yearday(m)); + + civil_year y(2015, 2, 3, 4, 5, 6); + EXPECT_EQ(2015, y.year()); + EXPECT_EQ(1, y.month()); + EXPECT_EQ(1, y.day()); + EXPECT_EQ(0, y.hour()); + EXPECT_EQ(0, y.minute()); + EXPECT_EQ(0, y.second()); + EXPECT_EQ(weekday::thursday, get_weekday(y)); + EXPECT_EQ(1, get_yearday(y)); +} + +TEST(CivilTime, OutputStream) { + // Tests formatting of civil_year, which does not pad. + EXPECT_EQ("2016", Format(civil_year(2016))); + EXPECT_EQ("123", Format(civil_year(123))); + EXPECT_EQ("0", Format(civil_year(0))); + EXPECT_EQ("-1", Format(civil_year(-1))); + + // Tests formatting of sub-year types, which pad to 2 digits + EXPECT_EQ("2016-02", Format(civil_month(2016, 2))); + EXPECT_EQ("2016-02-03", Format(civil_day(2016, 2, 3))); + EXPECT_EQ("2016-02-03T04", Format(civil_hour(2016, 2, 3, 4))); + EXPECT_EQ("2016-02-03T04:05", Format(civil_minute(2016, 2, 3, 4, 5))); + EXPECT_EQ("2016-02-03T04:05:06", Format(civil_second(2016, 2, 3, 4, 5, 6))); + + // Tests formatting of weekday. + EXPECT_EQ("Monday", Format(weekday::monday)); + EXPECT_EQ("Tuesday", Format(weekday::tuesday)); + EXPECT_EQ("Wednesday", Format(weekday::wednesday)); + EXPECT_EQ("Thursday", Format(weekday::thursday)); + EXPECT_EQ("Friday", Format(weekday::friday)); + EXPECT_EQ("Saturday", Format(weekday::saturday)); + EXPECT_EQ("Sunday", Format(weekday::sunday)); +} + +TEST(CivilTime, OutputStreamLeftFillWidth) { + civil_second cs(2016, 2, 3, 4, 5, 6); + { + std::stringstream ss; + ss << std::left << std::setfill('.'); + ss << std::setw(3) << 'X'; + ss << std::setw(21) << civil_year(cs); + ss << std::setw(3) << 'X'; + EXPECT_EQ("X..2016.................X..", ss.str()); + } + { + std::stringstream ss; + ss << std::left << std::setfill('.'); + ss << std::setw(3) << 'X'; + ss << std::setw(21) << civil_month(cs); + ss << std::setw(3) << 'X'; + EXPECT_EQ("X..2016-02..............X..", ss.str()); + } + { + std::stringstream ss; + ss << std::left << std::setfill('.'); + ss << std::setw(3) << 'X'; + ss << std::setw(21) << civil_day(cs); + ss << std::setw(3) << 'X'; + EXPECT_EQ("X..2016-02-03...........X..", ss.str()); + } + { + std::stringstream ss; + ss << std::left << std::setfill('.'); + ss << std::setw(3) << 'X'; + ss << std::setw(21) << civil_hour(cs); + ss << std::setw(3) << 'X'; + EXPECT_EQ("X..2016-02-03T04........X..", ss.str()); + } + { + std::stringstream ss; + ss << std::left << std::setfill('.'); + ss << std::setw(3) << 'X'; + ss << std::setw(21) << civil_minute(cs); + ss << std::setw(3) << 'X'; + EXPECT_EQ("X..2016-02-03T04:05.....X..", ss.str()); + } + { + std::stringstream ss; + ss << std::left << std::setfill('.'); + ss << std::setw(3) << 'X'; + ss << std::setw(21) << civil_second(cs); + ss << std::setw(3) << 'X'; + EXPECT_EQ("X..2016-02-03T04:05:06..X..", ss.str()); + } +} + +TEST(CivilTime, NextPrevWeekday) { + // Jan 1, 1970 was a Thursday. + const civil_day thursday(1970, 1, 1); + EXPECT_EQ(weekday::thursday, get_weekday(thursday)); + + // Thursday -> Thursday + civil_day d = next_weekday(thursday, weekday::thursday); + EXPECT_EQ(7, d - thursday) << Format(d); + EXPECT_EQ(d - 14, prev_weekday(thursday, weekday::thursday)); + + // Thursday -> Friday + d = next_weekday(thursday, weekday::friday); + EXPECT_EQ(1, d - thursday) << Format(d); + EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::friday)); + + // Thursday -> Saturday + d = next_weekday(thursday, weekday::saturday); + EXPECT_EQ(2, d - thursday) << Format(d); + EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::saturday)); + + // Thursday -> Sunday + d = next_weekday(thursday, weekday::sunday); + EXPECT_EQ(3, d - thursday) << Format(d); + EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::sunday)); + + // Thursday -> Monday + d = next_weekday(thursday, weekday::monday); + EXPECT_EQ(4, d - thursday) << Format(d); + EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::monday)); + + // Thursday -> Tuesday + d = next_weekday(thursday, weekday::tuesday); + EXPECT_EQ(5, d - thursday) << Format(d); + EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::tuesday)); + + // Thursday -> Wednesday + d = next_weekday(thursday, weekday::wednesday); + EXPECT_EQ(6, d - thursday) << Format(d); + EXPECT_EQ(d - 7, prev_weekday(thursday, weekday::wednesday)); +} + +TEST(CivilTime, NormalizeWithHugeYear) { + civil_month c(9223372036854775807, 1); + EXPECT_EQ("9223372036854775807-01", Format(c)); + c = c - 1; // Causes normalization + EXPECT_EQ("9223372036854775806-12", Format(c)); + + c = civil_month(-9223372036854775807 - 1, 1); + EXPECT_EQ("-9223372036854775808-01", Format(c)); + c = c + 12; // Causes normalization + EXPECT_EQ("-9223372036854775807-01", Format(c)); +} + +TEST(CivilTime, LeapYears) { + // Test data for leap years. + const struct { + int year; + int days; + struct { + int month; + int day; + } leap_day; // The date of the day after Feb 28. + } kLeapYearTable[]{ + {1900, 365, {3, 1}}, + {1999, 365, {3, 1}}, + {2000, 366, {2, 29}}, // leap year + {2001, 365, {3, 1}}, + {2002, 365, {3, 1}}, + {2003, 365, {3, 1}}, + {2004, 366, {2, 29}}, // leap year + {2005, 365, {3, 1}}, + {2006, 365, {3, 1}}, + {2007, 365, {3, 1}}, + {2008, 366, {2, 29}}, // leap year + {2009, 365, {3, 1}}, + {2100, 365, {3, 1}}, + }; + + for (const auto& e : kLeapYearTable) { + // Tests incrementing through the leap day. + const civil_day feb28(e.year, 2, 28); + const civil_day next_day = feb28 + 1; + EXPECT_EQ(e.leap_day.month, next_day.month()); + EXPECT_EQ(e.leap_day.day, next_day.day()); + + // Tests difference in days of leap years. + const civil_year year(feb28); + const civil_year next_year = year + 1; + EXPECT_EQ(e.days, civil_day(next_year) - civil_day(year)); + } +} + +TEST(CivilTime, FirstThursdayInMonth) { + const civil_day nov1(2014, 11, 1); + const civil_day thursday = next_weekday(nov1 - 1, weekday::thursday); + EXPECT_EQ("2014-11-06", Format(thursday)); + + // Bonus: Date of Thanksgiving in the United States + // Rule: Fourth Thursday of November + const civil_day thanksgiving = thursday + 7 * 3; + EXPECT_EQ("2014-11-27", Format(thanksgiving)); +} + +} // namespace cctz diff --git a/contrib/libs/cctz/test/time_zone_format_test.cc b/contrib/libs/cctz/test/time_zone_format_test.cc new file mode 100644 index 0000000000..0d07dad5c0 --- /dev/null +++ b/contrib/libs/cctz/test/time_zone_format_test.cc @@ -0,0 +1,1588 @@ +// 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 "cctz/time_zone.h" + +#include <chrono> +#include <iomanip> +#include <sstream> +#include <string> + +#include "cctz/civil_time.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace chrono = std::chrono; + +namespace cctz { + +namespace { + +// This helper is a macro so that failed expectations show up with the +// correct line numbers. +#define ExpectTime(tp, tz, y, m, d, hh, mm, ss, off, isdst, zone) \ + do { \ + time_zone::absolute_lookup al = tz.lookup(tp); \ + EXPECT_EQ(y, al.cs.year()); \ + EXPECT_EQ(m, al.cs.month()); \ + EXPECT_EQ(d, al.cs.day()); \ + EXPECT_EQ(hh, al.cs.hour()); \ + EXPECT_EQ(mm, al.cs.minute()); \ + EXPECT_EQ(ss, al.cs.second()); \ + EXPECT_EQ(off, al.offset); \ + EXPECT_TRUE(isdst == al.is_dst); \ + EXPECT_STREQ(zone, al.abbr); \ + } while (0) + +const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez"; +const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez"; + +const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z"; +const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z"; + +// A helper that tests the given format specifier by itself, and with leading +// and trailing characters. For example: TestFormatSpecifier(tp, "%a", "Thu"). +template <typename D> +void TestFormatSpecifier(time_point<D> tp, time_zone tz, const std::string& fmt, + const std::string& ans) { + EXPECT_EQ(ans, format(fmt, tp, tz)) << fmt; + EXPECT_EQ("xxx " + ans, format("xxx " + fmt, tp, tz)); + EXPECT_EQ(ans + " yyy", format(fmt + " yyy", tp, tz)); + EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz)); +} + +} // namespace + +// +// Testing format() +// + +TEST(Format, TimePointResolution) { + const char kFmt[] = "%H:%M:%E*S"; + const time_zone utc = utc_time_zone(); + const time_point<chrono::nanoseconds> t0 = + chrono::system_clock::from_time_t(1420167845) + + chrono::milliseconds(123) + chrono::microseconds(456) + + chrono::nanoseconds(789); + EXPECT_EQ( + "03:04:05.123456789", + format(kFmt, chrono::time_point_cast<chrono::nanoseconds>(t0), utc)); + EXPECT_EQ( + "03:04:05.123456", + format(kFmt, chrono::time_point_cast<chrono::microseconds>(t0), utc)); + EXPECT_EQ( + "03:04:05.123", + format(kFmt, chrono::time_point_cast<chrono::milliseconds>(t0), utc)); + EXPECT_EQ("03:04:05", + format(kFmt, chrono::time_point_cast<chrono::seconds>(t0), utc)); + EXPECT_EQ("03:04:05", + format(kFmt, chrono::time_point_cast<cctz::seconds>(t0), utc)); + EXPECT_EQ("03:04:00", + format(kFmt, chrono::time_point_cast<chrono::minutes>(t0), utc)); + EXPECT_EQ("03:00:00", + format(kFmt, chrono::time_point_cast<chrono::hours>(t0), utc)); +} + +TEST(Format, TimePointExtendedResolution) { + const char kFmt[] = "%H:%M:%E*S"; + const time_zone utc = utc_time_zone(); + const time_point<cctz::seconds> tp = + chrono::time_point_cast<cctz::seconds>( + chrono::system_clock::from_time_t(0)) + + chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56); + + EXPECT_EQ( + "12:34:56.123456789012345", + detail::format(kFmt, tp, detail::femtoseconds(123456789012345), utc)); + EXPECT_EQ( + "12:34:56.012345678901234", + detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc)); + EXPECT_EQ( + "12:34:56.001234567890123", + detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc)); + EXPECT_EQ( + "12:34:56.000123456789012", + detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc)); + + EXPECT_EQ("12:34:56.000000000000123", + detail::format(kFmt, tp, detail::femtoseconds(123), utc)); + EXPECT_EQ("12:34:56.000000000000012", + detail::format(kFmt, tp, detail::femtoseconds(12), utc)); + EXPECT_EQ("12:34:56.000000000000001", + detail::format(kFmt, tp, detail::femtoseconds(1), utc)); +} + +TEST(Format, Basics) { + time_zone tz = utc_time_zone(); + time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0); + + // Starts with a couple basic edge cases. + EXPECT_EQ("", format("", tp, tz)); + EXPECT_EQ(" ", format(" ", tp, tz)); + EXPECT_EQ(" ", format(" ", tp, tz)); + EXPECT_EQ("xxx", format("xxx", tp, tz)); + std::string big(128, 'x'); + EXPECT_EQ(big, format(big, tp, tz)); + // Cause the 1024-byte buffer to grow. + std::string bigger(100000, 'x'); + EXPECT_EQ(bigger, format(bigger, tp, tz)); + + tp += chrono::hours(13) + chrono::minutes(4) + chrono::seconds(5); + tp += chrono::milliseconds(6) + chrono::microseconds(7) + + chrono::nanoseconds(8); + EXPECT_EQ("1970-01-01", format("%Y-%m-%d", tp, tz)); + EXPECT_EQ("13:04:05", format("%H:%M:%S", tp, tz)); + EXPECT_EQ("13:04:05.006", format("%H:%M:%E3S", tp, tz)); + EXPECT_EQ("13:04:05.006007", format("%H:%M:%E6S", tp, tz)); + EXPECT_EQ("13:04:05.006007008", format("%H:%M:%E9S", tp, tz)); +} + +TEST(Format, PosixConversions) { + const time_zone tz = utc_time_zone(); + auto tp = chrono::system_clock::from_time_t(0); + + TestFormatSpecifier(tp, tz, "%d", "01"); + TestFormatSpecifier(tp, tz, "%e", " 1"); // extension but internal support + TestFormatSpecifier(tp, tz, "%H", "00"); + TestFormatSpecifier(tp, tz, "%I", "12"); + TestFormatSpecifier(tp, tz, "%j", "001"); + TestFormatSpecifier(tp, tz, "%m", "01"); + TestFormatSpecifier(tp, tz, "%M", "00"); + TestFormatSpecifier(tp, tz, "%S", "00"); + TestFormatSpecifier(tp, tz, "%U", "00"); + TestFormatSpecifier(tp, tz, "%w", "4"); // 4=Thursday + TestFormatSpecifier(tp, tz, "%W", "00"); + TestFormatSpecifier(tp, tz, "%y", "70"); + TestFormatSpecifier(tp, tz, "%Y", "1970"); + TestFormatSpecifier(tp, tz, "%z", "+0000"); + TestFormatSpecifier(tp, tz, "%Z", "UTC"); + TestFormatSpecifier(tp, tz, "%%", "%"); + +#if defined(__linux__) + // SU/C99/TZ extensions + TestFormatSpecifier(tp, tz, "%C", "19"); + TestFormatSpecifier(tp, tz, "%D", "01/01/70"); + TestFormatSpecifier(tp, tz, "%F", "1970-01-01"); + TestFormatSpecifier(tp, tz, "%g", "70"); + TestFormatSpecifier(tp, tz, "%G", "1970"); + TestFormatSpecifier(tp, tz, "%k", " 0"); + TestFormatSpecifier(tp, tz, "%l", "12"); + TestFormatSpecifier(tp, tz, "%n", "\n"); + TestFormatSpecifier(tp, tz, "%R", "00:00"); + TestFormatSpecifier(tp, tz, "%t", "\t"); + TestFormatSpecifier(tp, tz, "%T", "00:00:00"); + TestFormatSpecifier(tp, tz, "%u", "4"); // 4=Thursday + TestFormatSpecifier(tp, tz, "%V", "01"); + TestFormatSpecifier(tp, tz, "%s", "0"); +#endif +} + +TEST(Format, LocaleSpecific) { + const time_zone tz = utc_time_zone(); + auto tp = chrono::system_clock::from_time_t(0); + + TestFormatSpecifier(tp, tz, "%a", "Thu"); + TestFormatSpecifier(tp, tz, "%A", "Thursday"); + TestFormatSpecifier(tp, tz, "%b", "Jan"); + TestFormatSpecifier(tp, tz, "%B", "January"); + + // %c should at least produce the numeric year and time-of-day. + const std::string s = format("%c", tp, utc_time_zone()); + EXPECT_THAT(s, testing::HasSubstr("1970")); + EXPECT_THAT(s, testing::HasSubstr("00:00:00")); + + TestFormatSpecifier(tp, tz, "%p", "AM"); + TestFormatSpecifier(tp, tz, "%x", "01/01/70"); + TestFormatSpecifier(tp, tz, "%X", "00:00:00"); + +#if defined(__linux__) + // SU/C99/TZ extensions + TestFormatSpecifier(tp, tz, "%h", "Jan"); // Same as %b + TestFormatSpecifier(tp, tz, "%P", "am"); + TestFormatSpecifier(tp, tz, "%r", "12:00:00 AM"); + + // Modified conversion specifiers %E_ + TestFormatSpecifier(tp, tz, "%Ec", "Thu Jan 1 00:00:00 1970"); + TestFormatSpecifier(tp, tz, "%EC", "19"); + TestFormatSpecifier(tp, tz, "%Ex", "01/01/70"); + TestFormatSpecifier(tp, tz, "%EX", "00:00:00"); + TestFormatSpecifier(tp, tz, "%Ey", "70"); + TestFormatSpecifier(tp, tz, "%EY", "1970"); + + // Modified conversion specifiers %O_ + TestFormatSpecifier(tp, tz, "%Od", "01"); + TestFormatSpecifier(tp, tz, "%Oe", " 1"); + TestFormatSpecifier(tp, tz, "%OH", "00"); + TestFormatSpecifier(tp, tz, "%OI", "12"); + TestFormatSpecifier(tp, tz, "%Om", "01"); + TestFormatSpecifier(tp, tz, "%OM", "00"); + TestFormatSpecifier(tp, tz, "%OS", "00"); + TestFormatSpecifier(tp, tz, "%Ou", "4"); // 4=Thursday + TestFormatSpecifier(tp, tz, "%OU", "00"); + TestFormatSpecifier(tp, tz, "%OV", "01"); + TestFormatSpecifier(tp, tz, "%Ow", "4"); // 4=Thursday + TestFormatSpecifier(tp, tz, "%OW", "00"); + TestFormatSpecifier(tp, tz, "%Oy", "70"); +#endif +} + +TEST(Format, Escaping) { + const time_zone tz = utc_time_zone(); + auto tp = chrono::system_clock::from_time_t(0); + + TestFormatSpecifier(tp, tz, "%%", "%"); + TestFormatSpecifier(tp, tz, "%%a", "%a"); + TestFormatSpecifier(tp, tz, "%%b", "%b"); + TestFormatSpecifier(tp, tz, "%%Ea", "%Ea"); + TestFormatSpecifier(tp, tz, "%%Es", "%Es"); + TestFormatSpecifier(tp, tz, "%%E3S", "%E3S"); + TestFormatSpecifier(tp, tz, "%%OS", "%OS"); + TestFormatSpecifier(tp, tz, "%%O3S", "%O3S"); + + // Multiple levels of escaping. + TestFormatSpecifier(tp, tz, "%%%Y", "%1970"); + TestFormatSpecifier(tp, tz, "%%%E3S", "%00.000"); + TestFormatSpecifier(tp, tz, "%%%%E3S", "%%E3S"); +} + +TEST(Format, ExtendedSeconds) { + const time_zone tz = utc_time_zone(); + + // No subseconds. + time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0); + tp += chrono::seconds(5); + EXPECT_EQ("05", format("%E*S", tp, tz)); + EXPECT_EQ("05", format("%E0S", tp, tz)); + EXPECT_EQ("05.0", format("%E1S", tp, tz)); + EXPECT_EQ("05.00", format("%E2S", tp, tz)); + EXPECT_EQ("05.000", format("%E3S", tp, tz)); + EXPECT_EQ("05.0000", format("%E4S", tp, tz)); + EXPECT_EQ("05.00000", format("%E5S", tp, tz)); + EXPECT_EQ("05.000000", format("%E6S", tp, tz)); + EXPECT_EQ("05.0000000", format("%E7S", tp, tz)); + EXPECT_EQ("05.00000000", format("%E8S", tp, tz)); + EXPECT_EQ("05.000000000", format("%E9S", tp, tz)); + EXPECT_EQ("05.0000000000", format("%E10S", tp, tz)); + EXPECT_EQ("05.00000000000", format("%E11S", tp, tz)); + EXPECT_EQ("05.000000000000", format("%E12S", tp, tz)); + EXPECT_EQ("05.0000000000000", format("%E13S", tp, tz)); + EXPECT_EQ("05.00000000000000", format("%E14S", tp, tz)); + EXPECT_EQ("05.000000000000000", format("%E15S", tp, tz)); + + // With subseconds. + tp += chrono::milliseconds(6) + chrono::microseconds(7) + + chrono::nanoseconds(8); + EXPECT_EQ("05.006007008", format("%E*S", tp, tz)); + EXPECT_EQ("05", format("%E0S", tp, tz)); + EXPECT_EQ("05.0", format("%E1S", tp, tz)); + EXPECT_EQ("05.00", format("%E2S", tp, tz)); + EXPECT_EQ("05.006", format("%E3S", tp, tz)); + EXPECT_EQ("05.0060", format("%E4S", tp, tz)); + EXPECT_EQ("05.00600", format("%E5S", tp, tz)); + EXPECT_EQ("05.006007", format("%E6S", tp, tz)); + EXPECT_EQ("05.0060070", format("%E7S", tp, tz)); + EXPECT_EQ("05.00600700", format("%E8S", tp, tz)); + EXPECT_EQ("05.006007008", format("%E9S", tp, tz)); + EXPECT_EQ("05.0060070080", format("%E10S", tp, tz)); + EXPECT_EQ("05.00600700800", format("%E11S", tp, tz)); + EXPECT_EQ("05.006007008000", format("%E12S", tp, tz)); + EXPECT_EQ("05.0060070080000", format("%E13S", tp, tz)); + EXPECT_EQ("05.00600700800000", format("%E14S", tp, tz)); + EXPECT_EQ("05.006007008000000", format("%E15S", tp, tz)); + + // Times before the Unix epoch. + tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1); + EXPECT_EQ("1969-12-31 23:59:59.999999", + format("%Y-%m-%d %H:%M:%E*S", tp, tz)); + + // Here is a "%E*S" case we got wrong for a while. While the first + // instant below is correctly rendered as "...:07.333304", the second + // one used to appear as "...:07.33330499999999999". + tp = chrono::system_clock::from_time_t(0) + + chrono::microseconds(1395024427333304); + EXPECT_EQ("2014-03-17 02:47:07.333304", + format("%Y-%m-%d %H:%M:%E*S", tp, tz)); + tp += chrono::microseconds(1); + EXPECT_EQ("2014-03-17 02:47:07.333305", + format("%Y-%m-%d %H:%M:%E*S", tp, tz)); +} + +TEST(Format, ExtendedSubeconds) { + const time_zone tz = utc_time_zone(); + + // No subseconds. + time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0); + tp += chrono::seconds(5); + EXPECT_EQ("0", format("%E*f", tp, tz)); + EXPECT_EQ("", format("%E0f", tp, tz)); + EXPECT_EQ("0", format("%E1f", tp, tz)); + EXPECT_EQ("00", format("%E2f", tp, tz)); + EXPECT_EQ("000", format("%E3f", tp, tz)); + EXPECT_EQ("0000", format("%E4f", tp, tz)); + EXPECT_EQ("00000", format("%E5f", tp, tz)); + EXPECT_EQ("000000", format("%E6f", tp, tz)); + EXPECT_EQ("0000000", format("%E7f", tp, tz)); + EXPECT_EQ("00000000", format("%E8f", tp, tz)); + EXPECT_EQ("000000000", format("%E9f", tp, tz)); + EXPECT_EQ("0000000000", format("%E10f", tp, tz)); + EXPECT_EQ("00000000000", format("%E11f", tp, tz)); + EXPECT_EQ("000000000000", format("%E12f", tp, tz)); + EXPECT_EQ("0000000000000", format("%E13f", tp, tz)); + EXPECT_EQ("00000000000000", format("%E14f", tp, tz)); + EXPECT_EQ("000000000000000", format("%E15f", tp, tz)); + + // With subseconds. + tp += chrono::milliseconds(6) + chrono::microseconds(7) + + chrono::nanoseconds(8); + EXPECT_EQ("006007008", format("%E*f", tp, tz)); + EXPECT_EQ("", format("%E0f", tp, tz)); + EXPECT_EQ("0", format("%E1f", tp, tz)); + EXPECT_EQ("00", format("%E2f", tp, tz)); + EXPECT_EQ("006", format("%E3f", tp, tz)); + EXPECT_EQ("0060", format("%E4f", tp, tz)); + EXPECT_EQ("00600", format("%E5f", tp, tz)); + EXPECT_EQ("006007", format("%E6f", tp, tz)); + EXPECT_EQ("0060070", format("%E7f", tp, tz)); + EXPECT_EQ("00600700", format("%E8f", tp, tz)); + EXPECT_EQ("006007008", format("%E9f", tp, tz)); + EXPECT_EQ("0060070080", format("%E10f", tp, tz)); + EXPECT_EQ("00600700800", format("%E11f", tp, tz)); + EXPECT_EQ("006007008000", format("%E12f", tp, tz)); + EXPECT_EQ("0060070080000", format("%E13f", tp, tz)); + EXPECT_EQ("00600700800000", format("%E14f", tp, tz)); + EXPECT_EQ("006007008000000", format("%E15f", tp, tz)); + + // Times before the Unix epoch. + tp = chrono::system_clock::from_time_t(0) + chrono::microseconds(-1); + EXPECT_EQ("1969-12-31 23:59:59.999999", + format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz)); + + // Here is a "%E*S" case we got wrong for a while. While the first + // instant below is correctly rendered as "...:07.333304", the second + // one used to appear as "...:07.33330499999999999". + tp = chrono::system_clock::from_time_t(0) + + chrono::microseconds(1395024427333304); + EXPECT_EQ("2014-03-17 02:47:07.333304", + format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz)); + tp += chrono::microseconds(1); + EXPECT_EQ("2014-03-17 02:47:07.333305", + format("%Y-%m-%d %H:%M:%S.%E*f", tp, tz)); +} + +TEST(Format, CompareExtendSecondsVsSubseconds) { + const time_zone tz = utc_time_zone(); + + // This test case illustrates the differences/similarities between: + // fmt_A: %E<prec>S + // fmt_B: %S.%E<prec>f + auto fmt_A = [](const std::string& prec) { return "%E" + prec + "S"; }; + auto fmt_B = [](const std::string& prec) { return "%S.%E" + prec + "f"; }; + + // No subseconds: + time_point<chrono::nanoseconds> tp = chrono::system_clock::from_time_t(0); + tp += chrono::seconds(5); + // ... %E*S and %S.%E*f are different. + EXPECT_EQ("05", format(fmt_A("*"), tp, tz)); + EXPECT_EQ("05.0", format(fmt_B("*"), tp, tz)); + // ... %E0S and %S.%E0f are different. + EXPECT_EQ("05", format(fmt_A("0"), tp, tz)); + EXPECT_EQ("05.", format(fmt_B("0"), tp, tz)); + // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15]. + for (int prec = 1; prec <= 15; ++prec) { + const std::string a = format(fmt_A(std::to_string(prec)), tp, tz); + const std::string b = format(fmt_B(std::to_string(prec)), tp, tz); + EXPECT_EQ(a, b) << "prec=" << prec; + } + + // With subseconds: + // ... %E*S and %S.%E*f are the same. + tp += chrono::milliseconds(6) + chrono::microseconds(7) + + chrono::nanoseconds(8); + EXPECT_EQ("05.006007008", format(fmt_A("*"), tp, tz)); + EXPECT_EQ("05.006007008", format(fmt_B("*"), tp, tz)); + // ... %E0S and %S.%E0f are different. + EXPECT_EQ("05", format(fmt_A("0"), tp, tz)); + EXPECT_EQ("05.", format(fmt_B("0"), tp, tz)); + // ... %E<prec>S and %S.%E<prec>f are the same for prec in [1:15]. + for (int prec = 1; prec <= 15; ++prec) { + const std::string a = format(fmt_A(std::to_string(prec)), tp, tz); + const std::string b = format(fmt_B(std::to_string(prec)), tp, tz); + EXPECT_EQ(a, b) << "prec=" << prec; + } +} + +TEST(Format, ExtendedOffset) { + const auto tp = chrono::system_clock::from_time_t(0); + + auto tz = fixed_time_zone(cctz::seconds::zero()); + TestFormatSpecifier(tp, tz, "%z", "+0000"); + TestFormatSpecifier(tp, tz, "%:z", "+00:00"); + TestFormatSpecifier(tp, tz, "%Ez", "+00:00"); + + tz = fixed_time_zone(chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "+0000"); + TestFormatSpecifier(tp, tz, "%:z", "+00:00"); + TestFormatSpecifier(tp, tz, "%Ez", "+00:00"); + + tz = fixed_time_zone(-chrono::seconds(56)); // NOTE: +00:00 + TestFormatSpecifier(tp, tz, "%z", "+0000"); + TestFormatSpecifier(tp, tz, "%:z", "+00:00"); + TestFormatSpecifier(tp, tz, "%Ez", "+00:00"); + + tz = fixed_time_zone(chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%z", "+0034"); + TestFormatSpecifier(tp, tz, "%:z", "+00:34"); + TestFormatSpecifier(tp, tz, "%Ez", "+00:34"); + + tz = fixed_time_zone(-chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%z", "-0034"); + TestFormatSpecifier(tp, tz, "%:z", "-00:34"); + TestFormatSpecifier(tp, tz, "%Ez", "-00:34"); + + tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "+0034"); + TestFormatSpecifier(tp, tz, "%:z", "+00:34"); + TestFormatSpecifier(tp, tz, "%Ez", "+00:34"); + + tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "-0034"); + TestFormatSpecifier(tp, tz, "%:z", "-00:34"); + TestFormatSpecifier(tp, tz, "%Ez", "-00:34"); + + tz = fixed_time_zone(chrono::hours(12)); + TestFormatSpecifier(tp, tz, "%z", "+1200"); + TestFormatSpecifier(tp, tz, "%:z", "+12:00"); + TestFormatSpecifier(tp, tz, "%Ez", "+12:00"); + + tz = fixed_time_zone(-chrono::hours(12)); + TestFormatSpecifier(tp, tz, "%z", "-1200"); + TestFormatSpecifier(tp, tz, "%:z", "-12:00"); + TestFormatSpecifier(tp, tz, "%Ez", "-12:00"); + + tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "+1200"); + TestFormatSpecifier(tp, tz, "%:z", "+12:00"); + TestFormatSpecifier(tp, tz, "%Ez", "+12:00"); + + tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "-1200"); + TestFormatSpecifier(tp, tz, "%:z", "-12:00"); + TestFormatSpecifier(tp, tz, "%Ez", "-12:00"); + + tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%z", "+1234"); + TestFormatSpecifier(tp, tz, "%:z", "+12:34"); + TestFormatSpecifier(tp, tz, "%Ez", "+12:34"); + + tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%z", "-1234"); + TestFormatSpecifier(tp, tz, "%:z", "-12:34"); + TestFormatSpecifier(tp, tz, "%Ez", "-12:34"); + + tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) + + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "+1234"); + TestFormatSpecifier(tp, tz, "%:z", "+12:34"); + TestFormatSpecifier(tp, tz, "%Ez", "+12:34"); + + tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) - + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%z", "-1234"); + TestFormatSpecifier(tp, tz, "%:z", "-12:34"); + TestFormatSpecifier(tp, tz, "%Ez", "-12:34"); +} + +TEST(Format, ExtendedSecondOffset) { + const auto tp = chrono::system_clock::from_time_t(0); + + auto tz = fixed_time_zone(cctz::seconds::zero()); + TestFormatSpecifier(tp, tz, "%E*z", "+00:00:00"); + TestFormatSpecifier(tp, tz, "%::z", "+00:00:00"); + TestFormatSpecifier(tp, tz, "%:::z", "+00"); + + tz = fixed_time_zone(chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "+00:00:56"); + TestFormatSpecifier(tp, tz, "%::z", "+00:00:56"); + TestFormatSpecifier(tp, tz, "%:::z", "+00:00:56"); + + tz = fixed_time_zone(-chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "-00:00:56"); + TestFormatSpecifier(tp, tz, "%::z", "-00:00:56"); + TestFormatSpecifier(tp, tz, "%:::z", "-00:00:56"); + + tz = fixed_time_zone(chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%E*z", "+00:34:00"); + TestFormatSpecifier(tp, tz, "%::z", "+00:34:00"); + TestFormatSpecifier(tp, tz, "%:::z", "+00:34"); + + tz = fixed_time_zone(-chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%E*z", "-00:34:00"); + TestFormatSpecifier(tp, tz, "%::z", "-00:34:00"); + TestFormatSpecifier(tp, tz, "%:::z", "-00:34"); + + tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "+00:34:56"); + TestFormatSpecifier(tp, tz, "%::z", "+00:34:56"); + TestFormatSpecifier(tp, tz, "%:::z", "+00:34:56"); + + tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "-00:34:56"); + TestFormatSpecifier(tp, tz, "%::z", "-00:34:56"); + TestFormatSpecifier(tp, tz, "%:::z", "-00:34:56"); + + tz = fixed_time_zone(chrono::hours(12)); + TestFormatSpecifier(tp, tz, "%E*z", "+12:00:00"); + TestFormatSpecifier(tp, tz, "%::z", "+12:00:00"); + TestFormatSpecifier(tp, tz, "%:::z", "+12"); + + tz = fixed_time_zone(-chrono::hours(12)); + TestFormatSpecifier(tp, tz, "%E*z", "-12:00:00"); + TestFormatSpecifier(tp, tz, "%::z", "-12:00:00"); + TestFormatSpecifier(tp, tz, "%:::z", "-12"); + + tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "+12:00:56"); + TestFormatSpecifier(tp, tz, "%::z", "+12:00:56"); + TestFormatSpecifier(tp, tz, "%:::z", "+12:00:56"); + + tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "-12:00:56"); + TestFormatSpecifier(tp, tz, "%::z", "-12:00:56"); + TestFormatSpecifier(tp, tz, "%:::z", "-12:00:56"); + + tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%E*z", "+12:34:00"); + TestFormatSpecifier(tp, tz, "%::z", "+12:34:00"); + TestFormatSpecifier(tp, tz, "%:::z", "+12:34"); + + tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34)); + TestFormatSpecifier(tp, tz, "%E*z", "-12:34:00"); + TestFormatSpecifier(tp, tz, "%::z", "-12:34:00"); + TestFormatSpecifier(tp, tz, "%:::z", "-12:34"); + + tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) + + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "+12:34:56"); + TestFormatSpecifier(tp, tz, "%::z", "+12:34:56"); + TestFormatSpecifier(tp, tz, "%:::z", "+12:34:56"); + + tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) - + chrono::seconds(56)); + TestFormatSpecifier(tp, tz, "%E*z", "-12:34:56"); + TestFormatSpecifier(tp, tz, "%::z", "-12:34:56"); + TestFormatSpecifier(tp, tz, "%:::z", "-12:34:56"); +} + +TEST(Format, ExtendedYears) { + const time_zone utc = utc_time_zone(); + const char e4y_fmt[] = "%E4Y%m%d"; // no separators + + // %E4Y zero-pads the year to produce at least 4 chars, including the sign. + auto tp = convert(civil_second(-999, 11, 27, 0, 0, 0), utc); + EXPECT_EQ("-9991127", format(e4y_fmt, tp, utc)); + tp = convert(civil_second(-99, 11, 27, 0, 0, 0), utc); + EXPECT_EQ("-0991127", format(e4y_fmt, tp, utc)); + tp = convert(civil_second(-9, 11, 27, 0, 0, 0), utc); + EXPECT_EQ("-0091127", format(e4y_fmt, tp, utc)); + tp = convert(civil_second(-1, 11, 27, 0, 0, 0), utc); + EXPECT_EQ("-0011127", format(e4y_fmt, tp, utc)); + tp = convert(civil_second(0, 11, 27, 0, 0, 0), utc); + EXPECT_EQ("00001127", format(e4y_fmt, tp, utc)); + tp = convert(civil_second(1, 11, 27, 0, 0, 0), utc); + EXPECT_EQ("00011127", format(e4y_fmt, tp, utc)); + tp = convert(civil_second(9, 11, 27, 0, 0, 0), utc); + EXPECT_EQ("00091127", format(e4y_fmt, tp, utc)); + tp = convert(civil_second(99, 11, 27, 0, 0, 0), utc); + EXPECT_EQ("00991127", format(e4y_fmt, tp, utc)); + tp = convert(civil_second(999, 11, 27, 0, 0, 0), utc); + EXPECT_EQ("09991127", format(e4y_fmt, tp, utc)); + tp = convert(civil_second(9999, 11, 27, 0, 0, 0), utc); + EXPECT_EQ("99991127", format(e4y_fmt, tp, utc)); + + // When the year is outside [-999:9999], more than 4 chars are produced. + tp = convert(civil_second(-1000, 11, 27, 0, 0, 0), utc); + EXPECT_EQ("-10001127", format(e4y_fmt, tp, utc)); + tp = convert(civil_second(10000, 11, 27, 0, 0, 0), utc); + EXPECT_EQ("100001127", format(e4y_fmt, tp, utc)); +} + +TEST(Format, RFC3339Format) { + time_zone tz; + EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); + + time_point<chrono::nanoseconds> tp = + convert(civil_second(1977, 6, 28, 9, 8, 7), tz); + EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + + tp += chrono::milliseconds(100); + EXPECT_EQ("1977-06-28T09:08:07.1-07:00", format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + + tp += chrono::milliseconds(20); + EXPECT_EQ("1977-06-28T09:08:07.12-07:00", format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + + tp += chrono::milliseconds(3); + EXPECT_EQ("1977-06-28T09:08:07.123-07:00", format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + + tp += chrono::microseconds(400); + EXPECT_EQ("1977-06-28T09:08:07.1234-07:00", format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + + tp += chrono::microseconds(50); + EXPECT_EQ("1977-06-28T09:08:07.12345-07:00", format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + + tp += chrono::microseconds(6); + EXPECT_EQ("1977-06-28T09:08:07.123456-07:00", format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + + tp += chrono::nanoseconds(700); + EXPECT_EQ("1977-06-28T09:08:07.1234567-07:00", format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + + tp += chrono::nanoseconds(80); + EXPECT_EQ("1977-06-28T09:08:07.12345678-07:00", format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); + + tp += chrono::nanoseconds(9); + EXPECT_EQ("1977-06-28T09:08:07.123456789-07:00", + format(RFC3339_full, tp, tz)); + EXPECT_EQ("1977-06-28T09:08:07-07:00", format(RFC3339_sec, tp, tz)); +} + +TEST(Format, RFC1123Format) { // locale specific + time_zone tz; + EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); + + auto tp = convert(civil_second(1977, 6, 28, 9, 8, 7), tz); + EXPECT_EQ("Tue, 28 Jun 1977 09:08:07 -0700", format(RFC1123_full, tp, tz)); + EXPECT_EQ("28 Jun 1977 09:08:07 -0700", format(RFC1123_no_wday, tp, tz)); +} + +TEST(Format, Week) { + const time_zone utc = utc_time_zone(); + + auto tp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc); + EXPECT_EQ("2017-01-7", format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2017-00-0", format("%Y-%W-%w", tp, utc)); + + tp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc); + EXPECT_EQ("2017-53-7", format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2017-52-0", format("%Y-%W-%w", tp, utc)); + + tp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc); + EXPECT_EQ("2018-00-1", format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2018-01-1", format("%Y-%W-%w", tp, utc)); + + tp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc); + EXPECT_EQ("2018-52-1", format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2018-53-1", format("%Y-%W-%w", tp, utc)); + + tp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc); + EXPECT_EQ("2019-00-2", format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2019-00-2", format("%Y-%W-%w", tp, utc)); + + tp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc); + EXPECT_EQ("2019-52-2", format("%Y-%U-%u", tp, utc)); + EXPECT_EQ("2019-52-2", format("%Y-%W-%w", tp, utc)); +} + +// +// Testing parse() +// + +TEST(Parse, TimePointResolution) { + const char kFmt[] = "%H:%M:%E*S"; + const time_zone utc = utc_time_zone(); + + time_point<chrono::nanoseconds> tp_ns; + EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_ns)); + EXPECT_EQ("03:04:05.123456789", format(kFmt, tp_ns, utc)); + EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ns)); + EXPECT_EQ("03:04:05.123456", format(kFmt, tp_ns, utc)); + + time_point<chrono::microseconds> tp_us; + EXPECT_TRUE(parse(kFmt, "03:04:05.123456789", utc, &tp_us)); + EXPECT_EQ("03:04:05.123456", format(kFmt, tp_us, utc)); + EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_us)); + EXPECT_EQ("03:04:05.123456", format(kFmt, tp_us, utc)); + EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_us)); + EXPECT_EQ("03:04:05.123", format(kFmt, tp_us, utc)); + + time_point<chrono::milliseconds> tp_ms; + EXPECT_TRUE(parse(kFmt, "03:04:05.123456", utc, &tp_ms)); + EXPECT_EQ("03:04:05.123", format(kFmt, tp_ms, utc)); + EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_ms)); + EXPECT_EQ("03:04:05.123", format(kFmt, tp_ms, utc)); + EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_ms)); + EXPECT_EQ("03:04:05", format(kFmt, tp_ms, utc)); + + time_point<chrono::seconds> tp_s; + EXPECT_TRUE(parse(kFmt, "03:04:05.123", utc, &tp_s)); + EXPECT_EQ("03:04:05", format(kFmt, tp_s, utc)); + EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_s)); + EXPECT_EQ("03:04:05", format(kFmt, tp_s, utc)); + + time_point<chrono::minutes> tp_m; + EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_m)); + EXPECT_EQ("03:04:00", format(kFmt, tp_m, utc)); + + time_point<chrono::hours> tp_h; + EXPECT_TRUE(parse(kFmt, "03:04:05", utc, &tp_h)); + EXPECT_EQ("03:00:00", format(kFmt, tp_h, utc)); +} + +TEST(Parse, TimePointExtendedResolution) { + const char kFmt[] = "%H:%M:%E*S"; + const time_zone utc = utc_time_zone(); + + time_point<cctz::seconds> tp; + detail::femtoseconds fs; + EXPECT_TRUE(detail::parse(kFmt, "12:34:56.123456789012345", utc, &tp, &fs)); + EXPECT_EQ("12:34:56.123456789012345", detail::format(kFmt, tp, fs, utc)); + EXPECT_TRUE(detail::parse(kFmt, "12:34:56.012345678901234", utc, &tp, &fs)); + EXPECT_EQ("12:34:56.012345678901234", detail::format(kFmt, tp, fs, utc)); + EXPECT_TRUE(detail::parse(kFmt, "12:34:56.001234567890123", utc, &tp, &fs)); + EXPECT_EQ("12:34:56.001234567890123", detail::format(kFmt, tp, fs, utc)); + EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000123", utc, &tp, &fs)); + EXPECT_EQ("12:34:56.000000000000123", detail::format(kFmt, tp, fs, utc)); + EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000012", utc, &tp, &fs)); + EXPECT_EQ("12:34:56.000000000000012", detail::format(kFmt, tp, fs, utc)); + EXPECT_TRUE(detail::parse(kFmt, "12:34:56.000000000000001", utc, &tp, &fs)); + EXPECT_EQ("12:34:56.000000000000001", detail::format(kFmt, tp, fs, utc)); +} + +TEST(Parse, Basics) { + time_zone tz = utc_time_zone(); + time_point<chrono::nanoseconds> tp = + chrono::system_clock::from_time_t(1234567890); + + // Simple edge cases. + EXPECT_TRUE(parse("", "", tz, &tp)); + EXPECT_EQ(chrono::system_clock::from_time_t(0), tp); // everything defaulted + EXPECT_TRUE(parse(" ", " ", tz, &tp)); + EXPECT_TRUE(parse(" ", " ", tz, &tp)); + EXPECT_TRUE(parse("x", "x", tz, &tp)); + EXPECT_TRUE(parse("xxx", "xxx", tz, &tp)); + + EXPECT_TRUE( + parse("%Y-%m-%d %H:%M:%S %z", "2013-06-28 19:08:09 -0800", tz, &tp)); + ExpectTime(tp, tz, 2013, 6, 29, 3, 8, 9, 0, false, "UTC"); +} + +TEST(Parse, WithTimeZone) { + time_zone tz; + EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); + time_point<chrono::nanoseconds> tp; + + // We can parse a string without a UTC offset if we supply a timezone. + EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &tp)); + ExpectTime(tp, tz, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true, "PDT"); + + // But the timezone is ignored when a UTC offset is present. + EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S %z", "2013-06-28 19:08:09 +0800", + utc_time_zone(), &tp)); + ExpectTime(tp, tz, 2013, 6, 28, 19 - 8 - 7, 8, 9, -7 * 60 * 60, true, "PDT"); + + // Check a skipped time (a Spring DST transition). parse() uses the + // pre-transition offset. + EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-03-13 02:15:00", tz, &tp)); + ExpectTime(tp, tz, 2011, 3, 13, 3, 15, 0, -7 * 60 * 60, true, "PDT"); + + // Check a repeated time (a Fall DST transition). parse() uses the + // pre-transition offset. + EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2011-11-06 01:15:00", tz, &tp)); + ExpectTime(tp, tz, 2011, 11, 6, 1, 15, 0, -7 * 60 * 60, true, "PDT"); +} + +TEST(Parse, LeapSecond) { + time_zone tz; + EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz)); + time_point<chrono::nanoseconds> tp; + + // ":59" -> ":59" + EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59-08:00", tz, &tp)); + ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, "PDT"); + + // ":59.5" -> ":59.5" + EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:59.5-08:00", tz, &tp)); + ExpectTime(tp, tz, 2013, 6, 28, 8, 8, 59, -7 * 60 * 60, true, "PDT"); + + // ":60" -> ":00" + EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:60-08:00", tz, &tp)); + ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, "PDT"); + + // ":60.5" -> ":00.0" + EXPECT_TRUE(parse(RFC3339_full, "2013-06-28T07:08:60.5-08:00", tz, &tp)); + ExpectTime(tp, tz, 2013, 6, 28, 8, 9, 0, -7 * 60 * 60, true, "PDT"); + + // ":61" -> error + EXPECT_FALSE(parse(RFC3339_full, "2013-06-28T07:08:61-08:00", tz, &tp)); +} + +TEST(Parse, ErrorCases) { + const time_zone tz = utc_time_zone(); + auto tp = chrono::system_clock::from_time_t(0); + + // Illegal trailing data. + EXPECT_FALSE(parse("%S", "123", tz, &tp)); + + // Can't parse an illegal format specifier. + EXPECT_FALSE(parse("%Q", "x", tz, &tp)); + + // Fails because of trailing, unparsed data "blah". + EXPECT_FALSE(parse("%m-%d", "2-3 blah", tz, &tp)); + + // Trailing whitespace is allowed. + EXPECT_TRUE(parse("%m-%d", "2-3 ", tz, &tp)); + EXPECT_EQ(2, convert(tp, utc_time_zone()).month()); + EXPECT_EQ(3, convert(tp, utc_time_zone()).day()); + + // Feb 31 requires normalization. + EXPECT_FALSE(parse("%m-%d", "2-31", tz, &tp)); + + // Check that we cannot have spaces in UTC offsets. + EXPECT_TRUE(parse("%z", "-0203", tz, &tp)); + EXPECT_FALSE(parse("%z", "- 2 3", tz, &tp)); + EXPECT_TRUE(parse("%Ez", "-02:03", tz, &tp)); + EXPECT_FALSE(parse("%Ez", "- 2: 3", tz, &tp)); + + // Check that we reject other malformed UTC offsets. + EXPECT_FALSE(parse("%Ez", "+-08:00", tz, &tp)); + EXPECT_FALSE(parse("%Ez", "-+08:00", tz, &tp)); + + // Check that we do not accept "-0" in fields that allow zero. + EXPECT_FALSE(parse("%Y", "-0", tz, &tp)); + EXPECT_FALSE(parse("%E4Y", "-0", tz, &tp)); + EXPECT_FALSE(parse("%H", "-0", tz, &tp)); + EXPECT_FALSE(parse("%M", "-0", tz, &tp)); + EXPECT_FALSE(parse("%S", "-0", tz, &tp)); + EXPECT_FALSE(parse("%z", "+-000", tz, &tp)); + EXPECT_FALSE(parse("%Ez", "+-0:00", tz, &tp)); + EXPECT_FALSE(parse("%z", "-00-0", tz, &tp)); + EXPECT_FALSE(parse("%Ez", "-00:-0", tz, &tp)); +} + +TEST(Parse, PosixConversions) { + time_zone tz = utc_time_zone(); + auto tp = chrono::system_clock::from_time_t(0); + const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz); + + tp = reset; + EXPECT_TRUE(parse("%d", "15", tz, &tp)); + EXPECT_EQ(15, convert(tp, tz).day()); + + // %e is an extension, but is supported internally. + tp = reset; + EXPECT_TRUE(parse("%e", "15", tz, &tp)); + EXPECT_EQ(15, convert(tp, tz).day()); // Equivalent to %d + + tp = reset; + EXPECT_TRUE(parse("%H", "17", tz, &tp)); + EXPECT_EQ(17, convert(tp, tz).hour()); + + tp = reset; + EXPECT_TRUE(parse("%I", "5", tz, &tp)); + EXPECT_EQ(5, convert(tp, tz).hour()); + + // %j is parsed but ignored. + EXPECT_TRUE(parse("%j", "32", tz, &tp)); + + tp = reset; + EXPECT_TRUE(parse("%m", "11", tz, &tp)); + EXPECT_EQ(11, convert(tp, tz).month()); + + tp = reset; + EXPECT_TRUE(parse("%M", "33", tz, &tp)); + EXPECT_EQ(33, convert(tp, tz).minute()); + + tp = reset; + EXPECT_TRUE(parse("%S", "55", tz, &tp)); + EXPECT_EQ(55, convert(tp, tz).second()); + + // %U is parsed but ignored. + EXPECT_TRUE(parse("%U", "15", tz, &tp)); + + // %w is parsed but ignored. + EXPECT_TRUE(parse("%w", "2", tz, &tp)); + + // %W is parsed but ignored. + EXPECT_TRUE(parse("%W", "22", tz, &tp)); + + tp = reset; + EXPECT_TRUE(parse("%y", "04", tz, &tp)); + EXPECT_EQ(2004, convert(tp, tz).year()); + + tp = reset; + EXPECT_TRUE(parse("%Y", "2004", tz, &tp)); + EXPECT_EQ(2004, convert(tp, tz).year()); + + EXPECT_TRUE(parse("%%", "%", tz, &tp)); + +#if defined(__linux__) + // SU/C99/TZ extensions + + // Because we handle each (non-internal) specifier in a separate call + // to strptime(), there is no way to group %C and %y together. So we + // just skip the %C/%y case. +#if 0 + tp = reset; + EXPECT_TRUE(parse("%C %y", "20 04", tz, &tp)); + EXPECT_EQ(2004, convert(tp, tz).year()); +#endif + + tp = reset; + EXPECT_TRUE(parse("%D", "02/03/04", tz, &tp)); + EXPECT_EQ(2, convert(tp, tz).month()); + EXPECT_EQ(3, convert(tp, tz).day()); + EXPECT_EQ(2004, convert(tp, tz).year()); + + EXPECT_TRUE(parse("%n", "\n", tz, &tp)); + + tp = reset; + EXPECT_TRUE(parse("%R", "03:44", tz, &tp)); + EXPECT_EQ(3, convert(tp, tz).hour()); + EXPECT_EQ(44, convert(tp, tz).minute()); + + EXPECT_TRUE(parse("%t", "\t\v\f\n\r ", tz, &tp)); + + tp = reset; + EXPECT_TRUE(parse("%T", "03:44:55", tz, &tp)); + EXPECT_EQ(3, convert(tp, tz).hour()); + EXPECT_EQ(44, convert(tp, tz).minute()); + EXPECT_EQ(55, convert(tp, tz).second()); + + tp = reset; + EXPECT_TRUE(parse("%s", "1234567890", tz, &tp)); + EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp); + + // %s conversion, like %z/%Ez, pays no heed to the optional zone. + time_zone lax; + EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax)); + tp = reset; + EXPECT_TRUE(parse("%s", "1234567890", lax, &tp)); + EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp); + + // This is most important when the time has the same YMDhms + // breakdown in the zone as some other time. For example, ... + // 1414917000 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PDT) + // 1414920600 in US/Pacific -> Sun Nov 2 01:30:00 2014 (PST) + tp = reset; + EXPECT_TRUE(parse("%s", "1414917000", lax, &tp)); + EXPECT_EQ(chrono::system_clock::from_time_t(1414917000), tp); + tp = reset; + EXPECT_TRUE(parse("%s", "1414920600", lax, &tp)); + EXPECT_EQ(chrono::system_clock::from_time_t(1414920600), tp); +#endif +} + +TEST(Parse, LocaleSpecific) { + time_zone tz = utc_time_zone(); + auto tp = chrono::system_clock::from_time_t(0); + const auto reset = convert(civil_second(1977, 6, 28, 9, 8, 7), tz); + + // %a is parsed but ignored. + EXPECT_TRUE(parse("%a", "Mon", tz, &tp)); + + // %A is parsed but ignored. + EXPECT_TRUE(parse("%A", "Monday", tz, &tp)); + + tp = reset; + EXPECT_TRUE(parse("%b", "Feb", tz, &tp)); + EXPECT_EQ(2, convert(tp, tz).month()); + + tp = reset; + EXPECT_TRUE(parse("%B", "February", tz, &tp)); + EXPECT_EQ(2, convert(tp, tz).month()); + + // %p is parsed but ignored if it's alone. But it's used with %I. + EXPECT_TRUE(parse("%p", "AM", tz, &tp)); + tp = reset; + EXPECT_TRUE(parse("%I %p", "5 PM", tz, &tp)); + EXPECT_EQ(17, convert(tp, tz).hour()); + + tp = reset; + EXPECT_TRUE(parse("%x", "02/03/04", tz, &tp)); + if (convert(tp, tz).month() == 2) { + EXPECT_EQ(3, convert(tp, tz).day()); + } else { + EXPECT_EQ(2, convert(tp, tz).day()); + EXPECT_EQ(3, convert(tp, tz).month()); + } + EXPECT_EQ(2004, convert(tp, tz).year()); + + tp = reset; + EXPECT_TRUE(parse("%X", "15:44:55", tz, &tp)); + EXPECT_EQ(15, convert(tp, tz).hour()); + EXPECT_EQ(44, convert(tp, tz).minute()); + EXPECT_EQ(55, convert(tp, tz).second()); + +#if defined(__linux__) + // SU/C99/TZ extensions + + tp = reset; + EXPECT_TRUE(parse("%h", "Feb", tz, &tp)); + EXPECT_EQ(2, convert(tp, tz).month()); // Equivalent to %b + + tp = reset; + EXPECT_TRUE(parse("%l %p", "5 PM", tz, &tp)); + EXPECT_EQ(17, convert(tp, tz).hour()); + + tp = reset; + EXPECT_TRUE(parse("%r", "03:44:55 PM", tz, &tp)); + EXPECT_EQ(15, convert(tp, tz).hour()); + EXPECT_EQ(44, convert(tp, tz).minute()); + EXPECT_EQ(55, convert(tp, tz).second()); + + tp = reset; + EXPECT_TRUE(parse("%Ec", "Tue Nov 19 05:06:07 2013", tz, &tp)); + EXPECT_EQ(convert(civil_second(2013, 11, 19, 5, 6, 7), tz), tp); + + // Modified conversion specifiers %E_ + + tp = reset; + EXPECT_TRUE(parse("%Ex", "02/03/04", tz, &tp)); + EXPECT_EQ(2, convert(tp, tz).month()); + EXPECT_EQ(3, convert(tp, tz).day()); + EXPECT_EQ(2004, convert(tp, tz).year()); + + tp = reset; + EXPECT_TRUE(parse("%EX", "15:44:55", tz, &tp)); + EXPECT_EQ(15, convert(tp, tz).hour()); + EXPECT_EQ(44, convert(tp, tz).minute()); + EXPECT_EQ(55, convert(tp, tz).second()); + + // %Ey, the year offset from %EC, doesn't really make sense alone as there + // is no way to represent it in tm_year (%EC is not simply the century). + // Yet, because we handle each (non-internal) specifier in a separate call + // to strptime(), there is no way to group %EC and %Ey either. So we just + // skip the %EC and %Ey cases. + + tp = reset; + EXPECT_TRUE(parse("%EY", "2004", tz, &tp)); + EXPECT_EQ(2004, convert(tp, tz).year()); + + // Modified conversion specifiers %O_ + + tp = reset; + EXPECT_TRUE(parse("%Od", "15", tz, &tp)); + EXPECT_EQ(15, convert(tp, tz).day()); + + tp = reset; + EXPECT_TRUE(parse("%Oe", "15", tz, &tp)); + EXPECT_EQ(15, convert(tp, tz).day()); // Equivalent to %d + + tp = reset; + EXPECT_TRUE(parse("%OH", "17", tz, &tp)); + EXPECT_EQ(17, convert(tp, tz).hour()); + + tp = reset; + EXPECT_TRUE(parse("%OI", "5", tz, &tp)); + EXPECT_EQ(5, convert(tp, tz).hour()); + + tp = reset; + EXPECT_TRUE(parse("%Om", "11", tz, &tp)); + EXPECT_EQ(11, convert(tp, tz).month()); + + tp = reset; + EXPECT_TRUE(parse("%OM", "33", tz, &tp)); + EXPECT_EQ(33, convert(tp, tz).minute()); + + tp = reset; + EXPECT_TRUE(parse("%OS", "55", tz, &tp)); + EXPECT_EQ(55, convert(tp, tz).second()); + + // %OU is parsed but ignored. + EXPECT_TRUE(parse("%OU", "15", tz, &tp)); + + // %Ow is parsed but ignored. + EXPECT_TRUE(parse("%Ow", "2", tz, &tp)); + + // %OW is parsed but ignored. + EXPECT_TRUE(parse("%OW", "22", tz, &tp)); + + tp = reset; + EXPECT_TRUE(parse("%Oy", "04", tz, &tp)); + EXPECT_EQ(2004, convert(tp, tz).year()); +#endif +} + +TEST(Parse, ExtendedSeconds) { + const time_zone tz = utc_time_zone(); + const time_point<chrono::nanoseconds> unix_epoch = + chrono::system_clock::from_time_t(0); + + // All %E<prec>S cases are treated the same as %E*S on input. + auto precisions = {"*", "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "10", "11", "12", "13", "14", "15"}; + for (const std::string& prec : precisions) { + const std::string fmt = "%E" + prec + "S"; + SCOPED_TRACE(fmt); + time_point<chrono::nanoseconds> tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "5", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.0", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.00", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.6", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.60", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.600", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(600), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.67", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.670", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(670), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "05.678", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::seconds(5) + chrono::milliseconds(678), tp); + } + + // Here is a "%E*S" case we got wrong for a while. The fractional + // part of the first instant is less than 2^31 and was correctly + // parsed, while the second (and any subsecond field >=2^31) failed. + time_point<chrono::nanoseconds> tp = unix_epoch; + EXPECT_TRUE(parse("%E*S", "0.2147483647", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); + tp = unix_epoch; + EXPECT_TRUE(parse("%E*S", "0.2147483648", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); + + // We should also be able to specify long strings of digits far + // beyond the current resolution and have them convert the same way. + tp = unix_epoch; + EXPECT_TRUE(parse( + "%E*S", "0.214748364801234567890123456789012345678901234567890123456789", + tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); +} + +TEST(Parse, ExtendedSecondsScan) { + const time_zone tz = utc_time_zone(); + time_point<chrono::nanoseconds> tp; + for (int ms = 0; ms < 1000; ms += 111) { + for (int us = 0; us < 1000; us += 27) { + const int micros = ms * 1000 + us; + for (int ns = 0; ns < 1000; ns += 9) { + const auto expected = chrono::system_clock::from_time_t(0) + + chrono::nanoseconds(micros * 1000 + ns); + std::ostringstream oss; + oss << "0." << std::setfill('0') << std::setw(3); + oss << ms << std::setw(3) << us << std::setw(3) << ns; + const std::string input = oss.str(); + EXPECT_TRUE(parse("%E*S", input, tz, &tp)); + EXPECT_EQ(expected, tp) << input; + } + } + } +} + +TEST(Parse, ExtendedSubeconds) { + const time_zone tz = utc_time_zone(); + const time_point<chrono::nanoseconds> unix_epoch = + chrono::system_clock::from_time_t(0); + + // All %E<prec>f cases are treated the same as %E*f on input. + auto precisions = {"*", "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "10", "11", "12", "13", "14", "15"}; + for (const std::string& prec : precisions) { + const std::string fmt = "%E" + prec + "f"; + SCOPED_TRACE(fmt); + time_point<chrono::nanoseconds> tp = unix_epoch - chrono::seconds(1); + EXPECT_TRUE(parse(fmt, "", tz, &tp)); + EXPECT_EQ(unix_epoch, tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "6", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "60", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "600", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::milliseconds(600), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "67", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "670", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::milliseconds(670), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "678", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::milliseconds(678), tp); + tp = unix_epoch; + EXPECT_TRUE(parse(fmt, "6789", tz, &tp)); + EXPECT_EQ( + unix_epoch + chrono::milliseconds(678) + chrono::microseconds(900), tp); + } + + // Here is a "%E*f" case we got wrong for a while. The fractional + // part of the first instant is less than 2^31 and was correctly + // parsed, while the second (and any subsecond field >=2^31) failed. + time_point<chrono::nanoseconds> tp = unix_epoch; + EXPECT_TRUE(parse("%E*f", "2147483647", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); + tp = unix_epoch; + EXPECT_TRUE(parse("%E*f", "2147483648", tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); + + // We should also be able to specify long strings of digits far + // beyond the current resolution and have them convert the same way. + tp = unix_epoch; + EXPECT_TRUE(parse( + "%E*f", "214748364801234567890123456789012345678901234567890123456789", + tz, &tp)); + EXPECT_EQ(unix_epoch + chrono::nanoseconds(214748364), tp); +} + +TEST(Parse, ExtendedSubecondsScan) { + time_point<chrono::nanoseconds> tp; + const time_zone tz = utc_time_zone(); + for (int ms = 0; ms < 1000; ms += 111) { + for (int us = 0; us < 1000; us += 27) { + const int micros = ms * 1000 + us; + for (int ns = 0; ns < 1000; ns += 9) { + std::ostringstream oss; + oss << std::setfill('0') << std::setw(3) << ms; + oss << std::setw(3) << us << std::setw(3) << ns; + const std::string nanos = oss.str(); + const auto expected = chrono::system_clock::from_time_t(0) + + chrono::nanoseconds(micros * 1000 + ns); + for (int ps = 0; ps < 1000; ps += 250) { + std::ostringstream ps_oss; + oss << std::setfill('0') << std::setw(3) << ps; + const std::string input = nanos + ps_oss.str() + "999"; + EXPECT_TRUE(parse("%E*f", input, tz, &tp)); + EXPECT_EQ(expected + chrono::nanoseconds(ps) / 1000, tp) << input; + } + } + } + } +} + +TEST(Parse, ExtendedOffset) { + const time_zone utc = utc_time_zone(); + time_point<cctz::seconds> tp; + + EXPECT_TRUE(parse("%Ez", "+00:00", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse("%Ez", "-12:34", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); + EXPECT_TRUE(parse("%Ez", "+12:34", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); + EXPECT_FALSE(parse("%Ez", "-12:3", utc, &tp)); + + for (auto fmt : {"%Ez", "%z"}) { + EXPECT_TRUE(parse(fmt, "+0000", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-1234", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "+1234", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); + EXPECT_FALSE(parse(fmt, "-123", utc, &tp)); + + EXPECT_TRUE(parse(fmt, "+00", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-12", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "+12", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp); + EXPECT_FALSE(parse(fmt, "-1", utc, &tp)); + } +} + +TEST(Parse, ExtendedSecondOffset) { + const time_zone utc = utc_time_zone(); + time_point<cctz::seconds> tp; + + for (auto fmt : {"%Ez", "%E*z", "%:z", "%::z", "%:::z"}) { + EXPECT_TRUE(parse(fmt, "+00:00:00", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-12:34:56", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp); + EXPECT_TRUE(parse(fmt, "+12:34:56", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp); + EXPECT_FALSE(parse(fmt, "-12:34:5", utc, &tp)); + + EXPECT_TRUE(parse(fmt, "+000000", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-123456", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp); + EXPECT_TRUE(parse(fmt, "+123456", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp); + EXPECT_FALSE(parse(fmt, "-12345", utc, &tp)); + + EXPECT_TRUE(parse(fmt, "+00:00", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-12:34", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "+12:34", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); + EXPECT_FALSE(parse(fmt, "-12:3", utc, &tp)); + + EXPECT_TRUE(parse(fmt, "+0000", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-1234", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "+1234", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp); + EXPECT_FALSE(parse(fmt, "-123", utc, &tp)); + + EXPECT_TRUE(parse(fmt, "+00", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "-12", utc, &tp)); + EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp); + EXPECT_TRUE(parse(fmt, "+12", utc, &tp)); + EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp); + EXPECT_FALSE(parse(fmt, "-1", utc, &tp)); + } +} + +TEST(Parse, ExtendedYears) { + const time_zone utc = utc_time_zone(); + const char e4y_fmt[] = "%E4Y%m%d"; // no separators + time_point<cctz::seconds> tp; + + // %E4Y consumes exactly four chars, including any sign. + EXPECT_TRUE(parse(e4y_fmt, "-9991127", utc, &tp)); + EXPECT_EQ(convert(civil_second(-999, 11, 27, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(e4y_fmt, "-0991127", utc, &tp)); + EXPECT_EQ(convert(civil_second(-99, 11, 27, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(e4y_fmt, "-0091127", utc, &tp)); + EXPECT_EQ(convert(civil_second(-9, 11, 27, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(e4y_fmt, "-0011127", utc, &tp)); + EXPECT_EQ(convert(civil_second(-1, 11, 27, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(e4y_fmt, "00001127", utc, &tp)); + EXPECT_EQ(convert(civil_second(0, 11, 27, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(e4y_fmt, "00011127", utc, &tp)); + EXPECT_EQ(convert(civil_second(1, 11, 27, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(e4y_fmt, "00091127", utc, &tp)); + EXPECT_EQ(convert(civil_second(9, 11, 27, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(e4y_fmt, "00991127", utc, &tp)); + EXPECT_EQ(convert(civil_second(99, 11, 27, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(e4y_fmt, "09991127", utc, &tp)); + EXPECT_EQ(convert(civil_second(999, 11, 27, 0, 0, 0), utc), tp); + EXPECT_TRUE(parse(e4y_fmt, "99991127", utc, &tp)); + EXPECT_EQ(convert(civil_second(9999, 11, 27, 0, 0, 0), utc), tp); + + // When the year is outside [-999:9999], the parse fails. + EXPECT_FALSE(parse(e4y_fmt, "-10001127", utc, &tp)); + EXPECT_FALSE(parse(e4y_fmt, "100001127", utc, &tp)); +} + +TEST(Parse, RFC3339Format) { + const time_zone tz = utc_time_zone(); + time_point<chrono::nanoseconds> tp; + EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00+00:00", tz, &tp)); + ExpectTime(tp, tz, 2014, 2, 12, 20, 21, 0, 0, false, "UTC"); + + // Check that %ET also accepts "t". + time_point<chrono::nanoseconds> tp2; + EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12t20:21:00+00:00", tz, &tp2)); + EXPECT_EQ(tp, tp2); + + // Check that %Ez also accepts "Z" as a synonym for "+00:00". + time_point<chrono::nanoseconds> tp3; + EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp3)); + EXPECT_EQ(tp, tp3); + + // Check that %Ez also accepts "z" as a synonym for "+00:00". + time_point<chrono::nanoseconds> tp4; + EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00z", tz, &tp4)); + EXPECT_EQ(tp, tp4); +} + +TEST(Parse, Week) { + const time_zone utc = utc_time_zone(); + time_point<cctz::seconds> tp; + + auto exp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2017-01-7", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2017-00-0", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2017-53-7", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2017-52-0", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2018-00-1", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2018-01-1", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2018-52-1", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2018-53-1", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2019-00-2", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2019-00-2", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2019-52-2", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2019-52-2", utc, &tp)); + EXPECT_EQ(exp, tp); +} + +TEST(Parse, WeekYearShift) { + // %U/%W conversions with week values in {0, 52, 53} can slip + // into the previous/following calendar years. + const time_zone utc = utc_time_zone(); + time_point<cctz::seconds> tp; + + auto exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2020-00-2", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2020-00-2", utc, &tp)); + EXPECT_EQ(exp, tp); + + exp = convert(civil_second(2021, 1, 1, 0, 0, 0), utc); + EXPECT_TRUE(parse("%Y-%U-%u", "2020-52-5", utc, &tp)); + EXPECT_EQ(exp, tp); + EXPECT_TRUE(parse("%Y-%W-%w", "2020-52-5", utc, &tp)); + EXPECT_EQ(exp, tp); + + // Slipping into the previous/following calendar years should fail when + // we're already at the extremes. + EXPECT_FALSE(parse("%Y-%U-%u", "-9223372036854775808-0-7", utc, &tp)); + EXPECT_FALSE(parse("%Y-%U-%u", "9223372036854775807-53-7", utc, &tp)); +} + +TEST(Parse, MaxRange) { + const time_zone utc = utc_time_zone(); + time_point<cctz::seconds> tp; + + // tests the upper limit using +00:00 offset + EXPECT_TRUE( + parse(RFC3339_sec, "292277026596-12-04T15:30:07+00:00", utc, &tp)); + EXPECT_EQ(tp, time_point<cctz::seconds>::max()); + EXPECT_FALSE( + parse(RFC3339_sec, "292277026596-12-04T15:30:08+00:00", utc, &tp)); + + // tests the upper limit using -01:00 offset + EXPECT_TRUE( + parse(RFC3339_sec, "292277026596-12-04T14:30:07-01:00", utc, &tp)); + EXPECT_EQ(tp, time_point<cctz::seconds>::max()); + EXPECT_FALSE( + parse(RFC3339_sec, "292277026596-12-04T15:30:07-01:00", utc, &tp)); + + // tests the lower limit using +00:00 offset + EXPECT_TRUE( + parse(RFC3339_sec, "-292277022657-01-27T08:29:52+00:00", utc, &tp)); + EXPECT_EQ(tp, time_point<cctz::seconds>::min()); + EXPECT_FALSE( + parse(RFC3339_sec, "-292277022657-01-27T08:29:51+00:00", utc, &tp)); + + // tests the lower limit using +01:00 offset + EXPECT_TRUE( + parse(RFC3339_sec, "-292277022657-01-27T09:29:52+01:00", utc, &tp)); + EXPECT_EQ(tp, time_point<cctz::seconds>::min()); + EXPECT_FALSE( + parse(RFC3339_sec, "-292277022657-01-27T08:29:51+01:00", utc, &tp)); + + // tests max/min civil-second overflow + EXPECT_FALSE(parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01", + utc, &tp)); + EXPECT_FALSE(parse(RFC3339_sec, "-9223372036854775808-01-01T00:00:00+00:01", + utc, &tp)); + + // TODO: Add tests that parsing times with fractional seconds overflow + // appropriately. This can't be done until cctz::parse() properly detects + // overflow when combining the chrono seconds and femto. +} + +// +// Roundtrip test for format()/parse(). +// + +TEST(FormatParse, RoundTrip) { + time_zone lax; + EXPECT_TRUE(load_time_zone("America/Los_Angeles", &lax)); + const auto in = convert(civil_second(1977, 6, 28, 9, 8, 7), lax); + const auto subseconds = chrono::nanoseconds(654321); + + // RFC3339, which renders subseconds. + { + time_point<chrono::nanoseconds> out; + const std::string s = format(RFC3339_full, in + subseconds, lax); + EXPECT_TRUE(parse(RFC3339_full, s, lax, &out)) << s; + EXPECT_EQ(in + subseconds, out); // RFC3339_full includes %Ez + } + + // RFC1123, which only does whole seconds. + { + time_point<chrono::nanoseconds> out; + const std::string s = format(RFC1123_full, in, lax); + EXPECT_TRUE(parse(RFC1123_full, s, lax, &out)) << s; + EXPECT_EQ(in, out); // RFC1123_full includes %z + } + +#if defined(_WIN32) || defined(_WIN64) + // Initial investigations indicate the %c does not roundtrip on Windows. + // TODO: Figure out what is going on here (perhaps a locale problem). +#else + // Even though we don't know what %c will produce, it should roundtrip, + // but only in the 0-offset timezone. + { + time_point<chrono::nanoseconds> out; + time_zone utc = utc_time_zone(); + const std::string s = format("%c", in, utc); + EXPECT_TRUE(parse("%c", s, utc, &out)) << s; + EXPECT_EQ(in, out); + } +#endif +} + +TEST(FormatParse, RoundTripDistantFuture) { + const time_zone utc = utc_time_zone(); + const time_point<cctz::seconds> in = time_point<cctz::seconds>::max(); + const std::string s = format(RFC3339_full, in, utc); + time_point<cctz::seconds> out; + EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s; + EXPECT_EQ(in, out); +} + +TEST(FormatParse, RoundTripDistantPast) { + const time_zone utc = utc_time_zone(); + const time_point<cctz::seconds> in = time_point<cctz::seconds>::min(); + const std::string s = format(RFC3339_full, in, utc); + time_point<cctz::seconds> out; + EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s; + EXPECT_EQ(in, out); +} + +} // namespace cctz diff --git a/contrib/libs/cctz/test/time_zone_lookup_test.cc b/contrib/libs/cctz/test/time_zone_lookup_test.cc new file mode 100644 index 0000000000..991d7af1c8 --- /dev/null +++ b/contrib/libs/cctz/test/time_zone_lookup_test.cc @@ -0,0 +1,1435 @@ +// 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 "cctz/time_zone.h" + +#include <chrono> +#include <cstddef> +#include <cstdlib> +#include <future> +#include <limits> +#include <string> +#include <thread> +#include <vector> + +#include "cctz/civil_time.h" +#include "gtest/gtest.h" + +namespace chrono = std::chrono; + +namespace cctz { + +namespace { + +// A list of known time-zone names. +const char* const kTimeZoneNames[] = { + "Africa/Abidjan", + "Africa/Accra", + "Africa/Addis_Ababa", + "Africa/Algiers", + "Africa/Asmara", + "Africa/Asmera", + "Africa/Bamako", + "Africa/Bangui", + "Africa/Banjul", + "Africa/Bissau", + "Africa/Blantyre", + "Africa/Brazzaville", + "Africa/Bujumbura", + "Africa/Cairo", + "Africa/Casablanca", + "Africa/Ceuta", + "Africa/Conakry", + "Africa/Dakar", + "Africa/Dar_es_Salaam", + "Africa/Djibouti", + "Africa/Douala", + "Africa/El_Aaiun", + "Africa/Freetown", + "Africa/Gaborone", + "Africa/Harare", + "Africa/Johannesburg", + "Africa/Juba", + "Africa/Kampala", + "Africa/Khartoum", + "Africa/Kigali", + "Africa/Kinshasa", + "Africa/Lagos", + "Africa/Libreville", + "Africa/Lome", + "Africa/Luanda", + "Africa/Lubumbashi", + "Africa/Lusaka", + "Africa/Malabo", + "Africa/Maputo", + "Africa/Maseru", + "Africa/Mbabane", + "Africa/Mogadishu", + "Africa/Monrovia", + "Africa/Nairobi", + "Africa/Ndjamena", + "Africa/Niamey", + "Africa/Nouakchott", + "Africa/Ouagadougou", + "Africa/Porto-Novo", + "Africa/Sao_Tome", + "Africa/Timbuktu", + "Africa/Tripoli", + "Africa/Tunis", + "Africa/Windhoek", + "America/Adak", + "America/Anchorage", + "America/Anguilla", + "America/Antigua", + "America/Araguaina", + "America/Argentina/Buenos_Aires", + "America/Argentina/Catamarca", + "America/Argentina/ComodRivadavia", + "America/Argentina/Cordoba", + "America/Argentina/Jujuy", + "America/Argentina/La_Rioja", + "America/Argentina/Mendoza", + "America/Argentina/Rio_Gallegos", + "America/Argentina/Salta", + "America/Argentina/San_Juan", + "America/Argentina/San_Luis", + "America/Argentina/Tucuman", + "America/Argentina/Ushuaia", + "America/Aruba", + "America/Asuncion", + "America/Atikokan", + "America/Atka", + "America/Bahia", + "America/Bahia_Banderas", + "America/Barbados", + "America/Belem", + "America/Belize", + "America/Blanc-Sablon", + "America/Boa_Vista", + "America/Bogota", + "America/Boise", + "America/Buenos_Aires", + "America/Cambridge_Bay", + "America/Campo_Grande", + "America/Cancun", + "America/Caracas", + "America/Catamarca", + "America/Cayenne", + "America/Cayman", + "America/Chicago", + "America/Chihuahua", + "America/Coral_Harbour", + "America/Cordoba", + "America/Costa_Rica", + "America/Creston", + "America/Cuiaba", + "America/Curacao", + "America/Danmarkshavn", + "America/Dawson", + "America/Dawson_Creek", + "America/Denver", + "America/Detroit", + "America/Dominica", + "America/Edmonton", + "America/Eirunepe", + "America/El_Salvador", + "America/Ensenada", + "America/Fort_Nelson", + "America/Fort_Wayne", + "America/Fortaleza", + "America/Glace_Bay", + "America/Godthab", + "America/Goose_Bay", + "America/Grand_Turk", + "America/Grenada", + "America/Guadeloupe", + "America/Guatemala", + "America/Guayaquil", + "America/Guyana", + "America/Halifax", + "America/Havana", + "America/Hermosillo", + "America/Indiana/Indianapolis", + "America/Indiana/Knox", + "America/Indiana/Marengo", + "America/Indiana/Petersburg", + "America/Indiana/Tell_City", + "America/Indiana/Vevay", + "America/Indiana/Vincennes", + "America/Indiana/Winamac", + "America/Indianapolis", + "America/Inuvik", + "America/Iqaluit", + "America/Jamaica", + "America/Jujuy", + "America/Juneau", + "America/Kentucky/Louisville", + "America/Kentucky/Monticello", + "America/Knox_IN", + "America/Kralendijk", + "America/La_Paz", + "America/Lima", + "America/Los_Angeles", + "America/Louisville", + "America/Lower_Princes", + "America/Maceio", + "America/Managua", + "America/Manaus", + "America/Marigot", + "America/Martinique", + "America/Matamoros", + "America/Mazatlan", + "America/Mendoza", + "America/Menominee", + "America/Merida", + "America/Metlakatla", + "America/Mexico_City", + "America/Miquelon", + "America/Moncton", + "America/Monterrey", + "America/Montevideo", + "America/Montreal", + "America/Montserrat", + "America/Nassau", + "America/New_York", + "America/Nipigon", + "America/Nome", + "America/Noronha", + "America/North_Dakota/Beulah", + "America/North_Dakota/Center", + "America/North_Dakota/New_Salem", + "America/Nuuk", + "America/Ojinaga", + "America/Panama", + "America/Pangnirtung", + "America/Paramaribo", + "America/Phoenix", + "America/Port-au-Prince", + "America/Port_of_Spain", + "America/Porto_Acre", + "America/Porto_Velho", + "America/Puerto_Rico", + "America/Punta_Arenas", + "America/Rainy_River", + "America/Rankin_Inlet", + "America/Recife", + "America/Regina", + "America/Resolute", + "America/Rio_Branco", + "America/Rosario", + "America/Santa_Isabel", + "America/Santarem", + "America/Santiago", + "America/Santo_Domingo", + "America/Sao_Paulo", + "America/Scoresbysund", + "America/Shiprock", + "America/Sitka", + "America/St_Barthelemy", + "America/St_Johns", + "America/St_Kitts", + "America/St_Lucia", + "America/St_Thomas", + "America/St_Vincent", + "America/Swift_Current", + "America/Tegucigalpa", + "America/Thule", + "America/Thunder_Bay", + "America/Tijuana", + "America/Toronto", + "America/Tortola", + "America/Vancouver", + "America/Virgin", + "America/Whitehorse", + "America/Winnipeg", + "America/Yakutat", + "America/Yellowknife", + "Antarctica/Casey", + "Antarctica/Davis", + "Antarctica/DumontDUrville", + "Antarctica/Macquarie", + "Antarctica/Mawson", + "Antarctica/McMurdo", + "Antarctica/Palmer", + "Antarctica/Rothera", + "Antarctica/South_Pole", + "Antarctica/Syowa", + "Antarctica/Troll", + "Antarctica/Vostok", + "Arctic/Longyearbyen", + "Asia/Aden", + "Asia/Almaty", + "Asia/Amman", + "Asia/Anadyr", + "Asia/Aqtau", + "Asia/Aqtobe", + "Asia/Ashgabat", + "Asia/Ashkhabad", + "Asia/Atyrau", + "Asia/Baghdad", + "Asia/Bahrain", + "Asia/Baku", + "Asia/Bangkok", + "Asia/Barnaul", + "Asia/Beirut", + "Asia/Bishkek", + "Asia/Brunei", + "Asia/Calcutta", + "Asia/Chita", + "Asia/Choibalsan", + "Asia/Chongqing", + "Asia/Chungking", + "Asia/Colombo", + "Asia/Dacca", + "Asia/Damascus", + "Asia/Dhaka", + "Asia/Dili", + "Asia/Dubai", + "Asia/Dushanbe", + "Asia/Famagusta", + "Asia/Gaza", + "Asia/Harbin", + "Asia/Hebron", + "Asia/Ho_Chi_Minh", + "Asia/Hong_Kong", + "Asia/Hovd", + "Asia/Irkutsk", + "Asia/Istanbul", + "Asia/Jakarta", + "Asia/Jayapura", + "Asia/Jerusalem", + "Asia/Kabul", + "Asia/Kamchatka", + "Asia/Karachi", + "Asia/Kashgar", + "Asia/Kathmandu", + "Asia/Katmandu", + "Asia/Khandyga", + "Asia/Kolkata", + "Asia/Krasnoyarsk", + "Asia/Kuala_Lumpur", + "Asia/Kuching", + "Asia/Kuwait", + "Asia/Macao", + "Asia/Macau", + "Asia/Magadan", + "Asia/Makassar", + "Asia/Manila", + "Asia/Muscat", + "Asia/Nicosia", + "Asia/Novokuznetsk", + "Asia/Novosibirsk", + "Asia/Omsk", + "Asia/Oral", + "Asia/Phnom_Penh", + "Asia/Pontianak", + "Asia/Pyongyang", + "Asia/Qatar", + "Asia/Qostanay", + "Asia/Qyzylorda", + "Asia/Rangoon", + "Asia/Riyadh", + "Asia/Saigon", + "Asia/Sakhalin", + "Asia/Samarkand", + "Asia/Seoul", + "Asia/Shanghai", + "Asia/Singapore", + "Asia/Srednekolymsk", + "Asia/Taipei", + "Asia/Tashkent", + "Asia/Tbilisi", + "Asia/Tehran", + "Asia/Tel_Aviv", + "Asia/Thimbu", + "Asia/Thimphu", + "Asia/Tokyo", + "Asia/Tomsk", + "Asia/Ujung_Pandang", + "Asia/Ulaanbaatar", + "Asia/Ulan_Bator", + "Asia/Urumqi", + "Asia/Ust-Nera", + "Asia/Vientiane", + "Asia/Vladivostok", + "Asia/Yakutsk", + "Asia/Yangon", + "Asia/Yekaterinburg", + "Asia/Yerevan", + "Atlantic/Azores", + "Atlantic/Bermuda", + "Atlantic/Canary", + "Atlantic/Cape_Verde", + "Atlantic/Faeroe", + "Atlantic/Faroe", + "Atlantic/Jan_Mayen", + "Atlantic/Madeira", + "Atlantic/Reykjavik", + "Atlantic/South_Georgia", + "Atlantic/St_Helena", + "Atlantic/Stanley", + "Australia/ACT", + "Australia/Adelaide", + "Australia/Brisbane", + "Australia/Broken_Hill", + "Australia/Canberra", + "Australia/Currie", + "Australia/Darwin", + "Australia/Eucla", + "Australia/Hobart", + "Australia/LHI", + "Australia/Lindeman", + "Australia/Lord_Howe", + "Australia/Melbourne", + "Australia/NSW", + "Australia/North", + "Australia/Perth", + "Australia/Queensland", + "Australia/South", + "Australia/Sydney", + "Australia/Tasmania", + "Australia/Victoria", + "Australia/West", + "Australia/Yancowinna", + "Brazil/Acre", + "Brazil/DeNoronha", + "Brazil/East", + "Brazil/West", + "CET", + "CST6CDT", + "Canada/Atlantic", + "Canada/Central", + "Canada/Eastern", + "Canada/Mountain", + "Canada/Newfoundland", + "Canada/Pacific", + "Canada/Saskatchewan", + "Canada/Yukon", + "Chile/Continental", + "Chile/EasterIsland", + "Cuba", + "EET", + "EST", + "EST5EDT", + "Egypt", + "Eire", + "Etc/GMT", + "Etc/GMT+0", + "Etc/GMT+1", + "Etc/GMT+10", + "Etc/GMT+11", + "Etc/GMT+12", + "Etc/GMT+2", + "Etc/GMT+3", + "Etc/GMT+4", + "Etc/GMT+5", + "Etc/GMT+6", + "Etc/GMT+7", + "Etc/GMT+8", + "Etc/GMT+9", + "Etc/GMT-0", + "Etc/GMT-1", + "Etc/GMT-10", + "Etc/GMT-11", + "Etc/GMT-12", + "Etc/GMT-13", + "Etc/GMT-14", + "Etc/GMT-2", + "Etc/GMT-3", + "Etc/GMT-4", + "Etc/GMT-5", + "Etc/GMT-6", + "Etc/GMT-7", + "Etc/GMT-8", + "Etc/GMT-9", + "Etc/GMT0", + "Etc/Greenwich", + "Etc/UCT", + "Etc/UTC", + "Etc/Universal", + "Etc/Zulu", + "Europe/Amsterdam", + "Europe/Andorra", + "Europe/Astrakhan", + "Europe/Athens", + "Europe/Belfast", + "Europe/Belgrade", + "Europe/Berlin", + "Europe/Bratislava", + "Europe/Brussels", + "Europe/Bucharest", + "Europe/Budapest", + "Europe/Busingen", + "Europe/Chisinau", + "Europe/Copenhagen", + "Europe/Dublin", + "Europe/Gibraltar", + "Europe/Guernsey", + "Europe/Helsinki", + "Europe/Isle_of_Man", + "Europe/Istanbul", + "Europe/Jersey", + "Europe/Kaliningrad", + "Europe/Kiev", + "Europe/Kirov", + "Europe/Lisbon", + "Europe/Ljubljana", + "Europe/London", + "Europe/Luxembourg", + "Europe/Madrid", + "Europe/Malta", + "Europe/Mariehamn", + "Europe/Minsk", + "Europe/Monaco", + "Europe/Moscow", + "Europe/Nicosia", + "Europe/Oslo", + "Europe/Paris", + "Europe/Podgorica", + "Europe/Prague", + "Europe/Riga", + "Europe/Rome", + "Europe/Samara", + "Europe/San_Marino", + "Europe/Sarajevo", + "Europe/Saratov", + "Europe/Simferopol", + "Europe/Skopje", + "Europe/Sofia", + "Europe/Stockholm", + "Europe/Tallinn", + "Europe/Tirane", + "Europe/Tiraspol", + "Europe/Ulyanovsk", + "Europe/Uzhgorod", + "Europe/Vaduz", + "Europe/Vatican", + "Europe/Vienna", + "Europe/Vilnius", + "Europe/Volgograd", + "Europe/Warsaw", + "Europe/Zagreb", + "Europe/Zaporozhye", + "Europe/Zurich", + "GB", + "GB-Eire", + "GMT", + "GMT+0", + "GMT-0", + "GMT0", + "Greenwich", + "HST", + "Hongkong", + "Iceland", + "Indian/Antananarivo", + "Indian/Chagos", + "Indian/Christmas", + "Indian/Cocos", + "Indian/Comoro", + "Indian/Kerguelen", + "Indian/Mahe", + "Indian/Maldives", + "Indian/Mauritius", + "Indian/Mayotte", + "Indian/Reunion", + "Iran", + "Israel", + "Jamaica", + "Japan", + "Kwajalein", + "Libya", + "MET", + "MST", + "MST7MDT", + "Mexico/BajaNorte", + "Mexico/BajaSur", + "Mexico/General", + "NZ", + "NZ-CHAT", + "Navajo", + "PRC", + "PST8PDT", + "Pacific/Apia", + "Pacific/Auckland", + "Pacific/Bougainville", + "Pacific/Chatham", + "Pacific/Chuuk", + "Pacific/Easter", + "Pacific/Efate", + "Pacific/Enderbury", + "Pacific/Fakaofo", + "Pacific/Fiji", + "Pacific/Funafuti", + "Pacific/Galapagos", + "Pacific/Gambier", + "Pacific/Guadalcanal", + "Pacific/Guam", + "Pacific/Honolulu", + "Pacific/Johnston", + "Pacific/Kiritimati", + "Pacific/Kosrae", + "Pacific/Kwajalein", + "Pacific/Majuro", + "Pacific/Marquesas", + "Pacific/Midway", + "Pacific/Nauru", + "Pacific/Niue", + "Pacific/Norfolk", + "Pacific/Noumea", + "Pacific/Pago_Pago", + "Pacific/Palau", + "Pacific/Pitcairn", + "Pacific/Pohnpei", + "Pacific/Ponape", + "Pacific/Port_Moresby", + "Pacific/Rarotonga", + "Pacific/Saipan", + "Pacific/Samoa", + "Pacific/Tahiti", + "Pacific/Tarawa", + "Pacific/Tongatapu", + "Pacific/Truk", + "Pacific/Wake", + "Pacific/Wallis", + "Pacific/Yap", + "Poland", + "Portugal", + "ROC", + "ROK", + "Singapore", + "Turkey", + "UCT", + "US/Alaska", + "US/Aleutian", + "US/Arizona", + "US/Central", + "US/East-Indiana", + "US/Eastern", + "US/Hawaii", + "US/Indiana-Starke", + "US/Michigan", + "US/Mountain", + "US/Pacific", + "US/Samoa", + "UTC", + "Universal", + "W-SU", + "WET", + "Zulu", + nullptr +}; + +// Helper to return a loaded time zone by value (UTC on error). +time_zone LoadZone(const std::string& name) { + time_zone tz; + load_time_zone(name, &tz); + return tz; +} + +// This helper is a macro so that failed expectations show up with the +// correct line numbers. +#define ExpectTime(tp, tz, y, m, d, hh, mm, ss, off, isdst, zone) \ + do { \ + time_zone::absolute_lookup al = tz.lookup(tp); \ + EXPECT_EQ(y, al.cs.year()); \ + EXPECT_EQ(m, al.cs.month()); \ + EXPECT_EQ(d, al.cs.day()); \ + EXPECT_EQ(hh, al.cs.hour()); \ + EXPECT_EQ(mm, al.cs.minute()); \ + EXPECT_EQ(ss, al.cs.second()); \ + EXPECT_EQ(off, al.offset); \ + EXPECT_TRUE(isdst == al.is_dst); \ + /* EXPECT_STREQ(zone, al.abbr); */ \ + } while (0) + +// These tests sometimes run on platforms that have zoneinfo data so old +// that the transition we are attempting to check does not exist, most +// notably Android emulators. Fortunately, AndroidZoneInfoSource supports +// time_zone::version() so, in cases where we've learned that it matters, +// we can make the check conditionally. +int VersionCmp(time_zone tz, const std::string& target) { + std::string version = tz.version(); + if (version.empty() && !target.empty()) return 1; // unknown > known + return version.compare(target); +} + +} // namespace + +TEST(TimeZones, LoadZonesConcurrently) { + std::promise<void> ready_promise; + std::shared_future<void> ready_future(ready_promise.get_future()); + auto load_zones = [ready_future](std::promise<void>* started, + std::set<std::string>* failures) { + started->set_value(); + ready_future.wait(); + for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) { + std::string zone = *np; + time_zone tz; + if (load_time_zone(zone, &tz)) { + EXPECT_EQ(zone, tz.name()); + } else { + failures->insert(zone); + } + } + }; + + const std::size_t n_threads = 128; + std::vector<std::thread> threads; + std::vector<std::set<std::string>> thread_failures(n_threads); + for (std::size_t i = 0; i != n_threads; ++i) { + std::promise<void> started; + threads.emplace_back(load_zones, &started, &thread_failures[i]); + started.get_future().wait(); + } + ready_promise.set_value(); + for (auto& thread : threads) { + thread.join(); + } + + // Allow a small number of failures to account for skew between + // the contents of kTimeZoneNames and the zoneinfo data source. +#if defined(__ANDROID__) + // Cater to the possibility of using an even older zoneinfo data + // source when running on Android, where it is difficult to override + // the bionic tzdata provided by the test environment. + const std::size_t max_failures = 20; +#else + const std::size_t max_failures = 3; +#endif + std::set<std::string> failures; + for (const auto& thread_failure : thread_failures) { + failures.insert(thread_failure.begin(), thread_failure.end()); + } + EXPECT_LE(failures.size(), max_failures) << testing::PrintToString(failures); +} + +TEST(TimeZone, NamedTimeZones) { + const time_zone utc = utc_time_zone(); + EXPECT_EQ("UTC", utc.name()); + const time_zone nyc = LoadZone("America/New_York"); + EXPECT_EQ("America/New_York", nyc.name()); + const time_zone syd = LoadZone("Australia/Sydney"); + EXPECT_EQ("Australia/Sydney", syd.name()); + const time_zone fixed0 = fixed_time_zone(cctz::seconds::zero()); + EXPECT_EQ("UTC", fixed0.name()); + const time_zone fixed_pos = fixed_time_zone( + chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45)); + EXPECT_EQ("Fixed/UTC+03:25:45", fixed_pos.name()); + const time_zone fixed_neg = fixed_time_zone( + -(chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56))); + EXPECT_EQ("Fixed/UTC-12:34:56", fixed_neg.name()); +} + +TEST(TimeZone, Failures) { + time_zone tz; + EXPECT_FALSE(load_time_zone(":America/Los_Angeles", &tz)); + + tz = LoadZone("America/Los_Angeles"); + EXPECT_FALSE(load_time_zone("Invalid/TimeZone", &tz)); + EXPECT_EQ(chrono::system_clock::from_time_t(0), + convert(civil_second(1970, 1, 1, 0, 0, 0), tz)); // UTC + + // Ensures that the load still fails on a subsequent attempt. + tz = LoadZone("America/Los_Angeles"); + EXPECT_FALSE(load_time_zone("Invalid/TimeZone", &tz)); + EXPECT_EQ(chrono::system_clock::from_time_t(0), + convert(civil_second(1970, 1, 1, 0, 0, 0), tz)); // UTC + + // Loading an empty string timezone should fail. + tz = LoadZone("America/Los_Angeles"); + EXPECT_FALSE(load_time_zone("", &tz)); + EXPECT_EQ(chrono::system_clock::from_time_t(0), + convert(civil_second(1970, 1, 1, 0, 0, 0), tz)); // UTC +} + +TEST(TimeZone, Equality) { + const time_zone a; + const time_zone b; + EXPECT_EQ(a, b); + EXPECT_EQ(a.name(), b.name()); + + const time_zone implicit_utc; + const time_zone explicit_utc = utc_time_zone(); + EXPECT_EQ(implicit_utc, explicit_utc); + EXPECT_EQ(implicit_utc.name(), explicit_utc.name()); + + const time_zone fixed_zero = fixed_time_zone(cctz::seconds::zero()); + EXPECT_EQ(fixed_zero, LoadZone(fixed_zero.name())); + EXPECT_EQ(fixed_zero, explicit_utc); + + const time_zone fixed_utc = LoadZone("Fixed/UTC+00:00:00"); + EXPECT_EQ(fixed_utc, LoadZone(fixed_utc.name())); + EXPECT_EQ(fixed_utc, explicit_utc); + + const time_zone fixed_pos = fixed_time_zone( + chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45)); + EXPECT_EQ(fixed_pos, LoadZone(fixed_pos.name())); + EXPECT_NE(fixed_pos, explicit_utc); + const time_zone fixed_neg = fixed_time_zone( + -(chrono::hours(12) + chrono::minutes(34) + chrono::seconds(56))); + EXPECT_EQ(fixed_neg, LoadZone(fixed_neg.name())); + EXPECT_NE(fixed_neg, explicit_utc); + + const time_zone fixed_lim = fixed_time_zone(chrono::hours(24)); + EXPECT_EQ(fixed_lim, LoadZone(fixed_lim.name())); + EXPECT_NE(fixed_lim, explicit_utc); + const time_zone fixed_ovfl = + fixed_time_zone(chrono::hours(24) + chrono::seconds(1)); + EXPECT_EQ(fixed_ovfl, LoadZone(fixed_ovfl.name())); + EXPECT_EQ(fixed_ovfl, explicit_utc); + + EXPECT_EQ(fixed_time_zone(chrono::seconds(1)), + fixed_time_zone(chrono::seconds(1))); + + const time_zone local = local_time_zone(); + EXPECT_EQ(local, LoadZone(local.name())); + + time_zone la = LoadZone("America/Los_Angeles"); + time_zone nyc = LoadZone("America/New_York"); + EXPECT_NE(la, nyc); +} + +TEST(StdChronoTimePoint, TimeTAlignment) { + // Ensures that the Unix epoch and the system clock epoch are an integral + // number of seconds apart. This simplifies conversions to/from time_t. + auto diff = chrono::system_clock::time_point() - + chrono::system_clock::from_time_t(0); + EXPECT_EQ(chrono::system_clock::time_point::duration::zero(), + diff % chrono::seconds(1)); +} + +TEST(BreakTime, TimePointResolution) { + const time_zone utc = utc_time_zone(); + const auto t0 = chrono::system_clock::from_time_t(0); + + ExpectTime(chrono::time_point_cast<chrono::nanoseconds>(t0), utc, + 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast<chrono::microseconds>(t0), utc, + 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast<chrono::milliseconds>(t0), utc, + 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast<chrono::seconds>(t0), utc, + 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast<cctz::seconds>(t0), utc, + 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast<chrono::minutes>(t0), utc, + 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); + ExpectTime(chrono::time_point_cast<chrono::hours>(t0), utc, + 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); +} + +TEST(BreakTime, LocalTimeInUTC) { + const time_zone tz = utc_time_zone(); + const auto tp = chrono::system_clock::from_time_t(0); + ExpectTime(tp, tz, 1970, 1, 1, 0, 0, 0, 0, false, "UTC"); + EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz))); +} + +TEST(BreakTime, LocalTimeInUTCUnaligned) { + const time_zone tz = utc_time_zone(); + const auto tp = + chrono::system_clock::from_time_t(0) - chrono::milliseconds(500); + ExpectTime(tp, tz, 1969, 12, 31, 23, 59, 59, 0, false, "UTC"); + EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz))); +} + +TEST(BreakTime, LocalTimePosix) { + // See IEEE Std 1003.1-1988 B.2.3 General Terms, Epoch. + const time_zone tz = utc_time_zone(); + const auto tp = chrono::system_clock::from_time_t(536457599); + ExpectTime(tp, tz, 1986, 12, 31, 23, 59, 59, 0, false, "UTC"); + EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz))); +} + +TEST(TimeZoneImpl, LocalTimeInFixed) { + const cctz::seconds offset = + -(chrono::hours(8) + chrono::minutes(33) + chrono::seconds(47)); + const time_zone tz = fixed_time_zone(offset); + const auto tp = chrono::system_clock::from_time_t(0); + ExpectTime(tp, tz, 1969, 12, 31, 15, 26, 13, offset.count(), false, + "-083347"); + EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz))); +} + +TEST(BreakTime, LocalTimeInNewYork) { + const time_zone tz = LoadZone("America/New_York"); + const auto tp = chrono::system_clock::from_time_t(45); + ExpectTime(tp, tz, 1969, 12, 31, 19, 0, 45, -5 * 60 * 60, false, "EST"); + EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz))); +} + +TEST(BreakTime, LocalTimeInMTV) { + const time_zone tz = LoadZone("America/Los_Angeles"); + const auto tp = chrono::system_clock::from_time_t(1380855729); + ExpectTime(tp, tz, 2013, 10, 3, 20, 2, 9, -7 * 60 * 60, true, "PDT"); + EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz))); +} + +TEST(BreakTime, LocalTimeInSydney) { + const time_zone tz = LoadZone("Australia/Sydney"); + const auto tp = chrono::system_clock::from_time_t(90); + ExpectTime(tp, tz, 1970, 1, 1, 10, 1, 30, 10 * 60 * 60, false, "AEST"); + EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz))); +} + +TEST(MakeTime, TimePointResolution) { + const time_zone utc = utc_time_zone(); + const time_point<chrono::nanoseconds> tp_ns = + convert(civil_second(2015, 1, 2, 3, 4, 5), utc); + EXPECT_EQ("04:05", format("%M:%E*S", tp_ns, utc)); + const time_point<chrono::microseconds> tp_us = + convert(civil_second(2015, 1, 2, 3, 4, 5), utc); + EXPECT_EQ("04:05", format("%M:%E*S", tp_us, utc)); + const time_point<chrono::milliseconds> tp_ms = + convert(civil_second(2015, 1, 2, 3, 4, 5), utc); + EXPECT_EQ("04:05", format("%M:%E*S", tp_ms, utc)); + const time_point<chrono::seconds> tp_s = + convert(civil_second(2015, 1, 2, 3, 4, 5), utc); + EXPECT_EQ("04:05", format("%M:%E*S", tp_s, utc)); + const time_point<cctz::seconds> tp_s64 = + convert(civil_second(2015, 1, 2, 3, 4, 5), utc); + EXPECT_EQ("04:05", format("%M:%E*S", tp_s64, utc)); + + // These next two require chrono::time_point_cast because the conversion + // from a resolution of seconds (the return value of convert()) to a + // coarser resolution requires an explicit cast. + const time_point<chrono::minutes> tp_m = + chrono::time_point_cast<chrono::minutes>( + convert(civil_second(2015, 1, 2, 3, 4, 5), utc)); + EXPECT_EQ("04:00", format("%M:%E*S", tp_m, utc)); + const time_point<chrono::hours> tp_h = + chrono::time_point_cast<chrono::hours>( + convert(civil_second(2015, 1, 2, 3, 4, 5), utc)); + EXPECT_EQ("00:00", format("%M:%E*S", tp_h, utc)); +} + +TEST(MakeTime, Normalization) { + const time_zone tz = LoadZone("America/New_York"); + const auto tp = convert(civil_second(2009, 2, 13, 18, 31, 30), tz); + EXPECT_EQ(chrono::system_clock::from_time_t(1234567890), tp); + + // Now requests for the same time_point but with out-of-range fields. + EXPECT_EQ(tp, convert(civil_second(2008, 14, 13, 18, 31, 30), tz)); // month + EXPECT_EQ(tp, convert(civil_second(2009, 1, 44, 18, 31, 30), tz)); // day + EXPECT_EQ(tp, convert(civil_second(2009, 2, 12, 42, 31, 30), tz)); // hour + EXPECT_EQ(tp, convert(civil_second(2009, 2, 13, 17, 91, 30), tz)); // minute + EXPECT_EQ(tp, convert(civil_second(2009, 2, 13, 18, 30, 90), tz)); // second +} + +// NOTE: Run this with -ftrapv to detect overflow problems. +TEST(MakeTime, SysSecondsLimits) { + const char RFC3339[] = "%Y-%m-%d%ET%H:%M:%S%Ez"; + const time_zone utc = utc_time_zone(); + const time_zone east = fixed_time_zone(chrono::hours(14)); + const time_zone west = fixed_time_zone(-chrono::hours(14)); + time_point<cctz::seconds> tp; + + // Approach the maximal time_point<cctz::seconds> value from below. + tp = convert(civil_second(292277026596, 12, 4, 15, 30, 6), utc); + EXPECT_EQ("292277026596-12-04T15:30:06+00:00", format(RFC3339, tp, utc)); + tp = convert(civil_second(292277026596, 12, 4, 15, 30, 7), utc); + EXPECT_EQ("292277026596-12-04T15:30:07+00:00", format(RFC3339, tp, utc)); + EXPECT_EQ(time_point<cctz::seconds>::max(), tp); + tp = convert(civil_second(292277026596, 12, 4, 15, 30, 8), utc); + EXPECT_EQ(time_point<cctz::seconds>::max(), tp); + tp = convert(civil_second::max(), utc); + EXPECT_EQ(time_point<cctz::seconds>::max(), tp); + + // Checks that we can also get the maximal value for a far-east zone. + tp = convert(civil_second(292277026596, 12, 5, 5, 30, 7), east); + EXPECT_EQ("292277026596-12-05T05:30:07+14:00", format(RFC3339, tp, east)); + EXPECT_EQ(time_point<cctz::seconds>::max(), tp); + tp = convert(civil_second(292277026596, 12, 5, 5, 30, 8), east); + EXPECT_EQ(time_point<cctz::seconds>::max(), tp); + tp = convert(civil_second::max(), east); + EXPECT_EQ(time_point<cctz::seconds>::max(), tp); + + // Checks that we can also get the maximal value for a far-west zone. + tp = convert(civil_second(292277026596, 12, 4, 1, 30, 7), west); + EXPECT_EQ("292277026596-12-04T01:30:07-14:00", format(RFC3339, tp, west)); + EXPECT_EQ(time_point<cctz::seconds>::max(), tp); + tp = convert(civil_second(292277026596, 12, 4, 7, 30, 8), west); + EXPECT_EQ(time_point<cctz::seconds>::max(), tp); + tp = convert(civil_second::max(), west); + EXPECT_EQ(time_point<cctz::seconds>::max(), tp); + + // Approach the minimal time_point<cctz::seconds> value from above. + tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 53), utc); + EXPECT_EQ("-292277022657-01-27T08:29:53+00:00", format(RFC3339, tp, utc)); + tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 52), utc); + EXPECT_EQ("-292277022657-01-27T08:29:52+00:00", format(RFC3339, tp, utc)); + EXPECT_EQ(time_point<cctz::seconds>::min(), tp); + tp = convert(civil_second(-292277022657, 1, 27, 8, 29, 51), utc); + EXPECT_EQ(time_point<cctz::seconds>::min(), tp); + tp = convert(civil_second::min(), utc); + EXPECT_EQ(time_point<cctz::seconds>::min(), tp); + + // Checks that we can also get the minimal value for a far-east zone. + tp = convert(civil_second(-292277022657, 1, 27, 22, 29, 52), east); + EXPECT_EQ("-292277022657-01-27T22:29:52+14:00", format(RFC3339, tp, east)); + EXPECT_EQ(time_point<cctz::seconds>::min(), tp); + tp = convert(civil_second(-292277022657, 1, 27, 22, 29, 51), east); + EXPECT_EQ(time_point<cctz::seconds>::min(), tp); + tp = convert(civil_second::min(), east); + EXPECT_EQ(time_point<cctz::seconds>::min(), tp); + + // Checks that we can also get the minimal value for a far-west zone. + tp = convert(civil_second(-292277022657, 1, 26, 18, 29, 52), west); + EXPECT_EQ("-292277022657-01-26T18:29:52-14:00", format(RFC3339, tp, west)); + EXPECT_EQ(time_point<cctz::seconds>::min(), tp); + tp = convert(civil_second(-292277022657, 1, 26, 18, 29, 51), west); + EXPECT_EQ(time_point<cctz::seconds>::min(), tp); + tp = convert(civil_second::min(), west); + EXPECT_EQ(time_point<cctz::seconds>::min(), tp); + + // Some similar checks for the "libc" time-zone implementation. + if (sizeof(std::time_t) >= 8) { + // Checks that "tm_year + 1900", as used by the "libc" implementation, + // can produce year values beyond the range on an int without overflow. +#if defined(_WIN32) || defined(_WIN64) + // localtime_s() and gmtime_s() don't believe in years outside [1970:3000]. +#else + const time_zone cut = LoadZone("libc:UTC"); + const year_t max_tm_year = year_t{std::numeric_limits<int>::max()} + 1900; + tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), cut); +#if defined(__FreeBSD__) || defined(__OpenBSD__) + // The BSD gmtime_r() fails on extreme positive tm_year values. +#else + EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, cut)); +#endif + const year_t min_tm_year = year_t{std::numeric_limits<int>::min()} + 1900; + tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), cut); + EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, cut)); +#endif + } +} + +TEST(MakeTime, LocalTimeLibC) { + // Checks that cctz and libc agree on transition points in [1970:2037]. + // + // We limit this test case to environments where: + // 1) we know how to change the time zone used by localtime()/mktime(), + // 2) cctz and localtime()/mktime() will use similar-enough tzdata, and + // 3) we have some idea about how mktime() behaves during transitions. +#if defined(__linux__) && !defined(__ANDROID__) && defined(CCTZ_TEST_LIBC_LOCALTIME) + const char* const ep = getenv("TZ"); + std::string tz_name = (ep != nullptr) ? ep : ""; + for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) { + ASSERT_EQ(0, setenv("TZ", *np, 1)); // change what "localtime" means + const auto zi = local_time_zone(); + const auto lc = LoadZone("libc:localtime"); + time_zone::civil_transition transition; + for (auto tp = zi.lookup(civil_second()).trans; + zi.next_transition(tp, &transition); + tp = zi.lookup(transition.to).trans) { + const auto fcl = zi.lookup(transition.from); + const auto tcl = zi.lookup(transition.to); + civil_second cs; // compare cs in zi and lc + if (fcl.kind == time_zone::civil_lookup::UNIQUE) { + if (tcl.kind == time_zone::civil_lookup::UNIQUE) { + // Both unique; must be an is_dst or abbr change. + ASSERT_EQ(transition.from, transition.to); + const auto trans = fcl.trans; + const auto tal = zi.lookup(trans); + const auto tprev = trans - cctz::seconds(1); + const auto pal = zi.lookup(tprev); + if (pal.is_dst == tal.is_dst) { + ASSERT_STRNE(pal.abbr, tal.abbr); + } + continue; + } + ASSERT_EQ(time_zone::civil_lookup::REPEATED, tcl.kind); + cs = transition.to; + } else { + ASSERT_EQ(time_zone::civil_lookup::UNIQUE, tcl.kind); + ASSERT_EQ(time_zone::civil_lookup::SKIPPED, fcl.kind); + cs = transition.from; + } + if (cs.year() > 2037) break; // limit test time (and to 32-bit time_t) + const auto cl_zi = zi.lookup(cs); + if (zi.lookup(cl_zi.pre).is_dst == zi.lookup(cl_zi.post).is_dst) { + // The "libc" implementation cannot correctly classify transitions + // that don't change the "tm_isdst" flag. In Europe/Volgograd, for + // example, there is a SKIPPED transition from +03 to +04 with dst=F + // on both sides ... + // 1540681199 = 2018-10-28 01:59:59 +03:00:00 [dst=F off=10800] + // 1540681200 = 2018-10-28 03:00:00 +04:00:00 [dst=F off=14400] + // but std::mktime(2018-10-28 02:00:00, tm_isdst=0) fails, unlike, + // say, the similar Europe/Chisinau transition from +02 to +03 ... + // 1521935999 = 2018-03-25 01:59:59 +02:00:00 [dst=F off=7200] + // 1521936000 = 2018-03-25 03:00:00 +03:00:00 [dst=T off=10800] + // where std::mktime(2018-03-25 02:00:00, tm_isdst=0) succeeds and + // returns 1521936000. + continue; + } + if (cs == civil_second(2037, 10, 4, 2, 0, 0)) { + const std::string tzname = *np; + if (tzname == "Africa/Casablanca" || tzname == "Africa/El_Aaiun") { + // The "libc" implementation gets this transition wrong (at least + // until 2018g when it was removed), returning an offset of 3600 + // instead of 0. TODO: Revert this when 2018g is ubiquitous. + continue; + } + } + const auto cl_lc = lc.lookup(cs); + SCOPED_TRACE(testing::Message() << "For " << cs << " in " << *np); + EXPECT_EQ(cl_zi.kind, cl_lc.kind); + EXPECT_EQ(cl_zi.pre, cl_lc.pre); + EXPECT_EQ(cl_zi.trans, cl_lc.trans); + EXPECT_EQ(cl_zi.post, cl_lc.post); + } + } + if (ep == nullptr) { + ASSERT_EQ(0, unsetenv("TZ")); + } else { + ASSERT_EQ(0, setenv("TZ", tz_name.c_str(), 1)); + } +#endif +} + +TEST(NextTransition, UTC) { + const auto tz = utc_time_zone(); + time_zone::civil_transition trans; + + auto tp = time_point<cctz::seconds>::min(); + EXPECT_FALSE(tz.next_transition(tp, &trans)); + + tp = time_point<cctz::seconds>::max(); + EXPECT_FALSE(tz.next_transition(tp, &trans)); +} + +TEST(PrevTransition, UTC) { + const auto tz = utc_time_zone(); + time_zone::civil_transition trans; + + auto tp = time_point<cctz::seconds>::max(); + EXPECT_FALSE(tz.prev_transition(tp, &trans)); + + tp = time_point<cctz::seconds>::min(); + EXPECT_FALSE(tz.prev_transition(tp, &trans)); +} + +TEST(NextTransition, AmericaNewYork) { + const auto tz = LoadZone("America/New_York"); + time_zone::civil_transition trans; + + auto tp = convert(civil_second(2018, 6, 30, 0, 0, 0), tz); + EXPECT_TRUE(tz.next_transition(tp, &trans)); + EXPECT_EQ(civil_second(2018, 11, 4, 2, 0, 0), trans.from); + EXPECT_EQ(civil_second(2018, 11, 4, 1, 0, 0), trans.to); + + tp = time_point<cctz::seconds>::max(); + EXPECT_FALSE(tz.next_transition(tp, &trans)); + + tp = time_point<cctz::seconds>::min(); + EXPECT_TRUE(tz.next_transition(tp, &trans)); + if (trans.from == civil_second(1918, 3, 31, 2, 0, 0)) { + // It looks like the tzdata is only 32 bit (probably macOS), + // which bottoms out at 1901-12-13T20:45:52+00:00. + EXPECT_EQ(civil_second(1918, 3, 31, 3, 0, 0), trans.to); + } else { + EXPECT_EQ(civil_second(1883, 11, 18, 12, 3, 58), trans.from); + EXPECT_EQ(civil_second(1883, 11, 18, 12, 0, 0), trans.to); + } +} + +TEST(PrevTransition, AmericaNewYork) { + const auto tz = LoadZone("America/New_York"); + time_zone::civil_transition trans; + + auto tp = convert(civil_second(2018, 6, 30, 0, 0, 0), tz); + EXPECT_TRUE(tz.prev_transition(tp, &trans)); + EXPECT_EQ(civil_second(2018, 3, 11, 2, 0, 0), trans.from); + EXPECT_EQ(civil_second(2018, 3, 11, 3, 0, 0), trans.to); + + tp = time_point<cctz::seconds>::min(); + EXPECT_FALSE(tz.prev_transition(tp, &trans)); + + tp = time_point<cctz::seconds>::max(); + EXPECT_TRUE(tz.prev_transition(tp, &trans)); + // We have a transition but we don't know which one. +} + +TEST(TimeZoneEdgeCase, AmericaNewYork) { + const time_zone tz = LoadZone("America/New_York"); + + // Spring 1:59:59 -> 3:00:00 + auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz); + ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -5 * 3600, false, "EST"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 3, 10, 3, 0, 0, -4 * 3600, true, "EDT"); + + // Fall 1:59:59 -> 1:00:00 + tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz); + ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -4 * 3600, true, "EDT"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 11, 3, 1, 0, 0, -5 * 3600, false, "EST"); +} + +TEST(TimeZoneEdgeCase, AmericaLosAngeles) { + const time_zone tz = LoadZone("America/Los_Angeles"); + + // Spring 1:59:59 -> 3:00:00 + auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz); + ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -8 * 3600, false, "PST"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 3, 10, 3, 0, 0, -7 * 3600, true, "PDT"); + + // Fall 1:59:59 -> 1:00:00 + tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz); + ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -7 * 3600, true, "PDT"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 11, 3, 1, 0, 0, -8 * 3600, false, "PST"); +} + +TEST(TimeZoneEdgeCase, ArizonaNoTransition) { + const time_zone tz = LoadZone("America/Phoenix"); + + // No transition in Spring. + auto tp = convert(civil_second(2013, 3, 10, 1, 59, 59), tz); + ExpectTime(tp, tz, 2013, 3, 10, 1, 59, 59, -7 * 3600, false, "MST"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 3, 10, 2, 0, 0, -7 * 3600, false, "MST"); + + // No transition in Fall. + tp = convert(civil_second(2013, 11, 3, 1, 59, 59), tz); + ExpectTime(tp, tz, 2013, 11, 3, 1, 59, 59, -7 * 3600, false, "MST"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 11, 3, 2, 0, 0, -7 * 3600, false, "MST"); +} + +TEST(TimeZoneEdgeCase, AsiaKathmandu) { + const time_zone tz = LoadZone("Asia/Kathmandu"); + + // A non-DST offset change from +0530 to +0545 + // + // 504901799 == Tue, 31 Dec 1985 23:59:59 +0530 (+0530) + // 504901800 == Wed, 1 Jan 1986 00:15:00 +0545 (+0545) + auto tp = convert(civil_second(1985, 12, 31, 23, 59, 59), tz); + ExpectTime(tp, tz, 1985, 12, 31, 23, 59, 59, 5.5 * 3600, false, "+0530"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 1986, 1, 1, 0, 15, 0, 5.75 * 3600, false, "+0545"); +} + +TEST(TimeZoneEdgeCase, PacificChatham) { + const time_zone tz = LoadZone("Pacific/Chatham"); + + // One-hour DST offset changes, but at atypical values + // + // 1365256799 == Sun, 7 Apr 2013 03:44:59 +1345 (+1345) + // 1365256800 == Sun, 7 Apr 2013 02:45:00 +1245 (+1245) + auto tp = convert(civil_second(2013, 4, 7, 3, 44, 59), tz); + ExpectTime(tp, tz, 2013, 4, 7, 3, 44, 59, 13.75 * 3600, true, "+1345"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 4, 7, 2, 45, 0, 12.75 * 3600, false, "+1245"); + + // 1380376799 == Sun, 29 Sep 2013 02:44:59 +1245 (+1245) + // 1380376800 == Sun, 29 Sep 2013 03:45:00 +1345 (+1345) + tp = convert(civil_second(2013, 9, 29, 2, 44, 59), tz); + ExpectTime(tp, tz, 2013, 9, 29, 2, 44, 59, 12.75 * 3600, false, "+1245"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 9, 29, 3, 45, 0, 13.75 * 3600, true, "+1345"); +} + +TEST(TimeZoneEdgeCase, AustraliaLordHowe) { + const time_zone tz = LoadZone("Australia/Lord_Howe"); + + // Half-hour DST offset changes + // + // 1365260399 == Sun, 7 Apr 2013 01:59:59 +1100 (+11) + // 1365260400 == Sun, 7 Apr 2013 01:30:00 +1030 (+1030) + auto tp = convert(civil_second(2013, 4, 7, 1, 59, 59), tz); + ExpectTime(tp, tz, 2013, 4, 7, 1, 59, 59, 11 * 3600, true, "+11"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 4, 7, 1, 30, 0, 10.5 * 3600, false, "+1030"); + + // 1380986999 == Sun, 6 Oct 2013 01:59:59 +1030 (+1030) + // 1380987000 == Sun, 6 Oct 2013 02:30:00 +1100 (+11) + tp = convert(civil_second(2013, 10, 6, 1, 59, 59), tz); + ExpectTime(tp, tz, 2013, 10, 6, 1, 59, 59, 10.5 * 3600, false, "+1030"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2013, 10, 6, 2, 30, 0, 11 * 3600, true, "+11"); +} + +TEST(TimeZoneEdgeCase, PacificApia) { + const time_zone tz = LoadZone("Pacific/Apia"); + + // At the end of December 2011, Samoa jumped forward by one day, + // skipping 30 December from the local calendar, when the nation + // moved to the west of the International Date Line. + // + // A one-day, non-DST offset change + // + // 1325239199 == Thu, 29 Dec 2011 23:59:59 -1000 (-10) + // 1325239200 == Sat, 31 Dec 2011 00:00:00 +1400 (+14) + auto tp = convert(civil_second(2011, 12, 29, 23, 59, 59), tz); + ExpectTime(tp, tz, 2011, 12, 29, 23, 59, 59, -10 * 3600, true, "-10"); + EXPECT_EQ(363, get_yearday(convert(tp, tz))); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2011, 12, 31, 0, 0, 0, 14 * 3600, true, "+14"); + EXPECT_EQ(365, get_yearday(convert(tp, tz))); +} + +TEST(TimeZoneEdgeCase, AfricaCairo) { + const time_zone tz = LoadZone("Africa/Cairo"); + + if (VersionCmp(tz, "2014c") >= 0) { + // An interesting case of midnight not existing. + // + // 1400191199 == Thu, 15 May 2014 23:59:59 +0200 (EET) + // 1400191200 == Fri, 16 May 2014 01:00:00 +0300 (EEST) + auto tp = convert(civil_second(2014, 5, 15, 23, 59, 59), tz); + ExpectTime(tp, tz, 2014, 5, 15, 23, 59, 59, 2 * 3600, false, "EET"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2014, 5, 16, 1, 0, 0, 3 * 3600, true, "EEST"); + } +} + +TEST(TimeZoneEdgeCase, AfricaMonrovia) { + const time_zone tz = LoadZone("Africa/Monrovia"); + + if (VersionCmp(tz, "2017b") >= 0) { + // Strange offset change -00:44:30 -> +00:00:00 (non-DST) + // + // 63593069 == Thu, 6 Jan 1972 23:59:59 -0044 (MMT) + // 63593070 == Fri, 7 Jan 1972 00:44:30 +0000 (GMT) + auto tp = convert(civil_second(1972, 1, 6, 23, 59, 59), tz); + ExpectTime(tp, tz, 1972, 1, 6, 23, 59, 59, -44.5 * 60, false, "MMT"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 1972, 1, 7, 0, 44, 30, 0 * 60, false, "GMT"); + } +} + +TEST(TimeZoneEdgeCase, AmericaJamaica) { + // Jamaica discontinued DST transitions in 1983, and is now at a + // constant -0500. This makes it an interesting edge-case target. + // Note that the 32-bit times used in a (tzh_version == 0) zoneinfo + // file cannot represent the abbreviation-only transition of 1890, + // so we ignore the abbreviation by expecting what we received. + const time_zone tz = LoadZone("America/Jamaica"); + + // Before the first transition. + if (!tz.version().empty() && VersionCmp(tz, "2018d") >= 0) { + // We avoid the expectations on the -18430 offset below unless we are + // certain we have commit 907241e (Fix off-by-1 error for Jamaica and + // T&C before 1913) from 2018d. TODO: Remove the "version() not empty" + // part when 2018d is generally available from /usr/share/zoneinfo. + auto tp = convert(civil_second(1889, 12, 31, 0, 0, 0), tz); + ExpectTime(tp, tz, 1889, 12, 31, 0, 0, 0, -18430, false, + tz.lookup(tp).abbr); + + // Over the first (abbreviation-change only) transition. + // -2524503170 == Tue, 31 Dec 1889 23:59:59 -0507 (LMT) + // -2524503169 == Wed, 1 Jan 1890 00:00:00 -0507 (KMT) + tp = convert(civil_second(1889, 12, 31, 23, 59, 59), tz); + ExpectTime(tp, tz, 1889, 12, 31, 23, 59, 59, -18430, false, + tz.lookup(tp).abbr); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 1890, 1, 1, 0, 0, 0, -18430, false, "KMT"); + } + + // Over the last (DST) transition. + // 436341599 == Sun, 30 Oct 1983 01:59:59 -0400 (EDT) + // 436341600 == Sun, 30 Oct 1983 01:00:00 -0500 (EST) + auto tp = convert(civil_second(1983, 10, 30, 1, 59, 59), tz); + ExpectTime(tp, tz, 1983, 10, 30, 1, 59, 59, -4 * 3600, true, "EDT"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 1983, 10, 30, 1, 0, 0, -5 * 3600, false, "EST"); + + // After the last transition. + tp = convert(civil_second(1983, 12, 31, 23, 59, 59), tz); + ExpectTime(tp, tz, 1983, 12, 31, 23, 59, 59, -5 * 3600, false, "EST"); +} + +TEST(TimeZoneEdgeCase, WET) { + // Cover some non-existent times within forward transitions. + const time_zone tz = LoadZone("WET"); + + // Before the first transition. + auto tp = convert(civil_second(1977, 1, 1, 0, 0, 0), tz); + ExpectTime(tp, tz, 1977, 1, 1, 0, 0, 0, 0, false, "WET"); + + // Over the first transition. + // 228877199 == Sun, 3 Apr 1977 00:59:59 +0000 (WET) + // 228877200 == Sun, 3 Apr 1977 02:00:00 +0100 (WEST) + tp = convert(civil_second(1977, 4, 3, 0, 59, 59), tz); + ExpectTime(tp, tz, 1977, 4, 3, 0, 59, 59, 0, false, "WET"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 1977, 4, 3, 2, 0, 0, 1 * 3600, true, "WEST"); + + // A non-existent time within the first transition. + time_zone::civil_lookup cl1 = tz.lookup(civil_second(1977, 4, 3, 1, 15, 0)); + EXPECT_EQ(time_zone::civil_lookup::SKIPPED, cl1.kind); + ExpectTime(cl1.pre, tz, 1977, 4, 3, 2, 15, 0, 1 * 3600, true, "WEST"); + ExpectTime(cl1.trans, tz, 1977, 4, 3, 2, 0, 0, 1 * 3600, true, "WEST"); + ExpectTime(cl1.post, tz, 1977, 4, 3, 0, 15, 0, 0 * 3600, false, "WET"); + + // A non-existent time within the second forward transition. + time_zone::civil_lookup cl2 = tz.lookup(civil_second(1978, 4, 2, 1, 15, 0)); + EXPECT_EQ(time_zone::civil_lookup::SKIPPED, cl2.kind); + ExpectTime(cl2.pre, tz, 1978, 4, 2, 2, 15, 0, 1 * 3600, true, "WEST"); + ExpectTime(cl2.trans, tz, 1978, 4, 2, 2, 0, 0, 1 * 3600, true, "WEST"); + ExpectTime(cl2.post, tz, 1978, 4, 2, 0, 15, 0, 0 * 3600, false, "WET"); +} + +TEST(TimeZoneEdgeCase, FixedOffsets) { + const time_zone gmtm5 = LoadZone("Etc/GMT+5"); // -0500 + auto tp = convert(civil_second(1970, 1, 1, 0, 0, 0), gmtm5); + ExpectTime(tp, gmtm5, 1970, 1, 1, 0, 0, 0, -5 * 3600, false, "-05"); + EXPECT_EQ(chrono::system_clock::from_time_t(5 * 3600), tp); + + const time_zone gmtp5 = LoadZone("Etc/GMT-5"); // +0500 + tp = convert(civil_second(1970, 1, 1, 0, 0, 0), gmtp5); + ExpectTime(tp, gmtp5, 1970, 1, 1, 0, 0, 0, 5 * 3600, false, "+05"); + EXPECT_EQ(chrono::system_clock::from_time_t(-5 * 3600), tp); +} + +TEST(TimeZoneEdgeCase, NegativeYear) { + // Tests transition from year 0 (aka 1BCE) to year -1. + const time_zone tz = utc_time_zone(); + auto tp = convert(civil_second(0, 1, 1, 0, 0, 0), tz); + ExpectTime(tp, tz, 0, 1, 1, 0, 0, 0, 0 * 3600, false, "UTC"); + EXPECT_EQ(weekday::saturday, get_weekday(convert(tp, tz))); + tp -= cctz::seconds(1); + ExpectTime(tp, tz, -1, 12, 31, 23, 59, 59, 0 * 3600, false, "UTC"); + EXPECT_EQ(weekday::friday, get_weekday(convert(tp, tz))); +} + +TEST(TimeZoneEdgeCase, UTC32bitLimit) { + const time_zone tz = utc_time_zone(); + + // Limits of signed 32-bit time_t + // + // 2147483647 == Tue, 19 Jan 2038 03:14:07 +0000 (UTC) + // 2147483648 == Tue, 19 Jan 2038 03:14:08 +0000 (UTC) + auto tp = convert(civil_second(2038, 1, 19, 3, 14, 7), tz); + ExpectTime(tp, tz, 2038, 1, 19, 3, 14, 7, 0 * 3600, false, "UTC"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 2038, 1, 19, 3, 14, 8, 0 * 3600, false, "UTC"); +} + +TEST(TimeZoneEdgeCase, UTC5DigitYear) { + const time_zone tz = utc_time_zone(); + + // Rollover to 5-digit year + // + // 253402300799 == Fri, 31 Dec 9999 23:59:59 +0000 (UTC) + // 253402300800 == Sat, 1 Jan 1000 00:00:00 +0000 (UTC) + auto tp = convert(civil_second(9999, 12, 31, 23, 59, 59), tz); + ExpectTime(tp, tz, 9999, 12, 31, 23, 59, 59, 0 * 3600, false, "UTC"); + tp += cctz::seconds(1); + ExpectTime(tp, tz, 10000, 1, 1, 0, 0, 0, 0 * 3600, false, "UTC"); +} + +} // namespace cctz diff --git a/contrib/libs/cctz/test/ya.make b/contrib/libs/cctz/test/ya.make new file mode 100644 index 0000000000..8815f9769d --- /dev/null +++ b/contrib/libs/cctz/test/ya.make @@ -0,0 +1,36 @@ +GTEST() + +LICENSE(Apache-2.0) + +LICENSE_TEXTS(.yandex_meta/licenses.list.txt) + +OWNER( + dfyz + petrk +) + +PEERDIR( + contrib/libs/cctz + contrib/libs/cctz/tzdata +) + +ADDINCL( + contrib/libs/cctz/include +) + +IF (NOT AUTOCHECK) + # We do not set TZDIR to a stable data source, so + # LoadZone("libc:localtime") is inconsistent and makes + # LocalTimeLibC test fail on distbuild. + CFLAGS( + -DCCTZ_TEST_LIBC_LOCALTIME + ) +ENDIF() + +SRCS( + civil_time_test.cc + time_zone_format_test.cc + time_zone_lookup_test.cc +) + +END() diff --git a/contrib/libs/cctz/tzdata/README b/contrib/libs/cctz/tzdata/README new file mode 100644 index 0000000000..031fe514c6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/README @@ -0,0 +1,4 @@ +A standalone distribution of tzdata. Run 'cat VERSION' in this directory to find out which IANA version it's based on. + +When a new version of tzdata is released, run ./update_tzdata.py from this directory +to regenerate the CMakeLists.txt and the corresponding resources from a newer tzdata version. diff --git a/contrib/libs/cctz/tzdata/VERSION b/contrib/libs/cctz/tzdata/VERSION new file mode 100644 index 0000000000..ba4bbab789 --- /dev/null +++ b/contrib/libs/cctz/tzdata/VERSION @@ -0,0 +1 @@ +2020e
\ No newline at end of file diff --git a/contrib/libs/cctz/tzdata/factory.cpp b/contrib/libs/cctz/tzdata/factory.cpp new file mode 100644 index 0000000000..5a4b4a27b6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/factory.cpp @@ -0,0 +1,60 @@ +#include <contrib/libs/cctz/include/cctz/zone_info_source.h> + +#include <library/cpp/resource/resource.h> + +#include <util/generic/string.h> +#include <util/stream/str.h> +#include <util/string/builder.h> + +namespace cctz_extension { + namespace { + + class TZoneInfoSource: public cctz::ZoneInfoSource { + private: + TZoneInfoSource(TString&& data) + : TimeZoneData_(data) + , Stream_(TimeZoneData_) + { + } + + public: + static std::unique_ptr<cctz::ZoneInfoSource> LoadZone(const std::string& zoneName) { + TString resourceName = TStringBuilder() << "/cctz/tzdata/"sv << zoneName; + TString tzData; + if (!NResource::FindExact(resourceName, &tzData)) { + return nullptr; + } + return std::unique_ptr<cctz::ZoneInfoSource>(new TZoneInfoSource(std::move(tzData))); + } + + size_t Read(void* buf, size_t size) override { + return Stream_.Read(buf, size); + } + + int Skip(size_t offset) override { + Stream_.Skip(offset); + return 0; + } + + private: + const TString TimeZoneData_; + TStringInput Stream_; + }; + + std::unique_ptr<cctz::ZoneInfoSource> CustomFactory( + const std::string& name, + const std::function<std::unique_ptr<cctz::ZoneInfoSource>(const std::string& name)>& /*fallback*/ + ) + { + std::unique_ptr<cctz::ZoneInfoSource> zis = TZoneInfoSource::LoadZone(name); + if (zis) { + return zis; + } + return nullptr; + } + + } // namespace + + ZoneInfoSourceFactory zone_info_source_factory = CustomFactory; + +} // namespace cctz_extension diff --git a/contrib/libs/cctz/tzdata/generated/00636062cbcd94f2ead5a75cc197675a b/contrib/libs/cctz/tzdata/generated/00636062cbcd94f2ead5a75cc197675a Binary files differnew file mode 100644 index 0000000000..a461dceaa2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/00636062cbcd94f2ead5a75cc197675a diff --git a/contrib/libs/cctz/tzdata/generated/0124cd65b22dfd92129cb0a43719c717 b/contrib/libs/cctz/tzdata/generated/0124cd65b22dfd92129cb0a43719c717 Binary files differnew file mode 100644 index 0000000000..423c6c203a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0124cd65b22dfd92129cb0a43719c717 diff --git a/contrib/libs/cctz/tzdata/generated/0249d27eff0294ba6c5d090d9895fd17 b/contrib/libs/cctz/tzdata/generated/0249d27eff0294ba6c5d090d9895fd17 Binary files differnew file mode 100644 index 0000000000..58863e0436 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0249d27eff0294ba6c5d090d9895fd17 diff --git a/contrib/libs/cctz/tzdata/generated/02d7a06f7ede604bdd6bf40932b670c6 b/contrib/libs/cctz/tzdata/generated/02d7a06f7ede604bdd6bf40932b670c6 Binary files differnew file mode 100644 index 0000000000..3bfbbc563c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/02d7a06f7ede604bdd6bf40932b670c6 diff --git a/contrib/libs/cctz/tzdata/generated/045f2032b6a679c82581ba29669df8c8 b/contrib/libs/cctz/tzdata/generated/045f2032b6a679c82581ba29669df8c8 Binary files differnew file mode 100644 index 0000000000..a84d1dfdb3 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/045f2032b6a679c82581ba29669df8c8 diff --git a/contrib/libs/cctz/tzdata/generated/04875c383508e7181ae595cec9856228 b/contrib/libs/cctz/tzdata/generated/04875c383508e7181ae595cec9856228 Binary files differnew file mode 100644 index 0000000000..c39331e3aa --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/04875c383508e7181ae595cec9856228 diff --git a/contrib/libs/cctz/tzdata/generated/055c3628d78f3c9a01a7732c442f78f9 b/contrib/libs/cctz/tzdata/generated/055c3628d78f3c9a01a7732c442f78f9 Binary files differnew file mode 100644 index 0000000000..a9403eca46 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/055c3628d78f3c9a01a7732c442f78f9 diff --git a/contrib/libs/cctz/tzdata/generated/0672593cd4756dbfb8bba02b4555c91d b/contrib/libs/cctz/tzdata/generated/0672593cd4756dbfb8bba02b4555c91d Binary files differnew file mode 100644 index 0000000000..50a064fa01 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0672593cd4756dbfb8bba02b4555c91d diff --git a/contrib/libs/cctz/tzdata/generated/0727fa9015cd130fba15b7e7163ff139 b/contrib/libs/cctz/tzdata/generated/0727fa9015cd130fba15b7e7163ff139 Binary files differnew file mode 100644 index 0000000000..6f0558c3b6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0727fa9015cd130fba15b7e7163ff139 diff --git a/contrib/libs/cctz/tzdata/generated/07844fc101071f657d084ecb7d161aa0 b/contrib/libs/cctz/tzdata/generated/07844fc101071f657d084ecb7d161aa0 Binary files differnew file mode 100644 index 0000000000..e031750276 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/07844fc101071f657d084ecb7d161aa0 diff --git a/contrib/libs/cctz/tzdata/generated/07b0081174b26fd15187b9d6a019e322 b/contrib/libs/cctz/tzdata/generated/07b0081174b26fd15187b9d6a019e322 Binary files differnew file mode 100644 index 0000000000..388df2969f --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/07b0081174b26fd15187b9d6a019e322 diff --git a/contrib/libs/cctz/tzdata/generated/084d4da363c6b04024bd4027111502bf b/contrib/libs/cctz/tzdata/generated/084d4da363c6b04024bd4027111502bf Binary files differnew file mode 100644 index 0000000000..9228ee02ed --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/084d4da363c6b04024bd4027111502bf diff --git a/contrib/libs/cctz/tzdata/generated/0998859e2d38d079cc1a3429aa428db4 b/contrib/libs/cctz/tzdata/generated/0998859e2d38d079cc1a3429aa428db4 Binary files differnew file mode 100644 index 0000000000..2a49c6c50f --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0998859e2d38d079cc1a3429aa428db4 diff --git a/contrib/libs/cctz/tzdata/generated/09e36f9135b9ddb666cbb9496fecdf89 b/contrib/libs/cctz/tzdata/generated/09e36f9135b9ddb666cbb9496fecdf89 Binary files differnew file mode 100644 index 0000000000..a6a67300dd --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/09e36f9135b9ddb666cbb9496fecdf89 diff --git a/contrib/libs/cctz/tzdata/generated/0a83457e40c917a816db3dd80c348688 b/contrib/libs/cctz/tzdata/generated/0a83457e40c917a816db3dd80c348688 Binary files differnew file mode 100644 index 0000000000..19ccd3576d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0a83457e40c917a816db3dd80c348688 diff --git a/contrib/libs/cctz/tzdata/generated/0b00b9da0d4f68857bdebb750ea28c4d b/contrib/libs/cctz/tzdata/generated/0b00b9da0d4f68857bdebb750ea28c4d Binary files differnew file mode 100644 index 0000000000..940be4670a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0b00b9da0d4f68857bdebb750ea28c4d diff --git a/contrib/libs/cctz/tzdata/generated/0b403c8a9ccd7ca6e2a6efbb8ea7a0f0 b/contrib/libs/cctz/tzdata/generated/0b403c8a9ccd7ca6e2a6efbb8ea7a0f0 Binary files differnew file mode 100644 index 0000000000..d1c93c540c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0b403c8a9ccd7ca6e2a6efbb8ea7a0f0 diff --git a/contrib/libs/cctz/tzdata/generated/0b427173cd7de48179954c1706df9f0f b/contrib/libs/cctz/tzdata/generated/0b427173cd7de48179954c1706df9f0f Binary files differnew file mode 100644 index 0000000000..fb5185ca60 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0b427173cd7de48179954c1706df9f0f diff --git a/contrib/libs/cctz/tzdata/generated/0d49585e3c48010af348561943e319a2 b/contrib/libs/cctz/tzdata/generated/0d49585e3c48010af348561943e319a2 Binary files differnew file mode 100644 index 0000000000..5ef7be71fd --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0d49585e3c48010af348561943e319a2 diff --git a/contrib/libs/cctz/tzdata/generated/0d745dbfd2cee7fffbd809ae5176666d b/contrib/libs/cctz/tzdata/generated/0d745dbfd2cee7fffbd809ae5176666d Binary files differnew file mode 100644 index 0000000000..7ca9972502 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0d745dbfd2cee7fffbd809ae5176666d diff --git a/contrib/libs/cctz/tzdata/generated/0d81f8cc7c4066b8f84371ebbbb3e00c b/contrib/libs/cctz/tzdata/generated/0d81f8cc7c4066b8f84371ebbbb3e00c Binary files differnew file mode 100644 index 0000000000..ca7a81f656 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0d81f8cc7c4066b8f84371ebbbb3e00c diff --git a/contrib/libs/cctz/tzdata/generated/0dfaf73a64a7c3cfcd10756a6d545e08 b/contrib/libs/cctz/tzdata/generated/0dfaf73a64a7c3cfcd10756a6d545e08 Binary files differnew file mode 100644 index 0000000000..bb842cb1f5 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0dfaf73a64a7c3cfcd10756a6d545e08 diff --git a/contrib/libs/cctz/tzdata/generated/0e0379dfc5620381816641ce71fa9612 b/contrib/libs/cctz/tzdata/generated/0e0379dfc5620381816641ce71fa9612 Binary files differnew file mode 100644 index 0000000000..af3107db51 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0e0379dfc5620381816641ce71fa9612 diff --git a/contrib/libs/cctz/tzdata/generated/0e84cda11c5dc9030c43c51187a6c78d b/contrib/libs/cctz/tzdata/generated/0e84cda11c5dc9030c43c51187a6c78d Binary files differnew file mode 100644 index 0000000000..23fca12205 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0e84cda11c5dc9030c43c51187a6c78d diff --git a/contrib/libs/cctz/tzdata/generated/0e8c2a93c75cfb3705dc63788803ebfb b/contrib/libs/cctz/tzdata/generated/0e8c2a93c75cfb3705dc63788803ebfb Binary files differnew file mode 100644 index 0000000000..79e2a9419a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0e8c2a93c75cfb3705dc63788803ebfb diff --git a/contrib/libs/cctz/tzdata/generated/0fb4aa6fed3f28bc7a3dae35a993171a b/contrib/libs/cctz/tzdata/generated/0fb4aa6fed3f28bc7a3dae35a993171a Binary files differnew file mode 100644 index 0000000000..ea49c00b22 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/0fb4aa6fed3f28bc7a3dae35a993171a diff --git a/contrib/libs/cctz/tzdata/generated/11ca9bc056ef1ae4643107bea827928f b/contrib/libs/cctz/tzdata/generated/11ca9bc056ef1ae4643107bea827928f Binary files differnew file mode 100644 index 0000000000..4e31affb50 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/11ca9bc056ef1ae4643107bea827928f diff --git a/contrib/libs/cctz/tzdata/generated/1377f55949e2a3c4cf3ccc96bb5a91a5 b/contrib/libs/cctz/tzdata/generated/1377f55949e2a3c4cf3ccc96bb5a91a5 Binary files differnew file mode 100644 index 0000000000..60bdf4d07e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/1377f55949e2a3c4cf3ccc96bb5a91a5 diff --git a/contrib/libs/cctz/tzdata/generated/138f1cfa1b7558ef69bddd0870f7000d b/contrib/libs/cctz/tzdata/generated/138f1cfa1b7558ef69bddd0870f7000d Binary files differnew file mode 100644 index 0000000000..e1780a5750 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/138f1cfa1b7558ef69bddd0870f7000d diff --git a/contrib/libs/cctz/tzdata/generated/13f02d014fe55ec2ac75fad588dff1fc b/contrib/libs/cctz/tzdata/generated/13f02d014fe55ec2ac75fad588dff1fc Binary files differnew file mode 100644 index 0000000000..da0909cb21 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/13f02d014fe55ec2ac75fad588dff1fc diff --git a/contrib/libs/cctz/tzdata/generated/14af0ba77d76b97e0e666c070c2172cf b/contrib/libs/cctz/tzdata/generated/14af0ba77d76b97e0e666c070c2172cf Binary files differnew file mode 100644 index 0000000000..e06629d368 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/14af0ba77d76b97e0e666c070c2172cf diff --git a/contrib/libs/cctz/tzdata/generated/1530b1e45e83ed3f4e61d1a6f2f4f706 b/contrib/libs/cctz/tzdata/generated/1530b1e45e83ed3f4e61d1a6f2f4f706 Binary files differnew file mode 100644 index 0000000000..2f676d3bf5 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/1530b1e45e83ed3f4e61d1a6f2f4f706 diff --git a/contrib/libs/cctz/tzdata/generated/165baa2c51758e236a98a6a1c4cf09a0 b/contrib/libs/cctz/tzdata/generated/165baa2c51758e236a98a6a1c4cf09a0 Binary files differnew file mode 100644 index 0000000000..01c47ccb86 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/165baa2c51758e236a98a6a1c4cf09a0 diff --git a/contrib/libs/cctz/tzdata/generated/167b215e24978122218b1a0eec97ea7a b/contrib/libs/cctz/tzdata/generated/167b215e24978122218b1a0eec97ea7a Binary files differnew file mode 100644 index 0000000000..83a2816955 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/167b215e24978122218b1a0eec97ea7a diff --git a/contrib/libs/cctz/tzdata/generated/16a0b637c31e7e480cfccfc46dd75d67 b/contrib/libs/cctz/tzdata/generated/16a0b637c31e7e480cfccfc46dd75d67 Binary files differnew file mode 100644 index 0000000000..00bc80a65e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/16a0b637c31e7e480cfccfc46dd75d67 diff --git a/contrib/libs/cctz/tzdata/generated/17ca5b7fed86c92696b863cb6a78187f b/contrib/libs/cctz/tzdata/generated/17ca5b7fed86c92696b863cb6a78187f Binary files differnew file mode 100644 index 0000000000..660ce4cf69 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/17ca5b7fed86c92696b863cb6a78187f diff --git a/contrib/libs/cctz/tzdata/generated/19ed55c2f6f06452f1008cfb15e5636b b/contrib/libs/cctz/tzdata/generated/19ed55c2f6f06452f1008cfb15e5636b Binary files differnew file mode 100644 index 0000000000..c517002604 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/19ed55c2f6f06452f1008cfb15e5636b diff --git a/contrib/libs/cctz/tzdata/generated/19ef27aa43febb679c0795f8c5dedc0f b/contrib/libs/cctz/tzdata/generated/19ef27aa43febb679c0795f8c5dedc0f Binary files differnew file mode 100644 index 0000000000..378919ea11 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/19ef27aa43febb679c0795f8c5dedc0f diff --git a/contrib/libs/cctz/tzdata/generated/1a41268ed57dfc9d45a22013bd679866 b/contrib/libs/cctz/tzdata/generated/1a41268ed57dfc9d45a22013bd679866 Binary files differnew file mode 100644 index 0000000000..64841661a0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/1a41268ed57dfc9d45a22013bd679866 diff --git a/contrib/libs/cctz/tzdata/generated/1ae456cf0f29bd731d4d9f876c4a0905 b/contrib/libs/cctz/tzdata/generated/1ae456cf0f29bd731d4d9f876c4a0905 Binary files differnew file mode 100644 index 0000000000..4a6fa1d494 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/1ae456cf0f29bd731d4d9f876c4a0905 diff --git a/contrib/libs/cctz/tzdata/generated/1b6ec1c2e23ea5b37361d885e1db8450 b/contrib/libs/cctz/tzdata/generated/1b6ec1c2e23ea5b37361d885e1db8450 Binary files differnew file mode 100644 index 0000000000..131d77b54a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/1b6ec1c2e23ea5b37361d885e1db8450 diff --git a/contrib/libs/cctz/tzdata/generated/1c750fa694668ef0a1aad95b61533b2a b/contrib/libs/cctz/tzdata/generated/1c750fa694668ef0a1aad95b61533b2a Binary files differnew file mode 100644 index 0000000000..7969e30766 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/1c750fa694668ef0a1aad95b61533b2a diff --git a/contrib/libs/cctz/tzdata/generated/1df7e605c33529940c76c1c145c52fc5 b/contrib/libs/cctz/tzdata/generated/1df7e605c33529940c76c1c145c52fc5 Binary files differnew file mode 100644 index 0000000000..b1497bda63 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/1df7e605c33529940c76c1c145c52fc5 diff --git a/contrib/libs/cctz/tzdata/generated/1e571eef4b7112bb58a746099afd9f02 b/contrib/libs/cctz/tzdata/generated/1e571eef4b7112bb58a746099afd9f02 Binary files differnew file mode 100644 index 0000000000..5ab3243a5f --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/1e571eef4b7112bb58a746099afd9f02 diff --git a/contrib/libs/cctz/tzdata/generated/1ee6e72e10673d4a16b6e24671f793ec b/contrib/libs/cctz/tzdata/generated/1ee6e72e10673d4a16b6e24671f793ec Binary files differnew file mode 100644 index 0000000000..7e646d18e1 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/1ee6e72e10673d4a16b6e24671f793ec diff --git a/contrib/libs/cctz/tzdata/generated/1ef406c5a86f20d89cc555c116a7d104 b/contrib/libs/cctz/tzdata/generated/1ef406c5a86f20d89cc555c116a7d104 Binary files differnew file mode 100644 index 0000000000..71cca8877d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/1ef406c5a86f20d89cc555c116a7d104 diff --git a/contrib/libs/cctz/tzdata/generated/1fd961b54d21dd2ad91b05c7c71435a8 b/contrib/libs/cctz/tzdata/generated/1fd961b54d21dd2ad91b05c7c71435a8 Binary files differnew file mode 100644 index 0000000000..27539c2243 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/1fd961b54d21dd2ad91b05c7c71435a8 diff --git a/contrib/libs/cctz/tzdata/generated/239a70724a0ff39d5dd3e6b7f4a34212 b/contrib/libs/cctz/tzdata/generated/239a70724a0ff39d5dd3e6b7f4a34212 Binary files differnew file mode 100644 index 0000000000..b275f27c02 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/239a70724a0ff39d5dd3e6b7f4a34212 diff --git a/contrib/libs/cctz/tzdata/generated/247c3c527e0314c20b0c4e76b937c31c b/contrib/libs/cctz/tzdata/generated/247c3c527e0314c20b0c4e76b937c31c Binary files differnew file mode 100644 index 0000000000..772e23c4cd --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/247c3c527e0314c20b0c4e76b937c31c diff --git a/contrib/libs/cctz/tzdata/generated/253d5505eaf3a497f4fa107633bea235 b/contrib/libs/cctz/tzdata/generated/253d5505eaf3a497f4fa107633bea235 Binary files differnew file mode 100644 index 0000000000..9558bf7180 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/253d5505eaf3a497f4fa107633bea235 diff --git a/contrib/libs/cctz/tzdata/generated/2577d6d2ba90616ca47c8ee8d9fbca20 b/contrib/libs/cctz/tzdata/generated/2577d6d2ba90616ca47c8ee8d9fbca20 Binary files differnew file mode 100644 index 0000000000..465546bd39 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/2577d6d2ba90616ca47c8ee8d9fbca20 diff --git a/contrib/libs/cctz/tzdata/generated/268c9a38823e18c714ec9fb756a8042e b/contrib/libs/cctz/tzdata/generated/268c9a38823e18c714ec9fb756a8042e Binary files differnew file mode 100644 index 0000000000..c09a87558d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/268c9a38823e18c714ec9fb756a8042e diff --git a/contrib/libs/cctz/tzdata/generated/28fe8388ff78123cfd04d67e32057886 b/contrib/libs/cctz/tzdata/generated/28fe8388ff78123cfd04d67e32057886 Binary files differnew file mode 100644 index 0000000000..285bed2c63 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/28fe8388ff78123cfd04d67e32057886 diff --git a/contrib/libs/cctz/tzdata/generated/29067b92c3481871788d16e05841ce78 b/contrib/libs/cctz/tzdata/generated/29067b92c3481871788d16e05841ce78 Binary files differnew file mode 100644 index 0000000000..aff8d82d2a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/29067b92c3481871788d16e05841ce78 diff --git a/contrib/libs/cctz/tzdata/generated/29c0187634c10fc717832169fc449715 b/contrib/libs/cctz/tzdata/generated/29c0187634c10fc717832169fc449715 Binary files differnew file mode 100644 index 0000000000..6d5ce3db73 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/29c0187634c10fc717832169fc449715 diff --git a/contrib/libs/cctz/tzdata/generated/2a4c8fd0d241b11b207c41b0aedd6cf9 b/contrib/libs/cctz/tzdata/generated/2a4c8fd0d241b11b207c41b0aedd6cf9 Binary files differnew file mode 100644 index 0000000000..1a4c8ea863 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/2a4c8fd0d241b11b207c41b0aedd6cf9 diff --git a/contrib/libs/cctz/tzdata/generated/2aa03352ec7ce016dc2c87a064ae8bf7 b/contrib/libs/cctz/tzdata/generated/2aa03352ec7ce016dc2c87a064ae8bf7 Binary files differnew file mode 100644 index 0000000000..ffcf8bee10 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/2aa03352ec7ce016dc2c87a064ae8bf7 diff --git a/contrib/libs/cctz/tzdata/generated/2aa2dbd00a40fc7bdc1f1e3d461a2646 b/contrib/libs/cctz/tzdata/generated/2aa2dbd00a40fc7bdc1f1e3d461a2646 Binary files differnew file mode 100644 index 0000000000..7fa5f46835 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/2aa2dbd00a40fc7bdc1f1e3d461a2646 diff --git a/contrib/libs/cctz/tzdata/generated/2b3fb59013e51fa85db1cee17e54edc8 b/contrib/libs/cctz/tzdata/generated/2b3fb59013e51fa85db1cee17e54edc8 Binary files differnew file mode 100644 index 0000000000..5321bbd46e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/2b3fb59013e51fa85db1cee17e54edc8 diff --git a/contrib/libs/cctz/tzdata/generated/2c18bc1a2ddb1b06e98ffa553ef1aaee b/contrib/libs/cctz/tzdata/generated/2c18bc1a2ddb1b06e98ffa553ef1aaee Binary files differnew file mode 100644 index 0000000000..341a0235ef --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/2c18bc1a2ddb1b06e98ffa553ef1aaee diff --git a/contrib/libs/cctz/tzdata/generated/2d0a65ce6c15961ab95c917d9f23e882 b/contrib/libs/cctz/tzdata/generated/2d0a65ce6c15961ab95c917d9f23e882 Binary files differnew file mode 100644 index 0000000000..9d49cd35cd --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/2d0a65ce6c15961ab95c917d9f23e882 diff --git a/contrib/libs/cctz/tzdata/generated/2e2be8fa9483fe9dd59ab4d82ac4107f b/contrib/libs/cctz/tzdata/generated/2e2be8fa9483fe9dd59ab4d82ac4107f Binary files differnew file mode 100644 index 0000000000..dd3eb32278 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/2e2be8fa9483fe9dd59ab4d82ac4107f diff --git a/contrib/libs/cctz/tzdata/generated/2e506a44524d8b3a2b0a86edd0211628 b/contrib/libs/cctz/tzdata/generated/2e506a44524d8b3a2b0a86edd0211628 Binary files differnew file mode 100644 index 0000000000..fcb0328043 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/2e506a44524d8b3a2b0a86edd0211628 diff --git a/contrib/libs/cctz/tzdata/generated/2ee30998e941f8d603ad278135230cbd b/contrib/libs/cctz/tzdata/generated/2ee30998e941f8d603ad278135230cbd Binary files differnew file mode 100644 index 0000000000..dc0ed422f6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/2ee30998e941f8d603ad278135230cbd diff --git a/contrib/libs/cctz/tzdata/generated/30c97d0792df5d5939ff0f09c53c385d b/contrib/libs/cctz/tzdata/generated/30c97d0792df5d5939ff0f09c53c385d Binary files differnew file mode 100644 index 0000000000..fca97207b2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/30c97d0792df5d5939ff0f09c53c385d diff --git a/contrib/libs/cctz/tzdata/generated/310f6ba2360c27c334c6e17fccf2b9a5 b/contrib/libs/cctz/tzdata/generated/310f6ba2360c27c334c6e17fccf2b9a5 Binary files differnew file mode 100644 index 0000000000..65ee428ce1 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/310f6ba2360c27c334c6e17fccf2b9a5 diff --git a/contrib/libs/cctz/tzdata/generated/31b072dd08dde7ce02c27780c6b307aa b/contrib/libs/cctz/tzdata/generated/31b072dd08dde7ce02c27780c6b307aa Binary files differnew file mode 100644 index 0000000000..78ab35b6b0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/31b072dd08dde7ce02c27780c6b307aa diff --git a/contrib/libs/cctz/tzdata/generated/325a2d872e0c0e5339f2e134e921047a b/contrib/libs/cctz/tzdata/generated/325a2d872e0c0e5339f2e134e921047a Binary files differnew file mode 100644 index 0000000000..c9752d2f23 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/325a2d872e0c0e5339f2e134e921047a diff --git a/contrib/libs/cctz/tzdata/generated/33cffb9ac13285f945f3c4ef6ce13585 b/contrib/libs/cctz/tzdata/generated/33cffb9ac13285f945f3c4ef6ce13585 Binary files differnew file mode 100644 index 0000000000..c39ae382b5 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/33cffb9ac13285f945f3c4ef6ce13585 diff --git a/contrib/libs/cctz/tzdata/generated/34dc35c8aa0f4e3a0064a92e5aa5d762 b/contrib/libs/cctz/tzdata/generated/34dc35c8aa0f4e3a0064a92e5aa5d762 Binary files differnew file mode 100644 index 0000000000..62c5840a83 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/34dc35c8aa0f4e3a0064a92e5aa5d762 diff --git a/contrib/libs/cctz/tzdata/generated/356ff8bd249ee3f6983cba8426901244 b/contrib/libs/cctz/tzdata/generated/356ff8bd249ee3f6983cba8426901244 Binary files differnew file mode 100644 index 0000000000..8718efcce2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/356ff8bd249ee3f6983cba8426901244 diff --git a/contrib/libs/cctz/tzdata/generated/35eebba76b28756b47e8fff3157eafdb b/contrib/libs/cctz/tzdata/generated/35eebba76b28756b47e8fff3157eafdb Binary files differnew file mode 100644 index 0000000000..947b50995f --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/35eebba76b28756b47e8fff3157eafdb diff --git a/contrib/libs/cctz/tzdata/generated/36687b86e799dc46c4ad4c49e3222ea5 b/contrib/libs/cctz/tzdata/generated/36687b86e799dc46c4ad4c49e3222ea5 Binary files differnew file mode 100644 index 0000000000..0a948c2eac --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/36687b86e799dc46c4ad4c49e3222ea5 diff --git a/contrib/libs/cctz/tzdata/generated/37f26cf8b8fe9179833e366ca13b8916 b/contrib/libs/cctz/tzdata/generated/37f26cf8b8fe9179833e366ca13b8916 Binary files differnew file mode 100644 index 0000000000..14b2ad09ea --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/37f26cf8b8fe9179833e366ca13b8916 diff --git a/contrib/libs/cctz/tzdata/generated/39b21885c919ae9c27f51be3dc0fba9d b/contrib/libs/cctz/tzdata/generated/39b21885c919ae9c27f51be3dc0fba9d Binary files differnew file mode 100644 index 0000000000..5be6f9b016 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/39b21885c919ae9c27f51be3dc0fba9d diff --git a/contrib/libs/cctz/tzdata/generated/39b47bf37a27f7bcd5d3f7c51343c7fc b/contrib/libs/cctz/tzdata/generated/39b47bf37a27f7bcd5d3f7c51343c7fc Binary files differnew file mode 100644 index 0000000000..5e6b6de645 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/39b47bf37a27f7bcd5d3f7c51343c7fc diff --git a/contrib/libs/cctz/tzdata/generated/39d0994d5956e55a919f2945ccd7c0bf b/contrib/libs/cctz/tzdata/generated/39d0994d5956e55a919f2945ccd7c0bf Binary files differnew file mode 100644 index 0000000000..ea38c97008 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/39d0994d5956e55a919f2945ccd7c0bf diff --git a/contrib/libs/cctz/tzdata/generated/39ffa0df7491f260ed87949d60aa34da b/contrib/libs/cctz/tzdata/generated/39ffa0df7491f260ed87949d60aa34da Binary files differnew file mode 100644 index 0000000000..a595e60eea --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/39ffa0df7491f260ed87949d60aa34da diff --git a/contrib/libs/cctz/tzdata/generated/3a420ea50d496f0c159a0d18af06b211 b/contrib/libs/cctz/tzdata/generated/3a420ea50d496f0c159a0d18af06b211 Binary files differnew file mode 100644 index 0000000000..32c1941634 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/3a420ea50d496f0c159a0d18af06b211 diff --git a/contrib/libs/cctz/tzdata/generated/3c4a6f9840f3d89534c5f511329704e8 b/contrib/libs/cctz/tzdata/generated/3c4a6f9840f3d89534c5f511329704e8 Binary files differnew file mode 100644 index 0000000000..6e08a26127 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/3c4a6f9840f3d89534c5f511329704e8 diff --git a/contrib/libs/cctz/tzdata/generated/3c6db0baa05cea4617bcad88b40b1e6a b/contrib/libs/cctz/tzdata/generated/3c6db0baa05cea4617bcad88b40b1e6a Binary files differnew file mode 100644 index 0000000000..0edc52b9b7 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/3c6db0baa05cea4617bcad88b40b1e6a diff --git a/contrib/libs/cctz/tzdata/generated/3c6f113a11cbaf251e4f5afbcf15a7ac b/contrib/libs/cctz/tzdata/generated/3c6f113a11cbaf251e4f5afbcf15a7ac Binary files differnew file mode 100644 index 0000000000..e93dd5141b --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/3c6f113a11cbaf251e4f5afbcf15a7ac diff --git a/contrib/libs/cctz/tzdata/generated/3cf306430a541783b5e2b8465aa94342 b/contrib/libs/cctz/tzdata/generated/3cf306430a541783b5e2b8465aa94342 Binary files differnew file mode 100644 index 0000000000..c0cfc85a29 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/3cf306430a541783b5e2b8465aa94342 diff --git a/contrib/libs/cctz/tzdata/generated/3d7f8146ac1ad071d3b5738e49076af7 b/contrib/libs/cctz/tzdata/generated/3d7f8146ac1ad071d3b5738e49076af7 Binary files differnew file mode 100644 index 0000000000..350d77e28e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/3d7f8146ac1ad071d3b5738e49076af7 diff --git a/contrib/libs/cctz/tzdata/generated/3ee52913271777c67f23d5a918bb0f7c b/contrib/libs/cctz/tzdata/generated/3ee52913271777c67f23d5a918bb0f7c Binary files differnew file mode 100644 index 0000000000..773feba89d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/3ee52913271777c67f23d5a918bb0f7c diff --git a/contrib/libs/cctz/tzdata/generated/3f4c05321e52971f2213bfb9e45b7a35 b/contrib/libs/cctz/tzdata/generated/3f4c05321e52971f2213bfb9e45b7a35 Binary files differnew file mode 100644 index 0000000000..3e07850866 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/3f4c05321e52971f2213bfb9e45b7a35 diff --git a/contrib/libs/cctz/tzdata/generated/3ff9cb17a579851ce689eac23e64d899 b/contrib/libs/cctz/tzdata/generated/3ff9cb17a579851ce689eac23e64d899 Binary files differnew file mode 100644 index 0000000000..ecb69ef2c9 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/3ff9cb17a579851ce689eac23e64d899 diff --git a/contrib/libs/cctz/tzdata/generated/41073bcf4d5aaaf7dbd1da830ce5e1fe b/contrib/libs/cctz/tzdata/generated/41073bcf4d5aaaf7dbd1da830ce5e1fe Binary files differnew file mode 100644 index 0000000000..766024b36c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/41073bcf4d5aaaf7dbd1da830ce5e1fe diff --git a/contrib/libs/cctz/tzdata/generated/41dd4c2678c8776c4abdcc809932bbe7 b/contrib/libs/cctz/tzdata/generated/41dd4c2678c8776c4abdcc809932bbe7 Binary files differnew file mode 100644 index 0000000000..f06065ebd1 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/41dd4c2678c8776c4abdcc809932bbe7 diff --git a/contrib/libs/cctz/tzdata/generated/42fcd2bd28f14995f4fec31b081d88b0 b/contrib/libs/cctz/tzdata/generated/42fcd2bd28f14995f4fec31b081d88b0 Binary files differnew file mode 100644 index 0000000000..11d988e10a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/42fcd2bd28f14995f4fec31b081d88b0 diff --git a/contrib/libs/cctz/tzdata/generated/4335653c96fc0b0fc83e2604a8362934 b/contrib/libs/cctz/tzdata/generated/4335653c96fc0b0fc83e2604a8362934 Binary files differnew file mode 100644 index 0000000000..9fefee388e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4335653c96fc0b0fc83e2604a8362934 diff --git a/contrib/libs/cctz/tzdata/generated/43c7956d0835817f930236a5633cffa6 b/contrib/libs/cctz/tzdata/generated/43c7956d0835817f930236a5633cffa6 Binary files differnew file mode 100644 index 0000000000..d931558058 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/43c7956d0835817f930236a5633cffa6 diff --git a/contrib/libs/cctz/tzdata/generated/43d37a94ef2f6ee11c55e0a14c2898cb b/contrib/libs/cctz/tzdata/generated/43d37a94ef2f6ee11c55e0a14c2898cb Binary files differnew file mode 100644 index 0000000000..79a983e545 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/43d37a94ef2f6ee11c55e0a14c2898cb diff --git a/contrib/libs/cctz/tzdata/generated/44355d47052f97ac7388446bce23e3ab b/contrib/libs/cctz/tzdata/generated/44355d47052f97ac7388446bce23e3ab Binary files differnew file mode 100644 index 0000000000..720c679017 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/44355d47052f97ac7388446bce23e3ab diff --git a/contrib/libs/cctz/tzdata/generated/450d5ffb8f5928afc0981b5a1a8ba4fa b/contrib/libs/cctz/tzdata/generated/450d5ffb8f5928afc0981b5a1a8ba4fa Binary files differnew file mode 100644 index 0000000000..25c0232d95 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/450d5ffb8f5928afc0981b5a1a8ba4fa diff --git a/contrib/libs/cctz/tzdata/generated/46f6544a40a91d7f4369615095abd9fc b/contrib/libs/cctz/tzdata/generated/46f6544a40a91d7f4369615095abd9fc Binary files differnew file mode 100644 index 0000000000..b7f75a9cf6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/46f6544a40a91d7f4369615095abd9fc diff --git a/contrib/libs/cctz/tzdata/generated/4709139f1759e9693b8c02551b527f58 b/contrib/libs/cctz/tzdata/generated/4709139f1759e9693b8c02551b527f58 Binary files differnew file mode 100644 index 0000000000..72a3d4e87a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4709139f1759e9693b8c02551b527f58 diff --git a/contrib/libs/cctz/tzdata/generated/4709fe18f39068d2ca7de4c5396e1513 b/contrib/libs/cctz/tzdata/generated/4709fe18f39068d2ca7de4c5396e1513 Binary files differnew file mode 100644 index 0000000000..7c22f539d9 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4709fe18f39068d2ca7de4c5396e1513 diff --git a/contrib/libs/cctz/tzdata/generated/475a8ae9a30287527356f20d4456abd4 b/contrib/libs/cctz/tzdata/generated/475a8ae9a30287527356f20d4456abd4 Binary files differnew file mode 100644 index 0000000000..9416d522d0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/475a8ae9a30287527356f20d4456abd4 diff --git a/contrib/libs/cctz/tzdata/generated/47cad39dddf1619fc2287b9e98ad20e0 b/contrib/libs/cctz/tzdata/generated/47cad39dddf1619fc2287b9e98ad20e0 Binary files differnew file mode 100644 index 0000000000..cbe22a7622 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/47cad39dddf1619fc2287b9e98ad20e0 diff --git a/contrib/libs/cctz/tzdata/generated/48252c9a797f0f4bea97557a5094cf98 b/contrib/libs/cctz/tzdata/generated/48252c9a797f0f4bea97557a5094cf98 Binary files differnew file mode 100644 index 0000000000..c891866873 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/48252c9a797f0f4bea97557a5094cf98 diff --git a/contrib/libs/cctz/tzdata/generated/48c96bff46ef373ce5d759dc4a4d2de2 b/contrib/libs/cctz/tzdata/generated/48c96bff46ef373ce5d759dc4a4d2de2 Binary files differnew file mode 100644 index 0000000000..6eb3ac46ec --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/48c96bff46ef373ce5d759dc4a4d2de2 diff --git a/contrib/libs/cctz/tzdata/generated/48f03314923c2aaf9706fdbf9abf223d b/contrib/libs/cctz/tzdata/generated/48f03314923c2aaf9706fdbf9abf223d Binary files differnew file mode 100644 index 0000000000..45984a7599 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/48f03314923c2aaf9706fdbf9abf223d diff --git a/contrib/libs/cctz/tzdata/generated/49547ca54933b45b82497d8ede3b6acc b/contrib/libs/cctz/tzdata/generated/49547ca54933b45b82497d8ede3b6acc Binary files differnew file mode 100644 index 0000000000..6cb53d4e61 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/49547ca54933b45b82497d8ede3b6acc diff --git a/contrib/libs/cctz/tzdata/generated/4a5ba954919a3b34fb7779965387992f b/contrib/libs/cctz/tzdata/generated/4a5ba954919a3b34fb7779965387992f Binary files differnew file mode 100644 index 0000000000..7eba33c1c5 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4a5ba954919a3b34fb7779965387992f diff --git a/contrib/libs/cctz/tzdata/generated/4a956902cb69a4cba608798e1da71a58 b/contrib/libs/cctz/tzdata/generated/4a956902cb69a4cba608798e1da71a58 Binary files differnew file mode 100644 index 0000000000..bdbb494487 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4a956902cb69a4cba608798e1da71a58 diff --git a/contrib/libs/cctz/tzdata/generated/4aa21d2f4d29c826df846428917d6124 b/contrib/libs/cctz/tzdata/generated/4aa21d2f4d29c826df846428917d6124 Binary files differnew file mode 100644 index 0000000000..682bcbf61a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4aa21d2f4d29c826df846428917d6124 diff --git a/contrib/libs/cctz/tzdata/generated/4afacd60281211a6a7530a3ff8062781 b/contrib/libs/cctz/tzdata/generated/4afacd60281211a6a7530a3ff8062781 Binary files differnew file mode 100644 index 0000000000..837780922f --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4afacd60281211a6a7530a3ff8062781 diff --git a/contrib/libs/cctz/tzdata/generated/4b51b9e60156a250908acc46d7c8cabc b/contrib/libs/cctz/tzdata/generated/4b51b9e60156a250908acc46d7c8cabc Binary files differnew file mode 100644 index 0000000000..3b62585d0a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4b51b9e60156a250908acc46d7c8cabc diff --git a/contrib/libs/cctz/tzdata/generated/4b710acfb88ea85eda7b5f75df122214 b/contrib/libs/cctz/tzdata/generated/4b710acfb88ea85eda7b5f75df122214 Binary files differnew file mode 100644 index 0000000000..36681ed78e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4b710acfb88ea85eda7b5f75df122214 diff --git a/contrib/libs/cctz/tzdata/generated/4cd70a6fdc80b1b15c0b9f7c3b807107 b/contrib/libs/cctz/tzdata/generated/4cd70a6fdc80b1b15c0b9f7c3b807107 Binary files differnew file mode 100644 index 0000000000..cc44179564 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4cd70a6fdc80b1b15c0b9f7c3b807107 diff --git a/contrib/libs/cctz/tzdata/generated/4cddbf0831a9bbaa79369d3b91961a8f b/contrib/libs/cctz/tzdata/generated/4cddbf0831a9bbaa79369d3b91961a8f Binary files differnew file mode 100644 index 0000000000..bf7471dd3f --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4cddbf0831a9bbaa79369d3b91961a8f diff --git a/contrib/libs/cctz/tzdata/generated/4d5e4576a979e0cdeb6a7d0e81989b4e b/contrib/libs/cctz/tzdata/generated/4d5e4576a979e0cdeb6a7d0e81989b4e Binary files differnew file mode 100644 index 0000000000..30315cc078 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4d5e4576a979e0cdeb6a7d0e81989b4e diff --git a/contrib/libs/cctz/tzdata/generated/4d7ff90583dcd0e08fc8c51792761c2b b/contrib/libs/cctz/tzdata/generated/4d7ff90583dcd0e08fc8c51792761c2b Binary files differnew file mode 100644 index 0000000000..8dbe6ff741 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4d7ff90583dcd0e08fc8c51792761c2b diff --git a/contrib/libs/cctz/tzdata/generated/4e36cb5f575bdcbdd38b144d5a9195c9 b/contrib/libs/cctz/tzdata/generated/4e36cb5f575bdcbdd38b144d5a9195c9 Binary files differnew file mode 100644 index 0000000000..550e2a0877 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4e36cb5f575bdcbdd38b144d5a9195c9 diff --git a/contrib/libs/cctz/tzdata/generated/4f3988376fc77952194c6224a912e152 b/contrib/libs/cctz/tzdata/generated/4f3988376fc77952194c6224a912e152 Binary files differnew file mode 100644 index 0000000000..4ea8dae45a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4f3988376fc77952194c6224a912e152 diff --git a/contrib/libs/cctz/tzdata/generated/4fff9a8801bd2b75474dde3870d24e89 b/contrib/libs/cctz/tzdata/generated/4fff9a8801bd2b75474dde3870d24e89 Binary files differnew file mode 100644 index 0000000000..fe4d6c6d6d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/4fff9a8801bd2b75474dde3870d24e89 diff --git a/contrib/libs/cctz/tzdata/generated/506e99f9c797d9798e7a411495691504 b/contrib/libs/cctz/tzdata/generated/506e99f9c797d9798e7a411495691504 Binary files differnew file mode 100644 index 0000000000..00a27264c2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/506e99f9c797d9798e7a411495691504 diff --git a/contrib/libs/cctz/tzdata/generated/50e7cf27ff65d91d4a834e07e9936df2 b/contrib/libs/cctz/tzdata/generated/50e7cf27ff65d91d4a834e07e9936df2 Binary files differnew file mode 100644 index 0000000000..e3934e423c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/50e7cf27ff65d91d4a834e07e9936df2 diff --git a/contrib/libs/cctz/tzdata/generated/510c0710993f09c4d93d3639ac3fe609 b/contrib/libs/cctz/tzdata/generated/510c0710993f09c4d93d3639ac3fe609 Binary files differnew file mode 100644 index 0000000000..ecbc0966dc --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/510c0710993f09c4d93d3639ac3fe609 diff --git a/contrib/libs/cctz/tzdata/generated/511edb5c79692d730d309f4424bbaa0e b/contrib/libs/cctz/tzdata/generated/511edb5c79692d730d309f4424bbaa0e Binary files differnew file mode 100644 index 0000000000..d03bda045d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/511edb5c79692d730d309f4424bbaa0e diff --git a/contrib/libs/cctz/tzdata/generated/51d8a0e68892ebf0854a1b4250ffb26b b/contrib/libs/cctz/tzdata/generated/51d8a0e68892ebf0854a1b4250ffb26b Binary files differnew file mode 100644 index 0000000000..00841a6221 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/51d8a0e68892ebf0854a1b4250ffb26b diff --git a/contrib/libs/cctz/tzdata/generated/52569f1fcc560faffd0ed78e0e9eb69f b/contrib/libs/cctz/tzdata/generated/52569f1fcc560faffd0ed78e0e9eb69f Binary files differnew file mode 100644 index 0000000000..9c95bd0736 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/52569f1fcc560faffd0ed78e0e9eb69f diff --git a/contrib/libs/cctz/tzdata/generated/52f31607db7a4a081c63dfb4cc578408 b/contrib/libs/cctz/tzdata/generated/52f31607db7a4a081c63dfb4cc578408 Binary files differnew file mode 100644 index 0000000000..3c3584e09a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/52f31607db7a4a081c63dfb4cc578408 diff --git a/contrib/libs/cctz/tzdata/generated/53e0f8906861a26dcc561a46f034d49c b/contrib/libs/cctz/tzdata/generated/53e0f8906861a26dcc561a46f034d49c Binary files differnew file mode 100644 index 0000000000..168ef9baa4 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/53e0f8906861a26dcc561a46f034d49c diff --git a/contrib/libs/cctz/tzdata/generated/543113396c7e34a7532457a1ce759c4e b/contrib/libs/cctz/tzdata/generated/543113396c7e34a7532457a1ce759c4e Binary files differnew file mode 100644 index 0000000000..4f771828c9 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/543113396c7e34a7532457a1ce759c4e diff --git a/contrib/libs/cctz/tzdata/generated/56a77f4891fb3e9506aa233f5fbac27e b/contrib/libs/cctz/tzdata/generated/56a77f4891fb3e9506aa233f5fbac27e Binary files differnew file mode 100644 index 0000000000..fe7832cdf9 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/56a77f4891fb3e9506aa233f5fbac27e diff --git a/contrib/libs/cctz/tzdata/generated/56dbf10674ff9ef08ef9088d7e7ab639 b/contrib/libs/cctz/tzdata/generated/56dbf10674ff9ef08ef9088d7e7ab639 Binary files differnew file mode 100644 index 0000000000..137867c8bf --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/56dbf10674ff9ef08ef9088d7e7ab639 diff --git a/contrib/libs/cctz/tzdata/generated/57500f0613dd0355126a75ca0fb0db2c b/contrib/libs/cctz/tzdata/generated/57500f0613dd0355126a75ca0fb0db2c Binary files differnew file mode 100644 index 0000000000..75b2eebb57 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/57500f0613dd0355126a75ca0fb0db2c diff --git a/contrib/libs/cctz/tzdata/generated/58543f30ac34b6510b552b9b3e82b772 b/contrib/libs/cctz/tzdata/generated/58543f30ac34b6510b552b9b3e82b772 Binary files differnew file mode 100644 index 0000000000..2f75480e06 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/58543f30ac34b6510b552b9b3e82b772 diff --git a/contrib/libs/cctz/tzdata/generated/595e67b4c97fda031a90e5ef80813e7d b/contrib/libs/cctz/tzdata/generated/595e67b4c97fda031a90e5ef80813e7d Binary files differnew file mode 100644 index 0000000000..9154643f4c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/595e67b4c97fda031a90e5ef80813e7d diff --git a/contrib/libs/cctz/tzdata/generated/59dc58681872c7d33ac9f1e2f0d1c4c1 b/contrib/libs/cctz/tzdata/generated/59dc58681872c7d33ac9f1e2f0d1c4c1 Binary files differnew file mode 100644 index 0000000000..722751b20e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/59dc58681872c7d33ac9f1e2f0d1c4c1 diff --git a/contrib/libs/cctz/tzdata/generated/5c57dc3d11f5a64fac22a08ea0c64d25 b/contrib/libs/cctz/tzdata/generated/5c57dc3d11f5a64fac22a08ea0c64d25 Binary files differnew file mode 100644 index 0000000000..35a52e53d1 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/5c57dc3d11f5a64fac22a08ea0c64d25 diff --git a/contrib/libs/cctz/tzdata/generated/5d62b2758da6d68cb971d8f2cf64d432 b/contrib/libs/cctz/tzdata/generated/5d62b2758da6d68cb971d8f2cf64d432 Binary files differnew file mode 100644 index 0000000000..58a82e4eb7 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/5d62b2758da6d68cb971d8f2cf64d432 diff --git a/contrib/libs/cctz/tzdata/generated/5e8c48c7a60c434f1e2f1e535172cbb9 b/contrib/libs/cctz/tzdata/generated/5e8c48c7a60c434f1e2f1e535172cbb9 Binary files differnew file mode 100644 index 0000000000..55dce5722c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/5e8c48c7a60c434f1e2f1e535172cbb9 diff --git a/contrib/libs/cctz/tzdata/generated/5ed332a521639d91536739cfb9e4dde6 b/contrib/libs/cctz/tzdata/generated/5ed332a521639d91536739cfb9e4dde6 Binary files differnew file mode 100644 index 0000000000..40e3d492e6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/5ed332a521639d91536739cfb9e4dde6 diff --git a/contrib/libs/cctz/tzdata/generated/5fbedfd64bddc3ec7790a4eb0f22b66c b/contrib/libs/cctz/tzdata/generated/5fbedfd64bddc3ec7790a4eb0f22b66c Binary files differnew file mode 100644 index 0000000000..50c95e0cb0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/5fbedfd64bddc3ec7790a4eb0f22b66c diff --git a/contrib/libs/cctz/tzdata/generated/618a4a8f78720e26749b9c29ed4fd1b3 b/contrib/libs/cctz/tzdata/generated/618a4a8f78720e26749b9c29ed4fd1b3 Binary files differnew file mode 100644 index 0000000000..1aa066ce38 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/618a4a8f78720e26749b9c29ed4fd1b3 diff --git a/contrib/libs/cctz/tzdata/generated/628174eba2d7050564c54d1370a19ca8 b/contrib/libs/cctz/tzdata/generated/628174eba2d7050564c54d1370a19ca8 Binary files differnew file mode 100644 index 0000000000..fe6be8ea8c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/628174eba2d7050564c54d1370a19ca8 diff --git a/contrib/libs/cctz/tzdata/generated/63615364c91acab170ec8f719aa6f59f b/contrib/libs/cctz/tzdata/generated/63615364c91acab170ec8f719aa6f59f Binary files differnew file mode 100644 index 0000000000..ca324cb4cd --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/63615364c91acab170ec8f719aa6f59f diff --git a/contrib/libs/cctz/tzdata/generated/63f5d146aa8a66720b2c4db9e87ec1f4 b/contrib/libs/cctz/tzdata/generated/63f5d146aa8a66720b2c4db9e87ec1f4 Binary files differnew file mode 100644 index 0000000000..05e4c6c586 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/63f5d146aa8a66720b2c4db9e87ec1f4 diff --git a/contrib/libs/cctz/tzdata/generated/6413085a3a485b5683da3f49944995f0 b/contrib/libs/cctz/tzdata/generated/6413085a3a485b5683da3f49944995f0 Binary files differnew file mode 100644 index 0000000000..0a81cbddfa --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/6413085a3a485b5683da3f49944995f0 diff --git a/contrib/libs/cctz/tzdata/generated/641e03b9a1178df8c823447ea6563f25 b/contrib/libs/cctz/tzdata/generated/641e03b9a1178df8c823447ea6563f25 Binary files differnew file mode 100644 index 0000000000..aaf07787ad --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/641e03b9a1178df8c823447ea6563f25 diff --git a/contrib/libs/cctz/tzdata/generated/64afd19c03facc651ca57e6a603b9d05 b/contrib/libs/cctz/tzdata/generated/64afd19c03facc651ca57e6a603b9d05 Binary files differnew file mode 100644 index 0000000000..ea3fb5cd3c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/64afd19c03facc651ca57e6a603b9d05 diff --git a/contrib/libs/cctz/tzdata/generated/64e0eb5df848bbc06156c58b35959680 b/contrib/libs/cctz/tzdata/generated/64e0eb5df848bbc06156c58b35959680 Binary files differnew file mode 100644 index 0000000000..4b2fb3e560 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/64e0eb5df848bbc06156c58b35959680 diff --git a/contrib/libs/cctz/tzdata/generated/64e3b5dfa8069cf23c87bc1dc81cac60 b/contrib/libs/cctz/tzdata/generated/64e3b5dfa8069cf23c87bc1dc81cac60 Binary files differnew file mode 100644 index 0000000000..f4fe590342 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/64e3b5dfa8069cf23c87bc1dc81cac60 diff --git a/contrib/libs/cctz/tzdata/generated/655141cec48ac560e6fec124b1cd664f b/contrib/libs/cctz/tzdata/generated/655141cec48ac560e6fec124b1cd664f Binary files differnew file mode 100644 index 0000000000..8d6032264b --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/655141cec48ac560e6fec124b1cd664f diff --git a/contrib/libs/cctz/tzdata/generated/655680c9ae07d4896919210710185038 b/contrib/libs/cctz/tzdata/generated/655680c9ae07d4896919210710185038 Binary files differnew file mode 100644 index 0000000000..afb3929318 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/655680c9ae07d4896919210710185038 diff --git a/contrib/libs/cctz/tzdata/generated/656bd0f3d2def024f4d1e59fc668b538 b/contrib/libs/cctz/tzdata/generated/656bd0f3d2def024f4d1e59fc668b538 Binary files differnew file mode 100644 index 0000000000..16bac84446 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/656bd0f3d2def024f4d1e59fc668b538 diff --git a/contrib/libs/cctz/tzdata/generated/667e494c45d181f0706bd07b211c850b b/contrib/libs/cctz/tzdata/generated/667e494c45d181f0706bd07b211c850b Binary files differnew file mode 100644 index 0000000000..58d75bc26e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/667e494c45d181f0706bd07b211c850b diff --git a/contrib/libs/cctz/tzdata/generated/66a0ec5d00519d1826d055514861779d b/contrib/libs/cctz/tzdata/generated/66a0ec5d00519d1826d055514861779d Binary files differnew file mode 100644 index 0000000000..6f5d3a15ab --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/66a0ec5d00519d1826d055514861779d diff --git a/contrib/libs/cctz/tzdata/generated/66cda5383f8d5939a8cd80139a07d855 b/contrib/libs/cctz/tzdata/generated/66cda5383f8d5939a8cd80139a07d855 Binary files differnew file mode 100644 index 0000000000..7096b69a56 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/66cda5383f8d5939a8cd80139a07d855 diff --git a/contrib/libs/cctz/tzdata/generated/67c981ccf51584922a1f72dd2d529730 b/contrib/libs/cctz/tzdata/generated/67c981ccf51584922a1f72dd2d529730 Binary files differnew file mode 100644 index 0000000000..69ff7f6fb4 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/67c981ccf51584922a1f72dd2d529730 diff --git a/contrib/libs/cctz/tzdata/generated/6af1f235706f2c48a99cabb1efcd0e53 b/contrib/libs/cctz/tzdata/generated/6af1f235706f2c48a99cabb1efcd0e53 Binary files differnew file mode 100644 index 0000000000..4eb17ff005 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/6af1f235706f2c48a99cabb1efcd0e53 diff --git a/contrib/libs/cctz/tzdata/generated/6bf88ae0f329f2000f6671f8eb2ca943 b/contrib/libs/cctz/tzdata/generated/6bf88ae0f329f2000f6671f8eb2ca943 Binary files differnew file mode 100644 index 0000000000..d6ddda4822 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/6bf88ae0f329f2000f6671f8eb2ca943 diff --git a/contrib/libs/cctz/tzdata/generated/6c4f6742a67bbd289f89eb4fe7de8e57 b/contrib/libs/cctz/tzdata/generated/6c4f6742a67bbd289f89eb4fe7de8e57 Binary files differnew file mode 100644 index 0000000000..9e74745ca7 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/6c4f6742a67bbd289f89eb4fe7de8e57 diff --git a/contrib/libs/cctz/tzdata/generated/6cbb0a7b529efb1e79faaf166808d993 b/contrib/libs/cctz/tzdata/generated/6cbb0a7b529efb1e79faaf166808d993 Binary files differnew file mode 100644 index 0000000000..54aeb0ffa2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/6cbb0a7b529efb1e79faaf166808d993 diff --git a/contrib/libs/cctz/tzdata/generated/6ce46144754f3564668c5a51d6afb854 b/contrib/libs/cctz/tzdata/generated/6ce46144754f3564668c5a51d6afb854 Binary files differnew file mode 100644 index 0000000000..a5755685e3 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/6ce46144754f3564668c5a51d6afb854 diff --git a/contrib/libs/cctz/tzdata/generated/6ddb543268cbeb4a7fffad436081b019 b/contrib/libs/cctz/tzdata/generated/6ddb543268cbeb4a7fffad436081b019 Binary files differnew file mode 100644 index 0000000000..be6b1b6f1e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/6ddb543268cbeb4a7fffad436081b019 diff --git a/contrib/libs/cctz/tzdata/generated/6e5fd4a73872524a21354303cdfff0f8 b/contrib/libs/cctz/tzdata/generated/6e5fd4a73872524a21354303cdfff0f8 Binary files differnew file mode 100644 index 0000000000..ecefc15d8c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/6e5fd4a73872524a21354303cdfff0f8 diff --git a/contrib/libs/cctz/tzdata/generated/6ece595060d1d2db3153c5d523fb106b b/contrib/libs/cctz/tzdata/generated/6ece595060d1d2db3153c5d523fb106b Binary files differnew file mode 100644 index 0000000000..761d1d9af5 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/6ece595060d1d2db3153c5d523fb106b diff --git a/contrib/libs/cctz/tzdata/generated/702a65f05da90971b14686c21add1a90 b/contrib/libs/cctz/tzdata/generated/702a65f05da90971b14686c21add1a90 Binary files differnew file mode 100644 index 0000000000..e0d4fcb5c3 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/702a65f05da90971b14686c21add1a90 diff --git a/contrib/libs/cctz/tzdata/generated/70483b70b5e389865d462a090b99f2ed b/contrib/libs/cctz/tzdata/generated/70483b70b5e389865d462a090b99f2ed Binary files differnew file mode 100644 index 0000000000..10556d5d85 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/70483b70b5e389865d462a090b99f2ed diff --git a/contrib/libs/cctz/tzdata/generated/710422cb894d7b930689a115e97f688b b/contrib/libs/cctz/tzdata/generated/710422cb894d7b930689a115e97f688b Binary files differnew file mode 100644 index 0000000000..eabc972a22 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/710422cb894d7b930689a115e97f688b diff --git a/contrib/libs/cctz/tzdata/generated/71705112182911b4327ac195ffae174b b/contrib/libs/cctz/tzdata/generated/71705112182911b4327ac195ffae174b Binary files differnew file mode 100644 index 0000000000..9378d50539 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/71705112182911b4327ac195ffae174b diff --git a/contrib/libs/cctz/tzdata/generated/7176177837995c39668c29a4a459cb55 b/contrib/libs/cctz/tzdata/generated/7176177837995c39668c29a4a459cb55 Binary files differnew file mode 100644 index 0000000000..8fad7c6b0b --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/7176177837995c39668c29a4a459cb55 diff --git a/contrib/libs/cctz/tzdata/generated/721967abda97296c7f361100d8b868e4 b/contrib/libs/cctz/tzdata/generated/721967abda97296c7f361100d8b868e4 Binary files differnew file mode 100644 index 0000000000..cb45601c95 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/721967abda97296c7f361100d8b868e4 diff --git a/contrib/libs/cctz/tzdata/generated/7353b5d25ddb353ced2f1f9639251c16 b/contrib/libs/cctz/tzdata/generated/7353b5d25ddb353ced2f1f9639251c16 Binary files differnew file mode 100644 index 0000000000..425ad3fda7 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/7353b5d25ddb353ced2f1f9639251c16 diff --git a/contrib/libs/cctz/tzdata/generated/73727b5259886ffb64fb8e20d5456cc6 b/contrib/libs/cctz/tzdata/generated/73727b5259886ffb64fb8e20d5456cc6 Binary files differnew file mode 100644 index 0000000000..4ddc99d8b7 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/73727b5259886ffb64fb8e20d5456cc6 diff --git a/contrib/libs/cctz/tzdata/generated/74b8879270f5bd60554e01c6610b1efb b/contrib/libs/cctz/tzdata/generated/74b8879270f5bd60554e01c6610b1efb Binary files differnew file mode 100644 index 0000000000..fde4833f6b --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/74b8879270f5bd60554e01c6610b1efb diff --git a/contrib/libs/cctz/tzdata/generated/755a91932697ce463a5c9b642e5292d6 b/contrib/libs/cctz/tzdata/generated/755a91932697ce463a5c9b642e5292d6 Binary files differnew file mode 100644 index 0000000000..d9f54a18bb --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/755a91932697ce463a5c9b642e5292d6 diff --git a/contrib/libs/cctz/tzdata/generated/763d7a8374a42066d2b0bb81bd47218f b/contrib/libs/cctz/tzdata/generated/763d7a8374a42066d2b0bb81bd47218f Binary files differnew file mode 100644 index 0000000000..2b6c2eea14 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/763d7a8374a42066d2b0bb81bd47218f diff --git a/contrib/libs/cctz/tzdata/generated/7646ee0acd8d0f0543ad9a1b93603fe3 b/contrib/libs/cctz/tzdata/generated/7646ee0acd8d0f0543ad9a1b93603fe3 Binary files differnew file mode 100644 index 0000000000..6e3290717e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/7646ee0acd8d0f0543ad9a1b93603fe3 diff --git a/contrib/libs/cctz/tzdata/generated/767406f25e6c1c5396e19a3be033304b b/contrib/libs/cctz/tzdata/generated/767406f25e6c1c5396e19a3be033304b Binary files differnew file mode 100644 index 0000000000..0da1d1e211 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/767406f25e6c1c5396e19a3be033304b diff --git a/contrib/libs/cctz/tzdata/generated/768d11c820a4f93683de8f8bc03df8c8 b/contrib/libs/cctz/tzdata/generated/768d11c820a4f93683de8f8bc03df8c8 Binary files differnew file mode 100644 index 0000000000..f2acf6cbbd --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/768d11c820a4f93683de8f8bc03df8c8 diff --git a/contrib/libs/cctz/tzdata/generated/772e6342aeba16851eed7dcda632c5be b/contrib/libs/cctz/tzdata/generated/772e6342aeba16851eed7dcda632c5be Binary files differnew file mode 100644 index 0000000000..57240cf89f --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/772e6342aeba16851eed7dcda632c5be diff --git a/contrib/libs/cctz/tzdata/generated/7745376113623973fcea89b5f8c8812c b/contrib/libs/cctz/tzdata/generated/7745376113623973fcea89b5f8c8812c Binary files differnew file mode 100644 index 0000000000..1bd09fef27 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/7745376113623973fcea89b5f8c8812c diff --git a/contrib/libs/cctz/tzdata/generated/77d9cbb7aa1e48aa0380d2c3b61c75d5 b/contrib/libs/cctz/tzdata/generated/77d9cbb7aa1e48aa0380d2c3b61c75d5 Binary files differnew file mode 100644 index 0000000000..6db49124e2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/77d9cbb7aa1e48aa0380d2c3b61c75d5 diff --git a/contrib/libs/cctz/tzdata/generated/77ea6e8a582f87d7a397a9e7b2111be0 b/contrib/libs/cctz/tzdata/generated/77ea6e8a582f87d7a397a9e7b2111be0 Binary files differnew file mode 100644 index 0000000000..cdf0572be3 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/77ea6e8a582f87d7a397a9e7b2111be0 diff --git a/contrib/libs/cctz/tzdata/generated/7956f01b2e6933717e9ba4adfd327ccc b/contrib/libs/cctz/tzdata/generated/7956f01b2e6933717e9ba4adfd327ccc Binary files differnew file mode 100644 index 0000000000..c0427a40ee --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/7956f01b2e6933717e9ba4adfd327ccc diff --git a/contrib/libs/cctz/tzdata/generated/796a57137d718e4fa3db8ef611f18e61 b/contrib/libs/cctz/tzdata/generated/796a57137d718e4fa3db8ef611f18e61 Binary files differnew file mode 100644 index 0000000000..8906e88c81 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/796a57137d718e4fa3db8ef611f18e61 diff --git a/contrib/libs/cctz/tzdata/generated/79b1d15365011739a45fe1de0258ae52 b/contrib/libs/cctz/tzdata/generated/79b1d15365011739a45fe1de0258ae52 Binary files differnew file mode 100644 index 0000000000..f81d144206 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/79b1d15365011739a45fe1de0258ae52 diff --git a/contrib/libs/cctz/tzdata/generated/79eedb7a0a4788b9bc3c291c4c643b50 b/contrib/libs/cctz/tzdata/generated/79eedb7a0a4788b9bc3c291c4c643b50 Binary files differnew file mode 100644 index 0000000000..07e4c5f4ac --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/79eedb7a0a4788b9bc3c291c4c643b50 diff --git a/contrib/libs/cctz/tzdata/generated/7a350885dea1ebe1bf630eb4254e9abc b/contrib/libs/cctz/tzdata/generated/7a350885dea1ebe1bf630eb4254e9abc Binary files differnew file mode 100644 index 0000000000..31973271d2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/7a350885dea1ebe1bf630eb4254e9abc diff --git a/contrib/libs/cctz/tzdata/generated/7c49d7ec95c93d0934a7a98b1a1ae66f b/contrib/libs/cctz/tzdata/generated/7c49d7ec95c93d0934a7a98b1a1ae66f Binary files differnew file mode 100644 index 0000000000..820e0dd2cd --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/7c49d7ec95c93d0934a7a98b1a1ae66f diff --git a/contrib/libs/cctz/tzdata/generated/7ca29f8adb394d878db41ab40c4c9a5d b/contrib/libs/cctz/tzdata/generated/7ca29f8adb394d878db41ab40c4c9a5d Binary files differnew file mode 100644 index 0000000000..c255f89b6d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/7ca29f8adb394d878db41ab40c4c9a5d diff --git a/contrib/libs/cctz/tzdata/generated/7d4619fed11db15c54153613fcf23bda b/contrib/libs/cctz/tzdata/generated/7d4619fed11db15c54153613fcf23bda Binary files differnew file mode 100644 index 0000000000..d83fb076a2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/7d4619fed11db15c54153613fcf23bda diff --git a/contrib/libs/cctz/tzdata/generated/7dacf7ad9037fa33db4536edf63da220 b/contrib/libs/cctz/tzdata/generated/7dacf7ad9037fa33db4536edf63da220 Binary files differnew file mode 100644 index 0000000000..24f925a2dd --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/7dacf7ad9037fa33db4536edf63da220 diff --git a/contrib/libs/cctz/tzdata/generated/7f89369fd9501f16ae77919d4c0e5658 b/contrib/libs/cctz/tzdata/generated/7f89369fd9501f16ae77919d4c0e5658 Binary files differnew file mode 100644 index 0000000000..824f814160 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/7f89369fd9501f16ae77919d4c0e5658 diff --git a/contrib/libs/cctz/tzdata/generated/806c5856106eb6b28c3846dd93d3acc4 b/contrib/libs/cctz/tzdata/generated/806c5856106eb6b28c3846dd93d3acc4 Binary files differnew file mode 100644 index 0000000000..cd49f05344 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/806c5856106eb6b28c3846dd93d3acc4 diff --git a/contrib/libs/cctz/tzdata/generated/807e3c4820f8a2547e3bac8a344597ca b/contrib/libs/cctz/tzdata/generated/807e3c4820f8a2547e3bac8a344597ca Binary files differnew file mode 100644 index 0000000000..d29bcd68b0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/807e3c4820f8a2547e3bac8a344597ca diff --git a/contrib/libs/cctz/tzdata/generated/823a97c8e447d6f0016bacafd20a246e b/contrib/libs/cctz/tzdata/generated/823a97c8e447d6f0016bacafd20a246e Binary files differnew file mode 100644 index 0000000000..dbb8d57d91 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/823a97c8e447d6f0016bacafd20a246e diff --git a/contrib/libs/cctz/tzdata/generated/82840448c9d4782ffa56514a7fb4ca95 b/contrib/libs/cctz/tzdata/generated/82840448c9d4782ffa56514a7fb4ca95 Binary files differnew file mode 100644 index 0000000000..f66c9f79d6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/82840448c9d4782ffa56514a7fb4ca95 diff --git a/contrib/libs/cctz/tzdata/generated/82b091bd4358c77e600c08893560419b b/contrib/libs/cctz/tzdata/generated/82b091bd4358c77e600c08893560419b Binary files differnew file mode 100644 index 0000000000..6ea24b72cd --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/82b091bd4358c77e600c08893560419b diff --git a/contrib/libs/cctz/tzdata/generated/8371d9f10ef8a679be6eadedc6641d73 b/contrib/libs/cctz/tzdata/generated/8371d9f10ef8a679be6eadedc6641d73 Binary files differnew file mode 100644 index 0000000000..dc2ef554dc --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/8371d9f10ef8a679be6eadedc6641d73 diff --git a/contrib/libs/cctz/tzdata/generated/839eacc63921f196e4ecfded7245a67b b/contrib/libs/cctz/tzdata/generated/839eacc63921f196e4ecfded7245a67b Binary files differnew file mode 100644 index 0000000000..691c56978a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/839eacc63921f196e4ecfded7245a67b diff --git a/contrib/libs/cctz/tzdata/generated/8435b750c0255a506ff0fd58bf646f00 b/contrib/libs/cctz/tzdata/generated/8435b750c0255a506ff0fd58bf646f00 Binary files differnew file mode 100644 index 0000000000..86ef76bf22 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/8435b750c0255a506ff0fd58bf646f00 diff --git a/contrib/libs/cctz/tzdata/generated/85435a33486747b319872947c68317f3 b/contrib/libs/cctz/tzdata/generated/85435a33486747b319872947c68317f3 Binary files differnew file mode 100644 index 0000000000..b016880653 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/85435a33486747b319872947c68317f3 diff --git a/contrib/libs/cctz/tzdata/generated/8629c4ecded1abb6072c099aa6781c47 b/contrib/libs/cctz/tzdata/generated/8629c4ecded1abb6072c099aa6781c47 Binary files differnew file mode 100644 index 0000000000..017bb2e347 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/8629c4ecded1abb6072c099aa6781c47 diff --git a/contrib/libs/cctz/tzdata/generated/87fafd13e64ef4873b39f9946fed557b b/contrib/libs/cctz/tzdata/generated/87fafd13e64ef4873b39f9946fed557b Binary files differnew file mode 100644 index 0000000000..244af26f8a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/87fafd13e64ef4873b39f9946fed557b diff --git a/contrib/libs/cctz/tzdata/generated/88546761589cb98c5209ff92ac71be7d b/contrib/libs/cctz/tzdata/generated/88546761589cb98c5209ff92ac71be7d Binary files differnew file mode 100644 index 0000000000..75f16216f0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/88546761589cb98c5209ff92ac71be7d diff --git a/contrib/libs/cctz/tzdata/generated/89cb42bccb29740b74d74dad225a7f70 b/contrib/libs/cctz/tzdata/generated/89cb42bccb29740b74d74dad225a7f70 Binary files differnew file mode 100644 index 0000000000..38685d4219 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/89cb42bccb29740b74d74dad225a7f70 diff --git a/contrib/libs/cctz/tzdata/generated/89de77d185e9a76612bd5f9fb043a9c2 b/contrib/libs/cctz/tzdata/generated/89de77d185e9a76612bd5f9fb043a9c2 Binary files differnew file mode 100644 index 0000000000..3d7a71ba0e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/89de77d185e9a76612bd5f9fb043a9c2 diff --git a/contrib/libs/cctz/tzdata/generated/8a60b6309c1443774d2f065bcf2bbc61 b/contrib/libs/cctz/tzdata/generated/8a60b6309c1443774d2f065bcf2bbc61 Binary files differnew file mode 100644 index 0000000000..bb7be9f3a4 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/8a60b6309c1443774d2f065bcf2bbc61 diff --git a/contrib/libs/cctz/tzdata/generated/8a665ea4a3144c8c600eb41c70e1f942 b/contrib/libs/cctz/tzdata/generated/8a665ea4a3144c8c600eb41c70e1f942 Binary files differnew file mode 100644 index 0000000000..4c819fab02 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/8a665ea4a3144c8c600eb41c70e1f942 diff --git a/contrib/libs/cctz/tzdata/generated/8a8ef367f59b0e3880bd1cff6651b357 b/contrib/libs/cctz/tzdata/generated/8a8ef367f59b0e3880bd1cff6651b357 Binary files differnew file mode 100644 index 0000000000..ff976dd3b2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/8a8ef367f59b0e3880bd1cff6651b357 diff --git a/contrib/libs/cctz/tzdata/generated/8baab5c53cf4270f860fb2de701ded9d b/contrib/libs/cctz/tzdata/generated/8baab5c53cf4270f860fb2de701ded9d Binary files differnew file mode 100644 index 0000000000..8d0c26e5c8 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/8baab5c53cf4270f860fb2de701ded9d diff --git a/contrib/libs/cctz/tzdata/generated/8c3304792234093e5a3d5debcef24a32 b/contrib/libs/cctz/tzdata/generated/8c3304792234093e5a3d5debcef24a32 Binary files differnew file mode 100644 index 0000000000..65a9fa2cd2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/8c3304792234093e5a3d5debcef24a32 diff --git a/contrib/libs/cctz/tzdata/generated/8d2aeb9646f427ba69fab8ad34c51552 b/contrib/libs/cctz/tzdata/generated/8d2aeb9646f427ba69fab8ad34c51552 Binary files differnew file mode 100644 index 0000000000..bc8eb7a55b --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/8d2aeb9646f427ba69fab8ad34c51552 diff --git a/contrib/libs/cctz/tzdata/generated/8e7f6cfc11d44c8e29f7f4a59df5fcae b/contrib/libs/cctz/tzdata/generated/8e7f6cfc11d44c8e29f7f4a59df5fcae Binary files differnew file mode 100644 index 0000000000..bc70fe416f --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/8e7f6cfc11d44c8e29f7f4a59df5fcae diff --git a/contrib/libs/cctz/tzdata/generated/8f9746ead1fc03c962cdd7ddacde663d b/contrib/libs/cctz/tzdata/generated/8f9746ead1fc03c962cdd7ddacde663d Binary files differnew file mode 100644 index 0000000000..f85eb34157 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/8f9746ead1fc03c962cdd7ddacde663d diff --git a/contrib/libs/cctz/tzdata/generated/8fa410ffc232e56d0f945bd2b6c34dfe b/contrib/libs/cctz/tzdata/generated/8fa410ffc232e56d0f945bd2b6c34dfe Binary files differnew file mode 100644 index 0000000000..6855e4e9fe --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/8fa410ffc232e56d0f945bd2b6c34dfe diff --git a/contrib/libs/cctz/tzdata/generated/9006b968810f68ce90473c809b252776 b/contrib/libs/cctz/tzdata/generated/9006b968810f68ce90473c809b252776 Binary files differnew file mode 100644 index 0000000000..231bf9c3b7 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9006b968810f68ce90473c809b252776 diff --git a/contrib/libs/cctz/tzdata/generated/90518d05c449fad639594f7f575407d6 b/contrib/libs/cctz/tzdata/generated/90518d05c449fad639594f7f575407d6 Binary files differnew file mode 100644 index 0000000000..3a0d330ffd --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/90518d05c449fad639594f7f575407d6 diff --git a/contrib/libs/cctz/tzdata/generated/908281291c8446d94306e8ea21b692fa b/contrib/libs/cctz/tzdata/generated/908281291c8446d94306e8ea21b692fa Binary files differnew file mode 100644 index 0000000000..f1555f0032 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/908281291c8446d94306e8ea21b692fa diff --git a/contrib/libs/cctz/tzdata/generated/90db76a975de863aadbcf37b47e18cd2 b/contrib/libs/cctz/tzdata/generated/90db76a975de863aadbcf37b47e18cd2 Binary files differnew file mode 100644 index 0000000000..76e1f6285b --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/90db76a975de863aadbcf37b47e18cd2 diff --git a/contrib/libs/cctz/tzdata/generated/9208172103191bf0d660e0023b358ea1 b/contrib/libs/cctz/tzdata/generated/9208172103191bf0d660e0023b358ea1 Binary files differnew file mode 100644 index 0000000000..6b08d15bda --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9208172103191bf0d660e0023b358ea1 diff --git a/contrib/libs/cctz/tzdata/generated/92d3b867243120ea811c24c038e5b053 b/contrib/libs/cctz/tzdata/generated/92d3b867243120ea811c24c038e5b053 Binary files differnew file mode 100644 index 0000000000..47b4dc3416 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/92d3b867243120ea811c24c038e5b053 diff --git a/contrib/libs/cctz/tzdata/generated/9360bb34802002d91d9bba174c25a8dc b/contrib/libs/cctz/tzdata/generated/9360bb34802002d91d9bba174c25a8dc Binary files differnew file mode 100644 index 0000000000..4c49bbf524 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9360bb34802002d91d9bba174c25a8dc diff --git a/contrib/libs/cctz/tzdata/generated/93ccc0d9fe3d862e546a627982ce5ba7 b/contrib/libs/cctz/tzdata/generated/93ccc0d9fe3d862e546a627982ce5ba7 Binary files differnew file mode 100644 index 0000000000..3fc1f231cb --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/93ccc0d9fe3d862e546a627982ce5ba7 diff --git a/contrib/libs/cctz/tzdata/generated/93e1c90eb5222ffb3eca2a2a29b69a69 b/contrib/libs/cctz/tzdata/generated/93e1c90eb5222ffb3eca2a2a29b69a69 Binary files differnew file mode 100644 index 0000000000..640b259fd0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/93e1c90eb5222ffb3eca2a2a29b69a69 diff --git a/contrib/libs/cctz/tzdata/generated/940f5a339a1f12a7153474fc3c92c624 b/contrib/libs/cctz/tzdata/generated/940f5a339a1f12a7153474fc3c92c624 Binary files differnew file mode 100644 index 0000000000..28136808b6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/940f5a339a1f12a7153474fc3c92c624 diff --git a/contrib/libs/cctz/tzdata/generated/942449c95fb727fb919b341c1dea95a2 b/contrib/libs/cctz/tzdata/generated/942449c95fb727fb919b341c1dea95a2 Binary files differnew file mode 100644 index 0000000000..dfc509570a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/942449c95fb727fb919b341c1dea95a2 diff --git a/contrib/libs/cctz/tzdata/generated/94e0437e48ebbef69b3fb7fe2af5e0f2 b/contrib/libs/cctz/tzdata/generated/94e0437e48ebbef69b3fb7fe2af5e0f2 Binary files differnew file mode 100644 index 0000000000..a16da2c4d5 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/94e0437e48ebbef69b3fb7fe2af5e0f2 diff --git a/contrib/libs/cctz/tzdata/generated/959247e441092255286b22fef107172f b/contrib/libs/cctz/tzdata/generated/959247e441092255286b22fef107172f Binary files differnew file mode 100644 index 0000000000..c65155402d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/959247e441092255286b22fef107172f diff --git a/contrib/libs/cctz/tzdata/generated/95e6699e763f5bd303f05eab455d648b b/contrib/libs/cctz/tzdata/generated/95e6699e763f5bd303f05eab455d648b Binary files differnew file mode 100644 index 0000000000..b22ab147c3 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/95e6699e763f5bd303f05eab455d648b diff --git a/contrib/libs/cctz/tzdata/generated/964fb4bc6d047b2a8826a0734633ab0b b/contrib/libs/cctz/tzdata/generated/964fb4bc6d047b2a8826a0734633ab0b Binary files differnew file mode 100644 index 0000000000..b187d5f8c7 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/964fb4bc6d047b2a8826a0734633ab0b diff --git a/contrib/libs/cctz/tzdata/generated/9766867907fd0631d6357abfcb71fde5 b/contrib/libs/cctz/tzdata/generated/9766867907fd0631d6357abfcb71fde5 Binary files differnew file mode 100644 index 0000000000..ecb287e667 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9766867907fd0631d6357abfcb71fde5 diff --git a/contrib/libs/cctz/tzdata/generated/97ed2cb6ee44823ce8fabdc0beeae2b9 b/contrib/libs/cctz/tzdata/generated/97ed2cb6ee44823ce8fabdc0beeae2b9 Binary files differnew file mode 100644 index 0000000000..23ead1c004 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/97ed2cb6ee44823ce8fabdc0beeae2b9 diff --git a/contrib/libs/cctz/tzdata/generated/992f11daf970c1d1c32d67b8407ba5df b/contrib/libs/cctz/tzdata/generated/992f11daf970c1d1c32d67b8407ba5df Binary files differnew file mode 100644 index 0000000000..e7fccf8296 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/992f11daf970c1d1c32d67b8407ba5df diff --git a/contrib/libs/cctz/tzdata/generated/9aa23335da47827d5ce36afc1523bbd3 b/contrib/libs/cctz/tzdata/generated/9aa23335da47827d5ce36afc1523bbd3 Binary files differnew file mode 100644 index 0000000000..a3ce975991 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9aa23335da47827d5ce36afc1523bbd3 diff --git a/contrib/libs/cctz/tzdata/generated/9ac4de9fb3bcae616f7de40984ccb6b2 b/contrib/libs/cctz/tzdata/generated/9ac4de9fb3bcae616f7de40984ccb6b2 Binary files differnew file mode 100644 index 0000000000..fb7c145ac4 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9ac4de9fb3bcae616f7de40984ccb6b2 diff --git a/contrib/libs/cctz/tzdata/generated/9bc8fb09717950cb4149283c5aff15ac b/contrib/libs/cctz/tzdata/generated/9bc8fb09717950cb4149283c5aff15ac Binary files differnew file mode 100644 index 0000000000..546748d6ea --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9bc8fb09717950cb4149283c5aff15ac diff --git a/contrib/libs/cctz/tzdata/generated/9c4035bc2046d3be368e14a46fc8685d b/contrib/libs/cctz/tzdata/generated/9c4035bc2046d3be368e14a46fc8685d Binary files differnew file mode 100644 index 0000000000..589990ae89 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9c4035bc2046d3be368e14a46fc8685d diff --git a/contrib/libs/cctz/tzdata/generated/9c4211df749eab732ee3f7654b4824e0 b/contrib/libs/cctz/tzdata/generated/9c4211df749eab732ee3f7654b4824e0 Binary files differnew file mode 100644 index 0000000000..7b35793513 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9c4211df749eab732ee3f7654b4824e0 diff --git a/contrib/libs/cctz/tzdata/generated/9d9fdcb5bec6ef7173f20c0b968ae540 b/contrib/libs/cctz/tzdata/generated/9d9fdcb5bec6ef7173f20c0b968ae540 Binary files differnew file mode 100644 index 0000000000..f2136d6ed4 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9d9fdcb5bec6ef7173f20c0b968ae540 diff --git a/contrib/libs/cctz/tzdata/generated/9eaedd2c3574882c46ddbbfeabc5c444 b/contrib/libs/cctz/tzdata/generated/9eaedd2c3574882c46ddbbfeabc5c444 Binary files differnew file mode 100644 index 0000000000..9bdc2283c0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9eaedd2c3574882c46ddbbfeabc5c444 diff --git a/contrib/libs/cctz/tzdata/generated/9f39ae0771032afbfca86630bec12768 b/contrib/libs/cctz/tzdata/generated/9f39ae0771032afbfca86630bec12768 Binary files differnew file mode 100644 index 0000000000..c43e27c5d4 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9f39ae0771032afbfca86630bec12768 diff --git a/contrib/libs/cctz/tzdata/generated/9f69b262e7c296bffc967ca4cd6a4491 b/contrib/libs/cctz/tzdata/generated/9f69b262e7c296bffc967ca4cd6a4491 Binary files differnew file mode 100644 index 0000000000..dea9e3f586 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9f69b262e7c296bffc967ca4cd6a4491 diff --git a/contrib/libs/cctz/tzdata/generated/9f8d9f5acd176a1a163855959b566bb4 b/contrib/libs/cctz/tzdata/generated/9f8d9f5acd176a1a163855959b566bb4 Binary files differnew file mode 100644 index 0000000000..6225036742 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9f8d9f5acd176a1a163855959b566bb4 diff --git a/contrib/libs/cctz/tzdata/generated/9fae53762400421dfbba224c8f21038d b/contrib/libs/cctz/tzdata/generated/9fae53762400421dfbba224c8f21038d Binary files differnew file mode 100644 index 0000000000..4a45ea8f73 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/9fae53762400421dfbba224c8f21038d diff --git a/contrib/libs/cctz/tzdata/generated/a1085ba102822f56191705c405f2a8ad b/contrib/libs/cctz/tzdata/generated/a1085ba102822f56191705c405f2a8ad Binary files differnew file mode 100644 index 0000000000..1975a3a4bd --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a1085ba102822f56191705c405f2a8ad diff --git a/contrib/libs/cctz/tzdata/generated/a1239114e71b76c885dbad8f2fa61de4 b/contrib/libs/cctz/tzdata/generated/a1239114e71b76c885dbad8f2fa61de4 Binary files differnew file mode 100644 index 0000000000..69f0faad1e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a1239114e71b76c885dbad8f2fa61de4 diff --git a/contrib/libs/cctz/tzdata/generated/a181d1167a1dbfc2682f6d4ba9f3c803 b/contrib/libs/cctz/tzdata/generated/a181d1167a1dbfc2682f6d4ba9f3c803 Binary files differnew file mode 100644 index 0000000000..e5f2aec2bb --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a181d1167a1dbfc2682f6d4ba9f3c803 diff --git a/contrib/libs/cctz/tzdata/generated/a23719c2255c2c9829fe6978c1c8ecd7 b/contrib/libs/cctz/tzdata/generated/a23719c2255c2c9829fe6978c1c8ecd7 Binary files differnew file mode 100644 index 0000000000..8700ed9f06 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a23719c2255c2c9829fe6978c1c8ecd7 diff --git a/contrib/libs/cctz/tzdata/generated/a46a56e63a69fd5c5373a33203250d39 b/contrib/libs/cctz/tzdata/generated/a46a56e63a69fd5c5373a33203250d39 Binary files differnew file mode 100644 index 0000000000..bada0638f8 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a46a56e63a69fd5c5373a33203250d39 diff --git a/contrib/libs/cctz/tzdata/generated/a4ac1780d547f4e4c41cab4c6cf1d76d b/contrib/libs/cctz/tzdata/generated/a4ac1780d547f4e4c41cab4c6cf1d76d Binary files differnew file mode 100644 index 0000000000..a1bf9281ed --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a4ac1780d547f4e4c41cab4c6cf1d76d diff --git a/contrib/libs/cctz/tzdata/generated/a4fc7ef39a80ff8875d1cb2708ebc49e b/contrib/libs/cctz/tzdata/generated/a4fc7ef39a80ff8875d1cb2708ebc49e Binary files differnew file mode 100644 index 0000000000..d6f999b860 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a4fc7ef39a80ff8875d1cb2708ebc49e diff --git a/contrib/libs/cctz/tzdata/generated/a59f8bc0dd11620983017647a62ef6f0 b/contrib/libs/cctz/tzdata/generated/a59f8bc0dd11620983017647a62ef6f0 Binary files differnew file mode 100644 index 0000000000..f30dfc7014 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a59f8bc0dd11620983017647a62ef6f0 diff --git a/contrib/libs/cctz/tzdata/generated/a6b8c0b7319f5fdca0ed634760ff6e3b b/contrib/libs/cctz/tzdata/generated/a6b8c0b7319f5fdca0ed634760ff6e3b Binary files differnew file mode 100644 index 0000000000..e0c89971aa --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a6b8c0b7319f5fdca0ed634760ff6e3b diff --git a/contrib/libs/cctz/tzdata/generated/a749ae7552f77178b9eeff2d31ba0e30 b/contrib/libs/cctz/tzdata/generated/a749ae7552f77178b9eeff2d31ba0e30 Binary files differnew file mode 100644 index 0000000000..8283239eca --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a749ae7552f77178b9eeff2d31ba0e30 diff --git a/contrib/libs/cctz/tzdata/generated/a79c9f48310a80244f2065d08f09f91a b/contrib/libs/cctz/tzdata/generated/a79c9f48310a80244f2065d08f09f91a Binary files differnew file mode 100644 index 0000000000..fcb60ca246 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a79c9f48310a80244f2065d08f09f91a diff --git a/contrib/libs/cctz/tzdata/generated/a7d9f2c43b6cd330e6b243c2ff119e61 b/contrib/libs/cctz/tzdata/generated/a7d9f2c43b6cd330e6b243c2ff119e61 Binary files differnew file mode 100644 index 0000000000..88a6f3bdb4 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a7d9f2c43b6cd330e6b243c2ff119e61 diff --git a/contrib/libs/cctz/tzdata/generated/a813cd94645ca8774632d328080f8d97 b/contrib/libs/cctz/tzdata/generated/a813cd94645ca8774632d328080f8d97 Binary files differnew file mode 100644 index 0000000000..160a53e045 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a813cd94645ca8774632d328080f8d97 diff --git a/contrib/libs/cctz/tzdata/generated/a87061b72790e27d9f155644521d8cce b/contrib/libs/cctz/tzdata/generated/a87061b72790e27d9f155644521d8cce Binary files differnew file mode 100644 index 0000000000..651e5cf67a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a87061b72790e27d9f155644521d8cce diff --git a/contrib/libs/cctz/tzdata/generated/a99947596517f6c6087eddf73a7fca24 b/contrib/libs/cctz/tzdata/generated/a99947596517f6c6087eddf73a7fca24 Binary files differnew file mode 100644 index 0000000000..878b6a92f7 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a99947596517f6c6087eddf73a7fca24 diff --git a/contrib/libs/cctz/tzdata/generated/a9b6712f7efd08406ebb3f4a43bf1862 b/contrib/libs/cctz/tzdata/generated/a9b6712f7efd08406ebb3f4a43bf1862 Binary files differnew file mode 100644 index 0000000000..e347b369f7 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/a9b6712f7efd08406ebb3f4a43bf1862 diff --git a/contrib/libs/cctz/tzdata/generated/aa81c590ec60e26984a4be2979a548cc b/contrib/libs/cctz/tzdata/generated/aa81c590ec60e26984a4be2979a548cc Binary files differnew file mode 100644 index 0000000000..5c9a20b947 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/aa81c590ec60e26984a4be2979a548cc diff --git a/contrib/libs/cctz/tzdata/generated/ab10b4ee8dbac84167032fed4b886f05 b/contrib/libs/cctz/tzdata/generated/ab10b4ee8dbac84167032fed4b886f05 Binary files differnew file mode 100644 index 0000000000..143a1883b0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ab10b4ee8dbac84167032fed4b886f05 diff --git a/contrib/libs/cctz/tzdata/generated/ace635d426a79002a8e3657033da7795 b/contrib/libs/cctz/tzdata/generated/ace635d426a79002a8e3657033da7795 Binary files differnew file mode 100644 index 0000000000..e0d7653c64 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ace635d426a79002a8e3657033da7795 diff --git a/contrib/libs/cctz/tzdata/generated/acf014221290656a061fff7e9fa818ee b/contrib/libs/cctz/tzdata/generated/acf014221290656a061fff7e9fa818ee Binary files differnew file mode 100644 index 0000000000..8a4ba4d30a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/acf014221290656a061fff7e9fa818ee diff --git a/contrib/libs/cctz/tzdata/generated/ade2a36e23a06174c36b6fd5d795e865 b/contrib/libs/cctz/tzdata/generated/ade2a36e23a06174c36b6fd5d795e865 Binary files differnew file mode 100644 index 0000000000..e136690e16 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ade2a36e23a06174c36b6fd5d795e865 diff --git a/contrib/libs/cctz/tzdata/generated/aecc05607e312ffdbdf3a8f07ac64a6b b/contrib/libs/cctz/tzdata/generated/aecc05607e312ffdbdf3a8f07ac64a6b Binary files differnew file mode 100644 index 0000000000..ff5e565305 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/aecc05607e312ffdbdf3a8f07ac64a6b diff --git a/contrib/libs/cctz/tzdata/generated/aed64fc971bc7aa23cab042415d57d53 b/contrib/libs/cctz/tzdata/generated/aed64fc971bc7aa23cab042415d57d53 Binary files differnew file mode 100644 index 0000000000..30d3a672bf --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/aed64fc971bc7aa23cab042415d57d53 diff --git a/contrib/libs/cctz/tzdata/generated/af3038d5a348ad35e154a52d14029434 b/contrib/libs/cctz/tzdata/generated/af3038d5a348ad35e154a52d14029434 Binary files differnew file mode 100644 index 0000000000..8f83cefbcc --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/af3038d5a348ad35e154a52d14029434 diff --git a/contrib/libs/cctz/tzdata/generated/af82eec1529bf616942df14b2ffb4403 b/contrib/libs/cctz/tzdata/generated/af82eec1529bf616942df14b2ffb4403 Binary files differnew file mode 100644 index 0000000000..3a40d1175a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/af82eec1529bf616942df14b2ffb4403 diff --git a/contrib/libs/cctz/tzdata/generated/afaa4c77a1e912306f4ca578c933d4a6 b/contrib/libs/cctz/tzdata/generated/afaa4c77a1e912306f4ca578c933d4a6 Binary files differnew file mode 100644 index 0000000000..b7b30213e1 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/afaa4c77a1e912306f4ca578c933d4a6 diff --git a/contrib/libs/cctz/tzdata/generated/b14ab0a98fb1964def4eaf00d2a6bb73 b/contrib/libs/cctz/tzdata/generated/b14ab0a98fb1964def4eaf00d2a6bb73 Binary files differnew file mode 100644 index 0000000000..323cd3818a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/b14ab0a98fb1964def4eaf00d2a6bb73 diff --git a/contrib/libs/cctz/tzdata/generated/b22b7be8696db5ca60fb0b7bba4c8718 b/contrib/libs/cctz/tzdata/generated/b22b7be8696db5ca60fb0b7bba4c8718 Binary files differnew file mode 100644 index 0000000000..336f932e8d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/b22b7be8696db5ca60fb0b7bba4c8718 diff --git a/contrib/libs/cctz/tzdata/generated/b33eb6506380f950ad798d4d788d136a b/contrib/libs/cctz/tzdata/generated/b33eb6506380f950ad798d4d788d136a Binary files differnew file mode 100644 index 0000000000..3ae9691145 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/b33eb6506380f950ad798d4d788d136a diff --git a/contrib/libs/cctz/tzdata/generated/b3c87245083e0474ed4ce3d23abb7f4f b/contrib/libs/cctz/tzdata/generated/b3c87245083e0474ed4ce3d23abb7f4f Binary files differnew file mode 100644 index 0000000000..38036a3283 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/b3c87245083e0474ed4ce3d23abb7f4f diff --git a/contrib/libs/cctz/tzdata/generated/b4aa5f2b966a76ebc38d1aab44d86bce b/contrib/libs/cctz/tzdata/generated/b4aa5f2b966a76ebc38d1aab44d86bce Binary files differnew file mode 100644 index 0000000000..0edc72cfe4 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/b4aa5f2b966a76ebc38d1aab44d86bce diff --git a/contrib/libs/cctz/tzdata/generated/b61230343294608431fbbd939bb6971d b/contrib/libs/cctz/tzdata/generated/b61230343294608431fbbd939bb6971d Binary files differnew file mode 100644 index 0000000000..3ec32224f2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/b61230343294608431fbbd939bb6971d diff --git a/contrib/libs/cctz/tzdata/generated/b6fc5775917cac51306de9bf93d87827 b/contrib/libs/cctz/tzdata/generated/b6fc5775917cac51306de9bf93d87827 Binary files differnew file mode 100644 index 0000000000..28d2c56e1a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/b6fc5775917cac51306de9bf93d87827 diff --git a/contrib/libs/cctz/tzdata/generated/b72620d427a1898ea97232aeba51c2dc b/contrib/libs/cctz/tzdata/generated/b72620d427a1898ea97232aeba51c2dc Binary files differnew file mode 100644 index 0000000000..becf438330 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/b72620d427a1898ea97232aeba51c2dc diff --git a/contrib/libs/cctz/tzdata/generated/b7ad70caecef25e4a9ba1e5afd95fe25 b/contrib/libs/cctz/tzdata/generated/b7ad70caecef25e4a9ba1e5afd95fe25 Binary files differnew file mode 100644 index 0000000000..8f7de1c0a1 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/b7ad70caecef25e4a9ba1e5afd95fe25 diff --git a/contrib/libs/cctz/tzdata/generated/b7e741f6da031513afb238caed64c51b b/contrib/libs/cctz/tzdata/generated/b7e741f6da031513afb238caed64c51b Binary files differnew file mode 100644 index 0000000000..c828715283 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/b7e741f6da031513afb238caed64c51b diff --git a/contrib/libs/cctz/tzdata/generated/b85d659fabeeb1257ade1f6282a5ec7d b/contrib/libs/cctz/tzdata/generated/b85d659fabeeb1257ade1f6282a5ec7d Binary files differnew file mode 100644 index 0000000000..abc75ea7ef --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/b85d659fabeeb1257ade1f6282a5ec7d diff --git a/contrib/libs/cctz/tzdata/generated/b8c39bf52aaa707c58a301ce115ee576 b/contrib/libs/cctz/tzdata/generated/b8c39bf52aaa707c58a301ce115ee576 Binary files differnew file mode 100644 index 0000000000..f38dc56bf2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/b8c39bf52aaa707c58a301ce115ee576 diff --git a/contrib/libs/cctz/tzdata/generated/ba0134eab8c956f482f642c6a5440ee0 b/contrib/libs/cctz/tzdata/generated/ba0134eab8c956f482f642c6a5440ee0 Binary files differnew file mode 100644 index 0000000000..f4c5d5cc29 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ba0134eab8c956f482f642c6a5440ee0 diff --git a/contrib/libs/cctz/tzdata/generated/ba8d62a6ed66f462087e00ad76f7354d b/contrib/libs/cctz/tzdata/generated/ba8d62a6ed66f462087e00ad76f7354d Binary files differnew file mode 100644 index 0000000000..6bc216823e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ba8d62a6ed66f462087e00ad76f7354d diff --git a/contrib/libs/cctz/tzdata/generated/bbb3263234960c35b55fffa1327cc48c b/contrib/libs/cctz/tzdata/generated/bbb3263234960c35b55fffa1327cc48c Binary files differnew file mode 100644 index 0000000000..59c952ebc6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/bbb3263234960c35b55fffa1327cc48c diff --git a/contrib/libs/cctz/tzdata/generated/bc409b8b43f53e38abc4c7a220519f49 b/contrib/libs/cctz/tzdata/generated/bc409b8b43f53e38abc4c7a220519f49 Binary files differnew file mode 100644 index 0000000000..117503410c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/bc409b8b43f53e38abc4c7a220519f49 diff --git a/contrib/libs/cctz/tzdata/generated/bc58930f92342790d3ee214524808faa b/contrib/libs/cctz/tzdata/generated/bc58930f92342790d3ee214524808faa Binary files differnew file mode 100644 index 0000000000..c998491112 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/bc58930f92342790d3ee214524808faa diff --git a/contrib/libs/cctz/tzdata/generated/bcf8aa818432d7ae244087c7306bcb23 b/contrib/libs/cctz/tzdata/generated/bcf8aa818432d7ae244087c7306bcb23 Binary files differnew file mode 100644 index 0000000000..5d8fc3a1b2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/bcf8aa818432d7ae244087c7306bcb23 diff --git a/contrib/libs/cctz/tzdata/generated/bd9c4fdf467f96ab33dde64bf0ac700c b/contrib/libs/cctz/tzdata/generated/bd9c4fdf467f96ab33dde64bf0ac700c Binary files differnew file mode 100644 index 0000000000..b643c5517f --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/bd9c4fdf467f96ab33dde64bf0ac700c diff --git a/contrib/libs/cctz/tzdata/generated/bddbe9d355e1ed5dd3a4276dafe820f0 b/contrib/libs/cctz/tzdata/generated/bddbe9d355e1ed5dd3a4276dafe820f0 Binary files differnew file mode 100644 index 0000000000..ebd85d0f3e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/bddbe9d355e1ed5dd3a4276dafe820f0 diff --git a/contrib/libs/cctz/tzdata/generated/bde0fe003b2df5121f0d31d3954095a6 b/contrib/libs/cctz/tzdata/generated/bde0fe003b2df5121f0d31d3954095a6 Binary files differnew file mode 100644 index 0000000000..96203d7a42 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/bde0fe003b2df5121f0d31d3954095a6 diff --git a/contrib/libs/cctz/tzdata/generated/beb20df2d2d5e3e5f5f50fb2da2a4782 b/contrib/libs/cctz/tzdata/generated/beb20df2d2d5e3e5f5f50fb2da2a4782 Binary files differnew file mode 100644 index 0000000000..c210d0a598 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/beb20df2d2d5e3e5f5f50fb2da2a4782 diff --git a/contrib/libs/cctz/tzdata/generated/beb91df50b24718aed963a509c0c2958 b/contrib/libs/cctz/tzdata/generated/beb91df50b24718aed963a509c0c2958 Binary files differnew file mode 100644 index 0000000000..645ee94530 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/beb91df50b24718aed963a509c0c2958 diff --git a/contrib/libs/cctz/tzdata/generated/bf388a0a1da2be989c25dbfb587076d8 b/contrib/libs/cctz/tzdata/generated/bf388a0a1da2be989c25dbfb587076d8 Binary files differnew file mode 100644 index 0000000000..59bc6e40b7 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/bf388a0a1da2be989c25dbfb587076d8 diff --git a/contrib/libs/cctz/tzdata/generated/bfd18d52a4546531e2f3112725f092d3 b/contrib/libs/cctz/tzdata/generated/bfd18d52a4546531e2f3112725f092d3 Binary files differnew file mode 100644 index 0000000000..a3bf7f29b6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/bfd18d52a4546531e2f3112725f092d3 diff --git a/contrib/libs/cctz/tzdata/generated/c1b9655d5b1ce7fbc9ac213e921acc88 b/contrib/libs/cctz/tzdata/generated/c1b9655d5b1ce7fbc9ac213e921acc88 Binary files differnew file mode 100644 index 0000000000..09e54e5c7c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c1b9655d5b1ce7fbc9ac213e921acc88 diff --git a/contrib/libs/cctz/tzdata/generated/c4545a4f0d97801a69ba19bd8f1d89b9 b/contrib/libs/cctz/tzdata/generated/c4545a4f0d97801a69ba19bd8f1d89b9 Binary files differnew file mode 100644 index 0000000000..9d3afa6a53 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c4545a4f0d97801a69ba19bd8f1d89b9 diff --git a/contrib/libs/cctz/tzdata/generated/c46a3b3c120085251d04dd583a06b6a4 b/contrib/libs/cctz/tzdata/generated/c46a3b3c120085251d04dd583a06b6a4 Binary files differnew file mode 100644 index 0000000000..aeb733202a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c46a3b3c120085251d04dd583a06b6a4 diff --git a/contrib/libs/cctz/tzdata/generated/c4aa97ffb42eeeb70479979e2050d866 b/contrib/libs/cctz/tzdata/generated/c4aa97ffb42eeeb70479979e2050d866 Binary files differnew file mode 100644 index 0000000000..2684d8f8b8 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c4aa97ffb42eeeb70479979e2050d866 diff --git a/contrib/libs/cctz/tzdata/generated/c57843caa48aa4715344a26830df1f13 b/contrib/libs/cctz/tzdata/generated/c57843caa48aa4715344a26830df1f13 Binary files differnew file mode 100644 index 0000000000..639ca3be40 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c57843caa48aa4715344a26830df1f13 diff --git a/contrib/libs/cctz/tzdata/generated/c68faf20645ecd953e8eb2fb70469f59 b/contrib/libs/cctz/tzdata/generated/c68faf20645ecd953e8eb2fb70469f59 Binary files differnew file mode 100644 index 0000000000..8482167269 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c68faf20645ecd953e8eb2fb70469f59 diff --git a/contrib/libs/cctz/tzdata/generated/c72131eaa200e2aa58e1c12fe94f1f67 b/contrib/libs/cctz/tzdata/generated/c72131eaa200e2aa58e1c12fe94f1f67 Binary files differnew file mode 100644 index 0000000000..25a63ec8b9 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c72131eaa200e2aa58e1c12fe94f1f67 diff --git a/contrib/libs/cctz/tzdata/generated/c72cd4fac2e9b8659f6b5bb2392b9ae5 b/contrib/libs/cctz/tzdata/generated/c72cd4fac2e9b8659f6b5bb2392b9ae5 Binary files differnew file mode 100644 index 0000000000..092e40d701 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c72cd4fac2e9b8659f6b5bb2392b9ae5 diff --git a/contrib/libs/cctz/tzdata/generated/c7660bd5c4dc928d402bcba06e35f5f2 b/contrib/libs/cctz/tzdata/generated/c7660bd5c4dc928d402bcba06e35f5f2 Binary files differnew file mode 100644 index 0000000000..92e2ed2dbe --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c7660bd5c4dc928d402bcba06e35f5f2 diff --git a/contrib/libs/cctz/tzdata/generated/c7f10bbd9cbe1c4dd65b3e7b11f70d37 b/contrib/libs/cctz/tzdata/generated/c7f10bbd9cbe1c4dd65b3e7b11f70d37 Binary files differnew file mode 100644 index 0000000000..eb2c99cca5 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c7f10bbd9cbe1c4dd65b3e7b11f70d37 diff --git a/contrib/libs/cctz/tzdata/generated/c87b8b428cfdf54309e9503177e0ca5f b/contrib/libs/cctz/tzdata/generated/c87b8b428cfdf54309e9503177e0ca5f Binary files differnew file mode 100644 index 0000000000..a3f8217a54 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c87b8b428cfdf54309e9503177e0ca5f diff --git a/contrib/libs/cctz/tzdata/generated/c8c41a468e356c6bb65e89c69e4406dc b/contrib/libs/cctz/tzdata/generated/c8c41a468e356c6bb65e89c69e4406dc Binary files differnew file mode 100644 index 0000000000..5990010b64 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c8c41a468e356c6bb65e89c69e4406dc diff --git a/contrib/libs/cctz/tzdata/generated/c9dc6215d6b86ea9232f62c276c48833 b/contrib/libs/cctz/tzdata/generated/c9dc6215d6b86ea9232f62c276c48833 Binary files differnew file mode 100644 index 0000000000..2451aca76d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/c9dc6215d6b86ea9232f62c276c48833 diff --git a/contrib/libs/cctz/tzdata/generated/cbff2e606d3feafa5997dab0f3742e13 b/contrib/libs/cctz/tzdata/generated/cbff2e606d3feafa5997dab0f3742e13 Binary files differnew file mode 100644 index 0000000000..d3b0ca12c9 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/cbff2e606d3feafa5997dab0f3742e13 diff --git a/contrib/libs/cctz/tzdata/generated/cc7e35a2df60f44003b96877116f4d93 b/contrib/libs/cctz/tzdata/generated/cc7e35a2df60f44003b96877116f4d93 Binary files differnew file mode 100644 index 0000000000..305abcb8a2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/cc7e35a2df60f44003b96877116f4d93 diff --git a/contrib/libs/cctz/tzdata/generated/ccc5a76bcf9b46bc41f3ffb232850bbb b/contrib/libs/cctz/tzdata/generated/ccc5a76bcf9b46bc41f3ffb232850bbb Binary files differnew file mode 100644 index 0000000000..d18cedd524 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ccc5a76bcf9b46bc41f3ffb232850bbb diff --git a/contrib/libs/cctz/tzdata/generated/cea8767711bc79a4ec192e25706de5a5 b/contrib/libs/cctz/tzdata/generated/cea8767711bc79a4ec192e25706de5a5 Binary files differnew file mode 100644 index 0000000000..7c11134882 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/cea8767711bc79a4ec192e25706de5a5 diff --git a/contrib/libs/cctz/tzdata/generated/d00638c4bf95fabcc0c651f13e32e253 b/contrib/libs/cctz/tzdata/generated/d00638c4bf95fabcc0c651f13e32e253 Binary files differnew file mode 100644 index 0000000000..3f8e44b8a6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d00638c4bf95fabcc0c651f13e32e253 diff --git a/contrib/libs/cctz/tzdata/generated/d04546b33aa2a7b0a390fed538eb39ec b/contrib/libs/cctz/tzdata/generated/d04546b33aa2a7b0a390fed538eb39ec Binary files differnew file mode 100644 index 0000000000..b92b254a9a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d04546b33aa2a7b0a390fed538eb39ec diff --git a/contrib/libs/cctz/tzdata/generated/d155718faacae2f6288b0c88e66f851c b/contrib/libs/cctz/tzdata/generated/d155718faacae2f6288b0c88e66f851c Binary files differnew file mode 100644 index 0000000000..7fdee5cbee --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d155718faacae2f6288b0c88e66f851c diff --git a/contrib/libs/cctz/tzdata/generated/d1c5195eed8efac077678d1c6d988f7f b/contrib/libs/cctz/tzdata/generated/d1c5195eed8efac077678d1c6d988f7f Binary files differnew file mode 100644 index 0000000000..6dd927cb94 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d1c5195eed8efac077678d1c6d988f7f diff --git a/contrib/libs/cctz/tzdata/generated/d3ca7527ee42255559acf2d74d749d00 b/contrib/libs/cctz/tzdata/generated/d3ca7527ee42255559acf2d74d749d00 Binary files differnew file mode 100644 index 0000000000..166e4341d6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d3ca7527ee42255559acf2d74d749d00 diff --git a/contrib/libs/cctz/tzdata/generated/d3dbc4b002cc7a0e5761a3097651309a b/contrib/libs/cctz/tzdata/generated/d3dbc4b002cc7a0e5761a3097651309a Binary files differnew file mode 100644 index 0000000000..7f8047d939 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d3dbc4b002cc7a0e5761a3097651309a diff --git a/contrib/libs/cctz/tzdata/generated/d3dfd69107a4d78facbc67c4d8cea004 b/contrib/libs/cctz/tzdata/generated/d3dfd69107a4d78facbc67c4d8cea004 Binary files differnew file mode 100644 index 0000000000..c22f75e42d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d3dfd69107a4d78facbc67c4d8cea004 diff --git a/contrib/libs/cctz/tzdata/generated/d40107fc4f4515f2f2eed25a1ca88fb8 b/contrib/libs/cctz/tzdata/generated/d40107fc4f4515f2f2eed25a1ca88fb8 Binary files differnew file mode 100644 index 0000000000..e941412971 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d40107fc4f4515f2f2eed25a1ca88fb8 diff --git a/contrib/libs/cctz/tzdata/generated/d41b1974e5ec6b3bc790062a97894a37 b/contrib/libs/cctz/tzdata/generated/d41b1974e5ec6b3bc790062a97894a37 Binary files differnew file mode 100644 index 0000000000..3eeb1b72b6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d41b1974e5ec6b3bc790062a97894a37 diff --git a/contrib/libs/cctz/tzdata/generated/d44a4791346a5defc84c6bec9e52645d b/contrib/libs/cctz/tzdata/generated/d44a4791346a5defc84c6bec9e52645d Binary files differnew file mode 100644 index 0000000000..efe1a40f2a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d44a4791346a5defc84c6bec9e52645d diff --git a/contrib/libs/cctz/tzdata/generated/d5464310b37a30d92f5b85d128dd4937 b/contrib/libs/cctz/tzdata/generated/d5464310b37a30d92f5b85d128dd4937 Binary files differnew file mode 100644 index 0000000000..dc9a980a65 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d5464310b37a30d92f5b85d128dd4937 diff --git a/contrib/libs/cctz/tzdata/generated/d5fbcb2deb7db9a359b6b092bbdda3fe b/contrib/libs/cctz/tzdata/generated/d5fbcb2deb7db9a359b6b092bbdda3fe Binary files differnew file mode 100644 index 0000000000..36b05220ac --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d5fbcb2deb7db9a359b6b092bbdda3fe diff --git a/contrib/libs/cctz/tzdata/generated/d62d0d008574b60d70899d22545eb1f9 b/contrib/libs/cctz/tzdata/generated/d62d0d008574b60d70899d22545eb1f9 Binary files differnew file mode 100644 index 0000000000..6970b14c50 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d62d0d008574b60d70899d22545eb1f9 diff --git a/contrib/libs/cctz/tzdata/generated/d6de93e1ea78ccfaf37089631a603c39 b/contrib/libs/cctz/tzdata/generated/d6de93e1ea78ccfaf37089631a603c39 Binary files differnew file mode 100644 index 0000000000..e67b411b9f --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d6de93e1ea78ccfaf37089631a603c39 diff --git a/contrib/libs/cctz/tzdata/generated/d8977a620cda17fb8da4421e6c474f0c b/contrib/libs/cctz/tzdata/generated/d8977a620cda17fb8da4421e6c474f0c Binary files differnew file mode 100644 index 0000000000..7c667093c5 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d8977a620cda17fb8da4421e6c474f0c diff --git a/contrib/libs/cctz/tzdata/generated/d8af0cadc03a3813b866bbfeb041e167 b/contrib/libs/cctz/tzdata/generated/d8af0cadc03a3813b866bbfeb041e167 Binary files differnew file mode 100644 index 0000000000..98d5dcf917 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d8af0cadc03a3813b866bbfeb041e167 diff --git a/contrib/libs/cctz/tzdata/generated/d917645873cf9c7577ce2fdbe05963cb b/contrib/libs/cctz/tzdata/generated/d917645873cf9c7577ce2fdbe05963cb Binary files differnew file mode 100644 index 0000000000..26af4c90b3 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/d917645873cf9c7577ce2fdbe05963cb diff --git a/contrib/libs/cctz/tzdata/generated/da5aae5f9a71de05b4625f74b007c461 b/contrib/libs/cctz/tzdata/generated/da5aae5f9a71de05b4625f74b007c461 Binary files differnew file mode 100644 index 0000000000..1755147fab --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/da5aae5f9a71de05b4625f74b007c461 diff --git a/contrib/libs/cctz/tzdata/generated/da87d45f88e4684903d7dbb5b7ed08dc b/contrib/libs/cctz/tzdata/generated/da87d45f88e4684903d7dbb5b7ed08dc Binary files differnew file mode 100644 index 0000000000..56a4dd2a19 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/da87d45f88e4684903d7dbb5b7ed08dc diff --git a/contrib/libs/cctz/tzdata/generated/dada91f7db29bcab55bfd2478a5b0779 b/contrib/libs/cctz/tzdata/generated/dada91f7db29bcab55bfd2478a5b0779 Binary files differnew file mode 100644 index 0000000000..381ae6c463 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/dada91f7db29bcab55bfd2478a5b0779 diff --git a/contrib/libs/cctz/tzdata/generated/db536e94d95836d7c5725c3b3c086586 b/contrib/libs/cctz/tzdata/generated/db536e94d95836d7c5725c3b3c086586 Binary files differnew file mode 100644 index 0000000000..c2bd2f949b --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/db536e94d95836d7c5725c3b3c086586 diff --git a/contrib/libs/cctz/tzdata/generated/dc3ec90d1f373e27ab30f8ede132593d b/contrib/libs/cctz/tzdata/generated/dc3ec90d1f373e27ab30f8ede132593d Binary files differnew file mode 100644 index 0000000000..aeda06b522 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/dc3ec90d1f373e27ab30f8ede132593d diff --git a/contrib/libs/cctz/tzdata/generated/dc74e10d17659800407d742d3a5db22b b/contrib/libs/cctz/tzdata/generated/dc74e10d17659800407d742d3a5db22b Binary files differnew file mode 100644 index 0000000000..cb2c82f657 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/dc74e10d17659800407d742d3a5db22b diff --git a/contrib/libs/cctz/tzdata/generated/dced2b01cc7c29f0b1adf9c62f8603fd b/contrib/libs/cctz/tzdata/generated/dced2b01cc7c29f0b1adf9c62f8603fd Binary files differnew file mode 100644 index 0000000000..13aef80cbb --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/dced2b01cc7c29f0b1adf9c62f8603fd diff --git a/contrib/libs/cctz/tzdata/generated/deb70d248017e650da793ee281723de4 b/contrib/libs/cctz/tzdata/generated/deb70d248017e650da793ee281723de4 Binary files differnew file mode 100644 index 0000000000..97d80d752c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/deb70d248017e650da793ee281723de4 diff --git a/contrib/libs/cctz/tzdata/generated/dff9cd919f10d25842d1381cdff9f7f7 b/contrib/libs/cctz/tzdata/generated/dff9cd919f10d25842d1381cdff9f7f7 Binary files differnew file mode 100644 index 0000000000..d6b66984a2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/dff9cd919f10d25842d1381cdff9f7f7 diff --git a/contrib/libs/cctz/tzdata/generated/e0185725b852fe59ef8e5fef9f619990 b/contrib/libs/cctz/tzdata/generated/e0185725b852fe59ef8e5fef9f619990 Binary files differnew file mode 100644 index 0000000000..9080f5cdb1 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e0185725b852fe59ef8e5fef9f619990 diff --git a/contrib/libs/cctz/tzdata/generated/e019dabd72a8783f7d4b4c1fe3dd5c11 b/contrib/libs/cctz/tzdata/generated/e019dabd72a8783f7d4b4c1fe3dd5c11 Binary files differnew file mode 100644 index 0000000000..0ec4756470 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e019dabd72a8783f7d4b4c1fe3dd5c11 diff --git a/contrib/libs/cctz/tzdata/generated/e0e8162a9ade838f582c23557e530019 b/contrib/libs/cctz/tzdata/generated/e0e8162a9ade838f582c23557e530019 Binary files differnew file mode 100644 index 0000000000..991d1fae69 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e0e8162a9ade838f582c23557e530019 diff --git a/contrib/libs/cctz/tzdata/generated/e2433648de4223726f2f3cf01953e552 b/contrib/libs/cctz/tzdata/generated/e2433648de4223726f2f3cf01953e552 Binary files differnew file mode 100644 index 0000000000..4bce893003 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e2433648de4223726f2f3cf01953e552 diff --git a/contrib/libs/cctz/tzdata/generated/e243e347098f29868c31d03415863478 b/contrib/libs/cctz/tzdata/generated/e243e347098f29868c31d03415863478 Binary files differnew file mode 100644 index 0000000000..9d69a0ab81 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e243e347098f29868c31d03415863478 diff --git a/contrib/libs/cctz/tzdata/generated/e2d55321af8dab0e0fa2baee7c8bf5b8 b/contrib/libs/cctz/tzdata/generated/e2d55321af8dab0e0fa2baee7c8bf5b8 Binary files differnew file mode 100644 index 0000000000..248a7c93a5 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e2d55321af8dab0e0fa2baee7c8bf5b8 diff --git a/contrib/libs/cctz/tzdata/generated/e308055a9c06f33a854a9d579ed61249 b/contrib/libs/cctz/tzdata/generated/e308055a9c06f33a854a9d579ed61249 Binary files differnew file mode 100644 index 0000000000..d3f195ac2f --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e308055a9c06f33a854a9d579ed61249 diff --git a/contrib/libs/cctz/tzdata/generated/e3467a68822f3d1365e3494970219b03 b/contrib/libs/cctz/tzdata/generated/e3467a68822f3d1365e3494970219b03 Binary files differnew file mode 100644 index 0000000000..1dcc8d8543 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e3467a68822f3d1365e3494970219b03 diff --git a/contrib/libs/cctz/tzdata/generated/e369eb23db7f75930ece7bf91b6b86a7 b/contrib/libs/cctz/tzdata/generated/e369eb23db7f75930ece7bf91b6b86a7 Binary files differnew file mode 100644 index 0000000000..b4dd7735ed --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e369eb23db7f75930ece7bf91b6b86a7 diff --git a/contrib/libs/cctz/tzdata/generated/e442d2de2cc0849a5f375c905d88d9f9 b/contrib/libs/cctz/tzdata/generated/e442d2de2cc0849a5f375c905d88d9f9 Binary files differnew file mode 100644 index 0000000000..0263c90bd0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e442d2de2cc0849a5f375c905d88d9f9 diff --git a/contrib/libs/cctz/tzdata/generated/e4dec087eace60f8b638fff583ec78ca b/contrib/libs/cctz/tzdata/generated/e4dec087eace60f8b638fff583ec78ca Binary files differnew file mode 100644 index 0000000000..7c3a49c0e8 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e4dec087eace60f8b638fff583ec78ca diff --git a/contrib/libs/cctz/tzdata/generated/e5beade2f7db36705f5ca5f05b6c24eb b/contrib/libs/cctz/tzdata/generated/e5beade2f7db36705f5ca5f05b6c24eb Binary files differnew file mode 100644 index 0000000000..2ef2aa8971 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e5beade2f7db36705f5ca5f05b6c24eb diff --git a/contrib/libs/cctz/tzdata/generated/e68c0f2ebe9dc247712393ab1bd168d2 b/contrib/libs/cctz/tzdata/generated/e68c0f2ebe9dc247712393ab1bd168d2 Binary files differnew file mode 100644 index 0000000000..4d4ec8ceea --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e68c0f2ebe9dc247712393ab1bd168d2 diff --git a/contrib/libs/cctz/tzdata/generated/e7577ad74319a942781e7153a97d7690 b/contrib/libs/cctz/tzdata/generated/e7577ad74319a942781e7153a97d7690 Binary files differnew file mode 100644 index 0000000000..157573b1d3 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e7577ad74319a942781e7153a97d7690 diff --git a/contrib/libs/cctz/tzdata/generated/e770be0bb1b43b9bc7df85f9ac184a79 b/contrib/libs/cctz/tzdata/generated/e770be0bb1b43b9bc7df85f9ac184a79 Binary files differnew file mode 100644 index 0000000000..c3c307d7b9 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e770be0bb1b43b9bc7df85f9ac184a79 diff --git a/contrib/libs/cctz/tzdata/generated/e9faa2fda4c9671e5002bf470313be76 b/contrib/libs/cctz/tzdata/generated/e9faa2fda4c9671e5002bf470313be76 Binary files differnew file mode 100644 index 0000000000..743a7337ff --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/e9faa2fda4c9671e5002bf470313be76 diff --git a/contrib/libs/cctz/tzdata/generated/eaa234bf9babed72ac5b25c9a3dffa15 b/contrib/libs/cctz/tzdata/generated/eaa234bf9babed72ac5b25c9a3dffa15 Binary files differnew file mode 100644 index 0000000000..3ec4fc89fe --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/eaa234bf9babed72ac5b25c9a3dffa15 diff --git a/contrib/libs/cctz/tzdata/generated/eac76eb95be7b5cc25a41e0485b58c41 b/contrib/libs/cctz/tzdata/generated/eac76eb95be7b5cc25a41e0485b58c41 Binary files differnew file mode 100644 index 0000000000..9d90e745b0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/eac76eb95be7b5cc25a41e0485b58c41 diff --git a/contrib/libs/cctz/tzdata/generated/ec12549279e64ebeb926579888cf89d9 b/contrib/libs/cctz/tzdata/generated/ec12549279e64ebeb926579888cf89d9 Binary files differnew file mode 100644 index 0000000000..7409d74983 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ec12549279e64ebeb926579888cf89d9 diff --git a/contrib/libs/cctz/tzdata/generated/ec185892bb2764a8280ee41ff8f2b032 b/contrib/libs/cctz/tzdata/generated/ec185892bb2764a8280ee41ff8f2b032 Binary files differnew file mode 100644 index 0000000000..bf9a2d955f --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ec185892bb2764a8280ee41ff8f2b032 diff --git a/contrib/libs/cctz/tzdata/generated/ec589bada56b3352067a359694896292 b/contrib/libs/cctz/tzdata/generated/ec589bada56b3352067a359694896292 Binary files differnew file mode 100644 index 0000000000..43484117e2 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ec589bada56b3352067a359694896292 diff --git a/contrib/libs/cctz/tzdata/generated/ed9b458ec968ade14b1b738136300cf2 b/contrib/libs/cctz/tzdata/generated/ed9b458ec968ade14b1b738136300cf2 Binary files differnew file mode 100644 index 0000000000..b9f67a9f94 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ed9b458ec968ade14b1b738136300cf2 diff --git a/contrib/libs/cctz/tzdata/generated/eda5a4ce01efed633c50e04d09fe73b2 b/contrib/libs/cctz/tzdata/generated/eda5a4ce01efed633c50e04d09fe73b2 Binary files differnew file mode 100644 index 0000000000..35d89d036d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/eda5a4ce01efed633c50e04d09fe73b2 diff --git a/contrib/libs/cctz/tzdata/generated/ef31a488808a56cc6d3c9a3c5a53abeb b/contrib/libs/cctz/tzdata/generated/ef31a488808a56cc6d3c9a3c5a53abeb Binary files differnew file mode 100644 index 0000000000..9fa850a7d4 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ef31a488808a56cc6d3c9a3c5a53abeb diff --git a/contrib/libs/cctz/tzdata/generated/ef4485e168a60d91cc5347e5de9a3407 b/contrib/libs/cctz/tzdata/generated/ef4485e168a60d91cc5347e5de9a3407 Binary files differnew file mode 100644 index 0000000000..e56d5afdaf --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ef4485e168a60d91cc5347e5de9a3407 diff --git a/contrib/libs/cctz/tzdata/generated/ef8eca09259416ea4e1d5b4bb865a645 b/contrib/libs/cctz/tzdata/generated/ef8eca09259416ea4e1d5b4bb865a645 Binary files differnew file mode 100644 index 0000000000..a0953d1e79 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ef8eca09259416ea4e1d5b4bb865a645 diff --git a/contrib/libs/cctz/tzdata/generated/f07474008b0495a1830bf6ec76104684 b/contrib/libs/cctz/tzdata/generated/f07474008b0495a1830bf6ec76104684 Binary files differnew file mode 100644 index 0000000000..3e75731baa --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f07474008b0495a1830bf6ec76104684 diff --git a/contrib/libs/cctz/tzdata/generated/f0976c6697d91943b1d72c331844db50 b/contrib/libs/cctz/tzdata/generated/f0976c6697d91943b1d72c331844db50 Binary files differnew file mode 100644 index 0000000000..efa689ba9e --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f0976c6697d91943b1d72c331844db50 diff --git a/contrib/libs/cctz/tzdata/generated/f104bb3d3ae2809522db434bd995f6a8 b/contrib/libs/cctz/tzdata/generated/f104bb3d3ae2809522db434bd995f6a8 Binary files differnew file mode 100644 index 0000000000..8ce93e0124 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f104bb3d3ae2809522db434bd995f6a8 diff --git a/contrib/libs/cctz/tzdata/generated/f1758852685fee0e701b82aa868fc368 b/contrib/libs/cctz/tzdata/generated/f1758852685fee0e701b82aa868fc368 Binary files differnew file mode 100644 index 0000000000..58e9fdf42d --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f1758852685fee0e701b82aa868fc368 diff --git a/contrib/libs/cctz/tzdata/generated/f32590f9bcdfb4ab134294d441804ae5 b/contrib/libs/cctz/tzdata/generated/f32590f9bcdfb4ab134294d441804ae5 Binary files differnew file mode 100644 index 0000000000..08f0128ee6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f32590f9bcdfb4ab134294d441804ae5 diff --git a/contrib/libs/cctz/tzdata/generated/f3ac587344d641763d27895afbe16345 b/contrib/libs/cctz/tzdata/generated/f3ac587344d641763d27895afbe16345 Binary files differnew file mode 100644 index 0000000000..8b8ce226b6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f3ac587344d641763d27895afbe16345 diff --git a/contrib/libs/cctz/tzdata/generated/f3ce1cb0fb7595deac1b8caa16cae961 b/contrib/libs/cctz/tzdata/generated/f3ce1cb0fb7595deac1b8caa16cae961 Binary files differnew file mode 100644 index 0000000000..72fec9e8c5 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f3ce1cb0fb7595deac1b8caa16cae961 diff --git a/contrib/libs/cctz/tzdata/generated/f41368f5bca111c30ebd65d69f60c627 b/contrib/libs/cctz/tzdata/generated/f41368f5bca111c30ebd65d69f60c627 Binary files differnew file mode 100644 index 0000000000..c779cef92c --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f41368f5bca111c30ebd65d69f60c627 diff --git a/contrib/libs/cctz/tzdata/generated/f44dbe7ca52c5fb8b57e33fd8e094038 b/contrib/libs/cctz/tzdata/generated/f44dbe7ca52c5fb8b57e33fd8e094038 Binary files differnew file mode 100644 index 0000000000..ff6fe61d50 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f44dbe7ca52c5fb8b57e33fd8e094038 diff --git a/contrib/libs/cctz/tzdata/generated/f4cf94e44810f7c25b2529ffe37ab772 b/contrib/libs/cctz/tzdata/generated/f4cf94e44810f7c25b2529ffe37ab772 Binary files differnew file mode 100644 index 0000000000..ddfc34ffc0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f4cf94e44810f7c25b2529ffe37ab772 diff --git a/contrib/libs/cctz/tzdata/generated/f627017649ea589681b7b0dd45c03118 b/contrib/libs/cctz/tzdata/generated/f627017649ea589681b7b0dd45c03118 Binary files differnew file mode 100644 index 0000000000..551884d322 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f627017649ea589681b7b0dd45c03118 diff --git a/contrib/libs/cctz/tzdata/generated/f669833977d5968e30ce9d8288dccd22 b/contrib/libs/cctz/tzdata/generated/f669833977d5968e30ce9d8288dccd22 Binary files differnew file mode 100644 index 0000000000..cd397b02cd --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f669833977d5968e30ce9d8288dccd22 diff --git a/contrib/libs/cctz/tzdata/generated/f729c88451bacd2895fc1c8d29064c46 b/contrib/libs/cctz/tzdata/generated/f729c88451bacd2895fc1c8d29064c46 Binary files differnew file mode 100644 index 0000000000..c80e364801 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f729c88451bacd2895fc1c8d29064c46 diff --git a/contrib/libs/cctz/tzdata/generated/f72cea14be81564422856a5e3633b0f0 b/contrib/libs/cctz/tzdata/generated/f72cea14be81564422856a5e3633b0f0 Binary files differnew file mode 100644 index 0000000000..97b44a9bae --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f72cea14be81564422856a5e3633b0f0 diff --git a/contrib/libs/cctz/tzdata/generated/f789c65f289caa627ea1f690836c48f6 b/contrib/libs/cctz/tzdata/generated/f789c65f289caa627ea1f690836c48f6 Binary files differnew file mode 100644 index 0000000000..001289ceec --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f789c65f289caa627ea1f690836c48f6 diff --git a/contrib/libs/cctz/tzdata/generated/f8be05a9398502fc14e50eea2693497c b/contrib/libs/cctz/tzdata/generated/f8be05a9398502fc14e50eea2693497c Binary files differnew file mode 100644 index 0000000000..8aa8e588e3 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/f8be05a9398502fc14e50eea2693497c diff --git a/contrib/libs/cctz/tzdata/generated/fa85e90a2dcd44ced6128397a99b2668 b/contrib/libs/cctz/tzdata/generated/fa85e90a2dcd44ced6128397a99b2668 Binary files differnew file mode 100644 index 0000000000..ae13aac779 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/fa85e90a2dcd44ced6128397a99b2668 diff --git a/contrib/libs/cctz/tzdata/generated/fb4e7ca8ebc94bf7b651ad1921cb62df b/contrib/libs/cctz/tzdata/generated/fb4e7ca8ebc94bf7b651ad1921cb62df Binary files differnew file mode 100644 index 0000000000..bfc19f4e58 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/fb4e7ca8ebc94bf7b651ad1921cb62df diff --git a/contrib/libs/cctz/tzdata/generated/fb8a999658da8686edc727548949fd88 b/contrib/libs/cctz/tzdata/generated/fb8a999658da8686edc727548949fd88 Binary files differnew file mode 100644 index 0000000000..f5d58242c8 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/fb8a999658da8686edc727548949fd88 diff --git a/contrib/libs/cctz/tzdata/generated/fd46d501559b1cf8c8c1fa330196b1b0 b/contrib/libs/cctz/tzdata/generated/fd46d501559b1cf8c8c1fa330196b1b0 Binary files differnew file mode 100644 index 0000000000..68ddaae768 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/fd46d501559b1cf8c8c1fa330196b1b0 diff --git a/contrib/libs/cctz/tzdata/generated/fdc0ca37b4154de8d27e2347aeb7d0cf b/contrib/libs/cctz/tzdata/generated/fdc0ca37b4154de8d27e2347aeb7d0cf Binary files differnew file mode 100644 index 0000000000..d6ddf7d8f6 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/fdc0ca37b4154de8d27e2347aeb7d0cf diff --git a/contrib/libs/cctz/tzdata/generated/fdc9d5431dd16120c1465f298e28e260 b/contrib/libs/cctz/tzdata/generated/fdc9d5431dd16120c1465f298e28e260 Binary files differnew file mode 100644 index 0000000000..a730fe666b --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/fdc9d5431dd16120c1465f298e28e260 diff --git a/contrib/libs/cctz/tzdata/generated/fde842b2c314abede0d0689355c8803e b/contrib/libs/cctz/tzdata/generated/fde842b2c314abede0d0689355c8803e Binary files differnew file mode 100644 index 0000000000..0a2225244a --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/fde842b2c314abede0d0689355c8803e diff --git a/contrib/libs/cctz/tzdata/generated/fe03dcb43031a0d45d0039e33f1e4c42 b/contrib/libs/cctz/tzdata/generated/fe03dcb43031a0d45d0039e33f1e4c42 Binary files differnew file mode 100644 index 0000000000..75339e98d0 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/fe03dcb43031a0d45d0039e33f1e4c42 diff --git a/contrib/libs/cctz/tzdata/generated/fe54394a3dcf951bad3c293980109dd2 b/contrib/libs/cctz/tzdata/generated/fe54394a3dcf951bad3c293980109dd2 Binary files differnew file mode 100644 index 0000000000..5f4ebcb7f9 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/fe54394a3dcf951bad3c293980109dd2 diff --git a/contrib/libs/cctz/tzdata/generated/fefe5ae6107231a3f738b36d95153f77 b/contrib/libs/cctz/tzdata/generated/fefe5ae6107231a3f738b36d95153f77 Binary files differnew file mode 100644 index 0000000000..7da4b98fe3 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/fefe5ae6107231a3f738b36d95153f77 diff --git a/contrib/libs/cctz/tzdata/generated/ff94f36118acae9ef3e19438688e266b b/contrib/libs/cctz/tzdata/generated/ff94f36118acae9ef3e19438688e266b Binary files differnew file mode 100644 index 0000000000..ed687d2985 --- /dev/null +++ b/contrib/libs/cctz/tzdata/generated/ff94f36118acae9ef3e19438688e266b diff --git a/contrib/libs/cctz/tzdata/update_tzdata.py b/contrib/libs/cctz/tzdata/update_tzdata.py new file mode 100755 index 0000000000..9c3cd07352 --- /dev/null +++ b/contrib/libs/cctz/tzdata/update_tzdata.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python + +import glob +import hashlib +import os +import re +import shutil +import string +import subprocess +import sys +import tarfile +import tempfile +import urllib2 + +def create_cmakelists(zoneinfo_dir): + tz_to_hash = {} + hash_to_content = {} + total_size = 0 + for dirpath, _, filenames in os.walk(zoneinfo_dir): + for fn in filenames: + tz_file_name = os.path.join(dirpath, fn) + with open(tz_file_name) as f: + tz_content = f.read() + if not tz_content.startswith('TZif'): + continue + tz_hash = hashlib.md5(tz_content).hexdigest() + tz_name = tz_file_name.replace(zoneinfo_dir, '').lstrip('/') + tz_to_hash[tz_name] = tz_hash + hash_to_content[tz_hash] = tz_content + total_size += len(tz_content) + print 'Total data size in bytes:', total_size + + generated_dir = 'generated' + if not os.path.isdir(generated_dir): + os.mkdir(generated_dir) + for tz_hash, tz_content in hash_to_content.iteritems(): + with open(os.path.join(generated_dir, tz_hash), 'w') as f: + f.write(tz_content) + + yamake_template = ( + 'RESOURCE(\n' + '{}\n' + ')' + ) + resources = '\n'.join(' generated/{} /cctz/tzdata/{}'.format(tz_hash, tz_name) for tz_name, tz_hash in sorted(tz_to_hash.iteritems())) + + all_hashes = set(tz_to_hash.values()) + hash_pattern = os.path.join('generated', '[{}]'.format(string.hexdigits) * 32) + for fn in glob.glob(hash_pattern): + cmd = 'add' if os.path.basename(fn) in all_hashes else 'remove' + subprocess.check_call(['svn', cmd, '--force', fn]) + + with open('ya.make.resources', 'w') as f: + print >>f, yamake_template.format(resources) + +def get_latest_iana_version(): + index_html = urllib2.urlopen('http://www.iana.org/time-zones').read() + version_match = re.search('<a href="[^"]*">tzdata(.*).tar.gz</a>', index_html) + if not version_match: + raise Exception('Failed to determine the latest tzdata version') + return version_match.group(1) + +def get_current_version(): + try: + with open('VERSION') as f: + return f.read() + except: + return 0 + +def prepare_tzdata(version): + temp_dir = tempfile.mkdtemp() + try: + for file_type in ('data', 'code'): + file_name = 'tz{}{}.tar.gz'.format(file_type, version) + full_url = 'http://www.iana.org/time-zones/repository/releases/{}'.format(file_name) + print 'Downloading {}'.format(full_url) + + local_file_name = os.path.join(temp_dir, file_name) + with open(local_file_name, 'w') as f: + f.write(urllib2.urlopen(full_url).read()) + + print 'Extracting {}'.format(local_file_name) + with tarfile.open(local_file_name) as f: + f.extractall(path=temp_dir) + + print 'Converting tzdata to binary format' + subprocess.check_call(['make', '-s', '-C', temp_dir, 'TOPDIR={}'.format(temp_dir), 'install']) + + print 'Preparing ya.make.resources' + zoneinfo_dir = os.path.join(temp_dir, 'usr', 'share', 'zoneinfo') + create_cmakelists(zoneinfo_dir) + finally: + shutil.rmtree(temp_dir) + +def main(): + current_version, latest_version = get_current_version(), get_latest_iana_version() + print 'The current version of tzdata is {}'.format(current_version) + print 'The latest version of tzdata on the IANA site is {}'.format(latest_version) + if current_version == latest_version: + print 'You already have the latest version' + return + print 'Updating from {} to {}'.format(current_version, latest_version) + prepare_tzdata(latest_version) + + with open('VERSION', 'w') as f: + f.write(latest_version) + + print 'All good! Now make sure the tests pass, and run this:' + print 'svn ci -m "Updated tzdata to {}"'.format(latest_version) + +if __name__ == '__main__': + main() diff --git a/contrib/libs/cctz/tzdata/ya.make b/contrib/libs/cctz/tzdata/ya.make new file mode 100644 index 0000000000..3b9ff5cc67 --- /dev/null +++ b/contrib/libs/cctz/tzdata/ya.make @@ -0,0 +1,22 @@ +LIBRARY() + +WITHOUT_LICENSE_TEXTS() + +LICENSE(Apache-2.0) + +OWNER( + dfyz + petrk +) + +PEERDIR( + contrib/libs/cctz +) + +INCLUDE(ya.make.resources) + +SRCS( + GLOBAL factory.cpp +) + +END() diff --git a/contrib/libs/cctz/tzdata/ya.make.resources b/contrib/libs/cctz/tzdata/ya.make.resources new file mode 100644 index 0000000000..5c7575f3bd --- /dev/null +++ b/contrib/libs/cctz/tzdata/ya.make.resources @@ -0,0 +1,597 @@ +RESOURCE( + generated/58543f30ac34b6510b552b9b3e82b772 /cctz/tzdata/posixrules + generated/796a57137d718e4fa3db8ef611f18e61 /cctz/tzdata/Africa/Abidjan + generated/33cffb9ac13285f945f3c4ef6ce13585 /cctz/tzdata/Africa/Accra + generated/fe54394a3dcf951bad3c293980109dd2 /cctz/tzdata/Africa/Addis_Ababa + generated/da87d45f88e4684903d7dbb5b7ed08dc /cctz/tzdata/Africa/Algiers + generated/fe54394a3dcf951bad3c293980109dd2 /cctz/tzdata/Africa/Asmara + generated/fe54394a3dcf951bad3c293980109dd2 /cctz/tzdata/Africa/Asmera + generated/796a57137d718e4fa3db8ef611f18e61 /cctz/tzdata/Africa/Bamako + generated/89de77d185e9a76612bd5f9fb043a9c2 /cctz/tzdata/Africa/Bangui + generated/796a57137d718e4fa3db8ef611f18e61 /cctz/tzdata/Africa/Banjul + generated/767406f25e6c1c5396e19a3be033304b /cctz/tzdata/Africa/Bissau + generated/a87061b72790e27d9f155644521d8cce /cctz/tzdata/Africa/Blantyre + generated/89de77d185e9a76612bd5f9fb043a9c2 /cctz/tzdata/Africa/Brazzaville + generated/a87061b72790e27d9f155644521d8cce /cctz/tzdata/Africa/Bujumbura + generated/39d0994d5956e55a919f2945ccd7c0bf /cctz/tzdata/Africa/Cairo + generated/e442d2de2cc0849a5f375c905d88d9f9 /cctz/tzdata/Africa/Casablanca + generated/00636062cbcd94f2ead5a75cc197675a /cctz/tzdata/Africa/Ceuta + generated/796a57137d718e4fa3db8ef611f18e61 /cctz/tzdata/Africa/Conakry + generated/796a57137d718e4fa3db8ef611f18e61 /cctz/tzdata/Africa/Dakar + generated/fe54394a3dcf951bad3c293980109dd2 /cctz/tzdata/Africa/Dar_es_Salaam + generated/fe54394a3dcf951bad3c293980109dd2 /cctz/tzdata/Africa/Djibouti + generated/89de77d185e9a76612bd5f9fb043a9c2 /cctz/tzdata/Africa/Douala + generated/247c3c527e0314c20b0c4e76b937c31c /cctz/tzdata/Africa/El_Aaiun + generated/796a57137d718e4fa3db8ef611f18e61 /cctz/tzdata/Africa/Freetown + generated/a87061b72790e27d9f155644521d8cce /cctz/tzdata/Africa/Gaborone + generated/a87061b72790e27d9f155644521d8cce /cctz/tzdata/Africa/Harare + generated/a46a56e63a69fd5c5373a33203250d39 /cctz/tzdata/Africa/Johannesburg + generated/d5fbcb2deb7db9a359b6b092bbdda3fe /cctz/tzdata/Africa/Juba + generated/fe54394a3dcf951bad3c293980109dd2 /cctz/tzdata/Africa/Kampala + generated/d00638c4bf95fabcc0c651f13e32e253 /cctz/tzdata/Africa/Khartoum + generated/a87061b72790e27d9f155644521d8cce /cctz/tzdata/Africa/Kigali + generated/89de77d185e9a76612bd5f9fb043a9c2 /cctz/tzdata/Africa/Kinshasa + generated/89de77d185e9a76612bd5f9fb043a9c2 /cctz/tzdata/Africa/Lagos + generated/89de77d185e9a76612bd5f9fb043a9c2 /cctz/tzdata/Africa/Libreville + generated/796a57137d718e4fa3db8ef611f18e61 /cctz/tzdata/Africa/Lome + generated/89de77d185e9a76612bd5f9fb043a9c2 /cctz/tzdata/Africa/Luanda + generated/a87061b72790e27d9f155644521d8cce /cctz/tzdata/Africa/Lubumbashi + generated/a87061b72790e27d9f155644521d8cce /cctz/tzdata/Africa/Lusaka + generated/89de77d185e9a76612bd5f9fb043a9c2 /cctz/tzdata/Africa/Malabo + generated/a87061b72790e27d9f155644521d8cce /cctz/tzdata/Africa/Maputo + generated/a46a56e63a69fd5c5373a33203250d39 /cctz/tzdata/Africa/Maseru + generated/a46a56e63a69fd5c5373a33203250d39 /cctz/tzdata/Africa/Mbabane + generated/fe54394a3dcf951bad3c293980109dd2 /cctz/tzdata/Africa/Mogadishu + generated/4afacd60281211a6a7530a3ff8062781 /cctz/tzdata/Africa/Monrovia + generated/fe54394a3dcf951bad3c293980109dd2 /cctz/tzdata/Africa/Nairobi + generated/510c0710993f09c4d93d3639ac3fe609 /cctz/tzdata/Africa/Ndjamena + generated/89de77d185e9a76612bd5f9fb043a9c2 /cctz/tzdata/Africa/Niamey + generated/796a57137d718e4fa3db8ef611f18e61 /cctz/tzdata/Africa/Nouakchott + generated/796a57137d718e4fa3db8ef611f18e61 /cctz/tzdata/Africa/Ouagadougou + generated/89de77d185e9a76612bd5f9fb043a9c2 /cctz/tzdata/Africa/Porto-Novo + generated/7353b5d25ddb353ced2f1f9639251c16 /cctz/tzdata/Africa/Sao_Tome + generated/796a57137d718e4fa3db8ef611f18e61 /cctz/tzdata/Africa/Timbuktu + generated/a6b8c0b7319f5fdca0ed634760ff6e3b /cctz/tzdata/Africa/Tripoli + generated/63615364c91acab170ec8f719aa6f59f /cctz/tzdata/Africa/Tunis + generated/3c6db0baa05cea4617bcad88b40b1e6a /cctz/tzdata/Africa/Windhoek + generated/1df7e605c33529940c76c1c145c52fc5 /cctz/tzdata/America/Adak + generated/77ea6e8a582f87d7a397a9e7b2111be0 /cctz/tzdata/America/Anchorage + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/Anguilla + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/Antigua + generated/82840448c9d4782ffa56514a7fb4ca95 /cctz/tzdata/America/Araguaina + generated/a4fc7ef39a80ff8875d1cb2708ebc49e /cctz/tzdata/America/Argentina/Buenos_Aires + generated/e3467a68822f3d1365e3494970219b03 /cctz/tzdata/America/Argentina/Catamarca + generated/e3467a68822f3d1365e3494970219b03 /cctz/tzdata/America/Argentina/ComodRivadavia + generated/5c57dc3d11f5a64fac22a08ea0c64d25 /cctz/tzdata/America/Argentina/Cordoba + generated/239a70724a0ff39d5dd3e6b7f4a34212 /cctz/tzdata/America/Argentina/Jujuy + generated/0e84cda11c5dc9030c43c51187a6c78d /cctz/tzdata/America/Argentina/La_Rioja + generated/839eacc63921f196e4ecfded7245a67b /cctz/tzdata/America/Argentina/Mendoza + generated/e0e8162a9ade838f582c23557e530019 /cctz/tzdata/America/Argentina/Rio_Gallegos + generated/0249d27eff0294ba6c5d090d9895fd17 /cctz/tzdata/America/Argentina/Salta + generated/4a5ba954919a3b34fb7779965387992f /cctz/tzdata/America/Argentina/San_Juan + generated/6413085a3a485b5683da3f49944995f0 /cctz/tzdata/America/Argentina/San_Luis + generated/70483b70b5e389865d462a090b99f2ed /cctz/tzdata/America/Argentina/Tucuman + generated/07844fc101071f657d084ecb7d161aa0 /cctz/tzdata/America/Argentina/Ushuaia + generated/fdc0ca37b4154de8d27e2347aeb7d0cf /cctz/tzdata/America/Aruba + generated/9f8d9f5acd176a1a163855959b566bb4 /cctz/tzdata/America/Asuncion + generated/b7e741f6da031513afb238caed64c51b /cctz/tzdata/America/Atikokan + generated/1df7e605c33529940c76c1c145c52fc5 /cctz/tzdata/America/Atka + generated/1c750fa694668ef0a1aad95b61533b2a /cctz/tzdata/America/Bahia + generated/47cad39dddf1619fc2287b9e98ad20e0 /cctz/tzdata/America/Bahia_Banderas + generated/c4545a4f0d97801a69ba19bd8f1d89b9 /cctz/tzdata/America/Barbados + generated/ace635d426a79002a8e3657033da7795 /cctz/tzdata/America/Belem + generated/fb4e7ca8ebc94bf7b651ad1921cb62df /cctz/tzdata/America/Belize + generated/66cda5383f8d5939a8cd80139a07d855 /cctz/tzdata/America/Blanc-Sablon + generated/30c97d0792df5d5939ff0f09c53c385d /cctz/tzdata/America/Boa_Vista + generated/49547ca54933b45b82497d8ede3b6acc /cctz/tzdata/America/Bogota + generated/f3ce1cb0fb7595deac1b8caa16cae961 /cctz/tzdata/America/Boise + generated/a4fc7ef39a80ff8875d1cb2708ebc49e /cctz/tzdata/America/Buenos_Aires + generated/fde842b2c314abede0d0689355c8803e /cctz/tzdata/America/Cambridge_Bay + generated/8fa410ffc232e56d0f945bd2b6c34dfe /cctz/tzdata/America/Campo_Grande + generated/93e1c90eb5222ffb3eca2a2a29b69a69 /cctz/tzdata/America/Cancun + generated/4d7ff90583dcd0e08fc8c51792761c2b /cctz/tzdata/America/Caracas + generated/e3467a68822f3d1365e3494970219b03 /cctz/tzdata/America/Catamarca + generated/806c5856106eb6b28c3846dd93d3acc4 /cctz/tzdata/America/Cayenne + generated/595e67b4c97fda031a90e5ef80813e7d /cctz/tzdata/America/Cayman + generated/85435a33486747b319872947c68317f3 /cctz/tzdata/America/Chicago + generated/138f1cfa1b7558ef69bddd0870f7000d /cctz/tzdata/America/Chihuahua + generated/b7e741f6da031513afb238caed64c51b /cctz/tzdata/America/Coral_Harbour + generated/5c57dc3d11f5a64fac22a08ea0c64d25 /cctz/tzdata/America/Cordoba + generated/f32590f9bcdfb4ab134294d441804ae5 /cctz/tzdata/America/Costa_Rica + generated/e243e347098f29868c31d03415863478 /cctz/tzdata/America/Creston + generated/268c9a38823e18c714ec9fb756a8042e /cctz/tzdata/America/Cuiaba + generated/fdc0ca37b4154de8d27e2347aeb7d0cf /cctz/tzdata/America/Curacao + generated/356ff8bd249ee3f6983cba8426901244 /cctz/tzdata/America/Danmarkshavn + generated/79eedb7a0a4788b9bc3c291c4c643b50 /cctz/tzdata/America/Dawson + generated/6ece595060d1d2db3153c5d523fb106b /cctz/tzdata/America/Dawson_Creek + generated/c1b9655d5b1ce7fbc9ac213e921acc88 /cctz/tzdata/America/Denver + generated/48c96bff46ef373ce5d759dc4a4d2de2 /cctz/tzdata/America/Detroit + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/Dominica + generated/beb91df50b24718aed963a509c0c2958 /cctz/tzdata/America/Edmonton + generated/fefe5ae6107231a3f738b36d95153f77 /cctz/tzdata/America/Eirunepe + generated/ec589bada56b3352067a359694896292 /cctz/tzdata/America/El_Salvador + generated/0a83457e40c917a816db3dd80c348688 /cctz/tzdata/America/Ensenada + generated/0998859e2d38d079cc1a3429aa428db4 /cctz/tzdata/America/Fort_Nelson + generated/9208172103191bf0d660e0023b358ea1 /cctz/tzdata/America/Fort_Wayne + generated/c72cd4fac2e9b8659f6b5bb2392b9ae5 /cctz/tzdata/America/Fortaleza + generated/8f9746ead1fc03c962cdd7ddacde663d /cctz/tzdata/America/Glace_Bay + generated/73727b5259886ffb64fb8e20d5456cc6 /cctz/tzdata/America/Godthab + generated/7c49d7ec95c93d0934a7a98b1a1ae66f /cctz/tzdata/America/Goose_Bay + generated/eac76eb95be7b5cc25a41e0485b58c41 /cctz/tzdata/America/Grand_Turk + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/Grenada + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/Guadeloupe + generated/f8be05a9398502fc14e50eea2693497c /cctz/tzdata/America/Guatemala + generated/dada91f7db29bcab55bfd2478a5b0779 /cctz/tzdata/America/Guayaquil + generated/bddbe9d355e1ed5dd3a4276dafe820f0 /cctz/tzdata/America/Guyana + generated/ef31a488808a56cc6d3c9a3c5a53abeb /cctz/tzdata/America/Halifax + generated/14af0ba77d76b97e0e666c070c2172cf /cctz/tzdata/America/Havana + generated/a749ae7552f77178b9eeff2d31ba0e30 /cctz/tzdata/America/Hermosillo + generated/9208172103191bf0d660e0023b358ea1 /cctz/tzdata/America/Indiana/Indianapolis + generated/964fb4bc6d047b2a8826a0734633ab0b /cctz/tzdata/America/Indiana/Knox + generated/fdc9d5431dd16120c1465f298e28e260 /cctz/tzdata/America/Indiana/Marengo + generated/2c18bc1a2ddb1b06e98ffa553ef1aaee /cctz/tzdata/America/Indiana/Petersburg + generated/90db76a975de863aadbcf37b47e18cd2 /cctz/tzdata/America/Indiana/Tell_City + generated/768d11c820a4f93683de8f8bc03df8c8 /cctz/tzdata/America/Indiana/Vevay + generated/7ca29f8adb394d878db41ab40c4c9a5d /cctz/tzdata/America/Indiana/Vincennes + generated/a23719c2255c2c9829fe6978c1c8ecd7 /cctz/tzdata/America/Indiana/Winamac + generated/9208172103191bf0d660e0023b358ea1 /cctz/tzdata/America/Indianapolis + generated/0e0379dfc5620381816641ce71fa9612 /cctz/tzdata/America/Inuvik + generated/c7f10bbd9cbe1c4dd65b3e7b11f70d37 /cctz/tzdata/America/Iqaluit + generated/6ddb543268cbeb4a7fffad436081b019 /cctz/tzdata/America/Jamaica + generated/239a70724a0ff39d5dd3e6b7f4a34212 /cctz/tzdata/America/Jujuy + generated/a9b6712f7efd08406ebb3f4a43bf1862 /cctz/tzdata/America/Juneau + generated/9d9fdcb5bec6ef7173f20c0b968ae540 /cctz/tzdata/America/Kentucky/Louisville + generated/755a91932697ce463a5c9b642e5292d6 /cctz/tzdata/America/Kentucky/Monticello + generated/964fb4bc6d047b2a8826a0734633ab0b /cctz/tzdata/America/Knox_IN + generated/fdc0ca37b4154de8d27e2347aeb7d0cf /cctz/tzdata/America/Kralendijk + generated/fd46d501559b1cf8c8c1fa330196b1b0 /cctz/tzdata/America/La_Paz + generated/bd9c4fdf467f96ab33dde64bf0ac700c /cctz/tzdata/America/Lima + generated/641e03b9a1178df8c823447ea6563f25 /cctz/tzdata/America/Los_Angeles + generated/9d9fdcb5bec6ef7173f20c0b968ae540 /cctz/tzdata/America/Louisville + generated/fdc0ca37b4154de8d27e2347aeb7d0cf /cctz/tzdata/America/Lower_Princes + generated/823a97c8e447d6f0016bacafd20a246e /cctz/tzdata/America/Maceio + generated/8435b750c0255a506ff0fd58bf646f00 /cctz/tzdata/America/Managua + generated/bbb3263234960c35b55fffa1327cc48c /cctz/tzdata/America/Manaus + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/Marigot + generated/450d5ffb8f5928afc0981b5a1a8ba4fa /cctz/tzdata/America/Martinique + generated/59dc58681872c7d33ac9f1e2f0d1c4c1 /cctz/tzdata/America/Matamoros + generated/8a665ea4a3144c8c600eb41c70e1f942 /cctz/tzdata/America/Mazatlan + generated/839eacc63921f196e4ecfded7245a67b /cctz/tzdata/America/Mendoza + generated/b6fc5775917cac51306de9bf93d87827 /cctz/tzdata/America/Menominee + generated/cbff2e606d3feafa5997dab0f3742e13 /cctz/tzdata/America/Merida + generated/4335653c96fc0b0fc83e2604a8362934 /cctz/tzdata/America/Metlakatla + generated/2aa03352ec7ce016dc2c87a064ae8bf7 /cctz/tzdata/America/Mexico_City + generated/4b51b9e60156a250908acc46d7c8cabc /cctz/tzdata/America/Miquelon + generated/3ff9cb17a579851ce689eac23e64d899 /cctz/tzdata/America/Moncton + generated/9f69b262e7c296bffc967ca4cd6a4491 /cctz/tzdata/America/Monterrey + generated/64e0eb5df848bbc06156c58b35959680 /cctz/tzdata/America/Montevideo + generated/628174eba2d7050564c54d1370a19ca8 /cctz/tzdata/America/Montreal + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/Montserrat + generated/e5beade2f7db36705f5ca5f05b6c24eb /cctz/tzdata/America/Nassau + generated/763d7a8374a42066d2b0bb81bd47218f /cctz/tzdata/America/New_York + generated/ed9b458ec968ade14b1b738136300cf2 /cctz/tzdata/America/Nipigon + generated/97ed2cb6ee44823ce8fabdc0beeae2b9 /cctz/tzdata/America/Nome + generated/6c4f6742a67bbd289f89eb4fe7de8e57 /cctz/tzdata/America/Noronha + generated/b72620d427a1898ea97232aeba51c2dc /cctz/tzdata/America/North_Dakota/Beulah + generated/511edb5c79692d730d309f4424bbaa0e /cctz/tzdata/America/North_Dakota/Center + generated/6e5fd4a73872524a21354303cdfff0f8 /cctz/tzdata/America/North_Dakota/New_Salem + generated/73727b5259886ffb64fb8e20d5456cc6 /cctz/tzdata/America/Nuuk + generated/13f02d014fe55ec2ac75fad588dff1fc /cctz/tzdata/America/Ojinaga + generated/595e67b4c97fda031a90e5ef80813e7d /cctz/tzdata/America/Panama + generated/39b21885c919ae9c27f51be3dc0fba9d /cctz/tzdata/America/Pangnirtung + generated/7dacf7ad9037fa33db4536edf63da220 /cctz/tzdata/America/Paramaribo + generated/db536e94d95836d7c5725c3b3c086586 /cctz/tzdata/America/Phoenix + generated/f07474008b0495a1830bf6ec76104684 /cctz/tzdata/America/Port-au-Prince + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/Port_of_Spain + generated/0b427173cd7de48179954c1706df9f0f /cctz/tzdata/America/Porto_Acre + generated/d3dbc4b002cc7a0e5761a3097651309a /cctz/tzdata/America/Porto_Velho + generated/92d3b867243120ea811c24c038e5b053 /cctz/tzdata/America/Puerto_Rico + generated/aa81c590ec60e26984a4be2979a548cc /cctz/tzdata/America/Punta_Arenas + generated/6bf88ae0f329f2000f6671f8eb2ca943 /cctz/tzdata/America/Rainy_River + generated/c7660bd5c4dc928d402bcba06e35f5f2 /cctz/tzdata/America/Rankin_Inlet + generated/cc7e35a2df60f44003b96877116f4d93 /cctz/tzdata/America/Recife + generated/c87b8b428cfdf54309e9503177e0ca5f /cctz/tzdata/America/Regina + generated/045f2032b6a679c82581ba29669df8c8 /cctz/tzdata/America/Resolute + generated/0b427173cd7de48179954c1706df9f0f /cctz/tzdata/America/Rio_Branco + generated/5c57dc3d11f5a64fac22a08ea0c64d25 /cctz/tzdata/America/Rosario + generated/0a83457e40c917a816db3dd80c348688 /cctz/tzdata/America/Santa_Isabel + generated/79b1d15365011739a45fe1de0258ae52 /cctz/tzdata/America/Santarem + generated/655141cec48ac560e6fec124b1cd664f /cctz/tzdata/America/Santiago + generated/3f4c05321e52971f2213bfb9e45b7a35 /cctz/tzdata/America/Santo_Domingo + generated/94e0437e48ebbef69b3fb7fe2af5e0f2 /cctz/tzdata/America/Sao_Paulo + generated/77d9cbb7aa1e48aa0380d2c3b61c75d5 /cctz/tzdata/America/Scoresbysund + generated/c1b9655d5b1ce7fbc9ac213e921acc88 /cctz/tzdata/America/Shiprock + generated/4b710acfb88ea85eda7b5f75df122214 /cctz/tzdata/America/Sitka + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/St_Barthelemy + generated/a181d1167a1dbfc2682f6d4ba9f3c803 /cctz/tzdata/America/St_Johns + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/St_Kitts + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/St_Lucia + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/St_Thomas + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/St_Vincent + generated/4a956902cb69a4cba608798e1da71a58 /cctz/tzdata/America/Swift_Current + generated/b3c87245083e0474ed4ce3d23abb7f4f /cctz/tzdata/America/Tegucigalpa + generated/b8c39bf52aaa707c58a301ce115ee576 /cctz/tzdata/America/Thule + generated/2e506a44524d8b3a2b0a86edd0211628 /cctz/tzdata/America/Thunder_Bay + generated/0a83457e40c917a816db3dd80c348688 /cctz/tzdata/America/Tijuana + generated/628174eba2d7050564c54d1370a19ca8 /cctz/tzdata/America/Toronto + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/Tortola + generated/bc58930f92342790d3ee214524808faa /cctz/tzdata/America/Vancouver + generated/64e3b5dfa8069cf23c87bc1dc81cac60 /cctz/tzdata/America/Virgin + generated/a99947596517f6c6087eddf73a7fca24 /cctz/tzdata/America/Whitehorse + generated/1ee6e72e10673d4a16b6e24671f793ec /cctz/tzdata/America/Winnipeg + generated/3ee52913271777c67f23d5a918bb0f7c /cctz/tzdata/America/Yakutat + generated/f41368f5bca111c30ebd65d69f60c627 /cctz/tzdata/America/Yellowknife + generated/4d5e4576a979e0cdeb6a7d0e81989b4e /cctz/tzdata/Antarctica/Casey + generated/b61230343294608431fbbd939bb6971d /cctz/tzdata/Antarctica/Davis + generated/3cf306430a541783b5e2b8465aa94342 /cctz/tzdata/Antarctica/DumontDUrville + generated/93ccc0d9fe3d862e546a627982ce5ba7 /cctz/tzdata/Antarctica/Macquarie + generated/63f5d146aa8a66720b2c4db9e87ec1f4 /cctz/tzdata/Antarctica/Mawson + generated/655680c9ae07d4896919210710185038 /cctz/tzdata/Antarctica/McMurdo + generated/3a420ea50d496f0c159a0d18af06b211 /cctz/tzdata/Antarctica/Palmer + generated/0fb4aa6fed3f28bc7a3dae35a993171a /cctz/tzdata/Antarctica/Rothera + generated/655680c9ae07d4896919210710185038 /cctz/tzdata/Antarctica/South_Pole + generated/deb70d248017e650da793ee281723de4 /cctz/tzdata/Antarctica/Syowa + generated/11ca9bc056ef1ae4643107bea827928f /cctz/tzdata/Antarctica/Troll + generated/7646ee0acd8d0f0543ad9a1b93603fe3 /cctz/tzdata/Antarctica/Vostok + generated/942449c95fb727fb919b341c1dea95a2 /cctz/tzdata/Arctic/Longyearbyen + generated/165baa2c51758e236a98a6a1c4cf09a0 /cctz/tzdata/Asia/Aden + generated/eaa234bf9babed72ac5b25c9a3dffa15 /cctz/tzdata/Asia/Almaty + generated/7745376113623973fcea89b5f8c8812c /cctz/tzdata/Asia/Amman + generated/f627017649ea589681b7b0dd45c03118 /cctz/tzdata/Asia/Anadyr + generated/af82eec1529bf616942df14b2ffb4403 /cctz/tzdata/Asia/Aqtau + generated/34dc35c8aa0f4e3a0064a92e5aa5d762 /cctz/tzdata/Asia/Aqtobe + generated/c68faf20645ecd953e8eb2fb70469f59 /cctz/tzdata/Asia/Ashgabat + generated/c68faf20645ecd953e8eb2fb70469f59 /cctz/tzdata/Asia/Ashkhabad + generated/dc74e10d17659800407d742d3a5db22b /cctz/tzdata/Asia/Atyrau + generated/9aa23335da47827d5ce36afc1523bbd3 /cctz/tzdata/Asia/Baghdad + generated/ec12549279e64ebeb926579888cf89d9 /cctz/tzdata/Asia/Bahrain + generated/bde0fe003b2df5121f0d31d3954095a6 /cctz/tzdata/Asia/Baku + generated/ff94f36118acae9ef3e19438688e266b /cctz/tzdata/Asia/Bangkok + generated/8a8ef367f59b0e3880bd1cff6651b357 /cctz/tzdata/Asia/Barnaul + generated/5e8c48c7a60c434f1e2f1e535172cbb9 /cctz/tzdata/Asia/Beirut + generated/56a77f4891fb3e9506aa233f5fbac27e /cctz/tzdata/Asia/Bishkek + generated/d6de93e1ea78ccfaf37089631a603c39 /cctz/tzdata/Asia/Brunei + generated/16a0b637c31e7e480cfccfc46dd75d67 /cctz/tzdata/Asia/Calcutta + generated/2d0a65ce6c15961ab95c917d9f23e882 /cctz/tzdata/Asia/Chita + generated/36687b86e799dc46c4ad4c49e3222ea5 /cctz/tzdata/Asia/Choibalsan + generated/dff9cd919f10d25842d1381cdff9f7f7 /cctz/tzdata/Asia/Chongqing + generated/dff9cd919f10d25842d1381cdff9f7f7 /cctz/tzdata/Asia/Chungking + generated/d41b1974e5ec6b3bc790062a97894a37 /cctz/tzdata/Asia/Colombo + generated/940f5a339a1f12a7153474fc3c92c624 /cctz/tzdata/Asia/Dacca + generated/53e0f8906861a26dcc561a46f034d49c /cctz/tzdata/Asia/Damascus + generated/940f5a339a1f12a7153474fc3c92c624 /cctz/tzdata/Asia/Dhaka + generated/8a60b6309c1443774d2f065bcf2bbc61 /cctz/tzdata/Asia/Dili + generated/667e494c45d181f0706bd07b211c850b /cctz/tzdata/Asia/Dubai + generated/7d4619fed11db15c54153613fcf23bda /cctz/tzdata/Asia/Dushanbe + generated/4cd70a6fdc80b1b15c0b9f7c3b807107 /cctz/tzdata/Asia/Famagusta + generated/f1758852685fee0e701b82aa868fc368 /cctz/tzdata/Asia/Gaza + generated/dff9cd919f10d25842d1381cdff9f7f7 /cctz/tzdata/Asia/Harbin + generated/dc3ec90d1f373e27ab30f8ede132593d /cctz/tzdata/Asia/Hebron + generated/0d745dbfd2cee7fffbd809ae5176666d /cctz/tzdata/Asia/Ho_Chi_Minh + generated/f729c88451bacd2895fc1c8d29064c46 /cctz/tzdata/Asia/Hong_Kong + generated/3c4a6f9840f3d89534c5f511329704e8 /cctz/tzdata/Asia/Hovd + generated/4e36cb5f575bdcbdd38b144d5a9195c9 /cctz/tzdata/Asia/Irkutsk + generated/48252c9a797f0f4bea97557a5094cf98 /cctz/tzdata/Asia/Istanbul + generated/325a2d872e0c0e5339f2e134e921047a /cctz/tzdata/Asia/Jakarta + generated/4709fe18f39068d2ca7de4c5396e1513 /cctz/tzdata/Asia/Jayapura + generated/9360bb34802002d91d9bba174c25a8dc /cctz/tzdata/Asia/Jerusalem + generated/17ca5b7fed86c92696b863cb6a78187f /cctz/tzdata/Asia/Kabul + generated/959247e441092255286b22fef107172f /cctz/tzdata/Asia/Kamchatka + generated/ef4485e168a60d91cc5347e5de9a3407 /cctz/tzdata/Asia/Karachi + generated/67c981ccf51584922a1f72dd2d529730 /cctz/tzdata/Asia/Kashgar + generated/90518d05c449fad639594f7f575407d6 /cctz/tzdata/Asia/Kathmandu + generated/90518d05c449fad639594f7f575407d6 /cctz/tzdata/Asia/Katmandu + generated/c46a3b3c120085251d04dd583a06b6a4 /cctz/tzdata/Asia/Khandyga + generated/16a0b637c31e7e480cfccfc46dd75d67 /cctz/tzdata/Asia/Kolkata + generated/702a65f05da90971b14686c21add1a90 /cctz/tzdata/Asia/Krasnoyarsk + generated/3c6f113a11cbaf251e4f5afbcf15a7ac /cctz/tzdata/Asia/Kuala_Lumpur + generated/bf388a0a1da2be989c25dbfb587076d8 /cctz/tzdata/Asia/Kuching + generated/165baa2c51758e236a98a6a1c4cf09a0 /cctz/tzdata/Asia/Kuwait + generated/d3dfd69107a4d78facbc67c4d8cea004 /cctz/tzdata/Asia/Macao + generated/d3dfd69107a4d78facbc67c4d8cea004 /cctz/tzdata/Asia/Macau + generated/656bd0f3d2def024f4d1e59fc668b538 /cctz/tzdata/Asia/Magadan + generated/c8c41a468e356c6bb65e89c69e4406dc /cctz/tzdata/Asia/Makassar + generated/52f31607db7a4a081c63dfb4cc578408 /cctz/tzdata/Asia/Manila + generated/667e494c45d181f0706bd07b211c850b /cctz/tzdata/Asia/Muscat + generated/beb20df2d2d5e3e5f5f50fb2da2a4782 /cctz/tzdata/Asia/Nicosia + generated/71705112182911b4327ac195ffae174b /cctz/tzdata/Asia/Novokuznetsk + generated/8c3304792234093e5a3d5debcef24a32 /cctz/tzdata/Asia/Novosibirsk + generated/2ee30998e941f8d603ad278135230cbd /cctz/tzdata/Asia/Omsk + generated/c72131eaa200e2aa58e1c12fe94f1f67 /cctz/tzdata/Asia/Oral + generated/ff94f36118acae9ef3e19438688e266b /cctz/tzdata/Asia/Phnom_Penh + generated/28fe8388ff78123cfd04d67e32057886 /cctz/tzdata/Asia/Pontianak + generated/772e6342aeba16851eed7dcda632c5be /cctz/tzdata/Asia/Pyongyang + generated/ec12549279e64ebeb926579888cf89d9 /cctz/tzdata/Asia/Qatar + generated/f44dbe7ca52c5fb8b57e33fd8e094038 /cctz/tzdata/Asia/Qostanay + generated/4fff9a8801bd2b75474dde3870d24e89 /cctz/tzdata/Asia/Qyzylorda + generated/37f26cf8b8fe9179833e366ca13b8916 /cctz/tzdata/Asia/Rangoon + generated/165baa2c51758e236a98a6a1c4cf09a0 /cctz/tzdata/Asia/Riyadh + generated/0d745dbfd2cee7fffbd809ae5176666d /cctz/tzdata/Asia/Saigon + generated/a1239114e71b76c885dbad8f2fa61de4 /cctz/tzdata/Asia/Sakhalin + generated/9f39ae0771032afbfca86630bec12768 /cctz/tzdata/Asia/Samarkand + generated/da5aae5f9a71de05b4625f74b007c461 /cctz/tzdata/Asia/Seoul + generated/dff9cd919f10d25842d1381cdff9f7f7 /cctz/tzdata/Asia/Shanghai + generated/3d7f8146ac1ad071d3b5738e49076af7 /cctz/tzdata/Asia/Singapore + generated/d155718faacae2f6288b0c88e66f851c /cctz/tzdata/Asia/Srednekolymsk + generated/eda5a4ce01efed633c50e04d09fe73b2 /cctz/tzdata/Asia/Taipei + generated/310f6ba2360c27c334c6e17fccf2b9a5 /cctz/tzdata/Asia/Tashkent + generated/d3ca7527ee42255559acf2d74d749d00 /cctz/tzdata/Asia/Tbilisi + generated/908281291c8446d94306e8ea21b692fa /cctz/tzdata/Asia/Tehran + generated/9360bb34802002d91d9bba174c25a8dc /cctz/tzdata/Asia/Tel_Aviv + generated/b4aa5f2b966a76ebc38d1aab44d86bce /cctz/tzdata/Asia/Thimbu + generated/b4aa5f2b966a76ebc38d1aab44d86bce /cctz/tzdata/Asia/Thimphu + generated/618a4a8f78720e26749b9c29ed4fd1b3 /cctz/tzdata/Asia/Tokyo + generated/e770be0bb1b43b9bc7df85f9ac184a79 /cctz/tzdata/Asia/Tomsk + generated/c8c41a468e356c6bb65e89c69e4406dc /cctz/tzdata/Asia/Ujung_Pandang + generated/66a0ec5d00519d1826d055514861779d /cctz/tzdata/Asia/Ulaanbaatar + generated/66a0ec5d00519d1826d055514861779d /cctz/tzdata/Asia/Ulan_Bator + generated/67c981ccf51584922a1f72dd2d529730 /cctz/tzdata/Asia/Urumqi + generated/04875c383508e7181ae595cec9856228 /cctz/tzdata/Asia/Ust-Nera + generated/ff94f36118acae9ef3e19438688e266b /cctz/tzdata/Asia/Vientiane + generated/4709139f1759e9693b8c02551b527f58 /cctz/tzdata/Asia/Vladivostok + generated/b22b7be8696db5ca60fb0b7bba4c8718 /cctz/tzdata/Asia/Yakutsk + generated/37f26cf8b8fe9179833e366ca13b8916 /cctz/tzdata/Asia/Yangon + generated/bfd18d52a4546531e2f3112725f092d3 /cctz/tzdata/Asia/Yekaterinburg + generated/d1c5195eed8efac077678d1c6d988f7f /cctz/tzdata/Asia/Yerevan + generated/46f6544a40a91d7f4369615095abd9fc /cctz/tzdata/Atlantic/Azores + generated/b85d659fabeeb1257ade1f6282a5ec7d /cctz/tzdata/Atlantic/Bermuda + generated/1e571eef4b7112bb58a746099afd9f02 /cctz/tzdata/Atlantic/Canary + generated/b7ad70caecef25e4a9ba1e5afd95fe25 /cctz/tzdata/Atlantic/Cape_Verde + generated/253d5505eaf3a497f4fa107633bea235 /cctz/tzdata/Atlantic/Faeroe + generated/253d5505eaf3a497f4fa107633bea235 /cctz/tzdata/Atlantic/Faroe + generated/942449c95fb727fb919b341c1dea95a2 /cctz/tzdata/Atlantic/Jan_Mayen + generated/e4dec087eace60f8b638fff583ec78ca /cctz/tzdata/Atlantic/Madeira + generated/c9dc6215d6b86ea9232f62c276c48833 /cctz/tzdata/Atlantic/Reykjavik + generated/2aa2dbd00a40fc7bdc1f1e3d461a2646 /cctz/tzdata/Atlantic/South_Georgia + generated/796a57137d718e4fa3db8ef611f18e61 /cctz/tzdata/Atlantic/St_Helena + generated/2a4c8fd0d241b11b207c41b0aedd6cf9 /cctz/tzdata/Atlantic/Stanley + generated/a1085ba102822f56191705c405f2a8ad /cctz/tzdata/Australia/ACT + generated/02d7a06f7ede604bdd6bf40932b670c6 /cctz/tzdata/Australia/Adelaide + generated/d5464310b37a30d92f5b85d128dd4937 /cctz/tzdata/Australia/Brisbane + generated/35eebba76b28756b47e8fff3157eafdb /cctz/tzdata/Australia/Broken_Hill + generated/a1085ba102822f56191705c405f2a8ad /cctz/tzdata/Australia/Canberra + generated/8371d9f10ef8a679be6eadedc6641d73 /cctz/tzdata/Australia/Currie + generated/09e36f9135b9ddb666cbb9496fecdf89 /cctz/tzdata/Australia/Darwin + generated/e0185725b852fe59ef8e5fef9f619990 /cctz/tzdata/Australia/Eucla + generated/8371d9f10ef8a679be6eadedc6641d73 /cctz/tzdata/Australia/Hobart + generated/e68c0f2ebe9dc247712393ab1bd168d2 /cctz/tzdata/Australia/LHI + generated/1b6ec1c2e23ea5b37361d885e1db8450 /cctz/tzdata/Australia/Lindeman + generated/e68c0f2ebe9dc247712393ab1bd168d2 /cctz/tzdata/Australia/Lord_Howe + generated/e308055a9c06f33a854a9d579ed61249 /cctz/tzdata/Australia/Melbourne + generated/a1085ba102822f56191705c405f2a8ad /cctz/tzdata/Australia/NSW + generated/09e36f9135b9ddb666cbb9496fecdf89 /cctz/tzdata/Australia/North + generated/543113396c7e34a7532457a1ce759c4e /cctz/tzdata/Australia/Perth + generated/d5464310b37a30d92f5b85d128dd4937 /cctz/tzdata/Australia/Queensland + generated/02d7a06f7ede604bdd6bf40932b670c6 /cctz/tzdata/Australia/South + generated/a1085ba102822f56191705c405f2a8ad /cctz/tzdata/Australia/Sydney + generated/8371d9f10ef8a679be6eadedc6641d73 /cctz/tzdata/Australia/Tasmania + generated/e308055a9c06f33a854a9d579ed61249 /cctz/tzdata/Australia/Victoria + generated/543113396c7e34a7532457a1ce759c4e /cctz/tzdata/Australia/West + generated/35eebba76b28756b47e8fff3157eafdb /cctz/tzdata/Australia/Yancowinna + generated/0b427173cd7de48179954c1706df9f0f /cctz/tzdata/Brazil/Acre + generated/6c4f6742a67bbd289f89eb4fe7de8e57 /cctz/tzdata/Brazil/DeNoronha + generated/94e0437e48ebbef69b3fb7fe2af5e0f2 /cctz/tzdata/Brazil/East + generated/bbb3263234960c35b55fffa1327cc48c /cctz/tzdata/Brazil/West + generated/9bc8fb09717950cb4149283c5aff15ac /cctz/tzdata/CET + generated/43c7956d0835817f930236a5633cffa6 /cctz/tzdata/CST6CDT + generated/ef31a488808a56cc6d3c9a3c5a53abeb /cctz/tzdata/Canada/Atlantic + generated/1ee6e72e10673d4a16b6e24671f793ec /cctz/tzdata/Canada/Central + generated/628174eba2d7050564c54d1370a19ca8 /cctz/tzdata/Canada/Eastern + generated/beb91df50b24718aed963a509c0c2958 /cctz/tzdata/Canada/Mountain + generated/a181d1167a1dbfc2682f6d4ba9f3c803 /cctz/tzdata/Canada/Newfoundland + generated/bc58930f92342790d3ee214524808faa /cctz/tzdata/Canada/Pacific + generated/c87b8b428cfdf54309e9503177e0ca5f /cctz/tzdata/Canada/Saskatchewan + generated/a99947596517f6c6087eddf73a7fca24 /cctz/tzdata/Canada/Yukon + generated/655141cec48ac560e6fec124b1cd664f /cctz/tzdata/Chile/Continental + generated/807e3c4820f8a2547e3bac8a344597ca /cctz/tzdata/Chile/EasterIsland + generated/14af0ba77d76b97e0e666c070c2172cf /cctz/tzdata/Cuba + generated/19ef27aa43febb679c0795f8c5dedc0f /cctz/tzdata/EET + generated/b33eb6506380f950ad798d4d788d136a /cctz/tzdata/EST + generated/5fbedfd64bddc3ec7790a4eb0f22b66c /cctz/tzdata/EST5EDT + generated/39d0994d5956e55a919f2945ccd7c0bf /cctz/tzdata/Egypt + generated/9fae53762400421dfbba224c8f21038d /cctz/tzdata/Eire + generated/e7577ad74319a942781e7153a97d7690 /cctz/tzdata/Etc/GMT + generated/e7577ad74319a942781e7153a97d7690 /cctz/tzdata/Etc/GMT+0 + generated/d8af0cadc03a3813b866bbfeb041e167 /cctz/tzdata/Etc/GMT+1 + generated/9766867907fd0631d6357abfcb71fde5 /cctz/tzdata/Etc/GMT+10 + generated/d40107fc4f4515f2f2eed25a1ca88fb8 /cctz/tzdata/Etc/GMT+11 + generated/52569f1fcc560faffd0ed78e0e9eb69f /cctz/tzdata/Etc/GMT+12 + generated/29c0187634c10fc717832169fc449715 /cctz/tzdata/Etc/GMT+2 + generated/0d49585e3c48010af348561943e319a2 /cctz/tzdata/Etc/GMT+3 + generated/88546761589cb98c5209ff92ac71be7d /cctz/tzdata/Etc/GMT+4 + generated/9c4035bc2046d3be368e14a46fc8685d /cctz/tzdata/Etc/GMT+5 + generated/a79c9f48310a80244f2065d08f09f91a /cctz/tzdata/Etc/GMT+6 + generated/7956f01b2e6933717e9ba4adfd327ccc /cctz/tzdata/Etc/GMT+7 + generated/9eaedd2c3574882c46ddbbfeabc5c444 /cctz/tzdata/Etc/GMT+8 + generated/0d81f8cc7c4066b8f84371ebbbb3e00c /cctz/tzdata/Etc/GMT+9 + generated/e7577ad74319a942781e7153a97d7690 /cctz/tzdata/Etc/GMT-0 + generated/721967abda97296c7f361100d8b868e4 /cctz/tzdata/Etc/GMT-1 + generated/42fcd2bd28f14995f4fec31b081d88b0 /cctz/tzdata/Etc/GMT-10 + generated/ba0134eab8c956f482f642c6a5440ee0 /cctz/tzdata/Etc/GMT-11 + generated/f669833977d5968e30ce9d8288dccd22 /cctz/tzdata/Etc/GMT-12 + generated/7176177837995c39668c29a4a459cb55 /cctz/tzdata/Etc/GMT-13 + generated/39ffa0df7491f260ed87949d60aa34da /cctz/tzdata/Etc/GMT-14 + generated/f72cea14be81564422856a5e3633b0f0 /cctz/tzdata/Etc/GMT-2 + generated/6af1f235706f2c48a99cabb1efcd0e53 /cctz/tzdata/Etc/GMT-3 + generated/dced2b01cc7c29f0b1adf9c62f8603fd /cctz/tzdata/Etc/GMT-4 + generated/167b215e24978122218b1a0eec97ea7a /cctz/tzdata/Etc/GMT-5 + generated/43d37a94ef2f6ee11c55e0a14c2898cb /cctz/tzdata/Etc/GMT-6 + generated/ade2a36e23a06174c36b6fd5d795e865 /cctz/tzdata/Etc/GMT-7 + generated/8e7f6cfc11d44c8e29f7f4a59df5fcae /cctz/tzdata/Etc/GMT-8 + generated/ccc5a76bcf9b46bc41f3ffb232850bbb /cctz/tzdata/Etc/GMT-9 + generated/e7577ad74319a942781e7153a97d7690 /cctz/tzdata/Etc/GMT0 + generated/e7577ad74319a942781e7153a97d7690 /cctz/tzdata/Etc/Greenwich + generated/51d8a0e68892ebf0854a1b4250ffb26b /cctz/tzdata/Etc/UCT + generated/51d8a0e68892ebf0854a1b4250ffb26b /cctz/tzdata/Etc/UTC + generated/51d8a0e68892ebf0854a1b4250ffb26b /cctz/tzdata/Etc/Universal + generated/51d8a0e68892ebf0854a1b4250ffb26b /cctz/tzdata/Etc/Zulu + generated/1ae456cf0f29bd731d4d9f876c4a0905 /cctz/tzdata/Europe/Amsterdam + generated/89cb42bccb29740b74d74dad225a7f70 /cctz/tzdata/Europe/Andorra + generated/29067b92c3481871788d16e05841ce78 /cctz/tzdata/Europe/Astrakhan + generated/9006b968810f68ce90473c809b252776 /cctz/tzdata/Europe/Athens + generated/b14ab0a98fb1964def4eaf00d2a6bb73 /cctz/tzdata/Europe/Belfast + generated/a4ac1780d547f4e4c41cab4c6cf1d76d /cctz/tzdata/Europe/Belgrade + generated/2577d6d2ba90616ca47c8ee8d9fbca20 /cctz/tzdata/Europe/Berlin + generated/9ac4de9fb3bcae616f7de40984ccb6b2 /cctz/tzdata/Europe/Bratislava + generated/7a350885dea1ebe1bf630eb4254e9abc /cctz/tzdata/Europe/Brussels + generated/f0976c6697d91943b1d72c331844db50 /cctz/tzdata/Europe/Bucharest + generated/0b00b9da0d4f68857bdebb750ea28c4d /cctz/tzdata/Europe/Budapest + generated/07b0081174b26fd15187b9d6a019e322 /cctz/tzdata/Europe/Busingen + generated/d62d0d008574b60d70899d22545eb1f9 /cctz/tzdata/Europe/Chisinau + generated/48f03314923c2aaf9706fdbf9abf223d /cctz/tzdata/Europe/Copenhagen + generated/9fae53762400421dfbba224c8f21038d /cctz/tzdata/Europe/Dublin + generated/8629c4ecded1abb6072c099aa6781c47 /cctz/tzdata/Europe/Gibraltar + generated/b14ab0a98fb1964def4eaf00d2a6bb73 /cctz/tzdata/Europe/Guernsey + generated/aecc05607e312ffdbdf3a8f07ac64a6b /cctz/tzdata/Europe/Helsinki + generated/b14ab0a98fb1964def4eaf00d2a6bb73 /cctz/tzdata/Europe/Isle_of_Man + generated/48252c9a797f0f4bea97557a5094cf98 /cctz/tzdata/Europe/Istanbul + generated/b14ab0a98fb1964def4eaf00d2a6bb73 /cctz/tzdata/Europe/Jersey + generated/e019dabd72a8783f7d4b4c1fe3dd5c11 /cctz/tzdata/Europe/Kaliningrad + generated/af3038d5a348ad35e154a52d14029434 /cctz/tzdata/Europe/Kiev + generated/0b403c8a9ccd7ca6e2a6efbb8ea7a0f0 /cctz/tzdata/Europe/Kirov + generated/1a41268ed57dfc9d45a22013bd679866 /cctz/tzdata/Europe/Lisbon + generated/a4ac1780d547f4e4c41cab4c6cf1d76d /cctz/tzdata/Europe/Ljubljana + generated/b14ab0a98fb1964def4eaf00d2a6bb73 /cctz/tzdata/Europe/London + generated/4aa21d2f4d29c826df846428917d6124 /cctz/tzdata/Europe/Luxembourg + generated/1377f55949e2a3c4cf3ccc96bb5a91a5 /cctz/tzdata/Europe/Madrid + generated/1fd961b54d21dd2ad91b05c7c71435a8 /cctz/tzdata/Europe/Malta + generated/aecc05607e312ffdbdf3a8f07ac64a6b /cctz/tzdata/Europe/Mariehamn + generated/aed64fc971bc7aa23cab042415d57d53 /cctz/tzdata/Europe/Minsk + generated/a59f8bc0dd11620983017647a62ef6f0 /cctz/tzdata/Europe/Monaco + generated/39b47bf37a27f7bcd5d3f7c51343c7fc /cctz/tzdata/Europe/Moscow + generated/beb20df2d2d5e3e5f5f50fb2da2a4782 /cctz/tzdata/Europe/Nicosia + generated/942449c95fb727fb919b341c1dea95a2 /cctz/tzdata/Europe/Oslo + generated/506e99f9c797d9798e7a411495691504 /cctz/tzdata/Europe/Paris + generated/a4ac1780d547f4e4c41cab4c6cf1d76d /cctz/tzdata/Europe/Podgorica + generated/9ac4de9fb3bcae616f7de40984ccb6b2 /cctz/tzdata/Europe/Prague + generated/d917645873cf9c7577ce2fdbe05963cb /cctz/tzdata/Europe/Riga + generated/c57843caa48aa4715344a26830df1f13 /cctz/tzdata/Europe/Rome + generated/8baab5c53cf4270f860fb2de701ded9d /cctz/tzdata/Europe/Samara + generated/c57843caa48aa4715344a26830df1f13 /cctz/tzdata/Europe/San_Marino + generated/a4ac1780d547f4e4c41cab4c6cf1d76d /cctz/tzdata/Europe/Sarajevo + generated/c4aa97ffb42eeeb70479979e2050d866 /cctz/tzdata/Europe/Saratov + generated/a7d9f2c43b6cd330e6b243c2ff119e61 /cctz/tzdata/Europe/Simferopol + generated/a4ac1780d547f4e4c41cab4c6cf1d76d /cctz/tzdata/Europe/Skopje + generated/710422cb894d7b930689a115e97f688b /cctz/tzdata/Europe/Sofia + generated/2e2be8fa9483fe9dd59ab4d82ac4107f /cctz/tzdata/Europe/Stockholm + generated/2b3fb59013e51fa85db1cee17e54edc8 /cctz/tzdata/Europe/Tallinn + generated/e9faa2fda4c9671e5002bf470313be76 /cctz/tzdata/Europe/Tirane + generated/d62d0d008574b60d70899d22545eb1f9 /cctz/tzdata/Europe/Tiraspol + generated/0dfaf73a64a7c3cfcd10756a6d545e08 /cctz/tzdata/Europe/Ulyanovsk + generated/6ce46144754f3564668c5a51d6afb854 /cctz/tzdata/Europe/Uzhgorod + generated/07b0081174b26fd15187b9d6a019e322 /cctz/tzdata/Europe/Vaduz + generated/c57843caa48aa4715344a26830df1f13 /cctz/tzdata/Europe/Vatican + generated/fe03dcb43031a0d45d0039e33f1e4c42 /cctz/tzdata/Europe/Vienna + generated/57500f0613dd0355126a75ca0fb0db2c /cctz/tzdata/Europe/Vilnius + generated/19ed55c2f6f06452f1008cfb15e5636b /cctz/tzdata/Europe/Volgograd + generated/d44a4791346a5defc84c6bec9e52645d /cctz/tzdata/Europe/Warsaw + generated/a4ac1780d547f4e4c41cab4c6cf1d76d /cctz/tzdata/Europe/Zagreb + generated/4f3988376fc77952194c6224a912e152 /cctz/tzdata/Europe/Zaporozhye + generated/07b0081174b26fd15187b9d6a019e322 /cctz/tzdata/Europe/Zurich + generated/e369eb23db7f75930ece7bf91b6b86a7 /cctz/tzdata/Factory + generated/b14ab0a98fb1964def4eaf00d2a6bb73 /cctz/tzdata/GB + generated/b14ab0a98fb1964def4eaf00d2a6bb73 /cctz/tzdata/GB-Eire + generated/e7577ad74319a942781e7153a97d7690 /cctz/tzdata/GMT + generated/e7577ad74319a942781e7153a97d7690 /cctz/tzdata/GMT+0 + generated/e7577ad74319a942781e7153a97d7690 /cctz/tzdata/GMT-0 + generated/e7577ad74319a942781e7153a97d7690 /cctz/tzdata/GMT0 + generated/e7577ad74319a942781e7153a97d7690 /cctz/tzdata/Greenwich + generated/a813cd94645ca8774632d328080f8d97 /cctz/tzdata/HST + generated/f729c88451bacd2895fc1c8d29064c46 /cctz/tzdata/Hongkong + generated/c9dc6215d6b86ea9232f62c276c48833 /cctz/tzdata/Iceland + generated/fe54394a3dcf951bad3c293980109dd2 /cctz/tzdata/Indian/Antananarivo + generated/f3ac587344d641763d27895afbe16345 /cctz/tzdata/Indian/Chagos + generated/41073bcf4d5aaaf7dbd1da830ce5e1fe /cctz/tzdata/Indian/Christmas + generated/bc409b8b43f53e38abc4c7a220519f49 /cctz/tzdata/Indian/Cocos + generated/fe54394a3dcf951bad3c293980109dd2 /cctz/tzdata/Indian/Comoro + generated/f104bb3d3ae2809522db434bd995f6a8 /cctz/tzdata/Indian/Kerguelen + generated/992f11daf970c1d1c32d67b8407ba5df /cctz/tzdata/Indian/Mahe + generated/5d62b2758da6d68cb971d8f2cf64d432 /cctz/tzdata/Indian/Maldives + generated/cea8767711bc79a4ec192e25706de5a5 /cctz/tzdata/Indian/Mauritius + generated/fe54394a3dcf951bad3c293980109dd2 /cctz/tzdata/Indian/Mayotte + generated/e2d55321af8dab0e0fa2baee7c8bf5b8 /cctz/tzdata/Indian/Reunion + generated/908281291c8446d94306e8ea21b692fa /cctz/tzdata/Iran + generated/9360bb34802002d91d9bba174c25a8dc /cctz/tzdata/Israel + generated/6ddb543268cbeb4a7fffad436081b019 /cctz/tzdata/Jamaica + generated/618a4a8f78720e26749b9c29ed4fd1b3 /cctz/tzdata/Japan + generated/475a8ae9a30287527356f20d4456abd4 /cctz/tzdata/Kwajalein + generated/a6b8c0b7319f5fdca0ed634760ff6e3b /cctz/tzdata/Libya + generated/0727fa9015cd130fba15b7e7163ff139 /cctz/tzdata/MET + generated/ef8eca09259416ea4e1d5b4bb865a645 /cctz/tzdata/MST + generated/56dbf10674ff9ef08ef9088d7e7ab639 /cctz/tzdata/MST7MDT + generated/0a83457e40c917a816db3dd80c348688 /cctz/tzdata/Mexico/BajaNorte + generated/8a665ea4a3144c8c600eb41c70e1f942 /cctz/tzdata/Mexico/BajaSur + generated/2aa03352ec7ce016dc2c87a064ae8bf7 /cctz/tzdata/Mexico/General + generated/655680c9ae07d4896919210710185038 /cctz/tzdata/NZ + generated/41dd4c2678c8776c4abdcc809932bbe7 /cctz/tzdata/NZ-CHAT + generated/c1b9655d5b1ce7fbc9ac213e921acc88 /cctz/tzdata/Navajo + generated/dff9cd919f10d25842d1381cdff9f7f7 /cctz/tzdata/PRC + generated/74b8879270f5bd60554e01c6610b1efb /cctz/tzdata/PST8PDT + generated/87fafd13e64ef4873b39f9946fed557b /cctz/tzdata/Pacific/Apia + generated/655680c9ae07d4896919210710185038 /cctz/tzdata/Pacific/Auckland + generated/d8977a620cda17fb8da4421e6c474f0c /cctz/tzdata/Pacific/Bougainville + generated/41dd4c2678c8776c4abdcc809932bbe7 /cctz/tzdata/Pacific/Chatham + generated/64afd19c03facc651ca57e6a603b9d05 /cctz/tzdata/Pacific/Chuuk + generated/807e3c4820f8a2547e3bac8a344597ca /cctz/tzdata/Pacific/Easter + generated/4cddbf0831a9bbaa79369d3b91961a8f /cctz/tzdata/Pacific/Efate + generated/95e6699e763f5bd303f05eab455d648b /cctz/tzdata/Pacific/Enderbury + generated/afaa4c77a1e912306f4ca578c933d4a6 /cctz/tzdata/Pacific/Fakaofo + generated/50e7cf27ff65d91d4a834e07e9936df2 /cctz/tzdata/Pacific/Fiji + generated/31b072dd08dde7ce02c27780c6b307aa /cctz/tzdata/Pacific/Funafuti + generated/055c3628d78f3c9a01a7732c442f78f9 /cctz/tzdata/Pacific/Galapagos + generated/f4cf94e44810f7c25b2529ffe37ab772 /cctz/tzdata/Pacific/Gambier + generated/44355d47052f97ac7388446bce23e3ab /cctz/tzdata/Pacific/Guadalcanal + generated/ec185892bb2764a8280ee41ff8f2b032 /cctz/tzdata/Pacific/Guam + generated/5ed332a521639d91536739cfb9e4dde6 /cctz/tzdata/Pacific/Honolulu + generated/5ed332a521639d91536739cfb9e4dde6 /cctz/tzdata/Pacific/Johnston + generated/1530b1e45e83ed3f4e61d1a6f2f4f706 /cctz/tzdata/Pacific/Kiritimati + generated/fb8a999658da8686edc727548949fd88 /cctz/tzdata/Pacific/Kosrae + generated/475a8ae9a30287527356f20d4456abd4 /cctz/tzdata/Pacific/Kwajalein + generated/084d4da363c6b04024bd4027111502bf /cctz/tzdata/Pacific/Majuro + generated/82b091bd4358c77e600c08893560419b /cctz/tzdata/Pacific/Marquesas + generated/f789c65f289caa627ea1f690836c48f6 /cctz/tzdata/Pacific/Midway + generated/fa85e90a2dcd44ced6128397a99b2668 /cctz/tzdata/Pacific/Nauru + generated/9c4211df749eab732ee3f7654b4824e0 /cctz/tzdata/Pacific/Niue + generated/0e8c2a93c75cfb3705dc63788803ebfb /cctz/tzdata/Pacific/Norfolk + generated/7f89369fd9501f16ae77919d4c0e5658 /cctz/tzdata/Pacific/Noumea + generated/f789c65f289caa627ea1f690836c48f6 /cctz/tzdata/Pacific/Pago_Pago + generated/8d2aeb9646f427ba69fab8ad34c51552 /cctz/tzdata/Pacific/Palau + generated/acf014221290656a061fff7e9fa818ee /cctz/tzdata/Pacific/Pitcairn + generated/d04546b33aa2a7b0a390fed538eb39ec /cctz/tzdata/Pacific/Pohnpei + generated/d04546b33aa2a7b0a390fed538eb39ec /cctz/tzdata/Pacific/Ponape + generated/bcf8aa818432d7ae244087c7306bcb23 /cctz/tzdata/Pacific/Port_Moresby + generated/ab10b4ee8dbac84167032fed4b886f05 /cctz/tzdata/Pacific/Rarotonga + generated/ec185892bb2764a8280ee41ff8f2b032 /cctz/tzdata/Pacific/Saipan + generated/f789c65f289caa627ea1f690836c48f6 /cctz/tzdata/Pacific/Samoa + generated/0672593cd4756dbfb8bba02b4555c91d /cctz/tzdata/Pacific/Tahiti + generated/ba8d62a6ed66f462087e00ad76f7354d /cctz/tzdata/Pacific/Tarawa + generated/6cbb0a7b529efb1e79faaf166808d993 /cctz/tzdata/Pacific/Tongatapu + generated/64afd19c03facc651ca57e6a603b9d05 /cctz/tzdata/Pacific/Truk + generated/1ef406c5a86f20d89cc555c116a7d104 /cctz/tzdata/Pacific/Wake + generated/e2433648de4223726f2f3cf01953e552 /cctz/tzdata/Pacific/Wallis + generated/64afd19c03facc651ca57e6a603b9d05 /cctz/tzdata/Pacific/Yap + generated/d44a4791346a5defc84c6bec9e52645d /cctz/tzdata/Poland + generated/1a41268ed57dfc9d45a22013bd679866 /cctz/tzdata/Portugal + generated/eda5a4ce01efed633c50e04d09fe73b2 /cctz/tzdata/ROC + generated/da5aae5f9a71de05b4625f74b007c461 /cctz/tzdata/ROK + generated/3d7f8146ac1ad071d3b5738e49076af7 /cctz/tzdata/Singapore + generated/48252c9a797f0f4bea97557a5094cf98 /cctz/tzdata/Turkey + generated/51d8a0e68892ebf0854a1b4250ffb26b /cctz/tzdata/UCT + generated/77ea6e8a582f87d7a397a9e7b2111be0 /cctz/tzdata/US/Alaska + generated/1df7e605c33529940c76c1c145c52fc5 /cctz/tzdata/US/Aleutian + generated/db536e94d95836d7c5725c3b3c086586 /cctz/tzdata/US/Arizona + generated/85435a33486747b319872947c68317f3 /cctz/tzdata/US/Central + generated/9208172103191bf0d660e0023b358ea1 /cctz/tzdata/US/East-Indiana + generated/763d7a8374a42066d2b0bb81bd47218f /cctz/tzdata/US/Eastern + generated/5ed332a521639d91536739cfb9e4dde6 /cctz/tzdata/US/Hawaii + generated/964fb4bc6d047b2a8826a0734633ab0b /cctz/tzdata/US/Indiana-Starke + generated/48c96bff46ef373ce5d759dc4a4d2de2 /cctz/tzdata/US/Michigan + generated/c1b9655d5b1ce7fbc9ac213e921acc88 /cctz/tzdata/US/Mountain + generated/641e03b9a1178df8c823447ea6563f25 /cctz/tzdata/US/Pacific + generated/f789c65f289caa627ea1f690836c48f6 /cctz/tzdata/US/Samoa + generated/51d8a0e68892ebf0854a1b4250ffb26b /cctz/tzdata/UTC + generated/51d8a0e68892ebf0854a1b4250ffb26b /cctz/tzdata/Universal + generated/39b47bf37a27f7bcd5d3f7c51343c7fc /cctz/tzdata/W-SU + generated/0124cd65b22dfd92129cb0a43719c717 /cctz/tzdata/WET + generated/51d8a0e68892ebf0854a1b4250ffb26b /cctz/tzdata/Zulu +) diff --git a/contrib/libs/cctz/ya.make b/contrib/libs/cctz/ya.make new file mode 100644 index 0000000000..954d24908f --- /dev/null +++ b/contrib/libs/cctz/ya.make @@ -0,0 +1,54 @@ +# Generated by devtools/yamaker from nixpkgs 5852a21819542e6809f68ba5a798600e69874e76. + +LIBRARY() + +OWNER( + dfyz + petrk +) + +VERSION(2020-11-11) + +ORIGINAL_SOURCE(https://github.com/google/cctz/archive/98fb541c6f0f35cf0dffcbc3777d8385bbd5b4c1.tar.gz) + +LICENSE( + Apache-2.0 AND + Public-Domain +) + +LICENSE_TEXTS(.yandex_meta/licenses.list.txt) + +ADDINCL( + GLOBAL contrib/libs/cctz/include +) + +NO_COMPILER_WARNINGS() + +NO_UTIL() + +IF (OS_DARWIN) + LDFLAGS( + -framework + CoreFoundation + ) +ENDIF() + +SRCS( + src/civil_time_detail.cc + src/time_zone_fixed.cc + src/time_zone_format.cc + src/time_zone_if.cc + src/time_zone_impl.cc + src/time_zone_info.cc + src/time_zone_libc.cc + src/time_zone_lookup.cc + src/time_zone_posix.cc + src/zone_info_source.cc +) + +END() + +RECURSE( + test + tzdata +) |