问题
I've been looking for this for a while, with no success so far. Do you know if there's a "DateFormat" ish class, that will allow me to use "00:00:00" and "24:00:00" as input parameters (they're both midnight) but when called "getHour()" I'll get 0 or 24 as a result?
Using "kk" will only allow me to have <1:24> range, meanwhile I'm looking for <0:24> range formatting
回答1:
The value 24:00
is not represented in a LocalTime
because it is strictly part of the next day. Consideration was given to models where 24:00
could be represented as part of LocalTime
, but the conclusion was that it would be very confusing in a lot of use cases, and create more bugs than it solves.
There is support for 24:00
in java.time
however. It is perfectly possible to parse it using the standard formatting techniques, however it is necessary to use SMART or LENIENT mode, see ResolverStyle. The default mode is SMART, however the formtter constants on DateTimeFormatter
like DateTimeFormatter.ISO_LOCAL_DATE_TIME
are in STRICT mode. Thus, ofPattern()
defaults to SMART mode:
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
Note that this also works for OffsetDateTime
and ZonedDateTime
. The standard parser for Instant
supports 24:00
without a special formatter:
Instant instant = Instant.parse("2015-01-01T24:00:00Z");
System.out.println(instant); // 2015-01-02T00:00:00Z
Any formatter can be converted to SMART or LENIENT mode using withResolverStyle() as follows:
DateTimeFormatter f = ... // obtain a formatter somehow
DateTimeFormatter smartMode = f.withResolverStyle(ResolverStyle.SMART);
// for example
f = DateTimeFormatter.ISO_LOCAL_DATE_TIME.withResolverStyle(ResolverStyle.SMART);
The second element of support is parseExcessDays(). This allows the excess day to be obtained when only the time is being parsed:
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
Finally, a note for advanced users. It should in theory be possible to write your own implementation of Temporal
that is a copy of LocalTime
but with support for 24:00
as a valid value. Such a class, say LocalTimeWithEndOfDay
, could then operate with the formatter/parser without issue (and might make a good addition to ThreeTen-Extra.
回答2:
First let's make clear that the time 24:00 is a valid ISO-8601-time. Citation from 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.
Java itself does not support 24:00 unless you use the lenient parsing mode of SimpleDateFormat
. But even then the support is not available because if you ask the result (an instance of java.util.Date
) for the hour you get zero as you have already observed. Similar thoughts are valid for java.util.GregorianCalendar
. After parsing, there is no chance to determine if the input was 24:00 or not (without knowing what the original input was).
Java-8 also has no real support for this special hour. The best thing you can do here is using parseExcessDays() applied on the raw parsed data of DateTimeFormatter
. You could use a workaround like this:
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
The popular 3rd-party library Joda-Time has no support for 24:00. The situation is similar to SimpleDateFormat
.
The only library with built-in support I am aware of is Time4J which I have written myself. The full support is limited to PlainTime
(similar pendant to LocalTime
), not valid for complete date-time-representations (where it would be ambivalent, timestamps containing 24:00 will automatically be normalized to next day at 00:00):
PlainTime time = Iso8601Format.EXTENDED_WALL_TIME.parse("24:00:00");
System.out.println(time.get(PlainTime.ISO_HOUR)); // 24
Note that the state space of class PlainTime
is slightly extended such that it can hold this special ISO-time-value. Therefore a direct programmatical access like this is possible:
PlainTime time24 = PlainTime.midnightAtEndOfDay(); // or: PlainTime.of(24, 0);
System.out.println(time24); // T24
来源:https://stackoverflow.com/questions/31106357/simpledateformat-that-allow-240000-and-000000-as-inputs