Utilo

解释了Unix时间:秒,毫秒,时区和2038

如何转换每个主要语言的时间,以及如何避免时区,毫秒和Y2038错误。

· 5 分钟阅读

Open almost any log file,database table or API response and you will find numbers like 1760000000。这是一个Unix时间:自1970年1月1日00:00:00 UTC以来的秒数,。计算机最常见的时间表现方式,了解它可以防止一系列涉及时区,夏令和日期解析的错误。

为什么从1970年开始数秒?

早期的Unix开发人员需要一个简单的,紧的时间表示。从一个固定的近期日期计算秒钟,可以用一个整数,很容易比较和减去,避免了日历的复杂性。1970年1月1日是Unix开发时一个方便的起点。

它们的优势至今仍然存在:

  • ** 独立于时区.** 时间标识一个瞬间,而不是墙钟读数。在东京,柏林和圣保罗,
  • 简单的算法. 两个时间之间的区别是数秒的时间。增加了86,400个进步。
  • **紧且可分类.**整数需要8字节,并按时间顺序排序。
  • 明确. 03/04是3月4日或4月3日。

秒数与毫秒

最常见的时间错误是混合单位:

  • 现在的Unix工具,大多数数据库,JWT和许多API都使用秒,10个位数,例如1760000000。
  • JavaScript 的 Date.now(),Java 的 System.currentTimeMillis() 和许多分析系统使用 毫秒:13 位数,如 1760000000000。
  • 一些系统使用微秒 (16位数) 或纳米秒 (19位数)。

如果把毫秒解释为秒钟,。如果您在用户界面中看到 "1970-01-21",。一个时间转换器可以通过长度检测单位,这是一个快速的健康检查。

将时间转换为常用语言

简介:

const nowSeconds = Math.floor(Date.now() / 1000);
const date = new Date(1760000000 * 1000);
date.toISOString(); // "2025-10-09T08:53:20.000Z"

它们是什么?

import time, datetime
now = int(time.time())
dt = datetime.datetime.fromtimestamp(1760000000, tz=datetime.timezone.utc)

在Python中总是传递tz=;没有它,fromtimestamp返回一个简单的本地时间,很容易被误解。

在此之前,

SELECT to_timestamp(1760000000);           -- timestamptz
SELECT extract(epoch FROM now())::bigint;  -- current Unix time

让我们一起去吧。

t := time.Unix(1760000000, 0).UTC()
now := time.Now().Unix()

子

date +%s                    # current timestamp
date -u -d @1760000000      # GNU date
date -u -r 1760000000       # macOS/BSD date

时区:存储UTC,显示本地

时间没有时区,它是绝对的瞬间。转换到可读数据时会出现问题:

  • 没有区间的日期传输. new Date("2026-03-29 02:30") 在运行代码的任何机器的本地时区中进行解释。在UTC的服务器和柏林的笔记本电脑上,
  • **夏令时间的差距和重叠.**在夏令时间的区域,有些地方时间不存在 (时钟向前跳动),有些则发生两次 (时钟向后移动)。时间没有这样的模两可。
  • 如果您存储"2026-11-01 01:30"没有区间,您永远无法确定它是什么时刻。

基本规则:存储和传输时间或ISO 8601字符串,并明确偏移 (2026-10-11T09:30:00Z或+02:00)。只在显示时转换到用户的本地区域。如果您需要按本地时间安排事情,请单独存储用户的IANA时区名称 (如Europe/Berlin)。

ISO 8601与Unix时间

像2026-10-11T09:30:00Z这样的ISO 8601字符串是人类可读的,并且当它们包含Z或偏移时也是明确的。许多API更喜欢它们的可读性。在Unix中,时间较小,比较快。两者都很好,重要的是一致性,

秒

地球的旋转有点不规则,所以官方UTC偶尔会插入秒。每一天的时间是86,400秒,在秒内,时间重复或被抹去。对于几乎所有应用,。如果您需要高精度的定时,。国际计时机构已经决定到2035年逐步淘汰秒,

2038年的问题

许多旧系统将Unix时间存储为一个签名32位整数,其最大值为2,147,483,647。这与2038年1月19日的03:14:07 UTC相对应。一秒钟后,该值溢出到 −2,147,483,648,表示1901年12月13日。

现代64位操作系统,语言和数据库使用64位时间,。风险仍然存在于:

  • 嵌入式设备和具有长寿命的工业控制器。
  • 有32位时间字段的文件格式和网络协议。
  • 数据库列被声明为32位 INT 持有时代秒。MySQL 的 TIMESTAMP 类型有 2038 的限制;DATETIME 或 BIGINT 则没有。

检查长期存储的数据,尤其是存储未来日期的数据,

负时间

在1970年之前的日期有负时间。-86400 is 31 December 1969。大多数现代语言正确处理它们,但一些较旧的API和电子表格却没有,所以要明确测试历史日期。

实用调试检查列表

  1. 计算数字:秒数为10,毫秒为13。
  2. 首先转换为UTC,然后转换为本地时间,以将单元错误与区域错误分开。
  3. 在解析之前检查日期字符串是否包含 Z 或偏移。
  4. 如果令牌或签名失败,则将服务器和客户端时钟进行比较。请参阅[JWT如何工作] (http://blog/how-jwt-works) 了解为什么exp和nbf是Unix秒。
  5. 在安排重复工作时,请记住cron在服务器的区域运行;[这些cron示例] (/blog/cron-expression-examples) 涵盖详情。

总结

一个Unix时间是自1970-01-01 UTC以来的秒数。它是简单的,独立于时区,易于计算。大多数错误来自混合秒和毫秒,解析没有区的日期,。存储UTC,在边缘转换,使用64位整数,

本页内容由英文自动翻译而来,如发现错误,欢迎告诉我们。

相关指南