+static const UChar QUOTE = 0x27; // Single quote
+
+/*
+ * The field range check bias for each UDateFormatField.
+ * The bias is added to the minimum and maximum values
+ * before they are compared to the parsed number.
+ * For example, the calendar stores zero-based month numbers
+ * but the parsed month numbers start at 1, so the bias is 1.
+ *
+ * A value of -1 means that the value is not checked.
+ */
+static const int32_t gFieldRangeBias[] = {
+ -1, // 'G' - UDAT_ERA_FIELD
+ -1, // 'y' - UDAT_YEAR_FIELD
+ 1, // 'M' - UDAT_MONTH_FIELD
+ 0, // 'd' - UDAT_DATE_FIELD
+ -1, // 'k' - UDAT_HOUR_OF_DAY1_FIELD
+ -1, // 'H' - UDAT_HOUR_OF_DAY0_FIELD
+ 0, // 'm' - UDAT_MINUTE_FIELD
+ 0, // 's' - UDAT_SECOND_FIELD
+ -1, // 'S' - UDAT_FRACTIONAL_SECOND_FIELD (0-999?)
+ -1, // 'E' - UDAT_DAY_OF_WEEK_FIELD (1-7?)
+ -1, // 'D' - UDAT_DAY_OF_YEAR_FIELD (1 - 366?)
+ -1, // 'F' - UDAT_DAY_OF_WEEK_IN_MONTH_FIELD (1-5?)
+ -1, // 'w' - UDAT_WEEK_OF_YEAR_FIELD (1-52?)
+ -1, // 'W' - UDAT_WEEK_OF_MONTH_FIELD (1-5?)
+ -1, // 'a' - UDAT_AM_PM_FIELD
+ -1, // 'h' - UDAT_HOUR1_FIELD
+ -1, // 'K' - UDAT_HOUR0_FIELD
+ -1, // 'z' - UDAT_TIMEZONE_FIELD
+ -1, // 'Y' - UDAT_YEAR_WOY_FIELD
+ -1, // 'e' - UDAT_DOW_LOCAL_FIELD
+ -1, // 'u' - UDAT_EXTENDED_YEAR_FIELD
+ -1, // 'g' - UDAT_JULIAN_DAY_FIELD
+ -1, // 'A' - UDAT_MILLISECONDS_IN_DAY_FIELD
+ -1, // 'Z' - UDAT_TIMEZONE_RFC_FIELD
+ -1, // 'v' - UDAT_TIMEZONE_GENERIC_FIELD
+ 0, // 'c' - UDAT_STANDALONE_DAY_FIELD
+ 1, // 'L' - UDAT_STANDALONE_MONTH_FIELD
+ -1, // 'Q' - UDAT_QUARTER_FIELD (1-4?)
+ -1, // 'q' - UDAT_STANDALONE_QUARTER_FIELD
+ -1, // 'V' - UDAT_TIMEZONE_SPECIAL_FIELD
+ -1, // 'U' - UDAT_YEAR_NAME_FIELD
+ -1, // 'O' - UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD
+ -1, // 'X' - UDAT_TIMEZONE_ISO_FIELD
+ -1, // 'x' - UDAT_TIMEZONE_ISO_LOCAL_FIELD
+ -1, // 'r' - UDAT_RELATED_YEAR_FIELD
+#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
+ -1, // ':' - UDAT_TIME_SEPARATOR_FIELD
+#else
+ -1, // (no pattern character currently) - UDAT_TIME_SEPARATOR_FIELD
+#endif
+};
+// A slightly looser range check for lenient parsing
+static const int32_t gFieldRangeBiasLenient[] = {
+ -1, // 'G' - UDAT_ERA_FIELD
+ -1, // 'y' - UDAT_YEAR_FIELD
+ 8, // 'M' - UDAT_MONTH_FIELD (allow calendar max + 7, e.g. 19 for grego 1-based month)
+ 18, // 'd' - UDAT_DATE_FIELD (allow calendar max + 18, e.g. 49 for grego; tests require at least 40 for grego)
+ -1, // 'k' - UDAT_HOUR_OF_DAY1_FIELD
+ -1, // 'H' - UDAT_HOUR_OF_DAY0_FIELD
+ 40, // 'm' - UDAT_MINUTE_FIELD (allow calendar max + 40, e.g. 99)
+ 40, // 's' - UDAT_SECOND_FIELD (allow calendar max + 40, e.g. 99)
+ -1, // 'S' - UDAT_FRACTIONAL_SECOND_FIELD (0-999?)
+ -1, // 'E' - UDAT_DAY_OF_WEEK_FIELD (1-7?)
+ -1, // 'D' - UDAT_DAY_OF_YEAR_FIELD (1 - 366?)
+ -1, // 'F' - UDAT_DAY_OF_WEEK_IN_MONTH_FIELD (1-5?)
+ -1, // 'w' - UDAT_WEEK_OF_YEAR_FIELD (1-52?)
+ -1, // 'W' - UDAT_WEEK_OF_MONTH_FIELD (1-5?)
+ -1, // 'a' - UDAT_AM_PM_FIELD
+ -1, // 'h' - UDAT_HOUR1_FIELD
+ -1, // 'K' - UDAT_HOUR0_FIELD
+ -1, // 'z' - UDAT_TIMEZONE_FIELD
+ -1, // 'Y' - UDAT_YEAR_WOY_FIELD
+ -1, // 'e' - UDAT_DOW_LOCAL_FIELD
+ -1, // 'u' - UDAT_EXTENDED_YEAR_FIELD
+ -1, // 'g' - UDAT_JULIAN_DAY_FIELD
+ -1, // 'A' - UDAT_MILLISECONDS_IN_DAY_FIELD
+ -1, // 'Z' - UDAT_TIMEZONE_RFC_FIELD
+ -1, // 'v' - UDAT_TIMEZONE_GENERIC_FIELD
+ 18, // 'c' - UDAT_STANDALONE_DAY_FIELD (allow calendar max + 18, e.g. 49 for grego)
+ 8, // 'L' - UDAT_STANDALONE_MONTH_FIELD (allow calendar max + 7, e.g. 19 for grego 1-based month)
+ -1, // 'Q' - UDAT_QUARTER_FIELD (1-4?)
+ -1, // 'q' - UDAT_STANDALONE_QUARTER_FIELD
+ -1, // 'V' - UDAT_TIMEZONE_SPECIAL_FIELD
+ -1, // 'U' - UDAT_YEAR_NAME_FIELD
+ -1, // 'O' - UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD
+ -1, // 'X' - UDAT_TIMEZONE_ISO_FIELD
+ -1, // 'x' - UDAT_TIMEZONE_ISO_LOCAL_FIELD
+ -1, // 'r' - UDAT_RELATED_YEAR_FIELD
+#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
+ -1, // ':' - UDAT_TIME_SEPARATOR_FIELD
+#else
+ -1, // (no pattern character currently) - UDAT_TIME_SEPARATOR_FIELD
+#endif
+};
+
+// When calendar uses hebr numbering (i.e. he@calendar=hebrew),
+// offset the years within the current millenium down to 1-999
+static const int32_t HEBREW_CAL_CUR_MILLENIUM_START_YEAR = 5000;
+static const int32_t HEBREW_CAL_CUR_MILLENIUM_END_YEAR = 6000;
+
+static UMutex LOCK;