You need to enable JavaScript to run this app. macOS bash 中 date 处理 Asia/Yakutsk 时区为何返回 +0900 而非 +1000
优惠活动
大模型
产品
解决方案
定价
更多

macOS bash 中 date 处理 Asia/Yakutsk 时区为何返回 +0900 而非 +1000

这是两个问题叠加导致的,既存在tzdata过旧的问题,也存在BSD date不识别输入UTC偏移的问题:

1. BSD date 根本不会使用输入里%z对应的偏移

你当前输出的时分秒和输入完全一致,已经能说明这个问题:如果+1000真的参与了时刻计算,UTC+10的14:46转换到UTC+9应该是13:46,时间分量必然发生变化。

可以跑这条命令直接验证:

TZ=UTC date -j -f "%Y:%m:%d %H:%M:%S%z" "2014:09:28 14:46:56+1000" +"%Y:%m:%d %H:%M:%S%z"

输出如果是2014:09:28 14:46:56+0000即可实锤:BSD date调用strptime拿到时间结构后,直接把输入的年月日时分秒当作TZ指定时区的本地时间传给mktime计算,完全忽略%z解析出的tm_gmtoff字段。
而GNU date的逻辑是优先用输入自带的偏移算出绝对时间戳,再转换到目标时区输出,行为符合预期。

2. macOS自带tzdata确实版本过旧

你贴的zdump结果已经直接体现了:macOS的时区规则只收录到2009年的夏令时切换,2010年之后的所有变更都缺失,默认按最后一条「UTC+9标准时」规则向后延伸到2038年。

雅库茨克时区的实际变更时间线和你的判断一致:

  • 2011年3月前:冬令时UTC+9、夏令时UTC+10
  • 2011年3月27日起:俄罗斯取消冬令时切换,永久保持UTC+10
  • 2014年10月26日起:调回永久UTC+9

你测试的2014年9月28日正好处在UTC+10区间。

单独验证tzdata可以跑这条:

TZ=Asia/Yakutsk date -j -f "%Y-%m-%d" "2014-09-28" +"%z"

旧tzdata输出+0900,2014年之后更新的tzdata会输出+1000。

修复方法

方案一:换用GNU date(和Linux行为完全一致,最推荐)

通过Homebrew安装coreutils工具集:

brew install coreutils

安装后GNU版date命令名为gdate,直接替换原命令即可,参数和Debian环境完全通用:

TZ="Asia/Yakutsk" gdate --date "2014-09-28 14:46:56+1000" +"%Y:%m:%d %H:%M:%S%z"

方案二:仅更新tzdata(无法解决输入偏移失效问题)

如果要保留BSD date用法,可以先更新时区数据库:

brew install tzdata
export TZDIR="$(brew --prefix)/share/zoneinfo"

更新后时区偏移查询会恢复正常,但输入字符串里的%z仍然会被忽略,需要提前把输入时间转换为目标时区的本地时间再传入。

方案三:用系统自带Python处理(无需额外安装工具)

新版macOS预装Python3,可以直接处理带偏移的时间字符串,同时遵循TZ环境变量:

TZ="Asia/Yakutsk" python3 -c "from datetime import datetime; print(datetime.strptime('2014:09:28 14:46:56+1000', '%Y:%m:%d %H:%M:%S%z').strftime('%Y:%m:%d %H:%M:%S%z'))"

内容的提问来源于stack exchange,提问作者jotzet79

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 07:06:07