kleopatra 已经解释了如何Format
在日期选择器上设置 a。对于这个用例,我将应用 aCompositeFormat
和ParseAllFormat
而不是单独的编辑格式和常规模式的组合,以避免String
在开始编辑时更改 (正如您已经注意到的)。
复合格式
复合格式,顾名思义,是类的复合实现,Format
但仅用于解析。对于格式,它使用一个Format
. 这允许用户以多种形式输入他/她的日期,同时通过使用一种特定的格式来统一格式化。
您也可以通过编写更复杂的Format
. SimpleDateFormat
但在这种情况下,只使用JDK 类提供的格式化/解析功能会更容易。
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.List;
/**
* <p>Composite form of {@link java.text.Format Format}. It uses multiple formats for parsing, and
* only one format for formatting.</p>
*
* <p>A possible use-case is the formatting of user input (e.g. in a {@code JFormattedTextField}).
* Multiple formats for parsing allows accepting multiple forms of user input without having to
* write a complicated format.</p>
*/
public class CompositeFormat extends Format {
private List<Format> fFormats = new ArrayList<>();
private Format fFormattingFormat;
/**
* Create a new
*/
public CompositeFormat() {
}
/**
* Add a format to this composite format
*
* @param aFormat The format to add
*/
public void addFormat( Format aFormat ) {
assertNotNull( aFormat, "You cannot add a null Format" );
if ( !( fFormats.contains( aFormat ) ) ) {
fFormats.add( aFormat );
}
}
/**
* Remove a format from this composite format
*
* @param aFormat The format to remove
*/
public void removeFormat( Format aFormat ) {
assertNotNull( aFormat, "You cannot remove a null Format" );
fFormats.remove( aFormat );
updateFormattingFormat();
}
/**
* Sets <code>aFormat</code> as the format which will be used for formatting the
* objects. The format will also be added to the list of available formats.
* @param aFormat The format which will be used for formatting
*/
public void setFormattingFormat( Format aFormat ){
assertNotNull( aFormat, "Formatting format may not be null" );
addFormat( aFormat );
fFormattingFormat = aFormat;
}
private void assertNotNull( Object aObjectToCheck, String aMessage ) {
if ( aObjectToCheck == null ) {
throw new NullPointerException( aMessage );
}
}
private void updateFormattingFormat(){
if ( !( fFormats.contains( fFormattingFormat ) ) ){
fFormattingFormat = null;
if ( !( fFormats.isEmpty() ) ){
fFormattingFormat = fFormats.iterator().next();
}
}
}
@Override
public StringBuffer format( Object obj, StringBuffer toAppendTo, FieldPosition pos ) {
assertNotNull( fFormattingFormat, "Set a formatting format before using this format" );
return fFormattingFormat.format( obj, toAppendTo, pos );
}
@Override
public Object parseObject( String source, ParsePosition pos ) {
if ( fFormats.isEmpty() ){
throw new UnsupportedOperationException( "Add at least one format before using this composite format" );
}
Format formatToUse = fFormats.iterator().next();
int maxIndex = pos.getIndex();
for ( Format format : fFormats ) {
ParsePosition tempPos = new ParsePosition( pos.getIndex() );
tempPos.setErrorIndex( pos.getErrorIndex() );
format.parseObject( source, tempPos );
if ( tempPos.getIndex() > maxIndex ){
maxIndex = tempPos.getIndex();
formatToUse = format;
if( maxIndex == source.length() ){
//found a format which parses the whole string
break;
}
}
}
return formatToUse.parseObject( source, pos );
}
}
解析所有格式
通常对于用户输入,您希望可以对整个用户输入进行格式化/解析,以避免用户可以输入一半正确的字符串。TheParseAllFormat
是一个正则的装饰器,当只有一部分可以被解析时Format
抛出s 。ParseException
String
import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
/**
* <p>Decorator for a {@link Format Format} which only accepts values which can be completely parsed
* by the delegate format. If the value can only be partially parsed, the decorator will refuse to
* parse the value.</p>
*/
public class ParseAllFormat extends Format {
private final Format fDelegate;
/**
* Decorate <code>aDelegate</code> to make sure if parser everything or nothing
*
* @param aDelegate The delegate format
*/
public ParseAllFormat( Format aDelegate ) {
fDelegate = aDelegate;
}
@Override
public StringBuffer format( Object obj, StringBuffer toAppendTo, FieldPosition pos ) {
return fDelegate.format( obj, toAppendTo, pos );
}
@Override
public AttributedCharacterIterator formatToCharacterIterator( Object obj ) {
return fDelegate.formatToCharacterIterator( obj );
}
@Override
public Object parseObject( String source, ParsePosition pos ) {
int initialIndex = pos.getIndex();
Object result = fDelegate.parseObject( source, pos );
if ( result != null && pos.getIndex() < source.length() ) {
int errorIndex = pos.getIndex();
pos.setIndex( initialIndex );
pos.setErrorIndex( errorIndex );
return null;
}
return result;
}
@Override
public Object parseObject( String source ) throws ParseException {
//no need to delegate the call, super will call the parseObject( source, pos ) method
return super.parseObject( source );
}
}
这两个类的组合允许以下代码
import java.text.Format;
import java.text.ParseException;
import java.text.SimpleDateFormat;
public class FormattingDemo {
private static Format createCompositeDateFormat(){
Format formattingFormat = new ParseAllFormat( new SimpleDateFormat( "dd.MM.yyyy" ) );
SimpleDateFormat shortFormat = new SimpleDateFormat( "dd.MM.yy" );
Format otherFormat = new ParseAllFormat( shortFormat );
CompositeFormat compositeFormat = new CompositeFormat();
compositeFormat.addFormat( otherFormat );
compositeFormat.addFormat( formattingFormat );
compositeFormat.setFormattingFormat( formattingFormat );
return compositeFormat;
}
public static void main( String[] args ) throws ParseException {
Format dateFormat = createCompositeDateFormat();
System.out.println( dateFormat.parseObject( "27.01.2010" ) );
System.out.println( dateFormat.parseObject( "27.01.10" ) );
System.out.println( dateFormat.parseObject( "27.01.2012" ) );
System.out.println(dateFormat.format( dateFormat.parseObject( "27.01.2010" ) ));
System.out.println(dateFormat.format( dateFormat.parseObject( "27.01.10" ) ));
System.out.println(dateFormat.format( dateFormat.parseObject( "27.01.2012" ) ));
}
}
导致以下输出
Wed Jan 27 00:00:00 CET 2010
Wed Jan 27 00:00:00 CET 2010
Fri Jan 27 00:00:00 CET 2012
27.01.2010
27.01.2010
27.01.2012
请注意,有一个小问题我没有找到合适的解决方案。向 中添加Format
实例CompositeFormat
的顺序也是评估它们以进行解析的顺序。在这种情况下,您需要以正确的顺序添加它们,因为即使new SimpleDateFormat( "dd.MM.yyyy" )
似乎接受输入字符串27.01.10
并且可以将整个解析为String
等效Date
于27.01.0010
.