You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by sn...@apache.org on 2006/02/14 05:23:24 UTC

svn commit: r377611 - in /incubator/roller/trunk: src/org/roller/presentation/ src/org/roller/presentation/filters/ src/org/roller/presentation/velocity/ src/org/roller/presentation/weblog/tags/ src/org/roller/util/ web/WEB-INF/classes/

Author: snoopdave
Date: Mon Feb 13 20:23:23 2006
New Revision: 377611

URL: http://svn.apache.org/viewcvs?rev=377611&view=rev
Log:
Fixes ROL-473 (day page should show all entries for day) and ROL-1039 (show 404 instead of exception page)

Modified:
    incubator/roller/trunk/src/org/roller/presentation/RollerRequest.java
    incubator/roller/trunk/src/org/roller/presentation/filters/RefererFilter.java
    incubator/roller/trunk/src/org/roller/presentation/filters/RequestFilter.java
    incubator/roller/trunk/src/org/roller/presentation/velocity/LanguageServlet.java
    incubator/roller/trunk/src/org/roller/presentation/velocity/PageModel.java
    incubator/roller/trunk/src/org/roller/presentation/velocity/PageServlet.java
    incubator/roller/trunk/src/org/roller/presentation/velocity/PreviewServlet.java
    incubator/roller/trunk/src/org/roller/presentation/weblog/tags/WeblogCalendarModel.java
    incubator/roller/trunk/src/org/roller/util/DateUtil.java
    incubator/roller/trunk/web/WEB-INF/classes/ApplicationResources.properties
    incubator/roller/trunk/web/WEB-INF/classes/weblog.vm

Modified: incubator/roller/trunk/src/org/roller/presentation/RollerRequest.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/RollerRequest.java?rev=377611&r1=377610&r2=377611&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/RollerRequest.java (original)
+++ incubator/roller/trunk/src/org/roller/presentation/RollerRequest.java Mon Feb 13 20:23:23 2006
@@ -70,7 +70,9 @@
     private WebsiteData        mWebsite;
     private WeblogEntryData    mWeblogEntry;
     private WeblogCategoryData mWeblogCategory;
-    private boolean            mIsDateSpecified = false;
+    
+    private boolean            mIsDaySpecified = false;
+    private boolean            mIsMonthSpecified = false;
         
     private static ThreadLocal mRollerRequestTLS = new ThreadLocal();
     
@@ -104,7 +106,8 @@
     
     public static final String ROLLER_REQUEST        = "roller_request";
     
-    private SimpleDateFormat mFmt = DateUtil.get8charDateFormat();
+    private SimpleDateFormat m8charDateFormat = DateUtil.get8charDateFormat();
+    private SimpleDateFormat m6charDateFormat = DateUtil.get6charDateFormat();
 
     //----------------------------------------------------------- Constructors
 
@@ -230,7 +233,11 @@
                         // we have the /username/datestring form of URL
                         mDateString = pathInfo[1];
                         mPage = mWebsite.getDefaultPage();
-                        mIsDateSpecified = true;
+                        if (pathInfo[1].length() == 8) {
+                            mIsDaySpecified = true;
+                        } else {
+                            mIsMonthSpecified = true;
+                        }
                     }               
                 }
                 else if ( pathInfo.length == 3 )
@@ -248,17 +255,20 @@
                             mWeblogEntry = weblogMgr.getWeblogEntryByAnchor(
                                 mWebsite, pathInfo[2]);
                         }
-                        catch (Exception damn)
+                        catch (Exception e)
                         {
-                            // doesn't really matter, we've got the Page anyway
-                            mLogger.debug("Damn", damn);
+                            mLogger.debug("Can't find entry by anchor", e);
                         }
                     }
                     else
                     {
                         // we have the /username/pagelink/datestring form of URL
                         mDateString = pathInfo[2];
-                        mIsDateSpecified = true;
+                        if (pathInfo[1].length() == 8) {
+                            mIsDaySpecified = true;
+                        } else {
+                            mIsMonthSpecified = true;
+                        }
                     }
                 }
                 else if ( pathInfo.length == 4 )
@@ -269,7 +279,11 @@
                     
                     mDate = parseDate(pathInfo[2]);
                     mDateString = pathInfo[2];
-                    mIsDateSpecified = true;
+                    if (pathInfo[1].length() == 8) {
+                        mIsDaySpecified = true;
+                    } else {
+                        mIsMonthSpecified = true;
+                    }
 
                     // we have the /username/pagelink/date/anchor form of URL
                     WeblogManager weblogMgr = RollerFactory.getRoller().getWeblogManager();
@@ -280,7 +294,7 @@
             if (mDate == null && mWeblogEntry != null)
             {
                 mDate = mWeblogEntry.getPubTime();
-                mDateString = DateUtil.format8chars(mDate);
+                //mDateString = DateUtil.format8chars(mDate);
             }
         }
         catch ( Exception ignored )
@@ -288,11 +302,12 @@
             mLogger.debug("Exception parsing pathInfo",ignored);
         }
         
-        if ( mWebsite==null || mPage==null )
-        {            
-            String msg = "Invalid pathInfo: "+StringUtils.join(pathInfo,"|");
-            throw new RollerException(msg);
-        }
+        // NOTE: let the caller handle missing website/page instead
+        //if ( mWebsite==null || mPage==null )
+        //{            
+            //String msg = "Invalid pathInfo: "+StringUtils.join(pathInfo,"|");
+            //throw new RollerException(msg);
+        //}
     }       
     
     //------------------------------------------------------------------------
@@ -343,7 +358,7 @@
                 {
                     // we have the /username/datestring form of URL
                     mDateString = daystr;
-                    mIsDateSpecified = true;
+                    mIsDaySpecified = true;
                 }               
             }                  
         }
@@ -452,9 +467,14 @@
     
     //-----------------------------------------------------------------------------
     
-    public boolean isDateSpecified()
+    public boolean isDaySpecified()
+    {
+        return mIsDaySpecified;
+    }    
+    
+    public boolean isMonthSpecified()
     {
-        return mIsDateSpecified;
+        return mIsMonthSpecified;
     }
                 
     //--------------------------------------------------- Date specified by request
@@ -504,20 +524,19 @@
         return todayCal.getTime(); 
     }
 
-    /**
-     * Gets the YYYYMMDD date string specified by the request, or null.
+    /*
+     * Gets the YYYYMMDD or YYYYMM date string specified by the request, or null.
      * @return String
      */
-    public String getDateString()
+    public String getDateString1()
     {
-        return getDateString(false);
+        return mDateString;
     }
 
     /**
      * Gets the date specified by the request
      * @param orToday If no date specified, then use today's date.
-     * @return Date
-     */
+     * @return Date    
     public String getDateString( boolean orToday )
     {
         String ret = null;
@@ -535,10 +554,10 @@
                         this.getWebsite().getLocaleInstance());
             }
             todayCal.setTime( new Date() );
-            ret = mFmt.format(todayCal.getTime());            
+            ret = m8DigitDateFormat.format(todayCal.getTime());            
         }
         return ret;
