Pregunta Conversión de cadenas de Java a la fecha


¿Cuál es la mejor manera de convertir un String en el formato '2 de enero de 2010' a Date en Java?

En última instancia, quiero dividir el mes, el día y el año como números enteros para poder usar

Date date = new Date();
date.setMonth()..
date.setYear()..
date.setDay()..
date.setlong currentTime = date.getTime();

para convertir la fecha en tiempo


735
2017-11-18 15:53


origen


Respuestas:


Esa es la manera difícil, y esos java.util.Date los métodos setter han quedado en desuso desde Java 1.1 (1997). Simplemente formatee la fecha usando SimpleDateFormat utilizando un patrón de formato que coincida con la cadena de entrada.

En su caso específico de "2 de enero de 2010" como cadena de entrada:

  1. "Enero" es el mes del texto completo, así que use el MMMM patrón para ello
  2. "2" es el día corto del mes, así que use el d patrón para ello.
  3. "2010" es el año de 4 dígitos, así que use el yyyy patrón para ello.

String string = "January 2, 2010";
DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
Date date = format.parse(string);
System.out.println(date); // Sat Jan 02 00:00:00 GMT 2010

Tenga en cuenta la importancia de lo explícito Locale argumento. Si lo omites, usará el locale predeterminada que no es necesariamente inglés como se usa en el nombre del mes de la cadena de entrada. Si la configuración regional no coincide con la cadena de entrada, entonces confundiría una java.text.ParseException aunque cuando el patrón de formato parece válido.

Aquí hay un extracto de relevancia de el javadoc, listando todos los patrones de formato disponibles:

Letter  Date or Time Component  Presentation        Examples
------  ----------------------  ------------------  -------------------------------------
G       Era designator          Text                AD
y       Year                    Year                1996; 96
Y       Week year               Year                2009; 09
M/L     Month in year           Month               July; Jul; 07
w       Week in year            Number              27
W       Week in month           Number              2
D       Day in year             Number              189
d       Day in month            Number              10
F       Day of week in month    Number              2
E       Day in week             Text                Tuesday; Tue
u       Day number of week      Number              1
a       Am/pm marker            Text                PM
H       Hour in day (0-23)      Number              0
k       Hour in day (1-24)      Number              24
K       Hour in am/pm (0-11)    Number              0
h       Hour in am/pm (1-12)    Number              12
m       Minute in hour          Number              30
s       Second in minute        Number              55
S       Millisecond             Number              978
z       Time zone               General time zone   Pacific Standard Time; PST; GMT-08:00
Z       Time zone               RFC 822 time zone   -0800
X       Time zone               ISO 8601 time zone  -08; -0800; -08:00

Tenga en cuenta que los patrones distinguen entre mayúsculas y minúsculas y que los patrones basados ​​en texto de cuatro caracteres o más representan la forma completa; de lo contrario, se usa una forma abreviada o abreviada, si está disponible. Por ejemplo, MMMMM o más es innecesario.

Aquí hay algunos ejemplos de validez SimpleDateFormat patrones para analizar una cadena dada hasta la fecha:

Input string                            Pattern
------------------------------------    ----------------------------
2001.07.04 AD at 12:08:56 PDT           yyyy.MM.dd G 'at' HH:mm:ss z
Wed, Jul 4, '01                         EEE, MMM d, ''yy
12:08 PM                                h:mm a
12 o'clock PM, Pacific Daylight Time    hh 'o''clock' a, zzzz
0:08 PM, PDT                            K:mm a, z
02001.July.04 AD 12:08 PM               yyyyy.MMMM.dd GGG hh:mm aaa
Wed, 4 Jul 2001 12:08:56 -0700          EEE, d MMM yyyy HH:mm:ss Z
010704120856-0700                       yyMMddHHmmssZ
2001-07-04T12:08:56.235-0700            yyyy-MM-dd'T'HH:mm:ss.SSSZ
2001-07-04T12:08:56.235-07:00           yyyy-MM-dd'T'HH:mm:ss.SSSXXX
2001-W27-3                              YYYY-'W'ww-u

Una nota importante es que SimpleDateFormat es no a salvo de amenazas. En otras palabras, nunca debe declarar y asignarlo como una variable estática o de instancia y luego reutilizarlo desde diferentes métodos / hilos. Siempre debe crearlo nuevo dentro del alcance local del método.


Actualización de Java 8

Si está utilizando Java 8 o una versión posterior, utilice DateTimeFormatter (también aquí, haga clic en el enlace para ver todos los formateadores predefinidos y los patrones de formato disponibles; el tutorial está disponible aquí) Esta nueva API está inspirada en JodaTime.

String string = "January 2, 2010";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse(string, formatter);
System.out.println(date); // 2010-01-02

