用Java将日期/时间解析为OffsetDateTimes的最快方法是什么?是否有比标准库更快的库?
例如
OffsetDatetime x = Something.parse("2018-01-02T12:34:56+00:00");
答案 0 :(得分:2)
据我所知,答案是否定的,没有其他库可以将2018-01-02T12:34:56+00:00"
(ISO 8601格式)之类的字符串解析为OffsetDateTime
对象。如果有的话,我本来希望听到或读到它。
接下来的一点让我感到无所适从,但是我也对标准库(AKA java.time)足够有效率,并且可能达到预期的速度感到印象深刻。
编辑:我很好奇并编写了自己的解析方法,以查看我是否能够胜过单参OffsetDateTime.parse
。我曾是。我自己的方法(请参见下面的信息)没有内置方法的灵活性,它只接受大量标准格式的变体中的一个,这可能是其性能的强项。解析一百万次字符串需要花费时间:
OffsetDateTime.parse
这不是推荐!我可能永远不会使用自己的方法。对于绝大多数目的而言,维护负担是不值得的。如果有一天有另一种ISO 8601变体出现,那么您将遇到昂贵的支持问题和错误修复。
我的方法很简单:
private static final OffsetDateTime parse(String s) {
char offsetSign;
if (s.length() != 25
|| s.charAt(4) != '-'
|| s.charAt(7) != '-'
|| s.charAt(10) != 'T'
|| s.charAt(13) != ':'
|| s.charAt(16) != ':'
|| ((offsetSign = s.charAt(19)) != '+' && offsetSign != '-')
|| s.charAt(22) != ':') {
throw new IllegalArgumentException();
}
int offsetHours = Integer.parseInt(s.substring(20, 22));
int offsetMinutes = Integer.parseInt(s.substring(23, 25));
if (offsetSign == '-') {
offsetHours = -offsetHours;
offsetMinutes = -offsetMinutes;
}
return OffsetDateTime.of(Integer.parseInt(s.substring(0, 4)),
Integer.parseInt(s.substring(5, 7)),
Integer.parseInt(s.substring(8, 10)),
Integer.parseInt(s.substring(11, 13)),
Integer.parseInt(s.substring(14, 16)),
Integer.parseInt(s.substring(17, 19)),
0,
ZoneOffset.ofHoursMinutes(offsetHours, offsetMinutes));
}
我知道代码中的错误。我认为不值得彻底测试并修复此答案的错误,因为它不太可能对性能产生太大影响。
答案 1 :(得分:1)
每个解析时间不到一毫秒,您不必担心通过OffsetDateTime
优化解析。当然,您必须要炸更大的鱼。
让我们尝试一些基准测试。
注意事项:众所周知,微基准测试不可靠。但是希望这可以使我们接近现实的理解。
注意::我赶紧发送此代码和此帖子。请仔细检查我的工作。
为避免JVM进行运行时优化,我进行了一些微不足道的尝试,我使用31个不同的值,其中1月的每一天都使用一个值。我将这些重复一千遍以得到31,000个列表。然后我重新整理了清单。
尽管如此,我的结果表明在运行时需要进行大量优化。每次解析的纳秒级数*随循环数而变化很大。
我使用了Azul Systems的Java 11 JVM Zulu 产品,该产品基于OpenJDK版本11.0.2。在MacBook Pro(Retina,15英寸,2013年末),2.3 GHz Intel Core i7、16 GB 1600 MHz DDR3上运行。
结果摘要:
我的结论:
OffsetDateTime
输入字符串。 代码。
System.out.println( "INFO - Starting the OffsetDateTime parsing benchmark." );
List < String > inputsShort = new ArrayList <>( 31 );
inputsShort.add( "2018-01-01T12:34:56+00:00" );
inputsShort.add( "2018-01-02T12:34:56+00:00" );
inputsShort.add( "2018-01-03T12:34:56+00:00" );
inputsShort.add( "2018-01-04T12:34:56+00:00" );
inputsShort.add( "2018-01-05T12:34:56+00:00" );
inputsShort.add( "2018-01-06T12:34:56+00:00" );
inputsShort.add( "2018-01-07T12:34:56+00:00" );
inputsShort.add( "2018-01-08T12:34:56+00:00" );
inputsShort.add( "2018-01-09T12:34:56+00:00" );
inputsShort.add( "2018-01-10T12:34:56+00:00" );
inputsShort.add( "2018-01-11T12:34:56+00:00" );
inputsShort.add( "2018-01-12T12:34:56+00:00" );
inputsShort.add( "2018-01-13T12:34:56+00:00" );
inputsShort.add( "2018-01-14T12:34:56+00:00" );
inputsShort.add( "2018-01-15T12:34:56+00:00" );
inputsShort.add( "2018-01-16T12:34:56+00:00" );
inputsShort.add( "2018-01-17T12:34:56+00:00" );
inputsShort.add( "2018-01-18T12:34:56+00:00" );
inputsShort.add( "2018-01-19T12:34:56+00:00" );
inputsShort.add( "2018-01-20T12:34:56+00:00" );
inputsShort.add( "2018-01-21T12:34:56+00:00" );
inputsShort.add( "2018-01-22T12:34:56+00:00" );
inputsShort.add( "2018-01-23T12:34:56+00:00" );
inputsShort.add( "2018-01-24T12:34:56+00:00" );
inputsShort.add( "2018-01-25T12:34:56+00:00" );
inputsShort.add( "2018-01-26T12:34:56+00:00" );
inputsShort.add( "2018-01-27T12:34:56+00:00" );
inputsShort.add( "2018-01-28T12:34:56+00:00" );
inputsShort.add( "2018-01-29T12:34:56+00:00" );
inputsShort.add( "2018-01-30T12:34:56+00:00" );
inputsShort.add( "2018-01-31T12:34:56+00:00" );
int loops = 100; // 100_000=1,573 nanos each parse. 10_000=4,243. 1_000=10,177. 100=31,125. 1=693,687 nanos each parse.
List < String > inputs = new ArrayList <>( inputsShort.size() * loops );
for ( int i = 1 ; i <= loops ; i++ ) {
inputs.addAll( inputsShort );
}
Collections.shuffle( inputs );
//System.out.println( inputs );
long start = System.nanoTime();
for ( String input : inputs ) {
OffsetDateTime odt = OffsetDateTime.parse( input );
}
long stop = System.nanoTime();
long nanosPerParse = ( ( stop - start ) / inputs.size() );
System.out.println( "INFO: nanosPerParse: " + nanosPerParse + " for a count of: " + inputs.size() + "." );