as already explained I want to achieve, that when the user is editing a date within a JXDatePicker, he can choose, weather he types it again in the same format, which is by default dd.MM.yyyy or just dd.MM.yy. When he uses the short form I want the Picker to choose the current century.
Example:
27.01.2012 edited to 27.01.10 should result in 27.01.2010
as well as:
27.01.2012 edited to 27.01.2010 should also result in 27.01.2010
By default the JXDatePicker handels it the following way:
27.01.2012 edited to 27.01.10 results in 27.01.0010
Which is not really the way I wanted it to work. After some short research I found the following Method in 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)
On first view this sounded exactly like what I need. So I tested it and unfortunatly it didnt work like I hoped it would. This is because I want to use dd.MM.yyyy as format to display dates and also want it to be displayed like that in editmode. For example when the user klicks on a date like 27.01.2012, I also want it to be like that in editmode, too and not just the short form: 27.01.12.
My Problem now is, that set2DigitYearStart(Date) unfortunatly only works, when I choose to use the shortform in editmode. I made a small example to show this case (SwingX Library is required, because of jxdatepicker and can be found be 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 );
}
}
Anyone already had the same requirement and can tell me how to make this work? Any ideas are welcome. Thank you very much in advance. ymene
Final (hopefully :)
Summary of the first edit:
The reason is DatePickerFormatter: it doesn't allow to specify the formatting format (simply uses the first). The way out is a custom DatePickerFormatter, which supports it (in the snippet, it's hardcoded to use the second):
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);
Not entirely sure if we should support configuring the formatter in the base class. The DatePickerFormatter is a bit strange beast, not extending InternalFormatter and with the lookup process being a bit in competition with a FormatterFactory...
Original
It's not exactly the datePicker which handles it that way, it's the core formatting (as D1e already noted). None of the default format/ter/s support two formats at the same time: to see, try to achieve your goal with a core JFormattedTextField :-)
The way out might be a FormatterFactory: it allows to use different formats, depending on context: display and edit - the latter is used when the field is focused, the former at all other times. As the picker's editor is a JFormattedTextField, you can configure it directly (instead of using the setFormats methods)
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);
Edit
head banging after reading Robin's recent answer (+1!) - at last, embarassingly after years and years, I understand what SwingX' DatePickerFormatter is trying to do: that is to support a lookup chain of formatters (from longer to shorter), the longest used after committing, the shorter to ease the typing by users.
Unfortunately that doesn't work as intuitively expected. Given a sequence of formats, longer to shorter (and appropriately configured to the century):
"yyyy", "yy"
and given input
"10"
feels like being passed on from first to second, resulting in
2010
but isn't. As documented (who reads documention ... lazy me, cough ...) in 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.
At the end of the day - as DatePickerFormatter tries to support that lookup but isn't successful - this might be considered a SwingX problem, after all :-)