Convertir cadena a objeto de calendario en Java


175

Soy nuevo en Java, generalmente trabajo con PHP.

Estoy tratando de convertir esta cadena:

Lun mar 14 16:02:37 GMT 2011

En un objeto de calendario para poder extraer fácilmente el año y el mes de esta manera:

String yearAndMonth = cal.get(Calendar.YEAR)+cal.get(Calendar.MONTH);

¿Sería una mala idea analizarlo manualmente? ¿Usando un método de subcadena?

Cualquier consejo ayudaría, gracias!


Respuestas:


397
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
cal.setTime(sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));// all done

nota: establecer de Localeacuerdo a su entorno / requisito


Ver también


onlineconversion.com/unix_time.htm . Este es el convertidor de marca de tiempo en línea. El valor que se calcula mediante el código de Java y esta conversión en línea se vuelve diferente. ¿¿Por qué?? ¿Pueden pasar por esto? Gracias :)
Sachin J

66
Tenga en cuenta que esto pierde la información de la zona horaria. El objeto Calendario tendrá la zona horaria predeterminada del sistema, no la analizada.
Cristian Vrabie

Esta ya no debería ser la respuesta superior / aceptada. Dado que Java 8 ya está fuera por más de 4 años, la respuesta debe actualizarse para mencionarla java.time. Este Q / A aparece bastante destacado en Google.
Scolytus

18

tl; dr

El enfoque moderno utiliza las clases java.time .

YearMonth.from(
    ZonedDateTime.parse( 
        "Mon Mar 14 16:02:37 GMT 2011" , 
        DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" )
     )
).toString()

2011-03

Evite las clases de fecha y hora heredadas

La forma moderna es con las clases java.time. Las antiguas clases de fecha y hora, como Calendarhan demostrado ser mal diseñadas, confusas y problemáticas.

Defina un formateador personalizado para que coincida con su entrada de cadena.

String input = "Mon Mar 14 16:02:37 GMT 2011";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" );

Parse como a ZonedDateTime.

ZonedDateTime zdt = ZonedDateTime.parse( input , f );

Te interesa el año y el mes. Las clases java.time incluyen YearMonthclase para ese propósito.

YearMonth ym = YearMonth.from( zdt );

Puede consultar los números de año y mes si es necesario.

int year = ym.getYear();
int month = ym.getMonthValue();

Pero el toStringmétodo genera una cadena en formato estándar ISO 8601 .

String output = ym.toString();

Pon todo esto junto.

String input = "Mon Mar 14 16:02:37 GMT 2011";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "E MMM d HH:mm:ss z uuuu" );
ZonedDateTime zdt = ZonedDateTime.parse( input , f );
YearMonth ym = YearMonth.from( zdt );
int year = ym.getYear();
int month = ym.getMonthValue();

Volcado a la consola.

System.out.println( "input: " + input );
System.out.println( "zdt: " + zdt );
System.out.println( "ym: " + ym );

entrada: lun mar 14 16:02:37 GMT 2011

zdt: 2011-03-14T16: 02: 37Z [GMT]

ym: 2011-03

Código en vivo

Vea este código ejecutándose en IdeOne.com .

Conversión

Si debe tener un Calendarobjeto, puede convertirlo a GregorianCalendarusando nuevos métodos agregados a las clases anteriores.

GregorianCalendar gc = GregorianCalendar.from( zdt );

Sobre java.time

El marco java.time está integrado en Java 8 y versiones posteriores. Estas clases suplantar la vieja problemáticos heredados clases de fecha y hora como java.util.Date, Calendar, ySimpleDateFormat .

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 Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310 .

¿Dónde obtener las clases java.time?

  • Java SE 8 y SE 9 y posterior
    • Incorporado.
    • Parte de la API Java estándar con una implementación integrada.
    • Java 9 agrega algunas características menores y correcciones.
  • Java SE 6 y SE 7
    • Gran parte de la funcionalidad java.time se transfiere a Java 6 y 7 en ThreeTen-Backport .
  • Androide

El proyecto ThreeTen-Extra extiende java.time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time. Usted puede encontrar algunas clases útiles aquí, como Interval, YearWeek, YearQuarter, y más .


