1422 * @param literal the literal to append, not null
1423 * @return this, for chaining, not null
1424 */
1425 public DateTimeFormatterBuilder appendLiteral(char literal) {
1426 appendInternal(new CharLiteralPrinterParser(literal));
1427 return this;
1428 }
1429
1430 /**
1431 * Appends a string literal to the formatter.
1432 * <p>
1433 * This string will be output during a format.
1434 * <p>
1435 * If the literal is empty, nothing is added to the formatter.
1436 *
1437 * @param literal the literal to append, not null
1438 * @return this, for chaining, not null
1439 */
1440 public DateTimeFormatterBuilder appendLiteral(String literal) {
1441 Objects.requireNonNull(literal, "literal");
1442 if (literal.length() > 0) {
1443 if (literal.length() == 1) {
1444 appendInternal(new CharLiteralPrinterParser(literal.charAt(0)));
1445 } else {
1446 appendInternal(new StringLiteralPrinterParser(literal));
1447 }
1448 }
1449 return this;
1450 }
1451
1452 //-----------------------------------------------------------------------
1453 /**
1454 * Appends all the elements of a formatter to the builder.
1455 * <p>
1456 * This method has the same effect as appending each of the constituent
1457 * parts of the formatter directly to this builder.
1458 *
1459 * @param formatter the formatter to add, not null
1460 * @return this, for chaining, not null
1461 */
1462 public DateTimeFormatterBuilder append(DateTimeFormatter formatter) {
1815 throw new IllegalArgumentException("Unknown pattern letter: " + cur);
1816 }
1817 pos--;
1818
1819 } else if (cur == '\'') {
1820 // parse literals
1821 int start = pos++;
1822 for ( ; pos < pattern.length(); pos++) {
1823 if (pattern.charAt(pos) == '\'') {
1824 if (pos + 1 < pattern.length() && pattern.charAt(pos + 1) == '\'') {
1825 pos++;
1826 } else {
1827 break; // end of literal
1828 }
1829 }
1830 }
1831 if (pos >= pattern.length()) {
1832 throw new IllegalArgumentException("Pattern ends with an incomplete string literal: " + pattern);
1833 }
1834 String str = pattern.substring(start + 1, pos);
1835 if (str.length() == 0) {
1836 appendLiteral('\'');
1837 } else {
1838 appendLiteral(str.replace("''", "'"));
1839 }
1840
1841 } else if (cur == '[') {
1842 optionalStart();
1843
1844 } else if (cur == ']') {
1845 if (active.parent == null) {
1846 throw new IllegalArgumentException("Pattern invalid as it contains ] without previous [");
1847 }
1848 optionalEnd();
1849
1850 } else if (cur == '{' || cur == '}' || cur == '#') {
1851 throw new IllegalArgumentException("Pattern includes reserved character: '" + cur + "'");
1852 } else {
1853 appendLiteral(cur);
1854 }
1855 }
4315 return description;
4316 }
4317 }
4318
4319 //-----------------------------------------------------------------------
4320 /**
4321 * A String based prefix tree for parsing time-zone names.
4322 */
4323 static class PrefixTree {
4324 protected String key;
4325 protected String value;
4326 protected char c0; // performance optimization to avoid the
4327 // boundary check cost of key.charat(0)
4328 protected PrefixTree child;
4329 protected PrefixTree sibling;
4330
4331 private PrefixTree(String k, String v, PrefixTree child) {
4332 this.key = k;
4333 this.value = v;
4334 this.child = child;
4335 if (k.length() == 0){
4336 c0 = 0xffff;
4337 } else {
4338 c0 = key.charAt(0);
4339 }
4340 }
4341
4342 /**
4343 * Creates a new prefix parsing tree based on parse context.
4344 *
4345 * @param context the parse context
4346 * @return the tree, not null
4347 */
4348 public static PrefixTree newTree(DateTimeParseContext context) {
4349 //if (!context.isStrict()) {
4350 // return new LENIENT("", null, null);
4351 //}
4352 if (context.isCaseSensitive()) {
4353 return new PrefixTree("", null, null);
4354 }
4355 return new CI("", null, null);
|
1422 * @param literal the literal to append, not null
1423 * @return this, for chaining, not null
1424 */
1425 public DateTimeFormatterBuilder appendLiteral(char literal) {
1426 appendInternal(new CharLiteralPrinterParser(literal));
1427 return this;
1428 }
1429
1430 /**
1431 * Appends a string literal to the formatter.
1432 * <p>
1433 * This string will be output during a format.
1434 * <p>
1435 * If the literal is empty, nothing is added to the formatter.
1436 *
1437 * @param literal the literal to append, not null
1438 * @return this, for chaining, not null
1439 */
1440 public DateTimeFormatterBuilder appendLiteral(String literal) {
1441 Objects.requireNonNull(literal, "literal");
1442 if (!literal.isEmpty()) {
1443 if (literal.length() == 1) {
1444 appendInternal(new CharLiteralPrinterParser(literal.charAt(0)));
1445 } else {
1446 appendInternal(new StringLiteralPrinterParser(literal));
1447 }
1448 }
1449 return this;
1450 }
1451
1452 //-----------------------------------------------------------------------
1453 /**
1454 * Appends all the elements of a formatter to the builder.
1455 * <p>
1456 * This method has the same effect as appending each of the constituent
1457 * parts of the formatter directly to this builder.
1458 *
1459 * @param formatter the formatter to add, not null
1460 * @return this, for chaining, not null
1461 */
1462 public DateTimeFormatterBuilder append(DateTimeFormatter formatter) {
1815 throw new IllegalArgumentException("Unknown pattern letter: " + cur);
1816 }
1817 pos--;
1818
1819 } else if (cur == '\'') {
1820 // parse literals
1821 int start = pos++;
1822 for ( ; pos < pattern.length(); pos++) {
1823 if (pattern.charAt(pos) == '\'') {
1824 if (pos + 1 < pattern.length() && pattern.charAt(pos + 1) == '\'') {
1825 pos++;
1826 } else {
1827 break; // end of literal
1828 }
1829 }
1830 }
1831 if (pos >= pattern.length()) {
1832 throw new IllegalArgumentException("Pattern ends with an incomplete string literal: " + pattern);
1833 }
1834 String str = pattern.substring(start + 1, pos);
1835 if (str.isEmpty()) {
1836 appendLiteral('\'');
1837 } else {
1838 appendLiteral(str.replace("''", "'"));
1839 }
1840
1841 } else if (cur == '[') {
1842 optionalStart();
1843
1844 } else if (cur == ']') {
1845 if (active.parent == null) {
1846 throw new IllegalArgumentException("Pattern invalid as it contains ] without previous [");
1847 }
1848 optionalEnd();
1849
1850 } else if (cur == '{' || cur == '}' || cur == '#') {
1851 throw new IllegalArgumentException("Pattern includes reserved character: '" + cur + "'");
1852 } else {
1853 appendLiteral(cur);
1854 }
1855 }
4315 return description;
4316 }
4317 }
4318
4319 //-----------------------------------------------------------------------
4320 /**
4321 * A String based prefix tree for parsing time-zone names.
4322 */
4323 static class PrefixTree {
4324 protected String key;
4325 protected String value;
4326 protected char c0; // performance optimization to avoid the
4327 // boundary check cost of key.charat(0)
4328 protected PrefixTree child;
4329 protected PrefixTree sibling;
4330
4331 private PrefixTree(String k, String v, PrefixTree child) {
4332 this.key = k;
4333 this.value = v;
4334 this.child = child;
4335 if (k.isEmpty()) {
4336 c0 = 0xffff;
4337 } else {
4338 c0 = key.charAt(0);
4339 }
4340 }
4341
4342 /**
4343 * Creates a new prefix parsing tree based on parse context.
4344 *
4345 * @param context the parse context
4346 * @return the tree, not null
4347 */
4348 public static PrefixTree newTree(DateTimeParseContext context) {
4349 //if (!context.isStrict()) {
4350 // return new LENIENT("", null, null);
4351 //}
4352 if (context.isCaseSensitive()) {
4353 return new PrefixTree("", null, null);
4354 }
4355 return new CI("", null, null);
|