如何解决来自 LocalDate 和字符串的 Joda LocalDateTime
我有:
它们中的任何一个都可以不存在(Scala 的 Option
)。
如何将这两者结合起来获得 joda LocalDateTime
,即仅表示没有时区的日期和时间的实体?
解决方法
要结合这两个选项,自然的方法是使用 flatMap
方法,如下所示:
val onlyDateOption: Option[LocalDate] = ???
val timeAndZoneOption: Option[String] = ???
val result: Option[LocalDateTime] = onlyDateOption.flatMap { onlyDate =>
timeAndZoneOption.map { timeAndZone =>
// Some logic here to build the LocalDateTime from onlyDate and timeAndZone
}
}
也可以用 for-comprehension
以更易读的方式编写:
val result: Option[LocalDateTime] = for {
onlyDate <- onlyDateOption
timeAndZone <- timeAndZoneOption
} yield {
// Some logic here to build the LocalDateTime from onlyDate and timeAndZone
}
现在,如何使用 Joda 构建您期望的内容可能可以通过各种不同的方式来完成,其中一种可能是:
onlyDate
.toLocalDateTime(LocalTime.MIDNIGHT)
.withHourOfDay(...) // hour extracted from the string somehow
.withMinuteOfHour(...) // minute extracted from the string somehow
我不熟悉 Joda API,可能还有另一种更简单的方法
,如何使用 Joda-Time 组合 LocalDate 和 String
您已经得到了详细处理 Option
使用的答案。在这里,我想更详细地介绍使用 Joda-Time 将 LocalDate
和 String
组合成 LocalDateTime
。我了解您正在从旧代码中获取 Joda-Time LocalDate
,并且需要将 Joda-Time LocalDateTime
返回给旧代码。我假设您知道字符串中其缩写的时区。我认为您应该验证该缩写,因为中欧时间在一年的标准时间部分使用缩写 CET,在夏令时 (DST) 使用 CEST。原谅我的 Java 代码。
DateTimeUtils.setDefaultTimeZoneNames(createTimeZoneNamesMap());
DateTimeFormatter timeFormatter = DateTimeFormat.forPattern("H:mm z");
LocalDate date = new LocalDate(2021,5,22);
String timeAndZoneString = "14:20 CEST";
LocalTime time = LocalTime.parse(timeAndZoneString,timeFormatter);
DateTime dateTime = date.toDateTime(time,ZONE);
// Validate time zone abbreviation; take overlap at fall-back into account
String earlierCorrectTimeString = dateTime.withEarlierOffsetAtOverlap()
.toString(timeFormatter);
if (! timeAndZoneString.equals(earlierCorrectTimeString)) {
String laterCorrectTimeString = dateTime.withLaterOffsetAtOverlap()
.toString(timeFormatter);
if (! timeAndZoneString.equals(laterCorrectTimeString)) {
throw new IllegalStateException("Incorrect time zone abbreviation for date");
}
}
LocalDateTime ldt = dateTime.toLocalDateTime();
System.out.println(ldt);
输出:
2021-05-22T14:20:00.000
我用过这两个辅助声明:
private static final DateTimeZone ZONE = DateTimeZone.forID("Europe/Paris");
private static Map<String,DateTimeZone> createTimeZoneNamesMap() {
Map<String,DateTimeZone> names = new HashMap<>(4);
names.put("CET",ZONE);
names.put("CEST",ZONE);
return names;
}
日期时间的有效性也被验证:date.toDateTime()
验证结果 DateTime
不会落在 spring-forward 的间隙中,如果它抛出一个 IllegalInstantException:
会。
如果您在字符串中收到的小时数始终是两位数,则格式模式字符串需要指定这一点,因此 HH:mm z
。
请注意,您在极端情况下会丢失信息:如果时间落在回退的重叠中,时区缩写会消除歧义,但您生成的 LocalDateTime
是不明确的。例如,日期为 2021-10-31
,时间字符串为 2:20 CEST
。然后我们知道时间是在一年中的夏令时部分,也就是时钟倒转之前。您返回 2021-10-31T02:20:00.000,接收者将无法分辨是将其理解为 2021-10-31T02:20:00.000+02:00(夏令时)还是 2021-10-31T02 :20:00.000+01:00(标准时间)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。