【问题标题】:Java Custom Date Argument InputJava 自定义日期参数输入
【发布时间】:2016-12-30 00:13:00
【问题描述】:

我目前正在写一个 Spigot/Craftbukkit plugin 来管理禁令。在一种方法中,我有TempBan Command Executor。我的目标是让用户使用自定义的“速记”格式指定禁令持续时间。 例如:/tempban MyUser 5d2w My Reason"

我希望字符串 5d2w 被解析并以 MilliSeconds 的形式返回。我曾尝试自己制作,但它不可靠且仅支持一种时间格式。所以你不能做组合。有没有一种有效的方法来使用JodaTimeJava's default date format class 来完成此任务?谢谢!

【问题讨论】:

  • 如果您想要自定义格式,那么您必须为此编写自己的代码。
  • @BasilBourque 的答案很棒,因为它向您展示了许多示例,但您也可以将“自定义”格式传递给将其解码为正确格式以解析为正确时间格式的方法.不知道为什么你不能使用他的答案中提供的格式。

标签: java date date-formatting


【解决方案1】:

tl;博士

Duration.parse( "PT1H30M" ).toMillis()

ISO 8601

无需发明自己的自定义速记格式。 ISO 8601 标准已经定义了一个类似的format for durations

模式PnYnMnDTnHnMnS 使用P 标记开始,T 将任何年-月-日部分与任何小时-分钟-秒部分分开。

例子:

  • 一个半小时是PT1H30M
  • P3Y6M4D 代表“三年六个月四天”。

java.time

java.time 类在解析/生成字符串时默认使用 ISO 8601 格式。这包括 PeriodDuration 类,用于表示未附加到时间轴的时间跨度。

Duration

Duration d = Duration.ofHours( 1 ).plusMinutes( 30 );
String output = d.toString();

PT1H30M

然后解析。

Duration d2 = Duration.parse( "PT1H30M" );

您可以询问持续时间的总毫秒数。

long millis = d2.toMillis();

5400000

live code in IdeOne.com

但请记住,java.time 类具有更精细的分辨率,即纳秒级。因此,在请求毫秒时,您可能会丢失数据。

另外,我强烈建议您坚持使用 java.time 对象和 ISO 8601 字符串,并避免将日期时间值表示为毫秒等计数

Period

对于年-月-日,使用Period 类。

Period p = Period.parse( "P3Y6M4D" );

……和……

String output = p.toString();

P3Y6M4D

注意这个类的normalized 方法。例如,将“1 年 15 个月”的时间段标准化为“2 年 3 个月”。

另请注意,Period 是基于 LocalDate 信息构建的。因此,它没有时区的概念,也没有关于夏令时 (DST) 等异常的概念。

本课程以一整天的分辨率工作。所以这个类没有提供一个明确的方式来计算毫秒数。


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

  • 两个 cmets: 1. 对于那些使用 Java Duration 旨在表示基于时间的持续时间。但是,似乎 OP 将需要基于日期的持续时间(例如 5d3w),我认为应该使用 Period 代替,这将需要考虑不同的调整(例如 DST)。
  • @AdrianShum 仅供参考:Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。请参阅上一节中关于 ThreeTen-Backport 的第二个项目符号。
  • @AdrianShum 关于Period 的工作方式与Duration 类似,但我添加了一个明确的部分。感谢您提出这一点。但更正:Period 确实 将 DST 考虑在内。 Period 类与 LocalDate 一起使用,因此没有时区概念,也没有诸如夏令时 (DST) 之类的异常情况。在进行加减运算时,ZonedDateTime 可能会考虑夏令时,如 Period 类文档中所述,但这不是 Period 类的工作。
  • 是的,我知道 Joda-Time 处于维护模式 :) 只是另一种选择,有人可能会看。对于Period中的夏令时,可能我没有说清楚。例如,如果您有一个 LocalDateTime(或 ZonedDateTime),它正好在夏令时之前,如果您使用 localDateTime.plus(oneDayDuration)localDateTime.plus(oneDayPeriod),您应该会看到区别:添加 1 天的 Duration将在 24 小时后给您LocalDateTime,而添加 1 天的Period 将在第二天同样给您LocalDateTime(根据我的理解,尚未测试)
  • @AdrianShum 不,你不会看到区别。根据定义,LocalDateTime没有时区的概念,也没有与 UTC 的偏移量,PeriodDuration 也没有。夏令时 (DST) 与所有这三个类都无关。
猜你喜欢
  • 2016-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-30
  • 1970-01-01
  • 1970-01-01
  • 2021-08-05
  • 1970-01-01
相关资源
最近更新 更多