DateIntervalFormat is a class for formatting and parsing date
intervals in a language-independent manner.
Only formatting is supported. Parsing is not supported.
Date interval means from one date to another date,
for example, from "Jan 11, 2008" to "Jan 18, 2008".
We introduced class DateInterval to represent it.
DateInterval is a pair of UDate, which is
the standard milliseconds since 24:00 GMT, Jan 1, 1970.
DateIntervalFormat formats a DateInterval into
text as compactly as possible.
For example, the date interval format from "Jan 11, 2008" to "Jan 18,. 2008"
is "Jan 11-18, 2008" for English.
And it parses text into DateInterval,
although initially, parsing is not supported.
There is no structural information in date time patterns.
For any punctuations and string literals inside a date time pattern,
we do not know whether it is just a separator, or a prefix, or a suffix.
Without such information, so, it is difficult to generate a sub-pattern
(or super-pattern) by algorithm.
So, formatting a DateInterval is pattern-driven. It is very
similar to formatting in SimpleDateFormat.
We introduce class DateIntervalInfo to save date interval
patterns, similar to date time pattern in SimpleDateFormat.
Logically, the interval patterns are mappings
from (skeleton, the_largest_different_calendar_field)
to (date_interval_pattern).
A skeleton
-
only keeps the field pattern letter and ignores all other parts
in a pattern, such as space, punctuations, and string literals.
-
hides the order of fields.
-
might hide a field's pattern letter length.
For those non-digit calendar fields, the pattern letter length is
important, such as MMM, MMMM, and MMMMM; EEE and EEEE,
and the field's pattern letter length is honored.
For the digit calendar fields, such as M or MM, d or dd, yy or yyyy,
the field pattern length is ignored and the best match, which is defined
in date time patterns, will be returned without honor the field pattern
letter length in skeleton.
The calendar fields we support for interval formatting are:
year, month, date, day-of-week, am-pm, hour, hour-of-day, minute, and
second (though we do not currently have specific intervalFormat data for
skeletons with seconds).
Those calendar fields can be defined in the following order:
year > month > date > hour (in day) > minute > second
The largest different calendar fields between 2 calendars is the
first different calendar field in above order.
For example: the largest different calendar fields between "Jan 10, 2007"
and "Feb 20, 2008" is year.
For other calendar fields, the compact interval formatting is not
supported. And the interval format will be fall back to fall-back
patterns, which is mostly "{date0} - {date1}".
There is a set of pre-defined static skeleton strings in DateFormat,
There are pre-defined interval patterns for those pre-defined skeletons
in locales' resource files.
For example, for a skeleton YEAR_ABBR_MONTH_DAY, which is "yMMMd",
in en_US, if the largest different calendar field between date1 and date2
is "year", the date interval pattern is "MMM d, yyyy - MMM d, yyyy",
such as "Jan 10, 2007 - Jan 10, 2008".
If the largest different calendar field between date1 and date2 is "month",
the date interval pattern is "MMM d - MMM d, yyyy",
such as "Jan 10 - Feb 10, 2007".
If the largest different calendar field between date1 and date2 is "day",
the date interval pattern is ""MMM d-d, yyyy", such as "Jan 10-20, 2007".
For date skeleton, the interval patterns when year, or month, or date is
different are defined in resource files.
For time skeleton, the interval patterns when am/pm, or hour, or minute is
different are defined in resource files.
If a skeleton is not found in a locale's DateIntervalInfo, which means
the interval patterns for the skeleton is not defined in resource file,
the interval pattern will falls back to the interval "fallback" pattern
defined in resource file.
If the interval "fallback" pattern is not defined, the default fall-back
is "{date0} - {data1}".
For the combination of date and time,
The rule to genearte interval patterns are:
-
when the year, month, or day differs, falls back to fall-back
interval pattern, which mostly is the concatenate the two original
expressions with a separator between,
For example, interval pattern from "Jan 10, 2007 10:10 am"
to "Jan 11, 2007 10:10am" is
"Jan 10, 2007 10:10 am - Jan 11, 2007 10:10am"
-
otherwise, present the date followed by the range expression
for the time.
For example, interval pattern from "Jan 10, 2007 10:10 am"
to "Jan 10, 2007 11:10am" is "Jan 10, 2007 10:10 am - 11:10am"
If two dates are the same, the interval pattern is the single date pattern.
For example, interval pattern from "Jan 10, 2007" to "Jan 10, 2007" is
"Jan 10, 2007".
Or if the presenting fields between 2 dates have the exact same values,
the interval pattern is the single date pattern.
For example, if user only requests year and month,
the interval pattern from "Jan 10, 2007" to "Jan 20, 2007" is "Jan 2007".
DateIntervalFormat needs the following information for correct
formatting: time zone, calendar type, pattern, date format symbols,
and date interval patterns.
It can be instantiated in several ways:
-
create an instance using default or given locale plus given skeleton.
Users are encouraged to created date interval formatter this way and
to use the pre-defined skeleton macros, such as
YEAR_NUM_MONTH, which consists the calendar fields and
the format style.
-
create an instance using default or given locale plus given skeleton
plus a given DateIntervalInfo.
This factory method is for powerful users who want to provide their own
interval patterns.
Locale provides the timezone, calendar, and format symbols information.
Local plus skeleton provides full pattern information.
DateIntervalInfo provides the date interval patterns.
For the calendar field pattern letter, such as G, y, M, d, a, h, H, m, s etc.
DateIntervalFormat uses the same syntax as that of
DateTime format.
Code Sample: general usage
// the date interval object which the DateIntervalFormat formats on
// and parses into
DateInterval dtInterval = new DateInterval(1000*3600*24L, 1000*3600*24*2L);
DateIntervalFormat dtIntervalFmt = DateIntervalFormat.getInstance(
YEAR_MONTH_DAY, Locale("en", "GB", ""));
StringBuffer str = new StringBuffer("");
FieldPosition pos = new FieldPosition(0);
// formatting
dtIntervalFmt.format(dtInterval, dateIntervalString, pos);
Code Sample: for powerful users who wants to use their own interval pattern
import com.ibm.icu.text.DateIntervalInfo;
import com.ibm.icu.text.DateIntervalFormat;
....................
// Get DateIntervalFormat instance using default locale
DateIntervalFormat dtitvfmt = DateIntervalFormat.getInstance(YEAR_MONTH_DAY);
// Create an empty DateIntervalInfo object, which does not have any interval patterns inside.
dtitvinf = new DateIntervalInfo();
// a series of set interval patterns.
// Only ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY,
MINUTE and SECOND are supported.
dtitvinf.setIntervalPattern("yMMMd", Calendar.YEAR, "'y ~ y'");
dtitvinf.setIntervalPattern("yMMMd", Calendar.MONTH, "yyyy 'diff' MMM d - MMM d");
dtitvinf.setIntervalPattern("yMMMd", Calendar.DATE, "yyyy MMM d ~ d");
dtitvinf.setIntervalPattern("yMMMd", Calendar.HOUR_OF_DAY, "yyyy MMM d HH:mm ~ HH:mm");
// Set fallback interval pattern. Fallback pattern is used when interval pattern is not found.
// If the fall-back pattern is not set, falls back to {date0} - {date1} if interval pattern is not found.
dtitvinf.setFallbackIntervalPattern("{0} - {1}");
// Set above DateIntervalInfo object as the interval patterns of date interval formatter
dtitvfmt.setDateIntervalInfo(dtitvinf);
// Prepare to format
pos = new FieldPosition(0);
str = new StringBuffer("");
// The 2 calendars should be equivalent, otherwise, IllegalArgumentException will be thrown by format()
Calendar fromCalendar = (Calendar) dtfmt.getCalendar().clone();
Calendar toCalendar = (Calendar) dtfmt.getCalendar().clone();
fromCalendar.setTimeInMillis(....);
toCalendar.setTimeInMillis(...);
//Formatting given 2 calendars
dtitvfmt.format(fromCalendar, toCalendar, str, pos);
Synchronization
The format methods of DateIntervalFormat may be used concurrently from multiple threads.
Functions that alter the state of a DateIntervalFormat object (setters)
may not be used concurrently with any other functions.