-    }
+    }*/
     
     //------------------------------------------------------------------------
     /**
@@ -825,7 +844,7 @@
             && StringUtils.isNumeric(dateString) )
         {
             ParsePosition pos = new ParsePosition(0);
-            ret = mFmt.parse( dateString, pos );
+            ret = m8charDateFormat.parse( dateString, pos );
             
             // make sure the requested date is not in the future
             Date today = getToday();
@@ -833,6 +852,20 @@
             
             // since a specific date was requested set time to end of day
             ret = DateUtil.getEndOfDay(ret);
+        } 
+        if (   dateString!=null 
+            && dateString.length()==6
+            && StringUtils.isNumeric(dateString) )
+        {
+            ParsePosition pos = new ParsePosition(0);
+            ret = m6charDateFormat.parse( dateString, pos );
+            
+            // make sure the requested date is not in the future
+            Date today = getToday();
+            if (ret.after(today)) ret = today;
+            
+            // since a specific date was requested set time to end of day
+            ret = DateUtil.getEndOfMonth(ret); 
         }
         return ret;
     }

Modified: incubator/roller/trunk/src/org/roller/presentation/filters/RefererFilter.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/filters/RefererFilter.java?rev=377611&r1=377610&r2=377611&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/filters/RefererFilter.java (original)
+++ incubator/roller/trunk/src/org/roller/presentation/filters/RefererFilter.java Mon Feb 13 20:23:23 2006
@@ -62,13 +62,23 @@
         String requestUrl = request.getRequestURL().toString();
         
         // parse the incoming request and make sure it's a valid page request
+        WebsiteData weblog = null;
         WeblogPageRequest pageRequest = null;
         try {
             pageRequest = new WeblogPageRequest(request);
+            String handle = pageRequest.getWeblogHandle();
+            UserManager userMgr = RollerFactory.getRoller().getUserManager();
+            weblog = userMgr.getWebsiteByHandle(handle);
+      
         } catch(Exception e) {
-            // illegal page request
-            response.sendError(HttpServletResponse.SC_NOT_FOUND);
-            mLogger.debug("Illegal page request: "+request.getRequestURL());
+            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            mLogger.warn("ERROR processing request: "+request.getRequestURL());
+            return;
+        }
+        
+        // ReferrerManager only cares about weblog referrers
+        if (weblog == null) {             
+            chain.doFilter(req, res);
             return;
         }
         
@@ -83,13 +93,12 @@
         
         // validate the referrer
         if (pageRequest != null && pageRequest.getWeblogHandle() != null && !isRobot) {
-            String handle = pageRequest.getWeblogHandle();
             
             RollerContext rctx = RollerContext.getRollerContext();
             
             // Base page URLs, with and without www.
             String basePageUrlWWW =
-                    rctx.getAbsoluteContextUrl(request)+"/page/"+handle;
+                    rctx.getAbsoluteContextUrl(request)+"/page/"+weblog.getHandle();
             String basePageUrl = basePageUrlWWW;
             if ( basePageUrlWWW.startsWith("http://www.") ) {
                 // chop off the http://www.
@@ -101,24 +110,8 @@
                     (!referrerUrl.startsWith(basePageUrl) &&
                     !referrerUrl.startsWith(basePageUrlWWW))) {
                 
-                String selfSiteFragment = "/page/"+handle;
-                WebsiteData weblog = null;
-                
-                // lookup the weblog now
-                try {
-                    UserManager userMgr = RollerFactory.getRoller().getUserManager();
-                    weblog = userMgr.getWebsiteByHandle(handle);
-                    
-                    if(weblog == null) {
-                        throw new RollerException("invalid website: "+handle);
-                    }
-                } catch(Exception e) {
-                    // if we can't get the WebsiteData object we can't continue
-                    response.sendError(HttpServletResponse.SC_NOT_FOUND);
-                    mLogger.error("Unable to retrieve weblog: "+handle);
-                    return;
-                }
-                
+                String selfSiteFragment = "/page/"+weblog.getHandle();
+
                 // validate the referrer
                 if ( referrerUrl != null ) {
                     // ignore a Referrer from the persons own blog

Modified: incubator/roller/trunk/src/org/roller/presentation/filters/RequestFilter.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/filters/RequestFilter.java?rev=377611&r1=377610&r2=377611&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/filters/RequestFilter.java (original)
+++ incubator/roller/trunk/src/org/roller/presentation/filters/RequestFilter.java Mon Feb 13 20:23:23 2006
@@ -40,22 +40,15 @@
 public class RequestFilter implements Filter {
     private FilterConfig mFilterConfig = null;
     private static Log mLogger =
-            LogFactory.getFactory().getInstance(RequestFilter.class);
+        LogFactory.getFactory().getInstance(RequestFilter.class);
     
-    /**
-     * destroy
-     */
-    public void destroy() {
-    }
-    
-    /**
-     * Request filter.
-     */
     public void doFilter(
             ServletRequest req, ServletResponse res, FilterChain chain)
             throws IOException, ServletException {
+        
         // NOTE: Setting character encoding and JSTL/Struts locale sync has been
         // moved to CharEncodingFilter, which is mapped for all URIs in the context.
+        
         HttpSession session = ((HttpServletRequest)req).getSession();
         HttpServletRequest request = (HttpServletRequest)req;
         HttpServletResponse response = (HttpServletResponse)res;
@@ -63,27 +56,21 @@
         RollerRequest rreq = null;
         try {
             rreq = RollerRequest.getRollerRequest(
-                    request, mFilterConfig.getServletContext());
-        } catch (Throwable e) {
-            // An error initializing the request is considered to be a 404
-            response.sendError(
-                    HttpServletResponse.SC_NOT_FOUND,
-                    "Page not found or error parsing requested URL");
-            
-            // make sure any filters earlier in the chain know that we had
-            // an exception happen
-            request.setAttribute("DisplayException", e);
-            
+                       request, mFilterConfig.getServletContext());
+        } catch (Throwable e) {            
+            // NOTE: this is not a page-not-found problem
+            request.setAttribute("DisplayException", e);            
+            mLogger.error(e);
             return;
         }
         chain.doFilter(req, res);
     }
     
-    /**
-     * init
-     */
     public void init(FilterConfig filterConfig) throws ServletException {
         mFilterConfig = filterConfig;
+    }
+    
+    public void destroy() {
     }
 }
 

Modified: incubator/roller/trunk/src/org/roller/presentation/velocity/LanguageServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/velocity/LanguageServlet.java?rev=377611&r1=377610&r2=377611&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/velocity/LanguageServlet.java (original)
+++ incubator/roller/trunk/src/org/roller/presentation/velocity/LanguageServlet.java Mon Feb 13 20:23:23 2006
@@ -73,7 +73,7 @@
     public Template handleRequest(HttpServletRequest request,
                                 HttpServletResponse response,
                                 Context ctx) 
