Stack Overflow em Português Asked by DudisRoyer on December 11, 2021
new Date()
em JavaScript me retorna esse formato:
Tue Apr 01 2014 13:43:13 GMT-0300 (BRT)
Eu preciso converter isso para um java.util.Date
. Para isso estou tentando utilizar SimpleDateFormat
mas não achei um pattern que desse certo, sempre me retorna:
java.text.ParseException: Unparseable date: "Tue Apr 01 2014 13:43:13 GMT-0300"
Complementando, existem alguns detalhes que não foram cobertos nas outras respostas.
Por exemplo, o dia da semana e mês estão em inglês ("Tue Apr"), e por padrão SimpleDateFormat
usa o idioma correspondente ao locale default da JVM, então não é garantido que os códigos sugeridos na outra resposta funcionem sempre. Por exemplo, na minha JVM o locale default é pt_BR
(Português do Brasil), então o código sugerido dá erro, pois ele tenta fazer o parsing dos nomes em português.
Para que ele sempre considere os nomes em inglês, independente da configuração da JVM, basta informar o Locale
correto no construtor de SimpleDateFormat
:
String text = "Tue Apr 01 2014 13:43:13 GMT-0300 (BRT)";
String format = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z (zzz)";
// usando Locale.US (Inglês Americano)
SimpleDateFormat dateFormat = new SimpleDateFormat(format, Locale.US);
System.out.println(dateFormat.parse(text));
Usei Locale.US
(Inglês Americano), assim ele considera os nomes em inglês, independente do locale que estiver configurado na JVM.
Outro ponto que discordo da outra resposta é sobre "você já tem a identificação do TimeZone
correto, que no caso é o BRT". Na verdade essas abreviações como "BRT" não são padronizadas, e muitas são ambíguas: há várias delas que representam mais de um timezone - veja esta lista, temos o exemplo de "CST" que é usada nos Estados Unidos, Cuba e China, ou ainda "IST", que é usada na Irlanda, Índia e Israel. Ou seja, nem sempre (na verdade quase nunca) será possível determinar o timezone a partir da abreviação.
Mesmo no caso de "BRT", há mais de um timezone que usa esta sigla, como America/Sao_Paulo
e America/Recife
(a diferença entre eles é que em muitos anos, um adotava o horário de verão, e o outro não). Tudo bem que durante o horário de verão a sigla muda para "BRST", mas como já disse, as abreviações são ambíguas e não-padronizadas, e de qualquer forma, existem muitos outros timezones no Brasil, como America/Belem
, America/Rio_Branco
, entre outros, que apesar de usarem a mesma sigla, possuem diferentes históricos com relação a quando cada um adotava horário de verão ou não. Ou seja, ter a abreviação não garante "a identificação do timezone correto" (ou você aceita o default que SimpleDateFormat
usa, ou escolhe um arbitrariamente, como veremos a seguir).
E para entender melhor o que é um timezone e de onde vem esses nomes como America/Sao_Paulo
e America/Recife
, leia aqui.
java.time
A partir do Java 8 (lançado em 2014), é possível usar a API java.time
. A diferença que esta API é mais flexível, e nela é possível configurar qual timezone você quer usar para a abreviação (no caso de SimpleDateFormat
, ele usará um valor default e não é possível mudá-lo). Esta flexibilidade tem um preço, que é ter que dizer explicitamente o que queremos:
String text = "Tue Apr 01 2014 13:43:13 GMT-0300 (BRT)";
// timezones usados para "desambiguar" as abreviações
Set<ZoneId> preferredZones = new HashSet<ZoneId>();
preferredZones.add(ZoneId.of("America/Sao_Paulo"));
DateTimeFormatter parser = new DateTimeFormatterBuilder()
// data, hora e offset
.appendPattern("EEE MMM dd uuuu HH:mm:ss 'GMT'Z (")
// usar timezone arbitrário para abreviação
.appendZoneText(TextStyle.SHORT, preferredZones)
// usar locale inglês para mês e dia da semana
.appendLiteral(')').toFormatter(Locale.US);
// faz o parsing da String
ZonedDateTime data = ZonedDateTime.parse(text, parser);
// se precisar de um java.util.Date
Date date = Date.from(data.toInstant());
Uma das características desta API é que existem várias classes diferentes para representar datas e horas, e você pode escolher a mais adequada para cada situação. Como neste caso eu tenho a data, hora e timezone, a melhor opção é um ZonedDateTime
.
E se precisar especificamente de um java.util.Date
, o exemplo acima mostra como fazer a conversão.
Apesar de parecer mais trabalhoso, esta API corrige muitos dos problemas e falhas de design de Date
e Calendar
, então na minha opinião é um trabalho que no fim vale a pena.
Answered by hkotsubo on December 11, 2021
Estabeleça um padrão de data em String que o Javascript deva passar. Depois disso, deixe por conta do Java. Um jeito um pouco mais alternativo (só um pouco) de se fazer isso seria usando o método setTimeZone()
do DateFormat
da seguinte maneira:
DateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm");
df.setTimeZone(TimeZone.getTimeZone("GMT"));
String strData = "30/05/2014 21:45";
try {
Date data = df.parse(strData);
System.out.println(data);
}
catch (ParseException e) {
e.printStackTrace();
}
A saída seria:
Fri May 30 18:45:00 BRT 2014
Mas você pode se perguntar, quais os TimeZones disponíveis para a utilização no método setTimeZone()
. Você pode listar todos os TimeZones da seguinte forma:
for (String tz : TimeZone.getAvailableIDs()) {
System.out.println(tz);
}
Não vou postar aqui a saída, porque é um pouco extensa. Mas tenho certeza que o timezone que você procura estará na lista.
EDIT: Complementando a resposta a respeito do Javascript. Você pode formatar o object Date, através de vários métodos como getMonth()
, getDate()
, getMinutes()
... Dessa forma você formata a data como quiser para enviar ao Java. Veja a referência completa do objeto Date no Javascript.
Answered by humungs on December 11, 2021
Como você já tem a identificação do TimeZone
correto, que no caso é o BRT você poderia ignorar a parte que tem o GMT-0300, porque colocar o GMT no formato pode ser problemático, a não ser que ele seja fixo. Então proponho 2 soluções.
1) Removendo o GMT-0300
public static void main(String[] args) throws ParseException {
String text = stripGMT("Tue Apr 01 2014 13:43:13 GMT-0300 (BRT)");
String format = "EEE MMM dd yyyy HH:mm:ss (zzz)";
DateFormat dateFormat = new SimpleDateFormat(format);
System.out.println(dateFormat.parse(text));
}
private static String stripGMT(String text) {
return text.replaceAll("GMT-\d{4}", "");
}
2) Mantendo o GMT como um argumento fixo
public static void main(String[] args) throws ParseException {
String text = "Tue Apr 01 2014 13:43:13 GMT-0300 (BRT)";
String format = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z (zzz)";
DateFormat dateFormat = new SimpleDateFormat(format);
System.out.println(dateFormat.parse(text));
}
Answered by Rodrigo Sasaki on December 11, 2021
Como no SO em inglês
A melhor formar de converter é usando o time em milisegundos, UTC. O object Javascript Date e
java.util.Date suportam conversão utilizando milisegundos.
Answered by Leonardo Otto on December 11, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP