15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.nashorn.internal.objects;
27
28 import static java.lang.Character.DECIMAL_DIGIT_NUMBER;
29 import static java.lang.Character.LOWERCASE_LETTER;
30 import static java.lang.Character.OTHER_PUNCTUATION;
31 import static java.lang.Character.SPACE_SEPARATOR;
32 import static java.lang.Character.UPPERCASE_LETTER;
33
34 import java.util.HashMap;
35
36 /**
37 * JavaScript date parser. This class first tries to parse a date string
38 * according to the extended ISO 8601 format specified in ES5 15.9.1.15.
39 * If that fails, it falls back to legacy mode in which it accepts a range
40 * of different formats.
41 *
42 * <p>This class is neither thread-safe nor reusable. Calling the
43 * <tt>parse()</tt> method more than once will yield undefined results.</p>
44 */
45 public class DateParser {
46
47 /** Constant for index position of parsed year value. */
48 public final static int YEAR = 0;
49 /** Constant for index position of parsed month value. */
50 public final static int MONTH = 1;
51 /** Constant for index position of parsed day value. */
52 public final static int DAY = 2;
53 /** Constant for index position of parsed hour value. */
54 public final static int HOUR = 3;
469
470 private int readNumber(final int maxDigits) {
471 final int start = pos;
472 int n = 0;
473 final int max = Math.min(length, pos + maxDigits);
474 while (pos < max && isAsciiDigit(string.charAt(pos))) {
475 n = n * 10 + string.charAt(pos++) - '0';
476 }
477 tokenLength = pos - start;
478 return n;
479 }
480
481 private Name readName() {
482 final int start = pos;
483 final int limit = Math.min(pos + 3, length);
484
485 // first read up to the key length
486 while (pos < limit && isAsciiLetter(string.charAt(pos))) {
487 pos++;
488 }
489 final String key = string.substring(start, pos).toLowerCase();
490 final Name name = names.get(key);
491 // then advance to end of name
492 while (pos < length && isAsciiLetter(string.charAt(pos))) {
493 pos++;
494 }
495
496 tokenLength = pos - start;
497 // make sure we have the full name or a prefix
498 if (name != null && name.matches(string, start, tokenLength)) {
499 return name;
500 }
501 return null;
502 }
503
504 private int readTimeZoneOffset() {
505 final int sign = string.charAt(pos - 1) == '+' ? 1 : -1;
506 int offset = readNumber(2);
507 skip(':');
508 offset = offset * 60 + readNumber(2);
509 return sign * offset;
666
667 private static void addName(final String str, final int type, final int value) {
668 final Name name = new Name(str, type, value);
669 names.put(name.key, name);
670 }
671
672 private static class Name {
673 final String name;
674 final String key;
675 final int value;
676 final int type;
677
678 final static int DAY_OF_WEEK = -1;
679 final static int MONTH_NAME = 0;
680 final static int AM_PM = 1;
681 final static int TIMEZONE_ID = 2;
682 final static int TIME_SEPARATOR = 3;
683
684 Name(final String name, final int type, final int value) {
685 assert name != null;
686 assert name.equals(name.toLowerCase());
687
688 this.name = name;
689 // use first three characters as lookup key
690 this.key = name.substring(0, Math.min(3, name.length()));
691 this.type = type;
692 this.value = value;
693 }
694
695 public boolean matches(final String str, final int offset, final int len) {
696 return name.regionMatches(true, 0, str, offset, len);
697 }
698
699 @Override
700 public String toString() {
701 return name;
702 }
703 }
704
705 }
|
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package jdk.nashorn.internal.objects;
27
28 import static java.lang.Character.DECIMAL_DIGIT_NUMBER;
29 import static java.lang.Character.LOWERCASE_LETTER;
30 import static java.lang.Character.OTHER_PUNCTUATION;
31 import static java.lang.Character.SPACE_SEPARATOR;
32 import static java.lang.Character.UPPERCASE_LETTER;
33
34 import java.util.HashMap;
35 import java.util.Locale;
36
37 /**
38 * JavaScript date parser. This class first tries to parse a date string
39 * according to the extended ISO 8601 format specified in ES5 15.9.1.15.
40 * If that fails, it falls back to legacy mode in which it accepts a range
41 * of different formats.
42 *
43 * <p>This class is neither thread-safe nor reusable. Calling the
44 * <tt>parse()</tt> method more than once will yield undefined results.</p>
45 */
46 public class DateParser {
47
48 /** Constant for index position of parsed year value. */
49 public final static int YEAR = 0;
50 /** Constant for index position of parsed month value. */
51 public final static int MONTH = 1;
52 /** Constant for index position of parsed day value. */
53 public final static int DAY = 2;
54 /** Constant for index position of parsed hour value. */
55 public final static int HOUR = 3;
470
471 private int readNumber(final int maxDigits) {
472 final int start = pos;
473 int n = 0;
474 final int max = Math.min(length, pos + maxDigits);
475 while (pos < max && isAsciiDigit(string.charAt(pos))) {
476 n = n * 10 + string.charAt(pos++) - '0';
477 }
478 tokenLength = pos - start;
479 return n;
480 }
481
482 private Name readName() {
483 final int start = pos;
484 final int limit = Math.min(pos + 3, length);
485
486 // first read up to the key length
487 while (pos < limit && isAsciiLetter(string.charAt(pos))) {
488 pos++;
489 }
490 final String key = string.substring(start, pos).toLowerCase(Locale.ENGLISH);
491 final Name name = names.get(key);
492 // then advance to end of name
493 while (pos < length && isAsciiLetter(string.charAt(pos))) {
494 pos++;
495 }
496
497 tokenLength = pos - start;
498 // make sure we have the full name or a prefix
499 if (name != null && name.matches(string, start, tokenLength)) {
500 return name;
501 }
502 return null;
503 }
504
505 private int readTimeZoneOffset() {
506 final int sign = string.charAt(pos - 1) == '+' ? 1 : -1;
507 int offset = readNumber(2);
508 skip(':');
509 offset = offset * 60 + readNumber(2);
510 return sign * offset;
667
668 private static void addName(final String str, final int type, final int value) {
669 final Name name = new Name(str, type, value);
670 names.put(name.key, name);
671 }
672
673 private static class Name {
674 final String name;
675 final String key;
676 final int value;
677 final int type;
678
679 final static int DAY_OF_WEEK = -1;
680 final static int MONTH_NAME = 0;
681 final static int AM_PM = 1;
682 final static int TIMEZONE_ID = 2;
683 final static int TIME_SEPARATOR = 3;
684
685 Name(final String name, final int type, final int value) {
686 assert name != null;
687 assert name.equals(name.toLowerCase(Locale.ENGLISH));
688
689 this.name = name;
690 // use first three characters as lookup key
691 this.key = name.substring(0, Math.min(3, name.length()));
692 this.type = type;
693 this.value = value;
694 }
695
696 public boolean matches(final String str, final int offset, final int len) {
697 return name.regionMatches(true, 0, str, offset, len);
698 }
699
700 @Override
701 public String toString() {
702 return name;
703 }
704 }
705
706 }
|