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