将日期字符串转换为 ZonedDateTime

Converting Date String to ZonedDateTime

我收到一个 查询参数 日期,如 yyyy-MM-DD (2022-03-08)
我想将其转换为 java.util.Calendar / java.util.GregorianCalendar 格式。

所以我的想法是: 字符串 -> ZonedDateTime -> 日历。

我做了什么:

ZonedDateTime parsedDate = ZonedDateTime.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
//date = 2022-03-08

即使格式正确,我也会得到:

Text '2022-03-08' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {},ISO resolved to 2022-03-08 of type java.time.format.Parsed

我发现这个错误是因为我的字符串没有时区。

一个建议是使用 LocalDate

 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
 LocalDate date = LocalDate.parse(fecha, formatter);

但我不能使用 localDate 作为 ZonedDateTime.parse() 的参数。

我还能尝试什么?

除了它的静态 parse() 方法之外,还有其他获取 ZonedDateTime 的方法。以下是将 LocalDateTime 变成 ZonedDateTime 的方法:

ZonedDateTime zoned = dateTime.atZone(ZoneId.of( "America/New_York"));

或者如果你有 LocalDate:

ZonedDateTime zoned = 
          date.atStartOfDay( ZoneId.of( "America/New_York" ));

我不会使用 java.util.CalendarDate。他们是垃圾。我会坚持使用 LocalDate 或使用 ZonedDateTime,具体取决于您是否需要跟踪时区。我想,无论哪种方式,这都可以让您到达您想去的地方,因为一旦您拥有 ZonedDateTime.

,听起来您就知道自己想做什么了

更新:我查看了如何将 ZoneDateTime 转换为日历:

Calendar calendar = GregorianCalendar.from(zoned);

以防万一你还没有走那么远并且真的想走那条路。

I want to conver this to java.util.Calendar / java.util.GregorianCalendar formmat.

这似乎很愚蠢; Calendar/GregorianCalendar 已过时,API 可怕。既然工具箱里有一把闪亮的新螺丝刀,为什么还要使用破损的螺丝刀呢?不要这样做。

So my idea is converto: String -> ZonedDateTime -> Calendar.

这似乎很愚蠢。该字符串不包含 ZonedDateTime。它甚至不包含 LocalDateTime。分明就是一个LocalDate。因此,将其转换为本地日期,然后从那里开始。

java.time 包的强大之处在于,每个不同的概念及时在 j.t 包中都有一个正确命名的匹配类型。例如,java.util.Date是一个谎言:它是一个时间戳,与日期没有任何关系;为 'what year is it' 询问 Date 对象已损坏(尝试一下,您会收到警告)。

日历同样是一个彻头彻尾的谎言。它根本不代表日历;它也代表一个时间戳。

另一方面,

LocalDate 是完全正确的:它代表日期(不是时间),并且不包括时区或其他本地化信息:只有 'locally' 才有意义。

每一站都应该有意义,就其本身而言:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd");
LocalDate date = LocalDate.parse("2022-10-01", formatter);

到目前为止,还不错。我就停在那里 - 为什么说谎?为什么 return 日历既是 API 明智的谎言(class 不代表日历),即使有人确切地知道日历是什么,它仍然是 一个谎言:日历意味着它有准确的时间 一个时区。你没有有时间,也没有时区。为什么 return 暗示一些不存在的东西?

但是,如果必须,请显式添加时区和时间,然后继续:

ZonedDateTime zdt = someLocalDate.atStartOfDay().atZone(ZoneId.of("Europe/Amsterdam"));
GregorianCalendar gc = GregorianCalendar.from(zdt);

这段代码清晰易读:crystal清楚地表明代码选择了一个时间,选择了一个区域。

但是,再一次,现在你得到了一个你不应该为任何事情使用的可怕的、可怕的对象。