Android parse String to Date – неизвестный символ шаблона 'X'

У меня есть строка даты извлечения Service из сети, а затем я хочу привязать ее к объекту Date . Но почему-то приложение падает. Это моя строка, которую я 2015-02-05T05:20:02+00:00

onStartCommand ()

 String datetime = "2015-02-05T05:20:02+00:00"; Date new_date = stringToDate(datetime); 

stringToDate ()

 private Date stringToDate(String s){ DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); try{ return df.parse(s); }catch(ParseException e){ e.printStackTrace(); } return null; } 

LogCat:

 02-06 20:37:02.008: E/AndroidRuntime(28565): FATAL EXCEPTION: main 02-06 20:37:02.008: E/AndroidRuntime(28565): Process: com.dotmav.runescapenotifier, PID: 28565 02-06 20:37:02.008: E/AndroidRuntime(28565): java.lang.RuntimeException: Unable to start service com.dotmav.runescapenotifier.GEService@384655b5 with Intent { cmp=com.dotmav.runescapenotifier/.GEService }: java.lang.IllegalArgumentException: Unknown pattern character 'X' 02-06 20:37:02.008: E/AndroidRuntime(28565): at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2881) 02-06 20:37:02.008: E/AndroidRuntime(28565): at android.app.ActivityThread.access$2100(ActivityThread.java:144) 02-06 20:37:02.008: E/AndroidRuntime(28565): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1376) 02-06 20:37:02.008: E/AndroidRuntime(28565): at android.os.Handler.dispatchMessage(Handler.java:102) 02-06 20:37:02.008: E/AndroidRuntime(28565): at android.os.Looper.loop(Looper.java:135) 02-06 20:37:02.008: E/AndroidRuntime(28565): at android.app.ActivityThread.main(ActivityThread.java:5221) 02-06 20:37:02.008: E/AndroidRuntime(28565): at java.lang.reflect.Method.invoke(Native Method) 02-06 20:37:02.008: E/AndroidRuntime(28565): at java.lang.reflect.Method.invoke(Method.java:372) 02-06 20:37:02.008: E/AndroidRuntime(28565): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 02-06 20:37:02.008: E/AndroidRuntime(28565): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 02-06 20:37:02.008: E/AndroidRuntime(28565): Caused by: java.lang.IllegalArgumentException: Unknown pattern character 'X' 02-06 20:37:02.008: E/AndroidRuntime(28565): at java.text.SimpleDateFormat.validatePatternCharacter(SimpleDateFormat.java:314) 02-06 20:37:02.008: E/AndroidRuntime(28565): at java.text.SimpleDateFormat.validatePattern(SimpleDateFormat.java:303) 02-06 20:37:02.008: E/AndroidRuntime(28565): at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:356) 02-06 20:37:02.008: E/AndroidRuntime(28565): at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:249) 02-06 20:37:02.008: E/AndroidRuntime(28565): at com.dotmav.runescapenotifier.GEService.stringToDate(GEService.java:68) 02-06 20:37:02.008: E/AndroidRuntime(28565): at com.dotmav.runescapenotifier.GEService.onStartCommand(GEService.java:44) 02-06 20:37:02.008: E/AndroidRuntime(28565): at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2864) 02-06 20:37:02.008: E/AndroidRuntime(28565): ... 9 more 

EDIT: onDestroy () установить будильник для периодического обновления …

 AlarmManager alarm = (AlarmManager)getSystemService(ALARM_SERVICE); alarm.set( AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60), PendingIntent.getService(this, 0, new Intent(this, GEService.class), 0) ); 

Удалить «XXX» из

 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); 

И все будет хорошо работать.

Перейдите к списку символов, которые можно использовать внутри конструктора SimpleDateFormat . Это документация

Возможно, вы ищете "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

Измените свой код на

 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); 

или

 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); // if timezone is required 

Версия Android SimpleDateFormat не поддерживает шаблон X , поэтому XXX не будет работать, но вместо этого вы можете использовать ZZZZZ который делает то же самое, и выводит часовой пояс в формате +02:00 (или -02:00 зависимости от локального часового пояса) ,

Вы используете неправильный формат даты.

Используйте это вместо: DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");

Я думаю, что андроид, в отличие от Java 7, использует Z (как в Java 6) для часовых поясов, а не X. Таким образом, используйте это для ваших форматов даты.

