Here is the code for a JSpinnerModel
that handles Date
objects in simple format (e.g. ‘dd/MM/yyyy’). It extends a SpinnerDateModel
so most of the code is based on that class. This class assumes that values are separated by a slash (/). The reason why I created this was based on a client’s requirement where I could only display the date in simple format and select the calendar using a JSpinner
:
/**
* A SpinnerSimpleDateModel for sequences of formatted Dates.
* in simple format(e.g. "dd/MM/yyyy")
*
* @author William Mora
* @version 1.0
*/
public class SpinnerSimpleDateModel extends SpinnerDateModel {
private Comparable start , end ;
private Date value ;
private int calendarField ;
private SimpleDateFormat dateFormat ;
private boolean calendarFieldOK ( int calendarField ) {
switch ( calendarField ) {
case Calendar . DATE :
case Calendar . YEAR :
case Calendar . MONTH :
return true ;
default :
return false ;
}
}
/**
* Creates an instance of SpinnerSimpleDateModel
*
* @param value Initial date for the model
* @param start Minimum date for the model
* @param end Maximum date for the model
* @param calendarField The interval desired for next and previous values.
* The options are:
* Calendar.DATE - Day of the month
* Calendar.MONTH - Month
* Calendar.YEAR - Year
* @param dateFormat A format specified by an instance of SimpleDateFormat
*/
public SpinnerSimpleDateModel ( Date value , Comparable start , Comparable end ,
int calendarField , SimpleDateFormat dateFormat ) {
this . dateFormat = dateFormat ;
if ( value == null ) {
throw new IllegalArgumentException ( "value is null" );
}
if (! calendarFieldOK ( calendarField )) {
throw new IllegalArgumentException ( "invalid calendarField" );
}
if ( !((( start == null ) || ( start . compareTo ( value ) <= 0 )) &&
(( end == null ) || ( end . compareTo ( value ) >= 0 )))){
throw new IllegalArgumentException ( "(start <= value <= end) is false" );
}
this . value = value ;
this . start = start ;
this . end = end ;
this . calendarField = calendarField ;
}
@Override
public void setStart ( Comparable start ) {
if (( start == null ) ? ( this . start != null ) : ! start . equals ( this . start )) {
this . start = start ;
fireStateChanged ();
}
}
@Override
public void setEnd ( Comparable end ) {
if (( end == null ) ? ( this . end != null ) : ! end . equals ( this . end )) {
this . end = end ;
fireStateChanged ();
}
}
@Override
public void setCalendarField ( int calendarField ) {
if (! calendarFieldOK ( calendarField )) {
throw new IllegalArgumentException ( "invalid calendarField" );
}
if ( calendarField != this . calendarField ) {
this . calendarField = calendarField ;
fireStateChanged ();
}
}
@Override
public Comparable getEnd () {
return end ;
}
@Override
public Object getNextValue () {
Calendar cal = Calendar . getInstance ();
cal . setTime ( value );
cal . add ( calendarField , 1 );
Date next = cal . getTime ();
return ( end == null ) || ( end . compareTo ( next ) >= 0 ) ? next: null ;
}
@Override
public Object getPreviousValue () {
Calendar cal = Calendar . getInstance ();
cal . setTime ( value );
cal . add ( calendarField , - 1 );
Date prev = cal . getTime ();
return (( start == null ) || ( start . compareTo (( prev )) <= 0 )) ? prev : null ;
}
@Override
public Object getValue () {
return value ;
}
@Override
public void setValue ( Object value ) {
if ( value == null ) {
throw new NullPointerException ( "Date is null!" );
} else {
if (( value instanceof String ) && (( String ) value ). matches ( "[0-9]+[/][0-9]+[/][0-9]+" )) {
String date = (( String ) value );
int day = Integer . parseInt ( date . substring ( 0 , 2 ));
int month = Integer . parseInt ( date . substring ( 3 , 5 ));
int year = Integer . parseInt ( date . substring ( 6 ));
Calendar cal = Calendar . getInstance ();
//Month-1 because is zero-based
cal . set ( year , month - 1 , day );
this . value = cal . getTime ();
}
if ( value instanceof Date ) {
if (! dateFormat . format (( Date ) value ). equals ( dateFormat . format ( this . value ))) {
String temp = dateFormat . format (( Date ) value );
this . setValue ( temp );
fireStateChanged ();
}
}
}
}
}
Now the model can be used for any JSpinner. To create an instance for this class, the following will work: SpinnerSimpleDateModel spinnerModel = new SpinnerSimpleDateModel(new Date(), null, null, Calendar.DATE, new SimpleDateFormat("dd/MM/yyyy"));
Then, set the editor of the JSpinner
object to show the same format specified for the SpinnerSimpleDateModel
object like the following:
JSpinner spinner1 = new javax . swing . JSpinner ();
spinner1 . setModel ( spinnerModel );
spinner1 . setEditor ( new javax . swing . JSpinner . DateEditor ( spinner1 , "dd/MM/yyyy" ));
Hope someone finds this useful. An advantage of using this technique is to manipulate date formats as you wish regardless of the locale.