首页 文章

如何使用Java中的TimeZone解决夏令时问题

提问于
浏览
54

我必须在我的Java应用程序中打印EST时间 . 我使用以下方法将时区设置为EST:

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));

但是当在这个时区中遵循夏令时时,我的代码不能打印正确的时间(它打印的时间减少1小时) .

无论是否观察到夏令时,如何使代码始终能够正确读取正确的时间?

PS:我尝试将时区设置为EDT,但它没有解决问题 .

8 回答

  • 14

    这是问题的开始:

    Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));
    

    应全心全意地避免使用3个字母的缩写,以支持TZDB区域ID . EST是东部标准时间 - 标准时间从未观察到DST;它's not really a full time zone name. It'是用于部分时区的名称 . (不幸的是,我没有找到一个关于这个概念的好词 . )

    您需要一个完整的时区名称 . 例如, America/New_York 位于东部时区:

    TimeZone zone = TimeZone.getTimeZone("America/New_York");
    DateFormat format = DateFormat.getDateTimeInstance();
    format.setTimeZone(zone);
    
    System.out.println(format.format(new Date()));
    
  • 0

    其他答案是正确的,尤其是the one by Jon Skeet,但已过时 .

    java.time

    这些旧的日期时间类已被Java 8及更高版本中内置的java.time框架取代 .

    如果您只想以UTC格式显示当前时间,请使用 Instant 类 .

    Instant now = Instant.now();
    

    EST 不是时区,如correct Answer by Jon Skeet中所述 . 这样的3-4个字母代码既不是标准化也不是唯一的,并且进一步混淆了夏令时(DST) . 使用"continent/region"格式的正确时区名称 .

    也许你的意思是北美东海岸的东部标准时间?还是埃及标准时间?还是欧洲标准时间?

    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框架使用immutable objects而不是更改(变异)现有对象 .

    ZonedDateTime zdtGuam = zdt.withZoneSameInstant( ZoneId.of( "Pacific/Guam" ) ) ;
    
  • 2

    您可以输入“EST5EDT”,而不是输入“EST”作为时区 . 如你所知,只是“EDT”不起作用 . 这将解决夏令时问题 . 代码行如下所示:

    Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST5EDT"));
    
  • 0

    按照这个answer

    TimeZone tz = TimeZone.getTimeZone("EST");
    boolean inDs = tz.inDaylightTime(new Date());
    
  • -3
    public static float calculateTimeZone(String deviceTimeZone) {
        float ONE_HOUR_MILLIS = 60 * 60 * 1000;
    
        // Current timezone and date
        TimeZone timeZone = TimeZone.getTimeZone(deviceTimeZone);
        Date nowDate = new Date();
        float offsetFromUtc = timeZone.getOffset(nowDate.getTime()) / ONE_HOUR_MILLIS;
    
        // Daylight Saving time
        if (timeZone.useDaylightTime()) {
            // DST is used
            // I'm saving this is preferences for later use
    
            // save the offset value to use it later
            float dstOffset = timeZone.getDSTSavings() / ONE_HOUR_MILLIS;
            // DstOffsetValue = dstOffset
            // I'm saving this is preferences for later use
            // save that now we are in DST mode
            if (timeZone.inDaylightTime(nowDate)) {
                Log.e(Utility.class.getName(), "in Daylight Time");
                return -(ONE_HOUR_MILLIS * dstOffset);
            } else {
                Log.e(Utility.class.getName(), "not in Daylight Time");
                return 0;
            }
        } else
            return 0;
    }
    
  • 104
    private static Long DateTimeNowTicks(){
        long TICKS_AT_EPOCH = 621355968000000000L;
        TimeZone timeZone = Calendar.getInstance().getTimeZone();
        int offs = timeZone.getRawOffset();
        if (timeZone.inDaylightTime(new Date()))
            offs += 60 * 60 * 1000;
        return (System.currentTimeMillis() + offs) * 10000 + TICKS_AT_EPOCH;
    }
    
  • -2

    在java中,DateFormatter默认使用DST,为了避免日光节省(DST),你需要手动做一个技巧,
    首先你必须得到DST偏移,即应用多少毫秒的DST,对于某些地方,DST也是45分钟,而对于某些地方则是30分钟
    但在大多数情况下,DST为1小时
    您必须使用Timezone对象并检查日期是否属于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
      }
    
  • 0

    实现TimeZone类以将时区设置为日历可以节省夏令时 .

    java.util.TimeZone表示时区偏移量,并且还计算出夏令时 .

    示例代码:

    TimeZone est_timeZone = TimeZoneIDProvider.getTimeZoneID(TimeZoneID.US_EASTERN).getTimeZone();
    Calendar enteredCalendar = Calendar.getInstance();
    enteredCalendar.setTimeZone(est_timeZone);
    

相关问题