简而言之,如何让MSVCRT和MinGW MSYS共享TZ环境变量而不会发生冲突?或者,如何使两个支持时区没有冲突?
为了让MSYS的日期命令显示正确的本地时间,并且因为MSYS本身使用自己的C运行时而不是MSVCRT,我设置了TZ环境变量according to GNU C library documentation:
export TZ="BRT+3BRST,M10.3.0/0,M2.3.0/0"
不幸的是,this conflicts with Microsoft C runtime specs,它决定了DST名称部分:
如果夏令时在本地区永远不会生效,请设置TZ而不使用dzn的值。 C运行时库假定美国实施夏令时(DST)计算的规则
因此,在TZ变量中简单存在DST名称将导致依赖_tzset
的程序在美国境外发生故障。这是我的Bazaar DVCS的情况,我迟到了一小时的提交时间,因为MSVCRT假设我已经根据TZ设置进入了DST期间。如果我将TZ留空,MSYS日期显示UTC时间,但MSVCRT(和Bazaar)工作正常。如果我如上设置TZ,那么MSVCRT会增加一小时的提交时间,但MSYS日期会显示本地时间。
Bazaar受到影响,因为它使用的是Python,后者又在Windows下使用MSVCRT。即使我可以从DST名称中删除所有内容,这将破坏MSYS中的日期命令。我也尝试了几种TZ值。 MSYS似乎缺少比上面GNU参考中描述的更多的时区支持。另外,我想避免仅在调用Bazaar时设置TZ,或者仅在调用date命令时设置TZ,而是更通用的解决方案。
替代格式和zoneinfo数据库
TZ有另一种格式,上面的GNU文档中有第三种格式,但MSYS似乎不支持,如上所述:
但POSIX.1标准仅指定前两种格式的详细信息,
似乎第三种格式只是IANA的时区数据库which describes a different format for TZ,MSYS似乎也不支持它,如上所述:
要在扩展POSIX实现上使用数据库,请将TZ环境变量设置为该位置的全名,例如
TZ="America/New_York"
。
Desipe上面我试图手动将IANA的zoneinfo安装到MSYS上但没有成功。我不确定这些语句是否正确,MSYS甚至无法识别它们的格式,或者我是否无法正确安装zoneinfo数据文件。我找不到编译版本也不能自己编译,所以我只是尝试了Ubuntu的tzdata包。
但是,对我来说奇怪的是,上面的GNU C库文档已经提供了一个时区数据库(听起来像zoneinfo)。但是如上所述我在MSYS的任何地方都找不到任何类型的时区数据库,我也找不到任何与时区相关的mingw-get包。我想知道开发人员是否只是从发布中删除它。这就是文档所说的内容:GNU C Library附带了一个大型时区信息数据库,供大多数地区使用,由志愿者社区维护并置于公共领域。
总而言之,如果我可以在MSYS中制作zoneinfo或类似的替代工作,那么我可以放弃目前设置TZ的方法,如上所述。但是,我无法找到有关MSYS中时区支持的任何有用信息。
答案 0 :(得分:1)
简单的解决方案是按预期设置windows环境变量,然后将MSYS的〜/ .profile文件中的变量更改为POSIX所期望的值。
答案 1 :(得分:1)
我已经发现MSYS应该在没有TZ的情况下自动检测时区。以下错误报告记录了该问题:MSYS can't handle timeozones in localized Windows。
同时
到目前为止,我发现的最佳解决方案是这个错误没有得到修复:
创建一个以示例runcrt.sh
命名的包装脚本,可从系统路径获取并包含:
#!/bin/bash
env -u TZ $(basename "$0").exe "$@"
为此脚本创建NTFS符号链接,每个MSVCRT程序一个,我打算在MSYS中运行,但没有exe扩展,在系统路径中的实际可执行文件之前。例如,ruby,python,bzr等。
出于性能原因,在Windows初始化时将TZ的缓存配置(动态生成的导出语句)缓存到/etc/profile.d/timezone.sh
(实际上我们只需要每年更新一次TZ,这是DST期间的频率。改变,但无论如何)。
将BASH_ENV设置为/etc/profile.d/timezone.sh
,因此不仅可以使用交互式bash会话,还可以识别shell脚本。
这种方式,无论是交互式还是从shell脚本,例如,对bzr commit
的调用都会在代码库中获得正确的提交日期,因为该命令是在TZ未设置的情况下执行的。类似地,TZ设置为所有其他命令,例如date和ls,因此它们也打印正确的本地时间。我已经放弃了仅针对MSYS命令设置TZ的相反方法,并将其留空其他任何内容,因为取消设置操作比导出导出要快得多。
MSYS2作为替代
然而,MSYS2不受此错误的影响,并正确识别时区。事实上,它有适当的时区支持:
$ 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)
答案 2 :(得分:0)
在您的环境中,在没有msys的情况下运行纯Windows时没有任何问题。当您不访问本机Windows应用程序(如Bazaar)时,运行纯msys时没有问题。这就是我从你的问题中所假设的。
为在msys下运行的每个Windows命令取消设置TZ
的特殊脚本包装器似乎是合理的,我想这就是你所做的。我知道这不是你期望的答案,也不是你自己写的答案,但由于没有其他答案,我认为至少有一个应该在这里:)最不邪恶。
最后,我设想3级设置TZ
:
/etc/profile
或msys.bat
#!/bin/bash
{export TZ=; /usr/bin/bazaar "$@"
我无法想象一个更通用的解决方案。 shell如何知道给定命令首选哪个版本的/usr/local/bin/bazaar
变量?