Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中将十进制时间戳转换为带尾随小数的日期_Java_Date_Calendar_Bigdecimal - Fatal编程技术网

如何在Java中将十进制时间戳转换为带尾随小数的日期

如何在Java中将十进制时间戳转换为带尾随小数的日期,java,date,calendar,bigdecimal,Java,Date,Calendar,Bigdecimal,我一直在试图找出如何将时间戳转换为日期,但末尾有尾随的小数,例如: 时间戳-C50204EC EC42EE92相当于2004年9月27日03:18:04.922896299 UTC 时间戳格式包括前32位无符号秒作为跨越136年的字段和32位分数字段。在时间戳格式中,原始历元或纪元0的基准日期为0小时1900年1月1日UTC,此时所有位均为零 这是我迄今为止为代码编写的内容: BigDecimal bi = new BigDecimal("1096255084000"); dou

我一直在试图找出如何将时间戳转换为日期,但末尾有尾随的小数,例如: 时间戳-C50204EC EC42EE92相当于2004年9月27日03:18:04.922896299 UTC

时间戳格式包括前32位无符号秒作为跨越136年的字段和32位分数字段。在时间戳格式中,原始历元或纪元0的基准日期为0小时1900年1月1日UTC,此时所有位均为零

这是我迄今为止为代码编写的内容:

    BigDecimal bi = new BigDecimal("1096255084000");
    double decimal_timestamp = bi.doubleValue();

    DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss.SSS");
    formatter.setTimeZone(TimeZone.getTimeZone("UTC"));

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(decimal_timestamp);
    String date = formatter.format(calendar.getTime());

    System.out.println(decimal_timestamp + " = " + date); 
我的想法是,使用日历可能是不可能的,所以我必须从头开始,但我不知道如何去做。

java.time 使用解释中的示例:

时间戳-C50204EC EC42EE92相当于2004年9月27日 03:18:04.922896299 UTC

输出为:

2004-09-27T03:18:04.922896384Z

它关闭了85纳秒。可能更好的浮点运算可以做得更好。编辑:由于原始时间戳的分辨率为2^-32秒,这是
瞬间
的纳秒(10^-9秒)分辨率的4倍多,因此精度损失是不可避免的

您尝试使用的
Calendar
类的设计总是很糟糕,现在已经过时很久了。取而代之的是,我按照Amongalen在评论中的建议,使用java.time,这是一种现代的java日期和时间API。编辑:对于比较而言,
Calendar
具有毫秒分辨率,因此最多只能使您的精度降低一个亚基

编辑:更精确的数学 我不能让85纳秒的时间过去。以下是一个尽可能保持精度并给出预期结果的版本:

    BigDecimal timeStamp = new BigDecimal(new BigInteger("C50204ECEC42EE92", 16));

    // To get the whole part and the fraction right, divide by 2^32
    BigDecimal bit32 = new BigDecimal(0x1_0000_0000L);
    BigDecimal secondsSince1900 = timeStamp.divide(bit32);

    // Convert seconds to nanos by multiplying by 1 000 000 000; round to long
    long nanosSince1900 = secondsSince1900.multiply(new BigDecimal(TimeUnit.SECONDS.toNanos(1)))
            .setScale(0, RoundingMode.HALF_UP)
            .longValueExact();

    Instant converted = epoch.plusNanos(nanosSince1900);
2004-09-27T03:18:04.922896300Z

1纳米太多了?这是因为我在调用
setScale
时使用了半向上舍入。如果我改为截断(使用
RoundingMode.FLOOR
),我会从解释中得到准确的结果。所以我的版本不会比他们的更精确

链接 解释如何使用java.time。

java.time 使用解释中的示例:

时间戳-C50204EC EC42EE92相当于2004年9月27日 03:18:04.922896299 UTC

输出为:

2004-09-27T03:18:04.922896384Z

它关闭了85纳秒。可能更好的浮点运算可以做得更好。编辑:由于原始时间戳的分辨率为2^-32秒,这是
瞬间
的纳秒(10^-9秒)分辨率的4倍多,因此精度损失是不可避免的

您尝试使用的
Calendar
类的设计总是很糟糕,现在已经过时很久了。取而代之的是,我按照Amongalen在评论中的建议,使用java.time,这是一种现代的java日期和时间API。编辑:对于比较而言,
Calendar
具有毫秒分辨率,因此最多只能使您的精度降低一个亚基

编辑:更精确的数学 我不能让85纳秒的时间过去。以下是一个尽可能保持精度并给出预期结果的版本:

    BigDecimal timeStamp = new BigDecimal(new BigInteger("C50204ECEC42EE92", 16));

    // To get the whole part and the fraction right, divide by 2^32
    BigDecimal bit32 = new BigDecimal(0x1_0000_0000L);
    BigDecimal secondsSince1900 = timeStamp.divide(bit32);

    // Convert seconds to nanos by multiplying by 1 000 000 000; round to long
    long nanosSince1900 = secondsSince1900.multiply(new BigDecimal(TimeUnit.SECONDS.toNanos(1)))
            .setScale(0, RoundingMode.HALF_UP)
            .longValueExact();

    Instant converted = epoch.plusNanos(nanosSince1900);
2004-09-27T03:18:04.922896300Z

1纳米太多了?这是因为我在调用
setScale
时使用了半向上舍入。如果我改为截断(使用
RoundingMode.FLOOR
),我会从解释中得到准确的结果。所以我的版本不会比他们的更精确

链接
解释如何使用java.time。

您使用的是java 8还是更高版本?您可能应该考虑使用一个新的与时间相关的类,例如:LoalDATECTIME。“时间被表示为纳秒精度”-这对你来说足够了吗?作为旁白:那么你将在17年内遇到2036年的问题。你引用的是哪种系统的文档?在您的标题或问题中加上一条说明,让其他人查找。@Winsome如果此输入样式来自某个第三方库或系统,请注明名称。它可能会帮助其他人在将来找到此页面。我很好奇。我明白了,您指的是RFC 5905网络时间协议版本4:协议和算法规范。谢谢,这很有趣。您使用的是Java8还是更新版本?您可能应该考虑使用一个新的与时间相关的类,例如:LoalDATECTIME。“时间被表示为纳秒精度”-这对你来说足够了吗?作为旁白:那么你将在17年内遇到2036年的问题。你引用的是哪种系统的文档?在您的标题或问题中加上一条说明,让其他人查找。@Winsome如果此输入样式来自某个第三方库或系统,请注明名称。它可能会帮助其他人在将来找到此页面。我很好奇。我明白了,您指的是RFC 5905网络时间协议版本4:协议和算法规范。谢谢,真有意思。谢谢,这真是太棒了!我同意日历类很难修改以获得更高的准确性。“1096255084000”只是我使用的一个测试编号,它与代码无关,我忘了在我的问题中删除它。回答得很好。我建议添加一个明确的数据丢失警告,因为输入解析为数百皮秒,将被截断为纳秒以适应java.time。为了完整性,也许可以添加代码,说明如何向另一个方向发展,以生成示例输入中所示的文本。最后,我想知道对第一个输入块使用
Instant.ofEpochSecond
是否更清楚,然后将第二个输入块中表示的小数秒添加到该值中。@OleV.V。当然,考虑到不同的时代参考,我的建议是愚蠢的。我现在要喝更多的咖啡。谢谢,这真是太棒了!我同意日历类很难修改以获得更高的准确性。“1096255084000”只是我使用的一个测试编号,它与代码无关,我忘记在我的问题中删除它。