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