【问题标题】:Can't use year more than "2038" in date field : Java在日期字段中不能使用超过“2038”的年份:Java
【发布时间】:2019-09-05 08:48:56
【问题描述】:

在我的应用程序中保存日期超过 2038 年时遇到问题,在 jsp 页面上,我正在从日历中获取输入,例如 -

registry.byId('endDateCal').set('value', dojo.date.locale.parse('<c:out value="${empty taskForm.endDate ? taskForm.defaultDate : taskForm.endDate}"/>', {     datePattern: '<%=datePattern%>',     selector: "date"   }));

datePattern 我在我的 jsp 页面上设置,就像

   SimpleDateFormat dateFormat = (SimpleDateFormat)DateFormat.getDateInstance(DateFormat.SHORT, I18nUtility.getLanguageLocaleForCurrentUser());

   String datePattern = dateFormat.toPattern();

当这个值发送到我的 servlet 时,我得到了过去的值,例如 如果我将日期设置为 2040 年 9 月 30 日,那么它将发送日期值到 servlet 9/30/1941。

我看到了 2038 年的问题 Year 2038 problem 但它不是我的情况,因为我可以在 2038 年设置日期,但不能设置超过 2038 年,我也与 this 核对但没有帮助。

注意寻找jdk 7兼容解决方案

【问题讨论】:

  • 你确定它在 Java 方面被破坏了(而不是在 Javascript 代码中)?
  • ..您是否声称可以安全地设置日期after 03:14:07 UTC on 19 January 2038
  • 在发送到 servlet 之前客户端是否正确接收?
  • 80/20 规则。 为了使用缩写年份模式(“y”或“yy”)进行解析,SimpleDateFormat 必须解释相对于某个世纪的缩写年份。它通过将日期调整为创建 SimpleDateFormat 实例之前的 80 年和之后的 20 年来实现这一点。例如,使用“MM/dd/yy”模式和 1997 年 1 月 1 日创建的 SimpleDateFormat 实例,字符串“01/11/12”将被解释为 2012 年 1 月 11 日,而字符串“05/04/ 64" 将被解释为 1964 年 5 月 4 日。 from the docs.
  • 在 SimpleDateFormat 中,您可以设置开始日期以确定如何解释 2 位数年份。见docs.oracle.com/javase/7/docs/api/java/text/…

标签: java date datetime java-7


【解决方案1】:

tl;博士

LocalDate                                    // Modern class for representing a date-only value without time-of-day and without time zone.
.parse(
    "1/23/40" , 
    DateTimeFormatter.ofPattern( "M/d/uu" )  // Defaults to century 20xx. 
)                                            // Returns a `LocalDate` object.
.toString()                                  // Generate text in standard ISO 8601 format.

2040-01-23

指定默认世纪

SimpleDateFormat 类具有在解析具有两位数世纪的输入字符串时假定的世纪的设置:SimpleDateFormat::set2DigitYearStart

但是……你应该停止使用这个类。

java.time

SimpleDateFormat 类是 Java 最早版本捆绑的可怕日期时间类的一部分。这些类现在是遗留的,完全被 JSR 310 中定义的现代 java.time 类所取代。

LocalDate

LocalDate 类表示仅日期值,没有时间,也没有 time zoneoffset-from-UTC

➥ 这个类总是使用 20xx 的世纪来解析具有两位数年份的输入字符串。

String input = "1/23/40" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "M/d/uu" ) ;
LocalDate localDate = LocalDate.parse( input , f ) ;

看到这个code run live at IdeOne.com

localDate.toString(): 2040-01-23

提示:我发现在商业应用程序中使用 2 位数的年份非常麻烦。日期和月份的模糊性很容易产生误解和误解。我建议始终使用 4 位数的年份。

在跨文化共享数据时,这个问题会更加严重。然后我建议对文本日期时间值使用ISO 8601 格式。


关于java.time

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

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

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

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

从哪里获得 java.time 类?

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

【讨论】:

  • 感谢您的回答,此修复仅适用于 jdk8(java.time.*) 或更高版本,不适用于 jdk7 及以下版本,因为我们的应用程序使用的是旧版本的 java ,能否请您推荐jdk7及更低版本的解决方案
  • @Afgan 请参阅我最后添加的“关于 java.time”部分。将 ThreeTen-Backport 库添加到您的项目中绝对是值得的。永远不要使用Date/Calendar 等,它们真的很糟糕。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-11
  • 1970-01-01
  • 1970-01-01
  • 2011-07-18
相关资源
最近更新 更多