src/jdk/nashorn/internal/objects/DateParser.java

Print this page




  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 }