一句话结论:
date的默认输出格式由LC_TIME决定,与时区无关。LC_TIME=C.UTF-8(或en_GB.UTF-8)即得 24 小时制;LANG=zh_CN.UTF-8则连日期文字一起变中文。两者都写入/etc/locale.conf,对当前已登录会话不生效,需重新登录或export。
1. 原理:谁决定了 date 的输出长相
date 不加格式串时的输出,取自当前 locale 的 LC_TIME 类目下的 d_t_fmt(日期+时间格式串):
| locale | d_t_fmt 的时间部分 | date 呈现 |
|---|---|---|
en_US.UTF-8 | %r(12 小时 + AM/PM) | Sat Nov 7 07:55:42 PM CST 2026 |
C.UTF-8 / POSIX / en_GB.UTF-8 | %H:%M:%S | Sat Nov 7 19:56:42 CST 2026 |
zh_CN.UTF-8 | %H:%M:%S + 中文星期/年月日 | 2026年 11月 07日 星期六 17:54:32 CST |
locale 生效优先级(高 → 低):LC_ALL > LC_TIME > LANG > 默认 C。
由此两条推论:
- 改 24 小时制不必动语言 —— 只设
LC_TIME即可,LANG保持en_US.UTF-8,日志与命令输出仍是英文,脚本可继续按原格式解析。 - 原文两个案例恰好是这两种取向:案例一「只动
LC_TIME」,案例二「连LANG一起动」。生产环境优先选案例一的思路。
2. 案例一:12 小时制 → 24 小时制(不动语言)
原文终端记录还原(已去掉提示符、按行拆开,可直接复制):
# 1) 现状:PM 即 12 小时制
date
# Sat Nov 7 07:55:42 PM CST 2026
localectl
# System Locale: LANG=en_US.UTF-8
# VC Keymap: us
# X11 Layout: us
# 2) 只追加 LC_TIME,保留现有 LANG
localectl set-locale LC_TIME=C.UTF-8
# 3) 验证(改的是配置文件,当前会话尚未生效)
localectl
# System Locale: LANG=en_US.UTF-8
# VC Keymap: us
# X11 Layout: us
# 注意:原文此处打印里出现了 LC_TIME=C.UTF-8 一行;localectl 会把 /etc/locale.conf 中所有
# LANG/LC_* 逐行列出,以实际机器输出为准。
# 4) 退出并重新登录,再查
exit
# logout
date
# Sat Nov 7 19:56:42 CST 2026 ← 24 小时制
要点
localectl set-locale只修改参数中给出的变量,未给出的LANG原样保留,所以这一步不会把系统语言改掉。- 写盘位置:
/etc/locale.conf(systemd-localed 管理),等价于手工写入LC_TIME=C.UTF-8。 - 原文用「退出 → 重新登录」来生效,这是最稳妥的方式。若
locale -a里查不到C.UTF-8,改用LC_TIME=en_GB.UTF-8(同为 24 小时制、日期仍是英文)或LC_TIME=C。
3. 案例二:英文时间显示 → 中文时间显示
# 1) 现状:英文 + 24 小时制(LANG 为 C.UTF-8)
date
# Sat Nov 7 16:24:20 CST 2026
cat /etc/locale.conf
# LANG="C.UTF-8"
# 2) 装中文语言包
dnf install -y langpacks-zh_CN
# 3) 确认 zh_CN 系列 locale 已生成
locale -a | grep zh_CN
# zh_CN
# zh_CN.gb18030
# zh_CN.gbk
# zh_CN.utf8
# 4) 系统语言改为中文
localectl set-locale LANG=zh_CN.utf8
cat /etc/locale.conf
# LANG=zh_CN.utf8
# 5) 显式指定时间本地化类目(LANG 已是 zh_CN 时此步等价、可省略)
localectl set-locale LC_TIME=zh_CN.UTF-8
localectl
# System Locale: LANG=zh_CN.utf8
# VC Keymap: cn
# X11 Layout: cn
# 6) 重新登录验证
exit
# logout
date
# 2026年 11月 07日 星期六 17:54:32 CST
要点
langpacks-zh_CN是元包,真正提供 locale 数据的是glibc-langpack-zh。最小化安装若提示找不到langpacks-zh_CN,直接装dnf install -y glibc-langpack-zh,再用locale -a | grep zh_CN验证。- 输出里
VC Keymap: cn/X11 Layout: cn不是原文笔误:localectl在未显式配置键盘布局时,会按LANG的国家码推导出cn(案例一en_US推导为us)。这是localectl的既定行为,不影响 SSH 场景,但本地虚拟机图形控制台的键盘布局会跟着变。 zh_CN.utf8与zh_CN.UTF-8是同一个 locale(字符集名大小写/横线写法均被 glibc 接受),原文两种写法混用,实践上建议统一写zh_CN.UTF-8。- 原文示例里前后时间戳从
16:24:20跳到17:54:32,是作者不同时段的截图拼接,不是一次连续执行,不影响结论。
4. 一页速查
# A. 只要 24 小时制,语言保持英文(运维推荐)
localectl set-locale LC_TIME=C.UTF-8
# B. 要中文日期,同时保留 24 小时制
dnf install -y glibc-langpack-zh
localectl set-locale LANG=zh_CN.UTF-8
localectl set-locale LC_TIME=zh_CN.UTF-8
# C. 只对本次命令临时验证,不落盘
LC_TIME=C.UTF-8 date
LC_TIME=zh_CN.UTF-8 date
# D. 当前 shell 立即生效(不退出登录)
export LC_TIME=C.UTF-8 # 必须 export;source /etc/locale.conf 只有赋值、没有 export
# E. 排查:确认各 LC_* 实际生效值
locale # 列出 LANG / LC_ALL / 各类目当前值
locale -a | grep -E 'C\.|en_GB|zh_CN'
locale -k LC_TIME | grep -E 'd_t_fmt|^t_fmt'
| 想做的事 | 参数 | 是否改语言 |
|---|---|---|
| 24 小时制,英文 | LC_TIME=C.UTF-8 | 否 |
| 24 小时制,英文(英式日期) | LC_TIME=en_GB.UTF-8 | 否 |
| 中文日期 + 中文报错 | LANG=zh_CN.UTF-8 | 是 |
| 改时区(与本主题无关) | timedatectl set-timezone Asia/Shanghai | 否 |
5. 生效时机与影响面
| 对象 | 何时读到新 locale |
|---|---|
| 新登录的 SSH / 本地终端 | 登录时读取 /etc/locale.conf |
| 当前已登录 shell | 不生效;用 export 或重新登录 |
| systemd 服务 | 服务启动时注入环境变量,改后需 systemctl restart |
| cron / 计划任务 | 同上,随任务进程启动读取 |
| 交互式已开窗口(tmux/screen) | 不生效,需断开重连 |
6. 坑与补充(原文未涉及)
- 别把「时间格式」和「时区」混为一谈。
CST一直没变,本案例完全没碰时区;12/24 小时制是 locale 的呈现格式,date的底色仍是时区换算。 LC_ALL会压掉LC_TIME。 若环境变量里已有LC_ALL(容器镜像、部分 systemd unit 常见),单设LC_TIME不生效,必须unset LC_ALL或直接改LC_ALL。source /etc/locale.conf无效。 该文件是LC_TIME=C.UTF-8形式的纯赋值,没有export,在 bash 里 source 后仍是普通 shell 变量,不会传给子进程。要立即生效请export LC_TIME=...。- 生产环境慎改
LANG。 全量中文化会让日志、ls -l时间、dnf输出等都变中文,依赖英文输出的巡检脚本、awk '{print $4}'提时间的解析会直接错位;Oracle、Java 等程序还从LANG推导NLS_LANG,改LANG可能连带影响数据库客户端字符集行为。只做格式调整时,坚持只改LC_TIME。 localectl与date不是同一层。localectl看的是持久化配置值,date看的是当前进程的环境变量,所以「localectl显示已改、date没变」是正常现象,不是失败。C.UTF-8存在的兼容兜底。 个别精简镜像locale -a无此条目,用en_GB.UTF-8;若连en_GB都没装,dnf install -y glibc-langpack-en或退到LC_TIME=C。- 远程会话看服务端。 通过 SSH 看到的
date由服务端 locale 决定,改本地客户端没用。

徐万新之路

