Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.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.time解析秒的分数失败了吗?_Java_Java Time - Fatal编程技术网

java.time解析秒的分数失败了吗?

java.time解析秒的分数失败了吗?,java,java-time,Java,Java Time,随着Mac OS X(Mavericks)上Java 8(b132)的首次发布,以下代码使用了新的works: 渲染: 2011-12-03T12:34:56 但是,当我添加“SS”作为秒的分数(并将“55”作为输入),如中所述,将引发异常: java.time.format.DateTimeParseException:无法在索引0处分析文本“2011120312345655” 文档称默认情况下使用严格模式,并且需要与输入数字相同数量的格式字符。所以我不明白为什么这个代码会失败: Stri

随着Mac OS X(Mavericks)上Java 8(b132)的首次发布,以下代码使用了新的works:

渲染:

2011-12-03T12:34:56
但是,当我添加“SS”作为秒的分数(并将“55”作为输入),如中所述,将引发异常:

java.time.format.DateTimeParseException:无法在索引0处分析文本“2011120312345655”
文档称默认情况下使用严格模式,并且需要与输入数字相同数量的格式字符。所以我不明白为什么这个代码会失败:

String input = "2011120312345655"; 
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );

使用文档中的示例(“978”)的另一个示例(失败):


这个例子很有效,添加了一个小数点(但我在文档中没有发现这样的要求):

呈现:

localDateTime:2011-12-03T12:34:56.978

从输入字符串或格式中省略句点字符会导致失败

失败:

String input = "20111203123456.978"; 
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssSSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
String input = "20111203123456978"; 
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmss.SSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
失败:

String input = "20111203123456.978"; 
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssSSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
String input = "20111203123456978"; 
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHHmmss.SSS");
LocalDateTime localDateTime = LocalDateTime.parse( input, formatter );
Bug–在Java9中修复 这一问题已在中报告。Stephen Colebourne提到以下解决方案:

DateTimeFormatter dtf = 
  new DateTimeFormatterBuilder()
  .appendPattern("yyyyMMddHHmmss")
  .appendValue(ChronoField.MILLI_OF_SECOND, 3)
  .toFormatter();
注意:此解决方案不包括仅两个模式符号的用例。调整可能只使用其他字段,如微秒(6倍SSSS)或纳米秒(9倍SSSS)。有关两个小数位数,请参见下面的“我的更新”

@关于图案符号“S”的含义,请参见:

分数:以秒的分数输出秒场的纳米。 第二个值的nano有九个数字,因此模式的计数 字母从1到9。如果小于9,则纳米级为秒 值被截断,只有最有效的数字被截断 输出。在严格模式下解析时,必须指定解析的位数 匹配图案字母的计数。在宽松模式下解析时 解析的位数必须至少为模式字母的计数, 最多9位

我们看到S代表秒的任何分数(包括纳秒),而不仅仅是毫秒。此外,不幸的是,小数部分目前在邻接值解析中并不适用

编辑:

String input = "2011120312345655"; 
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
int len = input.length();
LocalDateTime ldt = LocalDateTime.parse(input.substring(0, len - 2),  dtf);
int millis = Integer.parseInt(input.substring(len - 2)) * 10;
ldt = ldt.plus(millis, ChronoUnit.MILLIS);
System.out.println(ldt); // 2011-12-03T12:34:56.550
String input = "2011120312345655"; 
DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyyMMddHHmmssSS");
System.out.println(dtf.parseLocalDateTime(input)); // 2011-12-03T12:34:56.550
String input = "2011120312345655"; 
ChronoFormatter<PlainTimestamp> f = 
  ChronoFormatter.ofTimestampPattern("yyyyMMddHHmmssSS", PatternType.CLDR, Locale.ROOT);
System.out.println(f.parse(input)); // 2011-12-03T12:34:56.550
作为背景,这里有一些关于邻接值解析的注释。只要字段由文字(如小数点或时间部分分隔符(冒号))分隔,就不难解释要解析的文本中的字段,因为解析器很容易知道何时停止,即字段部分何时结束以及下一个字段何时开始。因此,如果指定小数点,JSR-310解析器可以处理文本序列

但是,如果您有一个跨越多个字段的相邻数字序列,则会出现一些实现困难。为了让解析器知道字段在文本中何时停止,有必要提前指示解析器给定字段由固定宽度的数字字符表示。这适用于所有采用数字表示的
appendValue(…)
-方法