Поскольку Z и XXX отличаются друг от друга, я применил следующее обходное решение:

 // This is a workaround from Z to XXX timezone format new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") { @Override public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) { StringBuffer rfcFormat = super.format(date, toAppendTo, pos); return rfcFormat.insert(rfcFormat.length() - 2, ":"); } @Override public Date parse(String text, ParsePosition pos) { if (text.length() > 3) { text = text.substring(0, text.length() - 3) + text.substring(text.length() - 2); } return super.parse(text, pos); } } 

Android SimpleDateFormat отличается от Java 7 SDK и не поддерживает «X» для анализа ISO 8601. Вы можете использовать стили «Z» или «ZZZZZ» для форматирования и программного задания часового пояса в формате UTC. Вот класс утилиты:

 public class DateUtil { public static final String iso8601DatePattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"; public static final DateFormat iso8601DateFormat = new SimpleDateFormat(iso8601DatePattern); public static final TimeZone utcTimeZone = TimeZone.getTimeZone("UTC"); static { iso8601DateFormat.setTimeZone(utcTimeZone); } public static String formatAsIso8601(Date date) { return iso8601DateFormat.format(date); } } 

Ошибка говорит, что simpleDateFormat не распознает символ X. Если вы ищете миллисекунды, то он представлен символом S.

 DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); 

Следующий класс может использоваться для преобразования строки на дату, когда шаблон не знает об этом.

  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; } } 

ТЛ; др

 long millisecondsSinceEpoch = OffsetDateTime.parse( "2015-02-05T05:20:02+00:00" ).plusHour( 1 ).toInstant().toEpochMilli() // Warning: Possible loss of data in truncating nanoseconds to milliseconds. But not in this particular case. 

Детали

Другие ответы верны, но теперь устарели. Старые классы даты и времени теперь являются устаревшими. Вместо этого используйте классы java.time.

ISO 8601

Входная строка соответствует стандарту ISO 8601. Парсинг напрямую, нет необходимости определять шаблон форматирования, поскольку классы java.time по умолчанию используют ISO 8601.

OffsetDateTime

Вход включает в себя смещение-от-UTC с +00:00 поэтому мы можем анализировать как объект OffsetDateTime .

 String input = "2015-02-05T05:20:02+00:00" ; OffsetDateTime odt = OffsetDateTime.parse( input ); 

математический

Если вы хотите добавить час или минуту позже, чтобы установить будильник, вызовите методы plus .

 OffsetDateTime minuteLater = odt.plusMinutes( 1 ); OffsetDateTime hourLater = odt.plusHours( 1 ); 

Чтобы получить счет в миллисекундах, перейдите в класс Instant . Класс Instant представляет момент на временной шкале в UTC с разрешением наносекунд . Запрос миллисекунд означает возможную потерю данных, поскольку девять цифр десятичной дроби усекаются до трех цифр десятичной дроби.

 long millisecondsSinceEpoch = odt.toInstant().toEpochMilli(); // Warning: Possible loss of data in truncating nanoseconds to milliseconds. 

О java.time

Рамка java.time встроена в Java 8 и более поздних версий . Эти классы вытесняют старые неприятные классы времени, такие как java.util.Date , java.text.SimpleDateFormat и java.text.SimpleDateFormat .

Проект Joda-Time , теперь в режиме обслуживания , советует перейти на java.time.

Дополнительную информацию можно найти в учебнике Oracle . И поиск Stack Overflow для многих примеров и объяснений.

Большая часть функциональности java.time возвращается на Java 6 и 7 в ThreeTen-Backport и далее адаптирована для Android в ThreeTenABP .

Проект ThreeTen-Extra расширяет java.time с дополнительными классами. Этот проект является доказательством возможных будущих дополнений к java.time.

Intereting Posts
NullPointerException на findViewById () в android Отображение изображения в сводке ListPreference Ресурсы $ NotFoundException: ресурс не является Drawable (цвет или путь)? Firebase Auth получает дополнительную информацию о пользователе (возраст, пол) Круг, нарисованный на холсте, не соответствует экрану AvoidXferMode для замены цвета на холсте Какая лучшая IDE для разработки java android Почему у WebViews свой жизненный цикл? Зависимость org.apache.httpcomponents: httpclient: 4.4.1 игнорируется для выпуска, так как может противоречить внутренней версии, предоставляемой Android Isroid: exported = "true", необходимый для внутреннего использования поставщика контента Переход от одного действия к другому. Активность в Android. LibGdx GC_Concurrent running Twilio Client Android v1.2.8 сбой, когда клиентское устройство выполняет вызов, а метод onDisconnected ConnectionListener не вызывается автоматически Android RatingBar показывает более 5 звезд Получать и проверять сертификат с сервера HTTPS – андроид