java 是否足以存储以微秒为单位的纪元时间?

Is a java long enough to store epoch time in microseconds?

我可以使用 java long 以合理的精度存储纪元时间(以微秒为单位)而无需任何特殊的有符号到无符号转换技巧吗?如果是这样,我将如何计算结束日期范围?

这是通常的 8 字节日期范围: -9,223,372,036,854,775,808 至 9,223,372,036,854,775,807

更新

使用建议:

new Date(Long.MAX_VALUE)

这是嗯的结束日期:

new Date(Long.MAX_VALUE/1_000)

Sat Jan 09 20:00:54 PST 294247

这是使用纳秒正长值的结束日期:

new Date(Long.MAX_VALUE/1_000_000)

Fri Apr 11 16:47:16 PDT 2262

tl;博士

  • Nanos 只给出了 3 个世纪。
  • 永远不要自己计时。 ☛ 使用 java.time
  • 交换日期时间值时,切勿使用纪元计数,使用标准 ISO 8601 格式的文本。

做数学运算

您必须选择一个 epoch reference date. While dozens of various epochs are used in the industry, one of the more common is often referred to as Unix Time:UTC 中 1970 年的第一时刻,1970-01-01T00:00:00Z。该点之后的时刻使用正数进行跟踪,而之前的时刻使用负数进行跟踪。

当然,一年的长度因闰年而异,但我们可以很容易地估算出。使用 TimeUnit class 及其方便的转换方法获取一年中 nanoseconds 的数量。

计算一些数字。

long nanosPerDay = TimeUnit.DAYS.toNanos( 1L );
long nanosPerYear = ( long ) ( nanosPerDay * 365.25 );
long maximumYears = ( Long.MAX_VALUE / nanosPerYear );

转储到控制台。

System.out.println( "nanosPerDay: " + nanosPerDay );
System.out.println( "nanosPerYear: " + nanosPerYear );
System.out.println( "Long.MAX_VALUE: " + Long.MAX_VALUE + " provides for maximumYears: " + maximumYears );

看到这个 code run live at IdeOne.com

nanosPerDay: 86400000000000

nanosPerYear: 31557600000000000

Long.MAX_VALUE: 9223372036854775807 provides for maximumYears: 292

所以我们在 1970 年之前和之后得到的时间少于 ±3 个世纪。所以如果几个世纪对您的应用来说足够好,那么这种方法确实有效。至少当日历用完时你不会在附近修复它。 ;-)

Instant

幸运的是我们不需要自己做这个数学运算。

现代 Java 恰好配备了可用于面向业务的应用程序的最先进的日期时间处理框架: java.time classes 在 JSR 310.

中定义

java.time.Instant class 使用不同的策略来跟踪时间。 class 保持 whole 秒的计数 before/after 1970 UTC 的纪元,加上 separate 的纳秒计数瞬间的小数秒。

将其视为:

moment = ( whole-seconds + fractional-second ) ; // Since 1970-01-01T00:00:00Z.

这会启用 minimum/maximum 个:

请注意 java.time classes 确实具有纳秒级的分辨率,而遗留的 classes 他们取代了(Date, Calendar, 等等) 解析为 milliseconds.

有关详细信息,请参阅 class JavaDoc and the OpenJDK source code (in Mercurial)。

提示:java.time classes 最适合面向业务的用途。如果您从事科学、工程、考古学或历史工作,请使用适合该领域的其他符号,例如 String 类型。

粒度

请注意,不同的计算机系统在计时时使用不同的粒度。

如上所述,java.time classes 解析为纳秒,即十进制小数秒的九位数字。遗留 classes 使用毫秒,表示小数秒的三位数字。其他系统,例如 Postgres database, use microseconds 表示小数秒的六位数字。当跨系统交换或比较数据时,您可能希望在各种 java.time classes.

上使用 truncatedTo 方法

目前传统的计算机硬件时钟只能精确到微秒或更粗略。他们可能会以纳秒为单位进行报告,但并不准确到那个程度。所以,你会发现Java9、10、11中的Instant.now()方法将当前时刻捕获到微秒(而数据类型可以handlenanos , 它检测 当前 时间(以微秒为单位)。

Instant.now().toString(): 2019-01-23T12:34:56.123456Z


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些 classes 取代了麻烦的旧 legacy 日期时间 classes,例如 java.util.Date, Calendar, & SimpleDateFormat.

要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 中搜索许多示例和解释。规格为 JSR 310.

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes。 Hibernate 5 和 JPA 2.2 支持 java.time.

从哪里获得 java.time classes?