Nota: si su patrón de formato contiene la parte de tiempo también, entonces use LocalDateTime#parse(text, formatter) en lugar de LocalDate#parse(text, formatter). Y, si su patrón de formato también contiene el huso horario, utilice ZonedDateTime#parse(text, formatter) en lugar.

Aquí hay un extracto de relevancia de el javadoc, listando todos los patrones de formato disponibles:

Symbol  Meaning                     Presentation  Examples
------  --------------------------  ------------  ----------------------------------------------
G       era                         text          AD; Anno Domini; A
u       year                        year          2004; 04
y       year-of-era                 year          2004; 04
D       day-of-year                 number        189
M/L     month-of-year               number/text   7; 07; Jul; July; J
d       day-of-month                number        10

Q/q     quarter-of-year             number/text   3; 03; Q3; 3rd quarter
Y       week-based-year             year          1996; 96
w       week-of-week-based-year     number        27
W       week-of-month               number        4
E       day-of-week                 text          Tue; Tuesday; T
e/c     localized day-of-week       number/text   2; 02; Tue; Tuesday; T
F       week-of-month               number        3

a       am-pm-of-day                text          PM
h       clock-hour-of-am-pm (1-12)  number        12
K       hour-of-am-pm (0-11)        number        0
k       clock-hour-of-am-pm (1-24)  number        0

H       hour-of-day (0-23)          number        0
m       minute-of-hour              number        30
s       second-of-minute            number        55
S       fraction-of-second          fraction      978
A       milli-of-day                number        1234
n       nano-of-second              number        987654321
N       nano-of-day                 number        1234000000

V       time-zone ID                zone-id       America/Los_Angeles; Z; -08:30
z       time-zone name              zone-name     Pacific Standard Time; PST
O       localized zone-offset       offset-O      GMT+8; GMT+08:00; UTC-08:00;
X       zone-offset 'Z' for zero    offset-X      Z; -08; -0830; -08:30; -083015; -08:30:15;
x       zone-offset                 offset-x      +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z       zone-offset                 offset-Z      +0000; -0800; -08:00;

Tenga en cuenta que tiene varios Formateadores predefinidos para los patrones más populares. Entonces, en lugar de, por ejemplo, DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH);, podrías usar DateTimeFormatter.RFC_1123_DATE_TIME. Esto es posible porque son, al contrario que SimpleDateFormat, a salvo de amenazas. Por lo tanto, también podría definir el suyo, si es necesario.

Para un formato de cadena de entrada particular, no necesita usar un formato explícito de cadena de entrada. DateTimeFormatter: un estandar ISO 8601 fecha, como 2016-09-26T17: 44: 57Z, se puede analizar directamente con LocalDateTime#parse(text) como ya usa el ISO_LOCAL_DATE_TIME formateador. Similar, LocalDate#parse(text) analiza una fecha ISO sin el componente de tiempo (ver ISO_LOCAL_DATE), y ZonedDateTime#parse(text) analiza una fecha ISO con un desplazamiento y una zona horaria añadidos (ver ISO_ZONED_DATE_TIME)


1411
2017-11-18 15:55



Ah sí, la discusión de Java Date, de nuevo. Para lidiar con la manipulación de fechas que usamos Fecha, Calendario, Calendario Gregorianoy SimpleDateFormat. Por ejemplo, usando su fecha de enero como entrada:

Calendar mydate = new GregorianCalendar();
String mystring = "January 2, 2010";
Date thedate = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH).parse(mystring);
mydate.setTime(thedate);
//breakdown
System.out.println("mydate -> "+mydate);
System.out.println("year   -> "+mydate.get(Calendar.YEAR));
System.out.println("month  -> "+mydate.get(Calendar.MONTH));
System.out.println("dom    -> "+mydate.get(Calendar.DAY_OF_MONTH));
System.out.println("dow    -> "+mydate.get(Calendar.DAY_OF_WEEK));
System.out.println("hour   -> "+mydate.get(Calendar.HOUR));
System.out.println("minute -> "+mydate.get(Calendar.MINUTE));
System.out.println("second -> "+mydate.get(Calendar.SECOND));
System.out.println("milli  -> "+mydate.get(Calendar.MILLISECOND));
System.out.println("ampm   -> "+mydate.get(Calendar.AM_PM));
System.out.println("hod    -> "+mydate.get(Calendar.HOUR_OF_DAY));

Entonces puedes manipular eso con algo como:

