All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.struts2.components.Date Maven / Gradle / Ivy

/*
 * 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.apache.struts2.components;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.views.annotations.StrutsTag;
import org.apache.struts2.views.annotations.StrutsTagAttribute;

import java.io.IOException;
import java.io.Writer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;

/**
 * 
 *
 * Format Date object in different ways.
 * 

* The date tag will allow you to format a Date in a quick and easy way. * You can specify a custom format (eg. "dd/MM/yyyy hh:mm"), you can generate * easy readable notations (like "in 2 hours, 14 minutes"), or you can just fall back * on a predefined format with key 'struts.date.format' in your properties file. *

* *

* If that key is not defined, it will finally fall back to the default DateFormat.MEDIUM * formatting. *

* *

* Note: If the requested Date object isn't found on the stack, a blank will be returned. *

* *

* Configurable attributes are: *

* *
    *
  • name
  • *
  • nice
  • *
  • format
  • *
* *

* Following how the date component will work, depending on the value of nice attribute * (which by default is false) and the format attribute. *

* *

* Condition 1: With nice attribute as true *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
i18n keydefault
struts.date.format.past{0} ago
struts.date.format.futurein {0}
struts.date.format.secondsan instant
struts.date.format.minutes{0,choice,1#one minute|1<{0} minutes}
struts.date.format.hours{0,choice,1#one hour|1<{0} hours}{1,choice,0#|1#, one minute|1<, {1} minutes}
struts.date.format.days{0,choice,1#one day|1<{0} days}{1,choice,0#|1#, one hour|1<, {1} hours}
struts.date.format.years{0,choice,1#one year|1<{0} years}{1,choice,0#|1#, one day|1<, {1} days}
* *

* Condition 2: With nice attribute as false and format attribute is specified eg. dd/MM/yyyyy *

* *

In this case the format attribute will be used.

* *

* Condition 3: With nice attribute as false and no format attribute is specified *

* * * * * * * * * *
i18n keydefault
struts.date.formatif one is not found DateFormat.MEDIUM format will be used
* * * * *

Examples

*
 *  
 *  <s:date name="person.birthday" format="dd/MM/yyyy" />
 *  <s:date name="person.birthday" format="%{getText('some.i18n.key')}" />
 *  <s:date name="person.birthday" nice="true" />
 *  <s:date name="person.birthday" />
 *  
 * 
* * Date * */ @StrutsTag(name="date", tldBodyContent="empty", tldTagClass="org.apache.struts2.views.jsp.DateTag", description="Render a formatted date.") public class Date extends ContextBean { private static final Logger LOG = LogManager.getLogger(Date.class); /** * Property name to fall back when no format is specified */ public static final String DATETAG_PROPERTY = "struts.date.format"; /** * Property name that defines the past notation (default: {0} ago) */ public static final String DATETAG_PROPERTY_PAST = "struts.date.format.past"; private static final String DATETAG_DEFAULT_PAST = "{0} ago"; /** * Property name that defines the future notation (default: in {0}) */ public static final String DATETAG_PROPERTY_FUTURE = "struts.date.format.future"; private static final String DATETAG_DEFAULT_FUTURE = "in {0}"; /** * Property name that defines the seconds notation (default: in instant) */ public static final String DATETAG_PROPERTY_SECONDS = "struts.date.format.seconds"; private static final String DATETAG_DEFAULT_SECONDS = "an instant"; /** * Property name that defines the minutes notation (default: {0,choice,1#one minute|1<{0} minutes}) */ public static final String DATETAG_PROPERTY_MINUTES = "struts.date.format.minutes"; private static final String DATETAG_DEFAULT_MINUTES = "{0,choice,1#one minute|1<{0} minutes}"; /** * Property name that defines the hours notation (default: {0,choice,1#one hour|1<{0} hours}{1,choice,0#|1#, one * minute|1>, {1} minutes}) */ public static final String DATETAG_PROPERTY_HOURS = "struts.date.format.hours"; private static final String DATETAG_DEFAULT_HOURS = "{0,choice,1#one hour|1<{0} hours}{1,choice,0#|1#, one minute|1<, {1} minutes}"; /** * Property name that defines the days notation (default: {0,choice,1#one day|1<{0} days}{1,choice,0#|1#, one hour|1<, * {1} hours}) */ public static final String DATETAG_PROPERTY_DAYS = "struts.date.format.days"; private static final String DATETAG_DEFAULT_DAYS = "{0,choice,1#one day|1<{0} days}{1,choice,0#|1#, one hour|1<, {1} hours}"; /** * Property name that defines the years notation (default: {0,choice,1#one year|1<{0} years}{1,choice,0#|1#, one * day|1>, {1} days}) */ public static final String DATETAG_PROPERTY_YEARS = "struts.date.format.years"; private static final String DATETAG_DEFAULT_YEARS = "{0,choice,1#one year|1<{0} years}{1,choice,0#|1#, one day|1<, {1} days}"; private String name; private String format; private boolean nice; private String timezone; public Date(ValueStack stack) { super(stack); } private TextProvider findProviderInStack() { for (Object o : getStack().getRoot()) { if (o instanceof TextProvider) { return (TextProvider) o; } } return null; } /** * Calculates the difference in time from now to the given date, and outputs it nicely.
An example:
* Now = 2006/03/12 13:38:00, date = 2006/03/12 15:50:00 will output "in 1 hour, 12 minutes". * * @param tp text provider * @param date the date * @return the date nicely */ public String formatTime(TextProvider tp, java.util.Date date) { java.util.Date now = new java.util.Date(); StringBuilder sb = new StringBuilder(); List args = new ArrayList(); long secs = Math.abs((now.getTime() - date.getTime()) / 1000); long mins = secs / 60; long sec = secs % 60; int min = (int) mins % 60; long hours = mins / 60; int hour = (int) hours % 24; int days = (int) hours / 24; int day = days % 365; int years = days / 365; if (years > 0) { args.add(years); args.add(day); args.add(sb); args.add(null); sb.append(tp.getText(DATETAG_PROPERTY_YEARS, DATETAG_DEFAULT_YEARS, args)); } else if (day > 0) { args.add(day); args.add(hour); args.add(sb); args.add(null); sb.append(tp.getText(DATETAG_PROPERTY_DAYS, DATETAG_DEFAULT_DAYS, args)); } else if (hour > 0) { args.add(hour); args.add(min); args.add(sb); args.add(null); sb.append(tp.getText(DATETAG_PROPERTY_HOURS, DATETAG_DEFAULT_HOURS, args)); } else if (min > 0) { args.add(min); args.add(sec); args.add(sb); args.add(null); sb.append(tp.getText(DATETAG_PROPERTY_MINUTES, DATETAG_DEFAULT_MINUTES, args)); } else { args.add(sec); args.add(sb); args.add(null); sb.append(tp.getText(DATETAG_PROPERTY_SECONDS, DATETAG_DEFAULT_SECONDS, args)); } args.clear(); args.add(sb.toString()); if (date.before(now)) { // looks like this date is passed return tp.getText(DATETAG_PROPERTY_PAST, DATETAG_DEFAULT_PAST, args); } else { return tp.getText(DATETAG_PROPERTY_FUTURE, DATETAG_DEFAULT_FUTURE, args); } } public boolean end(Writer writer, String body) { String msg; java.util.Date date = null; // find the name on the valueStack try { //support Calendar also Object dateObject = findValue(name); if (dateObject instanceof java.util.Date) { date = (java.util.Date) dateObject; } else if (dateObject instanceof Calendar) { date = ((Calendar) dateObject).getTime(); } else if (dateObject instanceof Long) { date = new java.util.Date((long) dateObject); } else { if (devMode) { TextProvider tp = findProviderInStack(); String developerNotification = ""; if (tp != null) { developerNotification = findProviderInStack().getText( "devmode.notification", "Developer Notification:\n{0}", new String[]{ "Expression [" + name + "] passed to tag which was evaluated to [" + dateObject + "](" + (dateObject != null ? dateObject.getClass() : "null") + ") isn't instance of java.util.Date nor java.util.Calendar nor long!" } ); } LOG.warn(developerNotification); } else { LOG.debug("Expression [{}] passed to tag which was evaluated to [{}]({}) isn't instance of java.util.Date nor java.util.Calendar nor long!", name, dateObject, (dateObject != null ? dateObject.getClass() : "null")); } } } catch (Exception e) { LOG.error("Could not convert object with key '{}' to a java.util.Date instance", name); } //try to find the format on the stack if (format != null) { format = findString(format); } if (date != null) { TextProvider tp = findProviderInStack(); if (tp != null) { if (nice) { msg = formatTime(tp, date); } else { TimeZone tz = getTimeZone(); if (format == null) { String globalFormat = null; // if the format is not specified, fall back using the // defined property DATETAG_PROPERTY globalFormat = tp.getText(DATETAG_PROPERTY); // if tp.getText can not find the property then the // returned string is the same as input = // DATETAG_PROPERTY if (globalFormat != null && !DATETAG_PROPERTY.equals(globalFormat)) { SimpleDateFormat sdf = new SimpleDateFormat(globalFormat, ActionContext.getContext().getLocale()); sdf.setTimeZone(tz); msg = sdf.format(date); } else { DateFormat df = DateFormat.getDateTimeInstance( DateFormat.MEDIUM, DateFormat.MEDIUM, ActionContext.getContext().getLocale()); df.setTimeZone(tz); msg = df.format(date); } } else { SimpleDateFormat sdf = new SimpleDateFormat(format, ActionContext .getContext().getLocale()); sdf.setTimeZone(tz); msg = sdf.format(date); } } if (msg != null) { try { if (getVar() == null) { writer.write(msg); } else { putInContext(msg); } } catch (IOException e) { LOG.error("Could not write out Date tag", e); } } } } return super.end(writer, ""); } private TimeZone getTimeZone() { TimeZone tz = TimeZone.getDefault(); if (timezone != null) { timezone = stripExpressionIfAltSyntax(timezone); String actualTimezone = (String) getStack().findValue(timezone, String.class); if (actualTimezone != null) { timezone = actualTimezone; } tz = TimeZone.getTimeZone(timezone); } return tz; } @StrutsTagAttribute(description="Date or DateTime format pattern", rtexprvalue=false) public void setFormat(String format) { this.format = format; } @StrutsTagAttribute(description="Whether to print out the date nicely", type="Boolean", defaultValue="false") public void setNice(boolean nice) { this.nice = nice; } @StrutsTagAttribute(description = "The specific timezone in which to format the date", required = false) public void setTimezone(String timezone) { this.timezone = timezone; } /** * @return the name. */ public String getName() { return name; } @StrutsTagAttribute(description="The date value to format", required=true) public void setName(String name) { this.name = name; } /** * @return the format. */ public String getFormat() { return format; } /** * @return the nice. */ public boolean isNice() { return nice; } /** * @return the timezone. */ public String getTimezone() { return timezone; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy