为什么在Java日历对象上设置时区没有效果?

为什么在Java日历对象上设置时区没有效果?,java,date,datetime,calendar,timezone,Java,Date,Datetime,Calendar,Timezone,考虑以下代码片段 TimeZone tz = TimeZone.getTimeZone("GMT"); System.out.println(tz); Calendar cal = Calendar.getInstance(); cal.set(2017, Calendar.DECEMBER, 25); System.out.println("before setting time zone: " + cal.getTime()); cal.s

考虑以下代码片段

    TimeZone tz = TimeZone.getTimeZone("GMT");
    System.out.println(tz);

    Calendar cal = Calendar.getInstance();
    cal.set(2017, Calendar.DECEMBER, 25);

    System.out.println("before setting time zone: " + cal.getTime());
    cal.setTimeZone(tz);

    System.out.println("after setting time zone: " + cal.getTime());
结果如下:

sun.util.calendar.ZoneInfo[id="GMT",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]
before setting time zone: Mon Dec 25 22:39:53 EST 2017 
after setting time zone: Mon Dec 25 22:39:53 EST 2017
时区更改后,为什么日期的打印输出仍然显示EST?难道不是格林尼治时间吗?

tl;博士
避免遗留日期时间类 您正在使用非常麻烦的旧日期时间类,这些类现在是遗留的

要直接回答您的问题,该方法将返回一个。在这些类中的许多设计缺陷中,动态应用JVM的当前默认时区,同时生成字符串。这样您的
EST
就出现了

永远不要使用这些类。只使用它们的替代品,业界领先的java.time类

java.time 该类表示一个仅限日期的值,不包含一天中的时间和时区

LocalDate xmas2017 = LocalDate.of( 2017 , Month.DECEMBER , 25 ) ;
如果需要日期时间,即一天中的第一个时刻,则必须指定时区。时区对于确定日期至关重要。在任何一个特定的时刻,世界各地的日期都因地区而异。例如,中午夜后几分钟是新的一天,而中仍然是“昨天”

大陆/地区
的格式指定,例如,或
太平洋/奥克兰
切勿使用3-4个字母的缩写,例如
EST
IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)

永远不要假设一天从00:00开始。在某些区域,异常情况(如)意味着一天可能在其他时间开始,如01:00:00。让java.time确定一天中的第一个时刻

申请一份工作以获得一份工作

请注意,印度的圣诞节比纽约早得多

ZonedDateTime zdtKolkta = xmas2017.atStartOfDay( ZoneId.of( "Asia/Kolkata" ) ) ;
这就是为什么精灵们的后勤部门安排圣诞老人第一次送货。这些岛屿的圣诞节最早,时区比UTC提前14小时。从那里,驯鹿一只接一只地向东飞去,追逐着连续的午夜,地球旋转着进入新一天的阳光中

如果您希望将同一时刻调整为UTC,请提取始终以UTC为单位的
瞬间

Instant instant = zdt.toInstant() ;

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

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

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

从哪里获得java.time类

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

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

您可以将区域设置为
cal
而不是
cal.getTime()
。后一个是
java.util.Date
类型,您无法设置区域(其方法
java.util.Date.toString()
仅使用系统tz)。意识到
cal.getTime()
为您提供了
java.util.Date
这个著名的博客条目可能会有所帮助:。
ZonedDateTime zdtKolkta = xmas2017.atStartOfDay( ZoneId.of( "Asia/Kolkata" ) ) ;
Instant instant = zdt.toInstant() ;