Android parse String to Date - unknown pattern character 'X'

前端 未结 13 1006
耶瑟儿~
耶瑟儿~ 2021-01-31 07:32

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

相关标签:
13条回答
  • 2021-01-31 07:49

    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
    
    0 讨论(0)
  • 2021-01-31 07:49

    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.

    0 讨论(0)
  • 2021-01-31 07:50

    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());
    }
    
    0 讨论(0)
  • 2021-01-31 07:57

    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

    0 讨论(0)
  • 2021-01-31 08:04

    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;
        }
    }
    
    0 讨论(0)
  • 2021-01-31 08:05

    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");
    
    0 讨论(0)
提交回复
热议问题