Сравнивая две метки времени - PullRequest
1 голос
/ 07 января 2012

Я хочу сравнить следующие две метки времени.Он должен вернуть true, но из-за однозначных и двузначных миллисекунд в двух временных метках он возвращает false.Что я могу сделать, чтобы он вернулся true

public static void main(String[] args) throws ParseException {
    String d1 = "2011-12-31 07:11:01.5";
    String d2 = "2011-12-31 07:11:01.50";
    SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
    SimpleDateFormat s2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");

    Date dateOne = s1.parse(d1);
    Date dateTwo = s2.parse(d2);

    System.out.println(dateOne.equals(dateTwo));
}

Ответы [ 6 ]

2 голосов
/ 07 января 2012

Остальные уже ответили почему.Вот отправная точка, чтобы обойти это:

import java.text.*;
import java.util.Date;

public class DatePercentage {

    private final SimpleDateFormat dateFmt = new SimpleDateFormat(
                                "yyyy-MM-dd HH:mm:ss");
    private final DecimalFormat decFmt = new DecimalFormat();

    public Date parse(String text) throws ParseException {
        ParsePosition pos = new ParsePosition(0);
        Date d = dateFmt.parse(text, pos);

        if (d == null) {
            throw new ParseException("Could not parse " + text + ": " + pos,
                                     pos.getErrorIndex());
        } else if (pos.getIndex() < text.length()) {
            Number dec = decFmt.parse(text, pos); // % milliseceonds
            double pct = dec == null ? 0 : dec.doubleValue();

            if (0 < pct && pct < 1) {
                long moreMillis = Math.round(pct * 1000);
                d = new Date(d.getTime() + moreMillis);
            }
        }
        return d;
    }

    public static void main(String[] args) throws ParseException {
        String date = "2011-12-31 07:11:01";
        String [] millis = {"", ".5", ".50", ".500", ".5001", 
                            ".051", ".5009", "garbage"};

        DatePercentage dp = new DatePercentage();

        for (int i = 0; i < millis.length; i++) {
            String str = date + millis[i];
            System.out.format("%2s: %26s -> %tQ%n", i+1, str, dp.parse(str));
        }
    }
}

Вывод:

 1:        2011-12-31 07:11:01 -> 1325333461000
 2:      2011-12-31 07:11:01.5 -> 1325333461500
 3:     2011-12-31 07:11:01.50 -> 1325333461500
 4:    2011-12-31 07:11:01.500 -> 1325333461500
 5:   2011-12-31 07:11:01.5001 -> 1325333461500
 6:    2011-12-31 07:11:01.051 -> 1325333461051
 7:   2011-12-31 07:11:01.5009 -> 1325333461501
 8: 2011-12-31 07:11:01garbage -> 1325333461000
1 голос
/ 07 января 2012

Правильно, что equals возвращает false.Эти две строки различны - .5 (интерпретируется как .05) не может совпадать с .50.Также лучше использовать compareTo, если вы хотите сравнить Dates.

И я бы использовал только один SimpleDateFormat, например:

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");

Date dateOne = format.parse(d1);
Date dateTwo = format.parse(d2);

Так что мои предложения таковы:

  • Если вы действительно хотите, чтобы эти разные значения были одинаковыми, сравните их как строки с некоторым регулярным выражением ( Я бы не рекомендовал это решение ).
  • Если вы преобразуете их в Date, тогда они будут другими, потому что не одинаковы.
  • Или (как предлагают другие люди здесь) вы можете удалить.SS часть из шаблона, но тогда вы потеряете точность ..
1 голос
/ 07 января 2012

Проблема в том, что символ S анализирует числа как миллисекунды.Всегда.Таким образом, в первом случае «.5» анализируется как 5 миллисекунд, а «.50» анализируется как 50 миллисекунд.Ни одна из них не анализируется как полсекунды, что, я подозреваю, является тем, что вам нужно.

К сожалению, это является недостатком в SimpleDateFormat.Нет просто никакого способа проанализировать или отформатировать поля с точностью до секунды или центсекунды.

Когда мне в последний раз приходилось делать это (правда, только на время, а не на дату), я заканчивал анализ вручную - разбивая строкус регулярным выражением, а затем вручную преобразует поля в миллисекунды.Возможно, вы могли бы вырезать поле дробных секунд и проанализировать это вручную, а затем проанализировать оставшуюся строку с помощью SimpleDateFormat.

Альтернативой является заполнение строк завершающими нулями, чтобы дробные секунды всегда составляли три цифры, чтобудет проанализирован правильно.Уродливо, но, по крайней мере, просто.

0 голосов
/ 07 января 2012

См. Javadoc для SimpleDateFormat:

Число: Для форматирования количество букв шаблона является минимальным количеством цифр, а более короткие числа равны нулю.дополняется до этой суммы.При синтаксическом анализе количество букв шаблона игнорируется, если только это не необходимо для разделения двух смежных полей.

Так что ваши .S и .SS в вашей конструкции SimpleDateFormat используются только для форматирования, а недля разбора.Проверка equals возвращает значение false, поскольку значение getTime для обоих разное, как документ в методе equals класса Date.Для d1 он видит 5 миллисекунд, а для d2 50 миллисекунд.

Следовательно, при SimpleDateFormat эти два экземпляра никогда не будут равны.Вы можете игнорировать миллисекунды или, если возможно, настроить входные строки.

0 голосов
/ 07 января 2012

Кажется, что SimpleDateFormat интерпретирует последнюю часть как целое число, а не как десятичную часть.Очевидное решение состоит в том, чтобы убедиться, что в конце всегда есть три цифры, а справа нет 0, если нет.

Затем используйте шаблон yyyy-MM-dd HH:mm:ss.SSS для его анализа.

0 голосов
/ 07 января 2012

Просто попробуйте это (если вы не хотите считать миллисекунды):

SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");     
        Date dateOne = s1.parse(d1);     
        Date dateTwo = s1.parse(d2);      
System.out.println(dateOne.equals(dateTwo));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...