Unix Timestamp:定义、转换及在移动开发中的存储

作者: IT Sectr 发布日期: 2026-07-14 阅读时间: 9 分钟

Unix Timestamp — 是一个整数,表示自 1970 年 1 月 1 日 00:00:00 UTC 以来经过的秒数。这种通用时间格式用于操作系统、数据库、API 和移动应用程序中存储和传输时间戳,不受时区影响。根据 Google Developers Blog (2025) 的数据,Unix Timestamp 仍然是 REST API 中最流行的时序化格式 — 87% 的公共 Web 接口都在使用它。

要点

  • Unix Timestamp — 自 1970 年 1 月 1 日 UTC 以来的秒数,非负整数
  • 通用性 — 格式不依赖时区,简化了服务器与客户端之间的数据交换
  • 2038 年问题 — 对于 32 位系统,时间戳值将超过 2^31,导致溢出
  • 毫秒 — 在 Android 和 Java 中更常使用毫秒级的 Java Timestamp(Unix Timestamp x 1000)
  • 存储 — 时间戳比 ISO 字符串更紧凑,在数据库中排序和比较更高效

什么是 Unix Timestamp?

Unix Timestamp(也称为 POSIX time、Epoch time 或 Unix time)— 是一个时间测量系统,用于确定自 1970 年 1 月 1 日 00:00:00 UTC(Unix 纪元)以来经过的秒数。该日期被选为 Unix 操作系统的起始点,随后该格式成为计算机系统时间表示的事实标准。时间戳不考虑闰秒 — 每分钟按 60 秒计算,尽管国际地球自转服务有时会添加额外的一秒来校正原子时间。

Unix 纪元:为什么是 1970 年?

选择 1970 年 1 月 1 日与 Unix 操作系统的发展历史有关。开发者 Ken Thompson 和 Dennis Ritchie 选择了这个日期作为简单而整齐的起点 — 它足够早以覆盖所有可能的日期,同时又足够晚以便时间可以存储在 32 位有符号整数中。最初时间以秒的六十分之一计量,然后以滴答(1/60 秒)计量,直到第七版 Unix(V7,1979)格式才稳定为完整的秒数。根据 The Open Group Base Specifications(第 8 版,2024),POSIX 兼容系统必须支持此格式。

Unix Timestamp 的工作原理

Unix Timestamp 的工作原理基于一个简单的计数器:每过去一天就向值中添加 86 400 秒。例如,时间戳 1 720 000 000 对应 2024 年中期的一个日期 — 精确的转换可以通过除以一天、一小时和一分钟中的秒数来完成。这种方法使时间戳成为机器存储的理想选择:它是一个整数,占用 4 字节(32 位 int)或 8 字节(64 位 long),并支持直接比较 — 时间戳越大 = 日期越晚。

转换的数学原理

一天 = 86 400 秒(24 x 60 x 60)。一小时 = 3600 秒。要将时间戳转换为日期,需要依次计算自纪元开始以来的天数、小时数、分钟数和秒数。反向转换 — 将日期转换为自 1970-01-01 以来的天数,然后乘以 86 400 并加上相对于 UTC 的偏移量。在 Java 和 Kotlin 中,这些计算已在标准类 java.time.Instantjava.util.Date 中实现,使开发者免于手动计算。

kotlin
        // 以秒为单位获取 Unix Timestamp
val seconds = System.currentTimeMillis() / 1000

// 通过 java.time 将时间戳转换为日期
val instant = Instant.ofEpochSecond(seconds)
val localDate = instant.atZone(ZoneId.of("Europe/Moscow")).toLocalDate()

// 反向:日期转时间戳
val date = LocalDate.of(2026, 7, 21)
val ts = date.atStartOfDay(ZoneOffset.UTC).toEpochSecond()

Unix Timestamp 与日期的相互转换

Unix Timestamp 转换为人类可读的日期是移动开发中最常见的操作之一。在 Android 上,根据最低 API 版本有多种转换方法:对于 API 26+ 推荐使用 java.time.Instant,对于较旧版本使用 java.util.Date 和 java.text.SimpleDateFormat。重要的是要记住,Android 和 JVM 默认使用毫秒而非秒 — 如果从服务器接收的时间戳是以秒为单位的,则在传递给标准构造函数之前需要乘以 1000。

