(简单)允许24:00:00和00:00:00作为输入的DateFormat

时间:2015-06-29 00:55:00

标签: java jodatime simpledateformat java-time

我一直在寻找这个,但到目前为止没有成功。你知道是否有" DateFormat" ish class,这将允许我使用" 00:00:00"和" 24:00:00"作为输入参数(它们都是午夜)但是当被调用时#34; getHour()"结果我会得到0或24?

使用" kk"只会让我有< 1:24>范围,同时我正在寻找< 0:24>范围格式

2 个答案:

答案 0 :(得分:8)

24:00未在LocalTime中表示,因为它严格属于第二天。考虑了24:00可以表示为LocalTime的一部分的模型,但结论是在很多用例中它会非常混乱,并且会产生比它解决的更多错误。

然而,24:00支持java.time。完全可以使用标准格式化技术对其进行解析,但是必须使用SMART或LENIENT模式,请参阅ResolverStyle。默认模式为SMART,但DateTimeFormatter上的DateTimeFormatter.ISO_LOCAL_DATE_TIME上的formtter常量处于STRICT模式。因此,ofPattern()默认为SMART模式:

static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm");

LocalDateTime ldt = LocalDateTime.parse("2012-12-03T24:00", FORMATTER);
System.out.println(ldt);  // 2012-12-04T00:00

请注意,这也适用于OffsetDateTimeZonedDateTimeInstant的标准解析器支持24:00,没有特殊的格式化程序:

Instant instant = Instant.parse("2015-01-01T24:00:00Z");
System.out.println(instant);  // 2015-01-02T00:00:00Z

可以使用withResolverStyle()将任何格式化程序转换为SMART或LENIENT模式,如下所示:

DateTimeFormatter f = ...  // obtain a formatter somehow
DateTimeFormatter smartMode = f.withResolverStyle(ResolverStyle.SMART);

// for example
f = DateTimeFormatter.ISO_LOCAL_DATE_TIME.withResolverStyle(ResolverStyle.SMART);

支持的第二个要素是parseExcessDays()。这允许在仅解析时间时获得超出的日期:

static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm");

TemporalAccessor parsed = TIME_FORMATTER.parse("24:00");
LocalTime lt = LocalTime.from(parsed);
Period excessDays = parsed.query(DateTimeFormatter.parsedExcessDays());
System.out.println(lt + " + " + excessDays);  // 00:00 + P1D

最后,给高级用户留言。从理论上讲,可以编写自己的Temporal实现,它是LocalTime的副本,但支持24:00作为有效值。这样的一个类,比如LocalTimeWithEndOfDay,可以在没有问题的情况下与格式化程序/解析器一起运行(并且可以对ThreeTen-Extra做一个很好的补充。

答案 1 :(得分:6)

首先让我们明确时间 24:00是有效的ISO-8601时间。引自ISO-8601:

4.2 Time of day
4.2.1 General
  This International Standard is based on the 24-hour timekeeping System
  that is now in common use. In expressions of time of day
  hour is represented by two digits from [00] to [24]. The representation
  of the hour by [24] is only allowed to indicate the end of a calendar
  day, see 4.2.3.

除非您使用SimpleDateFormat宽松解析模式,否则Java本身不支持24:00。但即使这样,支持也无法获得,因为如果您在小时内询问结果(java.util.Date的一个实例),那么您已经观察到零。类似的想法对java.util.GregorianCalendar有效。解析后,没有机会确定输入是否是24:00(不知道原始输入是什么)。

Java-8 对此特殊时段也没有真正的支持。您可以在这里做的最好的事情是使用parseExcessDays()应用DateTimeFormatter的原始解析数据。你可以使用这样的解决方法:

String input = "24:00:00";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm:ss");
TemporalAccessor raw = dtf.parse(input);
int hour = raw.query(LocalTime::from).getHour();
Period period = raw.query(DateTimeFormatter.parsedExcessDays());
if (period.equals(Period.ofDays(1))) {
  hour = 24;
}
System.out.println("iso-hour=" + hour); // output: iso-hour=24

受欢迎的第三方图书馆 Joda-Time 不支持24:00。情况类似于SimpleDateFormat

我所知道的唯一具有内置支持的库是Time4J我自己编写的。完全支持仅限于PlainTime(类似于LocalTime的链接),对完整的日期时间表示无效(它会有矛盾,包含24:00的时间戳将自动标准化为第二天在00:00):

PlainTime time = Iso8601Format.EXTENDED_WALL_TIME.parse("24:00:00");
System.out.println(time.get(PlainTime.ISO_HOUR)); // 24

请注意,类PlainTime的状态空间稍微扩展,以便它可以保存此特殊的ISO时间值。因此,可以直接进行这样的程序化访问:

PlainTime time24 = PlainTime.midnightAtEndOfDay(); // or: PlainTime.of(24, 0);
System.out.println(time24); // T24