Stack Overflow em Português Asked by user2647038 on December 11, 2021
Como posso obter uma data em milissegundos?
Exemplo: 24, Sáb, Jan, 17:39:50 2015
Apenas para complementar, um ponto que não foi abordado nas outras respostas.
Conforme a resposta do @utluiz explica, o valor que você está pedindo (retornado por date.getTime()
) é a quantidade de milissegundos desde o Unix Epoch (que é 1970-01-01T00:00Z
- 1 de janeiro de 1970, meia-noite, em UTC). Este campo possui muitos nomes (Unix Time, Unix Timestamp, etc), mas vou chamar apenas de timestamp para encurtar.
Um detalhe sobre este número é que ele é o mesmo em todo o mundo.
Por exemplo, se eu rodar agora (neste exato momento em que escrevo), um programa que pega o valor de System.currentTimeMillis()
(um método que retorna o timestamp correspondente à data e hora atual), o resultado será 1529496070462
.
Este valor é o mesmo no mundo todo. Qualquer computador, em qualquer parte do planeta, que rodasse este programa neste mesmo instante, teria esse mesmo resultado.
A diferença é que este mesmo valor pode corresponder a uma data e hora diferente, dependendo do fuso horário em que você está. Abaixo está uma lista com os valores de data e hora, em cada lugar do mundo, que correspondem a este timestamp:
Repare que em São Paulo e Londres o dia é o mesmo, mas o horário não. E em Auckland, até mesmo o dia é diferente (lá já é dia 21).
Mas todas estas datas e horas correspondem ao mesmo instante (ao mesmo ponto na linha do tempo). Em outras palavras, o valor do timestamp é o mesmo.
Porque a data que você está usando (24, Sáb, Jan, 17:39:50 2015
) não tem nenhuma informação sobre o fuso horário, então ela pode resultar em um valor de timestamp (o "valor em milissegundos" que você quer) diferente, dependendo do fuso horário que você usa.
A resposta do @Maniero usa SimpleDateFormat
, e esta classe vai usar o timezone default da JVM (o fuso horário padrão que é usado pelo Java quando você não especifica nenhum). E dependendo do que estiver configurado, você pode obter um valor diferente.
Outro detalhe é que, na sua String
, o dia da semana e mês estão em português, então é importante usar um java.util.Locale
também. Se você não especificar o locale, o SimpleDateFormat
vai usar o default da JVM, e nem sempre pode ser o idioma que você precisa. Portanto, o código fica assim:
// usar locale pt_BR (português)
SimpleDateFormat sdf = new SimpleDateFormat("dd, EEE, MMM, HH:mm:ss yyyy", new Locale("pt", "BR"));
Date date = sdf.parse("24, Sáb, Jan, 17:39:50 2015");
System.out.println(date.getTime());
O resultado será 1422128390000
, que é um timestamp que corresponde a 24 de janeiro de 2015, às 17:39:50 em São Paulo. Isso porque o timezone default da JVM que estou usando é America/Sao_Paulo
(você pode ver qual é o seu usando TimeZone.getDefault()
).
Mas se eu mudar o timezone default, o valor do timestamp será diferente. Exemplo:
// mudando o timezone default
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Tokyo"));
SimpleDateFormat sdf = new SimpleDateFormat("dd, EEE, MMM, HH:mm:ss yyyy", new Locale("pt", "BR"));
Date date = sdf.parse("24, Sáb, Jan, 17:39:50 2015");
System.out.println(date.getTime());
Eu mudei o timezone default para Asia/Tokyo
, e agora o SimpleDateFormat
vai usar este timezone para fazer o parsing da data. O resultado será 1422088790000
, que corresponde a 24 de janeiro de 2015, às 17:39:50, em Tóquio.
Este mesmo timestamp, em São Paulo, corresponde a 24 de janeiro de 2015, às 06:39:50 (a diferença não é de 12 horas porque neste dia São Paulo estava em horário de verão).
Ou seja, dependendo do timezone configurado, o SimpleDateFormat
pode retornar um valor diferente. E confiar na configuração default nem sempre é uma boa ideia, já que qualquer ponto do seu sistema pode chamar TimeZone.setDefault
(até mesmo outras aplicações rodando na mesma JVM), e isto vai afetar todo o código rodando nesta JVM. Ou o time de infra pode atualizar o servidor e mudar o timezone (de propósito ou sem querer), e não te avisar sobre isso. Enfim, não é algo sobre o qual você tem muito controle.
Por isso, uma alternativa é setar um timezone no próprio SimpleDateFormat
, e assim você não depende do timezone default. Exemplo:
// mudando o timezone default
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Tokyo"));
SimpleDateFormat sdf = new SimpleDateFormat("dd, EEE, MMM, HH:mm:ss yyyy", new Locale("pt", "BR"));
// setar um timezone no SimpleDateFormat, para não depender do default
sdf.setTimeZone(TimeZone.getTimeZone("America/Sao_Paulo"));
Date date = sdf.parse("24, Sáb, Jan, 17:39:50 2015");
System.out.println(date.getTime());
Como eu setei o timezone America/Sao_Paulo
no SimpleDateFormat
, ele vai usar este timezone para fazer o parsing, ignorando o timezone default. Por isso o resultado é 1422128390000
(24 de janeiro de 2015, às 17:39:50 em São Paulo).
Se você sabe que aquela data e hora corresponde a um timezone específico, use-o no SimpleDateFormat
, ao invés de depender da configuração default da JVM (que pode mudar sem você perceber).
Se ao invés de um timezone específico, você quiser usar UTC, pode fazer TimeZone.getTimeZone("UTC")
.
A partir do Java 8 existe a API java.time
. Nesta API, a conversão é similar: você precisa saber qual o timezone a ser usado para converter a data e hora para o timestamp.
Primeiro obtemos um java.time.LocalDateTime
(uma classe que possui data e hora). Para isso, usamos um java.time.format.DateTimeFormatter
para fazer o parsing. Aqui, também precisamos usar um java.util.Locale
, pois o dia da semana e mês estão em português, e é melhor usar um locale específico do que depender da configuração default da JVM.
Outro detalhe é que algumas informações de localização mudaram no Java 8, então o mês com letra maiúscula não funcionou no meu teste (JDK 1.8.0_144). Por isso, eu também uso um java.time.format.DateTimeFormatterBuilder
, que possibilita criar um DateTimeFormatter
case insensitive:
DateTimeFormatter parser = new DateTimeFormatterBuilder()
// ignorar maiúsculas
.parseCaseInsensitive()
// pattern para data e hora
.appendPattern("dd, EEE, MMM, HH:mm:ss uuuu")
// usar locale pt_BR, pois o dia da semana e mês estão em português
.toFormatter(new Locale("pt", "BR"));
LocalDateTime dateTime = LocalDateTime.parse("24, Sáb, Jan, 17:39:50 2015", parser);
A classe LocalDateTime
possui apenas a data e hora, sem qualquer noção de fusos horários. Para convertê-la para um timezone, eu preciso usar um java.time.ZoneId
, e em seguida eu uso o resultado para obter o valor do timestamp:
long timestamp = dateTime
// converte para um timezone
.atZone(ZoneId.of("America/Sao_Paulo"))
// obtém o timestamp em milissegundos
.toInstant().toEpochMilli();
Como eu escolhi o timezone America/Sao_Paulo
, o valor do timestamp será 1422128390000
(pois corresponde a 24 de janeiro de 2015, às 17:39:50 em São Paulo).
Se você quiser outro timezone, basta mudar o nome passado para ZoneId.of
. Prefira sempre os nomes no padrão da IANA (no formato "Continente/Região", como America/Sao_Paulo
, Europe/London
, etc). Você pode usar o método ZoneId.getAvailableZoneIds()
, que retorna todos os nomes válidos.
Caso você escolha usar o timezone default da JVM, use ZoneId.systemDefault()
. Lembrando de todos os cuidados já citados acima, sobre o fato do timezone default poder ser mudado sem você perceber.
E para usar UTC, use a constante ZoneOffset.UTC
.
java.time
em versões anteriores ao Java 8Para JDK 6 e 7, existe o ThreeTen Backport, que é um backport do java.time
. Este backport contém as mesmas classes do Java 8 (com os mesmos nomes, métodos e funcionamento).
A diferença é que, em vez de estarem no pacote java.time
, estão no pacote org.threeten.bp
. Mas o modo de usar será o mesmo explicado acima.
Eu recomendo usar estas opções (java.time
para JDK >= 8 e ThreeTen Backport para JDK 6 e 7), pois é uma API muito superior à Date
, Calendar
e SimpleDateFormat
(que possuem muitos problemas e decisões de design questionáveis - motivos que levaram à criação de uma nova API de datas).
Em seu próprio site, o Joda-Time recomenda que se use o java.time
:
Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).
Tradução livre: "Note que o Joda-Time é considerado um projeto 'encerrado'. Não há melhorias planejadas. Se estiver usando Java SE 8, por favor migre para o
java.time
(JSR-310)."
De qualquer forma, é uma alternativa para quem ainda estiver preso ao JDK 5 e quer usar algo melhor que Date
e Calendar
(veja aqui uma discussão mais detalhada, aí você pode decidir melhor se vai usá-lo ou não). O funcionamento é parecido com o java.time
: fazer parsing, converter para um timezone e obter o timestamp.
Algumas classes tem o mesmo nome de classes do java.time
, mas elas ficam no pacote org.joda.time
, e além disso, elas não são exatamente iguais.
DateTimeFormatter parser = DateTimeFormat.forPattern("dd, EEE, MMM, HH:mm:ss yyyy")
// usar locale pt_BR, pois o dia da semana e mês estão em português
.withLocale(new Locale("pt", "BR"));
LocalDateTime dateTime = parser.parseLocalDateTime("24, Sáb, Jan, 17:39:50 2015");
long timestamp = dateTime
// converter para um timezone
.toDateTime(DateTimeZone.forID("America/Sao_Paulo"))
// obter o timestamp
.getMillis();
Answered by hkotsubo on December 11, 2021
A resposta do @Maniero responde diretamente ao que foi perguntado. No entanto, irei acrescentar mais alguns detalhes sobre a questão de milissegundos.
Date
A classe java.util.Date
representa internamente a data usando a quantidade de milissegundos passados desde 1 de Janeiro de 1970 UTC (conhecido como epoch) num atributo do tipo long
. Tanto que seu único construtor recomendado recebe justamente o tempo em ms.
Exemplo:
Date data = new Date(1422279151249l);
Mesmo quando usamos o construtor vazio, que cria uma data com a data e hora atuais, na verdade internamente a classe Date
simplesmente chama o método System.currentTimeMillis()
para recuperar os milissegundos atuais e repassa ao outro construtor:
public Date() {
this(System.currentTimeMillis());
}
Para recuperar o tempo interno em milissegundos, simplesmente use o método getTime()
:
data.getTime();
É possível modificar a data com o método setTime()
:
data.setTime(1422279151249l);
Mas isso não é recomendável, pois fere o princípio da imutabilidade do objeto e em alguns casos pode resultar em comportamentos inesperados.
String
para Date
Use a classe java.text.SimpleDateFormat
. Exemplo:
Date data = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2015-01-24 17:39:50");
Calendar
A classe java.util.Calendar é bem diferente de java.util.Date
. Ela armazena as informações sobre uma data num vetor interno com várias posições, incluindo o fuso horário.
Além disso, a classe Calendar
é abstrata, pois existem diferentes calendários que a implementam, sendo o mais comum o GregorianCalendar
.
Para criar uma instância de Calendar
no tempo atual e com as configurações padrão da sua JVM, basta chamar o método getInstance
da classe:
Calendar cal = Calendar.getInstance();
Para recuperar o tempo em milissegundos desde o epoch, basta usar o método getTimeInMillis()
:
cal.getTimeInMillis()
Para alterar o tempo usando milissegundos, use o método setter equivalente:
cal.setTimeInMillis(1422279151249l);
Diferente da classe Date
, a classe Calendar
permite facilmente recuperar partes da data. Por exemplo, para recuperar a hora de uma data:
int hora = cal.get(Calendar.HOUR);
Ou para recuperar os milissegundos de uma data:
int hora = cal.get(Calendar.MILLISECOND);
Mas note que o valor retornado não tem anda a ver com o retorno do método getTimeInMillis
. Enquanto este retorna o número de milissegundos desde o epoch, aquele contém o valor dos milissegundos da hora atual, isto é, um número entre 0
e 999
.
Para "converter" um Date
em Calendar
, use os métodos getTime()
e setTime()
:
Calendar cal = Calendar.getInstance();
Date data = cal.getTime();
cal.setTime(data);
String
para Calendar
Conforme a própria documentação já avisa, a classe Calendar
não possui implementações para converter texto em data ou formatar data em texto.
Portanto, a solução é usar SimpleDateFormat
para gerar um Date
e depois passar a informação para o Calendar
:
Date data = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2015-01-24 17:39:50");
Calendar cal = Calendar.getInstance();
cal.setTime(data);
LocalDateTime
(Java 8)A partir do Java 8 você deve representar data e hora usando java.time.LocalDateTime
. Essa classe é imutável, portanto thread-safe, além de muito mais confiável do que as anteriores. Também possui maior precisão, na casa dos nanossegundos.
Para obter a data e hora atuais, use o método factory now()
:
LocalDateTime dateTime = LocalDateTime.now();
Para obter os milissegundos desde o epoch, você pode usar o método toEpochSecond()
e multiplicar o resultado por 1000
:
long ms = 1000 * dateTime.toEpochSecond(ZoneOffset.UTC);
Por outro lado, para recuperar a quantidade de milissegundos passados desde o último segundo, use o método get()
:
long ms = dateTime.get(ChronoField.MILLI_OF_SECOND);
Note que é bem parecido com a classe Calendar
nesse aspecto.
String
para LocalDateTime
Use a nova classe DateTimeFormatter
:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
Depois é possível tanto fazer o parse:
LocalDateTime data = LocalDateTime.from(formatter.parse("2015-01-24 17:39:50"));
Como formatar a data:
String dataFormatada = data.format(formatter);
Answered by utluiz on December 11, 2021
Depende de como você quer usar tem várias maneiras, uma delas pode ser:
import java.util.*;
import java.lang.*;
import java.io.*;
import java.text.*;
class Ideone {
public static void main (String[] args) throws java.lang.Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date date = sdf.parse("2015-01-24 17:39:50.000");
System.out.println(date.getTime());
}
}
Veja funcionando no ideone. E no repl.it. Também coloquei no GitHub para referência futura.
Answered by Maniero on December 11, 2021
Quer somente o milissegundo? Use o java.sql.Timestamp:
import java.sql.Timestamp;
public class DateTest {
/**
* @param args
*/
public static void main(String[] args) {
System.out.println(new Timestamp(System.currentTimeMillis()));
}
}
Se você quiser TUDO, pode utilizar o Joda e você pode fazer isso em três linhas:
(http://joda-time.sourceforge.net/)
DateTime jodaTime = new DateTime();
DateTimeFormatter formatter = DateTimeFormat.forPattern("YYYY-MM-dd HH:mm:ss.SSS");
System.out.println("jodaTime = " + formatter.print(jodaTime));
Você também tem acesso direto aos campos individuais da data sem o uso de um calendário.
System.out.println("year = " + jodaTime.getYear());
System.out.println("month = " + jodaTime.getMonthOfYear());
System.out.println("day = " + jodaTime.getDayOfMonth());
System.out.println("hour = " + jodaTime.getHourOfDay());
System.out.println("minute = " + jodaTime.getMinuteOfHour());
System.out.println("second = " + jodaTime.getSecondOfMinute());
System.out.println("millis = " + jodaTime.getMillisOfSecond());
Saída :)
jodaTime = 2010-04-16 18:09:26.060
year = 2010
month = 4
day = 16
hour = 18
minute = 9
second = 26
millis = 60 **O QUE VOCÊ PEDIU NO COMENTÁRIO**
Ou use o java.util.Calendar.
Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
int month = now.get(Calendar.MONTH); // Note: zero based!
int day = now.get(Calendar.DAY_OF_MONTH);
int hour = now.get(Calendar.HOUR_OF_DAY);
int minute = now.get(Calendar.MINUTE);
int second = now.get(Calendar.SECOND);
int millis = now.get(Calendar.MILLISECOND);
System.out.printf("%d-%02d-%02d %02d:%02d:%02d.%03d", year, month + 1, day, hour, minute, second, millis);
Answered by Lollipop on December 11, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP