parse - Carácter de patrón "T" ilegal al analizar una cadena de fecha a java.util.Date
simpledateformat timezone (2)
tl; dr
Instant.parse( "2010-10-02T12:23:23Z" )
ISO 8601
Ese formato está definido por el ISO8601 para formatos de cadena de fecha y hora.
Ambos:
- framework java.time integrado en Java 8 y posterior ( Tutorial )
- Biblioteca Joda-Time
... use los formatos ISO 8601 por defecto para analizar y generar cadenas.
En general, debe evitar el uso de las antiguas clases java.util.Date /.Calendar y java.text.SimpleDateFormat, ya que son notoriamente problemáticas, confusas y defectuosas. Si es necesario para la interoperación, puede convertir de aquí para allá.
java.time
Incorporado en Java 8 y posterior es el nuevo marco java.time . Inspirado por Joda-Time , definido por JSR 310 , y extendido por el proyecto ThreeTen-Extra .
Instant instant = Instant.parse( "2010-10-02T12:23:23Z" ); // `Instant` is always in UTC.
Convierte a la clase anterior.
java.util.Date date = java.util.Date.from( instant ); // Pass an `Instant` to the `from` method.
Zona horaria
Si es necesario, puede asignar un huso horario.
ZoneId zoneId = ZoneId.of( "America/Montreal" ); // Define a time zone rather than rely implicitly on JVM’s current default time zone.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId ); // Assign a time zone adjustment from UTC.
Convertir.
java.util.Date date = java.util.Date.from( zdt.toInstant() ); // Extract an `Instant` from the `ZonedDateTime` to pass to the `from` method.
Joda-Time
ACTUALIZACIÓN: El proyecto Joda-Time ahora está en modo de mantenimiento. El equipo aconseja la migración a las clases java.time .
Aquí hay un código de ejemplo en Joda-Time 2.8.
org.joda.time.DateTime dateTime_Utc = new DateTime( "2010-10-02T12:23:23Z" , DateTimeZone.UTC ); // Specifying a time zone to apply, rather than implicitly assigning the JVM’s current default.
Convierte a la clase anterior. Tenga en cuenta que la zona horaria asignada se pierde en la conversión, ya que a juDate no se le puede asignar una zona horaria.
java.util.Date date = dateTime_Utc.toDate(); // The `toDate` method converts to old class.
Zona horaria
Si es necesario, puede asignar un huso horario.
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTime_Montreal = dateTime_Utc.withZone ( zone );
Acerca de java.time
El marco java.time está integrado en Java 8 y posterior. Estas clases suplantan a las problemáticas antiguas clases legacy fecha y hora como java.util.Date
, Calendar
y SimpleDateFormat
.
El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .
Para obtener más información, consulte el Tutorial . Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .
Puede intercambiar objetos java.time directamente con su base de datos. Use un controlador JDBC que cumpla con JDBC 4.2 o posterior. Sin necesidad de cadenas, sin necesidad de clases java.sql.*
.
¿Dónde obtener las clases de java.time?
- Java SE 8 , Java SE 9 y posterior
- Incorporado.
- Parte de la API Java estándar con una implementación integrada.
- Java 9 agrega algunas características y correcciones menores.
- Java SE 6 y Java SE 7
- Gran parte de la funcionalidad de java.time se transfiere a Java 6 y 7 en ThreeTen-Backport .
- Android
- Versiones posteriores de las implementaciones del paquete de Android de las clases java.time.
- Para Android anterior (<26), el proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente). Consulte Cómo utilizar 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. Puede encontrar algunas clases útiles aquí, como Interval
, YearWeek
, YearQuarter
y more .
Tengo una cadena de fecha y quiero analizarla en una fecha normal, use la API de fecha de Java, el siguiente es mi código:
public static void main(String[] args) {
String date="2010-10-02T12:23:23Z";
String pattern="yyyy-MM-ddThh:mm:ssZ";
SimpleDateFormat sdf=new SimpleDateFormat(pattern);
try {
Date d=sdf.parse(date);
System.out.println(d.getYear());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Sin embargo, obtuve una excepción: java.lang.IllegalArgumentException: Illegal pattern character ''T''
Entonces, me pregunto si tengo que dividir la cadena y analizarla manualmente.
Por cierto, he intentado agregar un solo carácter de comillas a cada lado de la T:
String pattern="yyyy-MM-dd''T''hh:mm:ssZ";
Tampoco funciona.
Actualización para Java 8 y superior
Ahora puede simplemente hacer Instance.parse("2015-04-28T14:23:38.521Z")
y obtener lo correcto ahora, especialmente debido a que debe utilizar Instance
lugar del java.util.Date
roto con las versiones más recientes. de Java.
Debería utilizar DateTimeFormatter
lugar de SimpleDateFormatter
también.
La siguiente explicación sigue siendo válida como lo que representa el formato.
Esto funciona con la entrada con la Z
final como se demuestra:
En el patrón, la
T
se escapa con''
en cualquier lado.El patrón para la
Z
al final es en realidadXXX
tal como se documenta enSimpleDateFormat
paraSimpleDateFormat
, simplemente no es muy claro sobre cómo usarlo, ya queZ
es el marcador de la antigua informaciónTimeZone
.
Q2597083.java
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
public class Q2597083
{
/**
* All Dates are normalized to UTC, it is up the client code to convert to the appropriate TimeZone.
*/
public static final TimeZone UTC;
/**
* @see <a href="http://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations">Combined Date and Time Representations</a>
*/
public static final String ISO_8601_24H_FULL_FORMAT = "yyyy-MM-dd''T''HH:mm:ss.SSSXXX";
/**
* 0001-01-01T00:00:00.000Z
*/
public static final Date BEGINNING_OF_TIME;
/**
* 292278994-08-17T07:12:55.807Z
*/
public static final Date END_OF_TIME;
static
{
UTC = TimeZone.getTimeZone("UTC");
TimeZone.setDefault(UTC);
final Calendar c = new GregorianCalendar(UTC);
c.set(1, 0, 1, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0);
BEGINNING_OF_TIME = c.getTime();
c.setTime(new Date(Long.MAX_VALUE));
END_OF_TIME = c.getTime();
}
public static void main(String[] args) throws Exception
{
final SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_24H_FULL_FORMAT);
sdf.setTimeZone(UTC);
System.out.println("sdf.format(BEGINNING_OF_TIME) = " + sdf.format(BEGINNING_OF_TIME));
System.out.println("sdf.format(END_OF_TIME) = " + sdf.format(END_OF_TIME));
System.out.println("sdf.format(new Date()) = " + sdf.format(new Date()));
System.out.println("sdf.parse(/"2015-04-28T14:23:38.521Z/") = " + sdf.parse("2015-04-28T14:23:38.521Z"));
System.out.println("sdf.parse(/"0001-01-01T00:00:00.000Z/") = " + sdf.parse("0001-01-01T00:00:00.000Z"));
System.out.println("sdf.parse(/"292278994-08-17T07:12:55.807Z/") = " + sdf.parse("292278994-08-17T07:12:55.807Z"));
}
}
Produce el siguiente resultado:
sdf.format(BEGINNING_OF_TIME) = 0001-01-01T00:00:00.000Z
sdf.format(END_OF_TIME) = 292278994-08-17T07:12:55.807Z
sdf.format(new Date()) = 2015-04-28T14:38:25.956Z
sdf.parse("2015-04-28T14:23:38.521Z") = Tue Apr 28 14:23:38 UTC 2015
sdf.parse("0001-01-01T00:00:00.000Z") = Sat Jan 01 00:00:00 UTC 1
sdf.parse("292278994-08-17T07:12:55.807Z") = Sun Aug 17 07:12:55 UTC 292278994