diff --git a/CHANGES.txt b/CHANGES.txt index 7e7762d..56e6b9f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,7 +4,22 @@ Changes 4.0.3 (unreleased) ------------------ -- Nothing changed yet. +- It turns out a lot of Linux distributions make the links between zoneinfo + aliases backwards, so instead of linking GB to Europe/London it actually + links the other way. When /etc/localtime then links to Europe/London, and you + also have a config file saying Europe/London, the code that checks if + /etc/localtime is a symlink ends up at GB instead of Europe/London and + we get an error, as it thinks GB and Europe/London are different zones. + + So now we check the symlink of all timezones in the uniqueness test. We still + return the name in the config file, though, so you would only get GB or Zulu + returned as the time zone instead of Europe/London or UTC if your only + configuration is the /etc/localtime symlink, as that's checked last, and + tzlocal will return the first configuration found. + +- The above change also means that GMT and UTC are no longer seen as synonyms, + as zoneinfo does not see them as synonyms. This might be controversial, + but you just have to live with it. Pick one and stay with it. ;-) 4.0.2 (2021-10-26) diff --git a/tests/test_data/noconflict/etc/localtime b/tests/test_data/noconflict/etc/localtime new file mode 120000 index 0000000..4bdf675 --- /dev/null +++ b/tests/test_data/noconflict/etc/localtime @@ -0,0 +1 @@ +../usr/share/zoneinfo/Zulu \ No newline at end of file diff --git a/tests/test_data/noconflict/etc/timezone b/tests/test_data/noconflict/etc/timezone index 330a1b1..efdba06 100644 --- a/tests/test_data/noconflict/etc/timezone +++ b/tests/test_data/noconflict/etc/timezone @@ -1 +1 @@ -UTC# We allow comments. It's unusual, but has happened +Etc/UTC# We allow comments. It's unusual, but has happened diff --git a/tests/test_data/noconflict/usr/share/zoneinfo/Etc/UCT b/tests/test_data/noconflict/usr/share/zoneinfo/Etc/UCT new file mode 120000 index 0000000..1ed0820 --- /dev/null +++ b/tests/test_data/noconflict/usr/share/zoneinfo/Etc/UCT @@ -0,0 +1 @@ +UTC \ No newline at end of file diff --git a/tests/test_data/noconflict/usr/share/zoneinfo/Etc/UTC b/tests/test_data/noconflict/usr/share/zoneinfo/Etc/UTC new file mode 100644 index 0000000..5583f5b Binary files /dev/null and b/tests/test_data/noconflict/usr/share/zoneinfo/Etc/UTC differ diff --git a/tests/test_data/noconflict/usr/share/zoneinfo/UTC b/tests/test_data/noconflict/usr/share/zoneinfo/UTC new file mode 120000 index 0000000..e8fc73f --- /dev/null +++ b/tests/test_data/noconflict/usr/share/zoneinfo/UTC @@ -0,0 +1 @@ +Etc/UCT \ No newline at end of file diff --git a/tests/test_data/noconflict/usr/share/zoneinfo/Zulu b/tests/test_data/noconflict/usr/share/zoneinfo/Zulu new file mode 120000 index 0000000..1ed0820 --- /dev/null +++ b/tests/test_data/noconflict/usr/share/zoneinfo/Zulu @@ -0,0 +1 @@ +UTC \ No newline at end of file diff --git a/tests/test_tzlocal.py b/tests/test_tzlocal.py index caad37e..fbd471e 100644 --- a/tests/test_tzlocal.py +++ b/tests/test_tzlocal.py @@ -271,9 +271,12 @@ def test_conflicting(): assert "localtime is a symlink to: Africa/Harare" in message +@pytest.mark.skipif( + platform.system() == "Windows", reason="Symbolic links are not available on Windows" +) def test_noconflict(): tz = tzlocal.unix._get_localzone(_root=tz_path("noconflict")) - assert str(tz) == "UTC" + assert str(tz) == "Etc/UTC" def test_pytz_compatibility(): diff --git a/tzlocal/unix.py b/tzlocal/unix.py index 4c170d6..eaf96d9 100644 --- a/tzlocal/unix.py +++ b/tzlocal/unix.py @@ -126,18 +126,15 @@ def _get_localzone_name(_root="/"): if len(found_configs) > 1: # Uh-oh, multiple configs. See if they match: unique_tzs = set() + zoneinfo = os.path.join(_root, "usr", "share", "zoneinfo") + directory_depth = len(zoneinfo.split(os.path.sep)) + for tzname in found_configs.values(): - # Get rid of any Etc's - tzname = tzname.replace("Etc/", "") - # Let's handle these synonyms as well. Many systems have tons - # of synonyms, including country names and other non-zoneinfo - # nonsense. Those will be seen as different ones. Let's stick - # to the official zoneinfo Continent/City names. - if tzname in ["GMT0", "GMT+0", "GMT-0"]: - tzname = "GMT" - if tzname in ["UCT", "Zulu"]: - tzname = "UTC" - unique_tzs.add(tzname) + # Look them up in /usr/share/zoneinfo, and find what they + # really point to: + path = os.path.realpath(os.path.join(zoneinfo, *tzname.split("/"))) + real_zone_name = "/".join(path.split(os.path.sep)[directory_depth:]) + unique_tzs.add(real_zone_name) if len(unique_tzs) != 1: message = "Multiple conflicting time zone configurations found:\n"