2016-09-13 109 views
1

我想比较当前日期(2016-08-31)与给定日期(2016-08-31)。 我的当前移动设备时区是GMT-08:00太平洋时间。比较日期使用GregorianCalendar

如果我在设备上禁用自动日期&时区并将时区设置为GMT + 08:00 Perth,则method1将返回true,但method2返回false;

由于我比较了没有时区的日期,因此预计方法2的结果,因此“2016-08-31”之前的“2​​016-08-31”为false;为什么method1返回true?

public boolean method1() { 
     try { 
      GregorianCalendar currentCalendar = new GregorianCalendar(); 
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 
      Date endDate = sdf.parse("2016-08-31"); 
      Calendar endCalendar = new GregorianCalendar(); 
      endCalendar.setTime(endDate); 

      if (endCalendar.before(currentCalendar)) { 
       return true; 
      } else { 
       return false; 
      } 
     } catch (ParseException e) { 
      ... 
     } 
    } 


    public boolean method2() {  
     try { 
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 
      Date currentDate = sdf.parse(formatter.format(new Date())); 
      Date endDate = sdf.parse("2016-08-31"); 

      if (endDate.before(currentDate)) { 
       return true; 
      } else { 
       return false; 
      } 

     } catch (ParseException e) { 
      ... 
     } 
    } 

回答

1

带和不带时区

可能的解释:你的代码混合使用划和UTC日期时间对象。在某些行中,您有一个对象指定了一个时区(java.util.Calendar),即JVM当前的默认时区。在其他行中,您有一个在UTC中修复的对象(java.util.Date)。 Australia/Perth时区比UTC早8小时,所以当然你可以看到日期的差异。打印出他们的毫秒数,因为时代号会使比较结果更加明显。

自己做一个青睐:避免这些臭名昭着的麻烦老班。改用java.time代替。

Boolean isFuture = 
    LocalDate.parse("2016-08-31") 
      .isAfter(LocalDate.now(ZoneId.of("Australia/Perth"))) ; 

使用java.time

您使用麻烦的旧传统的日期时间类,现在由java.time类取代。

获取当前日期需要一个时区。对于任何特定的时刻,日期因地区而异。如果省略,则隐式应用JVM的当前默认时区。更好地指定,因为该默认值可以随时更改。

指定proper time zone name。切勿使用3-4字母缩写,如ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of("Australia/Perth") ; 

LocalDate类表示没有时间一天和不同时区的日期,唯一的价值。

LocalDate today = LocalDate.now(z); 

您的输入字符串恰好符合标准ISO 8601格式。所以直接用LocalDate解析。无需指定格式化模式。

LocalDate ld = LocalDate.parse("2016-08-31"); 

比较isBeforeisAfterisEqualcompareTo

Boolean isFuture = ld.isAfter(today); 

关于java.time

java.time框架是建立在Java 8和更高版本。这些课程取代了麻烦的旧日期时间课程,如java.util.Date,.Calendar,& java.text.SimpleDateFormat

Joda-Time项目现在位于maintenance mode,建议迁移到java.time。请参阅Oracle Tutorial。并搜索堆栈溢出了很多例子和解释。

大部分的java.time功能后移植到Java 6 和ThreeTenABP还适于Android(见How to use…)。

ThreeTen-Extra项目扩展java.time与其他类。这个项目是未来可能增加java.time的一个试验场。你可以在这里找到一些有用的类,如Interval,YearWeek,YearQuarter,等等。

+0

谢谢@Basil Bourque,它非常详细。 – Huigege