This example has 2 columns of data.
Column 1 is a date without milliseconds and Column 2 is a data with milliseconds.
The display allows the user to change the Date format. The key is that column 1 should never include milliseconds while column 2 should always include milliseconds.
Granted if the date format is dd-MM-yyyy HH:mm:ss that the code could simply append ".SSS" when processing the data in Column 2, but the format can vary widely. For example, it could even be "MM-dd-yy" without including any time reference, yet the 2nd column should always include the time along with milliseconds.
Here is the code. There is extra miscellaneous code just to ensure that the milliseconds are visible the first time.
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
public class DateFormatRendererExample
{
public static void main(String[] args)
{
DateExampleSetup dateExampleSetup = new DateExampleSetup ();
}
}
class DateExampleSetup extends JFrame
{
final static Class[] columnClass = new Class[] { Date.class, Date.class };
String currentDateFormat = "MM-dd-yyyy HH:mm:ss";
String oldDateFormat = "MM-dd-yyyy HH:mm:ss";
MyTableModel model;
public DateExampleSetup()
{
model = new MyTableModel();
model.addRow("05-22-2020 12:12:12", "06-02-2020 20:11:55.123");
model.addRow("10-18-2020 14:16:17", "01-02-2020 09:09:49.567");
JTable table = new JTable(model);
table.setDefaultRenderer(Date.class, new MyDateCellRenderer(this));
JTextField dateFormatField = new JTextField(20);
dateFormatField.setText(currentDateFormat);
JButton activateDateFormat = new JButton("Activate new Date Format");
activateDateFormat.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent arg0)
{
setCurrentDateFormat(dateFormatField.getText());
MyTableModel newModel = new MyTableModel ();
newModel.addRow("05-22-2020 12:12:12", "06-02-2020 20:11:55.1234");
newModel.addRow("10-18-2020 14:16:17", "02-02-2020 09:09:49.5678");
table.setModel(newModel);
newModel.fireTableDataChanged();
setOldDateFormat(getCurrentDateFormat());
}
});
setLayout(new BorderLayout());
add(dateFormatField, BorderLayout.NORTH);
add(table, BorderLayout.CENTER);
add(activateDateFormat, BorderLayout.SOUTH);
setVisible(true);
setSize(500,300);
}
public String getCurrentDateFormat()
{
return currentDateFormat;
}
public void setCurrentDateFormat(String newCurrent)
{
currentDateFormat = newCurrent;
}
public String getOldDateFormat()
{
return oldDateFormat;
}
public void setOldDateFormat(String newCurrent)
{
currentDateFormat = newCurrent;
}
}
class MyDateCellRenderer extends JLabel implements TableCellRenderer
{
DateExampleSetup des;
boolean firstTimeRow1 = true;
boolean firstTimeRow2 = true;
public MyDateCellRenderer(DateExampleSetup des)
{
super();
this.des = des;
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int col) {
try
{
///Just to get the milliseconds to show the first time.
if (firstTimeRow1 && row == 0 && col == 1)
{
SimpleDateFormat tempDateFormat = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss.SSS");
Date tempDate = null;
tempDate = tempDateFormat.parse((String)value);
value = tempDateFormat.format(tempDate);
setText(value.toString());
firstTimeRow1 = false;
}
else if (firstTimeRow2 && row == 1 && col == 1)
{
SimpleDateFormat tempDateFormat = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss.SSS");
Date tempDate = null;
tempDate = tempDateFormat.parse((String)value);
value = tempDateFormat.format(tempDate);
setText(value.toString());
firstTimeRow2 = false;
}
else
{
SimpleDateFormat oldDateFormat = new SimpleDateFormat(des.getOldDateFormat());
SimpleDateFormat newDateFormat = new SimpleDateFormat(des.getCurrentDateFormat());
Date date = null;
date = oldDateFormat.parse((String)value);
value = newDateFormat.format(date);
setText(value.toString());
}
}
catch (ParseException e)
{
e.printStackTrace();
}
return this;
}
}
class MyTableModel extends AbstractTableModel {
private List<String[]> rows;
private String columnNames[] = { "Regular Date ", "Date with milliseconds"};
public MyTableModel() {
rows = new ArrayList<>(25);
}
@Override
public int getRowCount() {
return rows.size();
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return Date.class;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
String[] row = rows.get(rowIndex);
return row[columnIndex];
}
@Override
public String getColumnName(int col) {
return columnNames[col];
}
public void addRow(String s1, String s2)
{
String[] row = new String[getColumnCount()];
row[0] = s1;
row[1] = s2;
rows.add(row);
fireTableRowsInserted(getRowCount(), getRowCount());
}
}
When execute the following Frame is displayed. Notice the 2nd columns has the milliseconds.
When the date is change to "dd-MM-yyyy" and the "Activate new Date Format" button is pressed, the Dates in the 2nd column lose their hours, minutes and seconds and especially the milliseconds.
Is it possible to use a single Date format (that can be just about anything) for one column while using that same format for another column while ensuring the HH:mm:ss.sss always exists?