为什么java中的new java.util.Date(Long.MIN_值)等于;太阳12月2日11:47:04东部时间292269055;?

为什么java中的new java.util.Date(Long.MIN_值)等于;太阳12月2日11:47:04东部时间292269055;?,java,datetime,Java,Datetime,如标题所示,在Java中,如果我这样做的话 System.out.print(new java.util.Date(Long.MAX_VALUE)); System.out.print(new java.util.Date(0)); System.out.print(new java.util.Date(-86400000)); System.out.print(new java.util.Date(Long.MIN_VALUE)); 我把它作为输出 Sun Aug 17 02:12:55 E

如标题所示,在Java中,如果我这样做的话

System.out.print(new java.util.Date(Long.MAX_VALUE));
System.out.print(new java.util.Date(0));
System.out.print(new java.util.Date(-86400000));
System.out.print(new java.util.Date(Long.MIN_VALUE));
我把它作为输出

Sun Aug 17 02:12:55 EST 292278994
Wed Dec 31 19:00:00 EST 1969
Tue Dec 30 19:00:00 EST 1969
Sun Dec 02 11:47:04 EST 292269055
所以年份值变为
Long.MAX\u VALUE>Long.MIN\u VALUE>0>-86400000
?怎么搞的?为什么
日期(Long.MIN_值)
不是负年份

搜索时,我找不到任何与此相关的信息,Java文档也没有提到任何相关信息

我正在使用Java8

另外,执行以下命令

(new java.util.Date(Long.MIN_VALUE).getYear() >= new java.util.Date(0).getYear())
 Long.MIN_VALUE > -86400000
返回
true
,但

(new java.util.Date(Long.MIN_VALUE).after(new java.util.Date(0)))

返回
false

第一件事:以下内容

(new java.util.Date(Long.MIN_VALUE).getYear() >= new java.util.Date(0).getYear())
 Long.MIN_VALUE > -86400000
计算结果为
false

另一方面,Date类中构造函数的负值表示日历中“纪元”之前的日期,即1970年1月1日00:00:00 GMT

因此,用
Long.MIN_值构建的日期可以追溯到过去。更改打印日期的方式可以帮助您发现问题

    System.out.println(new SimpleDateFormat("dd.MM.yyyy GG HH:mm:ss.SSS").format(new Date(Long.MAX_VALUE / 1000)));
    System.out.println(new SimpleDateFormat("dd.MM.yyyy GG HH:mm:ss.SSS").format(new Date(0)));
    System.out.println(new SimpleDateFormat("dd.MM.yyyy GG HH:mm:ss.SSS").format(new Date(-86400000)));
    System.out.println(new SimpleDateFormat("dd.MM.yyyy GG HH:mm:ss.SSS").format(new Date(Long.MIN_VALUE)));
    System.out.println(Long.MIN_VALUE > -86400000);
因此,
新日期(Long.MIN_值)
是基督之前的日期

格式化程序模式非常有助于识别此类点


在这种情况下,G表示纪元指示符,所有的模式指示符都是。

我发现了
toString()的最后两行的可能实现

1029    sb.append(' ').append(date.getYear());  // yyyy
1030    return sb.toString();
因此,
toString
依赖于
getYear
,这反过来又给出了观察到的行为,例如

Date d = new Date(Long.MIN_VALUE);
System.out.println(d.getYear());
真的会印刷吗

292267155

好的,那么深入研究,
getYear()
是非常有用的

/**
* Returns the difference between the year represented by this
* <code>Date</code> object and 1900.
*
* @return the year minus 1900 represented by this date object.
* @deprecated Use Calendar instead of Date, and use get(Calendar.YEAR)
* instead.  Note the 1900 difference in the year.
* @see Calendar
* @see #setYear(int)
*/
public int getYear() {
  Calendar cal = Calendar.getInstance();
  cal.setTimeInMillis(time);
  return cal.get(Calendar.YEAR) - 1900;
}
所以,
Date.getYear()
实际上是
Calendar.getYear()-1900
。(为什么
-1900
?)


减去1900为什么?在1960年到1995年之间,人们通常写下 只有两个数字,例如60或95。当Java问世时,“年” “2000年问题”正是由这一事实引起的,所以他们 不想只返回年份%100,最后两位数。所以 计算减去1900仍然可以让你计算出 世纪,每个人都应该快乐。好吧,我们不是真的。:-—— 奥莱V.V

Calendar.getInstance()
()默认为
java.util.GregorianCalendar
()

所以,在
日历
摘要中

public void setTimeInMillis(long time) {
  clear();
  this.time = time;
  isTimeSet = true;
  computeFields();
}
computeFields()
又长又复杂,但是跟踪它的时间足够长了

if (year <= 0) {
  fields[ERA] = BC;
  fields[YEAR] = 1 - year;
} else {
  fields[ERA] = AD;
  fields[YEAR] = year;
}

if(year其他答案都是正确的。这里还有一些注释

java.time 为什么新的java.util.Date(Long.MIN_值)是java中的

新的?一点也不新。这个类非常旧,与Java的原始版本捆绑在一起

这个麻烦的旧类现在是遗留类,被java.time类所取代。具体地说,是类。要转换为/从,请参阅添加到旧类的新方法

对于最大值/历元值/最小值,这些值定义为常数


  • 100000000-12-31T23:59:59.999999Z

  • 1970-01-01T00:00:00Z

  • -100000000-01-01T00:00Z
小心使用限制 注意不要实际使用最小值或最大值

如果您的目的是为了表示“未知值”,请使用另一个值。许多其他工具(如数据库)将有非常不同的限制,因此您可能会遇到问题。此外,这些极端值对未来的读者/程序员/管理员可能没有任何可识别的意义。这些值甚至可能被误认为是错误或bug

如果只处理最近的日期,我会使用
Instant.EPOCH
作为这样一个标志。许多技术人员都认为1970年的开始很特别

ISO 8601 上面看到的字符串都是标准格式的

默认情况下,java.time类在解析/生成字符串时使用这些标准格式

要生成其他格式的字符串,请参见
DateTimeFormatter

Java8及更高版本 我正在使用Java8

那么您肯定应该从旧类迁移到现代java.time类,这是一个巨大的改进


关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,如,&

该项目现已启动,建议迁移到类

要了解更多信息,请参阅.和搜索堆栈溢出以获取许多示例和解释。规范为

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

从哪里获得java.time类

  • ,及以后
    • 内置的
    • 标准JavaAPI的一部分,带有捆绑实现
    • Java9添加了一些次要功能和修复
    • 大部分java.time功能都在中向后移植到Java6和Java7
    • 更高版本的Android捆绑包实现了java.time类
    • 对于早期的Android,该项目采用了ThreeTen Backport(如上所述)

该项目使用其他类扩展了java.time。该项目是将来可能添加到java.time的一个试验场。您可能会在此处找到一些有用的类,例如、、。

更改格式化程序时,您会注意到,使用
Long.MIN\u VALUE
参数,日期在基督之前!:-)出于礼貌,请在否决表决前留下评论,解释问题的错误之处,以便将来能够正确/避免。谢谢。@T.J.Crowder的“适当的格式化程序”您的意思是像GregorianCalendar?(这给了我同一年)@T.J.Crowder Ok。使用SimpleDataFormat(“y”)以正数表示年份,而SimpleDataFormat(“Y”)以负数表示年份……因为我猜是什么原因?X3@OleV.V.它不是溢出,负年份只是打印为正数,而toString()是