java - JXDatePicker 使用 SimpleDateFormat 将 dd.MM.yy 格式化为当前世纪的 dd.MM.yyyy

标签 java regex swing simpledateformat swingx

如前所述,我想实现的是,当用户在 JXDatePicker 中编辑日期时,他可以选择是否以相同的格式再次键入它,默认情况下是 dd.MM.yyyy 或只是 dd。 MM.yy。当他使用缩写形式时,我希望选择器选择当前世纪。

示例:

27.01.2012 edited to 27.01.10 should result in 27.01.2010

还有:

27.01.2012 edited to 27.01.2010 should also result in 27.01.2010

默认情况下,JXDatePicker 按以下方式处理它:

27.01.2012 edited to 27.01.10 results in 27.01.0010

这并不是我想要的工作方式。经过一些简短的研究,我在 SimpleDateFormat 中发现了以下方法

/**
 * Sets the 100-year period 2-digit years will be interpreted as being in
 * to begin on the date the user specifies.
 *
 * @param startDate During parsing, two digit years will be placed in the range
 * <code>startDate</code> to <code>startDate + 100 years</code>.
 */
public void set2DigitYearStart(Date startDate)

乍一看,这听起来完全符合我的需要。所以我测试了它,不幸的是它没有像我希望的那样工作。这是因为我想使用 dd.MM.yyyy 作为显示日期的格式,并且还希望它像在编辑模式中那样显示。例如,当用户点击 2012 年 1 月 27 日这样的日期时,我也希望它在编辑模式下也是这样,而不仅仅是缩写形式:27.01.12。

我现在的问题是,不幸的是,set2DigitYearStart(Date) 只有在我选择在编辑模式下使用简写格式时才有效。我做了一个小例子来展示这种情况(需要 SwingX 库,因为 jxdatepicker 并且可以在 here 中找到)。

public class DatePickerExample extends JPanel
{
  static JFrame frame;

  public DatePickerExample()
  {
    JXDatePicker picker = new JXDatePicker();
    JTextField field = new JTextField( 10 );

    add( field );
    add( picker );

    final Calendar instance = Calendar.getInstance();
    instance.set( 2012, 01, 26 );
    Date date = instance.getTime();
    picker.setDate( date );

    //    SimpleDateFormat format = new SimpleDateFormat( "dd.MM.yy" );//Works, but I wonna display and edit it with dd.MM.yyyy
    SimpleDateFormat format = new SimpleDateFormat( "dd.MM.yyyy" );
    final Date startDate = new Date( 0 );//01.01.1970
    format.set2DigitYearStart( startDate );

    picker.setFormats( format );
  }

  public static void main( String[] args )
  {
    frame = new JFrame();
    frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    frame.setBounds( 400, 400, 400, 400 );
    frame.setLayout( new BorderLayout() );
    frame.add( new DatePickerExample() );
    frame.setVisible( true );
  }
}

谁有过同样的需求,能告诉我如何实现吗?欢迎任何想法。非常感谢你提前。伊梅内

最佳答案

最终(希望 :)

第一次编辑总结:

  • DatePickerFormatter 已经实现了一个查找策略(或 CompoundFormat,正如@Robin 所建议的)
  • 解析的查找顺序可由客户端代码配置
  • 想法是从第一个(通常是“最长”)开始尝试解析,如果失败则尝试下一个(通常是“不太长”),依此类推,直到成功或抛出 parseException
  • 对于年份解析,SimpleDateFormat 的规则与最长优先查找冲突:它要求在“yyyy”之前尝试“yy”
  • 在 datePicker 中这样做会产生不需要的副作用,即总是以短年份格式显示日期

原因是 DatePickerFormatter:它不允许指定 formatting 格式(只使用第一个)。出路是自定义 DatePickerFormatter,它支持它(在代码片段中,它被硬编码为使用第二个):

