I have Service
fetch date string from web and then I want to pare it to Date
object. But somehow application crashes.
This is my string that I\'m parsi
Remove "XXX" from
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
and everything would work fine.
Go through the list of symbols that can be used inside a SimpleDateFormat
constructor. Although the documentation shows the "XXX" format, this doesn't work on Android and will throw an IllegalArgumentException
.
Probably you are looking for "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
Change your code to
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
or
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); // if timezone is required
You are using the wrong date formatter.
Use this instead: DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
I think that android in contrast with Java 7 uses Z (as in Java 6) for timezones and not X. So, use this for your date formats.
Based on idea from Alexander K, I optimize it and support parsing from and to UTC timezone format like 1970-01-01T00:00:00Z
, to make all behaviour exactly same as yyyy-MM-dd'T'HH:mm:ssXXX
.
public class IsoSimpleDateFormatBeforeNougat extends SimpleDateFormat {
public IsoSimpleDateFormatBeforeNougat() {
super("yyyy-MM-dd'T'HH:mm:ssZ");
}
public IsoSimpleDateFormatBeforeNougat(Locale locale) {
super("yyyy-MM-dd'T'HH:mm:ssZ", locale);
}
public IsoSimpleDateFormatBeforeNougat(DateFormatSymbols formatSymbols) {
super("yyyy-MM-dd'T'HH:mm:ssZ", formatSymbols);
}
@Override
public Date parse(String text, ParsePosition pos) {
if (text.endsWith("Z")) {
return super.parse(text.substring(0, text.length() - 1) + "+0000", pos);
}
if (text.length() > 3 && text.substring(text.length() - 3, text.length() - 2).equals(":")) {
text = text.substring(0, text.length() - 3) + text.substring(text.length() - 2);
}
return super.parse(text, pos);
}
@Override
public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) {
StringBuffer rfcFormat = super.format(date, toAppendTo, pos);
if (rfcFormat.substring(rfcFormat.length() - 5).equals("+0000")) {
return rfcFormat.replace(rfcFormat.length() - 5, rfcFormat.length(), "Z");
}
return rfcFormat.insert(rfcFormat.length() - 2, ":");
}
}
Test code:
@Test
public void test() throws ParseException {
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
SimpleDateFormat sdf = new IsoSimpleDateFormatBeforeNougat();
sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
assertEquals("1970-01-01T08:00:00+08:00", sdf.format(new Date(0)));
assertEquals(0L, sdf.parse("1970-01-01T08:00:00+08:00").getTime());
sdf.setTimeZone(TimeZone.getTimeZone("GMT+0"));
assertEquals("1970-01-01T00:00:00Z", sdf.format(new Date(0)));
assertEquals(0L, sdf.parse("1970-01-01T00:00:00Z").getTime());
}
Use a SimpleDateFormat
to produce a properly formatted String
output:
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
String formattedNow = simpleDateFormat.format(new Date(System.currentTimeMillis()));
Output : 2018-02-27T07:36:47.686Z
The following class can be used to convert the string to date when pattern doesn't aware of it.
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* StringToDateFormater is a concrete class for formatting and parsing dates in a locale-sensitive manner. It allows for
* formatting (date → text), parsing (text → date), and normalization.
*
* This class is mainly used for convert the date from string. It should be used only when date pattern doesn't aware of
* it.
*
*/
public class StringToDateFormater extends SimpleDateFormat {
private static final List<String> DATE_SUPPORTED_FORMAT_LIST = Arrays.asList("yyyyMMddHHmmss", "yyyyMMddHHmm",
"yyyyMMddHHmm", "yyyyMMddHH", "yyyyMMdd", "yyyyMMddHHmmssSS");
/**
*
*/
private static final long serialVersionUID = -1732857502488169225L;
/**
* @param pattern
*/
public StringToDateFormater() {
}
@Override
public Date parse(String source) {
Date date = null;
SimpleDateFormat dateFormat = null;
for (String format : DATE_SUPPORTED_FORMAT_LIST) {
dateFormat = new SimpleDateFormat(format);
try {
return dateFormat.parse(source);
} catch (Exception exception) {
}
}
return date;
}
}
The error is saying that simpleDateFormat does not recognize the character X. If you are looking for milliseconds it is represented with the character S.
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");