Joda-Time:将 SimpleDateFormat 模式转换为 DateTimeFormat.forPattern

Joda-Time: convert SimpleDateFormat pattern to DateTimeFormat.forPattern

我正在尝试修改一些代码以使用 Joda-Time 而不是 java.sql.Timestamp

目前代码正在使用 Threadlocal 和 SimpleDateFormat:

 public static final ThreadLocal<DateFormat> FORMAT_TIMESTAMP = new ThreadLocal<DateFormat>() {
    @Override
    protected DateFormat initialValue() {
        return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
    }
};

public static String format(Timestamp timestamp) {
    return FORMAT_TIMESTAMP.get().format(timestamp);
}

我的理解是Joda-time是线程安全的,所以没必要用ThreadLocal

考虑到这一点,我将代码修改为:

 public static String format(Instant timestamp) {

    Instant formated = Instant.parse(timestamp.toString(), DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssXXX"));

    return formated.toString();
}

如果我想稍后在代码中将值插入数据库,我打算使用 this 方法。

假设我以正确的方式解决这个问题,是否可以像

一样格式化 DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssXXX")

SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")

目前我收到 Invalid format 异常

X 未被 Joda 识别。将 XXX 替换为 ZZ 应该可以满足您的需要。

因为DateTimeFormat是线程安全的,所以可以跨线程共享。所以您的代码可能如下所示:

private static final DateTimeFormatter FORMAT_TIMESTAMP =
                                      DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZZ");

public static String format(Instant timestamp) {
    return FORMAT_TIMESTAMP.print(timestamp);
}

tl;博士

  • 无需为标准输入定义格式化模式。
  • 直接解析为 java.time 个对象。

例子…

// offset-from-UTC
OffsetDateTime.parse( "2016-01-23T12:34:56.123456789-07:00" ) 

// Z = Zulu = UTC
Instant.parse( "2016-01-23T12:34:56.123456789Z" )  

// ISO 8601 format extended with time zone name appended in square brackets.
ZonedDateTime.parse( "2016-01-23T12:34:56.123456789-05:30[Asia/Kolkata]" )  

详情

Joda-Time project, now in maintenance mode, advises migration to java.time classes.

java.time

不需要 ThreadLocal,因为 java.time class 本质上是 thread-safe because of they are immutable objects.

java.timeclasses 中默认使用日期时间值的标准 ISO 8601 格式。所以通常不需要为此类输入指定格式模式。

Instant

Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds(最多九 (9) 位小数)。

Instant.parse method can parse standard input strings ending in Z, short for Zulu, meaning UTC.

Instant instant = Instant.parse( 
    "2016-01-23T12:34:56.123456789Z" );

OffsetDateTime

对于包含特定 offset-from-UTC, use the OffsetDateTime class and its parse 方法的标准输入字符串。

OffsetDateTime odt = OffsetDateTime.parse( 
    "2016-01-23T12:34:56.123456789-07:00" );

ZonedDateTime

ZonedDateTime class 及其 toString 方法通过在方括号中附加名称来生成超出 ISO 8601 格式的格式的字符串。这是明智的,因为 time zone is much more than an offset-from-UTC. A time zone is an offset plus a set of rules for handling anomalies such as Daylight Saving Time (DST).

这个 class 可以解析并生成这样的字符串。

ZonedDateTime zdt = ZonedDateTime.parse( 
    "2016-01-23T12:34:56.123456789-05:30[Asia/Kolkata]" ) ;

DateTimeFormatter

对于非标准字符串格式,请在 Stack Overflow 中搜索 java.time.format.DateTimeFormatter class。

数据库

要通过支持 JDBC 4.2 或更高版本的 JDBC 驱动程序将此值发送到数据库,请使用 PreparedStatement::setObject 方法并使用 ResultSet::getObject 方法获取。

myPreparedStatement.setObject( … , instant );

如果您的驱动程序不符合要求,请退回到转换为旧的 java.sql 类型。查看添加到旧 classes 的 new conversion methods

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

关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode,建议迁移到java.time。

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

从哪里获得java.time classes?

  • Java SE 8 and SE 9 及更高版本
    • 内置。
    • 标准 Java API 的一部分,带有捆绑实施。
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 and SE 7
  • Android
    • ThreeTenABP项目专门为Android改编了ThreeTen-Backport(上面提到的)。
    • 参见

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.