studio simple example dateformat change java android date simpledateformat

java - example - simpledateformat to date



Android parse String to Date-carácter de patrón desconocido ''X'' (11)

Tengo la cadena de fecha de recuperación del servicio desde la web y luego quiero emparejarlo con el objeto Date . Pero de alguna manera falla la aplicación. Esta es la cadena que estoy analizando: 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 () configura la alarma para la actualización periódica ...

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


tl; dr

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.

Detalles

Otras respuestas son correctas pero ahora están desactualizadas. Las antiguas clases de fecha y hora ahora son heredadas. Use clases java.time en su lugar.

ISO 8601

La cadena de entrada está en formato estándar ISO 8601. Parse directamente, no es necesario definir un patrón de formateo ya que las clases java.time usan formatos ISO 8601 de forma predeterminada.

OffsetDateTime

La entrada incluye un offset-from-UTC con el +00:00 por lo que podemos analizar como un objeto OffsetDateTime .

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

Mates

Si desea agregar una hora o un minuto más tarde para configurar una alarma, llame a los métodos plus .

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

Para obtener una cuenta de milisegundos, vaya a la clase Instant . La clase Instant representa un momento en la línea de tiempo en UTC con una resolución de nanoseconds . Pedir milisegundos significa la pérdida de datos posible ya que los nueve dígitos de una fracción decimal se truncan a los tres dígitos de la fracción decimal.

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

Acerca de java.time

El marco java.time está integrado en Java 8 y posterior. Estas clases suplantan a las antiguas clases problemáticas de fecha y hora, como java.util.Date , .Calendar y java.text.SimpleDateFormat .

El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a java.time.

Para obtener más información, consulte el Tutorial de Oracle . Y busque para obtener muchos ejemplos y explicaciones.

Gran parte de la funcionalidad de java.time se transfiere a Java 6 y 7 en ThreeTen-Backport y se adapta aún más a Android en ThreeTenABP .

El proyecto ThreeTen-Extra amplía java.time con clases adicionales. Este proyecto es un terreno de prueba para posibles adiciones futuras a java.time.


Android developer.android.com/reference/java/text/SimpleDateFormat.html es diferente de Java 7 SDK y no admite ''X'' para analizar ISO 8601. Puede usar los estilos ''Z'' o ''ZZZZZ'' para formatear y establecer programáticamente la zona horaria en UTC. Aquí hay una clase util:

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


Como Z y XXX son diferentes, he implementado la siguiente solución alternativa:

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


El error es decir que simpleDateFormat no reconoce el carácter X. Si está buscando milisegundos, se representa con el carácter S.

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


Eliminar "XXX" de

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

y todo funcionaria bien

SimpleDateFormat la lista de símbolos que se pueden usar dentro de un constructor SimpleDateFormat . Esta es la developer.android.com/reference/java/text/SimpleDateFormat.html

Probablemente estás buscando "yyyy-MM-dd''T''HH:mm:ss.SSSZ"

Cambia tu código a

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

o

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


Está utilizando el formateador de fecha incorrecto.

Use esto en su lugar: DateFormat df = new SimpleDateFormat("yyyy-MM-dd''T''HH:mm:ssZ");

Creo que Android, en contraste con Java 7 usa Z (como en Java 6) para zonas horarias y no X. Por lo tanto, use developer.android.com/reference/java/text/SimpleDateFormat.html para sus formatos de fecha.


La siguiente clase se puede usar para convertir la cadena a la fecha cuando el patrón no la conoce.

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


La versión Android de SimpleDateFormat no admite el patrón X , por lo que XXX no funcionará, pero en su lugar puede usar ZZZZZ que hace lo mismo y genera la zona horaria en formato +02:00 (o -02:00 dependiendo de la zona horaria local) .


Nadie mencionó que este error ocurriera en los dispositivos de pre turrón, así que pensé en compartir mi respuesta y tal vez sea útil para aquellos que llegaron a este hilo debido a eso.

Esta answer correctamente menciona que "X" solo es compatible con los dispositivos Nougat +. Sigo viendo que la documentation sugiere usar "yyyy-MM-dd''T''HH:mm:ss.SSSXXX" y no estoy seguro de por qué no hacen explícito este punto.

Para mí, yyyy-MM-dd''T''HH:mm:ssXXX funcionaba bien hasta que intenté probarlo en el dispositivo 6.0 y comenzó a fallar, lo que me llevó a investigar sobre este tema. Sustituirlo por yyyy-MM-dd''T''HH:mm:ss.SSSZZZZZ ha resuelto el problema y funciona en todos los dispositivos 5.0+.


Solución simple:

Usa este yyyy-MM-dd''T''HH:mm:ss.SSSZZZZZ

En lugar de yyyy-MM-dd''T''HH:mm:ss.SSSXXX

Hecho.


Use un SimpleDateFormat para producir un resultado de String con String formato SimpleDateFormat :

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()));

Salida: 2018-02-27T07:36:47.686Z