2 *******************************************************************************
3 * Copyright (C) 2007-2009, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
7 package com.ibm.icu.impl;
9 import java.text.FieldPosition;
10 import java.text.ParsePosition;
11 import java.util.Comparator;
12 import java.util.Date;
13 import java.util.MissingResourceException;
15 import java.util.TreeSet;
17 import com.ibm.icu.text.DateFormat;
18 import com.ibm.icu.text.MessageFormat;
19 import com.ibm.icu.util.Calendar;
20 import com.ibm.icu.util.TimeZone;
21 import com.ibm.icu.util.ULocale;
22 import com.ibm.icu.util.UResourceBundle;
23 import com.ibm.icu.util.UResourceBundleIterator;
28 public class RelativeDateFormat extends DateFormat {
34 public class URelativeString {
35 URelativeString(int offset, String string) {
39 URelativeString(String offset, String string) {
40 this.offset = Integer.parseInt(offset);
50 * @param timeStyle The time style for the date and time.
51 * @param dateStyle The date style for the date and time.
52 * @param locale The locale for the date.
54 public RelativeDateFormat(int timeStyle, int dateStyle, ULocale locale) {
56 fTimeStyle = timeStyle;
57 fDateStyle = dateStyle;
59 if(fDateStyle != DateFormat.NONE) {
60 int newStyle = fDateStyle & ~DateFormat.RELATIVE;
61 fDateFormat = DateFormat.getDateInstance(newStyle, locale);
65 if(fTimeStyle != DateFormat.NONE) {
66 int newStyle = fTimeStyle & ~DateFormat.RELATIVE;
67 fTimeFormat = DateFormat.getTimeInstance(newStyle, locale);
72 initializeCalendar(null, fLocale);
74 initializeCombinedFormat(calendar, fLocale);
78 * serial version (generated)
80 private static final long serialVersionUID = 1131984966440549435L;
83 * @see com.ibm.icu.text.DateFormat#format(com.ibm.icu.util.Calendar, java.lang.StringBuffer, java.text.FieldPosition)
85 public StringBuffer format(Calendar cal, StringBuffer toAppendTo,
86 FieldPosition fieldPosition) {
88 String dayString = null;
89 if (fDateStyle != DateFormat.NONE) {
90 // calculate the difference, in days, between 'cal' and now.
91 int dayDiff = dayDifference(cal);
94 dayString = getStringForDay(dayDiff);
96 if (fTimeStyle == DateFormat.NONE) {
97 if (dayString != null) {
98 toAppendTo.append(dayString);
99 } else if (fDateStyle != DateFormat.NONE) {
100 fDateFormat.format(cal, toAppendTo, fieldPosition);
103 if (dayString == null && fDateStyle != DateFormat.NONE) {
104 dayString = fDateFormat.format(cal, new StringBuffer(), fieldPosition).toString();
106 FieldPosition timePos = new FieldPosition(fieldPosition.getField());
107 String timeString = fTimeFormat.format(cal, new StringBuffer(), timePos).toString();
108 fCombinedFormat.format(new Object[] {dayString, timeString}, toAppendTo, new FieldPosition(0));
110 if (fieldPosition.getEndIndex() > 0 && (offset = toAppendTo.toString().indexOf(dayString)) >= 0 ) {
111 // fieldPosition.getField() was found in dayString, offset start & end based on final position of dayString
112 fieldPosition.setBeginIndex( fieldPosition.getBeginIndex() + offset );
113 fieldPosition.setEndIndex( fieldPosition.getEndIndex() + offset );
114 } else if (timePos.getEndIndex() > 0 && (offset = toAppendTo.toString().indexOf(timeString)) >= 0) {
115 // fieldPosition.getField() was found in timeString, offset start & end based on final position of timeString
116 fieldPosition.setBeginIndex( timePos.getBeginIndex() + offset );
117 fieldPosition.setEndIndex( timePos.getEndIndex() + offset );
124 * @see com.ibm.icu.text.DateFormat#parse(java.lang.String, com.ibm.icu.util.Calendar, java.text.ParsePosition)
126 public void parse(String text, Calendar cal, ParsePosition pos) {
127 throw new UnsupportedOperationException("Relative Date parse is not implemented yet");
130 private DateFormat fDateFormat; // the held date format
131 private DateFormat fTimeFormat; // the held time format
132 private MessageFormat fCombinedFormat; // the {0} {1} format.
138 private transient URelativeString fDates[] = null; // array of strings
142 * Get the string at a specific offset.
143 * @param day day offset ( -1, 0, 1, etc.. )
144 * @return the string, or NULL if none at that location.
146 private String getStringForDay(int day) {
150 for(int i=0;i<fDates.length;i++) {
151 if(fDates[i].offset == day) {
152 return fDates[i].string;
159 * Load the Date string array
161 private synchronized void loadDates() {
162 CalendarData calData = new CalendarData(fLocale, calendar.getType());
163 UResourceBundle rb = calData.get("fields", "day", "relative");
165 Set<URelativeString> datesSet = new TreeSet<URelativeString>(new Comparator<URelativeString>() {
166 public int compare(URelativeString r1, URelativeString r2) {
168 if(r1.offset == r2.offset) {
170 } else if(r1.offset < r2.offset) {
178 for(UResourceBundleIterator i = rb.getIterator();i.hasNext();) {
179 UResourceBundle line = i.next();
181 String k = line.getKey();
182 String v = line.getString();
183 URelativeString rs = new URelativeString(k,v);
186 fDates = datesSet.toArray(new URelativeString[0]);
190 * @return the number of days in "until-now"
192 private static int dayDifference(Calendar until) {
193 Calendar nowCal = (Calendar)until.clone();
194 Date nowDate = new Date(System.currentTimeMillis());
196 nowCal.setTime(nowDate);
197 int dayDiff = until.get(Calendar.JULIAN_DAY) - nowCal.get(Calendar.JULIAN_DAY);
202 * initializes fCalendar from parameters. Returns fCalendar as a convenience.
203 * @param zone Zone to be adopted, or NULL for TimeZone::createDefault().
204 * @param locale Locale of the calendar
205 * @param status Error code
206 * @return the newly constructed fCalendar
208 private Calendar initializeCalendar(TimeZone zone, ULocale locale) {
209 if (calendar == null) {
211 calendar = Calendar.getInstance(locale);
213 calendar = Calendar.getInstance(zone, locale);
219 private MessageFormat initializeCombinedFormat(Calendar cal, ULocale locale) {
220 String pattern = "{1} {0}";
222 CalendarData calData = new CalendarData(locale, cal.getType());
223 String[] patterns = calData.getDateTimePatterns();
224 if (patterns != null && patterns.length >= 9) {
226 if (patterns.length >= 13)
230 case DateFormat.RELATIVE_FULL:
231 case DateFormat.FULL:
232 glueIndex += (DateFormat.FULL + 1);
234 case DateFormat.RELATIVE_LONG:
235 case DateFormat.LONG:
236 glueIndex += (DateFormat.LONG +1);
238 case DateFormat.RELATIVE_MEDIUM:
239 case DateFormat.MEDIUM:
240 glueIndex += (DateFormat.MEDIUM +1);
242 case DateFormat.RELATIVE_SHORT:
243 case DateFormat.SHORT:
244 glueIndex += (DateFormat.SHORT + 1);
250 pattern = patterns[glueIndex];
252 } catch (MissingResourceException e) {
255 fCombinedFormat = new MessageFormat(pattern, locale);
256 return fCombinedFormat;