2013-07-15 101 views
0

我想以字符串格式比较两个日期,并以HH:MM:SS:SSS的结果作为字符串返回结果。 当我尝试使用15 Jul 2013 17:08:34.903的开始日期和结束日期 15 Jul 2013 17:08:51.247运行以下内容时,我期望看到00:00:16.344的结果。相反,我得到01:00:16.344的差异。任何想法,为什么会这样?SimpleDateFormat比较问题

private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("d MMM yyyy HH:mm:ss.SSS"); 
    private static final SimpleDateFormat DATE_FORMAT_HH_MM_SS = new SimpleDateFormat("HH:mm:ss.SSS"); 

    public String calculateDuration(String startDateStr, String endDateStr){ 

     String methodName = "calculateDuration"; 
     try {   
      Date startDate = DATE_FORMAT.parse(startDateStr); 
      Date endDate = DATE_FORMAT.parse(endDateStr);   
      long diff = endDate.getTime() - startDate.getTime();   
      return DATE_FORMAT_HH_MM_SS.format(diff); 
+0

这是Java吗?考虑给它语言标记 – doctorlove

+0

是你的TZ UTC + 1? –

+2

我认为你应该使用[* JodaTime *](http://joda-time.sourceforge.net/)来计算时间差(持续时间)。这将简化你的生活。 – LaurentG

回答

0

JDK Date API太糟糕了。我建议使用Joda Time库,但如果必须使用JDK日期API试试这个代码:

private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
     "d MMM yyyy HH:mm:ss.SSS"); 

public String calculateDuration(String startDateStr, String endDateStr) 
     throws ParseException { 

    String methodName = "calculateDuration"; 
    Date startDate = DATE_FORMAT.parse(startDateStr); 
    Date endDate = DATE_FORMAT.parse(endDateStr); 

    // in milliseconds 
    long diff = endDate.getTime() - startDate.getTime(); 

    long diffMiliseconds = diff % 1000; 
    long diffSeconds = diff/1000 % 60; 
    long diffMinutes = diff/(60 * 1000) % 60; 
    long diffHours = diff/(60 * 60 * 1000) % 24; 

    return String.format("%02d:%02d:%02d.%02d", diffHours, diffMinutes, 
      diffSeconds, diffMiliseconds); 
} 
0

您还没有初始化日历对象你的SimpleDateFormat格式化,所以它使用的是默认的一个做的映射。我猜测这个默认日历正在识别DST。这在您使用.parse()日期时间时不会显示,因为DST调整会在相减中取消。

当您将结果转换为HMS格式时,格式化程序会再次应用DST调整。由于在这一步中没有减法,它会出现在你的结果中。

在我看来,只要有人有日期算术问题,橡皮图章,膝盖反射回应就是“使用JodaTime”。我们都喜欢JodaTime;它是一个精心设计的API。但使用它仍然是一个外部依赖,除非你需要 - 它不应该使用它。在我看来,对于这种情况,您根本不需要JodaTime ...您只需要Java日历API就可以将日期时间解析为日期。这就是你需要的。

一旦你在毫秒的差异,你真的应该避免使用格式化器转换结果。使用简单的算术题会更高性能:

private static final SimpleDateFormat DATE_FORMAT = 
    new SimpleDateFormat("d MMM yyyy HH:mm:ss.SSS"); 

private static final int DAYS = 0; 
private static final int HOURS = 1; 
private static final int MINUTES = 2; 
private static final int SECONDS = 3; 
private static final int MILLIS = 4; 
private final int[] result = new int[MILLIS]; 

public String calculateDuration(String startDateStr, String endDateStr){ 

    try {   
     Date startDate = DATE_FORMAT.parse(startDateStr); 
     Date endDate = DATE_FORMAT.parse(endDateStr); 
    } catch (Exception e) { /* exception processing */ } 

    long diff = endDate.getTime() - startDate.getTime();   

    double d; 
    for (int i = DAYS; i <= MILLIS; i++) {  
     switch(i) { 
      case DAYS: 
       d = ((double) diff)/(86400.0 * 1000.0); 
       break; 
      case HOURS: 
       d = d * 24.0; break; 
      case MINUTES: case SECONDS: 
       d = d * 60.0; break; 
      case MILLIS: 
       d = d * 1000.0; break; 
     } 
     result[i] = (int) Math.floor(d); 
     d = d - (double) result[i]; 
    } 

在这最后for循环结束时,阵列result包含对应天数的整数,小时,分钟,秒和MILLIS从您的日期派生减法。为了得到这个结果,不需要创建,分配或调用对象。您现在可以轻松使用String.format()函数将这些整数转换为您选择的字符串格式。

+0

我要求在JodaTime的问题上有所不同。尽管我同意一个人不必总是使用它,但我仍然喜欢指出这些问题,因为它使日历数据的处理变得更容易,有些人还没有听说过。我很高兴当我第一次询问有关日历和日期的事情时,我向乔达指出了这一点。 –

+0

@JannisAlexakis:日期对象之间的减法通常不需要日历API。在这种情况下,使用Calendar API不仅会慢很多,而且会导致错误,因为生成的时间间隔会映射(有点错误)到日历日期。外部依赖关系就是它们。如果普遍认为在可能的情况下最好放弃它们,那么我认为我们可以同意在这种情况下可以放弃一个。 – scottb

0

由于在评论中你说你只是测量应用程序的运行时间,所以根本不涉及Date,SimpleDateFormat或Calendar。

long tic = System.nanoTime(); 

...就是你所需要的。当你手上有苍蝇拍时,不要使用大炮杀死蚊子。