【问题标题】:MinGW MSYS, MSVCRT, and the TZ environment variableMinGW MSYS、MSVCRT 和 TZ 环境变量
【发布时间】:2012-10-07 02:38:50
【问题描述】:

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

更多信息

为了让 MSYS 的 date 命令显示正确的本地时间,并且由于 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,而 Python 在 Windows 下又使用 MSVCRT。即使我可以从 DST 名称中删除所有内容,这也会破坏 MSYS 中的日期命令。我也尝试了 TZ 的几个值。除了上面 GNU 参考中描述的内容之外,MSYS 似乎缺少任何进一步的时区支持。另外,我想避免只在调用 Bazaar 时设置 TZ,或者只在调用 date 命令时设置它,而是一个更通用的解决方案。

替代格式和 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 库带有一个包含世界大部分地区时区信息的大型数据库,由志愿者社区维护并公开。

总之,如果我可以在 MSYS 中使用 zoneinfo 或类似的替代方法,那么我可以放弃当前设置 TZ 的方法。但是,我在 MSYS 中找不到任何关于时区支持的好信息。

【问题讨论】:

    标签: timezone mingw msvcrt msys


    【解决方案1】:

    简单的解决方案是按照预期设置 Windows 环境变量,然后将 MSYS 的 ~/.profile 文件中的变量更改为 POSIX 预期的变量。

    【讨论】:

      【解决方案2】:

      我发现 MSYS 实际上应该在没有 TZ 的情况下自动检测时区。以下错误报告记录了该问题:MSYS can't handle timeozones in localized Windows

      同时

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

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

        #!/bin/bash
        env -u TZ $(basename "$0").exe "$@"
        
      2. 创建指向此脚本的 NTFS 符号链接,一个用于我打算在 MSYS 中运行的每个 MSVCRT 程序,但没有 exe 扩展名,并且在系统路径中的实际可执行文件之前。比如ruby、python、bzr等

      3. 1234563但无论如何)。
      4. 将 BASH_ENV 设置为 /etc/profile.d/timezone.sh,这样不仅交互式 bash 会话,而且 shell 脚本也可以识别时区。

      通过这种方式,例如,以交互方式或从 shell 脚本调用 bzr commit,将在代码存储库中获得正确的提交日期,因为该命令是在未设置 TZ 的情况下执行的。同样,为所有其他命令(例如 date 和 ls)设置了 TZ,因此它们也打印正确的本地时间。我已经放弃了只为 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)
      

      【讨论】:

        【解决方案3】:

        在您的环境中,在没有 msys 的情况下运行纯 Windows 不会有任何问题。当您不访问本机 Windows 应用程序(如 Bazaar)时,运行纯 msys 也没有问题。这就是我从你的问题中假设的。

        为在 msys 下运行的每个 windows 命令取消设置 TZ 的特殊脚本包装器似乎是合理的,我想这就是你所做的。我知道这不是您期望的答案,也不是您可以自己写的答案,但由于没有其他答案,我认为至少应该在这里:) 最不邪恶。

        最后我想象3级设置TZ

        1. 在 Windows 系统设置中为 Microsoft 设置的值
        2. /etc/profilemsys.bat 中设置的Msys 值
        3. Microsoft 在包装器中再次用于在 Msys 中运行 Windows 命令的值,例如:
          #!/bin/bash
          export TZ=; /usr/bin/bazaar "$@"
          在文件/usr/local/bin/bazaar

        我想不出更通用的解决方案。 shell 如何知道给定命令首选哪个版本的TZ 变量?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-16
          • 2019-08-21
          相关资源
          最近更新 更多