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

ame*_*nin 6 java jodatime simpledateformat java-time

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

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

Jod*_*hen 8

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


有支持24:00java.time不过.完全可以使用标准格式化技术对其进行解析,但是必须使用SMART或LENIENT模式,请参阅ResolverStyle.默认模式是SMART,但是DateTimeFormatter类似的formtter常量DateTimeFormatter.ISO_LOCAL_DATE_TIME是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
Run Code Online (Sandbox Code Playgroud)

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

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

可以使用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);
Run Code Online (Sandbox Code Playgroud)

第二个支持元素是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
Run Code Online (Sandbox Code Playgroud)

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


Men*_*ild 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.
Run Code Online (Sandbox Code Playgroud)

除非你使用宽松的解析模式,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
Run Code Online (Sandbox Code Playgroud)

受欢迎的第三方图书馆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
Run Code Online (Sandbox Code Playgroud)

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

PlainTime time24 = PlainTime.midnightAtEndOfDay(); // or: PlainTime.of(24, 0);
System.out.println(time24); // T24
Run Code Online (Sandbox Code Playgroud)