Comparing two timestamps
Solution 1
The others already answered why. Here's a starting point to get around it:
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));
}
}
}
Output:
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
Solution 2
The problem is that the S symbol parses numbers as milliseconds. Always. So, in the first case, ".5" is being parsed as 5 milliseconds, and ".50" is being parsed as 50 milliseconds. Neither of them is being parsed as half a second, which i suspect is what you want.
Sadly, this is a shortcoming in SimpleDateFormat. There is simply no way to parse or format decisecond or centisecond fields with it.
When i last had to do this (admittedly only for a time, not a date), i ended up parsing manually - splitting the string up with a regular expression, then converting the fields into a millisecond total by hand. You could perhaps slice off the fractional seconds field and parse that manually, then parse the remaining string with SimpleDateFormat.
The alternative is to pad the strings with trailing zeroes, so that the fractional seconds is always three digits, which will then be parsed correctly. Ugly, but at least simple.
Solution 3
It's right that equals
returns false
. Those two strings are different - .5
(interpreted as .05
) cannot be the same as .50
. Also it is better to use compareTo
if you want to compare Dates
.
And I would use only one SimpleDateFormat
like this:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");
Date dateOne = format.parse(d1);
Date dateTwo = format.parse(d2);
So my suggestions are these:
- If you really want to have those different values the same, compare them as strings with some regular expression (I wouldn't recommend this solution).
- If you covert them to
Date
then they will be different because the aren't the same. - Or (like other people here suggest) you can remove the
.SS
part from the pattern but then you will lose the precision..
Amit
Updated on June 04, 2022Comments
-
Amit almost 2 years
I want to compare the following two timestamps. It should return
true
but due to single digit and double digit milliseconds in the two timestamps, it is returningfalse
. What can I do to make it returntrue
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)); }
-
user219882 about 12 yearsThis does not work. It gives the same results as it did with
.SS
. -
Robin about 12 yearsIt does not matter what you use for parsing
ss.S
orss.SSS
, it will only be used for formatting. See the part of the javadoc I quoted in my answer -
JB Nizet about 12 years@Tomas. You missed the part when I tell you to right-pad the string with zeros to make sure there are always three digits.
-
user219882 about 12 years@JBNizet It's not worth the effort. I wouldn't recommend this kind of one-purpose solution with extra code to make it work.