SimpleDateFormat longFormat = new SimpleDateFormat( "dd.MM.yyyy" );
SimpleDateFormat shortFormat = new SimpleDateFormat( "dd.MM.yy" );
Date startDate = new Date( 0 );//01.01.1970
shortFormat.set2DigitYearStart( startDate );

DatePickerFormatter formatter = new DatePickerFormatter(
// invers sequence for parsing to satisfy the year parsing rules
        new DateFormat[] {shortFormat, longFormat}) {

            @Override
            public String valueToString(Object value) throws ParseException {
                if (value == null) return null;
                return getFormats()[1].format(value);
            }
        } ;
DefaultFormatterFactory factory = new DefaultFormatterFactory(formatter );
picker.getEditor().setFormatterFactory(factory);

不完全确定我们是否应该支持在基类中配置格式化程序。 DatePickerFormatter 有点奇怪,它没有扩展 InternalFormatter 并且查找过程有点与 FormatterFactory 竞争......

原创

不完全是 datePicker 以这种方式处理它,它是核心格式(正如 D1e 已经指出的那样)。默认格式/ter/s 都不支持同时两种格式:看,尝试使用核心 JFormattedTextField 实现您的目标:-)

出路可能是 FormatterFactory:它允许根据上下文使用不同的格式:显示和编辑 - 后者在字段获得焦点时使用,前者在所有其他时间使用。由于选择器的编辑器 JFormattedTextField,您可以直接配置它(而不是使用 setFormats 方法)

    SimpleDateFormat format = new SimpleDateFormat( "dd.MM.yyyy" );
    SimpleDateFormat editFormat = new SimpleDateFormat( "dd.MM.yy" );

    final Date startDate = new Date( 0 );//01.01.1970
    instance.setTime(startDate);
    editFormat.set2DigitYearStart( instance.getTime() );
    DefaultFormatterFactory factory = new DefaultFormatterFactory(
            new DatePickerFormatter(new DateFormat[] {format}),
            new DatePickerFormatter(new DateFormat[] {format}),
            new DatePickerFormatter(new DateFormat[] {editFormat})
            );
    picker.getEditor().setFormatterFactory(factory);

编辑

读完 Robin 最近的回答(+1!)后脑袋砰砰直跳——终于,在多年之后令人尴尬的是,我明白了 SwingX 的 DatePickerFormatter 试图做的事情:那就是支持格式化程序的查找链(从长到短), 提交后使用的时间最长,使用时间越短,以方便用户输入。

不幸的是,这并没有像直观预期的那样工作。给定一系列格式,从长到短(并根据世纪适当配置):

"yyyy", "yy"

和给定的输入

"10"

感觉像是从第一传到第二,导致

 2010

但不是。正如 SimpleDateFormat 中记录的那样(谁阅读文档......懒惰我,咳嗽......)

Year: [ ... ] For parsing, if the number of pattern letters is more than 2, the year is interpreted literally, regardless of the number of digits. So using the pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.

归根结底——因为 DatePickerFormatter 试图支持该查找但没有成功——毕竟这可能被认为是 SwingX 问题:-)

关于java - JXDatePicker 使用 SimpleDateFormat 将 dd.MM.yy 格式化为当前世纪的 dd.MM.yyyy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9034766/

相关文章:

java - 带注释方法的首选修饰符顺序

php - RegEx 用于匹配 CSS 文件中的特定 javaDoc 属性,并提取有关 css 定义的数据

java swing - 在 java swing 中创建一个类似旋转木马的按钮

java - 将文本添加到我的 JScrollPane/JArea 时如何自动滚动?

java - 确定与 Line2D 重叠的组件

java - 在Android中保存单例状态?

java - 'Single Read' REST API 的适当 HTTP 方法

java - JDK 15 密封类 - 如何跨包使用?

Javascript 正则表达式简写?

python - 如何在 CSS 选择器 scrapy 中使用正则表达式