0

我想以字符串格式比较两个日期,并将结果以 HH:MM:SS:SSS 作为字符串返回。15 Jul 2013 17:08:34.903当我尝试使用 startDate和 endDate 运行以下命令时,15 Jul 2013 17:08:51.247我希望看到00:00:16.344. 相反,我得到了01:00:16.344. 任何想法为什么会这样?

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);  
4

3 回答 3

0

Since in the comments you say that you're simply measuring running time for an application, don't involve Date, SimpleDateFormat, or Calendar at all.

long tic = System.nanoTime();

...is all you need. Don't use a cannon to kill a mosquito when you have a fly swatter on hand.

于 2013-07-15T17:38:51.417 回答
0

您尚未使用 Calendar 对象初始化 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包含对应于从日期减法得出的 DAYS、HOURS、MINUTES、SECONDS 和 MILLIS 数的整数。无需创建、分配或调用对象即可获得此结果。您现在可以轻松地使用该String.format()函数将这些整数放入您选择的字符串格式中。

于 2013-07-15T17:22:22.263 回答
0

JDK 日期 API 很糟糕。我建议使用Joda Time库,但如果您必须使用 JDK Date 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);
}
于 2013-07-15T17:05:55.963 回答