使用时区进行转换

Unix Timestamp 的主要优势之一是与位置无关。服务器始终以 UTC 返回时间戳,转换为本地日期和时间在客户端完成。在 Kotlin 中,使用带相应 ZoneId 的 ZonedDateTime — 系统或用户选择的。如果应用程序在不同时区显示时间(例如,对于旅行者),时间戳消除了从服务器传递时区的需要 — 一个时间戳就足够了。

kotlin
// 使用用户时区进行转换
fun formatTimestamp(seconds: Long, zoneId: ZoneId): String {
    val instant = Instant.ofEpochSecond(seconds)
    val formatter = DateTimeFormatter
        .ofPattern("dd.MM.yyyy HH:mm:ss")
    return formatter.format(instant.atZone(zoneId))
}

// 示例:timestamp = 1720000000,时区 = Europe/Moscow
val result = formatTimestamp(1720000000, ZoneId.of("Europe/Moscow"))

2038 年问题

2038 年问题(Year 2038 Problem,Y2K38)— 是 32 位有符号整数存储 Unix Timestamp 时的基本限制。32 位 signed int 的最大值是 2 147 483 647,对应 2038 年 1 月 19 日 03:14:07 UTC。在该日期之后,值溢出并变成负数,导致使用 32 位 time_t 的系统出现故障。该问题类似于著名的 Y2K 问题,但主要影响嵌入式系统、旧版 Android 和采用 32 位架构的 IoT 设备。

问题的规模

根据 Linux Foundation(2025)的数据,工业和 IoT 领域约 15% 的 Linux 设备仍在使用 32 位编译。Android 设备的风险较低 — 大多数现代智能手机运行在 64 位处理器(ARM64)上,但搭载 Android 4.x 及更低版本的旧型号可能使用 32 位 time_t。解决方案 — 迁移到 64 位 time_t,它在 2920 亿年内都是安全的。从 Android 5.0(API 21)开始,所有设备在内核级别使用 64 位时间。移动应用开发者只需将时间戳存储为 Long(64 位)类型即可避免应用级别的问题。

在 Android 中使用 Unix Timestamp

在 Android 开发中,正确使用 Unix Timestamp 对于数据同步、显示消息接收时间、计算超时和安排通知至关重要。系统调用 System.currentTimeMillis() 以毫秒为单位返回自 Unix 纪元以来的当前时间 — 这是设备上最精确的时间源。对于网络请求,通常使用以秒为单位的 Unix Timestamp,因为大多数 REST API 和数据库正是以秒为单位工作的。

推荐做法

切勿使用 System.currentTimeMillis() 来测量时间间隔 — 为此应使用 System.nanoTime(),它是单调的且不依赖于用户的时钟更改。为了显示时间,始终将时间戳存储在 UTC 中,并在界面端转换为本地时区。在使用数据库(SQLite、Room)时,使用 INTEGER 类型并将时间戳以秒为单位存储 — 这占用 8 字节(Long)并支持原生 SQL 排序。对于 JSON 序列化,建议将时间戳作为数字(Long)而非字符串发送 — 这样更紧凑且解析更快。

kotlin
// 正确测量执行时间
val start = System.nanoTime()
// ... 操作 ...
val elapsed = System.nanoTime() - start
val seconds = elapsed / 1_000_000_000.0

// 存储在 Room 中(Entity)
@Entity
data class Message(
    @PrimaryKey val id: Long,
    val text: String,
    val createdAt: Long // 以秒为单位的 Unix Timestamp
)

处理来自服务器的时间

在从服务器接收 Unix Timestamp 时,务必检查测量单位:某些 API 返回毫秒(兼容 JavaScript),其他返回秒(POSIX 标准)。关于单位的约定应在 API 文档中记录。在服务器响应中,时间戳可以作为 Long(JSON 数字)或 String(ISO 8601)发送。为便于调试,添加一个以人类可读格式显示时间戳的实用函数 — 这可以简化开发过程中时间戳正确性的检查。

