net.solarnetwork.util.JodaDateFormatEditor.java Source code

Java tutorial

Introduction

Here is the source code for net.solarnetwork.util.JodaDateFormatEditor.java

Source

/* ===================================================================
 * JodaDateFormatEditor.java
 * 
 * Created Aug 3, 2009 3:51:41 PM
 * 
 * Copyright (c) 2009 Solarnetwork.net Dev Team.
 * 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License as 
 * published by the Free Software Foundation; either version 2 of 
 * the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
 * 02111-1307 USA
 * ===================================================================
 * $Id$
 * ===================================================================
 */

package net.solarnetwork.util;

import java.beans.PropertyEditorSupport;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.ReadableInstant;
import org.joda.time.ReadablePartial;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

/**
 * PropertyEditor using Joda Time's DateTimeFormatter for thread-safe date
 * parsing and formatting.
 * 
 * <p>This class has been designed with {@link CloningPropertyEditorRegistrar}
 * in mind, so that one instance of a {@link DateTimeFormatter} can be shared
 * between multiple threads to parse or format Joda date objects.</p>
 * 
 * <p>The configurable properties of this class are:</p>
 * 
 * <dl class="class-properties">
 *   <dt>datePattern</dt>
 *   <dd>The date pattern format string to use for parsing / formatting dates.
 *   See the {@link org.joda.time.format.DateTimeFormat} JavaDocs for 
 *   information on how the patterns work. Defaults to {@code yyyy-MM-dd}.</dd>
 *   
 *   <dt>timeZone</dt>
 *   <dd>The TimeZone to use for parsing/formatting all dates. Defaults to 
 *   the platform's default time zone.</dd>
 *   
 *   <dt>parseMode</dt>
 *   <dd>A mode flag for handling different Joda date instance types.</dd>
 *   
 * </dl>
 *
 * @author matt
 * @version $Revision$ $Date$
 */
public class JodaDateFormatEditor extends PropertyEditorSupport implements Cloneable {

    /**
     * A mode flag to determine the type of dates to parse.
     */
    public enum ParseMode {

        /** Parse text into DateTime objects. */
        DateTime,

        /** Parse text into LocalDate objects. */
        LocalDate,

        /** Parse text into LocalTime objects. */
        LocalTime,

    }

    private TimeZone timeZone = TimeZone.getDefault();
    private String[] datePatterns = new String[] { "yyyy-MM-dd" };
    private ParseMode parseMode = ParseMode.DateTime;

    private DateTimeFormatter[] dateFormatters = null;

    /**
     * Default constructor.
     */
    public JodaDateFormatEditor() {
        super();
    }

    /**
     * Construct from a single date pattern value in the default time zone.
     * 
     * <p>This will also call the {@link #init()} method.</p>
     * 
     * @param datePattern the date pattern
     */
    public JodaDateFormatEditor(String datePattern) {
        this(datePattern, ParseMode.DateTime);
    }

    /**
     * Construct from a single date pattern value in the default time zone.
     * 
     * <p>This will also call the {@link #init()} method.</p>
     * 
     * @param datePattern the date pattern
     * @param parseMode the specific parse mode to use
     */
    public JodaDateFormatEditor(String datePattern, ParseMode parseMode) {
        this(datePattern, parseMode == ParseMode.DateTime ? TimeZone.getDefault() : null);
        this.parseMode = parseMode;
    }

    /**
     * Construct from a single date pattern value.
     * 
     * <p>This will also call the {@link #init()} method.</p>
     * 
     * @param datePattern the date pattern
     * @param timeZone the time zone
     */
    public JodaDateFormatEditor(String datePattern, TimeZone timeZone) {
        this(new String[] { datePattern }, timeZone);
    }

    /**
     * Construct from multiple date pattern values.
     * 
     * <p>This will also call the {@link #init()} method.</p>
     * 
     * @param datePatterns the date patterns
     * @param timeZone the time zone
     */
    public JodaDateFormatEditor(String[] datePatterns, TimeZone timeZone) {
        super();
        this.datePatterns = datePatterns;
        this.timeZone = timeZone;
        init();
    }

    /**
     * Initialize after properties set.
     */
    public void init() {
        this.dateFormatters = new DateTimeFormatter[this.datePatterns.length];
        for (int i = 0; i < this.dateFormatters.length; i++) {
            this.dateFormatters[i] = DateTimeFormat.forPattern(datePatterns[i]);
            if (timeZone != null) {
                this.dateFormatters[i] = dateFormatters[i].withZone(DateTimeZone.forTimeZone(timeZone));
            }
        }
    }

    @Override
    public String getAsText() {
        Object val = getValue();
        if (val == null) {
            return null;
        }
        DateTimeFormatter format = this.dateFormatters[0];
        if (val instanceof ReadableInstant) {
            return format.print((ReadableInstant) val);
        } else if (val instanceof ReadablePartial) {
            return format.print((ReadablePartial) val);
        } else if (val instanceof Date) {
            return format.print(((Date) val).getTime());
        } else if (val instanceof Calendar) {
            return format.print(((Calendar) val).getTimeInMillis());
        }
        throw new IllegalArgumentException("Unsupported date object [" + val.getClass() + "]: " + val);
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        IllegalArgumentException iae = null;
        // try patterns one at a time, if all fail to parse then throw exception
        for (DateTimeFormatter df : this.dateFormatters) {
            try {
                DateTime dt = df.parseDateTime(text);
                Object val = dt;
                switch (this.parseMode) {
                case LocalDate:
                    val = dt.toLocalDate();
                    break;

                case LocalTime:
                    val = dt.toLocalTime();
                    break;

                default:
                    // leave as DateTime
                }
                setValue(val);
                iae = null;
                break;
            } catch (IllegalArgumentException e) {
                iae = e;
            }
        }
        if (iae != null) {
            throw iae;
        }
    }

    @Override
    public Object clone() {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            // should never get here
            throw new RuntimeException(e);
        }
    }

    /**
     * Get the first date pattern.
     * 
     * @return the datePattern
     */
    public String getDatePattern() {
        if (datePatterns == null || datePatterns.length < 1) {
            return null;
        }
        return datePatterns[0];
    }

    /**
     * Set a single date pattern.
     * 
     * @param datePattern the datePattern to set
     */
    public void setDatePattern(String datePattern) {
        this.datePatterns = new String[] { datePattern };
    }

    /**
     * @return the timeZone
     */
    public TimeZone getTimeZone() {
        return timeZone;
    }

    /**
     * @param timeZone the timeZone to set
     */
    public void setTimeZone(TimeZone timeZone) {
        this.timeZone = timeZone;
    }

    /**
     * @return the datePatterns
     */
    public String[] getDatePatterns() {
        return datePatterns;
    }

    /**
     * @param datePatterns the datePatterns to set
     */
    public void setDatePatterns(String[] datePatterns) {
        this.datePatterns = datePatterns;
    }

    /**
     * @return the parseMode
     */
    public ParseMode getParseMode() {
        return parseMode;
    }

    /**
     * @param parseMode the parseMode to set
     */
    public void setParseMode(ParseMode parseMode) {
        this.parseMode = parseMode;
    }

}