如何在Java中使用TimeZone解决日光节约问题
我必须在我的Java应用程序中打印EST时间。 我使用以下方法将时区设置为EST:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));
但是,如果在这个时区中遵守夏令时,我的代码不会打印正确的时间(打印时间会less一小时)。
如何使代码工作始终阅读正确的时间,无论是否遵守夏令时?
PS:我尝试将时区设置为EDT,但不能解决问题。
这是开始的问题:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));
应该完全避免使用3个字母的缩写来支持TZDB区域ID。 EST是东部标准时间 – 标准时间从不观察DST; 这不是一个完整的时区名称。 这是用于部分时区的名称。 (不幸的是,我对这个“半时区”概念没有遇到很好的说法。)
你想要一个完整的时区名称。 例如, America/New_York
位于东部时区:
TimeZone zone = TimeZone.getTimeZone("America/New_York"); DateFormat format = DateFormat.getDateTimeInstance(); format.setTimeZone(zone); System.out.println(format.format(new Date()));
其他的答案是正确的,尤其是Jon Skeet的那个 ,但是已经过时了。
java.time
这些旧的date时间类已被Java 8及更高版本中内置的java.time框架取代。
如果您只需要UTC中的当前时间,请使用Instant
类。
Instant now = Instant.now();
正如Jon Skeet的正确答案所解释的, EST
不是一个时区。 这样的3-4个字母代码既不是标准化的,也不是独一无二的,而且还有夏令时(DST)的混淆。 在“大陆/地区”格式中使用适当的时区名称。
也许你指的是北美东海岸的东部标准时间? 还是埃及标准时间? 还是欧洲标准时间?
ZoneId zoneId = ZoneId.of( "America/New_York" ); ZoneId zoneId = ZoneId.of( "Africa/Cairo" ); ZoneId zoneId = ZoneId.of( "Europe/Lisbon" );
使用任何这样的ZoneId
对象来获取当前时刻调整到一个特定的时区产生一个ZonedDateTime
对象。
ZonedDateTime zdt = ZonedDateTime.now( zoneId ) ;
通过从第一个生成另一个ZonedDateTime对象,将ZonedDateTime调整到不同的时区。 java.time框架使用不可变的对象,而不是改变(改变)现有的对象。
ZonedDateTime zdtGuam = zdt.withZoneSameInstant( ZoneId.of( "Pacific/Guam" ) ) ;
而不是为时区input“EST”,您可以input“EST5EDT”。 正如你所说,只是“EDT”不起作用。 这将解决夏令时问题。 代码行如下所示:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST5EDT"));
根据这个答案 :
TimeZone tz = TimeZone.getTimeZone("EST"); boolean inDs = tz.inDaylightTime(new Date());
实现TimeZone类来设置日历的时区可以节省夏令时间。
java.util.TimeZone表示时区偏移量,并计算夏时制。
示例代码:
TimeZone est_timeZone = TimeZoneIDProvider.getTimeZoneID(TimeZoneID.US_EASTERN).getTimeZone(); Calendar enteredCalendar = Calendar.getInstance(); enteredCalendar.setTimeZone(est_timeZone);
在java中,DateFormatter默认使用DST,为了避免日光节约(DST),你需要手动做一个技巧,
首先你必须得到DST偏移,即应用多less毫秒的DST,对于某个地方,DST也是45分钟,对于某些地方是30分钟
但在大多数情况下,DST是1小时
您必须使用Timezone对象,并检查date是否属于DST,然后您必须手动添加DST的偏移量。 例如:
TimeZone tz = TimeZone.getTimeZone("EST"); boolean isDST = tz.inDaylightTime(yourDateObj); if(isDST){ int sec= tz.getDSTSavings()/1000;// for no. of seconds Calendar cal= Calendar.getInstance(); cal.setTime(yourDateObj); cal.add(Calendar.Seconds,sec); System.out.println(cal.getTime());// your Date with DST neglected }