2 /*********************************************************************
3 * Copyright (C) 2000-2009, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 *********************************************************************
7 package com.ibm.icu.text;
8 import com.ibm.icu.util.*;
9 import com.ibm.icu.impl.Utility;
11 import java.text.FieldPosition;
12 import java.text.ParsePosition;
13 import java.util.Locale;
14 //#if defined(FOUNDATION10) || defined(J2SE13)
16 import java.io.InvalidObjectException;
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.
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.
34 * <p>Summary of field changes vs. {@link SimpleDateFormat}:<pre>
35 * Symbol Meaning Presentation Example
36 * ------ ------- ------------ -------
38 * y year of cycle (1..60) (Number) 17
39 * l is leap month (Text) 4637
42 * @see com.ibm.icu.util.ChineseCalendar
43 * @see ChineseDateFormatSymbols
47 public class ChineseDateFormat extends SimpleDateFormat {
48 // Generated by serialver from JDK 1.4.1_01
49 static final long serialVersionUID = -4610300753104099899L;
51 // TODO Finish the constructors
54 * Construct a ChineseDateFormat from a date format pattern and locale
55 * @param pattern the pattern
56 * @param locale the locale
59 public ChineseDateFormat(String pattern, Locale locale) {
60 this(pattern, ULocale.forLocale(locale));
64 * Construct a ChineseDateFormat from a date format pattern and locale
65 * @param pattern the pattern
66 * @param locale the locale
69 public ChineseDateFormat(String pattern, ULocale locale) {
70 this(pattern, null, locale);
74 * Construct a ChineseDateFormat from a date format pattern and locale
75 * @param pattern the pattern
76 * @param locale the locale
79 public ChineseDateFormat(String pattern, String override, ULocale locale) {
80 super(pattern, new ChineseDateFormatSymbols(locale),
81 new ChineseCalendar(TimeZone.getDefault(), locale), locale, true, override);
84 // NOTE: This API still exists; we just inherit it from SimpleDateFormat
89 // protected String subFormat(char ch, int count, int beginOffset,
90 // FieldPosition pos, DateFormatSymbols formatData,
93 // case 'G': // 'G' - ERA
94 // return zeroPaddingNumber(cal.get(Calendar.ERA), 1, 9);
95 // case 'l': // 'l' - IS_LEAP_MONTH
97 // ChineseDateFormatSymbols symbols =
98 // (ChineseDateFormatSymbols) formatData;
99 // return symbols.getLeapMonth(cal.get(
100 // ChineseCalendar.IS_LEAP_MONTH));
103 // return super.subFormat(ch, count, beginOffset, pos, formatData, cal);
110 * @deprecated This API is ICU internal only.
112 protected void subFormat(StringBuffer buf,
113 char ch, int count, int beginOffset,
118 case 'G': // 'G' - ERA
119 zeroPaddingNumber(numberFormat,buf, cal.get(Calendar.ERA), 1, 9);
121 case 'l': // 'l' - IS_LEAP_MONTH
122 buf.append(((ChineseDateFormatSymbols) getSymbols()).
123 getLeapMonth(cal.get(ChineseCalendar.IS_LEAP_MONTH)));
126 super.subFormat(buf, ch, count, beginOffset, pos, cal);
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.
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);
147 start = Utility.skipWhitespace(text, start);
149 ParsePosition pos = new ParsePosition(start);
152 case 'G': // 'G' - ERA
153 case 'y': // 'y' - YEAR, but without the 2-digit Y2K adjustment
155 Number number = null;
157 if ((start+count) > text.length()) {
160 number = numberFormat.parse(text.substring(0, start+count), pos);
162 number = numberFormat.parse(text, pos);
164 if (number == null) {
167 int value = number.intValue();
168 cal.set(ch == 'G' ? Calendar.ERA : Calendar.YEAR, value);
169 return pos.getIndex();
171 case 'l': // 'l' - IS_LEAP_MONTH
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.
180 cal.set(ChineseCalendar.IS_LEAP_MONTH, 0);
187 return 0; // This can never happen
192 //#if defined(FOUNDATION10) || defined(J2SE13)
199 protected DateFormat.Field patternCharToDateFormatField(char ch) {
201 return ChineseDateFormat.Field.IS_LEAP_MONTH;
203 return super.patternCharToDateFormatField(ch);
207 * The instances of this inner class are used as attribute keys and values
208 * in AttributedCharacterIterator that
209 * ChineseDateFormat.formatToCharacterIterator() method returns.
211 * There is no public constructor to this class, the only instances are the
212 * constants defined here.
216 public static class Field extends DateFormat.Field {
218 private static final long serialVersionUID = -5102130532751400330L;
221 * Constant identifying the leap month marker.
224 public static final Field IS_LEAP_MONTH = new Field("is leap month", ChineseCalendar.IS_LEAP_MONTH);
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.
232 * @param name Name of the attribute
233 * @param calendarField <code>Calendar</code> field constant
237 protected Field(String name, int calendarField) {
238 super(name, calendarField);
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.
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.
254 public static DateFormat.Field ofCalendarField(int calendarField) {
255 if (calendarField == ChineseCalendar.IS_LEAP_MONTH) {
256 return IS_LEAP_MONTH;
258 return DateFormat.Field.ofCalendarField(calendarField);
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.");
270 if (this.getName().equals(IS_LEAP_MONTH.getName())) {
271 return IS_LEAP_MONTH;
273 throw new InvalidObjectException("Unknown attribute name.");