4 Replies Latest reply on Jan 15, 2008 8:00 AM by Daniel Soneira

    calendar - many formats

    marx3 Apprentice

      Is it possible to support two different formats of data at once in rich:calendar?

      My users is used to two different formats (dd:mm:yyyy and dd/mm/yyyy) and I don't want to force them to use only one. I imagine there should be primary format and one that automatically will change into primary on blur.

        • 1. Re: calendar - many formats
          Daniel Soneira Novice

          I wrote a converter, that can handle several formats at once. Please consider that our projects build upon myfaces.

          My code below shows a converter that is able to convert different inputs:
          (Today is 14.01.2008)

          "03" => "03.01.2008"
          "0104" => "01.04.2008"
          "9.5" => "09.05.2005"

          Just change it to fit your needs.

          By registering it as "standard" datetimeconverter you can use the f:convertDateTime tag.

           <converter>
           <converter-id>javax.faces.DateTime</converter-id>
           <converter-class>
           com.joynit.jsf.converter.DateTimeConverter
           </converter-class>
           </converter>
          


          To "trigger" this converter after the input I use the following jsp-fragment (facelets tag, so please change accordingly). The important parts are f:convertDateTime and a4j:support.

          <rich:calendar id="${id}"
           value="${value}"
           enableManualInput="true"
           popup="true"
           disabled="${disabled}"
           datePattern="dd.MM.yyyy"
           inputSize="10">
           <f:convertDateTime pattern="dd.MM.yyyy" timeZone="CET"/>
           <a4j:support event="oninputchange"
           reRender="${id}"
           ajaxSingle="true"/>
           </rich:calendar>
          



          public class DateTimeConverter
           extends javax.faces.convert.DateTimeConverter
           implements DateConverter {
          
           @Override
           public String getAsString(
           FacesContext context,
           UIComponent component,
           Object value)
           throws ConverterException {
           if (value instanceof Calendar) {
           value = ((Calendar)value).getTime();
           }
           final String result = super.getAsString(
           context,
           component,
           value);
           return result;
           }
          
           @Override
           public Object getAsObject(
           FacesContext context,
           UIComponent component,
           String value)
           throws ConverterException {
           Object asObject = null;
           final Class componentType = this.getComponentType(
           context,
           component);
           if (componentType != null) {
           try {
           // insert zeroes [3.4.07 => 03.04.07]
           String[] tokens = value.split("\\.");
           String edited = "";
           for (int index=0; index < tokens.length; index++) {
           String token = tokens[index];
           if (token.length()==1) token = "0".concat(token);
           edited = edited.concat(token);
           }
           asObject = super.getAsObject(
           context,
           component,
           edited);
           if (Calendar.class.isAssignableFrom(componentType) && asObject instanceof Date) {
           final Calendar calendar = Calendar.getInstance();
           calendar.setTime((Date)asObject);
           asObject = calendar;
           }
           } catch (ConverterException ex) {
           asObject = fallbackParse(value, componentType, ex);
           }
           }
           return asObject;
           }
          
           private Object fallbackParse(String value, final Class componentType, ConverterException ex) {
           Object asObject = null;
           ArrayList<SimpleDateFormat> formats = new ArrayList<SimpleDateFormat>();
           formats.add(new SimpleDateFormat("ddMMyy"));
           formats.add(new SimpleDateFormat("ddMMyyyy"));
           formats.add(new SimpleDateFormat("dd.MM.yy"));
           formats.add(new SimpleDateFormat("dd.MM.yyyy"));
          
           String[] tokens = value.split("\\.");
           String edited = "";
           for (int index=0; index < tokens.length; index++) {
           String token = tokens[index];
           if (token.length()==1) token = "0".concat(token);
           if (index>0) edited = edited.concat(".");
           edited = edited.concat(token);
           }
          
           String currYear = String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
           String currMonth = String.valueOf(Calendar.getInstance().get(Calendar.MONTH)+1);
           if (currMonth.length()==1) {
           currMonth = "0".concat(currMonth);
           }
          
           tokens = edited.split("\\.");
          
           // ONE dot [dd.MM]
           if (tokens.length == 2) {
           edited = tokens[0].concat(".").concat(tokens[1]).concat(".").concat(currYear);
           } else if (tokens.length == 1 && value.length()<4) {
           // no dots [dd]
           edited = edited.concat(currMonth).concat(currYear);
           } else if (tokens.length == 1 && value.length()<6) {
           // no dots [dd.MM]
           edited = edited.concat(currYear);
           }
          
           Date parsed = null;
           Iterator<SimpleDateFormat> it = formats.iterator();
           SimpleDateFormat format;
          
           while (parsed == null && it.hasNext()) {
           try {
           format = it.next();
           if (getTimeZone() != null) {
           format.setTimeZone(getTimeZone());
           }
           format.setLenient(false); // format cannot be lenient
           parsed = format.parse(edited);
           } catch (ParseException parseEx) {
           // no action necessary - just try next format
           }
           }
          
           // none of the fallback formats was recognized
           if (parsed == null) {
           throw ex; // rethrow original exception
           }
          
           if (Calendar.class.isAssignableFrom(componentType)) {
           final Calendar calendar = Calendar.getInstance();
           calendar.setTime(parsed);
           asObject = calendar;
           } else {
           asObject = parsed;
           }
           return asObject;
           }
           /**
           * Gets the component type for the given <code>component</code>.
           * @param context the current faces context.
           * @param component the component from which to retrieve the type.
           * @return true/false
           */
           private Class getComponentType(
           final FacesContext context,
           final UIComponent component) {
           Class type = null;
           final ValueBinding binding = component.getValueBinding("value");
           if (binding != null) {
           type = binding.getType(context);
           }
           return type;
           }
          
           /**
           * Gets the component Value for the given <code>component</code>.
           * @param context the current faces context.
           * @param component the component from which to retrieve the value.
           * @return true/false
           */
           private Object getComponentValue(
           final FacesContext context,
           final UIComponent component) {
           Object value = null;
           final ValueBinding binding = component.getValueBinding("value");
           if (binding != null) {
           value = binding.getValue(context);
           }
           return value;
           }
          
           public static final String CONVERTER_ID = "javax.faces.DateTime";
          
           /**
           * @see org.apache.myfaces.custom.calendar.HtmlCalendarRenderer.DateConverter#getAsDate(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
           */
           public Date getAsDate(
           FacesContext context,
           UIComponent component) {
           Object value = this.getComponentValue(
           context,
           component);
           if (value instanceof Calendar) {
           value = ((Calendar)value).getTime();
           }
           return (Date)value;
           }
          }
          


          • 2. Re: calendar - many formats
            marx3 Apprentice

            implements DateConverter - I can't find such interface

            • 3. Re: calendar - many formats
              marx3 Apprentice

              It seems this interface isn't needed - thank you! It works ok!

              • 4. Re: calendar - many formats
                Daniel Soneira Novice

                 

                "Marx3" wrote:
                It seems this interface isn't needed - thank you! It works ok!


                DateConverter is an interface of MyFaces with only one method: "getAsDate".

                Glad it worked for you - you're welcome :)