在Java或Scala中将微秒字符串转换为日期

在Java或Scala中将微秒字符串转换为日期,java,scala,Java,Scala,如何在Java/Scala中将时间戳(以微秒为单位)字符串转换为日期。 我的目标是比较两个时间戳并找出它们之间的差异。 我使用的是Java8,示例时间戳字符串是1474457086337977。 我想将其转换为日期或时间戳实例。您可以尝试以下代码,这些代码将时间戳作为字符串: BigInteger b = new BigInteger("1474457086337977"); b=b.divide(new BigInteger("1000")); String x =b.toString

如何在Java/Scala中将时间戳(以微秒为单位)字符串转换为日期。 我的目标是比较两个时间戳并找出它们之间的差异。 我使用的是Java8,示例时间戳字符串是1474457086337977。
我想将其转换为日期或时间戳实例。

您可以尝试以下代码,这些代码将时间戳作为字符串:

 BigInteger b = new BigInteger("1474457086337977");
 b=b.divide(new BigInteger("1000"));

 String x =b.toString();



DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");

long milliSeconds= Long.parseLong(x);
System.out.println(milliSeconds);

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(milliSeconds);
System.out.println(formatter.format(calendar.getTime())); 
或者,为了更精确,您可以使用BigDecimal:

BigDecimal b = new BigDecimal("1474457086337977");
b=b.divide(new BigDecimal("1000"));
String x =b.toString();

那么,如何将这些微秒转换为毫秒,然后创建一个时间戳对象呢

long microsecs = 1474457086337977L;
long millis = TimeUnit.MILLISECONDS.convert(microsecs, TimeUnit.MICROSECONDS);
Timestamp time = new Timestamp(millis);
那不管用吗

--编辑

针对答案中留下的评论:

关于Java 8新的日期时间API的信息

首先,既然您提到您正在使用Java8,我完全同意更好的方法是使用新的Java8日期/时间API。然而,这是一种奢侈,即使在使用Java8时也不总是如此,因为您可能仍然在与仍然使用旧Java日期/时间类的旧API交互,或者仅仅是因为您的API的其余部分仍然使用它们,并且您不想开始混合

您的问题中不清楚您是否已经知道这一点,您似乎确定要使用
java.util.Date
java.sql.Timestamp
,我没有对此提出疑问,我只是围绕您问题的参数进行了研究

很明显,新的Java日期/时间API比旧的要好得多,但仍有数百万行代码在使用旧的API,它们可以正常工作。再一次,我认为这超出了答案的范围,你们似乎已经有了其他好的答案来解决这个问题

关于可能的数据丢失

一条评论提到,答案可能会丢失数据。我认为在Java中,所有整数算法都会受到潜在的下溢或溢出的影响。我的错误可能是我没有提到它

确实,在某些情况下,
TimeUnit.convert
方法可能会导致溢出或下溢。它记录在方法中

  • 纳秒是十亿分之一秒(1/100000000)
  • 一微秒是百万分之一秒(1/1000000)
  • 一毫秒是千分之一秒(1/1000)
这意味着,一旦表示为长,毫秒数应该比微秒数小很多,对吗

TimeUnit.convert
使用的公式如下

final long MICROS = 1000000L;
final long MILLIS = 1000L;

long microsecs = 1474457086337977L;
long millisecs = microsecs / (MICROS / MILLIS)
这意味着只有在微秒数非常小的情况下(例如,如果微秒数小于1000微秒),才会导致数据丢失。您应该验证您的代码,不要进入这样的场景

这个答案左边的一条评论认为,正确的答案应该使用纳秒,但是纳秒长的值会比你的微秒大很多,因此,在转换到纳秒的过程中,你可能仍然会遇到溢出

例如,想想如果你有
Long.MAX\u值
微秒会发生什么,如果纳秒应该比你的
Long.MAX\u值
微秒大得多,你怎么能只用Java Long算术将它转换成纳秒而不产生溢出呢

我的观点是,无论您使用Java 8 Date Time还是旧式Java Date Time API,您都需要一个表示时间线中某个瞬间的
long
值,但是
long
对于过去或未来的距离以及在单位之间进行转换都有限制,那个算法会受到下溢和上溢的影响,并没有办法避免,你们应该意识到这一点,以避免非常讨厌的错误

再一次,我认为这是一个既定的问题,超出了问题的范围,我之所以提出这个问题,只是因为我对这个遗漏投了一些反对票。

tl;博士 java.time 这些类支持的分辨率为,足以满足您的需要

解析数字字符串 将字符串解析为
long
,以获取历元的微秒计数

long micros = Long.parse( "1474457086337977" );
当然,您可以始终使用整数文本。请注意,整数文本后面附加了
L

long micros = 1_474_457_086_337_977L ;
将长代码转换为即时代码 我们希望将1970年初以UTC(
1970-01-01T00:00:00Z
)为单位的微秒计数转换为
瞬间
。该类表示时间线上的一个时刻,分辨率为。这意味着小数点最多有九位数

Instant
类具有方便的静态方法,用于从、从或从转换。但不幸的是,在微秒或纳秒的计数中,没有这样的方法

作为一种解决方法,我们可以定义并将其添加到已定义为常量的历元参考日期。我们可以将
持续时间
实例化为纳秒数。为了得到纳秒,我们将微秒乘以1000。注意使用64位
long
而不是32位
int

Duration duration = Duration.ofNanos( micros * 1_000L );  
Instant instant = Instant.EPOCH.plus( duration );
instant.toString():2016-09-21T11:24:46.337977Z

或者,您可以使用枚举将微秒转换为纳秒,而无需硬编码“幻数”

Duration duration = Duration.ofNanos( TimeUnit.MICROSECONDS.toNanos( micros ) );  
要调整到其他偏移或时区,请在StackOverflow中搜索Java类
OffsetDateTime
ZonedDateTime

转换为传统日期时间类型 您应该避免与最早版本的Java捆绑在一起的旧日期时间类型。事实证明,它们设计拙劣、令人困惑且麻烦。现在被java.time类型取代

但是,如果必须与尚未更新为java.time类型的旧代码交互,则可以转换为java.time或从java.time转换为java.time。查看添加到旧类的新方法

java.sql.Timestamp ts = java.sql.Timestamp.from( instant );
从java.time类型转换为或
java.util.Calendar
时,请注意数据丢失。这些类型仅解析为。截断fr
java.sql.Timestamp ts = java.sql.Timestamp.from( instant );
java.util.Date utilDate = java.util.Date.from( instant );  // Caution: Data loss in truncating nanoseconds to milliseconds.