使用仅限字符串格式化程序将Epoch时间戳字符串转换为Joda Datetime

6
假设我有一个作为字符串的时间戳"1355409000003",是否有一种方式指定日期时间格式,将其解析为Joda DateTime?
即我可以使用格式"MM/dd/YYYY"解析"12/01/2012",使用"YYYY-MM-dd HH:mm"解析"2012-12-01 04:27",但是如何解析"1355409000003"?
编辑:不使用不同的构造函数,假设我必须指定一个字符串格式来解析。

似乎没有现有的格式化程序接受纪元时间。由于毫秒计数是DateTime存储的时间的内部表示,并且已经有一个接受long并设置该字段的构造函数,我认为以前没有人看到过这个需求。如果你真的想要一个,我认为你需要自己编写它。 - azurefrog
1个回答

3

简述

只需要将您的String解析为long。没什么大不了的。

使用取代Joda-Time项目的java.time类。

Instant.ofEpochMilli( 
    Long.parseLong( "1355409000003" ) 
)

2012-12-13T14:30:00.003Z

String解析为long

你的问题并没有太多意义。如果你得到一个代表从1970-01-01T00:00Z时刻起的毫秒数的字符串,那么将该String转换为long,并将其传递给Joda-Time DateTime类型的构造函数。

这在一个已被莫名其妙删除的答案中显示过。

DateTime dt = new DateTime( Long.parseLong( "1355409000003" ) ) ;

或者,个人认为我会分成两行。
long millisSinceEpoch = Long.parseLong( "1355409000003" ) ;
DateTime dt = new DateTime( millisSinceEpoch ) ;

您在该问题下发表了此评论:
很不幸,用于消耗这些时间戳的结构不适合使用不同的构造函数 - 假设我需要指定一个字符串格式,是否有一种格式可以解析时期时间戳?
再次强调,您对需要使用String构造函数的坚持是荒谬的,因为将文本数字包装到解析调用中非常简单: Long.parseLong(“1355409000003”)不要小题大做。

java.time

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

Instant 类表示时间线上的瞬间,以UTC为准,分辨率为纳秒(最多九位小数)。

与上面使用 Joda-Time 相同的方法,使用java.time:将 String 解析为 long,并使用该数字获取一个Instant对象(而不是一个DateTime对象)。

java.time 类避免使用构造函数。因此,不要调用构造函数,而是调用静态工厂方法 Instant.ofEpochMilli

long millisSinceEpoch = Long.parseLong( "1355409000003" ) ;
Instant instant = Instant.ofEpochMilli( millisSinceEpoch ) ;

自定义方法

如果您坚持的问题是这在您的代码中频繁发生,并且您想避免在代码库中散布所有额外的 Long.parseLong(,那么您可以创建自己的实用程序方法来封装此字符串到长整型的转换。

我并不建议这样做,因为它似乎有点过度。但如果您坚持,这里是一些示例代码。

package com.basilbourque.example;

import java.time.Instant;

public class InstantMaker
{
    static public Instant parseMillis ( String countOfMillisecondsSinceEpoch )
    {
        // TODO - Add code to test for invalid inputs, trap for exception thrown.
        long millis = Long.parseLong( countOfMillisecondsSinceEpoch );
        Instant instant = Instant.ofEpochMilli( millis);
        return instant;
    }

    // Constructor. Hide the default constructor as "private". We have no need for instances here.
    private InstantMaker ( )
    {
    }

    // `main` method for testing ad demonstration.
    public static void main ( String[] args )
    {
        Instant instant = InstantMaker.parseMillis( "1355409000003" );
        System.out.println( instant );
    }
}

如果这是您的关注点,我建议真正的问题在于不管是文本还是数字,都依赖于从纪元开始计数。从纪元开始计数会使日期时间处理变得更加困难,因为人类无法分辨这些值。这使得故障排除、调试和日志记录变得棘手和不必要地复杂。我建议重构您的代码,传递Instant实例而不是像"1355409000003"这样的字符串。
ISO 8601
如果您必须将日期时间值序列化为文本,请仅使用标准的ISO 8601格式。这是标准的主要目的,用于在系统之间交换日期时间值。这些格式被设计为实用和明智的,易于机器解析,但易于跨文化的人类阅读。
当解析/生成字符串时,默认情况下java.time类使用标准的ISO 8601格式。您可以在此答案中上面看到这些字符串的示例。

关于 java.time

java.time 框架内置于 Java 8 及其后续版本中。这些类取代了旧的 遗留 日期时间类,如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在已经进入维护模式,建议迁移到 java.time 类。

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

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

如何获取java.time类?

ThreeTen-Extra 项目扩展了 java.time 的附加类。该项目是 java.time 可能未来添加的试验场。您可能会在这里找到一些有用的类,例如 Interval, YearWeek, YearQuarter更多


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接