来自 LocalDate 和字符串的 Joda LocalDateTime
Joda LocalDateTime from LocalDate and string
我有:
- 一个joda
LocalDate
,所以它没有时间信息只有日期
- 包含时区信息的字符串,如
"14:20 CEST"
它们中的任何一个都可以不存在(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
,并且需要 return 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
。然后我们知道时间是在一年中的夏令时部分,也就是在时钟拨回之前。你 return 2021-10-31T02:20:00.000,接收方将无法判断是将其理解为 2021-10-31T02:20:00.000+02:00(夏令时)还是 2021 -10-31T02:20:00.000+01:00(标准时间)。
我有:
- 一个joda
LocalDate
,所以它没有时间信息只有日期 - 包含时区信息的字符串,如
"14:20 CEST"
它们中的任何一个都可以不存在(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
,并且需要 return 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
。然后我们知道时间是在一年中的夏令时部分,也就是在时钟拨回之前。你 return 2021-10-31T02:20:00.000,接收方将无法判断是将其理解为 2021-10-31T02:20:00.000+02:00(夏令时)还是 2021 -10-31T02:20:00.000+01:00(标准时间)。