/* * ----------------------------------------------------------------------- * Copyright © 2013-2016 Meno Hochschild, <http://www.menodata.de/> * ----------------------------------------------------------------------- * This file (PatternType.java) is part of project Time4J. * * Time4J is free software: You can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 2.1 of the License, or * (at your option) any later version. * * Time4J is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Time4J. If not, see <http://www.gnu.org/licenses/>. * ----------------------------------------------------------------------- */ package net.time4j.format.expert; import net.time4j.Moment; import net.time4j.PlainDate; import net.time4j.PlainTime; import net.time4j.Weekday; import net.time4j.Weekmodel; import net.time4j.engine.BridgeChronology; import net.time4j.engine.ChronoElement; import net.time4j.engine.ChronoExtension; import net.time4j.engine.Chronology; import net.time4j.engine.EpochDays; import net.time4j.format.Attributes; import net.time4j.format.CalendarText; import net.time4j.format.CalendarType; import net.time4j.format.ChronoPattern; import net.time4j.format.DisplayMode; import net.time4j.format.FormatEngine; import net.time4j.format.NumberSystem; import net.time4j.format.OutputContext; import net.time4j.format.TextElement; import net.time4j.format.TextWidth; import net.time4j.history.ChronoHistory; import net.time4j.history.internal.HistorizedElement; import net.time4j.i18n.UltimateFormatEngine; import java.util.Collections; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Set; /** * <p>Collection of different format patterns. </p> * * @author Meno Hochschild * @see net.time4j.format.expert.ChronoFormatter.Builder#addPattern(String, PatternType) * @since 3.0 */ /*[deutsch] * <p>Sammlung von verschiedenen Standard-Formatmustern. </p> * * @author Meno Hochschild * @see net.time4j.format.expert.ChronoFormatter.Builder#addPattern(String, PatternType) * @since 3.0 */ public enum PatternType implements ChronoPattern<PatternType> { //~ Statische Felder/Initialisierungen -------------------------------- /** * <p>This standard pattern is applicable on many chronologies and follows the standard * <a href="http://www.unicode.org/reports/tr35/tr35-dates.html">LDML</a> of unicode-consortium. </p> * * <p>If not explicitly stated otherwise the count of symbols always * controls the minimum count of digits in case of a numerical element. * Is an element shorter then the zero digit will be used for padding. </p> * * <p>Non-ISO-chronologies are also supported if their elements define CLDR-symbols. </p> * * <div style="margin-top:5px;"> * <table border="1"> * <caption>Legend</caption> * <tr> * <th>Element</th> * <th>Symbol</th> * <th>Description</th> * </tr> * <tr> * <td>{@link ChronoHistory#era() ERA}</td> * <td>G</td> * <td>One to three symbols indicate an abbreviation, four symbols * indicate the long form and five symbols stand for a letter. The era * is based on the chronological history of the current format locale. </td> * </tr> * <tr> * <td>{@link ChronoHistory#yearOfEra() YEAR_OF_ERA}</td> * <td>y</td> * <td>The count of symbols normally controls the minimum count of * digits. If it is 2 however then the year will be printed with * exact two digits using the attribute {@link Attributes#PIVOT_YEAR}. * Important: If the era is not present then this symbol will simply * be mapped to {@link PlainDate#YEAR}. </td> * </tr> * <tr> * <td>{@link PlainDate#YEAR_OF_WEEKDATE}</td> * <td>Y</td> * <td>Represents the year in an ISO-8601 week date and behaves * like the calendar year in formatting. The week-based year can * deviate from the calendar year however because it is bound to * the week cycle. </td> * </tr> * <tr> * <td>{@link PlainDate#YEAR}</td> * <td>u</td> * <td>Proleptic ISO-8601 calendar year. This year never uses * a pivot year, also not for "uu". A positive sign * will be used exactly if the year has more digits than given * by count of symbols. In contrast to the symbol y, this year * can never be the historized year-of-era. </td> * </tr> * <tr> * <td>RELATED_GREGORIAN_YEAR</td> * <td>r</td> * <td>The related gregorian year corresponds to the begin of the calendar year * in non-gregorian calender systems. In ISO-calendar systems, it is identical * to the proleptic ISO-8601 calendar year. For formatting or parsing, only the * ASCII-digits 0-9 will be used, even if other parts of the format use * alternative digits or other numeral systems. The count of symbols is * defined within the range 1-9. </td> * </tr> * <tr> * <td>{@link PlainDate#QUARTER_OF_YEAR}</td> * <td>Q</td> * <td>One or two symbols for the numerical form, three symbols * for the abbreviation, four for the full name and five for * a letter symbol (NARROW). </td> * </tr> * <tr> * <td>{@link PlainDate#QUARTER_OF_YEAR}</td> * <td>q</td> * <td>Like Q, but in the version {@link OutputContext#STANDALONE}. * In some languages (not english) the stand-alone-version requires * a special grammar. </td> * </tr> * <tr> * <td>MONTH_OF_YEAR</td> * <td>M</td> * <td>One or two symbols for the numerical form, three symbols * for the abbreviation, four for the full name and five for * a letter symbol (NARROW). Important: If the era is not present * then this symbol will simply be mapped to {@link PlainDate#MONTH_OF_YEAR}. </td> * </tr> * <tr> * <td>MONTH_OF_YEAR</td> * <td>L</td> * <td>Like M, but in the version {@link OutputContext#STANDALONE}. * In some languages (not english) the stand-alone-version requires * a special grammar. </td> * </tr> * <tr> * <td>{@link Weekmodel#weekOfYear()}</td> * <td>w</td> * <td>One or two symbols for the country-dependent week of year. </td> * </tr> * <tr> * <td>{@link Weekmodel#weekOfMonth()}</td> * <td>W</td> * <td>One symbol for the country-dependent week of month. </td> * </tr> * <tr> * <td>DAY_OF_MONTH</td> * <td>d</td> * <td>One or two symbols for the day of month. Important: If the era is not present * then this symbol will simply be mapped to {@link PlainDate#DAY_OF_MONTH}. </td> * </tr> * <tr> * <td>DAY_OF_YEAR</td> * <td>D</td> * <td>One, two or three symbols for the day of year. Important: If the era is not present * then this symbol will simply be mapped to {@link PlainDate#DAY_OF_YEAR}. </td> * </tr> * <tr> * <td>{@link PlainDate#WEEKDAY_IN_MONTH}</td> * <td>F</td> * <td>One symbol for the weekday in month. </td> * </tr> * <tr> * <td>{@link EpochDays#MODIFIED_JULIAN_DATE}</td> * <td>g</td> * <td>The count of symbols usually controls the minimum count of * digits of modified julian year, that is the count of days relative * to 1858-11-17. Is only supported by calendrical types like * {@code PlainDate}. </td> * </tr> * <tr> * <td>{@link PlainDate#DAY_OF_WEEK}</td> * <td>E</td> * <td>One to three symbols for the abbreviation, four for the full * name, five for a letter symbol or six for the short form. </td> * </tr> * <tr> * <td>{@link Weekmodel#localDayOfWeek()}</td> * <td>e</td> * <td>Like E, but if there are only one or two symbols then the * formatter will choose the localized numerical form. </td> * </tr> * <tr> * <td>{@link Weekmodel#localDayOfWeek()}</td> * <td>c</td> * <td>Like e, but in the version {@link OutputContext#STANDALONE}. * In some languages (not english) the stand-alone-version requires * a special grammar. However, 2 symbols are not allowed. </td> * </tr> * <tr> * <td>{@link PlainTime#AM_PM_OF_DAY}</td> * <td>a</td> * <td>1-3 symbols for the short form, 4 symbols for the full text form * and 5 symbols for the narrow form. </td> * </tr> * <tr> * <td>{@link net.time4j.DayPeriod#fixed()}</td> * <td>b</td> * <td>1-3 symbols for the short form, 4 symbols for the full text form * and 5 symbols for the narrow form. </td> * </tr> * <tr> * <td>{@link net.time4j.DayPeriod#approximate()}</td> * <td>B</td> * <td>1-3 symbols for the short form, 4 symbols for the full text form * and 5 symbols for the narrow form. </td> * </tr> * <tr> * <td>{@link PlainTime#CLOCK_HOUR_OF_AMPM}</td> * <td>h</td> * <td>One or two symbols for the numerical form. </td> * </tr> * <tr> * <td>{@link PlainTime#DIGITAL_HOUR_OF_DAY}</td> * <td>H</td> * <td>One or two symbols for the numerical form. </td> * </tr> * <tr> * <td>{@link PlainTime#DIGITAL_HOUR_OF_AMPM}</td> * <td>K</td> * <td>One or two symbols for the numerical form. </td> * </tr> * <tr> * <td>{@link PlainTime#CLOCK_HOUR_OF_DAY}</td> * <td>k</td> * <td>One or two symbols for the numerical form. </td> * </tr> * <tr> * <td>{@link PlainTime#MINUTE_OF_HOUR}</td> * <td>m</td> * <td>One or two symbols for the numerical form. </td> * </tr> * <tr> * <td>{@link PlainTime#SECOND_OF_MINUTE}</td> * <td>s</td> * <td>One or two symbols for the numerical form. </td> * </tr> * <tr> * <td>{@link PlainTime#NANO_OF_SECOND}</td> * <td>S</td> * <td>The count of symbols (1-9) controls the minimum and maximum * count of digits to be printed. The decimal separation char will * not be printed. </td> * </tr> * <tr> * <td>{@link PlainTime#MILLI_OF_DAY}</td> * <td>A</td> * <td>The count of symbols (1-9) controls the minimum * count of digits to be printed. </td> * </tr> * <tr> * <td>TIMEZONE_NAME</td> * <td>z</td> * <td>1-3 symbols for the abbreviation, 4 symbols for the full * timezone name. The specific non-location format will be used, * for example "Pacific Daylight Time" (PDT) or * "Pacific Standard Time" (PST). This symbol * can only be applied on the type {@link Moment}.</td> * </tr> * <tr> * <td>TIMEZONE_OFFSET</td> * <td>Z</td> * <td>1-3 symbols => see xxxx, 4 symbols => see OOOO, * 5 symbols = > see XXXXX.</td> * </tr> * <tr> * <td>LOCALIZED_GMT_OFFSET</td> * <td>O</td> * <td>One symbol for the abbreviation or 4 symbols for the long * variant. The GMT-prefix can be suppressed by help of the format * attribute {@link Attributes#NO_GMT_PREFIX}. See also * {@link ChronoFormatter.Builder#addLongLocalizedOffset()} * or its short counter part. </td> * </tr> * <tr> * <td>TIMEZONE_ID</td> * <td>V</td> * <td>The count of pattern symbols must always be 2. This symbol * can only be applied on the type {@link Moment}. </td> * </tr> * <tr> * <td>ISO_TIMEZONE_OFFSET</td> * <td>X</td> * <td>One symbol: ±HH[mm], two symbols: ±HHmm, three * symbols: ±HH:mm, four symbols: ±HHmm[ss[.{fraction}]], * five symbols: ±HH:mm[:ss[.{fraction}]]. If the timezone * offset is equal to {@code 0} then the letter "Z" will * be used. </td> * </tr> * <tr> * <td>ISO_TIMEZONE_OFFSET</td> * <td>x</td> * <td>Like X but without the special char "Z" if the * timezone offset is equal to {@code 0}. </td> * </tr> * </table> * </div> * * <p>Special notes for the Ethiopian calendar: </p> * * <p>The Ethiopian year will use the Ethiopic numerals in Amharic. This default behaviour can be overridden * on builder-level. And the clock time (symbol "h") will use the Ethiopian time starting * at 6 AM in the morning. </p> */ /*[deutsch] * <p>Dieses Standardmuster ist auf viele Chronologien anwendbar und folgt der Norm * <a href="http://www.unicode.org/reports/tr35/tr35-dates.html">LDML</a> * des Unicode-Konsortiums. </p> * * <p>Wenn nicht explizit anders angegeben, steuert die Anzahl der Symbole * immer die minimale Anzahl der zu formatierenden Stellen, ein numerisches * Element vorausgesetzt. Ist also ein Element in der Darstellung * kürzer, dann wird mit der Null-Ziffer aufgefüllt. </p> * * <p>Nicht-ISO-Chronologien werden auch unterstützt, wenn ihre Elemente CLDR-Symbole definieren. </p> * * <div style="margin-top:5px;"> * <table border="1"> * <caption>Legende</caption> * <tr> * <th>Element</th> * <th>Symbol</th> * <th>Beschreibung</th> * </tr> * <tr> * <td>{@link ChronoHistory#era() ERA}</td> * <td>G</td> * <td>Ein bis drei Symbole implizieren eine Abkürzung, vier * Symbole die Langform und fünf Symbole stehen für ein * Buchstabensymbol. Die Ära basiert auf dem Ausdruck * {@code ChronoHistory.of(format-locale)}. </td> * </tr> * <tr> * <td>YEAR_OF_ERA</td> * <td>y</td> * <td>Die Anzahl der Symbole regelt normalerweise die minimale * Ziffernzahl. Ist sie jedoch 2, dann wird das Jahr zweistellig * angezeigt - mit dem Attribut {@link Attributes#PIVOT_YEAR}. * Wichtig: Ist die Ära nicht im Muster vorhanden, wird dieses * Symbol dem Element {@link PlainDate#YEAR} zugeordnet. </td> * </tr> * <tr> * <td>{@link PlainDate#YEAR_OF_WEEKDATE}</td> * <td>Y</td> * <td>Entspricht dem Jahr in einem ISO-Wochendatum und verhält * sich in der Formatierung wie das Kalenderjahr. Das wochenbasierte * Jahr kann im Wochenmodell des ISO-8601-Standards vom Kalenderjahr * abweichen, weil es an den Wochenzyklus gebunden ist. </td> * </tr> * <tr> * <td>{@link PlainDate#YEAR}</td> * <td>u</td> * <td>Proleptisches ISO-Kalenderjahr. Diese Jahresangabe erfolgt * nie mit Kippjahr, auch nicht für "uu". Ein * positives Vorzeichen wird genau dann ausgegeben, wenn das Jahr * mehr Stellen hat als an Symbolen vorgegeben. Im Kontrast zum * Symbol y kann dieses Jahr niemals das historische Jahr einer * Ära sein. </td> * </tr> * <tr> * <td>RELATED_GREGORIAN_YEAR</td> * <td>r</td> * <td>In nicht-gregorianischen Kalendersystemen entspricht es dem * ISO-Jahr des Beginns des jeweiligen Kalenderjahres. Für ISO-Kalender * ist es identisch mit dem proleptischen ISO-Kalenderjahr. Zur Formatierung * werden immer die ASCII-Ziffern 0-9 verwendet, selbst wenn andere Teile * des Formats andere numerische Ziffern oder sogar andere Numeralsystem * verwenden. </td> * </tr> * <tr> * <td>{@link PlainDate#QUARTER_OF_YEAR}</td> * <td>Q</td> * <td>Ein oder zwei Symbole für die numerische Form, drei * für die Abkürzung, vier für den vollen Namen * oder fünf für ein Buchstabensymbol (NARROW). * </tr> * <tr> * <td>{@link PlainDate#QUARTER_OF_YEAR}</td> * <td>q</td> * <td>Wie Q, aber in der {@link OutputContext#STANDALONE * Stand-Alone-Version}. In manchen Sprachen (nicht englisch) * erfordert die alleinstehende Variante eine besondere * Deklination. </td> * </tr> * <tr> * <td>MONTH_OF_YEAR</td> * <td>M</td> * <td>Ein oder zwei Symbole für die numerische Form, drei * für die Abkürzung, vier für den vollen Namen * oder fünf für ein Buchstabensymbol (NARROW). * Wichtig: Ist die Ära nicht im Muster vorhanden, wird dieses * Symbol dem Element {@link PlainDate#MONTH_OF_YEAR} zugeordnet. </td> * </tr> * <tr> * <td>MONTH_OF_YEAR</td> * <td>L</td> * <td>Wie M, aber in der {@link OutputContext#STANDALONE * Stand-Alone-Version}. In manchen Sprachen (nicht englisch) * erfordert die alleinstehende Variante eine besondere * Deklination. </td> * </tr> * <tr> * <td>{@link Weekmodel#weekOfYear()}</td> * <td>w</td> * <td>Ein oder zwei Symbole für die länderabhängige * Woche des Jahres. </td> * </tr> * <tr> * <td>{@link Weekmodel#weekOfMonth()}</td> * <td>W</td> * <td>Ein Symbol für die länderabhängige * Woche des Monats. </td> * </tr> * <tr> * <td>DAY_OF_MONTH</td> * <td>d</td> * <td>Ein oder zwei Symbole für den Tag des Monats. * Wichtig: Ist die Ära nicht im Muster vorhanden, wird dieses * Symbol dem Element {@link PlainDate#DAY_OF_MONTH} zugeordnet.</td> * </tr> * <tr> * <td>DAY_OF_YEAR</td> * <td>D</td> * <td>Ein, zwei oder drei Symbole für den Tag des Jahres. * Wichtig: Ist die Ära nicht im Muster vorhanden, wird dieses * Symbol dem Element {@link PlainDate#DAY_OF_YEAR} zugeordnet. </td> * </tr> * <tr> * <td>{@link PlainDate#WEEKDAY_IN_MONTH}</td> * <td>F</td> * <td>Ein Symbol für den Wochentag im Monat. </td> * </tr> * <tr> * <td>{@link EpochDays#MODIFIED_JULIAN_DATE}</td> * <td>g</td> * <td>Die Anzahl der Symbole regelt wie üblich die minimale * Anzahl der Stellen des modifizierten julianischen Jahres, also * der Anzahl der Tage seit 1858-11-17. Wird nur von reinen * Datumsklassen wie {@code PlainDate} unterstützt. </td> * </tr> * <tr> * <td>{@link PlainDate#DAY_OF_WEEK}</td> * <td>E</td> * <td>Ein bis drei Symbole für die Abkürzung, vier * für den vollen Namen, fünf für ein Buchstabensymbol * oder sechs für die Kurzform. </td> * </tr> * <tr> * <td>{@link Weekmodel#localDayOfWeek()}</td> * <td>e</td> * <td>Wie E, aber wenn ein oder zwei Symbole angegeben sind, dann * wird die lokalisierte numerische Form gewählt. </td> * </tr> * <tr> * <td>{@link Weekmodel#localDayOfWeek()}</td> * <td>c</td> * <td>Wie e, aber in der {@link OutputContext#STANDALONE * Stand-Alone-Version}. In manchen Sprachen (nicht englisch) * erfordert die alleinstehende Variante eine besondere * Deklination. Zu beachten: 2 Symbole sind nicht erlaubt. </td> * </tr> * <tr> * <td>{@link PlainTime#AM_PM_OF_DAY}</td> * <td>a</td> * <td>Ein- bis drei Symbole für die Kurzform, 4 Symbole für * die volle Textform und fünf für die Symbolform. </td> * </tr> * <tr> * <td>{@link net.time4j.DayPeriod#fixed()}</td> * <td>b</td> * <td>Ein- bis drei Symbole für die Kurzform, 4 Symbole für * die volle Textform und fünf für die Symbolform. </td> * </tr> * <tr> * <td>{@link net.time4j.DayPeriod#approximate()}</td> * <td>B</td> * <td>Ein- bis drei Symbole für die Kurzform, 4 Symbole für * die volle Textform und fünf für die Symbolform. </td> * </tr> * <tr> * <td>{@link PlainTime#CLOCK_HOUR_OF_AMPM}</td> * <td>h</td> * <td>Ein oder zwei Symbole für die numerische Form. </td> * </tr> * <tr> * <td>{@link PlainTime#DIGITAL_HOUR_OF_DAY}</td> * <td>H</td> * <td>Ein oder zwei Symbole für die numerische Form. </td> * </tr> * <tr> * <td>{@link PlainTime#DIGITAL_HOUR_OF_AMPM}</td> * <td>K</td> * <td>Ein oder zwei Symbole für die numerische Form. </td> * </tr> * <tr> * <td>{@link PlainTime#CLOCK_HOUR_OF_DAY}</td> * <td>k</td> * <td>Ein oder zwei Symbole für die numerische Form. </td> * </tr> * <tr> * <td>{@link PlainTime#MINUTE_OF_HOUR}</td> * <td>m</td> * <td>Ein oder zwei Symbole für die numerische Form. </td> * </tr> * <tr> * <td>{@link PlainTime#SECOND_OF_MINUTE}</td> * <td>s</td> * <td>Ein oder zwei Symbole für die numerische Form. </td> * </tr> * <tr> * <td>{@link PlainTime#NANO_OF_SECOND}</td> * <td>S</td> * <td>Die Anzahl der Symbole (1-9) regelt die minimale und maximale * Anzahl der zu formatierenden Ziffern. Das Dezimaltrennzeichen * wird nicht ausgegeben. </td> * </tr> * <tr> * <td>{@link PlainTime#MILLI_OF_DAY}</td> * <td>A</td> * <td>Die Anzahl der Symbole (1-9) regelt die minimale Anzahl der * zu formatierenden Ziffern. </td> * </tr> * <tr> * <td>TIMEZONE_NAME</td> * <td>z</td> * <td>1-3 Symbole für die Kurzform, 4 Symbole für den * langen Zeitzonennamen. Es wird das <i>specific non-location format</i> verwendet, * zum Beispiel "Pacific Daylight Time" (PDT) oder * "Pacific Standard Time" (PST). Dieses Symbol kann * nur auf den Typ {@link Moment} angewandt werden. </td> * </tr> * <tr> * <td>TIMEZONE_OFFSET</td> * <td>Z</td> * <td>1-3 Symbole => siehe xxxx, 4 Symbole => siehe OOOO, * 5 Symbole = > siehe XXXXX.</td> * </tr> * <tr> * <td>LOCALIZED_GMT_OFFSET</td> * <td>O</td> * <td>Ein Symbol für die Kurzform oder 4 Symbole für die * Langform. Das GMT-Präfix kann mit Hilfe des Attributs * {@link Attributes#NO_GMT_PREFIX} unterdrückt werden. Siehe auch * {@link ChronoFormatter.Builder#addLongLocalizedOffset()} oder * sein kurzes Gegenstück. </td> * </tr> * <tr> * <td>TIMEZONE_ID</td> * <td>V</td> * <td>Es werden immer zwei Symbole erwartet. Dieses Symbol kann * nur auf den Typ {@link Moment} angewandt werden. </td> * </tr> * <tr> * <td>ISO_TIMEZONE_OFFSET</td> * <td>X</td> * <td>Ein Symbol: ±HH[mm], zwei Symbole: ±HHmm, drei * Symbole: ±HH:mm, vier Symbole: ±HHmm[ss[.{fraction}]], * fünf Symbole: ±HH:mm[:ss[.{fraction}]]. Ist der * Zeitzonen-Offset gleich {@code 0}, dann wird das Buchstabensymbol * "Z" verwendet. </td> * </tr> * <tr> * <td>ISO_TIMEZONE_OFFSET</td> * <td>x</td> * <td>Wie X, aber ohne das Spezialzeichen "Z", wenn der * Zeitzonen-Offset gleich {@code 0} ist. </td> * </tr> * </table> * </div> * * <p>Anmerkungen für den äthiopischen Kalender: </p> * * <p>Das äthiopische Jahr wird in Amharic die äthiopischen Numerale verwenden. Dieses * Standardverhalten kann auf <i>builder</i>-Ebene überschrieben werden. Und die Uhrzeit * (Symbol "h") wird die äthiopische Variante mit 6 Uhr morgens als Tagesbeginn * nutzen. </p> */ CLDR, /** * <p>Follows the format pattern description of class * {@link java.text.SimpleDateFormat}, which is very near, but not * exactly the same as CLDR. </p> * * <p>The permitted count of digits is usually unlimited. Users should treat this setting * only as approximation to any real implementation of {@code SimpleDateFormat}. For example, * this pattern style is only applicable on ISO-compatible chronologies. Other deviations from * {@link #CLDR}: </p> * * <div style="margin-top:5px;"> * <table border="1"> * <caption>Legend</caption> * <tr> * <th>Element</th> * <th>Symbol</th> * <th>Description</th> * </tr> * <tr> * <td>ISO_DAY_OF_WEEK</td> * <td>u</td> * <td>Corresponds to the weekday-numbering of ISO-8601-standard * ({@code Weekmodel.ISO.localDayOfWeek()}), that is: * Mo=1, Di=2, Mi=3, Do=4, Fr=5, Sa=6, So=7. </td> * </tr> * <tr> * <td>{@link Weekmodel#boundedWeekOfMonth()}</td> * <td>W</td> * <td>One symbol for the country-dependent week of month. </td> * </tr> * <tr> * <td>{@link PlainTime#MILLI_OF_SECOND}</td> * <td>S</td> * <td>No fractional but only integral display of millisecond. </td> * </tr> * <tr> * <td>QUARTER_OF_YEAR</td> * <td>Q</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>QUARTER_OF_YEAR</td> * <td>q</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>RELATED_GREGORIAN_YEAR</td> * <td>r</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>MODIFIED_JULIAN_DATE</td> * <td>g</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>{local-day-of-week-number}</td> * <td>e</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>{local-day-of-week-number}</td> * <td>c</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>{@link PlainTime#AM_PM_OF_DAY}</td> * <td>a</td> * <td>Only the short form is supported. </td> * </tr> * <tr> * <td>{@link net.time4j.DayPeriod#fixed()}</td> * <td>b</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>{@link net.time4j.DayPeriod#approximate()}</td> * <td>B</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>RFC_822_TIMEZONE_OFFSET</td> * <td>Z</td> * <td>Equivalent to CLDR-xx.</td> * </tr> * <tr> * <td>LOCALIZED_GMT_OFFSET</td> * <td>O</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>TIMEZONE_ID</td> * <td>V</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>ISO_TIMEZONE_OFFSET</td> * <td>X</td> * <td>Like in CLDR, but with only three symbols as upper limit. </td> * </tr> * <tr> * <td>ISO_TIMEZONE_OFFSET</td> * <td>x</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * </table> * </div> */ /*[deutsch] * <p>Folgt der Formatmusterbeschreibung der Klasse * {@link java.text.SimpleDateFormat}, die sich stark, aber * nicht exakt an CLDR orientiert. </p> * * <p>Die erlaubte Anzahl der Symbole ist in der Regel nach oben offen. Anwender sollten * diese Einstellung nur als Näherung zu einer realen Implementierung der Klasse * {@code SimpleDateFormat} ansehen. Zum Beispiel ist dieser Musterstil nur auf * ISO-Chronologien anwendbar. Andere Unterschiede zu {@link #CLDR}: </p> * * <div style="margin-top:5px;"> * <table border="1"> * <caption>Legende</caption> * <tr> * <th>Element</th> * <th>Symbol</th> * <th>Beschreibung</th> * </tr> * <tr> * <td>ISO_DAY_OF_WEEK</td> * <td>u</td> * <td>Entspricht der Wochentagsnummerierung des * ISO-8601-Formats ({@code Weekmodel.ISO.localDayOfWeek()}), * also: Mo=1, Di=2, Mi=3, Do=4, Fr=5, Sa=6, So=7. </td> * </tr> * <tr> * <td>{@link Weekmodel#boundedWeekOfMonth()}</td> * <td>W</td> * <td>Ein Symbol für die länderabhängige * Woche des Monats. </td> * </tr> * <tr> * <td>{@link PlainTime#MILLI_OF_SECOND}</td> * <td>S</td> * <td>Keine fraktionale, sondern nur integrale Darstellung der * Millisekunde. </td> * </tr> * <tr> * <td>QUARTER_OF_YEAR</td> * <td>Q</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>QUARTER_OF_YEAR</td> * <td>q</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>RELATED_GREGORIAN_YEAR</td> * <td>r</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>MODIFIED_JULIAN_DATE</td> * <td>g</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>{local-day-of-week-number}</td> * <td>e</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>{local-day-of-week-number}</td> * <td>c</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>{@link PlainTime#AM_PM_OF_DAY}</td> * <td>a</td> * <td>Nur die Kurzform wird unterstützt. </td> * </tr> * <tr> * <td>{@link net.time4j.DayPeriod#fixed()}</td> * <td>b</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>{@link net.time4j.DayPeriod#approximate()}</td> * <td>B</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>RFC_822_TIMEZONE_OFFSET</td> * <td>Z</td> * <td>Entspricht CLDR-xx.</td> * </tr> * <tr> * <td>LOCALIZED_GMT_OFFSET</td> * <td>O</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>TIMEZONE_ID</td> * <td>V</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>ISO_TIMEZONE_OFFSET</td> * <td>X</td> * <td>Wie in CLDR, aber nur mit maximal drei Symbolen. </td> * </tr> * <tr> * <td>ISO_TIMEZONE_OFFSET</td> * <td>x</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * </table> * </div> */ SIMPLE_DATE_FORMAT, /** * <p>Follows the format pattern description of class * {@link java.time.format.DateTimeFormatter}, which is very near, but not * exactly the same as CLDR and extends it in some details. </p> * * <p>Users should treat this setting only as approximation to the real behaviour in Java-8. * For example, this pattern style is only applicable on ISO-chronologies. Other deviations * from {@link #CLDR}: </p> * * <div style="margin-top:5px;"> * <table border="1"> * <caption>Legend</caption> * <tr> * <th>Element</th> * <th>Symbol</th> * <th>Description</th> * </tr> * <tr> * <td>{@link ChronoHistory#era() ERA}</td> * <td>G</td> * <td>Like in CLDR, but related to the proleptic gregorian calendar. It is NOT the historic era. </td> * </tr> * <tr> * <td>{@link ChronoHistory#yearOfEra() YEAR_OF_ERA}</td> * <td>y</td> * <td>Like in CLDR, but related to the proleptic gregorian calendar. It is NOT * the historic year of era. Another important difference: It will use the pivot year 2100 * for the range 2000-2099 if the two-digit-form is choosen. If you want to configure the pivot * year then use {@code PatternType.CLDR} instead. </td> * </tr> * <tr> * <td>{@link PlainDate#YEAR_OF_WEEKDATE}</td> * <td>Y</td> * <td>Like in CLDR, but the two-digit-form will use the pivot year 2100 for the range 2000-2099. * If you want to configure the pivot year then use {@code PatternType.CLDR} instead. </td> * </tr> * <tr> * <td>{@link PlainDate#YEAR}</td> * <td>u</td> * <td>Like in CLDR, but the two-digit-form will use the pivot year 2100 for the range 2000-2099. * If you want to configure the pivot year then use {@code PatternType.CLDR} and the symbol yy instead. </td> * </tr> * <tr> * <td>RELATED_GREGORIAN_YEAR</td> * <td>r</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>{@link EpochDays#MODIFIED_JULIAN_DATE}</td> * <td>g</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>{@link Weekmodel#boundedWeekOfMonth()}</td> * <td>W</td> * <td>One symbol for the country-dependent week of month. </td> * </tr> * <tr> * <td>{@link PlainDate#DAY_OF_WEEK}</td> * <td>E</td> * <td>Like in CLDR, but no more than five pattern symbols are allowed. </td> * </tr> * <tr> * <td>{@link Weekmodel#localDayOfWeek()}</td> * <td>e</td> * <td>Like in CLDR, but no more than five pattern symbols are allowed. </td> * </tr> * <tr> * <td>{@link Weekmodel#localDayOfWeek()}</td> * <td>c</td> * <td>Like in CLDR, but no more than five pattern symbols are allowed. </td> * </tr> * <tr> * <td>{@link net.time4j.DayPeriod#fixed()}</td> * <td>b</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>{@link net.time4j.DayPeriod#approximate()}</td> * <td>B</td> * <td>Not supported (as work-around: use CLDR). </td> * </tr> * <tr> * <td>{@link PlainTime#NANO_OF_SECOND}</td> * <td>n</td> * <td>1-9 symbols allowed, no CLDR-equivalent. </td> * </tr> * <tr> * <td>{@link PlainTime#NANO_OF_DAY}</td> * <td>N</td> * <td>1-18 symbols allowed, no CLDR-equivalent. </td> * </tr> * <tr> * <td>{@link ChronoFormatter.Builder#padNext(int)}</td> * <td>p</td> * <td>No CLDR-equivalent. </td> * </tr> * </table> * </div> * * @since 4.0 */ /*[deutsch] * <p>Folgt der Formatmusterbeschreibung der Klasse * {@link java.time.format.DateTimeFormatter}, die sich stark, aber * nicht exakt an CLDR orientiert und letzteres in einigen Details erweitert. </p> * * <p>Anwender sollten diese Einstellung nur als Näherung zum realen Verhalten in Java-8 * ansehen. Zum Beispiel ist dieser Musterstil nur auf ISO-Chronologien anwendbar. Andere * Unterschiede zu {@link #CLDR}: </p> * * <div style="margin-top:5px;"> * <table border="1"> * <caption>Legende</caption> * <tr> * <th>Element</th> * <th>Symbol</th> * <th>Beschreibung</th> * </tr> * <tr> * <td>{@link ChronoHistory#era() ERA}</td> * <td>G</td> * <td>Wie in CLDR, aber bezogen auf den proleptisch gregorianischen Kalender. Es handelt sich nicht * um die historische Ära. </td> * </tr> * <tr> * <td>{@link ChronoHistory#yearOfEra() YEAR_OF_ERA}</td> * <td>y</td> * <td>Wie in CLDR, aber bezogen auf den proleptisch gregorianischen Kalender. Es handelt sich nicht * um das historische Jahr der Ära. Ein anderer wichtiger Unterschied: Das Kippjahr 2100 für * den Bereich 2000-2099 wird benutzt wenn eine zweistellige Jahresangabe gewählt wird. Wenn das * Kippjahr konfiguriert werden soll, dann ist {@code PatternType.CLDR} zu verwenden. </td> * </tr> * <tr> * <td>{@link PlainDate#YEAR_OF_WEEKDATE}</td> * <td>Y</td> * <td>Wie in CLDR, aber eine zweistellige Jahresangabe wird das Kippjahr 2100 für * den Bereich 2000-2099 verwenden. Wenn das Kippjahr konfiguriert werden soll, ist * {@code PatternType.CLDR} zu verwenden. </td> * </tr> * <tr> * <td>{@link PlainDate#YEAR}</td> * <td>u</td> * <td>Wie in CLDR, aber eine zweistellige Jahresangabe wird das Kippjahr 2100 für * den Bereich 2000-2099 verwenden. Wenn das Kippjahr konfiguriert werden soll, ist * {@code PatternType.CLDR} nebst dem Symbol yy zu verwenden. </td> * </tr> * <tr> * <td>RELATED_GREGORIAN_YEAR</td> * <td>r</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>{@link EpochDays#MODIFIED_JULIAN_DATE}</td> * <td>g</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>{@link Weekmodel#boundedWeekOfMonth()}</td> * <td>W</td> * <td>Ein Symbol für die länderabhängige * Woche des Monats. </td> * </tr> * <tr> * <td>{@link PlainDate#DAY_OF_WEEK}</td> * <td>E</td> * <td>Wie in CLDR, aber nicht mehr als 5 Symbole sind erlaubt. </td> * </tr> * <tr> * <td>{@link Weekmodel#localDayOfWeek()}</td> * <td>e</td> * <td>Wie in CLDR, aber nicht mehr als 5 Symbole sind erlaubt. </td> * </tr> * <tr> * <td>{@link Weekmodel#localDayOfWeek()}</td> * <td>c</td> * <td>Wie in CLDR, aber nicht mehr als 5 Symbole sind erlaubt. </td> * </tr> * <tr> * <td>{@link net.time4j.DayPeriod#fixed()}</td> * <td>b</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>{@link net.time4j.DayPeriod#approximate()}</td> * <td>B</td> * <td>Unterstützung nicht hier, sondern nur in CLDR. </td> * </tr> * <tr> * <td>{@link PlainTime#NANO_OF_SECOND}</td> * <td>n</td> * <td>1-9 Symbole erlaubt, kein CLDR-Äquivalent. </td> * </tr> * <tr> * <td>{@link PlainTime#NANO_OF_DAY}</td> * <td>N</td> * <td>1-18 Symbole erlaubt, kein CLDR-Äquivalent. </td> * </tr> * <tr> * <td>{@link ChronoFormatter.Builder#padNext(int)}</td> * <td>p</td> * <td>Kein CLDR-Äquivalent. </td> * </tr> * </table> * </div> * * @since 4.0 */ THREETEN, /** * <p>CLDR-variant with the only difference how the symbol "H" will be interpreted. </p> * * <p>Deviations from {@link #CLDR}: </p> * * <div style="margin-top:5px;"> * <table border="1"> * <caption>Legend</caption> * <tr> * <th>Element</th> * <th>Symbol</th> * <th>Description</th> * </tr> * <tr> * <td>{@link PlainTime#ISO_HOUR}</td> * <td>H</td> * <td>Hour of day as defined in ISO-8601 - in range 0-24 (the value 24 is only permitted if * all other time parts are zero). </td> * </tr> * </table> * </div> * * @since 3.4/4.3 */ /*[deutsch] * <p>CLDR-Variante, die das Symbol "H" als ISO-8601-Stunde im Bereich 0-24 interpretiert. </p> * * <p>Unterschiede zu {@link #CLDR}: </p> * * <div style="margin-top:5px;"> * <table border="1"> * <caption>Legende</caption> * <tr> * <th>Element</th> * <th>Symbol</th> * <th>Beschreibung</th> * </tr> * <tr> * <td>{@link PlainTime#ISO_HOUR}</td> * <td>H</td> * <td>Stunde des ISO-8601-Formats im Bereich 0-24 (der Wert 24 ist nur dann erlaubt, * wenn alle anderen Uhrzeitanteile {@code 0} sind). </td> * </tr> * </table> * </div> * * @since 3.4/4.3 */ CLDR_24, /** * <p>A small subset of CLDR applicable on any non-ISO-chronology which has registered the * associated elements with same symbols. </p> * * <p>If not explicitly stated otherwise the count of symbols always * controls the minimum count of digits in case of a numerical element. * Is an element shorter then the zero digit will be used for padding. </p> * * <div style="margin-top:5px;"> * <table border="1"> * <caption>Legend</caption> * <tr> * <th>Element</th> * <th>Symbol</th> * <th>Description</th> * </tr> * <tr> * <td>ERA</td> * <td>G</td> * <td>One to three symbols indicate an abbreviation, four symbols * indicate the long form and five symbols stand for a letter. </td> * </tr> * <tr> * <td>YEAR_OF_ERA</td> * <td>y</td> * <td>The count of symbols normally controls the minimum count of * digits. If it is 2 however then the year will be printed with * exact two digits using the attribute {@link Attributes#PIVOT_YEAR}. </td> * </tr> * <tr> * <td>MONTH_OF_YEAR</td> * <td>M</td> * <td>One or two symbols for the numerical form, three symbols * for the abbreviation, four for the full name and five for * a letter symbol (NARROW). </td> * </tr> * <tr> * <td>MONTH_OF_YEAR</td> * <td>L</td> * <td>Like M, but in the version {@link OutputContext#STANDALONE}. * In some languages (not english) the stand-alone-version requires * a special grammar. </td> * </tr> * <tr> * <td>WEEK_OF_YEAR</td> * <td>w</td> * <td>One or two symbols for the country-dependent week of year. </td> * </tr> * <tr> * <td>WEEK_OF_MONTH</td> * <td>W</td> * <td>One symbol for the country-dependent week of month. </td> * </tr> * <tr> * <td>DAY_OF_MONTH</td> * <td>d</td> * <td>One or two symbols for the day of month. </td> * </tr> * <tr> * <td>DAY_OF_YEAR</td> * <td>D</td> * <td>One, two or three symbols for the day of year. </td> * </tr> * <tr> * <td>DAY_OF_WEEK</td> * <td>E</td> * <td>One to three symbols for the abbreviation, four for the full * name, five for a letter symbol or six for the short form. </td> * </tr> * <tr> * <td>LOCAL_DAY_OF_WEEK</td> * <td>e</td> * <td>Like E, but if there are only one or two symbols then the * formatter will choose the localized numerical form. </td> * </tr> * <tr> * <td>LOCAL_DAY_OF_WEEK</td> * <td>c</td> * <td>Like e, but in the version {@link OutputContext#STANDALONE}. * In some languages (not english) the stand-alone-version requires * a special grammar. However, 2 symbols are not allowed. </td> * </tr> * <tr> * <td>RELATED_GREGORIAN_YEAR</td> * <td>r</td> * <td>The related gregorian year corresponds to the begin of the calendar year * in non-gregorian calender systems. For formatting or parsing, only the * ASCII-digits 0-9 will be used, even if other parts of the format use * alternative digits or other numeral systems. The count of symbols is * defined within the range 1-9. </td> * </tr> * </table> * </div> * * <p>Special notes for the Ethiopian calendar: </p> * * <p>The Ethiopian year will use the Ethiopic numerals in Amharic. This default behaviour * can be overridden on builder-level. </p> * * @since 3.5/4.3 */ /*[deutsch] * <p>Eine kleine Untermenge von CLDR, die auf jede Non-ISO-Chronologie anwendbar ist, die die * assoziierten Elemente mit gleichen Symbolen registriert hat. </p> * * <p>Wenn nicht explizit anders angegeben, steuert die Anzahl der Symbole * immer die minimale Anzahl der zu formatierenden Stellen, ein numerisches * Element vorausgesetzt. Ist also ein Element in der Darstellung * kürzer, dann wird mit der Null-Ziffer aufgefüllt. </p> * * <div style="margin-top:5px;"> * <table border="1"> * <caption>Legende</caption> * <tr> * <th>Element</th> * <th>Symbol</th> * <th>Beschreibung</th> * </tr> * <tr> * <td>ERA</td> * <td>G</td> * <td>Ein bis drei Symbole implizieren eine Abkürzung, vier * Symbole die Langform und fünf Symbole stehen für ein * Buchstabensymbol. </td> * </tr> * <tr> * <td>YEAR_OF_ERA</td> * <td>y</td> * <td>Die Anzahl der Symbole regelt normalerweise die minimale * Ziffernzahl. Ist sie jedoch 2, dann wird das Jahr zweistellig * angezeigt - mit dem Attribut {@link Attributes#PIVOT_YEAR}. </td> * </tr> * <tr> * <td>MONTH_OF_YEAR</td> * <td>M</td> * <td>Ein oder zwei Symbole für die numerische Form, drei * für die Abkürzung, vier für den vollen Namen * oder fünf für ein Buchstabensymbol (NARROW). </td> * </tr> * <tr> * <td>MONTH_OF_YEAR</td> * <td>L</td> * <td>Wie M, aber in der {@link OutputContext#STANDALONE * Stand-Alone-Version}. In manchen Sprachen (nicht englisch) * erfordert die alleinstehende Variante eine besondere * Deklination. </td> * </tr> * <tr> * <td>WEEK_OF_YEAR</td> * <td>w</td> * <td>Ein oder zwei Symbole für die länderabhängige * Woche des Jahres. </td> * </tr> * <tr> * <td>WEEK_OF_MONTH</td> * <td>W</td> * <td>Ein Symbol für die länderabhängige * Woche des Monats. </td> * </tr> * <tr> * <td>DAY_OF_MONTH</td> * <td>d</td> * <td>Ein oder zwei Symbole für den Tag des Monats. </td> * </tr> * <tr> * <td>DAY_OF_YEAR</td> * <td>D</td> * <td>Ein, zwei oder drei Symbole für den Tag des Jahres. </td> * </tr> * <tr> * <td>DAY_OF_WEEK</td> * <td>E</td> * <td>Ein bis drei Symbole für die Abkürzung, vier * für den vollen Namen, fünf für ein Buchstabensymbol * oder sechs für die Kurzform. </td> * </tr> * <tr> * <td>LOCAL_DAY_OF_WEEK</td> * <td>e</td> * <td>Wie E, aber wenn ein oder zwei Symbole angegeben sind, dann * wird die lokalisierte numerische Form gewählt. </td> * </tr> * <tr> * <td>LOCAL_DAY_OF_WEEK</td> * <td>c</td> * <td>Wie e, aber in der {@link OutputContext#STANDALONE * Stand-Alone-Version}. In manchen Sprachen (nicht englisch) * erfordert die alleinstehende Variante eine besondere * Deklination. Zu beachten: 2 Symbole sind nicht erlaubt. </td> * </tr> * <tr> * <td>RELATED_GREGORIAN_YEAR</td> * <td>r</td> * <td>In nicht-gregorianischen Kalendersystemen entspricht es dem * ISO-Jahr des Beginns des jeweiligen Kalenderjahres. Zur Formatierung * werden immer die ASCII-Ziffern 0-9 verwendet, selbst wenn andere Teile * des Formats andere numerische Ziffern oder sogar andere Numeralsystem * verwenden. Die Anzahl der Symbole ist im Bereich 1-9 zu wählen. </td> * </tr> * </table> * </div> * * <p>Anmerkungen für den äthiopischen Kalender: </p> * * <p>Das äthiopische Jahr wird per Standard in Amharic die äthiopischen Numerale verwenden. * Diese Vorgabe kann auf <i>builder</i>-Ebene überschrieben werden. </p> * * @since 3.5/4.3 */ NON_ISO_DATE, /** * <p>Resolves a pattern such that the chronology used in current context determines the meaning * of any pattern symbols. </p> * * <p>In contrast to other pattern types like {@code CLDR}, the meaning of pattern symbols is not * defined by any external standard. The elements associated with symbols are looked up among the registered * elements of a chronology including those which can be found via any chronological extension. If the * found element is a {@link TextElement text element} then it will be treated as such, and the count of * symbols is determines the text width (1 = NARROW, 2 = SHORT, 3 = ABBREVIATED, 4 = WIDE). Otherwise * this pattern type tries to resolve the element in question as {@code ChronoElement<Integer>}, and * the count of symbols will determine the min width of displayed/parsed digits and apply some padding * if necessary. The maximum width is always 9, and no sign is used. </p> * * @see ChronoElement#getSymbol() * @since 4.20 */ /*[deutsch] * <p>Löst ein Muster so auf, daß die im aktuellen Kontext benutzte Chronologie die * Bedeutung von Mustersymbolen festlegt. </p> * * <p>Im Kontrast zu anderen Mustertypen wie {@code CLDR} ist die Bedeutung von Mustersymbolen nicht * durch irgendeinen externen Standard festgelegt. Die mit den Symbolen verknüpften Elemente * werden unter den registrierten Elementen einer Chronologie gesucht, notfalls auch in den chronologischen * Erweiterungen. Falls das gefundene Element ein {@link TextElement} ist, wird es als solches behandelt, * und die Anzahl der Symbole bestimmt dann die Textbreite (1 = NARROW, 2 = SHORT, 3 = ABBREVIATED, 4 = WIDE). * Sonst versucht dieser Mustertyp das fragliche Element als {@code ChronoElement<Integer>} aufzulösen, * und die Anzahl der Symbole wird die Mindestbreite der angezeigten/interpretierten Ziffern festlegen, * unter Umständen auch mit Auffüllen von Füllzeichen. Im numerischen Fall ist die maximale * Breite 9, und ein Vorzeichen wird nie verwendet. </p> * * @see ChronoElement#getSymbol() * @since 4.20 */ DYNAMIC; //~ Methoden ---------------------------------------------------------- @Override public FormatEngine<PatternType> getFormatEngine() { return UltimateFormatEngine.INSTANCE; } /** * <p>Registers a format symbol. </p> * * @param builder serves for construction of {@code ChronoFormatter} * @param locale current language- and country setting * @param symbol pattern symbol to be interpreted * @param count count of symbols in format pattern * @return map of elements which will replace other already registered * elements after pattern processing * @throws IllegalArgumentException if symbol resolution fails */ /*[deutsch] * <p>Registriert ein Formatsymbol. </p> * * @param builder serves for construction of {@code ChronoFormatter} * @param locale current language- and country setting * @param symbol pattern symbol to be interpreted * @param count count of symbols in format pattern * @return map of elements which will replace other already registered * elements after pattern processing * @throws IllegalArgumentException if symbol resolution fails */ Map<ChronoElement<?>, ChronoElement<?>> registerSymbol( ChronoFormatter.Builder<?> builder, Locale locale, char symbol, int count ) { switch (this) { case CLDR: return cldr(builder, locale, symbol, count); case SIMPLE_DATE_FORMAT: return sdf(builder, locale, symbol, count); case THREETEN: return threeten(builder, locale, symbol, count); case CLDR_24: return cldr24(builder, locale, symbol, count); case NON_ISO_DATE: if (isISO(builder.getChronology())) { throw new IllegalArgumentException("Choose CLDR or CLDR_24 for ISO-8601-chronology."); } return general(builder, symbol, count, locale); case DYNAMIC: return dynamic(builder, symbol, count, locale); default: throw new UnsupportedOperationException(this.name()); } } private static boolean isGeneralSymbol(char symbol) { switch (symbol) { case 'D': case 'E': case 'G': case 'L': case 'M': case 'd': case 'y': case 'r': case 'w': case 'W': case 'e': case 'c': return true; default: return false; } } private static boolean isISO(Chronology<?> chronology) { return getCalendarType(chronology).equals(CalendarText.ISO_CALENDAR_TYPE); } private static String getCalendarType(Chronology<?> chronology) { CalendarType ctype = chronology.getChronoType().getAnnotation(CalendarType.class); return ((ctype == null) ? CalendarText.ISO_CALENDAR_TYPE : ctype.value()); } private static ChronoElement<Integer> findEthiopianHour(Chronology<?> chronology) { for (ChronoExtension ext : chronology.getExtensions()) { for (ChronoElement<?> e : ext.getElements(Locale.ROOT, Attributes.empty())) { if (e.name().equals("ETHIOPIAN_HOUR")) { return cast(e); } } } return null; } private Map<ChronoElement<?>, ChronoElement<?>> cldr( ChronoFormatter.Builder<?> builder, Locale locale, char symbol, int count ) { Chronology<?> chronology = builder.getChronology(); if (isGeneralSymbol(symbol) && !isISO(chronology)) { return this.general(builder, symbol, count, locale); } else if ((symbol == 'h') && getCalendarType(chronology).equals("ethiopic")) { ChronoElement<Integer> ethioHour = findEthiopianHour(builder.getChronology()); if (ethioHour == null) { throw new IllegalArgumentException("Ethiopian time not available."); } addNumber(ethioHour, builder, count, false); return Collections.emptyMap(); } else { return this.cldrISO(builder, locale, symbol, count, false); } } private Map<ChronoElement<?>, ChronoElement<?>> cldrISO( ChronoFormatter.Builder<?> builder, Locale locale, char symbol, int count, boolean sdf ) { TextWidth width; switch (symbol) { case 'G': if (count <= 3) { width = TextWidth.ABBREVIATED; } else if ((count == 4) || sdf) { width = TextWidth.WIDE; } else if (count == 5) { width = TextWidth.NARROW; } else { throw new IllegalArgumentException( "Too many pattern letters (G): " + count); } builder.startSection(Attributes.TEXT_WIDTH, width); ChronoHistory history = ChronoHistory.of(locale); TextElement<?> eraElement = TextElement.class.cast(history.era()); builder.addText(eraElement); builder.endSection(); Map<ChronoElement<?>, ChronoElement<?>> replacement = new HashMap<>(); replacement.put(PlainDate.YEAR, history.yearOfEra()); replacement.put(PlainDate.MONTH_OF_YEAR, history.month()); replacement.put(PlainDate.MONTH_AS_NUMBER, history.month()); replacement.put(PlainDate.DAY_OF_MONTH, history.dayOfMonth()); replacement.put(PlainDate.DAY_OF_YEAR, history.dayOfYear()); return replacement; case 'y': if (count == 2) { builder.addTwoDigitYear(PlainDate.YEAR); } else { builder.addYear(PlainDate.YEAR, count, false, false); } break; case 'Y': if (count == 2) { builder.addTwoDigitYear(PlainDate.YEAR_OF_WEEKDATE); } else { builder.addYear(PlainDate.YEAR_OF_WEEKDATE, count, false, false); } break; case 'u': builder.addYear(PlainDate.YEAR, count, true, false); break; case 'r': builder.startSection(Attributes.NUMBER_SYSTEM, NumberSystem.ARABIC); builder.startSection(Attributes.ZERO_DIGIT, '0'); builder.addYear(PlainDate.YEAR, count, true, false); builder.endSection(); builder.endSection(); break; case 'Q': addQuarterOfYear(builder, count); break; case 'q': builder.startSection( Attributes.OUTPUT_CONTEXT, OutputContext.STANDALONE); try { addQuarterOfYear(builder, count); } finally { builder.endSection(); } break; case 'M': addMonth(builder, Math.min(count, sdf ? 4 : count)); break; case 'L': builder.startSection( Attributes.OUTPUT_CONTEXT, OutputContext.STANDALONE); try { addMonth(builder, count); } finally { builder.endSection(); } break; case 'w': if (count <= 2) { addNumber( Weekmodel.of(locale).weekOfYear(), builder, count, sdf); } else { throw new IllegalArgumentException( "Too many pattern letters (w): " + count); } break; case 'W': if (count == 1) { builder.addFixedInteger( Weekmodel.of(locale).weekOfMonth(), 1); } else { throw new IllegalArgumentException( "Too many pattern letters (W): " + count); } break; case 'd': addNumber(PlainDate.DAY_OF_MONTH, builder, count, sdf); break; case 'D': if (count < 3) { builder.addInteger(PlainDate.DAY_OF_YEAR, count, 3); } else if ((count == 3) || sdf) { builder.addFixedInteger(PlainDate.DAY_OF_YEAR, count); } else { throw new IllegalArgumentException( "Too many pattern letters (D): " + count); } break; case 'F': if ((count == 1) || sdf) { builder.addFixedInteger(PlainDate.WEEKDAY_IN_MONTH, count); } else { throw new IllegalArgumentException( "Too many pattern letters (F): " + count); } break; case 'g': builder.addLongNumber( EpochDays.MODIFIED_JULIAN_DATE, count, 18, SignPolicy.SHOW_WHEN_NEGATIVE); break; case 'E': if (count <= 3) { width = TextWidth.ABBREVIATED; } else if ((count == 4) || sdf) { width = TextWidth.WIDE; } else if (count == 5) { width = TextWidth.NARROW; } else if (count == 6) { width = TextWidth.SHORT; } else { throw new IllegalArgumentException( "Too many pattern letters: " + count); } builder.startSection(Attributes.TEXT_WIDTH, width); builder.addText(PlainDate.DAY_OF_WEEK); builder.endSection(); break; case 'e': if (count <= 2) { builder.addFixedNumerical( Weekmodel.of(locale).localDayOfWeek(), count); } else { cldrISO(builder, locale, 'E', count, sdf); } break; case 'c': if (count == 2) { throw new IllegalArgumentException( "Invalid pattern count of 2 for symbol 'c'."); } builder.startSection( Attributes.OUTPUT_CONTEXT, OutputContext.STANDALONE); try { if (count == 1) { builder.addFixedNumerical( Weekmodel.of(locale).localDayOfWeek(), 1); } else { cldrISO(builder, locale, 'E', count, sdf); } } finally { builder.endSection(); } break; case 'a': width = (sdf ? TextWidth.ABBREVIATED : getPeriodWidth(count)); builder.startSection(Attributes.TEXT_WIDTH, width); builder.addText(PlainTime.AM_PM_OF_DAY); builder.endSection(); if (getCalendarType(builder.getChronology()).equals("ethiopic")) { // AM/PM-marker denotes western reference! ChronoElement<Integer> ethioHour = findEthiopianHour(builder.getChronology()); if (ethioHour == null) { throw new IllegalArgumentException("Ethiopian time not available."); } Map<ChronoElement<?>, ChronoElement<?>> stdHours = new HashMap<>(); stdHours.put(ethioHour, PlainTime.CLOCK_HOUR_OF_AMPM); return stdHours; } break; case 'b': width = getPeriodWidth(count); builder.startSection(Attributes.TEXT_WIDTH, width); builder.addDayPeriodFixed(); builder.endSection(); break; case 'B': width = getPeriodWidth(count); builder.startSection(Attributes.TEXT_WIDTH, width); builder.addDayPeriodApproximate(); builder.endSection(); break; case 'h': addNumber(PlainTime.CLOCK_HOUR_OF_AMPM, builder, count, sdf); break; case 'H': addNumber(PlainTime.DIGITAL_HOUR_OF_DAY, builder, count, sdf); break; case 'K': addNumber(PlainTime.DIGITAL_HOUR_OF_AMPM, builder, count, sdf); break; case 'k': addNumber(PlainTime.CLOCK_HOUR_OF_DAY, builder, count, sdf); break; case 'm': addNumber(PlainTime.MINUTE_OF_HOUR, builder, count, sdf); break; case 's': addNumber(PlainTime.SECOND_OF_MINUTE, builder, count, sdf); break; case 'S': builder.addFraction( PlainTime.NANO_OF_SECOND, count, count, false); break; case 'A': builder.addInteger(PlainTime.MILLI_OF_DAY, count, 9); break; case 'z': try { if (count < 4) { builder.addShortTimezoneName(); } else if ((count == 4) || sdf) { builder.addLongTimezoneName(); } else { throw new IllegalArgumentException( "Too many pattern letters (z): " + count); } } catch (IllegalStateException ise) { throw new IllegalArgumentException(ise.getMessage()); } break; case 'Z': if (count < 4) { builder.addTimezoneOffset( DisplayMode.LONG, false, Collections.singletonList("+0000")); } else if (count == 4) { builder.addLongLocalizedOffset(); } else if (count == 5) { builder.addTimezoneOffset( DisplayMode.LONG, true, Collections.singletonList("Z")); } else { throw new IllegalArgumentException( "Too many pattern letters (Z): " + count); } break; case 'O': if (count == 1) { builder.addShortLocalizedOffset(); } else if (count == 4) { builder.addLongLocalizedOffset(); } else { throw new IllegalArgumentException( "Count of pattern letters is not 1 or 4: " + count); } break; case 'V': if (count == 2) { try { builder.addTimezoneID(); } catch (IllegalStateException ise) { throw new IllegalArgumentException(ise.getMessage()); } } else { throw new IllegalArgumentException( "Count of pattern letters is not 2: " + count); } break; case 'X': addOffset(builder, count, true); break; case 'x': addOffset(builder, count, false); break; default: throw new IllegalArgumentException( "Unsupported pattern symbol: " + symbol); } return Collections.emptyMap(); } private static TextWidth getPeriodWidth(int count) { if (count <= 3) { return TextWidth.ABBREVIATED; } else if (count == 4) { return TextWidth.WIDE; } else if (count == 5) { return TextWidth.NARROW; } else { throw new IllegalArgumentException( "Too many pattern letters: " + count); } } private Map<ChronoElement<?>, ChronoElement<?>> sdf( ChronoFormatter.Builder<?> builder, Locale locale, char symbol, int count ) { switch (symbol) { case 'W': builder.addFixedInteger( Weekmodel.of(locale).boundedWeekOfMonth(), count); break; case 'u': builder.addFixedNumerical(PlainDate.DAY_OF_WEEK, count); break; case 'S': builder.addFixedInteger(PlainTime.MILLI_OF_SECOND, count); break; case 'Z': addOffset(builder, 2, false); break; case 'b': case 'B': case 'Q': case 'q': case 'r': case 'g': case 'e': case 'c': case 'O': case 'V': case 'x': throw new IllegalArgumentException( "CLDR pattern symbol not supported" + " in SimpleDateFormat-style: " + symbol); case 'X': if (count >= 4) { throw new IllegalArgumentException( "Too many pattern letters: " + count); } return cldrISO(builder, locale, 'X', count, true); default: return cldrISO(builder, locale, symbol, count, true); } return Collections.emptyMap(); } private Map<ChronoElement<?>, ChronoElement<?>> threeten( ChronoFormatter.Builder<?> builder, Locale locale, char symbol, int count ) { switch (symbol) { case 'G': TextWidth eraWidth; if (count <= 3) { eraWidth = TextWidth.ABBREVIATED; } else if (count == 4) { eraWidth = TextWidth.WIDE; } else if (count == 5) { eraWidth = TextWidth.NARROW; } else { throw new IllegalArgumentException( "Too many pattern letters: " + count); } builder.startSection(Attributes.TEXT_WIDTH, eraWidth); ChronoHistory history = ChronoHistory.PROLEPTIC_GREGORIAN; TextElement<?> eraElement = TextElement.class.cast(history.era()); builder.addText(eraElement); builder.endSection(); builder.setProlepticGregorian(); Map<ChronoElement<?>, ChronoElement<?>> replacement = new HashMap<>(); replacement.put(PlainDate.YEAR, history.yearOfEra()); replacement.put(PlainDate.MONTH_OF_YEAR, history.month()); replacement.put(PlainDate.MONTH_AS_NUMBER, history.month()); replacement.put(PlainDate.DAY_OF_MONTH, history.dayOfMonth()); replacement.put(PlainDate.DAY_OF_YEAR, history.dayOfYear()); return replacement; case 'y': if (count == 2) { builder.startSection(Attributes.PIVOT_YEAR, 2100); builder.addTwoDigitYear(PlainDate.YEAR); builder.endSection(); } else { builder.addYear(PlainDate.YEAR, count, false, true); } break; case 'Y': if (count == 2) { builder.startSection(Attributes.PIVOT_YEAR, 2100); builder.addTwoDigitYear(PlainDate.YEAR_OF_WEEKDATE); builder.endSection(); } else { builder.addYear(PlainDate.YEAR_OF_WEEKDATE, count, false, true); } break; case 'u': if (count == 2) { builder.startSection(Attributes.PIVOT_YEAR, 2100); builder.addProlepticIsoYearWithTwoDigits(); builder.endSection(); } else { builder.addYear(PlainDate.YEAR, count, true, true); } break; case 'W': if (count == 1) { builder.addFixedInteger( Weekmodel.of(locale).boundedWeekOfMonth(), 1); } else { throw new IllegalArgumentException( "Too many pattern letters: " + count); } break; case 'E': TextWidth width; if (count <= 3) { width = TextWidth.ABBREVIATED; } else if (count == 4) { width = TextWidth.WIDE; } else if (count == 5) { width = TextWidth.NARROW; } else { throw new IllegalArgumentException( "Too many pattern letters: " + count); } builder.startSection(Attributes.TEXT_WIDTH, width); builder.addText(PlainDate.DAY_OF_WEEK); builder.endSection(); break; case 'e': if (count <= 2) { builder.addFixedNumerical( Weekmodel.of(locale).localDayOfWeek(), count); } else { threeten(builder, locale, 'E', count); } break; case 'c': if (count == 2) { throw new IllegalArgumentException( "Invalid pattern count of 2 for symbol 'c'."); } builder.startSection( Attributes.OUTPUT_CONTEXT, OutputContext.STANDALONE); try { threeten(builder, locale, 'e', count); } finally { builder.endSection(); } break; case 'a': width = getPeriodWidth(count); builder.startSection(Attributes.TEXT_WIDTH, width); builder.addText(PlainTime.AM_PM_OF_DAY); builder.endSection(); break; case 'w': case 'Q': case 'q': case 'M': case 'L': case 'd': case 'D': case 'F': case 'h': case 'H': case 'K': case 'k': case 'm': case 's': case 'S': case 'A': return cldrISO(builder, locale, symbol, count, false); case 'n': builder.addInteger(PlainTime.NANO_OF_SECOND, count, 9); break; case 'N': builder.addLongNumber(PlainTime.NANO_OF_DAY, count, 18, SignPolicy.SHOW_NEVER); break; case 'z': // TODO: if we are going to support "v" in CLDR then we should use that for zoneless types return cldrISO(builder, locale, 'z', count, false); case 'Z': if (count < 4) { builder.addTimezoneOffset( DisplayMode.MEDIUM, false, Collections.singletonList("+0000")); } else if (count == 4) { builder.addLongLocalizedOffset(); } else if (count == 5) { builder.addTimezoneOffset( DisplayMode.LONG, true, Collections.singletonList("Z")); } else { throw new IllegalArgumentException( "Too many pattern letters: " + count); } break; case 'O': case 'V': case 'X': case 'x': return cldrISO(builder, locale, symbol, count, false); case 'p': builder.padNext(count); break; default: throw new IllegalArgumentException( "Unsupported pattern symbol: " + symbol); } return Collections.emptyMap(); } private Map<ChronoElement<?>, ChronoElement<?>> cldr24( ChronoFormatter.Builder<?> builder, Locale locale, char symbol, int count ) { if (symbol == 'H') { addNumber(PlainTime.ISO_HOUR, builder, count, false); return Collections.emptyMap(); } return cldr(builder, locale, symbol, count); } private static void addOffset( ChronoFormatter.Builder<?> builder, int count, boolean zulu ) { switch (count) { case 1: builder.addTimezoneOffset( DisplayMode.SHORT, false, Collections.singletonList(zulu ? "Z" : "+00")); break; case 2: builder.addTimezoneOffset( DisplayMode.MEDIUM, false, Collections.singletonList(zulu ? "Z" : "+0000")); break; case 3: builder.addTimezoneOffset( DisplayMode.MEDIUM, true, Collections.singletonList(zulu ? "Z" : "+00:00")); break; case 4: builder.addTimezoneOffset( DisplayMode.LONG, false, Collections.singletonList(zulu ? "Z" : "+0000")); break; case 5: builder.addTimezoneOffset( DisplayMode.LONG, true, Collections.singletonList(zulu ? "Z" : "+00:00")); break; default: throw new IllegalArgumentException( "Too many pattern letters: " + count); } } private static void addNumber( ChronoElement<Integer> element, ChronoFormatter.Builder<?> builder, int count, boolean sdf ) { if (count == 1) { builder.addInteger(element, 1, 2); } else if ((count == 2) || sdf) { builder.addFixedInteger(element, count); } else { throw new IllegalArgumentException( "Too many pattern letters: " + count); } } private static void addMonth( ChronoFormatter.Builder<?> builder, int count ) { switch (count) { case 1: builder.addInteger(PlainDate.MONTH_AS_NUMBER, 1, 2); break; case 2: builder.addFixedInteger(PlainDate.MONTH_AS_NUMBER, 2); break; case 3: builder.startSection( Attributes.TEXT_WIDTH, TextWidth.ABBREVIATED); builder.addText(PlainDate.MONTH_OF_YEAR); builder.endSection(); break; case 4: builder.startSection( Attributes.TEXT_WIDTH, TextWidth.WIDE); builder.addText(PlainDate.MONTH_OF_YEAR); builder.endSection(); break; case 5: builder.startSection( Attributes.TEXT_WIDTH, TextWidth.NARROW); builder.addText(PlainDate.MONTH_OF_YEAR); builder.endSection(); break; default: throw new IllegalArgumentException( "Too many pattern letters: " + count); } } private static void addQuarterOfYear( ChronoFormatter.Builder<?> builder, int count ) { switch (count) { case 1: case 2: builder.addFixedNumerical(PlainDate.QUARTER_OF_YEAR, count); break; case 3: builder.startSection( Attributes.TEXT_WIDTH, TextWidth.ABBREVIATED); builder.addText(PlainDate.QUARTER_OF_YEAR); builder.endSection(); break; case 4: builder.startSection( Attributes.TEXT_WIDTH, TextWidth.WIDE); builder.addText(PlainDate.QUARTER_OF_YEAR); builder.endSection(); break; case 5: builder.startSection( Attributes.TEXT_WIDTH, TextWidth.NARROW); builder.addText(PlainDate.QUARTER_OF_YEAR); builder.endSection(); break; default: throw new IllegalArgumentException( "Too many pattern letters: " + count); } } private Map<ChronoElement<?>, ChronoElement<?>> general( ChronoFormatter.Builder<?> builder, char symbol, int count, Locale locale ) { Set<ChronoElement<?>> elements = getElements(builder, symbol, locale); String chronoType = builder.getChronology().getChronoType().getName(); ChronoElement<?> element = find(elements, symbol, chronoType); TextElement<?> textElement; ChronoElement<Integer> intElement; if (element.getType().isEnum() && (element instanceof TextElement)) { textElement = cast(element); intElement = null; } else if (Integer.class.isAssignableFrom(element.getType())) { textElement = null; if (element instanceof HistorizedElement) { textElement = cast(element); } intElement = cast(element); } else { throw new IllegalStateException("Implementation error: " + element + " in \"" + chronoType + "\""); } switch (symbol) { case 'G': TextWidth eraWidth; if (count <= 3) { eraWidth = TextWidth.ABBREVIATED; } else if (count == 4) { eraWidth = TextWidth.WIDE; } else if (count == 5) { eraWidth = TextWidth.NARROW; } else { throw new IllegalArgumentException( "Too many pattern letters: " + count); } builder.startSection(Attributes.TEXT_WIDTH, eraWidth); builder.addText(textElement); builder.endSection(); break; case 'y': boolean hasSpecialAttribute = false; if (locale.getLanguage().equals("am") && getCalendarType(builder.getChronology()).equals("ethiopic")) { hasSpecialAttribute = true; builder.startSection(Attributes.NUMBER_SYSTEM, NumberSystem.ETHIOPIC); } if (count == 2) { builder.addTwoDigitYear(intElement); } else { builder.addYear(intElement, count, false, false); } if (hasSpecialAttribute) { builder.endSection(); } break; case 'r': builder.startSection(Attributes.NUMBER_SYSTEM, NumberSystem.ARABIC); builder.startSection(Attributes.ZERO_DIGIT, '0'); builder.addYear(intElement, count, true, false); builder.endSection(); builder.endSection(); break; case 'M': addMonth(builder, Math.min(count, count), textElement); break; case 'L': builder.startSection( Attributes.OUTPUT_CONTEXT, OutputContext.STANDALONE); try { addMonth(builder, count, textElement); } finally { builder.endSection(); } break; case 'w': addNumber(intElement, builder, count, false); break; case 'W': if (count == 1) { builder.addFixedInteger(intElement, 1); } else { throw new IllegalArgumentException( "Too many pattern letters: " + count); } break; case 'd': addNumber(intElement, builder, count, false); break; case 'D': if (count < 3) { builder.addInteger(intElement, count, 3); } else if (count == 3) { builder.addFixedInteger(intElement, count); } else { throw new IllegalArgumentException( "Too many pattern letters: " + count); } break; case 'E': TextWidth width; if (count <= 3) { width = TextWidth.ABBREVIATED; } else if (count == 4) { width = TextWidth.WIDE; } else if (count == 5) { width = TextWidth.NARROW; } else if (count == 6) { width = TextWidth.SHORT; } else { throw new IllegalArgumentException( "Too many pattern letters: " + count); } builder.startSection(Attributes.TEXT_WIDTH, width); builder.addText(textElement); builder.endSection(); break; case 'e': if (count <= 2) { ChronoElement<Weekday> wde = cast(element); builder.addFixedNumerical(wde, count); } else { general(builder, 'E', count, locale); } break; case 'c': if (count == 2) { throw new IllegalArgumentException( "Invalid pattern count of 2 for symbol 'c'."); } builder.startSection( Attributes.OUTPUT_CONTEXT, OutputContext.STANDALONE); try { if (count == 1) { ChronoElement<Weekday> wde = cast(element); builder.addFixedNumerical(wde, 1); } else { general(builder, 'E', count, locale); } } finally { builder.endSection(); } break; default: throw new IllegalArgumentException( "Unsupported pattern symbol: " + symbol); } return Collections.emptyMap(); } private Map<ChronoElement<?>, ChronoElement<?>> dynamic( ChronoFormatter.Builder<?> builder, char symbol, int count, Locale locale ) { ChronoElement<?> found = null; Chronology<?> chronology = builder.getChronology(); if (chronology instanceof BridgeChronology) { chronology = chronology.preparser(); } for (ChronoElement<?> element : chronology.getRegisteredElements()) { if (element.getSymbol() == symbol) { found = element; break; } } if (found == null) { for (ChronoExtension extension : chronology.getExtensions()) { for (ChronoElement<?> element : extension.getElements(locale, Attributes.empty())) { if (element.getSymbol() == symbol) { found = element; break; } } if (found != null) { break; } } } if (found == null) { throw new IllegalArgumentException("Resolving failed for symbol: " + symbol); } else if (found instanceof TextElement) { switch (count) { case 1: builder.startSection(Attributes.TEXT_WIDTH, TextWidth.NARROW); break; case 2: builder.startSection(Attributes.TEXT_WIDTH, TextWidth.SHORT); break; case 3: builder.startSection(Attributes.TEXT_WIDTH, TextWidth.ABBREVIATED); break; case 4: builder.startSection(Attributes.TEXT_WIDTH, TextWidth.WIDE); break; default: throw new IllegalArgumentException("Illegal count of symbols: " + symbol); } TextElement<?> textElement = cast(found); builder.addText(textElement); builder.endSection(); } else if (found.getType() == Integer.class) { ChronoElement<Integer> intElement = cast(found); builder.addInteger(intElement, count, 9); } else { throw new IllegalArgumentException("Can only handle integer or text elements: " + found); } return Collections.emptyMap(); } private static Set<ChronoElement<?>> getElements( ChronoFormatter.Builder<?> builder, char symbol, Locale locale ) { if ((symbol == 'w') || (symbol == 'W') || (symbol == 'e') || (symbol == 'c')) { for (ChronoExtension extension : builder.getChronology().getExtensions()) { for (ChronoElement<?> element : extension.getElements(locale, Attributes.empty())) { if ( ((symbol == 'e' || symbol == 'c') && element.name().equals("LOCAL_DAY_OF_WEEK")) || ((symbol == 'w') && element.name().equals("WEEK_OF_YEAR")) || ((symbol == 'W') && element.name().equals("WEEK_OF_MONTH")) ) { return Collections.singleton(element); } } } return Collections.emptySet(); } else { return builder.getChronology().getRegisteredElements(); } } private static ChronoElement<?> find( Set<ChronoElement<?>> elements, char symbol, String chronoType ) { char c = ((symbol == 'L') ? 'M' : ((symbol == 'c') ? 'e' : symbol)); for (ChronoElement<?> element : elements) { if (element.getSymbol() == c) { return element; } } throw new IllegalArgumentException( "Cannot find any chronological element for symbol " + symbol + " in \"" + chronoType + "\"."); } private static <V extends Enum<V>> void addMonth( ChronoFormatter.Builder<?> builder, int count, TextElement<?> textElement ) { switch (count) { case 1: case 2: ChronoElement<V> enumElement = cast(textElement); if (count == 1) { builder.addNumerical(enumElement, 1, 2); } else if (count == 2) { builder.addFixedNumerical(enumElement, 2); } break; case 3: builder.startSection( Attributes.TEXT_WIDTH, TextWidth.ABBREVIATED); builder.addText(textElement); builder.endSection(); break; case 4: builder.startSection( Attributes.TEXT_WIDTH, TextWidth.WIDE); builder.addText(textElement); builder.endSection(); break; case 5: builder.startSection( Attributes.TEXT_WIDTH, TextWidth.NARROW); builder.addText(textElement); builder.endSection(); break; default: throw new IllegalArgumentException("Too many pattern letters: " + count); } } @SuppressWarnings("unchecked") private static <T> T cast(Object obj) { return (T) obj; } }