提问人:Reilas 提问时间:5/29/2023 最后编辑:Reilas 更新时间:6/21/2023 访问量:82
在转换和扩充值时,使用 ZoneDateTime 与 Calendar 有什么影响?
What are the implications of using ZoneDateTime versus Calendar, when converting and augmenting values?
问:
我不确定在使用 Calendar 对象与使用 ZonedDateTime 对象时会发生什么不可预见的影响,特别是失效。
我想知道是否可以深入了解为什么必须使用一个框架而不是另一个框架来完成值的转换或解析。
我已经查看了 Java 教程,参考了“遗留日期时间代码”,但我无法获得可能发生失效的地方。
套用一下,本教程提到了以下内容。
“Calendar 类不是类型安全的”。
我不关心类型安全,解析只是几个步骤。
“因为这些类是可变的,所以它们不能在多线程应用程序中使用”。
可变状态不是一个主题。
“由于月份编号异常和缺乏类型安全性,应用程序代码中的错误很常见”。
我不关心索引与枚举。
这些观点都不是抽象的对立面。
作为演示,我将同时使用这两个类,以尝试讨论它们的逻辑。
我可以使用 SimpleDateFormat 和 Calendar 解析格式化的 String 值。
String string = "MMMM dd, yyyy '@' h:mm:ss a z";
SimpleDateFormat format = new SimpleDateFormat(string);
String value = "May 28, 2023 @ 6:50:01 pm EDT";
Calendar calendar = Calendar.getInstance();
calendar.setTime(format.parse(value));
如果我从日历中打印数据,我会收到一个有效的结果。
System.out.println(calendar.getTimeInMillis());
System.out.printf("%tc", calendar.getTimeInMillis());
1685314201000
Sun May 28 18:50:01 EDT 2023
而且,我可以使用 DateTimeFormatter 和 ZonedDateTime 解析相同的格式化 String 值。
当然,我必须在值中将“PM”大写——这不是挫折。
DateTimeParseException 甚至指定了字符索引。
DateTimeFormatter format = DateTimeFormatter.ofPattern(string);
ZonedDateTime zonedDateTime = ZonedDateTime.parse(value, format);
同样,如果我从 zonedDateTime 打印数据,我会得到一个有效的结果。
System.out.println(zonedDateTime.toInstant().toEpochMilli());
System.out.printf("%tc%n", zonedDateTime.toInstant().toEpochMilli());
System.out.println(zonedDateTime);
1685314201000
Sun May 28 18:50:01 EDT 2023
2023-05-28T18:50:01-04:00[America/New_York]
如果并排查看数据,您会发现它们是等效的,因此两者都有效。
如果我想增加这些值,比如说,通过添加 4 小时来得出 UTC 值,因为 EDT 是 UTC-4;我可以通过两个班级实现这一点。
对于 Calendar 类,我可以使用 add 方法。
其中,具有 Calendar 类中的可扩展规范。
calendar.add(Calendar.HOUR_OF_DAY, 4);
1685328601000
Sun May 28 22:50:01 EDT 2023
同样,对于 zonedDateTime,我可以使用 plusHours 方法。
zonedDateTime = zonedDateTime.plusHours(4);
1685328601000
Sun May 28 22:50:01 EDT 2023
2023-05-28T22:50:01-04:00[America/New_York]
同样,我得出的值相等,就 Calendar 和 ZonedDateTime 而言。
如果我从 1,685,328,601,000 中减去 1,685,314,201,000,我得到 14,400,000。
14,400,000 相当于 4 小时×(60 分钟 ×(60 秒× 1000 毫秒))。
这使我得出了我的结论,即在基本解析和增强方面,使用一个类而不是另一个类的不利影响。
使用一个类与另一个类时将计算的不可预见的误差是什么?
例如,一个类是否使用更准确的年份度量值(例如 365.25 天)而不是 365.2425?
除了 Java 所陈述的设计含义之外,一个类在哪些方面被证明是惯用的——考虑到两个类将产生等效的值。
我的意思是从哲学的角度来看是惯用的,而不是以范式的、意识形态的、新教的方式说的惯用语。
经验证据不一定适用。
答:
不,他们没有使用“更准确的年份测量”。没有任何方面是 Calendar 不正确的,或者会导致值完全错误。
日历已经过时,因为它难以正确使用,例如将月份编号从 0 到 11 而不是 1 到 12。 它还将物理时间和民事时间混为一谈,区分两者很重要。
使用 java.util.Calendar 可以编写 100% 正确的代码。不过,大多数人不会。
评论
Calendar
ZonedDateTime
Calendar.getInstance()