Java - Manipulando Objeto Date

Boa noite,

Estou com problemas com objeto Data, utilizo hoje biblioteca util.Date

Gostaria de que o objeto Date fosse mostrado no padrão PTBR dd/MM/yyyy, porem para fazer isso preciso transformar em String, ocorre que o meu Objeto só recebe valores do Tipo Date.

while (rs.next()) {

             ModelLogistica lg = new ModelLogistica();
             Date sf = rs.getDate("Data");
             
             DateFormat dfm = DateFormat.getDateTimeInstance();
             String DataAForm1 = dfm.format(sf);
             String dn = dfm.format(rs.getTimestamp("Data"));
             Timestamp dt = rs.getTimestamp("Data" );
             //Date dr = dfm.parse(dn);
             System.out.println("Teste \n." + dn);
             lg.setPLACA(rs.getString("Placa"));
             
             //Preciso formatar esse cara ABAIXO
           
             lg.setDATA_GPS(rs.getTimestamp("Data"));
             
             
             
             log.add(lg);

Um objecto Date não tem formato. Deves, como dizes, transformar para String para mostrar com o formato que pretendes. Agora isso só deve ser feito na camada de visualização. Até lá, deves manter o Objecto como Date.

SimpleDateFormat pattern = new SimpleDateFormat(“dd/MM/yyyy”);
String sData = pattern.format(sf);

Pois, Mudar o formato como String, eu consigo, estudei bastante os métodos, mas não posso mudar o formato do Objeto Date.

Teria como me dar uma luz de como faria isso na Camada de visualização? Pois eu uso uma classe cujo cria um ArayList e leva direto para camada de visualização.

Como já dito anteriormente - e vou repetir para que você realmente entenda - um Date NÃO tem formato.

É claro que se você imprime um Date (com System.out.println(date), por exemplo) a data é mostrada de alguma forma. Mas esse é somente o formato escolhido pelo método toString(), e isso não quer dizer que a data está naquele formato - não está, pois internamente ela só possui um valor numérico que corresponde ao timestamp.

Um Date, portanto, representa apenas um instante específico, um ponto na linha do tempo. Você pode, claro, representar a mesma data em diferentes formatos (“19/10/2020”, ou “2020-10-19”, ou “October, 19th 2020”, ou “Dezenove de outubro de dois mil e vinte”, etc) - todos esses formatos podem ser diferentes, mas todos eles representam a mesma data. Um Date guarda somente o valor referente ao ponto no tempo que ele representa, mas a data em si não está em nenhum formato específico (quando você formata a data, na verdade está gerando uma String que representa a data em um formato específico, mas o formato não é a data, é apenas uma representação da mesma).

Dito isso, se sua classe guardar instâncias de Date, então passe objetos Date para ela e pronto. Somente na hora de mostrar estas datas para o usuário você se preocupa com a formatação.

E sem mais contexto, é o máximo que dá para sugerir (o código que você postou acima está incompleto e sem contexto, não dá pra saber exatamente qual é o problema).

Complementando o que foi dito pelo @hugokotsubo

Você disse que está passando os objetos como Date para sua camada de exibição.

Sendo assim, você precisa definir o formato desse campo na sua camada de de exibição (aí falta saber exatamente onde e como você está exibindo isso para podermos te ajudar mais).

Seria bom se vc der mais detalhes, por exemplo, se é uma aplicação desktop ou web, que tecnologia vc está usando no front (caso seja web), etc.

Resumindo, Se eu quiser Na camada de apresentação em meu Jtable, exibir uma Data em um formato PT, BR para usuário, tenho de tratar esse campo como “String”, tratando como String terei o BUG da API Java, que não vai ordenar corretamente a coluna, vai ordenar somente o primeiro Caractere. Se eu quiser resolver o BUG de ordenação tenho que passar a data como “Objeto Date” cujo não pode ser formatado.

Utilizo para popular minha Jtable um ArrayList, cujo esta estrutura com Setters de minha classe, dentro da classe “Tabela” defini os tipos de dados, String, inteiros e Dates, a partir deles gero os Setters. Tenho uma classe que chama por meio de “Resultset” os dados do BD e armazena no ArrayList os dados, de qualquer forma, não importa como eu faça, qualquer Objeto ou método Date não aceita formatação pois os métodos de Formatação são todos Strings.

Que bug da API?
Você pode ordenar como bem entender, pra isso existe a interface Comparator.
E pode continuar apresentando o texto da data no formato que quiser.
:man_shrugging:

Amigo, eu não estudei o método Comparator, utilizo o AutoSorter… já a anos quanto utilizei os campos Date como String, eu tive oque foi me dito como um Bug, pois quando ordeno uma coluna com dados de uma Data na “Interface” da aplicação, a aplicação só consegue ordenar pelo primeiro Caractere, ficando assim “Desordenado” os dados.
Então vou dar esse tema como vencido, vou mudar minha estrutura para String e formatar usando os métodos existentes. E claro vou estudar o comparator.

Não sei como está o seu código, mas é perfeitamente possível ordenar por data e mostrar as datas formatadas. Como não temos o seu código, vou colocar uma classe de exemplo:

public class User {
    private String nome;
    private Date dataNascimento;

    public User(String nome, Date dataNascimento) {
        this.nome = nome;
        this.dataNascimento = dataNascimento;
    }

    public String getNome() {
        return nome;
    }

    public Date getDataNascimento() {
        return dataNascimento;
    }
}

Em seguida, criamos uma lista de usuários:

// método auxiliar para criar um Date específico
static Date criarDataNasc(int dia, int mes, int ano) {
    Calendar c = Calendar.getInstance();
    c.set(ano, mes - 1, dia, 0, 0, 0);
    c.set(Calendar.MILLISECOND, 0);
    return c.getTime();
}

...
List<User> users = new ArrayList<>();
users.add(new User("Fulano", criarDataNasc(10, 1, 1980)));
users.add(new User("Ciclano", criarDataNasc(20, 11, 1970)));
users.add(new User("Beltrano", criarDataNasc(15, 4, 2000)));
users.add(new User("Trajano", criarDataNasc(19, 7, 2010)));

Para ordenar os User's por data, basta usar um java.util.Comparator:

users.sort(new Comparator<User>() {
    @Override
    public int compare(User u1, User u2) {
        // comparar 2 Users pela data de nascimento
        return u1.getDataNascimento().compareTo(u2.getDataNascimento());
    }
});

// ou, a partir do Java 8, pode ser usada a sintaxe de lambda
users.sort((u1, u2) -> u1.getDataNascimento().compareTo(u2.getDataNascimento()));
// ou ainda method reference
users.sort(Comparator.comparing(User::getDataNascimento));

Agora a lista está ordenada pela data de nascimento dos usuários, então eu posso imprimi-los e escolher o formato em que quero as datas:

SimpleDateFormat formato = new SimpleDateFormat("dd/MM/yyyy");
for (User user : users) {
    System.out.println(user.getNome() + " nasceu em " + formato.format(user.getDataNascimento()));
}

Pronto! A saída é:

Ciclano nasceu em 20/11/1970
Fulano nasceu em 10/01/1980
Beltrano nasceu em 15/04/2000
Trajano nasceu em 19/07/2010

Veja como as coisas ficam separadas:

  • ao manipular os dados (ou seja, criar o User, colocar na lista, ordenar) eu sempre trabalho com o Date
  • ao exibir os dados, eu escolho o formato que quero e gero as strings correspondentes (com o método format)

De maneira similar, você faria o mesmo na sua aplicação: ao ler do banco, guardar na lista, etc, você só trabalha com Date. Somente na hora de exibir os dados é que você formata.

Não tem segredo, em qualquer código que for mexer com datas, a ideia é a mesma. Infelizmente faz muito tempo que não mexo com JTable e não sei se tem alguma configuração específica para isso, mas não acho que seja um “bug” ou algo assim. Provavelmente é algum detalhe no seu código mesmo…

Que é isso jovem, não desista tão fácil.

Poderia ter dito desde o início.

Utilize a coluna com objetos do tipo Date e sete um TableCellRenderer para renderizar objetos Date no formato que você quiser.

Exemplo abaixo:

Uma classe Funcionario:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Funcionario {

    private String nome;
    private double altura;
    private double peso;
    private String cargo;
    private Date admissao;

    public Funcionario(String nome, double altura, double peso, String cargo, String dataAdmissao) {
        try {
            this.nome = nome;
            this.altura = altura;
            this.peso = peso;
            this.cargo = cargo;
            this.admissao = new SimpleDateFormat("dd/MM/yyyy").parse(dataAdmissao);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    public Date getAdmissao() {
        return admissao;
    }

    public double getAltura() {
        return altura;
    }

    public String getCargo() {
        return cargo;
    }

    public String getNome() {
        return nome;
    }

    public double getPeso() {
        return peso;
    }

    public void setAdmissao(Date dataAdmissao) {
        this.admissao = dataAdmissao;
    }

    public void setAltura(double altura) {
        this.altura = altura;
    }

    public void setCargo(String cargo) {
        this.cargo = cargo;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public void setPeso(double peso) {
        this.peso = peso;
    }
}

Um TableModel pra renderizar uma List<Funcionario>:

import java.util.List;

import javax.swing.table.AbstractTableModel;

@SuppressWarnings("serial")
class FuncionarioTableModel extends AbstractTableModel {

    private static final String[] COLUNAS = { "Nome", "Altura", "Peso", "Cargo", "Admissão" };

    private List<Funcionario> funcionarios;

    public FuncionarioTableModel(List<Funcionario> funcionarios) {
        this.funcionarios = funcionarios;
    }

    @Override
    public Class<?> getColumnClass(int coluna) {
        if (!funcionarios.isEmpty()) {
            return getValueAt(0, coluna).getClass();
        }
        return super.getColumnClass(coluna);
    }

    @Override
    public int getColumnCount() {
        return COLUNAS.length;
    }

    @Override
    public String getColumnName(int coluna) {
        return COLUNAS[coluna];
    }

    @Override
    public int getRowCount() {
        return funcionarios.size();
    }

    @Override
    public Object getValueAt(int linha, int coluna) {
        if (!funcionarios.isEmpty()) {

            Funcionario funcionario = funcionarios.get(linha);
            switch (coluna) {
                case 0:
                    return funcionario.getNome();
                case 1:
                    return funcionario.getPeso();
                case 2:
                    return funcionario.getAltura();
                case 3:
                    return funcionario.getCargo();
                case 4:
                    return funcionario.getAdmissao();
            }
        }
        return null;
    }
}

Um TableCellRenderer pra apresentar Date no formato dd/MM/yyyy:

import java.text.DateFormat;
import java.text.SimpleDateFormat;

import javax.swing.table.DefaultTableCellRenderer;

@SuppressWarnings("serial")
public class RenderizadorDatas extends DefaultTableCellRenderer {

    private DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");

    public void setValue(Object value) {
        setText(value == null ? "" : formatter.format(value));
    }
}

E finalmente uma telinha hipotética pra ilustrar o funcionamento:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.TableModel;

@SuppressWarnings("serial")
public class TelaExemplo extends JFrame {
    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            TelaExemplo telinha = new TelaExemplo();
            telinha.setVisible(true);
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    private JTable table;

    public TelaExemplo() {
        super("Exemplo Ordenação JTable");
        setMinimumSize(new Dimension(800, 600));

        List<Funcionario> funcionarios = carregarFuncionarios();

        TableModel tableModel = new FuncionarioTableModel(funcionarios);
        table = new JTable(tableModel);
        table.setDefaultRenderer(Date.class, new RenderizadorDatas());
        table.setAutoCreateRowSorter(true);

        add(new JScrollPane(table), BorderLayout.CENTER);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    public List<Funcionario> carregarFuncionarios() {
        List<Funcionario> funcionarios = new ArrayList<>();
        funcionarios.add(new Funcionario("Juliano", 70, 1.70, "Javeiro", "22/10/2020"));
        funcionarios.add(new Funcionario("Ricardo", 115, 1.83, "Fã do GUJ", "01/01/2002"));
        funcionarios.add(new Funcionario("Lilian", 60, 1.65, "Atendente", "03/04/2015"));
        funcionarios.add(new Funcionario("José", 86, 1.69, "Pedreiro", "07/11/1996"));
        funcionarios.add(new Funcionario("Maria", 49, 1.55, "Professora", "26/09/2000"));
        return funcionarios;
    }
}

Ordenado por nome:
ordenado-nome

Ordenado por altura:
ordenado-altura

Ordenado por Data de Admissão:
ordenado-admissao

1 curtida

Meu amigo,
Você deu um show agora, ficou muito bem esclarecido. Vou estudar estudar seu exemplo junto ao meu código, Obrigado pelo conhecimento emprestado.

1 curtida