| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 |
| * |
| * http://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 "Adaptor.hh" |
| #include "Timezone.hh" |
| #include "wrap/gtest-wrapper.h" |
| |
| #include <iostream> |
| #include <vector> |
| |
| namespace orc { |
| |
| bool isLeap(int64_t year); |
| |
| TEST(TestTimezone, isLeap) { |
| EXPECT_TRUE(isLeap(2000)); |
| EXPECT_FALSE(isLeap(2001)); |
| EXPECT_TRUE(isLeap(2004)); |
| EXPECT_FALSE(isLeap(2100)); |
| EXPECT_FALSE(isLeap(2200)); |
| EXPECT_FALSE(isLeap(2300)); |
| EXPECT_TRUE(isLeap(2400)); |
| } |
| |
| int64_t binarySearch(const std::vector<int64_t> &array, int64_t target); |
| |
| TEST(TestTimezone, testBinarySearch) { |
| std::vector<int64_t> vect; |
| EXPECT_EQ(-1, binarySearch(vect, 0)); |
| vect.push_back(0); |
| EXPECT_EQ(-1, binarySearch(vect, -5)); |
| EXPECT_EQ(0, binarySearch(vect, 0)); |
| EXPECT_EQ(0, binarySearch(vect, 5)); |
| vect.push_back(2); |
| EXPECT_EQ(-1, binarySearch(vect, -1)); |
| EXPECT_EQ(0, binarySearch(vect, 0)); |
| EXPECT_EQ(0, binarySearch(vect, 1)); |
| EXPECT_EQ(1, binarySearch(vect, 2)); |
| EXPECT_EQ(1, binarySearch(vect, 3)); |
| } |
| |
| /** |
| * Parse a future rule string and return the parsed rule as a string. |
| */ |
| std::string stringifyRule(const std::string& ruleString) { |
| std::shared_ptr<FutureRule> rule = parseFutureRule(ruleString); |
| std::stringstream buffer; |
| rule->print(buffer); |
| return buffer.str(); |
| } |
| |
| |
| TEST(TestTimezone, parseFutureRule) { |
| EXPECT_EQ(" Future rule: FOO0\n standard FOO 0\n", |
| stringifyRule("FOO0")); |
| EXPECT_EQ(" Future rule: <FOO+->010:02\n standard <FOO+-> -36120\n", |
| stringifyRule("<FOO+->010:02")); |
| // unclosed '<' |
| EXPECT_THROW(stringifyRule("<FOO12"), TimezoneError); |
| // empty name |
| EXPECT_THROW(stringifyRule("+8"), TimezoneError); |
| // missing offset |
| EXPECT_THROW(stringifyRule("FOO"), TimezoneError); |
| EXPECT_EQ(" Future rule: FOO-123:45:67\n standard FOO 445567\n", |
| stringifyRule("FOO-123:45:67")); |
| EXPECT_EQ(" Future rule: FOO+8\n standard FOO -28800\n", |
| stringifyRule("FOO+8")); |
| EXPECT_EQ((" Future rule: FOO8BAR,J10,20\n standard FOO -28800\n" |
| " dst BAR -25200 (dst)\n start julian 10 at 2:0:0\n" |
| " end day 20 at 2:0:0\n"), |
| stringifyRule("FOO8BAR,J10,20")); |
| EXPECT_EQ((" Future rule: FOO+8BAR-0:30,M3.1.0,M10.5.6\n" |
| " standard FOO -28800\n" |
| " dst BAR 1800 (dst)\n" |
| " start month 3 week 1 day 0 at 2:0:0\n" |
| " end month 10 week 5 day 6 at 2:0:0\n"), |
| stringifyRule("FOO+8BAR-0:30,M3.1.0,M10.5.6")); |
| EXPECT_EQ((" Future rule: FOO10BAR1,3,4\n" |
| " standard FOO -36000\n" |
| " dst BAR -3600 (dst)\n" |
| " start day 3 at 2:0:0\n" |
| " end day 4 at 2:0:0\n"), |
| stringifyRule("FOO10BAR1,3,4")); |
| // missing transition times |
| EXPECT_THROW(stringifyRule("FOO8BAR"), TimezoneError); |
| // check left over text |
| EXPECT_THROW(stringifyRule("FOO8BAR,10,20x"), TimezoneError); |
| EXPECT_EQ((" Future rule: FOO8BAR,3/3,4/4:30\n" |
| " standard FOO -28800\n" |
| " dst BAR -25200 (dst)\n" |
| " start day 3 at 3:0:0\n" |
| " end day 4 at 4:30:0\n"), |
| stringifyRule("FOO8BAR,3/3,4/4:30")); |
| EXPECT_EQ((" Future rule: FOO-8BAR,J3/3,M4.5.6/00:04:0007\n" |
| " standard FOO 28800\n" |
| " dst BAR 32400 (dst)\n" |
| " start julian 3 at 3:0:0\n" |
| " end month 4 week 5 day 6 at 0:4:7\n"), |
| stringifyRule("FOO-8BAR,J3/3,M4.5.6/00:04:0007")); |
| // too many fields in offset |
| EXPECT_THROW(stringifyRule("FOO8BAR,10,20/4:30:20:10"), TimezoneError); |
| |
| EXPECT_FALSE(parseFutureRule("")->isDefined()); |
| EXPECT_TRUE(parseFutureRule("FOO12")->isDefined()); |
| } |
| |
| const std::string& getZoneFromRule(FutureRule *rule, |
| const std::string& date) { |
| tm timeStruct; |
| if (strptime(date.c_str(), "%Y-%m-%d %H:%M:%S", &timeStruct) == nullptr) { |
| throw TimezoneError("bad time " + date); |
| } |
| return rule->getVariant(timegm(&timeStruct)).name; |
| } |
| |
| TEST(TestTimezone, useFutureRule) { |
| std::shared_ptr<FutureRule> rule = |
| parseFutureRule("FOO8BAR,M3.2.0,M11.1.0"); |
| // 1970 |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1970-01-01 00:00:00")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1970-03-08 09:59:59")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1970-03-08 10:00:00")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1970-04-01 00:00:00")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1970-11-01 08:59:59")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1970-11-01 09:00:00")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1970-12-31 00:00:00")); |
| |
| // 2369 |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "2369-01-01 00:00:00")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "2369-03-09 09:59:59")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "2369-03-09 10:00:00")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "2369-11-02 08:59:59")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "2369-11-02 09:00:00")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "2369-12-31 00:00:00")); |
| |
| // 2370 |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "2370-01-01 00:00:00")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "2370-03-08 09:59:59")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "2370-03-08 10:00:00")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "2370-04-01 00:00:00")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "2370-11-01 08:59:59")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "2370-11-01 09:00:00")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "2370-12-31 00:00:00")); |
| |
| rule = parseFutureRule("FOO8BAR,J10,J360"); |
| //1970 |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1970-01-11 09:59:59")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1970-01-11 10:00:00")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1970-12-27 08:59:59")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1970-12-27 09:00:00")); |
| //1972 |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1972-01-11 09:59:59")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1972-01-11 10:00:00")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1972-12-27 08:59:59")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1972-12-27 09:00:00")); |
| |
| rule = parseFutureRule("FOO8BAR,10,360"); |
| #ifdef HAS_PRE_1970 |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1969-01-11 09:59:59")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1969-01-11 10:00:00")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1969-12-27 08:59:59")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1969-12-27 09:00:00")); |
| #endif |
| //1970 |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1970-01-11 09:59:59")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1970-01-11 10:00:00")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1970-12-27 08:59:59")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1970-12-27 09:00:00")); |
| //1972 |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1972-01-11 09:59:59")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1972-01-11 10:00:00")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1972-12-26 08:59:59")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1972-12-26 09:00:00")); |
| |
| // test a southern hemisphere timezone |
| rule = parseFutureRule("FOO8BAR,360,10"); |
| //1970 |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1970-01-11 08:59:59")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1970-01-11 09:00:00")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1970-12-27 09:59:59")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1970-12-27 10:00:00")); |
| //1972 |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1972-01-11 08:59:59")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1972-01-11 09:00:00")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1972-12-26 09:59:59")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1972-12-26 10:00:00")); |
| |
| rule = parseFutureRule("FOO8BAR,J10/3,J360/3:30"); |
| //1970 |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1970-01-11 10:59:59")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1970-01-11 11:00:00")); |
| EXPECT_EQ("BAR", getZoneFromRule(rule.get(), "1970-12-27 10:29:59")); |
| EXPECT_EQ("FOO", getZoneFromRule(rule.get(), "1970-12-27 10:30:00")); |
| } |
| |
| unsigned char decodeBase64Char(unsigned char ch) { |
| switch (ch >> 4) { |
| case 4: case 5: return static_cast<unsigned char>(ch - 'A'); |
| case 6: case 7: return static_cast<unsigned char>(ch - 'a' + 26); |
| case 3: return static_cast<unsigned char>(ch - '0' + 52); |
| case 2: return static_cast<unsigned char>(ch == '+' ? 62 : 63); |
| default: return 255; |
| } |
| } |
| |
| std::vector<unsigned char> decodeBase64(const std::string& input) { |
| std::vector<unsigned char> result; |
| result.reserve(3 * (input.size() / 4)); |
| uint32_t accumulator = 0; |
| uint32_t bits = 0; |
| for(uint32_t c=0; c < input.size() && input[c] != '='; ++c) { |
| accumulator = (accumulator << 6) | |
| decodeBase64Char(static_cast<unsigned char>(input[c])); |
| bits += 6; |
| if (bits >= 8) { |
| bits -= 8; |
| result.push_back(static_cast<unsigned char>(accumulator >> bits)); |
| accumulator &= ~(0xffffffff << bits); |
| } |
| } |
| return result; |
| } |
| |
| static const char *LA_VER1 = |
| ("VFppZgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAC5AAAABAAAABCepkig" |
| "n7sVkKCGKqChmveQy4kaoNIj9HDSYSYQ1v50INiArZDa/tGg28CQENzes6DdqayQ3r6Vo" |
| "N+JjpDgnneg4WlwkOJ+WaDjSVKQ5F47oOUpNJDmR1gg5xJREOgnOiDo8jMQ6gccIOrSFR" |
| "Dr5v4g7LH3EO3G4CDukdkQ76/8oPBxuxDxj96g8n/BkPNvwKD0X6OQ9U+ioPY/hZD3L4S" |
| "g+CiiEPkPZqD6CIQQ+viDIPvoZhD82GUg/chIEP64RyD/qCoQAJgpIAGIDBACeAsgA3Eo" |
| "kARhJ6AFUQqQBkEJoAcw7JAHjUOgCRDOkAmtvyAK8LCQC+CvoAzZzRANwJGgDrmvEA+pr" |
| "iAQmZEQEYmQIBJ5cxATaXIgFFlVEBVJVCAWOTcQFyk2IBgiU5AZCRggGgI1kBryNKAb4h" |
| "eQHNIWoB3B+ZAesfigH6HbkCB2KyAhgb2QIlYNICNq2hAkNe8gJUq8ECYV0SAnKp4QJ/7" |
| "toCkKgBAp3s+gKupiECu+saAs036QLZ6ToC6zYJAvfnWgMJNCkDFnkiAycySQM0d0IDRT" |
| "BpA1J1YgNjLokDcHOCA4HAUQOOcaIDn75xA6xvwgO9vJEDywGKA9u6sQPo/6oD+bjRBAb" |
| "9ygQYSpkEJPvqBDZIuQRC+goEVEbZBF89MgRy2KEEfTtSBJDWwQSbOXIErtThBLnLOgTN" |
| "ZqkE18laBOtkyQT1x3oFCWLpBRPFmgUnYQkFMcO6BUVfKQVPwdoFY11JBW5TogWB7xEFj" |
| "FHCBZ/tMQWqT+IFvetRBchOAgXb6XEF5kwiBfnnkQYE3eoGGHlZBiLcCgY2d3kGQNoqBl" |
| "R1mQZe2EoGcnO5BnzWagaQcdkGmtSKBq5v+Qa5ZlIGzQHBBtdkcgbq/+EG9WKSBwj+AQc" |
| "TYLIHJvwhBzFe0gdE+kEHT/CaB2OMCQdt7roHgYopB4vs2gefiEkHqer6B72GaQfH6RoH" |
| "24SJB+XnOgf5gqkAABAAECAwEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQA" |
| "BAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEA" |
| "AQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABA" |
| "AEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAB//+dkAEA//+PgA" |
| "AE//+dkAEI//+dkAEMUERUAFBTVABQV1QAUFBUAAAAAAEAAAAB"); |
| |
| static const char *LA_VER2 = |
| ("VFppZjIAAAAAAAAAAAAAAAAAAAAAAAAFAAAABQAAAAAAAAC6AAAABQAAABSAAAAAnqZIoJ" |
| "+7FZCghiqgoZr3kMuJGqDSI/Rw0mEmENb+dCDYgK2Q2v7RoNvAkBDc3rOg3amskN6+laD" |
| "fiY6Q4J53oOFpcJDiflmg40lSkOReO6DlKTSQ5kdYIOcSURDoJzog6PIzEOoHHCDq0hUQ" |
| "6+b+IOyx9xDtxuAg7pHZEO+v/KDwcbsQ8Y/eoPJ/wZDzb8Cg9F+jkPVPoqD2P4WQ9y+Eo" |
| "PgoohD5D2ag+giEEPr4gyD76GYQ/NhlIP3ISBD+uEcg/6gqEACYKSABiAwQAngLIANxKJ" |
| "AEYSegBVEKkAZBCaAHMOyQB41DoAkQzpAJrb8gCvCwkAvgr6AM2c0QDcCRoA65rxAPqa4" |
| "gEJmREBGJkCASeXMQE2lyIBRZVRAVSVQgFjk3EBcpNiAYIlOQGQkYIBoCNZAa8jSgG+IX" |
| "kBzSFqAdwfmQHrH4oB+h25AgdisgIYG9kCJWDSAjatoQJDXvICVKvBAmFdEgJyqeECf+7" |
| "aApCoAQKd7PoCrqYhArvrGgLNN+kC2ek6Aus2CQL351oDCTQpAxZ5IgMnMkkDNHdCA0Uw" |
| "aQNSdWIDYy6JA3BzggOBwFEDjnGiA5++cQOsb8IDvbyRA8sBigPburED6P+qA/m40QQG/" |
| "coEGEqZBCT76gQ2SLkEQvoKBFRG2QRfPTIEctihBH07UgSQ1sEEmzlyBK7U4QS5yzoEzW" |
| "apBNfJWgTrZMkE9cd6BQli6QUTxZoFJ2EJBTHDugVFXykFT8HaBWNdSQVuU6IFge8RBYx" |
| "RwgWf7TEFqk/iBb3rUQXITgIF2+lxBeZMIgX555EGBN3qBhh5WQYi3AoGNnd5BkDaKgZU" |
| "dZkGXthKBnJzuQZ81moGkHHZBprUigaub/kGuWZSBs0BwQbXZHIG6v/hBvVikgcI/gEHE" |
| "2CyByb8IQcxXtIHRPpBB0/wmgdjjAkHbe66B4GKKQeL7NoHn4hJB6nq+ge9hmkHx+kaB9" |
| "uEiQfl5zoH+YKpACAQIBAgMEAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECA" |
| "QIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAg" |
| "ECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQI" |
| "BAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQL//5EmAAD//52Q" |
| "AQT//4+AAAj//52QAQz//52QARBMTVQAUERUAFBTVABQV1QAUFBUAAAAAAABAAAAAAFUW" |
| "mlmMgAAAAAAAAAAAAAAAAAAAAAAAAUAAAAFAAAAAAAAALsAAAAFAAAAFPgAAAAAAAAA//" |
| "///14EGsD/////nqZIoP////+fuxWQ/////6CGKqD/////oZr3kP/////LiRqg/////9I" |
| "j9HD/////0mEmEP/////W/nQg/////9iArZD/////2v7RoP/////bwJAQ/////9zes6D/" |
| "////3amskP/////evpWg/////9+JjpD/////4J53oP/////haXCQ/////+J+WaD/////4" |
| "0lSkP/////kXjug/////+UpNJD/////5kdYIP/////nElEQ/////+gnOiD/////6PIzEP" |
| "/////qBxwg/////+rSFRD/////6+b+IP/////ssfcQ/////+3G4CD/////7pHZEP/////" |
| "vr/yg//////BxuxD/////8Y/eoP/////yf8GQ//////NvwKD/////9F+jkP/////1T6Kg" |
| "//////Y/hZD/////9y+EoP/////4KKIQ//////kPZqD/////+giEEP/////6+IMg/////" |
| "/voZhD//////NhlIP/////9yEgQ//////64RyD//////6gqEAAAAAAAmCkgAAAAAAGIDB" |
| "AAAAAAAngLIAAAAAADcSiQAAAAAARhJ6AAAAAABVEKkAAAAAAGQQmgAAAAAAcw7JAAAAA" |
| "AB41DoAAAAAAJEM6QAAAAAAmtvyAAAAAACvCwkAAAAAAL4K+gAAAAAAzZzRAAAAAADcCR" |
| "oAAAAAAOua8QAAAAAA+priAAAAAAEJmREAAAAAARiZAgAAAAABJ5cxAAAAAAE2lyIAAAA" |
| "AAUWVUQAAAAABVJVCAAAAAAFjk3EAAAAAAXKTYgAAAAABgiU5AAAAAAGQkYIAAAAAAaAj" |
| "WQAAAAABryNKAAAAAAG+IXkAAAAAAc0hagAAAAAB3B+ZAAAAAAHrH4oAAAAAAfoduQAAA" |
| "AACB2KyAAAAAAIYG9kAAAAAAiVg0gAAAAACNq2hAAAAAAJDXvIAAAAAAlSrwQAAAAACYV" |
| "0SAAAAAAJyqeEAAAAAAn/u2gAAAAACkKgBAAAAAAKd7PoAAAAAAq6mIQAAAAACu+saAAA" |
| "AAALNN+kAAAAAAtnpOgAAAAAC6zYJAAAAAAL351oAAAAAAwk0KQAAAAADFnkiAAAAAAMn" |
| "MkkAAAAAAzR3QgAAAAADRTBpAAAAAANSdWIAAAAAA2MuiQAAAAADcHOCAAAAAAOBwFEAA" |
| "AAAA45xogAAAAADn75xAAAAAAOsb8IAAAAAA728kQAAAAADywGKAAAAAAPburEAAAAAA+" |
| "j/qgAAAAAD+bjRAAAAAAQG/coAAAAABBhKmQAAAAAEJPvqAAAAAAQ2SLkAAAAABEL6CgA" |
| "AAAAEVEbZAAAAAARfPTIAAAAABHLYoQAAAAAEfTtSAAAAAASQ1sEAAAAABJs5cgAAAAAE" |
| "rtThAAAAAAS5yzoAAAAABM1mqQAAAAAE18laAAAAAATrZMkAAAAABPXHegAAAAAFCWLpA" |
| "AAAAAUTxZoAAAAABSdhCQAAAAAFMcO6AAAAAAVFXykAAAAABU/B2gAAAAAFY11JAAAAAA" |
| "VuU6IAAAAABYHvEQAAAAAFjFHCAAAAAAWf7TEAAAAABapP4gAAAAAFvetRAAAAAAXITgI" |
| "AAAAABdvpcQAAAAAF5kwiAAAAAAX555EAAAAABgTd6gAAAAAGGHlZAAAAAAYi3AoAAAAA" |
| "BjZ3eQAAAAAGQNoqAAAAAAZUdZkAAAAABl7YSgAAAAAGcnO5AAAAAAZ81moAAAAABpBx2" |
| "QAAAAAGmtSKAAAAAAaub/kAAAAABrlmUgAAAAAGzQHBAAAAAAbXZHIAAAAABur/4QAAAA" |
| "AG9WKSAAAAAAcI/gEAAAAABxNgsgAAAAAHJvwhAAAAAAcxXtIAAAAAB0T6QQAAAAAHT/C" |
| "aAAAAAAdjjAkAAAAAB23uugAAAAAHgYopAAAAAAeL7NoAAAAAB5+ISQAAAAAHqer6AAAA" |
| "AAe9hmkAAAAAB8fpGgAAAAAH24SJAAAAAAfl5zoAAAAAB/mCqQAAIBAgECAwQCAQIBAgE" |
| "CAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIB" |
| "AgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECA" |
| "QIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAgECAQIBAg" |
| "ECAQIBAgECAQIBAgECAQIBAv//kSYAAP//nZABBP//j4AACP//nZABDP//nZABEExNVAB" |
| "QRFQAUFNUAFBXVABQUFQAAAAAAAEAAAAAAQpQU1Q4UERULE0zLjIuMCxNMTEuMS4wCg=="); |
| |
| const std::string& getVariantFromZone(const Timezone& zone, |
| const std::string& date) { |
| tm timeStruct; |
| if (strptime(date.c_str(), "%Y-%m-%d %H:%M:%S", &timeStruct) == nullptr) { |
| throw TimezoneError("bad time " + date); |
| } |
| return zone.getVariant(timegm(&timeStruct)).name; |
| } |
| |
| TEST(TestTimezone, testParser) { |
| std::unique_ptr<Timezone> la = getTimezone("America/Los_Angeles", |
| decodeBase64(LA_VER1)); |
| EXPECT_EQ(1, la->getVersion()); |
| EXPECT_EQ("PST", getVariantFromZone(*la, "1974-01-06 09:59:59")); |
| EXPECT_EQ("PDT", getVariantFromZone(*la, "1974-01-06 10:00:00")); |
| // v1 won't have information past 2038 |
| EXPECT_EQ("PST", getVariantFromZone(*la, "2100-03-14 09:59:59")); |
| EXPECT_EQ("PST", getVariantFromZone(*la, "2100-03-14 10:00:00")); |
| |
| la = getTimezone("America/Los_Angeles", decodeBase64(LA_VER2)); |
| EXPECT_EQ(2, la->getVersion()); |
| EXPECT_EQ("PST", getVariantFromZone(*la, "1974-01-06 09:59:59")); |
| EXPECT_EQ("PDT", getVariantFromZone(*la, "1974-01-06 10:00:00")); |
| EXPECT_EQ("PST", getVariantFromZone(*la, "2100-03-14 09:59:59")); |
| EXPECT_EQ("PDT", getVariantFromZone(*la, "2100-03-14 10:00:00")); |
| } |
| |
| TEST(TestTimezone, testZoneCache) { |
| const Timezone *la1 = &getTimezoneByName("America/Los_Angeles"); |
| const Timezone *ny1 = &getTimezoneByName("America/New_York"); |
| const Timezone *la2 = &getTimezoneByName("America/Los_Angeles"); |
| const Timezone *ny2 = &getTimezoneByName("America/New_York"); |
| EXPECT_EQ(la1, la2); |
| EXPECT_EQ(ny1, ny2); |
| EXPECT_EQ("PST", getVariantFromZone(*la1, "1974-01-06 09:59:59")); |
| EXPECT_EQ("PDT", getVariantFromZone(*la1, "1974-01-06 10:00:00")); |
| EXPECT_EQ("PDT", getVariantFromZone(*la1, "1974-10-27 08:59:59")); |
| EXPECT_EQ("PST", getVariantFromZone(*la1, "1974-10-27 09:00:00")); |
| EXPECT_EQ("EST", getVariantFromZone(*ny1, "1974-01-06 06:59:59")); |
| EXPECT_EQ("EDT", getVariantFromZone(*ny1, "1974-01-06 07:00:00")); |
| EXPECT_EQ("EDT", getVariantFromZone(*ny1, "1974-10-27 05:59:59")); |
| EXPECT_EQ("EST", getVariantFromZone(*ny1, "1974-10-27 06:00:00")); |
| } |
| |
| TEST(TestTimezone, testGMTv1) { |
| const char GMT[] = ("VFppZgAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAA" |
| "AAAAAAAAAAAQAAAAQAAAAAAABHTVQAAAA="); |
| std::unique_ptr<Timezone> gmt = getTimezone("GMT", decodeBase64(GMT)); |
| EXPECT_EQ(1, gmt->getVersion()); |
| EXPECT_EQ("GMT", getVariantFromZone(*gmt, "1974-01-06 09:59:59")); |
| EXPECT_EQ("GMT", getVariantFromZone(*gmt, "2015-06-06 12:34:56")); |
| } |
| } // namespace orc |