-            throws IOException {
+            throws Exception {
         
         mLogger.debug("Processing language change...");
         ServletContext servletContext = RollerContext.getServletContext();

Modified: incubator/roller/trunk/src/org/roller/presentation/velocity/PageModel.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/velocity/PageModel.java?rev=377611&r1=377610&r2=377611&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/velocity/PageModel.java (original)
+++ incubator/roller/trunk/src/org/roller/presentation/velocity/PageModel.java Mon Feb 13 20:23:23 2006
@@ -295,24 +295,24 @@
      * <li></li>
      * </ul>
      *
-     * @param maxEntries Maximum number of entries to be returned.
-     * @param categoryName Only return entries from this category and it's
-     *         subcategories. If null, returns all categories of entry.
-     * @return Map of Lists of WeblogEntryData, keyed by 8-char date strings.
+     * @param maxEntries Maximum number of entries to be returned (only applies 
+     *                   if specific day not specified).
+     * @param catName    Only return entries from this category and it's
+     *                   subcategories. If null, returns all categories of entry
+     * @return           Map of Lists of WeblogEntryData, keyed by 8-char date 
+     *                   strings.
      */
-    public Map getRecentWeblogEntries(int maxEntries, String categoryName) {
-        if (VELOCITY_NULL.equals(categoryName)) categoryName = null;
+    public Map getRecentWeblogEntries(int maxEntries, String catName) {
+        if (VELOCITY_NULL.equals(catName)) catName = null;
         Map ret = new HashMap();
-        try {
-
-            
+        try {            
             // If request specifies a category, then use that
             String catParam = null;
             if (mRollerReq.getWeblogCategory() != null) {
                 catParam = mRollerReq.getWeblogCategory().getPath();
-            } else if (categoryName != null) {
+            } else if (catName != null) {
                 // use category argument instead
-                catParam = categoryName;
+                catParam = catName;
             } else if (mRollerReq.getWebsite() != null) // MAIN
             {
                 catParam = mRollerReq.getWebsite().getDefaultCategory().getPath();
@@ -325,13 +325,15 @@
             Date startDate = null;
             Date endDate = mRollerReq.getDate();
             if (endDate == null) endDate = new Date();
-            if (mRollerReq.isDateSpecified()) { 
+            if (mRollerReq.isDaySpecified()) { 
                 // URL specified a specific day
                 // so get entries for that day
                 endDate = DateUtil.getEndOfDay(endDate);
                 startDate = DateUtil.getStartOfDay(endDate); 
                 // and get them ALL, no limit
                 limit = null;                  
+            } else if (mRollerReq.isMonthSpecified()) {
+                endDate = DateUtil.getEndOfDay(endDate);
             }
             Map mRet = RollerFactory.getRoller().getWeblogManager().getWeblogEntryObjectMap(
                     mRollerReq.getWebsite(),

Modified: incubator/roller/trunk/src/org/roller/presentation/velocity/PageServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/velocity/PageServlet.java?rev=377611&r1=377610&r2=377611&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/velocity/PageServlet.java (original)
+++ incubator/roller/trunk/src/org/roller/presentation/velocity/PageServlet.java Mon Feb 13 20:23:23 2006
@@ -63,28 +63,28 @@
     public Template handleRequest(HttpServletRequest request,
                                 HttpServletResponse response, 
                                 Context ctx) 
-            throws IOException {
+        throws Exception {
         
         Template outty = null;
         RollerRequest rreq = null;
         WebsiteData website = null;
         
+        PageContext pageContext =
+            JspFactory.getDefaultFactory().getPageContext(
+            this, request, response,"", true, 8192, true);
+
         // first off lets parse the incoming request and validate it
         try {
-            PageContext pageContext =
-                    JspFactory.getDefaultFactory().getPageContext(
-                    this, request, response,"", true, 8192, true);
             rreq = RollerRequest.getRollerRequest(pageContext);
-            
-            // make sure the website is valid
-            website = rreq.getWebsite();
-            if(website == null)
-                throw new InvalidRequestException("invalid weblog");
-        } catch (Throwable e) {
-            // An error initializing the request is considered to be a 404
+        } catch (Throwable t) {
+            // NOTE: indicates real problem, not just a "not found" error
+            throw new Exception("ERROR: creating RollerRequest");
+        }
+
+        // All pages exist within website, so website MUST be specified
+        website = rreq.getWebsite();
+        if (website == null) {
             response.sendError(HttpServletResponse.SC_NOT_FOUND);
-            request.setAttribute("DisplayException", e);
-            mLogger.debug("ERROR initializing RollerRequest",e);
             return null;
         }
                
@@ -164,7 +164,7 @@
                                             HttpServletResponse response,
                                             org.roller.pojos.Template page) 
             
-            throws ResourceNotFoundException, RollerException {
+         throws ResourceNotFoundException, RollerException {
         
         Template outty = null;
         

Modified: incubator/roller/trunk/src/org/roller/presentation/velocity/PreviewServlet.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/velocity/PreviewServlet.java?rev=377611&r1=377610&r2=377611&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/velocity/PreviewServlet.java (original)
+++ incubator/roller/trunk/src/org/roller/presentation/velocity/PreviewServlet.java Mon Feb 13 20:23:23 2006
@@ -41,7 +41,7 @@
     public Template handleRequest( HttpServletRequest request,
                                 HttpServletResponse response,
                                 Context ctx ) 
-            throws IOException {
+            throws Exception {
         
         Theme previewTheme = null;
         

Modified: incubator/roller/trunk/src/org/roller/presentation/weblog/tags/WeblogCalendarModel.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/presentation/weblog/tags/WeblogCalendarModel.java?rev=377611&r1=377610&r2=377611&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/presentation/weblog/tags/WeblogCalendarModel.java (original)
+++ incubator/roller/trunk/src/org/roller/presentation/weblog/tags/WeblogCalendarModel.java Mon Feb 13 20:23:23 2006
@@ -254,19 +254,23 @@
         Calendar nextCal = getCalendar();
         nextCal.setTime( mDay );
         nextCal.add( Calendar.MONTH, 1 );
-        Date nextMonth = getLastDayOfMonth(nextCal).getTime();
-        String nextMonthUrl = computeUrl(nextMonth, true);            
-        return nextMonthUrl;
+        String nextMonth = computeUrl(nextCal.getTime(), true);            
+        
+        // and strip off last two digits to get a month URL
+        return nextMonth.substring(0, nextMonth.length() - 2);
     }
 
     public String computePrevMonthUrl()
     {
+        // Create yyyyMMdd dates for prev month, prev month and today 
         Calendar prevCal = getCalendar();
         prevCal.setTime( mDay );
         prevCal.add( Calendar.MONTH, -1 );
-        getLastDayOfMonth( prevCal );
+        //getLastDayOfMonth( prevCal );
         String prevMonth = computeUrl(prevCal.getTime(),true);
-        return prevMonth;
+        
+        // and strip off last two digits to get a month URL
+        return prevMonth.substring(0, prevMonth.length() - 2);
     }
 
     public String computeTodayMonthUrl()

Modified: incubator/roller/trunk/src/org/roller/util/DateUtil.java
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/src/org/roller/util/DateUtil.java?rev=377611&r1=377610&r2=377611&view=diff
==============================================================================
--- incubator/roller/trunk/src/org/roller/util/DateUtil.java (original)
+++ incubator/roller/trunk/src/org/roller/util/DateUtil.java Mon Feb 13 20:23:23 2006
@@ -1 +1 @@
-package org.roller.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * General purpose date utilities.
 * @author Mark Saarinen
 * @author Lance Lavandowska
 */
public abstract class DateUtil extends Object
{
    public static final long millisInDay = 86400000;

    // some static date formats
    private static SimpleDateFormat[] mDateFormats = loadDateFormats();
    
    private static final SimpleDateFormat mFormat8chars = 
        new SimpleDateFormat("yyyyMMdd");

    private static final SimpleDateFormat mFormatIso8601Day = 
        new SimpleDateFormat("yyyy-MM-dd");

    private static final SimpleDateFormat mFormatIso8601 = 
        new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
    
    // http://www.w3.org/Protocols/rfc822/Overview.html#z28
    // Using Locale.US to fix ROL-725 and ROL-628
    private static final SimpleDateFormat mFormatRfc822 = 
        new
  SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.US); 

    
    private static SimpleDateFormat[] loadDateFormats()
    {
        SimpleDateFormat[] temp = {
            //new SimpleDateFormat("MM/dd/yyyy hh:mm:ss.SSS a"),
            new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy"), // standard Date.toString() results
            new SimpleDateFormat("M/d/yy hh:mm:ss"),
            new SimpleDateFormat("M/d/yyyy hh:mm:ss"),
            new SimpleDateFormat("M/d/yy hh:mm a"),
            new SimpleDateFormat("M/d/yyyy hh:mm a"),
            new SimpleDateFormat("M/d/yy HH:mm"),
            new SimpleDateFormat("M/d/yyyy HH:mm"),
            new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"),
            new SimpleDateFormat("yy-MM-dd HH:mm:ss.SSS"),
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"), // standard Timestamp.toString() results
            new SimpleDateFormat("M-d-yy HH:mm"),
            new SimpleDateFormat("M-d-yyyy HH:mm"),
            new SimpleDa
 teFormat("MM/dd/yyyy HH:mm:ss.SSS"),
            new SimpleDateFormat("M/d/yy"),
            new SimpleDateFormat("M/d/yyyy"),
            new SimpleDateFormat("M-d-yy"),
            new SimpleDateFormat("M-d-yyyy"),
            new SimpleDateFormat("MMMM d, yyyyy"),
            new SimpleDateFormat("MMM d, yyyyy")
        };
    
        return temp;
    }
    //-----------------------------------------------------------------------
    /**
     * Gets the array of SimpleDateFormats that DateUtil knows about.
    **/
    private static SimpleDateFormat[] getFormats()
    {
        return mDateFormats;
    }

	//-----------------------------------------------------------------------
	/**
	 * Returns a Date set to the last possible millisecond of the day, just
	 * before midnight. If a null day is passed in, a new Date is created.
	 * midnight (00m 00h 00s)
	 */
	public static Date getEndOfDay(Date day)
	{
		return getEndOfDay(day,Calendar.getInstance());
	}
	public static Da
 te getEndOfDay(Date day,Calendar cal)
	{
		if (day == null) day = new Date();
		cal.setTime(day);
		cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
		cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
		cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
        return cal.getTime();
	}

    //-----------------------------------------------------------------------
	/**
	 * Returns a Date set to the first possible millisecond of the day, just
	 * after midnight. If a null day is passed in, a new Date is created.
	 * midnight (00m 00h 00s)
	 */
	public static Date getStartOfDay(Date day)
	{
		return getStartOfDay(day, Calendar.getInstance());
	}
	/**
	 * Returns a Date set to the first possible millisecond of the day, just
	 * after midnight. If a null day is passed in, a new Date is created.
	 * midnight (00m 00h 00s)
	 */
	public static Date getStartOfDay(Date
  day, Calendar cal)
	{
		if (day == null) day = new Date();
		cal.setTime(day);
		cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
		cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
		cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
        return cal.getTime();
	}

    /**
     * Returns a Date set just to Noon, to the closest possible millisecond
     * of the day. If a null day is passed in, a new Date is created.
     * nnoon (00m 12h 00s)
     */
    public static Date getNoonOfDay(Date day, Calendar cal)
    {
        if (day == null) day = new Date();
        cal.setTime(day);
        cal.set(Calendar.HOUR_OF_DAY, 12);
        cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
        retur
 n cal.getTime();
    }
    
    //-----------------------------------------------------------------------
    public static Date parseFromFormats(String aValue)
    {
        if (StringUtils.isEmpty(aValue)) return null;

        // get DateUtil's formats
        SimpleDateFormat formats[] = DateUtil.getFormats();
        if (formats == null) return null;

        // iterate over the array and parse
        Date myDate = null;
        for (int i = 0; i <formats.length; i++)
        {
            try
            {
                myDate = DateUtil.parse(aValue, formats[i]);
                //if (myDate instanceof Date) 
                return myDate;
            }
            catch (Exception e)
            {
                // do nothing because we want to try the next
                // format if current one fails
            }
       }
       // haven't returned so couldn't parse
       return null;
    }

    //-------------------------------------------------------------
 ----------
    public static java.sql.Timestamp parseTimestampFromFormats(String aValue)
    {
        if (StringUtils.isEmpty(aValue)) return null;

        // call the regular Date formatter
        Date myDate = DateUtil.parseFromFormats(aValue);
        if (myDate != null) return new java.sql.Timestamp(myDate.getTime());
        return null;
    }
    //-----------------------------------------------------------------------
    /**
     * Returns a java.sql.Timestamp equal to the current time
    **/
    public static java.sql.Timestamp now()
    {
        return new java.sql.Timestamp(new java.util.Date().getTime());
    }

    //-----------------------------------------------------------------------
    /**
     * Returns a string the represents the passed-in date parsed
     * according to the passed-in format.  Returns an empty string
     * if the date or the format is null.
    **/
    public static String format(Date aDate, SimpleDateFormat aFormat)
    {
        
 if (aDate == null || aFormat == null ) { return ""; }
        synchronized (aFormat) 
        {
            return aFormat.format(aDate);
        }
    }

    //-----------------------------------------------------------------------
    /**
     * Tries to take the passed-in String and format it as a date string in the
     * the passed-in format.
    **/
    public static String formatDateString(String aString, SimpleDateFormat aFormat)
    {
        if (StringUtils.isEmpty(aString) || aFormat == null)  return "";
        try
        {
            java.sql.Timestamp aDate = parseTimestampFromFormats(aString);
            if (aDate != null)
            {
                return DateUtil.format(aDate, aFormat);
            }
        }
        catch (Exception e)
        {
            // Could not parse aString.
        }
        return "";
    }

    //-----------------------------------------------------------------------
    /**
     * Returns a Date using the passed-in stri
 ng and format.  Returns null if the string
     * is null or empty or if the format is null.  The string must match the format.
    **/
    public static Date parse(String aValue, SimpleDateFormat aFormat) throws ParseException
    {
        if (StringUtils.isEmpty(aValue) || aFormat == null)
        {
            return null;
        }

        return aFormat.parse(aValue);
    }

    //-----------------------------------------------------------------------
    /**
     * Returns true if endDate is after startDate or if startDate equals endDate
     * or if they are the same date.  Returns false if either value is null.
    **/
    public static boolean isValidDateRange(Date startDate, Date endDate)
    {
        return isValidDateRange(startDate, endDate, true);
    }

    //-----------------------------------------------------------------------
    /**
     * Returns true if endDate is after startDate or if startDate equals endDate.
     * Returns false if either value is
  null.  If equalOK, returns true if the
     * dates are equal.
    **/
    public static boolean isValidDateRange(Date startDate, Date endDate, boolean equalOK)
    {
        // false if either value is null
        if (startDate == null || endDate == null) { return false; }

        if (equalOK)
        {
            // true if they are equal
            if (startDate.equals(endDate)) { return true; }
        }

        // true if endDate after startDate
        if (endDate.after(startDate)) { return true; }

        return false;
    }

    //-----------------------------------------------------------------------
    // returns full timestamp format
    public static java.text.SimpleDateFormat defaultTimestampFormat()
    {
        return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    }

    //-----------------------------------------------------------------------
    // convenience method returns minimal date format
    public static java.text.SimpleDateF
 ormat get8charDateFormat()
    {
        return DateUtil.mFormat8chars;
    }

    //-----------------------------------------------------------------------
    // convenience method returns minimal date format
    public static java.text.SimpleDateFormat defaultDateFormat()
    {
        return DateUtil.friendlyDateFormat(true);
    }

    //-----------------------------------------------------------------------
    // convenience method
    public static String defaultTimestamp(Date date)
    {
        return DateUtil.format(date, DateUtil.defaultTimestampFormat());
    }
    
    //-----------------------------------------------------------------------
    // convenience method
    public static String defaultDate(Date date)
    {
        return DateUtil.format(date, DateUtil.defaultDateFormat());
    }

    //-----------------------------------------------------------------------
    // convenience method returns long friendly timestamp format
    public static java.text
 .SimpleDateFormat friendlyTimestampFormat()
    {
        return new java.text.SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
    }

    //-----------------------------------------------------------------------
    // convenience method returns long friendly formatted timestamp
    public static String friendlyTimestamp(Date date)
    {
        return DateUtil.format(date, DateUtil.friendlyTimestampFormat());
    }

    //-----------------------------------------------------------------------
    // convenience method returns long friendly formatted timestamp
    public static String format8chars(Date date)
    {
        return DateUtil.format(date, mFormat8chars);
    }

    //-----------------------------------------------------------------------
    // convenience method returns long friendly formatted timestamp
    public static String formatIso8601Day(Date date)
    {
        return DateUtil.format(date, mFormatIso8601Day);
    }

    //---------------------------------------
 --------------------------------
    public static String formatRfc822(Date date)
    {
        return DateUtil.format(date,mFormatRfc822);
    }

    //-----------------------------------------------------------------------
    // This is a hack, but it seems to work
    public static String formatIso8601(Date date)
    {
        if (date == null) return "";
        
        // Add a colon 2 chars before the end of the string
        // to make it a valid ISO-8601 date.
         
        String str = DateUtil.format(date,mFormatIso8601);
        StringBuffer sb = new StringBuffer();
        sb.append( str.substring(0,str.length()-2) );
        sb.append( ":" );
        sb.append( str.substring(str.length()-2) );
        return sb.toString();
    }

    //-----------------------------------------------------------------------
    // convenience method returns minimal date format
    public static java.text.SimpleDateFormat minimalDateFormat()
    {
        return DateUtil.fr
 iendlyDateFormat(true);
    }

    //-----------------------------------------------------------------------
    // convenience method using minimal date format
    public static String minimalDate(Date date)
    {
        return DateUtil.format(date, DateUtil.minimalDateFormat());
    }

    //-----------------------------------------------------------------------
    // convenience method that returns friendly data format
    // using full month, day, year digits.
    public static java.text.SimpleDateFormat fullDateFormat()
    {
        return DateUtil.friendlyDateFormat(false);
    }

    //-----------------------------------------------------------------------
    public static String fullDate(Date date)
    {
        return DateUtil.format(date, DateUtil.fullDateFormat());
    }

    //-----------------------------------------------------------------------
    /** Returns a "friendly" date format.
     *  @param mimimalFormat Should the date format allow single digits
 .
    **/
    public static java.text.SimpleDateFormat friendlyDateFormat(boolean minimalFormat)
    {
        if (minimalFormat)
        {
            return new java.text.SimpleDateFormat("d.M.yy");
        }

        return new java.text.SimpleDateFormat("dd.MM.yyyy");
    }

    //-----------------------------------------------------------------------
    /**
     * Format the date using the "friendly" date format.
     */
    public static String friendlyDate(Date date, boolean minimalFormat)
    {
        return DateUtil.format(date, DateUtil.friendlyDateFormat(minimalFormat));
    }

    //-----------------------------------------------------------------------
    // convenience method
    public static String friendlyDate(Date date)
    {
        return DateUtil.format(date, DateUtil.friendlyDateFormat(true));
    }
    
    public static Date parseIso8601(String value) throws Exception
    {
        return ISO8601DateParser.parse(value);
    }


}
\ No newline at end of file
+package org.roller.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * General purpose date utilities.
 * @author Mark Saarinen
 * @author Lance Lavandowska
 */
public abstract class DateUtil extends Object
{
    public static final long millisInDay = 86400000;

    // some static date formats
    private static SimpleDateFormat[] mDateFormats = loadDateFormats();
    
    private static final SimpleDateFormat mFormat8chars = 
        new SimpleDateFormat("yyyyMMdd");

    private static final SimpleDateFormat mFormat6chars = 
        new SimpleDateFormat("yyyyMM");

    private static final SimpleDateFormat mFormatIso8601Day = 
        new SimpleDateFormat("yyyy-MM-dd");

    private static final SimpleDateFormat mFormatIso8601 = 
        new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
    
    // http://www.w3.org/Protocols/rfc822/Overview.html#z28
    // Using Locale.
 US to fix ROL-725 and ROL-628
    private static final SimpleDateFormat mFormatRfc822 = 
        new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.US); 

    
    private static SimpleDateFormat[] loadDateFormats()
    {
        SimpleDateFormat[] temp = {
            //new SimpleDateFormat("MM/dd/yyyy hh:mm:ss.SSS a"),
            new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy"), // standard Date.toString() results
            new SimpleDateFormat("M/d/yy hh:mm:ss"),
            new SimpleDateFormat("M/d/yyyy hh:mm:ss"),
            new SimpleDateFormat("M/d/yy hh:mm a"),
            new SimpleDateFormat("M/d/yyyy hh:mm a"),
            new SimpleDateFormat("M/d/yy HH:mm"),
            new SimpleDateFormat("M/d/yyyy HH:mm"),
            new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"),
            new SimpleDateFormat("yy-MM-dd HH:mm:ss.SSS"),
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"), // standard Timestamp.toString() results
            new SimpleDate
 Format("M-d-yy HH:mm"),
            new SimpleDateFormat("M-d-yyyy HH:mm"),
            new SimpleDateFormat("MM/dd/yyyy HH:mm:ss.SSS"),
            new SimpleDateFormat("M/d/yy"),
            new SimpleDateFormat("M/d/yyyy"),
            new SimpleDateFormat("M-d-yy"),
            new SimpleDateFormat("M-d-yyyy"),
            new SimpleDateFormat("MMMM d, yyyyy"),
            new SimpleDateFormat("MMM d, yyyyy")
        };
    
        return temp;
    }
    //-----------------------------------------------------------------------
    /**
     * Gets the array of SimpleDateFormats that DateUtil knows about.
    **/
    private static SimpleDateFormat[] getFormats()
    {
        return mDateFormats;
    }

	//-----------------------------------------------------------------------
	/**
	 * Returns a Date set to the last possible millisecond of the day, just
	 * before midnight. If a null day is passed in, a new Date is created.
	 * midnight (00m 00h 00s)
	 */
	public static 
 Date getEndOfDay(Date day)
	{
		return getEndOfDay(day,Calendar.getInstance());
	}
	public static Date getEndOfDay(Date day,Calendar cal)
	{
		if (day == null) day = new Date();
		cal.setTime(day);
		cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
		cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
		cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
        return cal.getTime();
	}	

    //-----------------------------------------------------------------------
	/**
	 * Returns a Date set to the last possible millisecond of the day, just
	 * before midnight. If a null day is passed in, a new Date is created.
	 * midnight (00m 00h 00s)
	 */
	public static Date getEndOfMonth(Date day)
	{
		return getEndOfMonth(day,Calendar.getInstance());
	}
	public static Date getEndOfMonth(Date day,Calendar cal)
	{
		if (day == null) day = new Date();
		cal.setTime(day);
   
      
        // set time to end of day
		cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE,      cal.getMaximum(Calendar.MINUTE));
		cal.set(Calendar.SECOND,      cal.getMaximum(Calendar.SECOND));
		cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
        
        // set time to first day of month
        cal.set(Calendar.DAY_OF_MONTH, 1);
        
        // add one month
        cal.add(Calendar.MONTH, 1);
        
        // back up one day
        cal.add(Calendar.DAY_OF_MONTH, -1);
        
        return cal.getTime();
	}

    //-----------------------------------------------------------------------
	/**
	 * Returns a Date set to the first possible millisecond of the day, just
	 * after midnight. If a null day is passed in, a new Date is created.
	 * midnight (00m 00h 00s)
	 */
	public static Date getStartOfDay(Date day)
	{
		return getStartOfDay(day, Calendar.getInstance());
	}
	/**
	 * Returns a Date s
 et to the first possible millisecond of the day, just
	 * after midnight. If a null day is passed in, a new Date is created.
	 * midnight (00m 00h 00s)
	 */
	public static Date getStartOfDay(Date day, Calendar cal)
	{
		if (day == null) day = new Date();
		cal.setTime(day);
		cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE,      cal.getMinimum(Calendar.MINUTE));
		cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
		cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
        return cal.getTime();
	}

    /**
     * Returns a Date set just to Noon, to the closest possible millisecond
     * of the day. If a null day is passed in, a new Date is created.
     * nnoon (00m 12h 00s)
     */
    public static Date getNoonOfDay(Date day, Calendar cal)
    {
        if (day == null) day = new Date();
        cal.setTime(day);
        cal.set(Calendar.HOUR_OF_DAY, 12);
        cal.set(Calendar.MINUTE,      c
 al.getMinimum(Calendar.MINUTE));
        cal.set(Calendar.SECOND,      cal.getMinimum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
        return cal.getTime();
    }
    
    //-----------------------------------------------------------------------
    public static Date parseFromFormats(String aValue)
    {
        if (StringUtils.isEmpty(aValue)) return null;

        // get DateUtil's formats
        SimpleDateFormat formats[] = DateUtil.getFormats();
        if (formats == null) return null;

        // iterate over the array and parse
        Date myDate = null;
        for (int i = 0; i <formats.length; i++)
        {
            try
            {
                myDate = DateUtil.parse(aValue, formats[i]);
                //if (myDate instanceof Date) 
                return myDate;
            }
            catch (Exception e)
            {
                // do nothing because we want to try the next
              
   // format if current one fails
            }
       }
       // haven't returned so couldn't parse
       return null;
    }

    //-----------------------------------------------------------------------
    public static java.sql.Timestamp parseTimestampFromFormats(String aValue)
    {
        if (StringUtils.isEmpty(aValue)) return null;

        // call the regular Date formatter
        Date myDate = DateUtil.parseFromFormats(aValue);
        if (myDate != null) return new java.sql.Timestamp(myDate.getTime());
        return null;
    }
    //-----------------------------------------------------------------------
    /**
     * Returns a java.sql.Timestamp equal to the current time
    **/
    public static java.sql.Timestamp now()
    {
        return new java.sql.Timestamp(new java.util.Date().getTime());
    }

    //-----------------------------------------------------------------------
    /**
     * Returns a string the represents the passed-in date parsed
     *
  according to the passed-in format.  Returns an empty string
     * if the date or the format is null.
    **/
    public static String format(Date aDate, SimpleDateFormat aFormat)
    {
        if (aDate == null || aFormat == null ) { return ""; }
        synchronized (aFormat) 
        {
            return aFormat.format(aDate);
        }
    }

    //-----------------------------------------------------------------------
    /**
     * Tries to take the passed-in String and format it as a date string in the
     * the passed-in format.
    **/
    public static String formatDateString(String aString, SimpleDateFormat aFormat)
    {
        if (StringUtils.isEmpty(aString) || aFormat == null)  return "";
        try
        {
            java.sql.Timestamp aDate = parseTimestampFromFormats(aString);
            if (aDate != null)
            {
                return DateUtil.format(aDate, aFormat);
            }
        }
        catch (Exception e)
        {
            /
 / Could not parse aString.
        }
        return "";
    }

    //-----------------------------------------------------------------------
    /**
     * Returns a Date using the passed-in string and format.  Returns null if the string
     * is null or empty or if the format is null.  The string must match the format.
    **/
    public static Date parse(String aValue, SimpleDateFormat aFormat) throws ParseException
    {
        if (StringUtils.isEmpty(aValue) || aFormat == null)
        {
            return null;
        }

        return aFormat.parse(aValue);
    }

    //-----------------------------------------------------------------------
    /**
     * Returns true if endDate is after startDate or if startDate equals endDate
     * or if they are the same date.  Returns false if either value is null.
    **/
    public static boolean isValidDateRange(Date startDate, Date endDate)
    {
        return isValidDateRange(startDate, endDate, true);
    }

    //------
 -----------------------------------------------------------------
    /**
     * Returns true if endDate is after startDate or if startDate equals endDate.
     * Returns false if either value is null.  If equalOK, returns true if the
     * dates are equal.
    **/
    public static boolean isValidDateRange(Date startDate, Date endDate, boolean equalOK)
    {
        // false if either value is null
        if (startDate == null || endDate == null) { return false; }

        if (equalOK)
        {
            // true if they are equal
            if (startDate.equals(endDate)) { return true; }
        }

        // true if endDate after startDate
        if (endDate.after(startDate)) { return true; }

        return false;
    }

    //-----------------------------------------------------------------------
    // returns full timestamp format
    public static java.text.SimpleDateFormat defaultTimestampFormat()
    {
        return new java.text.SimpleDateFormat("yyyy-MM-dd
  HH:mm:ss.SSS");
    }

    //-----------------------------------------------------------------------
    // convenience method returns minimal date format
    public static java.text.SimpleDateFormat get8charDateFormat()
    {
        return DateUtil.mFormat8chars;
    }   
    
    // convenience method returns minimal date format
    public static java.text.SimpleDateFormat get6charDateFormat()
    {
        return DateUtil.mFormat6chars;
    }

    //-----------------------------------------------------------------------
    // convenience method returns minimal date format
    public static java.text.SimpleDateFormat defaultDateFormat()
    {
        return DateUtil.friendlyDateFormat(true);
    }

    //-----------------------------------------------------------------------
    // convenience method
    public static String defaultTimestamp(Date date)
    {
        return DateUtil.format(date, DateUtil.defaultTimestampFormat());
    }
    
    //-----------------------
 ------------------------------------------------
    // convenience method
    public static String defaultDate(Date date)
    {
        return DateUtil.format(date, DateUtil.defaultDateFormat());
    }

    //-----------------------------------------------------------------------
    // convenience method returns long friendly timestamp format
    public static java.text.SimpleDateFormat friendlyTimestampFormat()
    {
        return new java.text.SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
    }

    //-----------------------------------------------------------------------
    // convenience method returns long friendly formatted timestamp
    public static String friendlyTimestamp(Date date)
    {
        return DateUtil.format(date, DateUtil.friendlyTimestampFormat());
    }

    //-----------------------------------------------------------------------
    // convenience method returns long friendly formatted timestamp
    public static String format8chars(Date date)
    {
         return DateUtil.format(date, mFormat8chars);
    }

    //-----------------------------------------------------------------------
    // convenience method returns long friendly formatted timestamp
    public static String formatIso8601Day(Date date)
    {
        return DateUtil.format(date, mFormatIso8601Day);
    }

    //-----------------------------------------------------------------------
    public static String formatRfc822(Date date)
    {
        return DateUtil.format(date,mFormatRfc822);
    }

    //-----------------------------------------------------------------------
    // This is a hack, but it seems to work
    public static String formatIso8601(Date date)
    {
        if (date == null) return "";
        
        // Add a colon 2 chars before the end of the string
        // to make it a valid ISO-8601 date.
         
        String str = DateUtil.format(date,mFormatIso8601);
        StringBuffer sb = new StringBuffer();
        sb.append( str.s
 ubstring(0,str.length()-2) );
        sb.append( ":" );
        sb.append( str.substring(str.length()-2) );
        return sb.toString();
    }

    //-----------------------------------------------------------------------
    // convenience method returns minimal date format
    public static java.text.SimpleDateFormat minimalDateFormat()
    {
        return DateUtil.friendlyDateFormat(true);
    }

    //-----------------------------------------------------------------------
    // convenience method using minimal date format
    public static String minimalDate(Date date)
    {
        return DateUtil.format(date, DateUtil.minimalDateFormat());
    }

    //-----------------------------------------------------------------------
    // convenience method that returns friendly data format
    // using full month, day, year digits.
    public static java.text.SimpleDateFormat fullDateFormat()
    {
        return DateUtil.friendlyDateFormat(false);
    }

    //------------
 -----------------------------------------------------------
    public static String fullDate(Date date)
    {
        return DateUtil.format(date, DateUtil.fullDateFormat());
    }

    //-----------------------------------------------------------------------
    /** Returns a "friendly" date format.
     *  @param mimimalFormat Should the date format allow single digits.
    **/
    public static java.text.SimpleDateFormat friendlyDateFormat(boolean minimalFormat)
    {
        if (minimalFormat)
        {
            return new java.text.SimpleDateFormat("d.M.yy");
        }

        return new java.text.SimpleDateFormat("dd.MM.yyyy");
    }

    //-----------------------------------------------------------------------
    /**
     * Format the date using the "friendly" date format.
     */
    public static String friendlyDate(Date date, boolean minimalFormat)
    {
        return DateUtil.format(date, DateUtil.friendlyDateFormat(minimalFormat));
    }

    //-----------
 ------------------------------------------------------------
    // convenience method
    public static String friendlyDate(Date date)
    {
        return DateUtil.format(date, DateUtil.friendlyDateFormat(true));
    }
    
    public static Date parseIso8601(String value) throws Exception
    {
        return ISO8601DateParser.parse(value);
    }


}
\ No newline at end of file

Modified: incubator/roller/trunk/web/WEB-INF/classes/ApplicationResources.properties
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/web/WEB-INF/classes/ApplicationResources.properties?rev=377611&r1=377610&r2=377611&view=diff
==============================================================================
--- incubator/roller/trunk/web/WEB-INF/classes/ApplicationResources.properties (original)
+++ incubator/roller/trunk/web/WEB-INF/classes/ApplicationResources.properties Mon Feb 13 20:23:23 2006
@@ -641,6 +641,7 @@
 macro.weblog.allcategories=All
 macro.weblog.nolanguages=This site does not support multiple langauges.
 macro.weblog.notifyMeOfComments=Notify me by email of new comments
+macro.weblog.noEntriesForDate=No entries found for specified date
 
 # -------------------------------------------------------------------- Main page
 

Modified: incubator/roller/trunk/web/WEB-INF/classes/weblog.vm
URL: http://svn.apache.org/viewcvs/incubator/roller/trunk/web/WEB-INF/classes/weblog.vm?rev=377611&r1=377610&r2=377611&view=diff
==============================================================================
--- incubator/roller/trunk/web/WEB-INF/classes/weblog.vm (original)
+++ incubator/roller/trunk/web/WEB-INF/classes/weblog.vm Mon Feb 13 20:23:23 2006
@@ -12,7 +12,9 @@
 
 #**
  * Shows weblog entries from specified category using specified page as a "day 
- * template" for the display of each day. 
+ * template" for the display of each day. The maxEntries argument is ignored
+ * because now the number of entries to display is controlled by the 
+ * entryDisplayCount property on the Preferences:Settings page.
  * 
  * If a specific weblog entry is specified by the current request (using the 
  * entry parameter), this macro will display only that entry and the comments 
@@ -35,19 +37,15 @@
  *#
 #macro( showWeblogEntriesInCategory $pageName $maxEntries $category)
     #set($maxEntries = $website.entryDisplayCount)
-    #if ($pageModel.getWeblogEntry())
-        #set($entry = $pageModel.getWeblogEntry())
-    #end
     #set($dayTemplateId = $pageModel.getPageIdByName($pageName))
     #if(!$dayTemplateId ) ## if no page name, try Preview space
         #set($dayTemplateId = $pageName)
     #end
-    #if ($entry)
-        <div class="top-next-prev">#showNextPreviousLinks()</div>
+    #if ($pageModel.weblogEntry)
+        <div class="top-next-prev">#showNextPreviousControl()</div>
         #set($day = $entry.pubTime)
-        #set($entries = [$entry])
+        #set($entries = [$pageModel.weblogEntry])
         #parse($dayTemplateId )
-        <div class="top-next-prev">#showNextPreviousControl()</div>
         #if($trackbacksEnabled && $website.allowComments && $entry.commentsStillAllowed)
            <div class="trackbackUrl">
            $text.get("macro.weblog.trackback") #showTrackbackURL($entry)
@@ -73,10 +71,13 @@
             #showSearchPager()
         #else
             #set($map = $pageModel.getRecentWeblogEntries($maxEntries, $category))
-            <div class="top-next-prev">#showNextPreviousControl()</div>
-            #foreach($day in $map.keySet())
-                #set($entries = $map.get($day))
-                #parse($dayTemplateId)
+            #if($map.size() == 0)
+               $text.get("macro.weblog.noEntriesForDate")
+            #else               
+               #foreach($day in $map.keySet())
+                   #set($entries = $map.get($day))
+                   #parse($dayTemplateId)
+               #end
             #end
             <div class="bottom-next-prev">#showNextPreviousControl()</div>
         #end
@@ -84,23 +85,8 @@
 #end
 
 #**
- * Shows weblog entries using specified page as a "day template" for the 
- * display of each day. The maxEntries argument is ignored because now, the 
- * number of entries to display is controlled by the entryDisplayCount property 
- * under Preferences:Settings.
- *
- * @param pageName   Page name of page to serve as day template.
- * @param maxEntries (ignored)
- *#
-#macro( showWeblogEntries $pageName $maxEntries )
-#showWeblogEntriesInCategory($pageName $maxEntries 'nil')
-#end
-
-
-#**
- * Shows weblog entries using the standard "_day" template for the display of 
- * each day. The number of entries to display is controlled by the 
- * entryDisplayCount property under Preferences:Settings.
+ * Shows weblog entries by calling showWeblogEntriesInCategory() and passing
+ * 'nil' to indicate that all categories are to be included.
  *#
 #macro( displayWeblogEntries )
 #showWeblogEntriesInCategory("_day" 15 'nil')
@@ -109,7 +95,6 @@
 
 #**
  * Shows list of links to recent weblog entries in one category.
- *
  * @param entryCount Maximum number of entry links to display
 **#
 #macro( showRecentEntriesInCategory $entryCount $catPath )
@@ -164,13 +149,6 @@
     </div>
 #end
 
-#macro( showNextPreviousLinks )
-   <!-- 
-   showNextPreviousLinks() is no longer needed as next/prev links are 
-   built-into the #showRecentEntries() macro.
-   -->
-#end
-
 #**
  * Display link to chronologically previous entry or day in the
  * same category (if specified).
@@ -179,13 +157,15 @@
     <span class="previousEntry">
     #if( $pageModel.previousEntry )
         #set( $prev = $pageModel.previousEntry )
-        #if( $entry )
+        #if( $pageModel.weblogEntry )
             #set( $prevURL = "${ctxPath}${prev.permaLink}" )
+            <a href="$prevURL" title="Previous Entry"
+                >$utilities.truncateNicely($prev.title, 20, 20, "...") &raquo;</a>
         #else
             #set( $prevURL = "${ctxPath}/page/${website.handle}/#formatDate($plainFormat ${prev.pubTime})" )
+            <a href="$prevURL" title="Previous Entries"
+                >#showEntryDate(${prev.pubTime}) &raquo;</a>
         #end
-        <a href="$prevURL" title="Previous Entries"
-            > $utilities.truncateNicely($prev.title, 20, 20, "...") &raquo;</a>
     #end
     </span>
 #end
@@ -198,28 +178,21 @@
     <span class="nextEntry">
     #if( $pageModel.nextEntry )
         #set( $next = $pageModel.nextEntry )        
-        #if( $entry )
+        #if( $pageModel.weblogEntry )
             #set( $nextURL = "${ctxPath}${next.permaLink}" )
+            <a href="$nextURL" title="Next Entry"
+                >&laquo; $utilities.truncateNicely($next.title, 20, 20, "...")</a>
         #else
             #set( $nextURL = "${ctxPath}/page/${website.handle}/#formatDate($plainFormat ${next.pubTime})" )
+            <a href="$nextURL" title="Next Entries"
+                >&laquo; #showEntryDate(${next.pubTime})</a>
         #end
-        <a href="$nextURL" title="Next Entries"
-            >&laquo; $utilities.truncateNicely($next.title, 20, 20, "...")</a>
+
     #end
     </span>
 #end
 
 
-#**
- * Show the last $maxEntries number of weblogentry titles, as links to
- * entry links.  Names of fields must be different than in showWeblogEntries
- * (those values take precedence for some reason).
-**#
-#macro( showRecentEntryLinks $numEntries )
-#showRecentEntryLinksInCategory($numEntries "nil")
-#end
-
-
 #** ======================================================================== *#
 #** Individual weblog entry display macros *#
 #** ======================================================================== *#
@@ -546,8 +519,9 @@
 
 
 #**
- * Shows list of links for recent weblog entries in one category.
- * DEPRECATED: use showRecentWelobEntries() instead.
+ * (DEPRECATED) Shows list of links for recent weblog entries in one category
+ * using the link field (which is no longer exposed in the editor UI).
+ * You should use showRecentEntriesInCategory() instead.
  *
  * @param numEntries Maximum number of entries to display
  * @param cat        Category to be displayed 
@@ -573,4 +547,38 @@
    </ul>
 #end
 
+
+#**
+ * (DEPRECATED) Shows list of links for recent weblog entries in all categories
+ * using the link field (which is no longer exposed in the editor UI). 
+ * You should use showRecentEntries() instead.
+**#
+#macro( showRecentEntryLinks $numEntries )
+#showRecentEntryLinksInCategory($numEntries "nil")
+#end
+
+
+#**
+ * (DEPRECATED) Shows weblog entries by calling showWeblogEntriesInCategory(), 
+ * but passes category of 'nil' to indicate that all categories are to be 
+ * included. You should use displayWeblogEntries() instead.
+ * 
+ * @param pageName   Page name of page to serve as day template.
+ * @param maxEntries (ignored)
+ *#
+#macro( showWeblogEntries $pageName $maxEntries )
+#showWeblogEntriesInCategory($pageName $maxEntries 'nil')
+#end
+
+
+#**
+ * (DEPRECATED) This macro does nothing because now, next/prev links are 
+ * built-into the showWeblogEntries() macro. 
+ *#
+#macro( showNextPreviousLinks )
+   <!-- 
+   showNextPreviousLinks() is no longer needed as next/prev links are 
+   built-into the #showRecentEntries() macro.
+   -->
+#end