Calendar now = Calendar.getInstance();
mydate.set(Calendar.YEAR,2009);
mydate.set(Calendar.MONTH,Calendar.FEBRUARY);
mydate.set(Calendar.DAY_OF_MONTH,25);
mydate.set(Calendar.HOUR_OF_DAY,now.get(Calendar.HOUR_OF_DAY));
mydate.set(Calendar.MINUTE,now.get(Calendar.MINUTE));
mydate.set(Calendar.SECOND,now.get(Calendar.SECOND));
// or with one statement
//mydate.set(2009, Calendar.FEBRUARY, 25, now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
System.out.println("mydate -> "+mydate);
System.out.println("year   -> "+mydate.get(Calendar.YEAR));
System.out.println("month  -> "+mydate.get(Calendar.MONTH));
System.out.println("dom    -> "+mydate.get(Calendar.DAY_OF_MONTH));
System.out.println("dow    -> "+mydate.get(Calendar.DAY_OF_WEEK));
System.out.println("hour   -> "+mydate.get(Calendar.HOUR));
System.out.println("minute -> "+mydate.get(Calendar.MINUTE));
System.out.println("second -> "+mydate.get(Calendar.SECOND));
System.out.println("milli  -> "+mydate.get(Calendar.MILLISECOND));
System.out.println("ampm   -> "+mydate.get(Calendar.AM_PM));
System.out.println("hod    -> "+mydate.get(Calendar.HOUR_OF_DAY));

62
2017-11-19 03:27



String str_date = "11-June-07";
DateFormat formatter;
Date date;
formatter = new SimpleDateFormat("dd-MMM-yy");
date = formatter.parse(str_date);

36
2018-01-15 07:02



Con Java 8 obtenemos una nueva API de fecha / hora (JSR 310)

La siguiente forma se puede usar para analizar la fecha en Java 8 sin depender de Joda-Time:

String str = "January 2, 2010";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse(str, formatter);

// access date fields
int year = date.getYear(); // 2010
int day = date.getDayOfMonth(); // 2
Month month = date.getMonth(); // JANUARY
int monthAsInt = month.getValue(); // 1

LocalDate es la clase estándar de Java 8 para representar una fecha (sin tiempo). Si desea analizar valores que contienen información de fecha y hora, debe usar LocalDateTime. Para valores con uso de zonas horarias ZonedDateTime. Ambos proporcionan un parse() método similar a LocalDate:

LocalDateTime dateWithTime = LocalDateTime.parse(strWithDateAndTime, dateTimeFormatter);
ZonedDateTime zoned = ZonedDateTime.parse(strWithTimeZone, zoneFormatter);

La lista de caracteres de formato de DateTimeFormatter Javadoc:

All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. 
The following pattern letters are defined:

Symbol  Meaning                     Presentation      Examples
------  -------                     ------------      -------
 G       era                         text              AD; Anno Domini; A
 u       year                        year              2004; 04
 y       year-of-era                 year              2004; 04
 D       day-of-year                 number            189
 M/L     month-of-year               number/text       7; 07; Jul; July; J
 d       day-of-month                number            10

 Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
 Y       week-based-year             year              1996; 96
 w       week-of-week-based-year     number            27
 W       week-of-month               number            4
 E       day-of-week                 text              Tue; Tuesday; T
 e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
 F       week-of-month               number            3

 a       am-pm-of-day                text              PM
 h       clock-hour-of-am-pm (1-12)  number            12
 K       hour-of-am-pm (0-11)        number            0
 k       clock-hour-of-am-pm (1-24)  number            0

 H       hour-of-day (0-23)          number            0
 m       minute-of-hour              number            30
 s       second-of-minute            number            55
 S       fraction-of-second          fraction          978
 A       milli-of-day                number            1234
 n       nano-of-second              number            987654321
 N       nano-of-day                 number            1234000000

 V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
 z       time-zone name              zone-name         Pacific Standard Time; PST
 O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
 X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
 x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
 Z       zone-offset                 offset-Z          +0000; -0800; -08:00;

29
2018-03-04 18:56



Si bien algunas de las respuestas son técnicamente correctas, no son aconsejables.

  • Las clases java.util.Date y Calendar son notoriamente problemáticas. Debido a fallas en el diseño y la implementación, evítelos. Afortunadamente, tenemos nuestra opción de otras dos excelentes bibliotecas de fecha y hora:
    • Joda-Time
      Esta popular biblioteca gratuita de código abierto se puede usar en varias versiones de Java. Se pueden encontrar muchos ejemplos de su uso en StackOverflow. Leer algunos de estos le ayudará a ponerse al día rápidamente.
    • paquete java.time. *
      Este nuevo conjunto de clases está inspirado en Joda-Time y definido por JSR 310. Estas clases están integradas en Java 8. Se está llevando a cabo un proyecto para respaldar estas clases con Java 7, pero Oracle no respalda esa retroinformación.
  • Como Kristopher Johnson señaló correctamente en su comentario sobre la pregunta, las otras respuestas ignoran cuestiones vitales de:
    • Hora del día
      La fecha tiene una parte de fecha y una parte de hora del día)
    • Zona horaria
      El comienzo de un día depende de la zona horaria. Si no especifica una zona horaria, se aplica la zona horaria predeterminada de la JVM. Eso significa que el comportamiento de su código puede cambiar cuando se ejecuta en otras computadoras o con una configuración de zona horaria modificada. Probablemente no es lo que quieres.
    • Lugar
      El idioma de la configuración regional especifica cómo interpretar las palabras (nombre del mes y del día) encontradas durante el análisis. (Los respuesta por BalusC maneja esto correctamente). Además, la configuración regional afecta la salida de algunos formateadores al generar una representación de cadena de su fecha y hora.

