本文介绍了MinGW MSYS,MSVCRT和TZ环境变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简而言之,如何使MSVCRT和MinGW MSYS共享TZ环境变量而不会发生冲突?或者,如何使两个支持时区都没有冲突?

In short, how to make both MSVCRT and MinGW MSYS share the TZ environment variable without conflicts? Or, how to make both support timezones without conflicts?

为了使MSYS的date命令显示正确的本地时间,并且由于MSYS本身使用其自己的C运行时而不是MSVCRT,我设置了TZ环境变量根据GNU C库文档:

In order to have date command of MSYS displaying correct local time, and because MSYS itself uses its own C runtime instead of MSVCRT, I have set TZ environment variable according to GNU C library documentation:

export TZ="BRT+3BRST,M10.3.0/0,M2.3.0/0"

不幸的是,这与Microsoft C冲突运行时规范,其中规定了DST名称部分:

Unfortunately, this conflicts with Microsoft C runtime specs, which dictates for the DST name part:

因此,在TZ变量中仅存在DST名称将导致依赖_tzset的程序在美国以外出现故障.我在Bazaar DVCS上就是这种情况,我在错误的提交时间上晚了一个小时,因为MSVCRT假定我已经基于TZ设置进入了夏令时.如果我将TZ保留为空,则MSYS日期显示UTC时间,但是MSVCRT(和Bazaar)可以正常工作.如果我将TZ设置为如上所述,则MSVCRT会增加一小时的提交时间,但是MSYS日期会显示本地时间.

Hence, the simple presence of a DST name in TZ variable will cause programs relying on _tzset to malfunction outside the USA. This is my case with Bazaar DVCS, where I have been getting wrong commit times, one hour late, because MSVCRT assumes I have already entered DST period based on TZ setting. If I leave TZ empty, MSYS date displays UTC time, but MSVCRT (and Bazaar) works just fine. If I set TZ as above, then MSVCRT adds one hour to commit times, but MSYS date displays local time.

Bazaar受到影响,因为它使用Python,而后者又在Windows下使用MSVCRT.即使可以删除DST名称上的所有内容,这也会中断MSYS中的date命令.我也尝试了TZ的几个值. MSYS似乎缺少比GNU参考文献中上面描述的时区更多的时区支持.另外,我想避免仅在调用Bazaar时设置TZ,或者仅在调用date命令时才设置TZ,而是更通用的解决方案.

Bazaar is affected because it uses Python which in turn uses MSVCRT under Windows. Even though I can remove everything from DST name on, that will break date command in MSYS. I have tried several values of TZ as well. MSYS seems to lack any further timezone support than what is described above in GNU reference. Also, I wanted to avoid having TZ not set only when invoking Bazaar, or have it set only when invoking date command, but rather a more general solution.

备用格式和zoneinfo数据库

TZ有另一种格式,这是上面的GNU文档中的第三种格式,但是MSYS似乎不支持它,如下所述:

There is an alternative format for TZ, third one in GNU documentation above, but it seems to not be supported by MSYS, as stated:

似乎第三种格式只是IANA的时区数据库, 描述了TZ的另一种格式,似乎也不受MSYS支持,

It seems this third format is just IANA's Time Zone Database, which describes a different format for TZ which seems to not be supported by MSYS either, as stated:

描述以上内容,我尝试将IANA的zoneinfo手动安装到MSYS上,但没有成功.我不确定这些语句是否正确以及它们的格式甚至不能被MSYS识别,或者我只是无法正确安装zoneinfo数据文件.我找不到编译版本,也无法编译自己,所以我只是试用了Ubuntu的tzdata软件包.

Desipe the above I tried to install IANA's zoneinfo manually onto MSYS without success. I'm not sure if these statements are correct and their formats aren't even recognized by MSYS, or if I just have failed to install zoneinfo data files correctly. I couldn't find a compiled version neither could I compile myself, so I just tried out the tzdata package from Ubuntu.

让我感到奇怪的是,上面的GNU C库文档表明它已经带有一个时区数据库(在我看来,它类似于zoneinfo).但是,正如我所说的那样,我找不到在MSYS中任何位置安装的任何类型的时区数据库,也找不到与时区相关的任何mingw-get程序包.我想知道开发人员是否只是从发行版中删除了它.这就是文档所说的:

Something odd to me, though, is that GNU C library documentation above stands it comes with a timezone database already (it sounds to me like zoneinfo). However as said I can't find any kind of timezone database installed anywhere in MSYS, neither I can find any mingw-get package related to timezones. I wonder if the developers simply removed it from the release. This is what the documentation says:

因此,总而言之,如果我可以在MSYS中进行zoneinfo或类似的替代工作,那么我可以放弃上面设置TZ的当前方法.但是,我找不到有关MSYS中时区支持的任何有用信息.

So in sum, if I could make zoneinfo or similar alternative work in MSYS, then I could abandon my current approach of setting TZ as above. I can't find, however, any good information about timezone support in MSYS.

推荐答案

我发现MSYS实际上应该在没有TZ的情况下自动检测时区.以下错误报告记录了该问题: MSYS可以在本地化的Windows中处理时区.

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.

与此同时

到目前为止,我发现的最好的解决方案是:

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

  1. 创建一个名为runcrt.sh的包装脚本,该脚本可从系统路径获得并包含:

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

#!/bin/bash
env -u TZ $(basename "$0").exe "$@"

  • 为此脚本创建NTFS符号链接,为我打算在MSYS中运行的每个MSVCRT程序创建一个NTFS符号链接,但没有exe扩展名,并且位于系统路径中的实际可执行文件之前.例如,ruby,python,bzr等.

  • 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.

    出于性能方面的考虑,在Windows初始化时将TZ(动态生成的导出语句)的缓存配置存储到/etc/profile.d/timezone.sh中(实际上,我们只需要每年更新一次TZ,这就是DST周期可能多久更改一次,但无论如何).

    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).

    将BASH_ENV设置为/etc/profile.d/timezone.sh,因此不仅交互式bash会话而且Shell脚本都可以识别时区.

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

    例如,通过交互方式或从Shell脚本调用bzr commit,将在代码存储库中获得正确的提交日期,因为该命令是在未设置TZ的情况下执行的.同样,为所有其他命令(例如date和ls)设置了TZ,因此它们也将打印正确的本地时间.我放弃了相反的方法,即仅对MSYS命令设置TZ,而对其他任何内容都保留TZ,因为未设置的操作比采购导出要快得多.

    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

    MSYS2不受此错误影响,并且可以正确识别时区.实际上,它具有适当的时区支持:

    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)
    

    这篇关于MinGW MSYS,MSVCRT和TZ环境变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

  • 08-01 21:29