尽管值正确,但JSpinner显示时间具有恒定的小时偏移

时间:2017-02-15 11:16:05

标签: java swing time jspinner

我有一段代码可以在JSpinner对象中显示时间

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.AM_PM, 0);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);

spStartTime = new JSpinner(new CustomSpinnerModel(cal.getTime(), null, null, cal.get(Calendar.HOUR_OF_DAY), 100, "start"));

((JSpinner.DefaultEditor) spStartTime.getEditor()).getTextField().setFormatterFactory(new DefaultFormatterFactory(new DateFormatter(new SimpleDateFormat("hh:mm:ss,SSS"))));

CustomSpinnerModel扩展了SpinnerDateModel,我重写了getNextValue()和getPreviousValue()。

public Object getNextValue()
{
    Object next = super.getValue();
    Calendar calendar = new GregorianCalendar();

    calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
    calendar.setTime((Date) next);

    Date helper = new Date(calendar.getTimeInMillis() + defaultStep);

    calendar.setTime(helper);

    System.out.println(calendar.getTimeInMillis());
    return calendar.getTime();
}

现在,当我第一次点击向上箭头时,这会打印100毫秒,这意味着值正确,因为我从0毫秒开始。问题是我在JSpinner中看到的是

02:00:00,100

可视化中有一个恒定的2小时偏移。

1 个答案:

答案 0 :(得分:1)

我认为DateFormat#setTimeZone(TimeZone)正是您所寻找的:

//((JSpinner.DefaultEditor) spStartTime.getEditor()).getTextField()
//  .setFormatterFactory(new DefaultFormatterFactory(
//    new DateFormatter(new SimpleDateFormat("hh:mm:ss,SSS"))));
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss,SSS");
format.setTimeZone(TimeZone.getTimeZone("GMT"));
((JSpinner.DefaultEditor) spStartTime.getEditor()).getTextField()
    .setFormatterFactory(new DefaultFormatterFactory(
      new DateFormatter(format)));
import java.awt.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.text.*;

public class DateEditorTimeZoneTest {
  public JComponent makeUI() {
    SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss,SSS");
    format.setTimeZone(TimeZone.getTimeZone("GMT"));

    Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    cal.clear(Calendar.HOUR_OF_DAY);
    cal.clear(Calendar.AM_PM);
    cal.clear(Calendar.HOUR);
    cal.clear(Calendar.MINUTE);
    cal.clear(Calendar.SECOND);
    cal.clear(Calendar.MILLISECOND);

    Date start = cal.getTime();
    System.out.println(start);
    System.out.println(format.format(start));

    int defaultStep = 100;
    JSpinner spinner = new JSpinner(new SpinnerDateModel(
            start, null, null, Calendar.MILLISECOND) {
      @Override public void setCalendarField(int calendarField) {
        // If you only want one field to spin you can subclass
        // and ignore the setCalendarField calls. 
      }
      @Override public Object getNextValue() {
        Object next = super.getValue();
        Calendar calendar = new GregorianCalendar();
        calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
        calendar.setTime((Date) next);
        Date helper = new Date(calendar.getTimeInMillis() + defaultStep);
        calendar.setTime(helper);
        System.out.println(calendar.getTimeInMillis());
        return calendar.getTime();
      }
      //@Override public Object getPreviousValue() {
      //  //...
      //}
    });
    JSpinner.DateEditor editor = new JSpinner.DateEditor(spinner, "HH:mm:ss,SSS");
    spinner.setEditor(editor);
    editor.getTextField().setFormatterFactory(
        new DefaultFormatterFactory(new DateFormatter(format)));

    JPanel p = new JPanel();
    p.add(spinner);
    return p;
  }
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new DateEditorTimeZoneTest().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}