【问题标题】:Parse seconds-of-day as part of a date string将秒数解析为日期字符串的一部分
【发布时间】:2016-10-18 10:48:17
【问题描述】:

我需要解析具有以下格式的日期字符串: yyyy-MM-dd TTTTT。所有模式字母都是标准的DateTimeFormatter 字母,除了TTTTT 部分,它是一个seconds-of-day 字段。

由于没有为这样的字段定义模式,我需要想出一些别的东西。我的第一个想法是尝试将该字段解析为 milli-of-day (A),但通过使用 5 A's 我的字段被视为最不重要的字符。 ..是的,不是我想要的。

是否有任何开箱即用的解决方案我可以使用,或者我必须求助于一些定制的解决方案(比如忽略TTTTT 字段,手动解析它并在结果日期使用LocalDateTime.plusSeconds())?

也就是说,我怎样才能使下面的测试用例通过?

public class DateTimeParserTest {
    private static final String PATTERN = "yyyy-MM-dd TTTTT";
    private static final DateTimeFormatter FORMATTER =
        DateTimeFormatter.ofPattern(PATTERN);

    @Test
    public void testParseSecondsOfDay() throws Exception {
        String input = "2016-01-01 86399";
        LocalDateTime localDateTime = LocalDateTime.parse(input, FORMATTER);
        assertEquals("2016-01-01T23:59:59", localDateTime.toString());
    }
}

【问题讨论】:

  • 86399 as second-of-day 对应于时钟时间 23:59:59,而不是 00:00,因此您的输入包含两个不同的时间。你想如何解决这种矛盾心理? “00:00:86399”部分根本无效。因此解决方案new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd HH:mm:").appendValue(ChronoField.SECOND_OF_DAY, 5).toFormatter(); 将无济于事。
  • @Meno Hochschild 你完全正确,我更正了问题以反映你的评论。

标签: java datetime datetime-format java-time datetime-parsing


【解决方案1】:

根据您的更正(省略可能矛盾的部分“HH:mm”),Java-8 解决方案将如下所示:

private static final DateTimeFormatter FORMATTER =
  new DateTimeFormatterBuilder()
  .appendPattern("yyyy-MM-dd ")
  .appendValue(ChronoField.SECOND_OF_DAY, 5)
  .toFormatter(); 

【讨论】:

    【解决方案2】:

    嗯,它可能不是你正在寻找的,但我希望它会有所帮助

        private static final String PATTERN = "yyyy-MM-dd HH:mm:ss"; //MODIFICATION HERE 
        private static final DateTimeFormatter FORMATTER =
            DateTimeFormatter.ofPattern(PATTERN);
    
        @Test
        public void testParseSecondsOfDay() throws Exception {
            String input = "2016-01-01 00:00:86399";
    
            int lastIndexOf = input.lastIndexOf(':');
            CharSequence parsable = input.subSequence(0,lastIndexOf)+":00";
            CharSequence TTTTPart = input.subSequence(lastIndexOf+1, input.length());
    
    
            LocalDateTime localDateTime = LocalDateTime.parse(parsable, FORMATTER);
    
            Calendar calendar = Calendar.getInstance(); // gets a calendar using the default time zone and locale.
            calendar.set(
                    localDateTime.getYear(), 
                    localDateTime.getMonth().ordinal(),
                    localDateTime.getDayOfMonth(),
                    localDateTime.getHour(),
                    localDateTime.getMinute(),
                    0);
    
            calendar.add(Calendar.SECOND, Integer.parseInt(TTTTPart.toString()));
    
            StringBuilder toParse = new StringBuilder();
            toParse.append(calendar.get(Calendar.YEAR) /* It gives 2016 but you what 2016, why */-1);
            toParse.append("-").append(calendar.get(Calendar.MONTH) + 1 < 10 ? "0" : "")
                .append(calendar.get(Calendar.MONTH)+1);
            toParse.append("-").append(calendar.get(Calendar.DAY_OF_MONTH) < 10 ? "0" : "")
                .append(calendar.get(Calendar.DAY_OF_MONTH));
            toParse.append(" ").append(calendar.get(Calendar.HOUR_OF_DAY) < 10 ? "0" : "")
                .append(calendar.get(Calendar.HOUR_OF_DAY));
            toParse.append(":").append(calendar.get(Calendar.MINUTE) < 10 ? "0" : "")
                .append(calendar.get(Calendar.MINUTE));
            toParse.append(":").append(calendar.get(Calendar.SECOND) < 10 ? "0" : "")
                .append(calendar.get(Calendar.SECOND));
    
            localDateTime = LocalDateTime.parse(toParse, FORMATTER);
    
            //Why 2015 and not 2016?
            assertEquals("2015-01-01T23:59:59", localDateTime.toString());
    
        }
    

    困扰我的是 2015 年而不是 2016 年,请注意,解决方案被敲定为给您 2015 年而不是 2016 年。

    【讨论】:

      【解决方案3】:

      我仍在使用 Joda,没有 java8,但它会是

          Chronology lenient = LenientChronology.getInstance(ISOChronology.getInstance());
      
          DateTimeFormatter FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:sssss").withChronology(lenient);
          DateTime dateTime = DateTime.parse("2016-01-01 00:00:86399", FORMATTER);
          assertEquals("2016-01-01T23:59:59", dateTime.toLocalDateTime().toString());
      

      也许您可以使用以下方法获得相同的行为:

      DateTimeFormatter formatter =
               DateTimeFormatter.ISO_LOCAL_DATE.withResolverStyle(ResolverStyle.LENIENT);
      

      【讨论】:

      • 没有秒的模式符号(“s”是秒)。对矛盾信息的宽松处理肯定不好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-27
      • 1970-01-01
      • 2013-08-10
      • 2013-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多