2 /*********************************************************************
\r
3 * Copyright (C) 2000-2009, International Business Machines Corporation and
\r
4 * others. All Rights Reserved.
\r
5 *********************************************************************
\r
7 package com.ibm.icu.text;
\r
8 import com.ibm.icu.util.*;
\r
9 import com.ibm.icu.impl.Utility;
\r
11 import java.text.FieldPosition;
\r
12 import java.text.ParsePosition;
\r
13 import java.util.Locale;
\r
14 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
16 import java.io.InvalidObjectException;
\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
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
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
42 * @see com.ibm.icu.util.ChineseCalendar
\r
43 * @see ChineseDateFormatSymbols
\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
51 // TODO Finish the constructors
\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
59 public ChineseDateFormat(String pattern, Locale locale) {
\r
60 this(pattern, ULocale.forLocale(locale));
\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
69 public ChineseDateFormat(String pattern, ULocale locale) {
\r
70 this(pattern, null, locale);
\r
74 * Construct a ChineseDateFormat from a date format pattern and locale
\r
75 * @param pattern the pattern
\r
76 * @param locale the locale
\r
79 public ChineseDateFormat(String pattern, String override, ULocale locale) {
\r
80 super(pattern, new ChineseDateFormatSymbols(locale),
\r
81 new ChineseCalendar(TimeZone.getDefault(), locale), locale, true, override);
\r
84 // NOTE: This API still exists; we just inherit it from SimpleDateFormat
\r
87 // * @stable ICU 2.0
\r
89 // protected String subFormat(char ch, int count, int beginOffset,
\r
90 // FieldPosition pos, DateFormatSymbols formatData,
\r
93 // case 'G': // 'G' - ERA
\r
94 // return zeroPaddingNumber(cal.get(Calendar.ERA), 1, 9);
\r
95 // case 'l': // 'l' - IS_LEAP_MONTH
\r
97 // ChineseDateFormatSymbols symbols =
\r
98 // (ChineseDateFormatSymbols) formatData;
\r
99 // return symbols.getLeapMonth(cal.get(
\r
100 // ChineseCalendar.IS_LEAP_MONTH));
\r
103 // return super.subFormat(ch, count, beginOffset, pos, formatData, cal);
\r
110 * @deprecated This API is ICU internal only.
\r
112 protected void subFormat(StringBuffer buf,
\r
113 char ch, int count, int beginOffset,
\r
118 case 'G': // 'G' - ERA
\r
119 zeroPaddingNumber(numberFormat,buf, cal.get(Calendar.ERA), 1, 9);
\r
121 case 'l': // 'l' - IS_LEAP_MONTH
\r
122 buf.append(((ChineseDateFormatSymbols) getSymbols()).
\r
123 getLeapMonth(cal.get(ChineseCalendar.IS_LEAP_MONTH)));
\r
126 super.subFormat(buf, ch, count, beginOffset, pos, cal);
\r
130 // TODO: add code to set FieldPosition for 'G' and 'l' fields. This
\r
131 // is a DESIGN FLAW -- subclasses shouldn't have to duplicate the
\r
132 // code that handles this at the end of SimpleDateFormat.subFormat.
\r
133 // The logic should be moved up into SimpleDateFormat.format.
\r
140 protected int subParse(String text, int start, char ch, int count,
\r
141 boolean obeyCount, boolean allowNegative, boolean[] ambiguousYear, Calendar cal) {
\r
142 if (ch != 'G' && ch != 'l' && ch != 'y') {
\r
143 return super.subParse(text, start, ch, count, obeyCount, allowNegative, ambiguousYear, cal);
\r
147 start = Utility.skipWhitespace(text, start);
\r
149 ParsePosition pos = new ParsePosition(start);
\r
152 case 'G': // 'G' - ERA
\r
153 case 'y': // 'y' - YEAR, but without the 2-digit Y2K adjustment
\r
155 Number number = null;
\r
157 if ((start+count) > text.length()) {
\r
160 number = numberFormat.parse(text.substring(0, start+count), pos);
\r
162 number = numberFormat.parse(text, pos);
\r
164 if (number == null) {
\r
167 int value = number.intValue();
\r
168 cal.set(ch == 'G' ? Calendar.ERA : Calendar.YEAR, value);
\r
169 return pos.getIndex();
\r
171 case 'l': // 'l' - IS_LEAP_MONTH
\r
173 ChineseDateFormatSymbols symbols =
\r
174 (ChineseDateFormatSymbols) getSymbols();
\r
175 int result = matchString(text, start, ChineseCalendar.IS_LEAP_MONTH,
\r
176 symbols.isLeapMonth, cal);
\r
177 // Treat the absence of any matching string as setting
\r
178 // IS_LEAP_MONTH to false.
\r
180 cal.set(ChineseCalendar.IS_LEAP_MONTH, 0);
\r
187 return 0; // This can never happen
\r
192 //#if defined(FOUNDATION10) || defined(J2SE13)
\r
199 protected DateFormat.Field patternCharToDateFormatField(char ch) {
\r
201 return ChineseDateFormat.Field.IS_LEAP_MONTH;
\r
203 return super.patternCharToDateFormatField(ch);
\r
207 * The instances of this inner class are used as attribute keys and values
\r
208 * in AttributedCharacterIterator that
\r
209 * ChineseDateFormat.formatToCharacterIterator() method returns.
\r
211 * There is no public constructor to this class, the only instances are the
\r
212 * constants defined here.
\r
216 public static class Field extends DateFormat.Field {
\r
218 private static final long serialVersionUID = -5102130532751400330L;
\r
221 * Constant identifying the leap month marker.
\r
224 public static final Field IS_LEAP_MONTH = new Field("is leap month", ChineseCalendar.IS_LEAP_MONTH);
\r
227 * Constructs a <code>ChineseDateFormat.Field</code> with the given name and
\r
228 * the <code>ChineseCalendar</code> field which this attribute represents.
\r
229 * Use -1 for <code>calendarField</code> if this field does not have a
\r
230 * corresponding <code>ChineseCalendar</code> field.
\r
232 * @param name Name of the attribute
\r
233 * @param calendarField <code>Calendar</code> field constant
\r
237 protected Field(String name, int calendarField) {
\r
238 super(name, calendarField);
\r
242 * Returns the <code>Field</code> constant that corresponds to the <code>
\r
243 * ChineseCalendar</code> field <code>calendarField</code>. If there is no
\r
244 * corresponding <code>Field</code> is available, null is returned.
\r
246 * @param calendarField <code>ChineseCalendar</code> field constant
\r
247 * @return <code>Field</code> associated with the <code>calendarField</code>,
\r
248 * or null if no associated <code>Field</code> is available.
\r
249 * @throws IllegalArgumentException if <code>calendarField</code> is not
\r
250 * a valid <code>Calendar</code> field constant.
\r
254 public static DateFormat.Field ofCalendarField(int calendarField) {
\r
255 if (calendarField == ChineseCalendar.IS_LEAP_MONTH) {
\r
256 return IS_LEAP_MONTH;
\r
258 return DateFormat.Field.ofCalendarField(calendarField);
\r
266 protected Object readResolve() throws InvalidObjectException {
\r
267 if (this.getClass() != ChineseDateFormat.Field.class) {
\r
268 throw new InvalidObjectException("A subclass of ChineseDateFormat.Field must implement readResolve.");
\r
270 if (this.getName().equals(IS_LEAP_MONTH.getName())) {
\r
271 return IS_LEAP_MONTH;
\r
273 throw new InvalidObjectException("Unknown attribute name.");
\r