MinGW MSYS, MSVCRT, and the TZ environment variable

寵の児 提交于 2019-12-05 17:27:41

The simple solution is to set your windows environment variable as you expect then change the variable in your ~/.profile file for MSYS to what POSIX expects.

I have figured out MSYS should actually detect timezone automatically without TZ. The following bug report documents the problem: MSYS can't handle timeozones in localized Windows.

In the meanwhile

The best solution I have found so far while this bug doesn't get fixed was:

  1. Create a wrapper script named for example runcrt.sh, available from system path and containing:

    #!/bin/bash
    env -u TZ $(basename "$0").exe "$@"
    
  2. Create NTFS symlinks to this script, one for each MSVCRT program I intend to run in MSYS, but without the exe extension and before the actual executables in system path. For example, ruby, python, bzr etc.

  3. For performance reasons, cache configuration of TZ (the export statement generated dynamically) into /etc/profile.d/timezone.sh on Windows initialization (actually we just need to update TZ once a year, which is how often DST period may ever change, but whatever).

  4. Set BASH_ENV to /etc/profile.d/timezone.sh, so not just interactive bash sessions but also shell scripts can be timezone aware.

This way, either interactively or from a shell script, calls to bzr commit, for instance, will get the right commit date into the code repository, because that command is being executed with TZ unset. Similarly, TZ is set for all the other commands such as date and ls, so they print the correct local time as well. I have dropped the opposite approach of setting TZ only for MSYS commands and leaving it blank for anything else because the unset operation is much faster than sourcing the export.

MSYS2 as alternative

MSYS2, however, is not affected by this bug and recognizes the timezone correctly. In fact, it has proper timezone support:

$ tzset
America/Sao_Paulo

$ date +"%T, timezone %Z (%z)"
10:18:12, timezone BRT (-0300)

$ TZ=America/Los_Angeles date +"%T, timezone %Z (%z)"
06:18:14, timezone PDT (-0700)

In your environment you don't have any problems running pure Windows, without msys. And you have no problems running pure msys, when you don't access native Windows apps, like Bazaar. That's what I assume from your question.

Special script wrappers unsetting TZ for every windows command run under msys seems to be reasonable and I guess that's what you do. I know this is not the answer you expected or the one you could write yourself, but since there are no other answers, I thought at least one should be here :) The least evil.

Finally I imagine 3 levels of setting TZ:

  1. A value for Microsoft set in Windows system settings
  2. A value for Msys set in /etc/profile or msys.bat
  3. A value for Microsoft again in wrappers to run Windows commands within Msys, like:
    #!/bin/bash
    export TZ=; /usr/bin/bazaar "$@"
    in the file /usr/local/bin/bazaar

I can't imagine a more general solution. How can a shell know which version of TZ variable is preferred for the given command?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!