diff --git a/std/datetime/timezone.d b/std/datetime/timezone.d index c58af7f333b..6b4e4f4f6f2 100644 --- a/std/datetime/timezone.d +++ b/std/datetime/timezone.d @@ -2474,6 +2474,10 @@ public: { auto tzName = de.name[tzDatabaseDir.length .. $]; + // For the case where tzDatabaseDir does not have a trailing slash. + if (tzName.length > 1 && tzName[0] == '/') + tzName = tzName[1 .. $]; + if (!tzName.extension().empty || !tzName.startsWith(subName) || baseName(tzName) == "leapseconds" || @@ -2537,6 +2541,119 @@ public: } } + // https://github.com/dlang/phobos/issues/11000 + version (Posix) @safe unittest + { + version (Android) + {} + else + { + import std.algorithm.searching : canFind; + import std.file : chdir, copy, exists, getcwd, mkdirRecurse, rmdirRecurse, tempDir; + import std.path : buildPath; + + immutable baseDir = buildPath(tempDir, "tztest"); + immutable tzDir = buildPath(baseDir, "tz"); + immutable tzDirSlash = buildPath(baseDir, "tz/"); + immutable tzDirDoubleSlash = buildPath(baseDir, "tz//"); + assert(tzDirSlash[$ - 1] == '/'); // just in case buildPath ever strips the slash + + scope(failure) if (baseDir.exists) rmdirRecurse(baseDir); + + mkdirRecurse(buildPath(tzDir, "America")); + mkdirRecurse(buildPath(tzDir, "Europe")); + + copy(buildPath(defaultTZDatabaseDir, "America/Denver"), + buildPath(tzDir, "America/Denver")); + copy(buildPath(defaultTZDatabaseDir, "America/Denver"), + buildPath(tzDir, "America/Chicago")); + copy(buildPath(defaultTZDatabaseDir, "Europe/London"), + buildPath(tzDir, "Europe/London")); + copy(buildPath(defaultTZDatabaseDir, "UTC"), + buildPath(tzDir, "UTC")); + + foreach (dir; [tzDir, tzDirSlash, tzDirDoubleSlash]) + { + { + auto names = getInstalledTZNames("", dir); + assert(names.length == 4); + assert(names.canFind("America/Denver")); + assert(names.canFind("America/Chicago")); + assert(names.canFind("Europe/London")); + assert(names.canFind("UTC")); + } + { + auto names = getInstalledTZNames("America", dir); + assert(names.length == 2); + assert(names.canFind("America/Denver")); + assert(names.canFind("America/Chicago")); + } + } + + immutable cwd = getcwd(); + scope(exit) chdir(cwd); + + chdir(baseDir); + foreach (dir; ["tz", "tz/", "tz///"]) + { + { + auto names = getInstalledTZNames("", dir); + assert(names.length == 4); + assert(names.canFind("America/Denver")); + assert(names.canFind("America/Chicago")); + assert(names.canFind("Europe/London")); + assert(names.canFind("UTC")); + } + { + auto names = getInstalledTZNames("America", dir); + assert(names.length == 2); + assert(names.canFind("America/Denver")); + assert(names.canFind("America/Chicago")); + } + } + + immutable other = buildPath(baseDir, "other"); + mkdirRecurse(other); + chdir(other); + foreach (dir; ["../tz", "../tz/", "..///tz/////"]) + { + { + auto names = getInstalledTZNames("", dir); + assert(names.length == 4); + assert(names.canFind("America/Denver")); + assert(names.canFind("America/Chicago")); + assert(names.canFind("Europe/London")); + assert(names.canFind("UTC")); + } + { + auto names = getInstalledTZNames("America", dir); + assert(names.length == 2); + assert(names.canFind("America/Denver")); + assert(names.canFind("America/Chicago")); + } + } + + chdir(tzDir); + foreach (dir; [".", "./", ".///"]) + { + { + auto names = getInstalledTZNames("", dir); + assert(names.length == 4); + assert(names.canFind("America/Denver")); + assert(names.canFind("America/Chicago")); + assert(names.canFind("Europe/London")); + assert(names.canFind("UTC")); + } + { + auto names = getInstalledTZNames("America", dir); + assert(names.length == 2); + assert(names.canFind("America/Denver")); + assert(names.canFind("America/Chicago")); + } + } + } + } + private: