【问题标题】:(Simple)DateFormat that allow 24:00:00 and 00:00:00 as inputs(简单)允许 24:00:00 和 00:00:00 作为输入的日期格式
【发布时间】:2015-06-29 00:55:00
【问题描述】:

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

使用“kk”只会让我拥有 范围,同时我正在寻找 范围格式

【问题讨论】:

  • 格式没有任何意义。或者如果确实如此,它也可能是 、 或 等,因为它们都超过了 24 小时限制,因此都同样“合法”。在 24 小时时钟格式中,第一分钟是 00:00,最后一分钟是 23:59。 23:59 之后的一分钟又是 00:00。 24:00 不存在
  • @deyur 你对 hh 的想法,其中小时数是 1-23,kk 小时数是 1-24。
  • @UnknownOctopus 我在想 hh 因为 OP 希望小时从 0 开始。我同意你的观点,kk 小时是 1-24 但这仍然不能使 0-24 合法(在任何格式)。
  • @deyur 哦,好的,现在我明白了,很抱歉造成混乱。
  • @deyur 24:00 是有道理的,请参阅 ISO-8601 文件,其中明确允许并描述为一天结束时的午夜。

标签: java jodatime simpledateformat java-time


【解决方案1】:

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


不过,java.time 支持 24:00。完全可以使用标准格式化技术对其进行解析,但是必须使用 SMART 或 LENIENT 模式,请参阅ResolverStyle。默认模式是 SMART,但是 DateTimeFormatter 上的格式器常量(如 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

请注意,这也适用于 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的一个很好的补充。

【讨论】:

  • 好吧,我认为 OP 的真正问题不在于宽大(智能、严格等,另请参见宽大模式下的SimpleDateFormat),而是关于如何在解析后实现功能getHour() == 24如果输入是“24:00:00”,则结果。因此,Java-8 中唯一的支持元素仅限于parseExcessDays()(以及实现新Temporal-class 的抽象选项)。你同意吗?
【解决方案2】:

首先让我们明确时间 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.

Java 本身不支持 24:00,除非您使用 SimpleDateFormat 的宽松解析模式。但是即使那样,支持也不可用,因为如果您询问结果(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

流行的第 3 方库 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

【讨论】:

猜你喜欢
  • 2017-09-21
  • 1970-01-01
  • 2013-06-09
  • 2015-02-03
  • 1970-01-01
  • 2011-06-27
  • 1970-01-01
  • 2015-07-19
  • 1970-01-01
相关资源
最近更新 更多