2016-09-24 272 views
-1

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

+0

为什么你只是得到当前的日期和时间? – Kaushal28

+1

@NoOne因为当前的日期和时间不会帮助您获得两个时间戳之间的差异,就像问题清楚地解释:/ – Gimby

+0

实际上,我将从外部资源获取这个时间戳,作为我的数据的一部分,我需要比较这个时间戳,并做一些逻辑。 – BDR

回答

1

好了,关于如何将那些微秒什么到毫秒,然后创建一个时间戳对象?

long microsecs = 1474457086337977L; 
long millis = TimeUnit.MILLISECONDS.convert(microsecs, TimeUnit.MICROSECONDS); 
Timestamp time = new Timestamp(millis); 

这不行吗?

- 编辑

为了解决留在答案的评论:

帮助Java 8新的日期时间API

首先,既然你提到你使用的是Java 8我完全同意,更好的方法是使用新的Java 8 Date/Time API。但是,即使在使用Java 8时,这也是一种奢侈,因为您仍然可能仍在使用旧的Java Date/Time类与旧的API进行交互,或者仅仅因为其余的API仍然使用它们并且你不想开始混合东西。

这不是你的问题清楚,如果你已经知道这一点,你似乎是肯定要为使用java.util.Datejava.sql.Timestamp,我没问题,我就在你的问题的参数工作。

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

关于可能造成数据丢失

一条意见提到,答案可能会遇到数据丢失。我认为在Java中,所有整数算术都有可能发生下溢或溢出。我的错误可能没有提到它。

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

  • 纳秒是第二(1000000000分之1)十亿分之一
  • 甲微秒是第二(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_VALUE微秒会发生什么,你怎么可以将其转换成使用纯Java长算法,而不溢出纳秒考虑到纳秒应该是比你的Long.MAX_VALUE微秒一个更大的数字?

我的观点的存在,不管你使用Java 8日期时间或遗留Java日期时间的API,你需要代表在时间线的瞬间long值,但long有关于限制多远过去还是怎么的在不远的将来,你可以走了,当你这样做单位之间的转换,算术是受下溢和溢出,有没有办法解决它,你应该知道的是,为了避免非常讨厌的错误。

再次,我认为这是一个给定的,问题的范围之内,我把它仅仅是因为我得到了这个遗漏一些downvotes。

+0

这就是我想要的。谢谢 – BDR

+0

知道['java.sql.Timestamp'](https://docs.oracle.com/javase/8/docs/api/java/sql/Timestamp.html)是一类错误的破解, java.util.Date“,但假装没有。推荐用于必要时将数据传入/传出数据库,但不推荐用于业务逻辑。这个类是现在被java.time类取代的麻烦的旧日期时间类的一部分。 java.time类可以处理[纳秒](https://en.wikipedia.org/wiki/Nanosecond)(甚至比微秒更好)。 –

+0

此答案的代码**导致数据丢失**,将微秒截断为毫秒。尽管使用java.time是一条更好的路线,但如果坚持这种方法,那么您可能需要通过调用['setNanos'](http://docs.oracle.com)来设置此Timestamp对象的纳米字段,的.com/JavaSE的/ 7 /文档/ API/JAVA/SQL/Timestamp.html#setNanos(INT))。 –

0

你可以试试下面的代码,这将需要时间标记为一个字符串:

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(); 
+0

感谢您的回复。让我试试看。 – BDR

+0

你的毫秒数太大。给出如下输入:1474717464404 – Kaushal28

+0

哦你的字符串是在微秒内,然后将其转换为毫秒。 – Kaushal28

4

TL;博士

Instant.EPOCH.plus( 
    Duration.ofNanos( 
     TimeUnit.MICROSECONDS.toNanos( 
      Long.parse("1474457086337977")))) 

java.time

java.time类支持分辨率为nanoseconds,绰绰有余为您microseconds

解析数

的字符串解析字符串作为long摆脱时代微秒的计数。

long micros = Long.parse("1474457086337977"); 

当然,您始终可以使用整数字面量。请注意0​​附加到整数文字。

long micros = 1_474_457_086_337_977L ; 

转换长成Instant

我们希望在UTC(1970-01-01T00:00:00Z)改造微秒是计数从1970年开始的epochInstant。该Instant类表示UTC时间轴与nanoseconds分辨率上一会儿。这意味着最多九位数的小数部分。

Instant类具有方便的静态方法,用于从count of whole secondscount of whole seconds plus a fractional second in nanosecondscount of milliseconds转换。但不幸的是没有这样的方法计数微秒或纳秒。

作为一种解决方法,我们可以定义一个Duration并将其添加到已定义为常量的时期参考日期。我们可以将一个Duration实例化为几纳秒。为了得到纳秒,我们将你的微秒乘以一千。请注意使用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

或者,您可以使用TimeUnit枚举微秒转换为纳秒没有硬编码“幻数“。

Duration duration = Duration.ofNanos(TimeUnit.MICROSECONDS.toNanos(micros)); 

要调整到其他偏移或时区,搜索StackOverflow的Java类OffsetDateTimeZonedDateTime

转换成传统的日期 - 时间类型

你应该避免使用Java的早期版本中捆绑的旧日期 - 时间类型。事实证明,它们设计不佳,混乱且麻烦。现在由java.time类型取代。

但是,如果您必须与尚未更新为java.time类型的旧代码进行交互,则可以将其转换为/ from java.time。寻找新的方法添加到旧的类。

java.sql.Timestamp ts = java.sql.Timestamp.from(instant); 

从java.time类型转换为java.util.Datejava.util.Calendar时当心数据的丢失。这些类型只解析为milliseconds。截止从纳秒到毫秒的过程默默地进行,将最后六个(九个)可能的小数秒数字截掉。

java.util.Date utilDate = java.util.Date.from(instant); // Caution: Data loss in truncating nanoseconds to milliseconds. 

关于java.time

java.time框架是建立在Java 8和更高版本。这些类代替了令人讨厌的旧日期时间类,例如java.util.Date,.Calendar,& java.text.SimpleDateFormat

Joda-Time项目现在位于maintenance mode,建议迁移到java.time。请参阅Oracle Tutorial。并搜索堆栈溢出了很多例子和解释。

大部分的java.time功能后移植到Java 6 和ThreeTenABP还适于Android(见How to use…)。

ThreeTen-Extra项目扩展java.time与其他类。这个项目是未来可能增加java.time的一个试验场。

+0

有趣的是,在你的回答中,'TimeUnit.MICROSECONDS.toNanos'受制于'TimeUnit.MICROSECONDS.toMillis'的相同问题。就在相反的方向。 toMillis转换可能会下溢,在您的回答中,toNanos转换可能会发生溢出。例如,如果你有'microsecs = Long.MAX_VALUE'。 –

+0

@EdwinDalorzo为什么任何人都有一个日期时间值作为“Long.MAX_VALUE”微秒的计数时间? –

+0

您在使用'TimeUnit.convert'时在我的答案中留下了关于可能的数据丢失的评论。我认为强调这个解决方案也不能解决问题是公平的。我以'Long.MAX_VALUE'为例,但不需要达到该数字就可以获得溢出。在哪些情况下才有意义?有关系吗?当你突出显示它时,我可以在我的答案中提出同样的问题。但仅举一个例子,天体计算可能很容易超过这个数字。 –