views:

118

answers:

5

I have two dates - a start and an end. I'd like to format them so that if the months match, they collapse to something like "20-23 AUG" and still format correctly if they break over the end of the month, like "20 SEP - 1 OCT". Are there any libraries out there for accomplishing this, or would I have to hand code rules for displaying ranges of dates using individual DateFormats?

+3  A: 

Checkout java's SimpleDateFormat class. You can construct a SimpleDateFormat passing you're date pattern as a String.

Jeroen Rosenberg
@Jeroen - First, this class can format *one* Date but not a range and, second, the formatter is pretty static, it can't vary formatting based on the input.
Andreas_D
+1  A: 

To add to Jeroen's answer, you're going to use SimpleDateFormat twice, once for each end of the range.

Dean J
And the OP could use a simple regex to check if the months match and trim accordingly.
Igor Klimer
A: 

There is not such type as day range in Java by default, so none of the DateFormats apply to string representation of this case.

The best in my opinion, well be creation of type TimeSpan or TimeDiff and override method to string. Or as You suggested create a DateFormmater if you need two also parsing.

Vash
+5  A: 

Here's a solution using JodaTime, the best library for dealing with dates in Java (last time I checked). The formatting is simple and could no doubt be improved by using custom DateFormatter implementations. This also checks that the year is the same, but doesn't output the year, which could be confusing.

import org.joda.time.DateTime;

public class DateFormatterTest {

    public static void main(String[] args) {

        DateTime august23rd = new DateTime(2010, 8, 23, 0, 0, 0, 0);
        DateTime august25th = new DateTime(2010, 8, 25, 0, 0, 0, 0);
        DateTime september5th = new DateTime(2010, 9, 5, 0, 0, 0, 0);

        DateFormatterTest tester = new DateFormatterTest();
        tester.outputDate(august23rd, august25th);
        tester.outputDate(august23rd, september5th);

    }

    private void outputDate(DateTime firstDate, DateTime secondDate) {
        if ((firstDate.getMonthOfYear() == secondDate.getMonthOfYear()) && (firstDate.getYear() == secondDate.getYear())) {
            System.out.println(firstDate.getDayOfMonth() + " - " + secondDate.getDayOfMonth() + " " + firstDate.monthOfYear().getAsShortText());
        } else {
            System.out.println(firstDate.getDayOfMonth() + " " + firstDate.monthOfYear().getAsShortText() + " - " + secondDate.getDayOfMonth() + " " + secondDate.monthOfYear().getAsShortText());
        }
    }
}

Output:

23 - 25 Aug

23 Aug - 5 Sep

stark
+1 - I was just writing my on recommendation to use [joda time](http://joda-time.sourceforge.net/index.html). Now you get my upvote instead :)
Andreas_D
Will JodaTime work in GWT?
SorcyCat
@SorcyCat - According to [this thread](http://sourceforge.net/projects/joda-time/forums/forum/337835/topic/3460297) I'd say that it works. If they just discuss commenting 2 lines in the tests to make test gwt compatible, then I think it's worth trying.
Andreas_D
@Andreas_D: There are multiple projects trying to port joda to GWT, but they have different kinds of issues. See also [this thread](http://groups.google.com/group/google-web-toolkit/browse_thread/thread/941a5c09f366d9de/) on the GWT group. For me, it's not yet realistically possible to use the Joda API with GWT.
Chris Lercher
+3  A: 

I was disappointed with the answers that didn't seem to read the question. Joda time didn't work in GWT and neither does SimpleDateFormat. Anyway, I already knew about DateTimeFormat in GWT. The main issue is that date objects getMonth() function is deprecated, and there doesn't seem to be a good way to compare months and/or years. This solution doesn't include year checking (which could be easily added by changing the monthFormatter), but that's not important for my case.

public final class DateUtility
{
    public static final DateTimeFormat MONTH_FORMAT = DateTimeFormat.getFormat("MMM");
    public static final DateTimeFormat DAY_FORMAT = DateTimeFormat.getFormat("dd");
    public static final DateTimeFormat DAY_MONTH_FORMAT = DateTimeFormat.getFormat("dd MMM");

    public static final String DASH = " - ";

    /**
     * Returns a "collapsed" date range String representing the period of time
     * between two Date parameters. Example: August 19 as a {@code startDate}
     * and August 30 as an {@code endDate} will return "19 - 30 AUG", August 28
     * as a {@code startDate} and September 7 as an {@code endDate} will return
     * "28 AUG - 07 SEP". This means if you pass this two dates which cannot
     * collapse into a shorter form, then the longer form is returned.  Years
     * are ignored, and the start and end dates are not checked to ensure we
     * are not going backwards in time (Aug 10 - July 04 is not checked).
     * 
     * @param startDate
     *            the start Date in the range.
     * @param endDate
     *            the end Date in the range.
     * @return a String representation of the range between the two dates given.
     */
    public static String collapseDate(Date startDate, Date endDate) {
        String formattedDateRange;

        // Get a comparison result to determine if the Months are the same
        String startDateMonth = MONTH_FORMAT.format(startDate);
        String endDateMonth = MONTH_FORMAT.format(endDate);

        if (startDateMonth.equals(endDateMonth))
        {
            formattedDateRange = DAY_FORMAT.format(startDate) + DASH
                    + DAY_MONTH_FORMAT.format(endDate).toUpperCase();
        }
        else
        {
            // Months don't match, split the string across both months
            formattedDateRange = DAY_MONTH_FORMAT.format(startDate).toUpperCase()
                    + DASH + DAY_MONTH_FORMAT.format(endDate).toUpperCase();
        }
        return formattedDateRange;
    }
}
SorcyCat