< prev index next >

src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java

Print this page




1757                         appendLocalizedOffset(TextStyle.FULL);
1758                     } else {
1759                         throw new IllegalArgumentException("Pattern letter count must be 1 or 4: " + cur);
1760                     }
1761                 } else if (cur == 'X') {
1762                     if (count > 5) {
1763                         throw new IllegalArgumentException("Too many pattern letters: " + cur);
1764                     }
1765                     appendOffset(OffsetIdPrinterParser.PATTERNS[count + (count == 1 ? 0 : 1)], "Z");
1766                 } else if (cur == 'x') {
1767                     if (count > 5) {
1768                         throw new IllegalArgumentException("Too many pattern letters: " + cur);
1769                     }
1770                     String zero = (count == 1 ? "+00" : (count % 2 == 0 ? "+0000" : "+00:00"));
1771                     appendOffset(OffsetIdPrinterParser.PATTERNS[count + (count == 1 ? 0 : 1)], zero);
1772                 } else if (cur == 'W') {
1773                     // Fields defined by Locale
1774                     if (count > 1) {
1775                         throw new IllegalArgumentException("Too many pattern letters: " + cur);
1776                     }
1777                     appendInternal(new WeekBasedFieldPrinterParser(cur, count));
1778                 } else if (cur == 'w') {
1779                     // Fields defined by Locale
1780                     if (count > 2) {
1781                         throw new IllegalArgumentException("Too many pattern letters: " + cur);
1782                     }
1783                     appendInternal(new WeekBasedFieldPrinterParser(cur, count));
1784                 } else if (cur == 'Y') {
1785                     // Fields defined by Locale
1786                     appendInternal(new WeekBasedFieldPrinterParser(cur, count));




1787                 } else {
1788                     throw new IllegalArgumentException("Unknown pattern letter: " + cur);
1789                 }
1790                 pos--;
1791 
1792             } else if (cur == '\'') {
1793                 // parse literals
1794                 int start = pos++;
1795                 for ( ; pos < pattern.length(); pos++) {
1796                     if (pattern.charAt(pos) == '\'') {
1797                         if (pos + 1 < pattern.length() && pattern.charAt(pos + 1) == '\'') {
1798                             pos++;
1799                         } else {
1800                             break;  // end of literal
1801                         }
1802                     }
1803                 }
1804                 if (pos >= pattern.length()) {
1805                     throw new IllegalArgumentException("Pattern ends with an incomplete string literal: " + pattern);
1806                 }


1826                 appendLiteral(cur);
1827             }
1828         }
1829     }
1830 
1831     @SuppressWarnings("fallthrough")
1832     private void parseField(char cur, int count, TemporalField field) {
1833         boolean standalone = false;
1834         switch (cur) {
1835             case 'u':
1836             case 'y':
1837                 if (count == 2) {
1838                     appendValueReduced(field, 2, 2, ReducedPrinterParser.BASE_DATE);
1839                 } else if (count < 4) {
1840                     appendValue(field, count, 19, SignStyle.NORMAL);
1841                 } else {
1842                     appendValue(field, count, 19, SignStyle.EXCEEDS_PAD);
1843                 }
1844                 break;
1845             case 'c':
1846                 if (count == 2) {



1847                     throw new IllegalArgumentException("Invalid pattern \"cc\"");
1848                 }
1849                 /*fallthrough*/
1850             case 'L':
1851             case 'q':
1852                 standalone = true;
1853                 /*fallthrough*/
1854             case 'M':
1855             case 'Q':
1856             case 'E':
1857             case 'e':
1858                 switch (count) {
1859                     case 1:
1860                     case 2:
1861                         if (cur == 'c' || cur == 'e') {
1862                             appendInternal(new WeekBasedFieldPrinterParser(cur, count));
1863                         } else if (cur == 'E') {
1864                             appendText(field, TextStyle.SHORT);
1865                         } else {
1866                             if (count == 1) {
1867                                 appendValue(field);
1868                             } else {
1869                                 appendValue(field, 2);
1870                             }
1871                         }
1872                         break;
1873                     case 3:
1874                         appendText(field, standalone ? TextStyle.SHORT_STANDALONE : TextStyle.SHORT);
1875                         break;
1876                     case 4:
1877                         appendText(field, standalone ? TextStyle.FULL_STANDALONE : TextStyle.FULL);
1878                         break;
1879                     case 5:
1880                         appendText(field, standalone ? TextStyle.NARROW_STANDALONE : TextStyle.NARROW);
1881                         break;
1882                     default:


4754                 }
4755             }
4756             return formatter;
4757         }
4758 
4759         @Override
4760         public String toString() {
4761             return "Localized(" + (dateStyle != null ? dateStyle : "") + "," +
4762                 (timeStyle != null ? timeStyle : "") + ")";
4763         }
4764     }
4765 
4766     //-----------------------------------------------------------------------
4767     /**
4768      * Prints or parses a localized pattern from a localized field.
4769      * The specific formatter and parameters is not selected until the
4770      * the field is to be printed or parsed.
4771      * The locale is needed to select the proper WeekFields from which
4772      * the field for day-of-week, week-of-month, or week-of-year is selected.
4773      */
4774     static final class WeekBasedFieldPrinterParser implements DateTimePrinterParser {
4775         private char chr;
4776         private int count;
4777 
4778         /**
4779          * Constructor.
4780          *
4781          * @param chr the pattern format letter that added this PrinterParser.
4782          * @param count the repeat count of the format letter
4783          */
4784         WeekBasedFieldPrinterParser(char chr, int count) {






4785             this.chr = chr;
4786             this.count = count;
4787         }
4788 

























4789         @Override
4790         public boolean format(DateTimePrintContext context, StringBuilder buf) {
4791             return printerParser(context.getLocale()).format(context, buf);
4792         }
4793 
4794         @Override
4795         public int parse(DateTimeParseContext context, CharSequence text, int position) {
4796             return printerParser(context.getLocale()).parse(context, text, position);
4797         }
4798 
4799         /**
4800          * Gets the printerParser to use based on the field and the locale.
4801          *
4802          * @param locale  the locale to use, not null
4803          * @return the formatter, not null
4804          * @throws IllegalArgumentException if the formatter cannot be found
4805          */
4806         private DateTimePrinterParser printerParser(Locale locale) {
4807             WeekFields weekDef = WeekFields.of(locale);
4808             TemporalField field = null;
4809             switch (chr) {
4810                 case 'Y':
4811                     field = weekDef.weekBasedYear();
4812                     if (count == 2) {
4813                         return new ReducedPrinterParser(field, 2, 2, 0, ReducedPrinterParser.BASE_DATE, 0);

4814                     } else {
4815                         return new NumberPrinterParser(field, count, 19,
4816                                 (count < 4) ? SignStyle.NORMAL : SignStyle.EXCEEDS_PAD, -1);

4817                     }
4818                 case 'e':
4819                 case 'c':
4820                     field = weekDef.dayOfWeek();
4821                     break;
4822                 case 'w':
4823                     field = weekDef.weekOfWeekBasedYear();
4824                     break;
4825                 case 'W':
4826                     field = weekDef.weekOfMonth();
4827                     break;
4828                 default:
4829                     throw new IllegalStateException("unreachable");
4830             }
4831             return new NumberPrinterParser(field, (count == 2 ? 2 : 1), 2, SignStyle.NOT_NEGATIVE);
4832         }
4833 
4834         @Override
4835         public String toString() {
4836             StringBuilder sb = new StringBuilder(30);
4837             sb.append("Localized(");
4838             if (chr == 'Y') {
4839                 if (count == 1) {
4840                     sb.append("WeekBasedYear");
4841                 } else if (count == 2) {
4842                     sb.append("ReducedValue(WeekBasedYear,2,2,2000-01-01)");
4843                 } else {
4844                     sb.append("WeekBasedYear,").append(count).append(",")
4845                             .append(19).append(",")
4846                             .append((count < 4) ? SignStyle.NORMAL : SignStyle.EXCEEDS_PAD);
4847                 }
4848             } else {
4849                 switch (chr) {
4850                     case 'c':
4851                     case 'e':




1757                         appendLocalizedOffset(TextStyle.FULL);
1758                     } else {
1759                         throw new IllegalArgumentException("Pattern letter count must be 1 or 4: " + cur);
1760                     }
1761                 } else if (cur == 'X') {
1762                     if (count > 5) {
1763                         throw new IllegalArgumentException("Too many pattern letters: " + cur);
1764                     }
1765                     appendOffset(OffsetIdPrinterParser.PATTERNS[count + (count == 1 ? 0 : 1)], "Z");
1766                 } else if (cur == 'x') {
1767                     if (count > 5) {
1768                         throw new IllegalArgumentException("Too many pattern letters: " + cur);
1769                     }
1770                     String zero = (count == 1 ? "+00" : (count % 2 == 0 ? "+0000" : "+00:00"));
1771                     appendOffset(OffsetIdPrinterParser.PATTERNS[count + (count == 1 ? 0 : 1)], zero);
1772                 } else if (cur == 'W') {
1773                     // Fields defined by Locale
1774                     if (count > 1) {
1775                         throw new IllegalArgumentException("Too many pattern letters: " + cur);
1776                     }
1777                     appendValue(new WeekBasedFieldPrinterParser(cur, count, count, count));
1778                 } else if (cur == 'w') {
1779                     // Fields defined by Locale
1780                     if (count > 2) {
1781                         throw new IllegalArgumentException("Too many pattern letters: " + cur);
1782                     }
1783                     appendValue(new WeekBasedFieldPrinterParser(cur, count, count, 2));
1784                 } else if (cur == 'Y') {
1785                     // Fields defined by Locale
1786                     if (count == 2) {
1787                         appendValue(new WeekBasedFieldPrinterParser(cur, count, count, 2));
1788                     } else {
1789                         appendValue(new WeekBasedFieldPrinterParser(cur, count, count, 19));
1790                     }
1791                 } else {
1792                     throw new IllegalArgumentException("Unknown pattern letter: " + cur);
1793                 }
1794                 pos--;
1795 
1796             } else if (cur == '\'') {
1797                 // parse literals
1798                 int start = pos++;
1799                 for ( ; pos < pattern.length(); pos++) {
1800                     if (pattern.charAt(pos) == '\'') {
1801                         if (pos + 1 < pattern.length() && pattern.charAt(pos + 1) == '\'') {
1802                             pos++;
1803                         } else {
1804                             break;  // end of literal
1805                         }
1806                     }
1807                 }
1808                 if (pos >= pattern.length()) {
1809                     throw new IllegalArgumentException("Pattern ends with an incomplete string literal: " + pattern);
1810                 }


1830                 appendLiteral(cur);
1831             }
1832         }
1833     }
1834 
1835     @SuppressWarnings("fallthrough")
1836     private void parseField(char cur, int count, TemporalField field) {
1837         boolean standalone = false;
1838         switch (cur) {
1839             case 'u':
1840             case 'y':
1841                 if (count == 2) {
1842                     appendValueReduced(field, 2, 2, ReducedPrinterParser.BASE_DATE);
1843                 } else if (count < 4) {
1844                     appendValue(field, count, 19, SignStyle.NORMAL);
1845                 } else {
1846                     appendValue(field, count, 19, SignStyle.EXCEEDS_PAD);
1847                 }
1848                 break;
1849             case 'c':
1850                 if (count == 1) {
1851                     appendValue(new WeekBasedFieldPrinterParser(cur, count, count, count));     
1852                     break;                
1853                 } else if (count == 2) {
1854                     throw new IllegalArgumentException("Invalid pattern \"cc\"");
1855                 }
1856                 /*fallthrough*/
1857             case 'L':
1858             case 'q':
1859                 standalone = true;
1860                 /*fallthrough*/
1861             case 'M':
1862             case 'Q':
1863             case 'E':
1864             case 'e':
1865                 switch (count) {
1866                     case 1:
1867                     case 2:
1868                         if (cur == 'e') {
1869                             appendValue(new WeekBasedFieldPrinterParser(cur, count, count, 2));
1870                         } else if (cur == 'E') {
1871                             appendText(field, TextStyle.SHORT);
1872                         } else {
1873                             if (count == 1) {
1874                                 appendValue(field);
1875                             } else {
1876                                 appendValue(field, 2);
1877                             }
1878                         }
1879                         break;
1880                     case 3:
1881                         appendText(field, standalone ? TextStyle.SHORT_STANDALONE : TextStyle.SHORT);
1882                         break;
1883                     case 4:
1884                         appendText(field, standalone ? TextStyle.FULL_STANDALONE : TextStyle.FULL);
1885                         break;
1886                     case 5:
1887                         appendText(field, standalone ? TextStyle.NARROW_STANDALONE : TextStyle.NARROW);
1888                         break;
1889                     default:


4761                 }
4762             }
4763             return formatter;
4764         }
4765 
4766         @Override
4767         public String toString() {
4768             return "Localized(" + (dateStyle != null ? dateStyle : "") + "," +
4769                 (timeStyle != null ? timeStyle : "") + ")";
4770         }
4771     }
4772 
4773     //-----------------------------------------------------------------------
4774     /**
4775      * Prints or parses a localized pattern from a localized field.
4776      * The specific formatter and parameters is not selected until the
4777      * the field is to be printed or parsed.
4778      * The locale is needed to select the proper WeekFields from which
4779      * the field for day-of-week, week-of-month, or week-of-year is selected.
4780      */
4781     static final class WeekBasedFieldPrinterParser extends NumberPrinterParser {
4782         private char chr;
4783         private int count;
4784 
4785         /**
4786          * Constructor.
4787          *
4788          * @param chr the pattern format letter that added this PrinterParser.
4789          * @param count the repeat count of the format letter
4790          */
4791         WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth) {
4792             this(chr, count, minWidth, maxWidth, 0);
4793         }
4794 
4795         WeekBasedFieldPrinterParser(char chr, int count, int minWidth, int maxWidth,
4796                 int subsequentWidth) {
4797             super(null, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, subsequentWidth);
4798             this.chr = chr;
4799             this.count = count;
4800         }
4801 
4802         /**
4803          * Returns a new instance with fixed width flag set.
4804          *
4805          * @return a new updated printer-parser, not null
4806          */
4807         @Override
4808         WeekBasedFieldPrinterParser withFixedWidth() {
4809             if (subsequentWidth == -1) {
4810                 return this;
4811             }
4812             return new WeekBasedFieldPrinterParser(chr, count, minWidth, maxWidth, -1);
4813         }
4814 
4815         /**
4816          * Returns a new instance with an updated subsequent width.
4817          *
4818          * @param subsequentWidth  the width of subsequent non-negative numbers, 0 or greater
4819          * @return a new updated printer-parser, not null
4820          */
4821         @Override
4822         WeekBasedFieldPrinterParser withSubsequentWidth(int subsequentWidth) {
4823             return new WeekBasedFieldPrinterParser(chr, count, minWidth, maxWidth,
4824                     this.subsequentWidth + subsequentWidth);
4825         }
4826 
4827         @Override
4828         public boolean format(DateTimePrintContext context, StringBuilder buf) {
4829             return printerParser(context.getLocale()).format(context, buf);
4830         }
4831 
4832         @Override
4833         public int parse(DateTimeParseContext context, CharSequence text, int position) {
4834             return printerParser(context.getLocale()).parse(context, text, position);
4835         }
4836 
4837         /**
4838          * Gets the printerParser to use based on the field and the locale.
4839          *
4840          * @param locale  the locale to use, not null
4841          * @return the formatter, not null
4842          * @throws IllegalArgumentException if the formatter cannot be found
4843          */
4844         private DateTimePrinterParser printerParser(Locale locale) {
4845             WeekFields weekDef = WeekFields.of(locale);
4846             TemporalField field = null;
4847             switch (chr) {
4848                 case 'Y':
4849                     field = weekDef.weekBasedYear();
4850                     if (count == 2) {
4851                         return new ReducedPrinterParser(field, 2, 2, 0, ReducedPrinterParser.BASE_DATE,
4852                                 this.subsequentWidth);
4853                     } else {
4854                         return new NumberPrinterParser(field, count, 19,
4855                                 (count < 4) ? SignStyle.NORMAL : SignStyle.EXCEEDS_PAD,
4856                                 this.subsequentWidth);
4857                     }
4858                 case 'e':
4859                 case 'c':
4860                     field = weekDef.dayOfWeek();
4861                     break;
4862                 case 'w':
4863                     field = weekDef.weekOfWeekBasedYear();
4864                     break;
4865                 case 'W':
4866                     field = weekDef.weekOfMonth();
4867                     break;
4868                 default:
4869                     throw new IllegalStateException("unreachable");
4870             }
4871             return new NumberPrinterParser(field, minWidth, maxWidth, SignStyle.NOT_NEGATIVE, this.subsequentWidth);
4872         }
4873 
4874         @Override
4875         public String toString() {
4876             StringBuilder sb = new StringBuilder(30);
4877             sb.append("Localized(");
4878             if (chr == 'Y') {
4879                 if (count == 1) {
4880                     sb.append("WeekBasedYear");
4881                 } else if (count == 2) {
4882                     sb.append("ReducedValue(WeekBasedYear,2,2,2000-01-01)");
4883                 } else {
4884                     sb.append("WeekBasedYear,").append(count).append(",")
4885                             .append(19).append(",")
4886                             .append((count < 4) ? SignStyle.NORMAL : SignStyle.EXCEEDS_PAD);
4887                 }
4888             } else {
4889                 switch (chr) {
4890                     case 'c':
4891                     case 'e':


< prev index next >