Java Calendar.getInstance().getTime()返回“中的日期”;格林尼治标准时间;而不是默认时区
输出: 2017年9月12日星期二12:36:24 2007年1月1日星期一12:36:24 但是,当我在不同的环境中使用相同的代码时,输出更改如下: 输出: 2017年9月12日星期二12:36:24 2007年1月1日星期一12:36:24 GMT 仅供参考,我试图打印日历实例的时区,在设置值之前和之后,两者都在“IST”中Java Calendar.getInstance().getTime()返回“中的日期”;格林尼治标准时间;而不是默认时区,java,calendar,gettime,Java,Calendar,Gettime,输出: 2017年9月12日星期二12:36:24 2007年1月1日星期一12:36:24 但是,当我在不同的环境中使用相同的代码时,输出更改如下: 输出: 2017年9月12日星期二12:36:24 2007年1月1日星期一12:36:24 GMT 仅供参考,我试图打印日历实例的时区,在设置值之前和之后,两者都在“IST”中 我想知道这件事的根本原因 您需要设置时区,您将获得所需的结果 TimeZone.setDefault(TimeZone.getTimeZone(“IST”) 这是一个工
我想知道这件事的根本原因 您需要设置时区,您将获得所需的结果
TimeZone.setDefault(TimeZone.getTimeZone(“IST”)代码>
这是一个工作代码
Calendar c = Calendar.getInstance();
System.out.println(c.getTime());
c.set(2007, 0, 1);
System.out.println(c.getTime());
根据“通常情况下,您可以使用getDefault获得时区,它根据程序运行的时区创建时区。例如,对于在日本运行的程序,getDefault根据日本标准时间创建时区对象。”
因此,当您在不同的时区运行时,它将用作默认时区。希望你现在明白了。我附上医生。请阅读。谈论这种有趣的行为:
Calendar类的源代码:
import java.util.Calendar;
import java.util.TimeZone;
public class Cal {
public static void main(String[] args) {
// TODO Auto-generated method stub
TimeZone.setDefault(TimeZone.getTimeZone("IST")); // Add this before print
Calendar c = Calendar.getInstance();
System.out.println(c.getTime());
c.set(2007, 0, 1);
System.out.println(c.getTime());
}
}
这导致了set方法:
public final void set(int year, int month, int date)
{
set(YEAR, year);
set(MONTH, month);
set(DATE, date);
}
这里有趣的部分是computeFields()方法,它有两个实现(一个用于Gregorian,一个用于Japenese calendar)。这些方法相当复杂,但据我所知,这是您的日历实例在您的用例中可能更改时区的唯一地方。您问题的第二个输出是运行爱尔兰时间(欧洲/都柏林)的JVM上的正确和预期行为。2017年9月12日,爱尔兰进入夏季时间(DST)。虽然没有明确的文档记录,Date.toString()
(在打印从c.getTime()
获得的Date
时隐式调用该函数)打印JVM时区中的日期和时间,该时区在9月份呈现为爱尔兰夏季的IST
当您在日历
对象上使用爱尔兰时间设置日期时,将保留一天中的小时数;在你的情况下,你得到2007年1月1日12:36:24爱尔兰标准时间。现在想象一下,如果爱尔兰夏季时间和爱尔兰标准时间都被视为IST,那会有多混乱。你将无法分辨。相反,由于爱尔兰标准时间与格林尼治标准时间一致,因此当日期不在一年中的夏季(一月不是)时,这就是Date.toString()
打印的内容
我的猜测是,您的第一个输出来自一个在印度运行的JVM。它也被渲染为IST,由于印度不使用夏季时间,所以相同的缩写被命名为summer和winter
java.time
在理解您观察到的行为的解释之前,我发表了一篇关于过时和现代Java日期和时间类的评论。不过,我仍然不认为这一评论有什么不妥。这是代码的现代等价物:
public void set(int field, int value)
{
// If the fields are partially normalized, calculate all the
// fields before changing any fields.
if (areFieldsSet && !areAllFieldsSet) {
computeFields();
}
internalSet(field, value);
isTimeSet = false;
areFieldsSet = false;
isSet[field] = true;
stamp[field] = nextStamp++;
if (nextStamp == Integer.MAX_VALUE) {
adjustStamp();
}
}
它打印
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Europe/Dublin"));
System.out.println(zdt);
zdt = zdt.with(LocalDate.of(2007, Month.JANUARY, 1));
System.out.println(zdt);
如果要使用JVM的时区设置,请使用ZoneId.systemDefault()
而不是ZoneId.of(“欧洲/都柏林”)
。正如名称所述,Date
与之相反,ZonedDateTime
包含时区。它更多地对应于旧的日历
类。如您所见,其toString
方法以明确的地区/城市格式打印UTC的偏移量(Z
表示零偏移量)和时区名称。我相信这会减少混乱的空间。如果要以特定格式打印日期,请使用DateTimeFormatter
附录:代码的示例输出
为完整起见,以下是运行不同时区时代码的输出,这些时区可能呈现为IST:
- 欧洲/都柏林(同意您的第二次输出)
- 亚洲/特拉维夫
Tue Sep 12 11:19:28 IST 2017
Mon Jan 01 11:19:28 GMT 2007
- 亚洲/加尔各答(同意您的第一个输出)
则另一台机器上的默认时区不同。检查系统的时区配置。日期没有时区,如果要更改日历的时区,您需要使用日历的时区。设置时区(时区)。如果对你有帮助的话。我完全肯定,并反复核对了各种情况。无法透露在哪里,但我仍然看不到相同的行为。i、 例如,在同一个*JVM上运行的两个不同java类中getTime()的两个不同输出感谢您的响应。在第一种情况下,我没有设置时区。但是,我仍然可以在默认时区打印date对象。我需要知道为什么这两种情况不同。我希望能够找到差异的根本原因。我有这种方法作为解决此问题的备份解决方案。但是,我实际上想知道这一切的根本原因。再次感谢您的快速响应:)是的,您可以更改JVM的默认时区。从而破坏了您自己的程序和JVM中运行的其他程序的功能。注意,谢谢你的建议,先生@OleV.V。让我试试这个。@UDID恐怕我们彼此没有正确地理解对方。这个想法是你的,你写了TimeZone.setDefault(TimeZone.getTimeZone(“IST”)代码>。我警告你,这很有趣,但并不相关。Calendar
对象包含一个时区,但是由getTime()
返回的Date
对象不包含相同的时区-仅仅因为它根本不包含任何时区。@OleV.V。也许我遗漏了什么:在两个print语句之间的某个地方,时区发生了变化(至少输出显示了类似的情况)。发生了三件事:1。调用日历的set(int,int,int)方法2。调用calendars getTime()方法3。对日期的toString()方法的隐式调用。我写道,时区的内部状态可以通过第一次通话来改变。或者我是。如果我们假设日历的内部时区状态为
Tue Sep 12 11:19:28 IST 2017
Mon Jan 01 11:19:28 GMT 2007
Tue Sep 12 13:19:28 IDT 2017
Mon Jan 01 13:19:28 IST 2007
Tue Sep 12 15:49:28 IST 2017
Mon Jan 01 15:49:28 IST 2007