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

cru*_*sam 5 java regex swing swingx simpledateformat

正如我已经解释过的那样,当用户在JXDatePicker中编辑日期时,他可以选择,天气他再次以相同的格式输入它,默认情况下是dd.MM.yyyy或者只是dd.MM.yy .当他使用短形式时,我希望Picker选择当前的世纪.

例:

27.01.2012 edited to 27.01.10 should result in 27.01.2010
Run Code Online (Sandbox Code Playgroud)

以及:

27.01.2012 edited to 27.01.2010 should also result in 27.01.2010
Run Code Online (Sandbox Code Playgroud)

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

27.01.2012 edited to 27.01.10 results in 27.01.0010
Run Code Online (Sandbox Code Playgroud)

这不是我希望它工作的方式.经过一些简短的研究后,我在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)
Run Code Online (Sandbox Code Playgroud)

在第一个视图中,这听起来就像我需要的那样.所以我测试了它,不幸的是它没有像我希望的那样工作.这是因为我想使用dd.MM.yyyy作为格式来显示日期,并希望它在editmode中显示.例如,当用户点击像27.01.2012这样的日期时,我也希望它在editmode中也是如此,而不仅仅是简短形式:27.01.12.

我现在的问题是,当我选择在editmode中使用shortform时,set2DigitYearStart(Date)不幸地起作用.我做了一个小例子来展示这种情况(需要使用SwingX库,因为jxdatepicker可以在这里找到).

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 );
  }
}
Run Code Online (Sandbox Code Playgroud)

任何人都有相同的要求,可以告诉我如何使这项工作?欢迎任何想法.非常感谢你提前.ymene

kle*_*tra 5

决赛(希望:)

第一次编辑摘要:

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

原因是DatePickerFormatter:它不允许指定格式化格式(只使用第一个).出路是一个自定义的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);
Run Code Online (Sandbox Code Playgroud)

不完全确定我们是否应该支持在基类中配置formatter.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);
Run Code Online (Sandbox Code Playgroud)

编辑

在阅读了Robin最近的回答(+1!)之后敲打头 - 最后,经过多年和多年的尴尬,我明白SwingX'DatePickerFormatter正在尝试做什么:那就是支持格式化程序的查找链(从长到短),提交后使用时间最长,用户输入的时间越短越容易.

不幸的是,这并不像直觉预期那样有效.给定一系列格式,从更长到更短(并适当配置到本世纪):

"yyyy", "yy"
Run Code Online (Sandbox Code Playgroud)

给定输入

"10"
Run Code Online (Sandbox Code Playgroud)

感觉就像从第一个传递到第二个,导致

 2010
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.正如在SimpleDateFormat中记录的那样(谁读了文档......懒惰我,咳嗽......)

年份:[...]对于解析,如果模式字母的数量大于2,则无论数字位数如何,都将按字面解释年份.所以使用"MM/dd/yyyy"模式,"01/11/12"解析到公元12年1月11日

在一天结束时 - 由于DatePickerFormatter试图支持该查找但不成功 - 毕竟这可能被认为是一个SwingX问题:-)


JMe*_*nik 2

我不太清楚 JXDatePicker 具体情况,但如果您想要模拟的具体功能是:用户输入 27.01.2010 和 27.01.10 独立应该产生 27.01.2010

然后这将起作用:

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

public class Main {

    public static void main(String[] args) throws ParseException {
        String inputLiteralDateYY = "27.01.10"; //Also works with "27.01.97"
        String inputLiteralDateYYYY = "27.01.2010"; //Also works with "27.01.1997"

        DateFormat dfYYYY = new SimpleDateFormat("dd.MM.yyyy");
        DateFormat dfYY = new SimpleDateFormat("dd.MM.yy");


        Date dateFromYY = dfYY.parse(inputLiteralDateYY);
        Date dateFromYYYY = dfYY.parse(inputLiteralDateYYYY);

        String outputLiteralDateFromYY = dfYYYY.format(dateFromYY);
        String outputLiteralDateFromYYYY = dfYYYY.format(dateFromYYYY);

        System.out.println(outputLiteralDateFromYY);
        System.out.println(outputLiteralDateFromYYYY);
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是,首先使用“dd.MM.yy”模式解析输入,然后使用“dd.MM.yyyy”模式返回其格式。

希望这有助于或有助于将其应用到您的场景中。