在数据库中存储时间戳

数据库中的时间存储格式选择直接影响查询性能、代码复杂度和时区处理的正确性。Unix Timestamp — 是关系型数据库最高效的格式:存储为整数(4 或 8 字节),支持索引和快速排序。与 ISO 8601 字符串不同,时间戳在排序时不需要解析,并且在索引中占用更少的空间。对于 Room 和 SQLite,建议将时间戳存储为 INTEGER 类型并在时间列上使用索引。

存储格式大小排序索引
Unix Timestamp (INTEGER)4–8 字节快速高效
ISO 8601 (TEXT)20–30 字节缓慢中等
DATETIME (SQLite)8 字节中等中等

移动项目建议

对于使用 Room 库的 Android 应用程序,建议将时间戳存储为 Long(64 位)并使用 TypeConverter 在 Long 与 Date 或 Instant 之间自动转换。在数据库查询中,使用比较运算符(>、<、BETWEEN)— 它们与数值类型原生兼容。对于需要按时间排序的数据缓存(例如消息列表),务必在时间戳列上创建索引 — 这将在大数据量下将 ORDER BY 查询加速若干个数量级。

常见问题

什么是 Unix Timestamp 及其工作原理?

Unix Timestamp — 自 1970 年 1 月 1 日 00:00:00 UTC 以来的秒数。它像一个简单的计数器一样工作:每过去一天就添加 86 400 秒。这是一个整数,可以轻松地在服务器和客户端之间进行比较、排序和传输,不受时区影响。

如何在 Kotlin 中将 Unix Timestamp 转换为日期?

对于 java.time 使用 Instant.ofEpochSecond(timestamp)(API 26+)或对于较旧版本的 Android 使用 Date(timestamp * 1000)。获取 Instant 后,可以将其转换为 LocalDate、ZonedDateTime 或通过 DateTimeFormatter 格式化。如果时间戳以秒为单位,别忘了乘以 1000。

2038 年问题的本质是什么?

2038 年 1 月 19 日 03:14:07 UTC,32 位 signed int(2 147 483 647)的值将被超出,导致溢出。使用 32 位 time_t 的系统将开始将时间解释为负数。解决方案 — 迁移到 64 位 time_t,它已用于现代 Android 设备(API 21+)。

如何在 Android 中获取当前的 Unix Timestamp?

调用 System.currentTimeMillis() / 1000 获取秒或 System.currentTimeMillis() 获取毫秒。要获得带网络同步的更精确结果,请使用 Instant.now().epochSecond(需要 API 26+)或适用于 Android 的 NTP 客户端库。

Unix Timestamp 与毫秒有何区别?

Unix Timestamp — 自 1970-01-01 UTC 以来的秒数(整数)。Java Timestamp 使用 毫秒 — 相同的偏移量,但精确 1000 倍。转换:毫秒除以 1000。在 JSON-API 中更常使用秒(Unix Timestamp),而在 Android 平台上使用毫秒(System.currentTimeMillis)。

总结

  • Unix Timestamp — 基于自 1970 年 1 月 1 日 UTC 以来的秒数的通用数字时间格式
  • 时区无关性 — 时间戳始终为 UTC,转换为本地时间在客户端完成,消除了与时区相关的一类错误
  • 转换 — 在 Android 中使用 Instant.ofEpochSecond(API 26+)或 Date 乘以 1000 用于平台旧版本
  • 2038 年问题 — 32 位 time_t 的限制;解决方案 — 存储在 64 位 Long 中并使用现代 Android 版本(API 21+)
  • 数据库存储 — 在 SQLite/Room 中以 INTEGER 形式存储的时间戳在大小、排序速度和索引方面优于 ISO 8601 字符串
  • 时间测量 — 使用 System.nanoTime() 测量间隔,System.currentTimeMillis() 测量时间戳(考虑用户调整)
  • 服务器约定 — 为避免转换错误,始终在 API 文档中指定测量单位(秒或毫秒)

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读