从微秒以微秒的精度以字符串格式创建实际日期

Kha*_*hah 0 java java.util.date java-8

我想从微秒创建一个 java.util.Date 对象。但我不想失去它的精度微秒到毫秒。目前我正在通过以下方式将微秒转换为 Date 对象。如果我将微秒传递给 Date 构造函数,那么它会给出一个错误的日期,例如56521-12-01.

long microSeconds = value.getTimestampValue();// This function returns a microseconds.
DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS);
long millis = TimeUnit.MILLISECONDS.convert(microSeconds, TimeUnit.MICROSECONDS);
String startDate = FORMAT.format(new Date(millis));
Run Code Online (Sandbox Code Playgroud)

我不想将微秒转换为毫秒。是否有 API 或 java-8 实用程序的方法可以将微秒直接转换为 Date 对象?

这种方法的问题是它删除微秒的最后三位数字使其成为毫秒,然后从毫秒创建一个日期对象,解析器只需将其毫秒部分乘以将其1000转换为微秒。通过这种方式,我丢失了一个实际的微发送。

jsh*_*ran 6

您将无法使用java.util.Date. 从 API

类 Date 表示特定的时刻,精度为毫秒。


Bas*_*que 5

tl;博士

Instant                                                  // Represent a moment as a count since the epoch reference of 1970-01-01T00:00Z.
.ofEpochSecond(                                          // Instantiate a `Instant` as a count of whole seconds plus fractional second.
    TimeUnit.MICROSECONDS.toSeconds( microseconds ) ,    // Count of whole seconds since the epoch reference.
    TimeUnit.MICROSECONDS.toNanos( microseconds )        // Calculate fractional second as a count of nanoseconds.
    - 
    TimeUnit.SECONDS.toNanos( 
        TimeUnit.MICROSECONDS.toSeconds( microseconds )
    ) 
)                                                        // Returns an `Instant`.
.toString()                                              // Generate text in standard ISO 8601 format.
.replace( "T" , " " )                                    // Replace a `T` with a SPACE for desired output format.
.replace( "Z" , "" )                                     // Remove the `Z` from the end, that indicates the date and time is in the context of UTC.   
Run Code Online (Sandbox Code Playgroud)

避免遗留的日期时间类

您正在使用多年前被JSR 310 中定义的现代java.time类取代的糟糕的日期时间类。

此外,正如其他人指出的那样,遗留类不能容纳微秒,只能容纳毫秒。嗯,实际上,遗留类java.sql.Timestamp试图表示纳秒,但它是通过一个可怕的技巧来实现的,其中包括以毫秒为单位的小数秒以纳秒为单位的小数秒(真是一团糟)。

时间

Java 中的日期时间类型表,现代和传统

样本数据

对于演示,让我们创建自 UTC 时间 1970 年的第一个时刻以来的微秒样本数。

// Convert to microseconds. Use as input value to further code below.
Instant instantPrime = Instant.now().truncatedTo( ChronoUnit.MICROS ); // Drop any nanoseconds, to keep only microseconds.
long wholeSecondsPrime = instantPrime.getEpochSecond();
long nanoAdjustmentPrime = instantPrime.getNano();
long microseconds = 
    TimeUnit.SECONDS.toMicros( wholeSecondsPrime ) + 
    TimeUnit.NANOSECONDS.toMicros( nanoAdjustmentPrime )
;
Run Code Online (Sandbox Code Playgroud)

加工

让我们将微秒计数分为两部分,自 1970-01-01T00:00Z 以来的整秒数,以及作为微秒数的小数秒。

// Convert from microseconds.
long wholeSeconds = TimeUnit.MICROSECONDS.toSeconds( microseconds );
long nanoAdjustment = TimeUnit.MICROSECONDS.toNanos( microseconds ) - TimeUnit.SECONDS.toNanos( wholeSeconds );
Run Code Online (Sandbox Code Playgroud)

将它们重新组合在一起。

Instant instant = Instant.ofEpochSecond( wholeSeconds , nanoAdjustment );
boolean match = instant.equals( instantPrime );
Run Code Online (Sandbox Code Playgroud)

转储到控制台。

System.out.println( "instantPrime = " + instantPrime );
System.out.println( "wholeSecondsPrime = " + wholeSecondsPrime );
System.out.println( "nanoAdjustmentPrime = " + nanoAdjustmentPrime );

System.out.println( "microseconds = " + microseconds );

System.out.println( "wholeSeconds = " + wholeSeconds );
System.out.println( "nanoAdjustment = " + nanoAdjustment );
System.out.println( "instant = " + instant );

System.out.println( "match = " + match );
Run Code Online (Sandbox Code Playgroud)

InstantPrime = 2020-01-07T23:32:26.385565Z

整个秒数 = 1578439946

nanoAdjustmentPrime = 385565000

微秒 = 1578439946385565

整秒 = 1578439946

纳米调整 = 385565000

即时 = 2020-01-07T23:32:26.385565Z

匹配 = 真

字符串

Instant使用标准 ISO 8601 格式生成表示您的值的文本。

String output = instant.toString() ;
Run Code Online (Sandbox Code Playgroud)

2020-01-07T23:32:26.385565Z

你想要的格式接近那个。用T空格替换。并删除Z,但要小心。将日期时间显示为文本而不指示时区或与 UTC 的偏移量可能会给读者带来歧义和混淆。我建议包括Z.

String output = instant.toString().replace( "T" , " " ).replace( "Z" , "" ) ;
Run Code Online (Sandbox Code Playgroud)

2020-01-07 23:32:26.385565


关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

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

现在处于维护模式Joda-Time项目建议迁移到java.time类。

您可以直接与您的数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*

从哪里获得 java.time 类?

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多