java.util.Calendar 的默认时区是什么?

8

代码

public String testDate(){ 
      TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
      Calendar fromDate = Calendar.getInstance();
      Date date= new Date();
      System.out.println(fromDate);
      System.out.println(date);
}

在调试下面的日历变量时,我的日历变量显示一个日期时间值为2013-12-09T00:00:00.000Z和时间值为1386649779590

Calendar cal = Calendar.getInstance();

我看到的完整日历详细信息,打印对象时

System.out.println(cal);

控制台

java.util.GregorianCalendar[time=1386649779590,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="US/Eastern",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=US/Eastern,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2013,MONTH=11,WEEK_OF_YEAR=50,WEEK_OF_MONTH=2,DAY_OF_MONTH=9,DAY_OF_YEAR=343,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=11,HOUR_OF_DAY=23,MINUTE=29,SECOND=39,MILLISECOND=590,ZONE_OFFSET=-18000000,DST_OFFSET=0]

当我的java.util.date变量显示日期为Mon Dec 09 07:37:50 EST 2013时,在调试日期变量时

Date date= new Date();

我的默认时区是在程序启动时设置的,为 EST

TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));

我现在从时区 IST 工作。

我的问题是:

为什么 CalendarcalDate()date 不同?


1
@JonSkeet 我已经发布了我所检查的结果。但是我没有得到时区。 - Dileep
1
@JonSkeet 2013-12-09T00:00:00.000Z 这是我在调试日历变量时发现的值。 - Dileep
@JonSkeet 我在问的是 getDefault 时区是 Date 变量的默认时区,对吧?那么 Calendar 的默认时区值是什么?由于这两个值不同,我相信它们正在采用不同的时区! - Dileep
不,你没有。你在问Calendar的默认时区是什么,这与Date不同。你从来没有问过Date的默认时区,这只在toString调用中实际上是相关的。(Date实例没有时区;toString只是使用当前默认时区。)而且你仍然没有说出到底是什么产生了“你发现的值” - 是的,你在调试,但这并没有告诉我们太多信息。一个简短但完整的程序会更加有信息量。 - Jon Skeet
1
我只是想说,在任何时区中,纪元1386592669972都不等于“2013-12-09T00:00:00.000Z”。纪元1386592669972是“2013-12-09T12:37:49.972Z”。您需要准确地显示您如何看到第一个日期 - 调试器还是toString()或其他什么。最好提供一个SSCCE - dcsohl
显示剩余6条评论
4个回答

19
根据Oracle文档,明确提到:

public static Calendar getInstance()
获取使用默认时区和区域设置的日历。返回的日历基于默认时区中的当前时间以及默认区域设置。

默认时区通过public static TimeZone getDefault()进行获取,并在TimeZone.getDefault()中有所提及:

获取此主机的默认时区。默认时区的来源可能会因实现而异。

它将返回计算机上设置的默认时区,除非您已使用public static void setDefault(TimeZone zone)函数显式地设置了TimeZone

我相信上述解释回答了您的两个问题:

  1. java.util.Calendar的默认时区是什么?
  2. 为什么我的类型为Calendar的变量cal显示的时间不是IST或EST?

编辑后:根据您编辑后的问题:

为什么Calendar的cal和Date()的日期不同?

当您调用System.out.println(date);时,将调用toString()函数,如果您查看Date 的源代码,您会发现它通过调用默认时区的displayName函数返回3个字母的简写的时区,而在您的情况下是EST,它是美国东部标准时间(GMT-05:00) 印第安纳州(东部)


第一部分已经解决了,但是为什么在调试时显示的两个日期不同呢? - Dileep

4
日期本身没有任何时区。它的toString()方法使用当前默认时区返回一个字符串。

3
通常使用getDefault来获取TimeZone,它基于程序运行所在的时区创建TimeZone对象。例如,在日本运行的程序中,getDefault会创建一个基于日本标准时间的TimeZone对象。
更多信息请查看TimeZone

是的,时区是默认值由日期使用,但是日历和日期是不同的,它们使用不同的时区值。 - Dileep
@Dileep:不,实际上并不会。如果你认为会出现这种情况,那么请展示一个简短但完整的程序来证明问题,就像我之前所要求的那样。 - Jon Skeet

1
你提到了 "cdate",我注意到日历对象内部有一个名为 "cdate" 的字段。在运行你的示例代码时,我看到 "cdate" 字段确实被初始化为 "2013-12-10T00:00:00.000Z"(当然现在已经过去了24小时)。
那又怎样呢?我不知道你为什么要查看类的内部字段,因为你永远不会直接使用它们。
因此,你的解决方案是忽略它。不要担心你的日历中的 "cdate" 字段;关注那些真正影响你的程序的事情。 CalendartoString() 不太好看,而且是用于调试的;你应该调用 cal.getTime(),这将给你一个 java.util.Date,然后你可以直接打印出来或使用 java.text.DateFormatter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接