]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/text/ChineseDateFormat.java
go
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / text / ChineseDateFormat.java
1 //##header J2SE15
2 /*********************************************************************
3  * Copyright (C) 2000-2009, International Business Machines Corporation and
4  * others. All Rights Reserved.
5  *********************************************************************
6  */
7 package com.ibm.icu.text;
8 import com.ibm.icu.util.*;
9 import com.ibm.icu.impl.Utility;
10
11 import java.text.FieldPosition;
12 import java.text.ParsePosition;
13 import java.util.Locale;
14 //#if defined(FOUNDATION10) || defined(J2SE13)
15 //#else
16 import java.io.InvalidObjectException;
17 //#endif
18
19 /**
20  * A concrete {@link DateFormat} for {@link com.ibm.icu.util.ChineseCalendar}.
21  * This class handles a <code>ChineseCalendar</code>-specific field,
22  * <code>ChineseCalendar.IS_LEAP_MONTH</code>.  It also redefines the
23  * handling of two fields, <code>ERA</code> and <code>YEAR</code>.  The
24  * former is displayed numerically, instead of symbolically, since it is
25  * the numeric cycle number in <code>ChineseCalendar</code>.  The latter is
26  * numeric, as before, but has no special 2-digit Y2K behavior.
27  *
28  * <p>With regard to <code>ChineseCalendar.IS_LEAP_MONTH</code>, this
29  * class handles parsing specially.  If no string symbol is found at all,
30  * this is taken as equivalent to an <code>IS_LEAP_MONTH</code> value of
31  * zero.  This allows formats to display a special string (e.g., "*") for
32  * leap months, but no string for normal months.
33  *
34  * <p>Summary of field changes vs. {@link SimpleDateFormat}:<pre>
35  * Symbol   Meaning                 Presentation        Example
36  * ------   -------                 ------------        -------
37  * G        cycle                   (Number)            78
38  * y        year of cycle (1..60)   (Number)            17
39  * l        is leap month           (Text)              4637
40  * </pre>
41  *
42  * @see com.ibm.icu.util.ChineseCalendar
43  * @see ChineseDateFormatSymbols
44  * @author Alan Liu
45  * @stable ICU 2.0
46  */
47 public class ChineseDateFormat extends SimpleDateFormat {
48     // Generated by serialver from JDK 1.4.1_01
49     static final long serialVersionUID = -4610300753104099899L;
50     
51     // TODO Finish the constructors
52
53     /**
54      * Construct a ChineseDateFormat from a date format pattern and locale
55      * @param pattern the pattern
56      * @param locale the locale
57      * @stable ICU 2.0
58      */
59    public ChineseDateFormat(String pattern, Locale locale) {
60        this(pattern, ULocale.forLocale(locale));
61     }
62
63     /**
64      * Construct a ChineseDateFormat from a date format pattern and locale
65      * @param pattern the pattern
66      * @param locale the locale
67      * @stable ICU 3.2
68      */
69    public ChineseDateFormat(String pattern, ULocale locale) {
70        this(pattern, null, locale);
71     }
72
73     /**
74      * Construct a ChineseDateFormat from a date format pattern and locale
75      * @param pattern the pattern
76      * @param locale the locale
77      * @stable ICU 3.2
78      */
79    public ChineseDateFormat(String pattern, String override, ULocale locale) {
80        super(pattern, new ChineseDateFormatSymbols(locale), 
81                new ChineseCalendar(TimeZone.getDefault(), locale), locale, true, override);
82     }
83
84 // NOTE: This API still exists; we just inherit it from SimpleDateFormat
85 // as of ICU 3.0
86 //  /**
87 //   * @stable ICU 2.0
88 //   */
89 //  protected String subFormat(char ch, int count, int beginOffset,
90 //                             FieldPosition pos, DateFormatSymbols formatData,
91 //                             Calendar cal)  {
92 //      switch (ch) {
93 //      case 'G': // 'G' - ERA
94 //          return zeroPaddingNumber(cal.get(Calendar.ERA), 1, 9);
95 //      case 'l': // 'l' - IS_LEAP_MONTH
96 //          {
97 //              ChineseDateFormatSymbols symbols =
98 //                  (ChineseDateFormatSymbols) formatData;
99 //              return symbols.getLeapMonth(cal.get(
100 //                             ChineseCalendar.IS_LEAP_MONTH));
101 //          }
102 //      default:
103 //          return super.subFormat(ch, count, beginOffset, pos, formatData, cal);
104 //      }
105 //  }    
106
107     /**
108      * {@inheritDoc}
109      * @internal
110      * @deprecated This API is ICU internal only.
111      */
112     protected void subFormat(StringBuffer buf,
113                              char ch, int count, int beginOffset,
114                              FieldPosition pos,
115                              Calendar cal) {
116
117         switch (ch) {
118         case 'G': // 'G' - ERA
119             zeroPaddingNumber(numberFormat,buf, cal.get(Calendar.ERA), 1, 9);
120             break;
121         case 'l': // 'l' - IS_LEAP_MONTH
122             buf.append(((ChineseDateFormatSymbols) getSymbols()).
123                        getLeapMonth(cal.get(ChineseCalendar.IS_LEAP_MONTH)));
124             break;
125         default:
126             super.subFormat(buf, ch, count, beginOffset, pos, cal);
127             break;
128         }
129
130         // TODO: add code to set FieldPosition for 'G' and 'l' fields. This
131         // is a DESIGN FLAW -- subclasses shouldn't have to duplicate the
132         // code that handles this at the end of SimpleDateFormat.subFormat.
133         // The logic should be moved up into SimpleDateFormat.format.
134     }
135
136     /**
137      * {@inheritDoc}
138      * @stable ICU 2.0
139      */
140     protected int subParse(String text, int start, char ch, int count,
141                            boolean obeyCount, boolean allowNegative, boolean[] ambiguousYear, Calendar cal) {
142         if (ch != 'G' && ch != 'l' && ch != 'y') {
143             return super.subParse(text, start, ch, count, obeyCount, allowNegative, ambiguousYear, cal);
144         }
145
146         // Skip whitespace
147         start = Utility.skipWhitespace(text, start);
148
149         ParsePosition pos = new ParsePosition(start);
150
151         switch (ch) {
152         case 'G': // 'G' - ERA
153         case 'y': // 'y' - YEAR, but without the 2-digit Y2K adjustment
154             {
155                 Number number = null;
156                 if (obeyCount) {
157                     if ((start+count) > text.length()) {
158                         return -start;
159                     }
160                     number = numberFormat.parse(text.substring(0, start+count), pos);
161                 } else {
162                     number = numberFormat.parse(text, pos);
163                 }
164                 if (number == null) {
165                     return -start;
166                 }
167                 int value = number.intValue();
168                 cal.set(ch == 'G' ? Calendar.ERA : Calendar.YEAR, value);
169                 return pos.getIndex();
170             }
171         case 'l': // 'l' - IS_LEAP_MONTH
172             {
173                 ChineseDateFormatSymbols symbols =
174                     (ChineseDateFormatSymbols) getSymbols();
175                 int result = matchString(text, start, ChineseCalendar.IS_LEAP_MONTH,
176                                          symbols.isLeapMonth, cal);
177                 // Treat the absence of any matching string as setting
178                 // IS_LEAP_MONTH to false.
179                 if (result<0) {
180                     cal.set(ChineseCalendar.IS_LEAP_MONTH, 0);
181                     result = start;
182                 }
183                 return result;
184             }
185         default:
186             ///CLOVER:OFF
187             return 0; // This can never happen
188             ///CLOVER:ON
189         }
190     }
191
192 //#if defined(FOUNDATION10) || defined(J2SE13)
193 //#else
194     /**
195      * {@inheritDoc}
196      * 
197      * @stable ICU 3.8
198      */
199     protected DateFormat.Field patternCharToDateFormatField(char ch) {
200         if (ch == 'l') {
201             return ChineseDateFormat.Field.IS_LEAP_MONTH;
202         }
203         return super.patternCharToDateFormatField(ch);
204     }
205
206     /**
207      * The instances of this inner class are used as attribute keys and values
208      * in AttributedCharacterIterator that
209      * ChineseDateFormat.formatToCharacterIterator() method returns.
210      * <p>
211      * There is no public constructor to this class, the only instances are the
212      * constants defined here.
213      * <p>
214      * @stable ICU 3.8
215      */
216     public static class Field extends DateFormat.Field {
217
218         private static final long serialVersionUID = -5102130532751400330L;
219
220         /**
221          * Constant identifying the leap month marker.
222          * @stable ICU 3.8
223          */
224         public static final Field IS_LEAP_MONTH = new Field("is leap month", ChineseCalendar.IS_LEAP_MONTH);
225
226         /**
227          * Constructs a <code>ChineseDateFormat.Field</code> with the given name and
228          * the <code>ChineseCalendar</code> field which this attribute represents.
229          * Use -1 for <code>calendarField</code> if this field does not have a
230          * corresponding <code>ChineseCalendar</code> field.
231          * 
232          * @param name          Name of the attribute
233          * @param calendarField <code>Calendar</code> field constant
234          * 
235          * @stable ICU 3.8
236          */
237         protected Field(String name, int calendarField) {
238             super(name, calendarField);
239         }
240
241         /**
242          * Returns the <code>Field</code> constant that corresponds to the <code>
243          * ChineseCalendar</code> field <code>calendarField</code>.  If there is no
244          * corresponding <code>Field</code> is available, null is returned.
245          * 
246          * @param calendarField <code>ChineseCalendar</code> field constant
247          * @return <code>Field</code> associated with the <code>calendarField</code>,
248          * or null if no associated <code>Field</code> is available.
249          * @throws IllegalArgumentException if <code>calendarField</code> is not
250          * a valid <code>Calendar</code> field constant.
251          * 
252          * @stable ICU 3.8
253          */
254         public static DateFormat.Field ofCalendarField(int calendarField) {
255             if (calendarField == ChineseCalendar.IS_LEAP_MONTH) {
256                 return IS_LEAP_MONTH;
257             }
258             return DateFormat.Field.ofCalendarField(calendarField);
259         }
260
261         /**
262          * {@inheritDoc}
263          * 
264          * @stable ICU 3.8
265          */
266         protected Object readResolve() throws InvalidObjectException {
267             if (this.getClass() != ChineseDateFormat.Field.class) {
268                 throw new InvalidObjectException("A subclass of ChineseDateFormat.Field must implement readResolve.");
269             }
270             if (this.getName().equals(IS_LEAP_MONTH.getName())) {
271                 return IS_LEAP_MONTH;
272             } else {
273                 throw new InvalidObjectException("Unknown attribute name.");
274             }
275         }
276     }
277 //#endif
278 }