001: /*********************************************************************
002: * Copyright (C) 2000-2006, International Business Machines Corporation and
003: * others. All Rights Reserved.
004: *********************************************************************
005: */package com.ibm.icu.text;
006:
007: import com.ibm.icu.util.*;
008: import com.ibm.icu.impl.Utility;
009: import java.text.FieldPosition;
010: import java.text.ParsePosition;
011: import java.util.Locale;
012:
013: /**
014: * A concrete {@link DateFormat} for {@link com.ibm.icu.util.ChineseCalendar}.
015: * This class handles a <code>ChineseCalendar</code>-specific field,
016: * <code>ChineseCalendar.IS_LEAP_MONTH</code>. It also redefines the
017: * handling of two fields, <code>ERA</code> and <code>YEAR</code>. The
018: * former is displayed numerically, instead of symbolically, since it is
019: * the numeric cycle number in <code>ChineseCalendar</code>. The latter is
020: * numeric, as before, but has no special 2-digit Y2K behavior.
021: *
022: * <p>With regard to <code>ChineseCalendar.IS_LEAP_MONTH</code>, this
023: * class handles parsing specially. If no string symbol is found at all,
024: * this is taken as equivalent to an <code>IS_LEAP_MONTH</code> value of
025: * zero. This allows formats to display a special string (e.g., "*") for
026: * leap months, but no string for normal months.
027: *
028: * <p>Summary of field changes vs. {@link SimpleDateFormat}:<pre>
029: * Symbol Meaning Presentation Example
030: * ------ ------- ------------ -------
031: * G cycle (Number) 78
032: * y year of cycle (1..60) (Number) 17
033: * l is leap month (Text) 4637
034: * </pre>
035: *
036: * @see com.ibm.icu.util.ChineseCalendar
037: * @see ChineseDateFormatSymbols
038: * @author Alan Liu
039: * @stable ICU 2.0
040: */
041: public class ChineseDateFormat extends SimpleDateFormat {
042: // Generated by serialver from JDK 1.4.1_01
043: static final long serialVersionUID = -4610300753104099899L;
044:
045: // TODO Finish the constructors
046:
047: /**
048: * Construct a ChineseDateFormat from a date format pattern and locale
049: * @param pattern the pattern
050: * @param locale the locale
051: * @stable ICU 2.0
052: */
053: public ChineseDateFormat(String pattern, Locale locale) {
054: // TODO: convert to use ULocale
055: super (pattern, new ChineseDateFormatSymbols(locale), true);
056: }
057:
058: /**
059: * Construct a ChineseDateFormat from a date format pattern and locale
060: * @param pattern the pattern
061: * @param locale the locale
062: * @draft ICU 3.2
063: * @provisional This API might change or be removed in a future release.
064: */
065: public ChineseDateFormat(String pattern, ULocale locale) {
066: // TODO: convert CDFS to use ULocale
067: //super(pattern, new ChineseDateFormatSymbols(locale.toLocale()), true);
068: super (pattern, new ChineseDateFormatSymbols(locale), locale);
069: }
070:
071: // NOTE: This API still exists; we just inherit it from SimpleDateFormat
072: // as of ICU 3.0
073: // /**
074: // * @stable ICU 2.0
075: // */
076: // protected String subFormat(char ch, int count, int beginOffset,
077: // FieldPosition pos, DateFormatSymbols formatData,
078: // Calendar cal) {
079: // switch (ch) {
080: // case 'G': // 'G' - ERA
081: // return zeroPaddingNumber(cal.get(Calendar.ERA), 1, 9);
082: // case 'l': // 'l' - IS_LEAP_MONTH
083: // {
084: // ChineseDateFormatSymbols symbols =
085: // (ChineseDateFormatSymbols) formatData;
086: // return symbols.getLeapMonth(cal.get(
087: // ChineseCalendar.IS_LEAP_MONTH));
088: // }
089: // default:
090: // return super.subFormat(ch, count, beginOffset, pos, formatData, cal);
091: // }
092: // }
093:
094: /**
095: * @internal
096: * @deprecated This API is ICU internal only.
097: */
098: protected void subFormat(StringBuffer buf, char ch, int count,
099: int beginOffset, FieldPosition pos, Calendar cal) {
100: switch (ch) {
101: case 'G': // 'G' - ERA
102: zeroPaddingNumber(buf, cal.get(Calendar.ERA), 1, 9);
103: break;
104: case 'l': // 'l' - IS_LEAP_MONTH
105: buf.append(((ChineseDateFormatSymbols) getSymbols())
106: .getLeapMonth(cal
107: .get(ChineseCalendar.IS_LEAP_MONTH)));
108: break;
109: default:
110: super .subFormat(buf, ch, count, beginOffset, pos, cal);
111: break;
112: }
113:
114: // TODO: add code to set FieldPosition for 'G' and 'l' fields. This
115: // is a DESIGN FLAW -- subclasses shouldn't have to duplicate the
116: // code that handles this at the end of SimpleDateFormat.subFormat.
117: // The logic should be moved up into SimpleDateFormat.format.
118: }
119:
120: /**
121: * @stable ICU 2.0
122: */
123: protected int subParse(String text, int start, char ch, int count,
124: boolean obeyCount, boolean allowNegative,
125: boolean[] ambiguousYear, Calendar cal) {
126: if (ch != 'G' && ch != 'l' && ch != 'y') {
127: return super .subParse(text, start, ch, count, obeyCount,
128: allowNegative, ambiguousYear, cal);
129: }
130:
131: // Skip whitespace
132: start = Utility.skipWhitespace(text, start);
133:
134: ParsePosition pos = new ParsePosition(start);
135:
136: switch (ch) {
137: case 'G': // 'G' - ERA
138: case 'y': // 'y' - YEAR, but without the 2-digit Y2K adjustment
139: {
140: Number number = null;
141: if (obeyCount) {
142: if ((start + count) > text.length()) {
143: return -start;
144: }
145: number = numberFormat.parse(text.substring(0, start
146: + count), pos);
147: } else {
148: number = numberFormat.parse(text, pos);
149: }
150: if (number == null) {
151: return -start;
152: }
153: int value = number.intValue();
154: cal.set(ch == 'G' ? Calendar.ERA : Calendar.YEAR, value);
155: return pos.getIndex();
156: }
157: case 'l': // 'l' - IS_LEAP_MONTH
158: {
159: ChineseDateFormatSymbols symbols = (ChineseDateFormatSymbols) getSymbols();
160: int result = matchString(text, start,
161: ChineseCalendar.IS_LEAP_MONTH, symbols.isLeapMonth,
162: cal);
163: // Treat the absence of any matching string as setting
164: // IS_LEAP_MONTH to false.
165: if (result < 0) {
166: cal.set(ChineseCalendar.IS_LEAP_MONTH, 0);
167: result = start;
168: }
169: return result;
170: }
171: default:
172: ///CLOVER:OFF
173: return 0; // This can never happen
174: ///CLOVER:ON
175: }
176: }
177: }
|