Converter String em objeto de calendário em Java

174

Eu sou novo em Java, geralmente trabalho com PHP.

Estou tentando converter esta seqüência de caracteres:

Seg 14 de março 16:02:37 GMT 2011

Em um objeto de calendário para que eu possa facilmente puxar o ano e o mês assim:

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

Seria uma má ideia analisá-lo manualmente? Usando um método de substring?

Qualquer conselho ajudaria obrigado!

Doug Molineux
fonte

Respostas:

396
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: defina de Localeacordo com o seu ambiente / requisito


Veja também

Jigar Joshi
fonte
onlineconversion.com/unix_time.htm . Este é o conversor de carimbo de data / hora online. O valor que é calculado pelo código java e essa conversão online é diferente. Por quê?? Você pode passar por isso. Obrigado :)
Sachin J
6
Observe que isso perde as informações do fuso horário. O objeto Calendário terá o Fuso Horário padrão do sistema e não o analisado.
Cristian Vrabie
Esta não deve ser a resposta mais aceita / aceita. Como o Java 8 já está fora há mais de 4 anos, a resposta deve ser atualizada para mencionar java.time. Esta pergunta / pergunta aparece bastante proeminente no google.
Scolytus
18

tl; dr

A abordagem moderna usa as classes 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 classes de data e hora herdadas

A maneira moderna é com as classes java.time. As antigas classes de data e hora, como as Calendarque provaram ser mal projetadas, confusas e problemáticas.

Defina um formatador personalizado para corresponder à sua entrada de sequência.

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

Analisar como um ZonedDateTime.

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

Você está interessado no ano e no mês. As classes java.time incluem YearMonthclasse para esse fim.

YearMonth ym = YearMonth.from( zdt );

Você pode interrogar os números do ano e do mês, se necessário.

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

Mas o toStringmétodo gera uma sequência no formato ISO 8601 padrão.

String output = ym.toString();

Coloque tudo isso 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();

Despejar no console.

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

entrada: segunda-feira 14 de março 16:02:37 GMT 2011

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

ym: 2011-03

Código ao vivo

Veja este código em execução no IdeOne.com .

Conversão

Se você precisar de um Calendarobjeto, poderá converter para um GregorianCalendarusando novos métodos adicionados às classes antigas.

GregorianCalendar gc = GregorianCalendar.from( zdt );

Sobre java.time

A estrutura java.time é integrada ao Java 8 e posterior. Essas classes suplantar os velhos problemáticos legados aulas de data e hora, como java.util.Date, Calendar, e SimpleDateFormat.

O projeto Joda-Time , agora em modo de manutenção , aconselha a migração para java.time.

Para saber mais, consulte o Tutorial do Oracle . E procure Stack Overflow para muitos exemplos e explicações. A especificação é JSR 310 .

Onde obter as classes java.time?

  • Java SE 8 e SE 9 e posterior
    • Construídas em.
    • Parte da API Java padrão com uma implementação em pacote configurável.
    • O Java 9 adiciona alguns recursos e correções menores.
  • Java SE 6 e SE 7
    • Grande parte da funcionalidade java.time é portada para Java 6 e 7 no ThreeTen-Backport .
  • Android
    • O projeto ThreeTenABP adapta o ThreeTen-Backport (mencionado acima) para o Android especificamente.
    • Consulte Como usar… .

O projeto ThreeTen-Extra estende java.time com classes adicionais. Este projeto é um campo de prova para possíveis adições futuras ao java.time. Você pode encontrar algumas classes úteis aqui, como Interval, YearWeek, YearQuarter, e mais .

Basil Bourque
fonte
14

Bem, acho que seria uma má idéia replicar o código que já está presente em classes como SimpleDateFormat.

Por outro lado, pessoalmente, sugiro evitar Calendare, Datese possível, e usar o Joda Time como uma API de data e hora muito melhor projetada. Por exemplo, você precisa estar ciente de que nãoSimpleDateFormat é seguro para threads, portanto, você precisa de locais de threads, sincronização ou uma nova instância sempre que usá-lo. Os analisadores e formatadores Joda são seguros para threads.

Jon Skeet
fonte
Obrigado pela sua contribuição, certamente irei investigar o uso do Joda no futuro, parece que pode ser muito útil.
Doug Molineux
@ Jon Skeet Joda não deserializará no Android. Joda vale pouco, a menos que você não precise salvar datas e horas.
21817 Frank Zappa
@FrankZappa: Eu discordo disso - você pode fazer todos os seus cálculos de data / hora no Joda Time, mas depois converter para outros tipos (talvez apenas para simplificar) para fins de serialização.
21816 Jon Skeet
Desculpe, tive que reduzir o voto, a resposta é muito antiga, está desatualizada para ser a resposta de classificação mais alta. Hoje java.timeé o caminho a seguir, Basil Bourque deu uma excelente resposta.
Scolytus
2
@ Scolytus: A resposta superior (e aceita) tem 332 votos, em comparação com 10 neste. Eu acho que se você votar a cada resposta de 7 ou mais anos que tiver uma solução melhor agora, ficará sem votos ... (eu concordo que a resposta de Basil é boa, e eu votei nessa.)
Jon Skeet
10

Nenhum novo Calendário precisa ser criado, o SimpleDateFormat já usa um Calendário embaixo.

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

(Ainda não posso comentar, foi por isso que criei uma nova resposta)

GoGoris
fonte
1
Sua solução parece elegante, mas tem duas desvantagens: 1. O JavaDoc não garante que o comportamento seja o esperado. 2. Pelo menos para Java 6, você encontra um caminho na linha 1353 em que o objeto de calendário é clonado. Então, então! Date.equals (cal.getTime ()).
Niels
5

SimpleDateFormaté ótimo, observe que HHé diferente de hhquando se trabalha com horas. HHretornará 24 horas por dia e hh retornará 12 horas.

Por exemplo, o seguinte retornará 12 horas:

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

Enquanto isso retornará 24 horas:

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
Philip
fonte
4

Analisar uma hora com o fuso horário, Zno padrão, é para o fuso horário

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

Saída: retornará a hora UTC

1508899140000

insira a descrição da imagem aqui

Se não definirmos o fuso horário como padrão yyyy-MM-dd'T'HH:mm:ss. SimpleDateFormatusará o fuso horário definido emSetting

Phan Van Linh
fonte
3

Sim, seria uma prática ruim analisá-lo você mesmo. Dê uma olhada no SimpleDateFormat , ele transformará a String em uma data e você poderá definir a data em uma instância do calendário.

John Vint
fonte
1

Método simples:

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;
}
Alberto Cerqueira
fonte