Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ORC-1684: [C++] Find tzdb without TZDIR when in conda-environments #1882

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions c++/src/Timezone.cc
Original file line number Diff line number Diff line change
Expand Up @@ -656,10 +656,18 @@ namespace orc {
epoch_ = utcEpoch - getVariant(utcEpoch).gmtOffset;
}

const char* getTimezoneDirectory() {
std::string getTimezoneDirectory() {
const char* dir = getenv("TZDIR");
if (!dir) {
dir = DEFAULT_TZDIR;
// this is present if we're in an activated conda environment
const char* condaPrefix = getenv("CONDA_PREFIX");
if (condaPrefix) {
std::string condaDir(condaPrefix);
condaDir += "/share/zoneinfo";
return condaDir;
} else {
dir = DEFAULT_TZDIR;
}
}
return dir;
}
Expand Down
50 changes: 46 additions & 4 deletions c++/test/TestTimezone.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "wrap/gmock.h"
#include "wrap/gtest-wrapper.h"

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
Expand Down Expand Up @@ -421,20 +422,61 @@ namespace orc {
}

TEST(TestTimezone, testMissingTZDB) {
const char* tzDirBackup = std::getenv("TZDIR");
if (tzDirBackup != nullptr) {
const char* tzDir = std::getenv("TZDIR");
std::string tzDirBackup;
if (tzDir != nullptr) {
// std::string creates a deepcopy of buffer, which avoids that
// unsetting environment variable wrecks pointer to tzDir
tzDirBackup = tzDir;
ASSERT_TRUE(delEnv("TZDIR"));
}
ASSERT_TRUE(setEnv("TZDIR", "/path/to/wrong/tzdb"));
EXPECT_THAT([]() { getTimezoneByName("America/Los_Angeles"); },
testing::ThrowsMessage<TimezoneError>(testing::HasSubstr(
"Time zone file /path/to/wrong/tzdb/America/Los_Angeles does not exist."
" Please install IANA time zone database and set TZDIR env.")));
if (tzDirBackup != nullptr) {
ASSERT_TRUE(setEnv("TZDIR", tzDirBackup));
if (!tzDirBackup.empty()) {
ASSERT_TRUE(setEnv("TZDIR", tzDirBackup.c_str()));
} else {
ASSERT_TRUE(delEnv("TZDIR"));
}
}

TEST(TestTimezone, testTzdbFromCondaEnv) {
const char* tzDir = std::getenv("TZDIR");
// test only makes sense if TZDIR exists
if (tzDir != nullptr) {
std::string tzDirBackup = tzDir;
ASSERT_TRUE(delEnv("TZDIR"));

// remove "/share/zoneinfo" from TZDIR (as set through TZDATA_DIR in CI) to
// get the equivalent of CONDA_PREFIX, relative to the location of the tzdb
std::string condaPrefix(tzDirBackup);
condaPrefix += "/../..";
ASSERT_TRUE(setEnv("CONDA_PREFIX", condaPrefix.c_str()));
h-vetinari marked this conversation as resolved.
Show resolved Hide resolved

// small test sample to ensure tzbd loads with CONDA_PREFIX, even without TZDIR
const Timezone* zrh = &getTimezoneByName("Europe/Zurich");
EXPECT_EQ("CET", getVariantFromZone(*zrh, "2024-03-31 00:59:59"));
EXPECT_EQ("CEST", getVariantFromZone(*zrh, "2024-03-31 01:00:00"));
EXPECT_EQ("CEST", getVariantFromZone(*zrh, "2024-10-27 00:59:59"));
EXPECT_EQ("CET", getVariantFromZone(*zrh, "2024-10-27 01:00:00"));

// CONDA_PREFIX contains backslashes on windows; test that this doesn't blow up
std::replace(condaPrefix.begin(), condaPrefix.end(), '/', '\\');
ASSERT_TRUE(setEnv("CONDA_PREFIX", condaPrefix.c_str()));

// as above, but different timezone to avoid hitting cache
const Timezone* syd = &getTimezoneByName("Australia/Sydney");
EXPECT_EQ("AEDT", getVariantFromZone(*syd, "2024-04-06 15:59:59"));
EXPECT_EQ("AEST", getVariantFromZone(*syd, "2024-04-06 16:00:00"));
EXPECT_EQ("AEST", getVariantFromZone(*syd, "2024-10-05 15:59:59"));
EXPECT_EQ("AEDT", getVariantFromZone(*syd, "2024-10-05 16:00:00"));

// restore state of environment variables
ASSERT_TRUE(delEnv("CONDA_PREFIX"));
ASSERT_TRUE(setEnv("TZDIR", tzDirBackup.c_str()));
}
}

} // namespace orc
Loading