问题
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 returning false
. What can I do to make it return 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));
}
回答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
回答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.
回答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..
回答4:
Just try this (assuming you don't want to consider milliseconds):
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));
回答5:
It seems that SimpleDateFormat interprets the last part as an integer, and not as decimal part. The obvious solution is to make sure there are always three digits at the end, and right pad with 0 if not.
Then use the pattern yyyy-MM-dd HH:mm:ss.SSS
to parse it.
回答6:
See the javadoc of the SimpleDateFormat:
Number: For formatting, the number of pattern letters is the minimum number of digits, and shorter numbers are zero-padded to this amount. For parsing, the number of pattern letters is ignored unless it's needed to separate two adjacent fields.
So your .S
and .SS
in your SimpleDateFormat
construction are only used for formatting, not for parsing. The equals
check returns false since the getTime
value is different for both, as document in the equals method of the Date
class. For d1
it sees 5 milliseconds and for d2
50 milliseconds.
Hence, with SimpleDateFormat
those two instances will never be equal. You could opt to ignore the milliseconds or if possible to adjust the input Strings.
来源:https://stackoverflow.com/questions/8769456/comparing-two-timestamps