不幸的是,JSR-310并没有很好地处理小数部分(
appendFraction(…)
)。如果在类
DateTimeFormatterBuilder
的javadoc中查找关键字“nextant”,则会发现此功能仅通过
appendValue(…)
-方法实现。请注意,模式字母S的规范略有不同,但内部委托给
appendFraction()
-method。我假设我们至少要等到Java9(如JDKBug日志或更高版本中所报告的那样?),直到分数部分也可以管理相邻值解析


从2015年11月25日起更新:

String input = "2011120312345655"; 
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
int len = input.length();
LocalDateTime ldt = LocalDateTime.parse(input.substring(0, len - 2),  dtf);
int millis = Integer.parseInt(input.substring(len - 2)) * 10;
ldt = ldt.plus(millis, ChronoUnit.MILLIS);
System.out.println(ldt); // 2011-12-03T12:34:56.550
String input = "2011120312345655"; 
DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyyMMddHHmmssSS");
System.out.println(dtf.parseLocalDateTime(input)); // 2011-12-03T12:34:56.550
String input = "2011120312345655"; 
ChronoFormatter<PlainTimestamp> f = 
  ChronoFormatter.ofTimestampPattern("yyyyMMddHHmmssSS", PatternType.CLDR, Locale.ROOT);
System.out.println(f.parse(input)); // 2011-12-03T12:34:56.550
以下仅使用两个小数位数的代码不起作用,并误解了毫秒部分:

    DateTimeFormatter dtf =
        new DateTimeFormatterBuilder()
            .appendPattern("yyyyMMddHHmmss")
            .appendValue(ChronoField.MILLI_OF_SECOND, 2)
            .toFormatter();
    String input = "2011120312345655";
    LocalDateTime ldt = LocalDateTime.parse(input, dtf);
    System.out.println(ldt); // 2011-12-03T12:34:56.055
解决办法

String input = "2011120312345655"; 
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS");
Date d = sdf.parse(input);
System.out.println(d.toInstant()); // 2011-12-03T12:34:56.055Z
不起作用,因为
SimpleDataFormat
也以错误的方式解释分数,类似于现代示例(请参见输出,55毫秒而不是550毫秒)

剩下的解决方案要么是等待不确定的很长时间,直到Java9(或更高版本?),要么是编写自己的hack或使用第三方库作为解决方案

基于恶意攻击的解决方案:

String input = "2011120312345655"; 
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
int len = input.length();
LocalDateTime ldt = LocalDateTime.parse(input.substring(0, len - 2),  dtf);
int millis = Integer.parseInt(input.substring(len - 2)) * 10;
ldt = ldt.plus(millis, ChronoUnit.MILLIS);
System.out.println(ldt); // 2011-12-03T12:34:56.550
String input = "2011120312345655"; 
DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyyMMddHHmmssSS");
System.out.println(dtf.parseLocalDateTime(input)); // 2011-12-03T12:34:56.550
String input = "2011120312345655"; 
ChronoFormatter<PlainTimestamp> f = 
  ChronoFormatter.ofTimestampPattern("yyyyMMddHHmmssSS", PatternType.CLDR, Locale.ROOT);
System.out.println(f.parse(input)); // 2011-12-03T12:34:56.550
解决方案使用:

String input = "2011120312345655"; 
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
int len = input.length();
LocalDateTime ldt = LocalDateTime.parse(input.substring(0, len - 2),  dtf);
int millis = Integer.parseInt(input.substring(len - 2)) * 10;
ldt = ldt.plus(millis, ChronoUnit.MILLIS);
System.out.println(ldt); // 2011-12-03T12:34:56.550
String input = "2011120312345655"; 
DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyyMMddHHmmssSS");
System.out.println(dtf.parseLocalDateTime(input)); // 2011-12-03T12:34:56.550
String input = "2011120312345655"; 
ChronoFormatter<PlainTimestamp> f = 
  ChronoFormatter.ofTimestampPattern("yyyyMMddHHmmssSS", PatternType.CLDR, Locale.ROOT);
System.out.println(f.parse(input)); // 2011-12-03T12:34:56.550
使用我的库的解决方案:

