TransWikia.com

Como posso obter uma data (dia, mês, ano, hora, minuto e segundo) convertidos em milissegundos em Java?

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

4 Answers

Apenas para complementar, um ponto que não foi abordado nas outras respostas.

Timestamp

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:

  • São Paulo: 20 de junho de 2018, às 09:01:10.462
  • Londres: 20 de junho de 2018, às 13:01:10.462
  • Auckland (Nova Zelândia): 21 de junho de 2018, às 00:01:10.462

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.

Por que estou falando tudo isso?

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").

Java 8

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.

Usar java.time em versões anteriores ao Java 8

Para 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).

Joda-Time

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.

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

Convertendo 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.

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

Fonte: https://stackoverflow.com/questions/2654025/how-to-get-year-month-day-hours-minutes-seconds-and-milliseconds-of-the-cur

Answered by Lollipop on December 11, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP