2013-07-15 2 views
0

Я хотел бы сравнить две даты в строковом формате и вернуть результат в HH: MM: SS: SSS в качестве строки. Когда я пытаюсь запустить следующее с startDate от 15 Jul 2013 17:08:34.903 и endDate от 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

API-интерфейс JDK Date ужасен. Я рекомендую использовать 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 форматировщик с объектом Calendar, поэтому он использует по умолчанию один, чтобы сделать отображение. Я предполагаю, что этот календарь по умолчанию распознает DST. Это не проявляется, когда вы .parse() datetimes, потому что настройка DST отменяется при вычитании.

При преобразовании результата в формат HMS форматер снова применяет настройку DST. Поскольку на этом шаге нет вычитания, оно появляется в вашем результате.

Мне кажется, что всякий раз, когда у кого-то есть арифметический вопрос по дате, ответ рефлекса резинового штампа и коленного рефлекса «используется JodaTime». Мы все любим JodaTime; это хорошо продуманный API. Но использование его по-прежнему является внешней зависимостью, и если вы не используете ее, вы не должны ее использовать. На мой взгляд, для этой ситуации вам совсем не нужен JodaTime ... вам нужен только Java Calendar 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 содержит целые числа, которые соответствуют количеству дней, часы, минуты, секунды и Миллис происходит от вашей даты вычитание. Для получения этого результата не нужно создавать, выделять или вызывать объекты. Теперь вы можете легко использовать функцию String.format(), чтобы поместить эти целые числа в строковый формат по вашему выбору.

+0

Я прошу отличиться в вопросе JodaTime. Хотя я согласен с тем, что его всегда не нужно использовать, мне все равно нравится указывать на такие вопросы, потому что он облегчает работу с календарными данными, и некоторые люди еще не слышали об этом. Я рад, что меня указали на Джоду, когда я впервые спросил кое-что о Календарях и Датах. –

+0

@JannisAlexakis: вычитание объектов Date часто не требует API календаря. В этом случае использование API календаря не только значительно медленнее, но и приводит к ошибке, так как полученный интервал отображается (несколько ошибочно) на календарную дату. Внешние зависимости - это то, что они есть. Если в целом согласны с тем, что, когда это возможно, лучше отказаться от них, то я думаю, мы можем согласиться с тем, что в этом случае можно обойтись без него. – scottb

0

Поскольку в комментариях вы говорите, что вы просто измеряете время работы приложения, не включайте Date, SimpleDateFormat или Calendar вообще.

long tic = System.nanoTime(); 

... это все, что вам нужно. Не используйте пушку, чтобы убить москита, когда у вас есть мухобойка под рукой.

Смежные вопросы