]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/impl/RelativeDateFormat.java
icu4jsrc
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / impl / RelativeDateFormat.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 2007-2009, International Business Machines Corporation and         *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.impl;\r
8 \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
16 \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
24 \r
25 /**\r
26  * @author srl\r
27  */\r
28 public class RelativeDateFormat extends DateFormat {\r
29 \r
30     /**\r
31      * @author srl\r
32      *\r
33      */\r
34     public class URelativeString {\r
35         URelativeString(int offset, String string) {\r
36             this.offset = offset;\r
37             this.string = string;\r
38         }\r
39         URelativeString(String offset, String string) {\r
40             this.offset = Integer.parseInt(offset);\r
41             this.string = string;\r
42         }\r
43         public int    offset;\r
44         public String string;\r
45     }\r
46 \r
47     // copy c'tor?\r
48     \r
49     /**\r
50      * @param timeStyle\r
51      * @param dateStyle\r
52      * @param locale\r
53      */\r
54     public RelativeDateFormat(int timeStyle, int dateStyle, ULocale locale) {\r
55         fLocale = locale;\r
56         fTimeStyle = timeStyle;\r
57         fDateStyle = dateStyle;\r
58         \r
59         if(fDateStyle != DateFormat.NONE) {\r
60             int newStyle = fDateStyle & ~DateFormat.RELATIVE;\r
61             fDateFormat = DateFormat.getDateInstance(newStyle, locale);\r
62         } else {\r
63             fDateFormat = null;\r
64         }\r
65         if(fTimeStyle != DateFormat.NONE) {\r
66             int newStyle = fTimeStyle & ~DateFormat.RELATIVE;\r
67             fTimeFormat = DateFormat.getTimeInstance(newStyle, locale);\r
68         } else {\r
69             fTimeFormat = null;\r
70         }\r
71 \r
72         initializeCalendar(null, fLocale);\r
73         loadDates();\r
74         initializeCombinedFormat(calendar, fLocale);\r
75     }\r
76     \r
77     /**\r
78      * serial version (generated)\r
79      */\r
80     private static final long serialVersionUID = 1131984966440549435L;\r
81 \r
82     /* (non-Javadoc)\r
83      * @see com.ibm.icu.text.DateFormat#format(com.ibm.icu.util.Calendar, java.lang.StringBuffer, java.text.FieldPosition)\r
84      */\r
85     public StringBuffer format(Calendar cal, StringBuffer toAppendTo,\r
86             FieldPosition fieldPosition) {\r
87 \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
92 \r
93             // look up string\r
94             dayString = getStringForDay(dayDiff);\r
95         }\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
101             }\r
102         } else {\r
103             if (dayString == null && fDateStyle != DateFormat.NONE) {\r
104                 dayString = fDateFormat.format(cal, new StringBuffer(), fieldPosition).toString();\r
105             }\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
109             int offset;\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
118             }\r
119         }\r
120         return toAppendTo;\r
121     }\r
122 \r
123     /* (non-Javadoc)\r
124      * @see com.ibm.icu.text.DateFormat#parse(java.lang.String, com.ibm.icu.util.Calendar, java.text.ParsePosition)\r
125      */\r
126     public void parse(String text, Calendar cal, ParsePosition pos) {\r
127         throw new UnsupportedOperationException("Relative Date parse is not implemented yet");\r
128     }\r
129 \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
133 \r
134     int fDateStyle;\r
135     int fTimeStyle;\r
136     ULocale  fLocale;\r
137     \r
138     private transient URelativeString fDates[] = null; // array of strings\r
139     \r
140     \r
141     /**\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
145      */\r
146     private String getStringForDay(int day) {\r
147         if(fDates == null) {\r
148             loadDates();\r
149         }\r
150         for(int i=0;i<fDates.length;i++) {\r
151             if(fDates[i].offset == day) {\r
152                 return fDates[i].string;\r
153             }\r
154         }\r
155         return null;\r
156     }\r
157     \r
158     /** \r
159      * Load the Date string array\r
160      */\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
164         \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
169                 \r
170                 if(r1.offset == r2.offset) {\r
171                     return 0;\r
172                 } else if(r1.offset < r2.offset) {\r
173                     return -1;\r
174                 } else {\r
175                     return 1;\r
176                 }\r
177             }\r
178         }) ;\r
179         \r
180         for(UResourceBundleIterator i = rb.getIterator();i.hasNext();) {\r
181             UResourceBundle line = i.next();\r
182             \r
183             String k = line.getKey();\r
184             String v = line.getString();\r
185             URelativeString rs = new URelativeString(k,v);\r
186             datesSet.add(rs);\r
187         }\r
188         fDates = new URelativeString[0];\r
189         fDates = (URelativeString[])datesSet.toArray(fDates);\r
190     }\r
191     \r
192     /**\r
193      * @return the number of days in "until-now"\r
194      */\r
195     private static int dayDifference(Calendar until) {\r
196         Calendar nowCal = (Calendar)until.clone();\r
197         Date nowDate = new Date(System.currentTimeMillis());\r
198         nowCal.clear();\r
199         nowCal.setTime(nowDate);\r
200         int dayDiff = until.get(Calendar.JULIAN_DAY) - nowCal.get(Calendar.JULIAN_DAY);\r
201         return dayDiff;\r
202     }\r
203     \r
204     /**\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
210      */\r
211     private Calendar initializeCalendar(TimeZone zone, ULocale locale) {\r
212         if (calendar == null) {\r
213             if(zone == null) {\r
214                 calendar = Calendar.getInstance(locale);\r
215             } else {\r
216                 calendar = Calendar.getInstance(zone, locale);\r
217             }\r
218         }\r
219         return calendar;\r
220     }\r
221 \r
222     private MessageFormat initializeCombinedFormat(Calendar cal, ULocale locale) {\r
223         String pattern = "{1} {0}";\r
224         try {\r
225             CalendarData calData = new CalendarData(locale, cal.getType());\r
226             String[] patterns = calData.getDateTimePatterns();\r
227             if (patterns != null && patterns.length >= 9) {\r
228                 int glueIndex = 8;\r
229                 if (patterns.length >= 13)\r
230                 {\r
231                     switch (fDateStyle)\r
232                     {\r
233                         case DateFormat.RELATIVE_FULL:\r
234                         case DateFormat.FULL:\r
235                             glueIndex += (DateFormat.FULL + 1);\r
236                             break;\r
237                         case DateFormat.RELATIVE_LONG:\r
238                         case DateFormat.LONG:\r
239                             glueIndex += (DateFormat.LONG +1);\r
240                             break;\r
241                         case DateFormat.RELATIVE_MEDIUM:\r
242                         case DateFormat.MEDIUM:\r
243                             glueIndex += (DateFormat.MEDIUM +1);\r
244                             break;\r
245                         case DateFormat.RELATIVE_SHORT:\r
246                         case DateFormat.SHORT:\r
247                             glueIndex += (DateFormat.SHORT + 1);\r
248                             break;\r
249                         default:\r
250                             break;\r
251                     }\r
252                 }\r
253                 pattern = patterns[glueIndex];\r
254             }\r
255         } catch (MissingResourceException e) {\r
256             // use default\r
257         }\r
258         fCombinedFormat = new MessageFormat(pattern, locale);\r
259         return fCombinedFormat;\r
260     }\r
261 }\r