Joda-Time

Algunas notas sobre Joda-Time siguen.

Zona horaria

En Joda-Time, un Fecha y hora objeto realmente sabe su propia zona horaria asignada. Esto contrasta la clase java.util.Date que parece tener un huso horario pero no.

Tenga en cuenta en el siguiente código de ejemplo cómo pasamos un objeto de zona horaria al formateador que analiza la cadena. Esa zona horaria se usa para interpretar que la fecha y hora ocurrió en esa zona horaria. Entonces, debe pensar y determinar la zona horaria representada por esa entrada de cadena.

Como no tiene una porción de tiempo en su cadena de entrada, Joda-Time asigna el primer momento del día de la zona horaria especificada como la hora del día. Usualmente esto significa 00:00:00 pero no siempre, debido a Horario de verano (DST) u otras anomalías. Por cierto, puede hacer lo mismo con cualquier instancia de DateTime llamando withTimeAtStartOfDay.

Patrón de formateador

Los caracteres utilizados en el patrón de un formateador son similares en Joda-Time a los de java.util.Date/Calendar pero no son exactamente iguales. Lea detenidamente el documento.

Inmutabilidad

Usualmente usamos las clases inmutables en Joda-Time. En lugar de modificar un objeto Date-Time existente, llamamos a los métodos que crean una nueva instancia nueva basada en el otro objeto con la mayoría de los aspectos copiados, excepto cuando se deseaban modificaciones. Un ejemplo es la llamada a withZone en la última línea a continuación. Inmutabilidad ayuda a hacer Joda-Time muy seguro para subprocesos, y también puede hacer que un trabajo sea más claro.

Conversión

Necesitará objetos java.util.Date para usar con otras clases / framework que no conozcan los objetos Joda-Time. Afortunadamente, es muy fácil avanzar y retroceder.

Yendo desde un objeto java.util.Date (aquí nombrado date) a Joda-Time DateTime ...

org.joda.time.DateTime dateTime = new DateTime( date, timeZone );

Yendo en la otra dirección desde Joda-Time a un objeto java.util.Date ...

java.util.Date date = dateTime.toDate();

Código de muestra

String input = "January 2, 2010";

java.util.Locale locale = java.util.Locale.US;
DateTimeZone timeZone = DateTimeZone.forID( "Pacific/Honolulu" ); // Arbitrarily chosen for example.
DateTimeFormatter formatter = DateTimeFormat.forPattern( "MMMM d, yyyy" ).withZone( timeZone ).withLocale( locale );
DateTime dateTime = formatter.parseDateTime( input );

System.out.println( "dateTime: " + dateTime );
System.out.println( "dateTime in UTC/GMT: " + dateTime.withZone( DateTimeZone.UTC ) );

Cuando se ejecuta ...

dateTime: 2010-01-02T00:00:00.000-10:00
dateTime in UTC/GMT: 2010-01-02T10:00:00.000Z

20
2018-02-13 08:22



Al tratar con la clase SimpleDateFormat, es importante recordar que Date no es seguro para subprocesos y que no puede compartir un solo objeto Date con varios subprocesos.

También hay una gran diferencia entre "m" y "M", donde se usa una minúscula para los minutos y mayúscula para el mes. Lo mismo con "d" y "D". Esto puede causar errores sutiles que a menudo pasan desapercibidos. Ver Javadoc o Guía para convertir cadena hasta la fecha en Java para más detalles.


16
2017-12-02 01:48



    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    Date date;
    try {
        date = dateFormat.parse("2013-12-4");
        System.out.println(date.toString()); // Wed Dec 04 00:00:00 CST 2013

        String output = dateFormat.format(date);
        System.out.println(output); // 2013-12-04
    } 
    catch (ParseException e) {
        e.printStackTrace();
    }

Funciona bien para mí.


13
2017-12-04 12:46



Además, SimpleDateFormat no está disponible con algunas de las tecnologías del lado del cliente, como GWT.

Es una buena idea ir a Calendar.getInstance (), y su requisito es comparar dos fechas; ir por una cita larga.


5
2017-12-10 16:16