Package org.jtalks.jcommune.web.tags

Source Code of org.jtalks.jcommune.web.tags.FormattedDate

/**
* Copyright (C) 2011  JTalks.org Team
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library 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
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
package org.jtalks.jcommune.web.tags;


import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.contrib.jsptag.FormatTag;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.PageContext;
import java.util.concurrent.TimeUnit;

/**
* This tag replaces the existing Joda Time format tag to take
* into account the local time offset set in cookies.
* Although the library has out-of-box timezone support,
* we cannot use it since we don't know the timezone.
* Automatic timezone detection is a complicated task:
* - ip-based detection is inaccurate for some regions
* - bare time offset cannot be properly mapped on the timezone,
* 'cause timezones have different DST settings
* <p/>
* We also could ask the user himself for the timezone, but it's
* as boring, as irritating.
*
* @author Evgeniy Naumenko
*/
public class FormattedDate extends FormatTag {

    /**
     * Serializable class should define it
     */
    private static final long serialVersionUID = 34588L;

    public static final String GMT_COOKIE_NAME = "GMT";

    /**
     * Example: 01 Jan 2011 05:13
     * Localized month names are to be inserted by magic
     */
    public static final String DEFAULT_DATE_FORMAT_PATTERN = "dd MMM yyyy HH:mm";

    private long offset = DEFAULT_OFFSET;

    public static final int DEFAULT_OFFSET = 0;

    public FormattedDate() {
        super();
        // override parent default
        pattern = DEFAULT_DATE_FORMAT_PATTERN;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setPageContext(PageContext pageContext) {
        Cookie[] cookies = ((HttpServletRequest) pageContext.getRequest()).getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(GMT_COOKIE_NAME)) {
                    offset = this.convertTimeZoneOffset(cookie.getValue());
                    break;
                }
            }
        }
        super.setPageContext(pageContext);
        this.setDateFormattingOptions();
    }

    /**
     * This method adds the corresponding offset to make the date and time
     * match local user's timezone. If value is not a DateTime it's
     * formatted as is
     *
     * @param value value to be formatted as date
     * @throws JspTagException only from super() call
     */
    @Override
    public void setValue(Object value) throws JspTagException {
        if (value != null) {
            DateTime time = (DateTime) value;
            DateTimeZone zone = time.getZone();
            long utcTime = zone.convertLocalToUTC(time.getMillis(), false);
            time = new DateTime(utcTime + offset);
            super.setValue(time);
        } else {
            super.setValue(null);
        }
    }

    /**
     * Converts timezone offset representation to millisecond offset.
     * If timezone offset representation is incorrect, then GMT
     * timezone value is used.
     *
     * @param jsRepresentation time difference between GMT and
     *                         local time, in minutes. Example: "-120"
     * @return signed millisecond timezone offset
     */
    private long convertTimeZoneOffset(String jsRepresentation) {
        try {
            int offsetInMinutes = -Integer.parseInt(jsRepresentation);
            return TimeUnit.MINUTES.toMillis(offsetInMinutes);
        } catch (NumberFormatException e) {
            // someone has passed wrong offset in cookie, use GMT
            return DEFAULT_OFFSET;
        }
    }

    /**
     * Figures out the the current locale and defines the date formatting pattern.
     * Change the pattern here to affect all the dates formatting on pages.
     */
    private void setDateFormattingOptions() {
        try {
            HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
            LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
            this.setLocale(localeResolver.resolveLocale(request));
        } catch (JspTagException e) {
            throw new IllegalStateException("Error while rendering the date", e);
        }
    }
}
TOP

Related Classes of org.jtalks.jcommune.web.tags.FormattedDate

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.