将一天中的秒数作为日期字符串的一部分进行解析

Parse seconds-of-day as part of a date string

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

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

是否有任何我可以使用的开箱即用的解决方案,或者我是否必须求助于一些定制的解决方案(比如忽略 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());
    }
}

好吧,这可能不是您想要的,但我希望它对您有所帮助

    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 年。

我仍在使用 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);

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

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