org.wicketstuff.datetime.DateConverter.java Source code

Java tutorial

Introduction

Here is the source code for org.wicketstuff.datetime.DateConverter.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.wicketstuff.datetime;

import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.wicket.Session;
import org.apache.wicket.core.request.ClientInfo;
import org.apache.wicket.protocol.http.request.WebClientInfo;
import org.apache.wicket.util.convert.ConversionException;
import org.apache.wicket.util.convert.IConverter;
import org.apache.wicket.util.string.Strings;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormatter;

/**
 * Base class for Joda Time based date converters. It contains the logic to parse and format,
 * optionally taking the time zone difference between clients and the server into account.
 * <p>
 * Converters of this class are best suited for per-component use.
 * </p>
 * 
 * @author eelcohillenius
 */
public abstract class DateConverter implements IConverter<Date> {
    private static final long serialVersionUID = 1L;

    /**
     * Whether to apply the time zone difference when interpreting dates.
     */
    private final boolean applyTimeZoneDifference;

    /**
     * Construct. </p> When applyTimeZoneDifference is true, the current time is applied on the
     * parsed date, and the date will be corrected for the time zone difference between the server
     * and the client. For instance, if I'm in Seattle and the server I'm working on is in
     * Amsterdam, the server is 9 hours ahead. So, if I'm inputting say 12/24 at a couple of hours
     * before midnight, at the server it is already 12/25. If this boolean is true, it will be
     * transformed to 12/25, while the client sees 12/24. </p>
     * 
     * @param applyTimeZoneDifference
     *            whether to apply the difference in time zones between client and server
     */
    public DateConverter(boolean applyTimeZoneDifference) {
        this.applyTimeZoneDifference = applyTimeZoneDifference;
    }

    /**
     * @see org.apache.wicket.util.convert.IConverter#convertToObject(java.lang.String,
     *      java.util.Locale)
     */
    @Override
    public Date convertToObject(String value, Locale locale) {
        if (Strings.isEmpty(value)) {
            return null;
        }

        DateTimeFormatter format = getFormat(locale);
        if (format == null) {
            throw new IllegalStateException("format must be not null");
        }

        if (applyTimeZoneDifference) {
            TimeZone zone = getClientTimeZone();
            DateTime dateTime;

            // set time zone for client
            format = format.withZone(getTimeZone());

            try {
                // parse date retaining the time of the submission
                dateTime = format.parseDateTime(value);
            } catch (RuntimeException e) {
                throw newConversionException(e, locale);
            }
            // apply the server time zone to the parsed value
            if (zone != null) {
                dateTime = dateTime.withZoneRetainFields(DateTimeZone.forTimeZone(zone));
            }

            return dateTime.toDate();
        } else {
            try {
                DateTime date = format.parseDateTime(value);
                return date.toDate();
            } catch (RuntimeException e) {
                throw newConversionException(e, locale);
            }
        }
    }

    /**
     * Creates a ConversionException and sets additional context information to it.
     *
     * @param cause
     *            - {@link RuntimeException} cause
     * @param locale
     *            - {@link Locale} used to set 'format' variable with localized pattern
     * @return {@link ConversionException}
     */
    private ConversionException newConversionException(RuntimeException cause, Locale locale) {
        return new ConversionException(cause).setVariable("format", getDatePattern(locale));
    }

    /**
     * @see org.apache.wicket.util.convert.IConverter#convertToString(java.lang.Object,
     *      java.util.Locale)
     */
    @Override
    public String convertToString(Date value, Locale locale) {
        DateTime dt = new DateTime(value.getTime(), getTimeZone());
        DateTimeFormatter format = getFormat(locale);

        if (applyTimeZoneDifference) {
            TimeZone zone = getClientTimeZone();
            if (zone != null) {
                // apply time zone to formatter
                format = format.withZone(DateTimeZone.forTimeZone(zone));
            }
        }
        return format.print(dt);
    }

    /**
     * Gets whether to apply the time zone difference when interpreting dates.
     * 
     * </p> When true, the current time is applied on the parsed date, and the date will be
     * corrected for the time zone difference between the server and the client. For instance, if
     * I'm in Seattle and the server I'm working on is in Amsterdam, the server is 9 hours ahead.
     * So, if I'm inputting say 12/24 at a couple of hours before midnight, at the server it is
     * already 12/25. If this boolean is true, it will be transformed to 12/25, while the client
     * sees 12/24. </p>
     * 
     * @return whether to apply the difference in time zones between client and server
     */
    public final boolean getApplyTimeZoneDifference() {
        return applyTimeZoneDifference;
    }

    /**
     * @param locale
     *            The locale used to convert the value
     * @return Gets the pattern that is used for printing and parsing
     */
    public abstract String getDatePattern(Locale locale);

    /**
     * Gets the client's time zone.
     * 
     * @return The client's time zone or null
     */
    protected TimeZone getClientTimeZone() {
        ClientInfo info = Session.get().getClientInfo();
        if (info instanceof WebClientInfo) {
            return ((WebClientInfo) info).getProperties().getTimeZone();
        }
        return null;
    }

    /**
     * @param locale
     *            The locale used to convert the value
     * 
     * @return formatter The formatter for the current conversion
     */
    protected abstract DateTimeFormatter getFormat(Locale locale);

    /**
     * Gets the server time zone. Override this method if you want to fix to a certain time zone,
     * regardless of what actual time zone the server is in.
     * 
     * @return The server time zone
     */
    protected DateTimeZone getTimeZone() {
        return DateTimeZone.getDefault();
    }
}