I have a problem with the standard JSpinner.DateEditor (as probably does everyone else). When it works with the Java.util.Date class, it only gets a default format from the Locale set on the spinner. It appears to be TimeZone ignorant.
When we have a Date that is on the March Clock change day which in the UK has no 2 o'clock - the time jumps from 01:59:59.999 AM to 03:00 AM with day light savings applied.
Therefore in the JSpinner.DateEditor I do not want the user to see anything for 02:00 to 02:59:59.999. When the hour is on 1 and they click up, I want to jump to 3 and vice versa.
Is it possible to implement any kind of workaround to do this?
Many thanks
Andez
can you please edit your question and use this SSCCE that demonstrating your issue about DTS
import java.awt.*;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
public class TimeZoneSpinners {
private final String[] zones = {"Asia/Tokyo", "Asia/Hong_Kong",
"Asia/Calcutta", "Europe/Paris", "Europe/London",
"America/New_York", "America/Los_Angeles"
};
private final JLabel[] labels = new JLabel[zones.length];
private final SimpleDateFormat[] formats = new SimpleDateFormat[zones.length];
private JSpinner spinner;
private SpinnerDateModel model;
private SimpleDateFormat format;
private JPanel panel;
private JFrame frame = new JFrame();
public void makeUI() {
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
model = new SpinnerDateModel();
model.setValue(date);
spinner = new JSpinner(model);
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
Date date = (Date) ((JSpinner) e.getSource()).getValue();
for (int i = 0; i < labels.length; i++) {
labels[i].setText(formats[i].format(date));
}
}
});
format = ((JSpinner.DateEditor) spinner.getEditor()).getFormat();
format.setTimeZone(TimeZone.getTimeZone(zones[0]));
format.applyPattern("yyyy-MM-dd HH:mm:ss");
panel = new JPanel(new GridLayout(zones.length, 2, 10, 10));
for (int i = 0; i < zones.length; i++) {
formats[i] = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
formats[i].setTimeZone(TimeZone.getTimeZone(zones[i]));
JLabel label = new JLabel(zones[i]);
labels[i] = new JLabel(formats[i].format(date));
panel.add(label);
panel.add(labels[i]);
}
frame.setLayout(new BorderLayout(10, 10));
frame.add(spinner, BorderLayout.NORTH);
frame.add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TimeZoneSpinners().makeUI();
}
});
}
}
After reading mKorbels solution, I used it to essentially get what I wanted. I have modified the code to the following:
package datesandtimes.javax.swing;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerDateModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class JSpinnerProblem
extends JFrame {
static {
TimeZone simpleTimeZone = new SimpleTimeZone(0, "Elexon Date Time");
TimeZone.setDefault(simpleTimeZone);
}
private static final String DATE_FORMAT_TIMEZONE = "yyyy-MM-dd HH:mm:ss zzz";
private static final TimeZone tz = TimeZone.getTimeZone("Europe/London");
private JPanel panel;
private JPanel panelButtons;
private JSpinner spinner;
private SpinnerDateModel model;
private SimpleDateFormat format;
private JButton buttonClose;
public JSpinnerProblem() {
try {
setDefaultCloseOperation(JSpinnerProblem.EXIT_ON_CLOSE);
setLayout(new BorderLayout(5, 5));
// create instances
panel = new JPanel(new BorderLayout());
panelButtons = new JPanel(new GridLayout(1, 1));
model = new SpinnerDateModel();
buttonClose = new JButton("Close");
spinner = new JSpinner(model);
spinner.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
}
});
buttonClose.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
// set date format
format = ((JSpinner.DateEditor) spinner.getEditor()).getFormat();
format.setTimeZone(tz);
format.applyPattern("yyyy-MM-dd HH:mm:ss zzz");
// default to march clock change
Date d = format.parse("2012-03-25 00:00:00 GMT");
model.setValue(d);
panel.add(spinner, BorderLayout.CENTER);
panelButtons.add(buttonClose);
add(panel, BorderLayout.CENTER);
add(panelButtons, BorderLayout.SOUTH);
pack();
} catch (ParseException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JSpinnerProblem().setVisible(true);
}
});
}
}
Now when using the JSpinner, clicking the up and down buttons actually changes the hour to the correct hour based on the time zone.