]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/classes/core/src/com/ibm/icu/impl/RelativeDateFormat.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / classes / core / 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 The time style for the date and time.\r
51      * @param dateStyle The date style for the date and time.\r
52      * @param locale The locale for the date.\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<URelativeString> datesSet = new TreeSet<URelativeString>(new Comparator<URelativeString>() { \r
166             public int compare(URelativeString r1, URelativeString r2) {\r
167                 \r
168                 if(r1.offset == r2.offset) {\r
169                     return 0;\r
170                 } else if(r1.offset < r2.offset) {\r
171                     return -1;\r
172                 } else {\r
173                     return 1;\r
174                 }\r
175             }\r
176         }) ;\r
177         \r
178         for(UResourceBundleIterator i = rb.getIterator();i.hasNext();) {\r
179             UResourceBundle line = i.next();\r
180             \r
181             String k = line.getKey();\r
182             String v = line.getString();\r
183             URelativeString rs = new URelativeString(k,v);\r
184             datesSet.add(rs);\r
185         }\r
186         fDates = datesSet.toArray(new URelativeString[0]);\r
187     }\r
188     \r
189     /**\r
190      * @return the number of days in "until-now"\r
191      */\r
192     private static int dayDifference(Calendar until) {\r
193         Calendar nowCal = (Calendar)until.clone();\r
194         Date nowDate = new Date(System.currentTimeMillis());\r
195         nowCal.clear();\r
196         nowCal.setTime(nowDate);\r
197         int dayDiff = until.get(Calendar.JULIAN_DAY) - nowCal.get(Calendar.JULIAN_DAY);\r
198         return dayDiff;\r
199     }\r
200     \r
201     /**\r
202      * initializes fCalendar from parameters.  Returns fCalendar as a convenience.\r
203      * @param zone  Zone to be adopted, or NULL for TimeZone::createDefault().\r
204      * @param locale Locale of the calendar\r
205      * @param status Error code\r
206      * @return the newly constructed fCalendar\r
207      */\r
208     private Calendar initializeCalendar(TimeZone zone, ULocale locale) {\r
209         if (calendar == null) {\r
210             if(zone == null) {\r
211                 calendar = Calendar.getInstance(locale);\r
212             } else {\r
213                 calendar = Calendar.getInstance(zone, locale);\r
214             }\r
215         }\r
216         return calendar;\r
217     }\r
218 \r
219     private MessageFormat initializeCombinedFormat(Calendar cal, ULocale locale) {\r
220         String pattern = "{1} {0}";\r
221         try {\r
222             CalendarData calData = new CalendarData(locale, cal.getType());\r
223             String[] patterns = calData.getDateTimePatterns();\r
224             if (patterns != null && patterns.length >= 9) {\r
225                 int glueIndex = 8;\r
226                 if (patterns.length >= 13)\r
227                 {\r
228                     switch (fDateStyle)\r
229                     {\r
230                         case DateFormat.RELATIVE_FULL:\r
231                         case DateFormat.FULL:\r
232                             glueIndex += (DateFormat.FULL + 1);\r
233                             break;\r
234                         case DateFormat.RELATIVE_LONG:\r
235                         case DateFormat.LONG:\r
236                             glueIndex += (DateFormat.LONG +1);\r
237                             break;\r
238                         case DateFormat.RELATIVE_MEDIUM:\r
239                         case DateFormat.MEDIUM:\r
240                             glueIndex += (DateFormat.MEDIUM +1);\r
241                             break;\r
242                         case DateFormat.RELATIVE_SHORT:\r
243                         case DateFormat.SHORT:\r
244                             glueIndex += (DateFormat.SHORT + 1);\r
245                             break;\r
246                         default:\r
247                             break;\r
248                     }\r
249                 }\r
250                 pattern = patterns[glueIndex];\r
251             }\r
252         } catch (MissingResourceException e) {\r
253             // use default\r
254         }\r
255         fCombinedFormat = new MessageFormat(pattern, locale);\r
256         return fCombinedFormat;\r
257     }\r
258 }\r