14

Bueno, creo que sería una mala idea replicar el código que ya está presente en clases como SimpleDateFormat .

Por otro lado, personalmente sugeriría evitar Calendary por Datecompleto si puedes, y usar Joda Time en su lugar, como una API de fecha y hora mucho mejor diseñada. Por ejemplo, debe tener en cuenta que noSimpleDateFormat es seguro para subprocesos, por lo que necesita locales de subprocesos, sincronización o una nueva instancia cada vez que lo usa. Los analizadores y formateadores Joda son seguros para subprocesos.


Gracias por su aporte, ciertamente consideraré usar Joda en el futuro, parece que puede ser muy útil
Doug Molineux

@Jon Skeet Joda no se deserializará en Android. Joda vale poco a menos que no tenga necesidad de guardar fechas y horas.
Frank Zappa

@FrankZappa: No estoy de acuerdo con eso: puede hacer todos sus cálculos de fecha / hora en Joda Time, pero luego convertir a otros tipos (tal vez solo cadenas para simplificar) con fines de serialización.
Jon Skeet

Lo sentimos, tuve que votar negativamente, la respuesta es demasiado antigua, está desactualizada para ser la respuesta de más alto rango. Hoy java.timees el camino a seguir, Basil Bourque proporcionó una excelente respuesta.
Scolytus

2
@Scolytus: La respuesta principal (y aceptada) tiene 332 votos en comparación con 10 en este caso. Creo que si va a votar a favor cada respuesta de más de 7 años que tiene una mejor solución ahora, se quedará sin votos negativos ... (Estoy de acuerdo en que la respuesta de Basilio es buena, y he votado a favor)
Jon Skeet

10

No es necesario crear un nuevo calendario, SimpleDateFormat ya usa un calendario debajo.

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.EN_US);
Date date = sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));// all done
Calendar cal = sdf.getCalendar();

(No puedo comentar todavía, por eso creé una nueva respuesta)


1
Su solución se ve elegante, pero tiene dos desventajas: 1. JavaDoc no garantiza que el comportamiento sea el esperado. 2. Al menos para Java 6, encontrará una ruta en la línea 1353 donde se clona el objeto calendario. Entonces, entonces! Date.equals (cal.getTime ()).
Niels

5

SimpleDateFormates genial, solo ten en cuenta que HHes diferente de hhcuando trabajas con horas. HHdevolverá las horas basadas en 24 horas y hh devolverá las horas basadas en 12 horas.

Por ejemplo, lo siguiente devolverá 12 horas:

SimpleDateFormat sdf = new SimpleDateFormat("hh:mm aa");

Si bien esto devolverá el tiempo de 24 horas:

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");

4

Analiza una hora con zona horaria, Zen el patrón es para zona horaria

String aTime = "2017-10-25T11:39:00+09:00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());
try {
    Calendar cal = Calendar.getInstance();
    cal.setTime(sdf.parse(aTime));
    Log.i(TAG, "time = " + cal.getTimeInMillis()); 
} catch (ParseException e) {
    e.printStackTrace();
}

Salida: devolverá la hora UTC

1508899140000

ingrese la descripción de la imagen aquí

Si no establecemos la zona horaria en patrón como yyyy-MM-dd'T'HH:mm:ss. SimpleDateFormatutilizará la zona horaria que se ha establecido enSetting


3

Sí, sería una mala práctica analizarlo usted mismo. Eche un vistazo a SimpleDateFormat , convertirá la Cadena en una Fecha y puede establecer la Fecha en una instancia de Calendario.


1

Método simple:

public Calendar stringToCalendar(String date, String pattern) throws ParseException {
    String DEFAULT_LOCALE_NAME = "pt";
    String DEFAULT_COUNTRY = "BR";
    Locale DEFAULT_LOCALE = new Locale(DEFAULT_LOCALE_NAME, DEFAULT_COUNTRY);
    SimpleDateFormat format = new SimpleDateFormat(pattern, LocaleUtils.DEFAULT_LOCALE);
    Date d = format.parse(date);
    Calendar c = getCalendar();
    c.setTime(d);
    return c;
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.