/* Copyright (2012) Schibsted ASA * This file is part of Possom. * * Possom 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 3 of the License, or * (at your option) any later version. * * Possom 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 Possom. If not, see <http://www.gnu.org/licenses/>. */ /* * DateFormattingDirective.java * * Created on 24. november 2006, 11:34 * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package no.sesat.search.view.velocity; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.velocity.context.InternalContextAdapter; import org.apache.velocity.exception.MethodInvocationException; import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.exception.ResourceNotFoundException; import org.apache.velocity.runtime.directive.Directive; import org.apache.velocity.runtime.parser.Token; import org.apache.velocity.runtime.parser.node.Node; import java.io.IOException; import java.io.Writer; import java.text.DateFormatSymbols; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.TimeZone; /** * A velocity directive to format newsnavigator date. * <p/> * Newsdate comes from the fastnavigator in four forms:<br/> * 1. 10-2006 -> Oktober 2006<br/> * 2. 24-10-2006 -> 24. oktober 2006<br/> * 3. 2006-10 -> Oktober 2006<br/> * 4. 2006-10-24 -> 24. oktober 2006<br/> * <p/> * if 'newsdateOnly' navigator, we shuold check if the date is today or yesterday * <p/> * <b>Note:</b> This directive is meant to be used on navigators. that means that the timeZone for the dates are in "CET" */ public final class DateFormattingDirective extends Directive { // We could get Locale from the site in the context, but then we had to create a new // dateformatter for each call. (can be up to 100 calls for one request.) Leaving it to "no" only for now. private static DateFormatSymbols formatSymbols = new DateFormatSymbols(new Locale("no")); // static { // // Default symbols are all lowercase for "no", so we have to set new ones. // formatSymbols.setMonths(new String[]{"Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"}); // } private static SimpleDateFormat shortFormatter = new SimpleDateFormat("MMMMM yyyy", formatSymbols); private static SimpleDateFormat longFormatter = new SimpleDateFormat("d. MMMMM yyyy", formatSymbols); private static final Logger LOG = Logger.getLogger(DateFormattingDirective.class); private static final String NAME = "dateFormatting"; private static SimpleDateFormat formOneParser = new SimpleDateFormat("MM-yyyy"); private static SimpleDateFormat formTwoParser = new SimpleDateFormat("dd-MM-yyyy"); private static SimpleDateFormat formThreeParser = new SimpleDateFormat("yyyy-MM"); private static SimpleDateFormat formFourParser = new SimpleDateFormat("yyyy-MM-dd"); /** * {@inheritDoc} */ public String getName() { return NAME; } /** * {@inheritDoc} */ public int getType() { return LINE; } /** * {@inheritDoc} */ public boolean render(final InternalContextAdapter context, final Writer writer, final Node node) throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException { if (node.jjtGetNumChildren() < 1) { rsvc.error("#" + getName() + " - missing argument"); return false; } final String input = node.jjtGetChild(0).value(context).toString(); String navName = null; if (node.jjtGetNumChildren() > 1) { navName = node.jjtGetChild(1).value(context).toString(); } String fDate = input; try { fDate = formatDate(input, navName); } catch (ParseException e) { LOG.error("Could not parse date", e); } writer.write(fDate); final Token lastToken = node.getLastToken(); if (lastToken.image.endsWith("\n")) { writer.write("\n"); } return true; } protected String formatDate(String input, String navName) throws ParseException { if (input.substring(2, 3).equals("-")) { // Form one or two if (input.length() == 10) { return formatFormTwo(input, "newsdateOnly".equals(navName)); } else { return StringUtils.capitalize(formatFormOne(input)); } } else { // From three or four if (input.length() == 10) { return formatFormFour(input, "newsdateOnly".equals(navName)); } else { return StringUtils.capitalize(formatFormThree(input)); } } } protected String formatFormOne(String input) throws ParseException { // 1. 10-2006 -> oktober 2006 return shortFormatter.format(formOneParser.parse(input)); } protected String formatFormTwo(String input, boolean newsDateOnly) throws ParseException { // 2. 24-10-2006 -> 24. oktober 2006 Date parsedDate = formTwoParser.parse(input); return longFormat(parsedDate, newsDateOnly); } protected String formatFormThree(String input) throws ParseException { // 3. 2006-10 -> oktober 2006 return shortFormatter.format(formThreeParser.parse(input)); } protected String formatFormFour(String input, boolean newsDateOnly) throws ParseException { Date parsedDate = formFourParser.parse(input); return longFormat(parsedDate, newsDateOnly); } private String longFormat(Date parsedDate, boolean newsDateOnly) { if (newsDateOnly) { if (isToday(parsedDate)) { return "I dag"; } else if (isYesterday(parsedDate)) { return "I går"; } } return longFormatter.format(parsedDate); } private boolean isToday(Date parsedDate) { Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("CET")); int todayDay = cal.get(Calendar.DAY_OF_YEAR); int year = cal.get(Calendar.YEAR); cal.setTime(parsedDate); return todayDay == cal.get(Calendar.DAY_OF_YEAR) && year == cal.get(Calendar.YEAR); } private boolean isYesterday(Date parsedDate) { Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("CET")); cal.add(Calendar.DAY_OF_YEAR, -1); int yesterdayDay = cal.get(Calendar.DAY_OF_YEAR); int year = cal.get(Calendar.YEAR); cal.setTime(parsedDate); return yesterdayDay == cal.get(Calendar.DAY_OF_YEAR) && year == cal.get(Calendar.YEAR); } }