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