String input = "2011120312345655"; 
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
int len = input.length();
LocalDateTime ldt = LocalDateTime.parse(input.substring(0, len - 2),  dtf);
int millis = Integer.parseInt(input.substring(len - 2)) * 10;
ldt = ldt.plus(millis, ChronoUnit.MILLIS);
System.out.println(ldt); // 2011-12-03T12:34:56.550
String input = "2011120312345655"; 
DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyyMMddHHmmssSS");
System.out.println(dtf.parseLocalDateTime(input)); // 2011-12-03T12:34:56.550
String input = "2011120312345655"; 
ChronoFormatter<PlainTimestamp> f = 
  ChronoFormatter.ofTimestampPattern("yyyyMMddHHmmssSS", PatternType.CLDR, Locale.ROOT);
System.out.println(f.parse(input)); // 2011-12-03T12:34:56.550
String input=“2011120312345655”;
计时器f=
TimeStampPattern的计时格式(“yyyymmddhhmmsss”,PatternType.CLDR,Locale.ROOT);
System.out.println(f.parse(input));//2011-12-03T12:34:56.550

从2016年4月29日起更新:

String input = "2011120312345655"; 
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
int len = input.length();
LocalDateTime ldt = LocalDateTime.parse(input.substring(0, len - 2),  dtf);
int millis = Integer.parseInt(input.substring(len - 2)) * 10;
ldt = ldt.plus(millis, ChronoUnit.MILLIS);
System.out.println(ldt); // 2011-12-03T12:34:56.550
String input = "2011120312345655"; 
DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyyMMddHHmmssSS");
System.out.println(dtf.parseLocalDateTime(input)); // 2011-12-03T12:34:56.550
String input = "2011120312345655"; 
ChronoFormatter<PlainTimestamp> f = 
  ChronoFormatter.ofTimestampPattern("yyyyMMddHHmmssSS", PatternType.CLDR, Locale.ROOT);
System.out.println(f.parse(input)); // 2011-12-03T12:34:56.550

正如人们通过上面提到的JDK问题所看到的,它现在被标记为已解决-对于Java9这里有一个算法,它调整从格式化日期
字符串
返回的尾随零的顺序

/**
 * Takes a Date and provides the format whilst compensating for the mistaken representation of sub-second values.
 * i.e. 2017-04-03-22:46:19.000991 -> 2017-04-03-22:46:19.991000
 * @param pDate Defines the Date object to format.
 * @param pPrecision Defines number of valid subsecond characters contained in the system's response.
 * */
private static final String subFormat(final Date pDate, final SimpleDateFormat pSimpleDateFormat, final int pPrecision) throws ParseException {
    // Format as usual.
    final String lString        = pSimpleDateFormat.format(pDate);
    // Count the number of characters.
    final String lPattern       = pSimpleDateFormat.toLocalizedPattern();
    // Find where the SubSeconds are.
    final int    lStart         = lPattern.indexOf('S');
    final int    lEnd           = lPattern.lastIndexOf('S');
    // Ensure they're in the expected format.
    for(int i = lStart; i <= lEnd; i++) { if(lPattern.charAt(i) != 'S') {
        // Throw an Exception; the date has been provided in the wrong format.
       throw new ParseException("Unable to process subseconds in the provided form. (" + lPattern + ").", i);
    } }
    // Calculate the number of Subseconds. (Account for zero indexing.)
    final int lNumSubSeconds = (lEnd - lStart) + 1;
    // Fetch the original quantity.
    String lReplaceString = lString.substring(lStart + (lNumSubSeconds - pPrecision), lStart + lNumSubSeconds);
    // Append trailing zeros.
    for(int i = 0; i < lNumSubSeconds - pPrecision; i++) { lReplaceString += "0"; }
    // Return the String.
    return lString.substring(0, lStart) + lReplaceString;
}
/**
*获取日期并提供格式,同时补偿亚秒值的错误表示。
*即2017-04-03-22:46:19.000991->2017-04-03-22:46:19.991000
*@param pDate定义要格式化的日期对象。
*@param pPrecision定义系统响应中包含的有效亚秒字符数。
* */
私有静态最终字符串子格式(最终日期更新、最终SimpleDateFormat pSimpleDateFormat、最终整数精度)引发ParseException异常{
//格式和往常一样。
最终字符串lString=pSimpleDateFormat.format(pDate);
//计算字符数。
最后一个字符串lPattern=pSimpleDateFormat.toLocalizedPattern();
//找到亚秒的位置。
final int lStart=lPattern.indexOf('S');
final int lEnd=lPattern.lastIndexOf('S');
//确保它们符合预期格式。
对于(int i=l开始;i

类似这样的东西帮助我

分数是纳秒。你能试着用9位数字吗?尽管从阅读文档来看,只要模式与数字匹配,它应该用少于9位数字就行了