
django 并不直接读取系统 `tz` 环境变量,而是优先使用其内置设置 `time_zone`(默认为 `"america/chicago"`),该设置独立于操作系统级 `tz` 变量,用于控制 django 的默认时区行为。
在 Django 应用中,你可能会观察到一个看似矛盾的现象:通过 os.environ.get('TZ') 在普通 Python 脚本或 shell 中能正确获取系统设置的时区(如 "Asia/Shanghai"),但在 Django 项目中却始终返回 "America/Chicago" —— 即使 printenv TZ 和 os.environ 其他键值均与系统一致。
这并非 Django “覆盖”了 TZ 环境变量,而是Django 根本不依赖 TZ 环境变量做时区决策。根据 Django 官方文档,Django 使用的是 TIME_ZONE 设置项(对应 settings.py 中的 TIME_ZONE 配置),该配置默认为 'America/Chicago'(新项目模板中已改为 'UTC')。这个值仅用于定义 Django 的默认时区(default time zone),即未启用时区支持(USE_TZ = False)时的本地时间基准,或作为 timezone.get_default_timezone() 的返回值。
✅ 正确做法是:
-
若需统一时区行为,请显式在 settings.py 中设置:
# settings.py TIME_ZONE = 'Asia/Shanghai' # 或从环境变量安全读取 USE_TZ = True # 强烈建议启用,以使用 UTC 存储 + 本地化显示
-
如需动态从环境变量加载(推荐生产环境):
import os from django.core.exceptions import ImproperlyConfigured def get_env_setting(name, default=None): value = os.environ.get(name, default) if value is None: raise ImproperlyConfigured(f"Required environment variable {name} not set.") return value TIME_ZONE = get_env_setting('DJANGO_TIME_ZONE', 'UTC')
⚠️ 注意事项:
- os.environ['TZ'] 的修改(如 os.environ['TZ'] = 'Asia/Shanghai')对 Django 的 datetime 行为无效,因为 Python 的 time 模块时区缓存(time.tzset())仅影响 time.* 函数,而 Django 主要依赖 zoneinfo(Python 3.9+)或 pytz 进行时区处理;
- 修改 TZ 环境变量后若调用 time.tzset(),可能影响 datetime.datetime.now() 等原生函数,但不会改变 django.utils.timezone.now() 的行为;
- 始终优先使用 django.utils.timezone.now() 而非 datetime.datetime.now(),确保时区逻辑与 Django 设置一致。
总结:Django 的时区逻辑由 TIME_ZONE 和 USE_TZ 两个设置共同驱动,与系统 TZ 变量无直接关联。解决“TZ 不一致”问题的关键,不是修复环境变量读取,而是明确配置并统一管理 Django 的 TIME_ZONE 设置。









