changeset 8303:5435f112e5ea

Merge
author vinnie
date Fri, 12 Apr 2013 10:42:50 -0700
parents 0f93bd5cc8d7 e2cd40d7567c
children 6f80a6584fb9
files src/share/classes/java/time/chrono/HijrahDeviationReader.java src/share/classes/java/time/format/DateTimeBuilder.java src/share/classes/java/time/format/DateTimeFormatStyleProvider.java src/share/classes/java/time/temporal/Adjusters.java src/share/classes/java/time/temporal/Queries.java test/java/time/tck/java/time/TestChronology.java test/java/time/tck/java/time/chrono/TestChronoLocalDate.java test/java/time/tck/java/time/chrono/TestChronoLocalDateTime.java test/java/time/tck/java/time/chrono/TestHijrahChronology.java test/java/time/tck/java/time/chrono/TestJapaneseChronology.java test/java/time/tck/java/time/chrono/TestMinguoChronology.java test/java/time/tck/java/time/chrono/TestThaiBuddhistChronology.java test/java/time/tck/java/time/temporal/TCKDateTimeAdjusters.java test/java/time/tck/java/time/temporal/TestChronoLocalDate.java test/java/time/tck/java/time/temporal/TestChronoLocalDateTime.java test/java/time/tck/java/time/temporal/TestChronoZonedDateTime.java test/java/time/test/java/time/temporal/TestDateTimeAdjusters.java test/java/time/test/java/time/temporal/TestJapaneseChronoImpl.java test/java/time/test/java/time/temporal/TestThaiBuddhistChronoImpl.java
diffstat 434 files changed, 34761 insertions(+), 18078 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Thu Apr 11 21:03:24 2013 -0700
+++ b/.hgtags	Fri Apr 12 10:42:50 2013 -0700
@@ -206,3 +206,4 @@
 624bcb4800065c6656171948e31ebb2925f25c7a jdk8-b82
 ac519af51769e92c51b597a730974e8607357709 jdk8-b83
 7b4721e4edb4e1c65e9c839a70d7cc67f81c7632 jdk8-b84
+296676d534c52888c36e305a2bf7f345c4ca70f8 jdk8-b85
--- a/make/java/java/Makefile	Thu Apr 11 21:03:24 2013 -0700
+++ b/make/java/java/Makefile	Fri Apr 12 10:42:50 2013 -0700
@@ -313,6 +313,12 @@
 CAL_PROPS = calendars.properties
 
 #
+# Rule to copy Hijrah-umalqura calendar properties file.
+#
+HIJRAH_UMALQURA_PROPS = hijrah-config-umalqura.properties
+
+
+#
 # Rule to copy tzmappings file on Windows
 #
 ifeq ($(PLATFORM), windows)
@@ -324,7 +330,7 @@
 	$(call chmod-file, 444)
 endif
 
-build: $(LIBDIR)/$(PROPS) $(LIBDIR)/$(CAL_PROPS) $(TZMAP)
+build: $(LIBDIR)/$(PROPS) $(LIBDIR)/$(CAL_PROPS) $(LIBDIR)/$(HIJRAH_UMALQURA_PROPS) $(TZMAP)
 
 $(LIBDIR)/$(PROPS): $(PLATFORM_SRC)/lib/$(PROPS)
 	$(install-file)
@@ -332,6 +338,9 @@
 $(LIBDIR)/$(CAL_PROPS): $(SHARE_SRC)/lib/$(CAL_PROPS)
 	$(install-file)
 
+$(LIBDIR)/$(HIJRAH_UMALQURA_PROPS): $(SHARE_SRC)/lib/$(HIJRAH_UMALQURA_PROPS)
+	$(install-file)
+
 clean:: 
 	$(RM) -r $(LIBDIR)/$(PROPS) $(TZMAP)
 
--- a/make/java/text/base/FILES_java.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/make/java/text/base/FILES_java.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -105,5 +105,7 @@
         sun/text/resources/CollationData.java \
 	\
         sun/text/resources/FormatData.java \
+        sun/text/resources/JavaTimeSupplementary.java \
         sun/text/resources/en/FormatData_en.java \
-        sun/text/resources/en/FormatData_en_US.java
+        sun/text/resources/en/FormatData_en_US.java \
+        sun/text/resources/en/JavaTimeSupplementary_en.java \
--- a/make/java/util/FILES_java.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/make/java/util/FILES_java.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 FILES_java = \
         sun/util/resources/LocaleData.java \
         sun/util/resources/OpenListResourceBundle.java \
+        sun/util/resources/ParallelListResourceBundle.java \
         sun/util/resources/LocaleNamesBundle.java \
         sun/util/resources/TimeZoneNamesBundle.java \
         sun/util/resources/TimeZoneNames.java \
--- a/make/sun/text/FILES_java.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/make/sun/text/FILES_java.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -227,5 +227,54 @@
                 sun/util/resources/sv/TimeZoneNames_sv.java \
 		sun/util/resources/zh/TimeZoneNames_zh_CN.java \
 		sun/util/resources/zh/TimeZoneNames_zh_TW.java \
-		sun/util/resources/zh/TimeZoneNames_zh_HK.java
+		sun/util/resources/zh/TimeZoneNames_zh_HK.java \
+                \
+                sun/text/resources/ar/JavaTimeSupplementary_ar.java \
+                sun/text/resources/be/JavaTimeSupplementary_be.java \
+                sun/text/resources/bg/JavaTimeSupplementary_bg.java \
+                sun/text/resources/ca/JavaTimeSupplementary_ca.java \
+                sun/text/resources/cs/JavaTimeSupplementary_cs.java \
+                sun/text/resources/da/JavaTimeSupplementary_da.java \
+                sun/text/resources/de/JavaTimeSupplementary_de.java \
+                sun/text/resources/el/JavaTimeSupplementary_el.java \
+                sun/text/resources/en/JavaTimeSupplementary_en_GB.java \
+                sun/text/resources/en/JavaTimeSupplementary_en_SG.java \
+                sun/text/resources/es/JavaTimeSupplementary_es.java \
+                sun/text/resources/et/JavaTimeSupplementary_et.java \
+                sun/text/resources/fi/JavaTimeSupplementary_fi.java \
+                sun/text/resources/fr/JavaTimeSupplementary_fr.java \
+                sun/text/resources/ga/JavaTimeSupplementary_ga.java \
+                sun/text/resources/hi/JavaTimeSupplementary_hi_IN.java \
+                sun/text/resources/hr/JavaTimeSupplementary_hr.java \
+                sun/text/resources/hu/JavaTimeSupplementary_hu.java \
+                sun/text/resources/is/JavaTimeSupplementary_is.java \
+                sun/text/resources/it/JavaTimeSupplementary_it.java \
+                sun/text/resources/iw/JavaTimeSupplementary_iw.java \
+                sun/text/resources/iw/JavaTimeSupplementary_iw_IL.java \
+                sun/text/resources/ja/JavaTimeSupplementary_ja.java \
+                sun/text/resources/ko/JavaTimeSupplementary_ko.java \
+                sun/text/resources/lt/JavaTimeSupplementary_lt.java \
+                sun/text/resources/lv/JavaTimeSupplementary_lv.java \
+                sun/text/resources/mk/JavaTimeSupplementary_mk.java \
+                sun/text/resources/ms/JavaTimeSupplementary_ms.java \
+                sun/text/resources/mt/JavaTimeSupplementary_mt.java \
+                sun/text/resources/nl/JavaTimeSupplementary_nl.java \
+                sun/text/resources/no/JavaTimeSupplementary_no.java \
+                sun/text/resources/pl/JavaTimeSupplementary_pl.java \
+                sun/text/resources/pt/JavaTimeSupplementary_pt.java \
+                sun/text/resources/pt/JavaTimeSupplementary_pt_PT.java \
+                sun/text/resources/ro/JavaTimeSupplementary_ro.java \
+                sun/text/resources/ru/JavaTimeSupplementary_ru.java \
+                sun/text/resources/sk/JavaTimeSupplementary_sk.java \
+                sun/text/resources/sl/JavaTimeSupplementary_sl.java \
+                sun/text/resources/sq/JavaTimeSupplementary_sq.java \
+                sun/text/resources/sr/JavaTimeSupplementary_sr.java \
+                sun/text/resources/sr/JavaTimeSupplementary_sr_Latn.java \
+                sun/text/resources/sv/JavaTimeSupplementary_sv.java \
+                sun/text/resources/th/JavaTimeSupplementary_th.java \
+                sun/text/resources/tr/JavaTimeSupplementary_tr.java \
+                sun/text/resources/uk/JavaTimeSupplementary_uk.java \
+                sun/text/resources/vi/JavaTimeSupplementary_vi.java \
+                sun/text/resources/zh/JavaTimeSupplementary_zh.java \
+                sun/text/resources/zh/JavaTimeSupplementary_zh_TW.java
 
--- a/make/sun/tzdb/Makefile	Thu Apr 11 21:03:24 2013 -0700
+++ b/make/sun/tzdb/Makefile	Fri Apr 12 10:42:50 2013 -0700
@@ -42,7 +42,6 @@
 # Time zone data file creation
 #
 TZDATA_DIR := ../javazic/tzdata
-TZDATA_VER := $(subst tzdata,,$(shell $(GREP) '^tzdata' $(TZDATA_DIR)/VERSION))
 TZFILE := \
     africa antarctica asia australasia europe northamerica \
     pacificnew southamerica backward etcetera \
@@ -50,9 +49,7 @@
 
 TZFILES := $(addprefix $(TZDATA_DIR)/,$(TZFILE))
 
-
-
-TZDB_JAR = tzdb.jar
+TZDB_DAT = $(LIBDIR)/tzdb.dat
 
 #
 # Rules
@@ -62,13 +59,12 @@
 #
 # Add to the build rule
 #
-build: $(LIBDIR)/$(TZDB_JAR)
+build: $(TZDB_DAT)
 
-$(LIBDIR)/$(TZDB_JAR): $(TZFILES)
+$(TZDB_DAT): $(TZFILES)
 	$(prep-target)
-	echo build tzdb from version $(TZDATA_VER)
 	$(BOOT_JAVA_CMD) -jar $(BUILDTOOLJARDIR)/tzdb.jar \
-	  -version $(TZDATA_VER) -srcdir $(TZDATA_DIR) -dstdir $(LIBDIR) $(TZFILE)
+	  -srcdir $(TZDATA_DIR) -dstfile $(TZDB_DAT) $(TZFILE)
 
 clean clobber::
-	$(RM) $(LIBDIR)/$(TZDB_JAR)
+	$(RM) $(TZDB_DAT)
--- a/make/tools/src/build/tools/cldrconverter/AbstractLDMLHandler.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/make/tools/src/build/tools/cldrconverter/AbstractLDMLHandler.java	Fri Apr 12 10:42:50 2013 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 
 package build.tools.cldrconverter;
 
+import build.tools.cldrconverter.CLDRConverter.DraftType;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
@@ -88,7 +89,7 @@
         }
         String draftValue = attributes.getValue("draft");
         if (draftValue != null) {
-            return CLDRConverter.draftType > CLDRConverter.DRAFT_MAP.get(draftValue);
+            return DraftType.getDefault().ordinal() > DraftType.forKeyword(draftValue).ordinal();
         }
         return false;
     }
--- a/make/tools/src/build/tools/cldrconverter/Bundle.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/make/tools/src/build/tools/cldrconverter/Bundle.java	Fri Apr 12 10:42:50 2013 -0700
@@ -266,6 +266,9 @@
             handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "DayNarrows");
             handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "AmPmMarkers");
             handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "narrow.AmPmMarkers");
+            handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterNames");
+            handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterAbbreviations");
+            handleMultipleInheritance(myMap, parentsMap, calendarPrefix + "QuarterNarrows");
 
             adjustEraNames(myMap, calendarType);
 
@@ -484,25 +487,33 @@
         for (String k : patternKeys) {
             if (myMap.containsKey(calendarPrefix + k)) {
                 int len = patternKeys.length;
-                List<String> rawPatterns = new ArrayList<>();
-                List<String> patterns = new ArrayList<>();
+                List<String> rawPatterns = new ArrayList<>(len);
+                List<String> patterns = new ArrayList<>(len);
                 for (int i = 0; i < len; i++) {
                     String key = calendarPrefix + patternKeys[i];
                     String pattern = (String) myMap.remove(key);
                     if (pattern == null) {
                         pattern = (String) parentsMap.remove(key);
                     }
+                    rawPatterns.add(i, pattern);
                     if (pattern != null) {
-                        rawPatterns.add(i, pattern);
                         patterns.add(i, translateDateFormatLetters(calendarType, pattern));
+                    } else {
+                        patterns.add(i, null);
                     }
                 }
+                // If patterns is empty or has any nulls, discard patterns.
                 if (patterns.isEmpty()) {
                     return;
                 }
+                for (String p : patterns) {
+                    if (p == null) {
+                        return;
+                    }
+                }
                 String key = calendarPrefix + name;
                 if (!rawPatterns.equals(patterns)) {
-                    myMap.put("cldr." + key, rawPatterns.toArray(new String[len]));
+                    myMap.put("java.time." + key, rawPatterns.toArray(new String[len]));
                 }
                 myMap.put(key, patterns.toArray(new String[len]));
                 break;
--- a/make/tools/src/build/tools/cldrconverter/CLDRConverter.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/make/tools/src/build/tools/cldrconverter/CLDRConverter.java	Fri Apr 12 10:42:50 2013 -0700
@@ -68,25 +68,43 @@
     static MetaZonesParseHandler handlerMetaZones;
     private static BundleGenerator bundleGenerator;
 
-    static int draftType;
-    private static final String DRAFT_UNCONFIRMED = "unconfirmed";
-    private static final String DRAFT_PROVISIONAL = "provisional";
-    private static final String DRAFT_CONTRIBUTED = "contributed";
-    private static final String DRAFT_APPROVED = "approved";
-    private static final String DRAFT_TRUE = "true";
-    private static final String DRAFT_FALSE = "false";
-    private static final String DRAFT_DEFAULT = DRAFT_APPROVED;
-    static final Map<String, Integer> DRAFT_MAP = new HashMap<>();
+    static enum DraftType {
+        UNCONFIRMED,
+        PROVISIONAL,
+        CONTRIBUTED,
+        APPROVED;
 
-    static {
-        DRAFT_MAP.put(DRAFT_UNCONFIRMED, 0);
-        DRAFT_MAP.put(DRAFT_PROVISIONAL, 1);
-        DRAFT_MAP.put(DRAFT_CONTRIBUTED, 2);
-        DRAFT_MAP.put(DRAFT_APPROVED, 3);
-        DRAFT_MAP.put(DRAFT_TRUE, 0);
-        DRAFT_MAP.put(DRAFT_FALSE, 2);
-        draftType = DRAFT_MAP.get(DRAFT_DEFAULT);
-    };
+        private static final Map<String, DraftType> map = new HashMap<>();
+        static {
+            for (DraftType dt : values()) {
+                map.put(dt.getKeyword(), dt);
+            }
+        }
+        static private DraftType defaultType = CONTRIBUTED;
+
+        private final String keyword;
+
+        private DraftType() {
+            keyword = this.name().toLowerCase(Locale.ROOT);
+
+        }
+
+        static DraftType forKeyword(String keyword) {
+            return map.get(keyword);
+        }
+
+        static DraftType getDefault() {
+            return defaultType;
+        }
+
+        static void setDefault(String keyword) {
+            defaultType = Objects.requireNonNull(forKeyword(keyword));
+        }
+
+        String getKeyword() {
+            return keyword;
+        }
+    }
 
     static boolean USE_UTF8 = false;
     private static boolean verbose;
@@ -106,7 +124,7 @@
                     case "-draft":
                         String draftDataType = args[++i];
                         try {
-                            draftType = DRAFT_MAP.get(draftDataType);
+                            DraftType.setDefault(draftDataType);
                         } catch (NullPointerException e) {
                             severe("Error: incorrect draft value: %s%n", draftDataType);
                             System.exit(1);
@@ -525,7 +543,7 @@
         "standalone.MonthNames",
         "MonthAbbreviations",
         "standalone.MonthAbbreviations",
-        "MonthNarrow",
+        "MonthNarrows",
         "standalone.MonthNarrows",
         "DayNames",
         "standalone.DayNames",
@@ -533,6 +551,12 @@
         "standalone.DayAbbreviations",
         "DayNarrows",
         "standalone.DayNarrows",
+        "QuarterNames",
+        "standalone.QuarterNames",
+        "QuarterAbbreviations",
+        "standalone.QuarterAbbreviations",
+        "QuarterNarrows",
+        "standalone.QuarterNarrows",
         "AmPmMarkers",
         "narrow.AmPmMarkers",
         "long.Eras",
@@ -560,7 +584,7 @@
             String prefix = calendarType.keyElementName();
             for (String element : FORMAT_DATA_ELEMENTS) {
                 String key = prefix + element;
-                copyIfPresent(map, "cldr." + key, formatData);
+                copyIfPresent(map, "java.time." + key, formatData);
                 copyIfPresent(map, key, formatData);
             }
         }
--- a/make/tools/src/build/tools/cldrconverter/LDMLParseHandler.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/make/tools/src/build/tools/cldrconverter/LDMLParseHandler.java	Fri Apr 12 10:42:50 2013 -0700
@@ -356,6 +356,44 @@
                 }
             }
             break;
+        case "quarterContext":
+            {
+                // for FormatData
+                // need to keep stand-alone and format, to allow for inheritance in CLDR
+                String type = attributes.getValue("type");
+                if ("stand-alone".equals(type) || "format".equals(type)) {
+                    pushKeyContainer(qName, attributes, type);
+                } else {
+                    pushIgnoredContainer(qName);
+                }
+            }
+            break;
+        case "quarterWidth":
+            {
+                // for FormatData
+                // keep info about the context type so we can sort out inheritance later
+                String prefix = (currentCalendarType == null) ? "" : currentCalendarType.keyElementName();
+                switch (attributes.getValue("type")) {
+                case "wide":
+                    pushStringArrayEntry(qName, attributes, prefix + "QuarterNames/" + getContainerKey(), 4);
+                    break;
+                case "abbreviated":
+                    pushStringArrayEntry(qName, attributes, prefix + "QuarterAbbreviations/" + getContainerKey(), 4);
+                    break;
+                case "narrow":
+                    pushStringArrayEntry(qName, attributes, prefix + "QuarterNarrows/" + getContainerKey(), 4);
+                    break;
+                default:
+                    pushIgnoredContainer(qName);
+                    break;
+                }
+            }
+            break;
+        case "quarter":
+            // for FormatData
+            // add to string array entry of quarterWidth element
+            pushStringArrayElement(qName, attributes, Integer.parseInt(attributes.getValue("type")) - 1);
+            break;
 
         //
         // Time zone names
--- a/make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/make/tools/src/build/tools/tzdb/TzdbZoneRulesCompiler.java	Fri Apr 12 10:42:50 2013 -0700
@@ -58,12 +58,12 @@
 
 import static build.tools.tzdb.Utils.*;
 
-import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.text.ParsePosition;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -71,132 +71,131 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
+import java.util.NoSuchElementException;
+import java.util.Scanner;
 import java.util.SortedMap;
-import java.util.StringTokenizer;
 import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.jar.JarOutputStream;
-import java.util.zip.ZipEntry;
 import java.util.regex.Matcher;
+import java.util.regex.MatchResult;
 import java.util.regex.Pattern;
 
 /**
- * A builder that can read the TZDB time-zone files and build {@code ZoneRules} instances.
+ * A compiler that reads a set of TZDB time-zone files and builds a single
+ * combined TZDB data file.
  *
  * @since 1.8
  */
 public final class TzdbZoneRulesCompiler {
 
-    private static final Matcher YEAR = Pattern.compile("(?i)(?<min>min)|(?<max>max)|(?<only>only)|(?<year>[0-9]+)").matcher("");
-    private static final Matcher MONTH = Pattern.compile("(?i)(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)").matcher("");
-    private static final Matcher DOW = Pattern.compile("(?i)(mon)|(tue)|(wed)|(thu)|(fri)|(sat)|(sun)").matcher("");
-    private static final Matcher TIME = Pattern.compile("(?<neg>-)?+(?<hour>[0-9]{1,2})(:(?<minute>[0-5][0-9]))?+(:(?<second>[0-5][0-9]))?+").matcher("");
+    public static void main(String[] args) {
+        new TzdbZoneRulesCompiler().compile(args);
+    }
 
-    /**
-     * Constant for MJD 1972-01-01.
-     */
-    private static final long MJD_1972_01_01 = 41317L;
-
-    /**
-     * Reads a set of TZDB files and builds a single combined data file.
-     *
-     * @param args  the arguments
-     */
-    public static void main(String[] args) {
+    private void compile(String[] args) {
         if (args.length < 2) {
             outputHelp();
             return;
         }
-
-        // parse args
+        Path srcDir = null;
+        Path dstFile = null;
         String version = null;
-        File baseSrcDir = null;
-        File dstDir = null;
-        boolean verbose = false;
-
-        // parse options
+        // parse args/options
         int i;
         for (i = 0; i < args.length; i++) {
             String arg = args[i];
-            if (arg.startsWith("-") == false) {
+            if (!arg.startsWith("-")) {
                 break;
             }
             if ("-srcdir".equals(arg)) {
-                if (baseSrcDir == null && ++i < args.length) {
-                    baseSrcDir = new File(args[i]);
+                if (srcDir == null && ++i < args.length) {
+                    srcDir = Paths.get(args[i]);
                     continue;
                 }
-            } else if ("-dstdir".equals(arg)) {
-                if (dstDir == null && ++i < args.length) {
-                    dstDir = new File(args[i]);
-                    continue;
-                }
-            } else if ("-version".equals(arg)) {
-                if (version == null && ++i < args.length) {
-                    version = args[i];
+            } else if ("-dstfile".equals(arg)) {
+                if (dstFile == null && ++i < args.length) {
+                    dstFile = Paths.get(args[i]);
                     continue;
                 }
             } else if ("-verbose".equals(arg)) {
-                if (verbose == false) {
+                if (!verbose) {
                     verbose = true;
                     continue;
                 }
-            } else if ("-help".equals(arg) == false) {
+            } else if (!"-help".equals(arg)) {
                 System.out.println("Unrecognised option: " + arg);
             }
             outputHelp();
             return;
         }
-
         // check source directory
-        if (baseSrcDir == null) {
-            System.out.println("Source directory must be specified using -srcdir: " + baseSrcDir);
-            return;
+        if (srcDir == null) {
+            System.err.println("Source directory must be specified using -srcdir");
+            System.exit(1);
         }
-        if (baseSrcDir.isDirectory() == false) {
-            System.out.println("Source does not exist or is not a directory: " + baseSrcDir);
-            return;
+        if (!Files.isDirectory(srcDir)) {
+            System.err.println("Source does not exist or is not a directory: " + srcDir);
+            System.exit(1);
         }
-        dstDir = (dstDir != null ? dstDir : baseSrcDir);
-
         // parse source file names
-        List<String> srcFileNames = Arrays.asList(Arrays.copyOfRange(args, i, args.length));
-        if (srcFileNames.isEmpty()) {
-            System.out.println("Source filenames not specified, using default set");
-            System.out.println("(africa antarctica asia australasia backward etcetera europe northamerica southamerica)");
-            srcFileNames = Arrays.asList("africa", "antarctica", "asia", "australasia", "backward",
-                    "etcetera", "europe", "northamerica", "southamerica");
+        if (i == args.length) {
+            i = 0;
+            args = new String[] {"africa", "antarctica", "asia", "australasia", "europe",
+                                 "northamerica","southamerica", "backward", "etcetera" };
+            System.out.println("Source filenames not specified, using default set ( ");
+            for (String name : args) {
+                System.out.printf(name + " ");
+            }
+            System.out.println(")");
         }
-
-        // find source directories to process
-        List<File> srcDirs = new ArrayList<>();
-        if (version != null) {
-            //  if the "version" specified, as in jdk repo, the "baseSrcDir" is
-            //  the "srcDir" that contains the tzdb data.
-            srcDirs.add(baseSrcDir);
-        } else {
-            File[] dirs = baseSrcDir.listFiles();
-            for (File dir : dirs) {
-                if (dir.isDirectory() && dir.getName().matches("[12][0-9]{3}[A-Za-z0-9._-]+")) {
-                    srcDirs.add(dir);
-                }
+        // source files in this directory
+        List<Path> srcFiles = new ArrayList<>();
+        for (; i < args.length; i++) {
+            Path file = srcDir.resolve(args[i]);
+            if (Files.exists(file)) {
+                srcFiles.add(file);
+            } else {
+                System.err.println("Source directory does not contain source file: " + args[i]);
+                System.exit(1);
             }
         }
-        if (srcDirs.isEmpty()) {
-            System.out.println("Source directory contains no valid source folders: " + baseSrcDir);
-            return;
+        // check destination file
+        if (dstFile == null) {
+            dstFile = srcDir.resolve("tzdb.dat");
+        } else {
+            Path parent = dstFile.getParent();
+            if (parent != null && !Files.exists(parent)) {
+                System.err.println("Destination directory does not exist: " + parent);
+                System.exit(1);
+            }
         }
-        // check destination directory
-        if (dstDir.exists() == false && dstDir.mkdirs() == false) {
-            System.out.println("Destination directory could not be created: " + dstDir);
-            return;
+        try {
+            // get tzdb source version
+            Matcher m = Pattern.compile("tzdata(?<ver>[0-9]{4}[A-z])")
+                               .matcher(new String(Files.readAllBytes(srcDir.resolve("VERSION")),
+                                                   "ISO-8859-1"));
+            if (m.find()) {
+                version = m.group("ver");
+            } else {
+                System.exit(1);
+                System.err.println("Source directory does not contain file: VERSION");
+            }
+            printVerbose("Compiling TZDB version " + version);
+            // parse source files
+            for (Path file : srcFiles) {
+                printVerbose("Parsing file: " + file);
+                parseFile(file);
+            }
+            // build zone rules
+            printVerbose("Building rules");
+            buildZoneRules();
+            // output to file
+            printVerbose("Outputting tzdb file: " + dstFile);
+            outputFile(dstFile, version, builtZones, links);
+        } catch (Exception ex) {
+            System.out.println("Failed: " + ex.toString());
+            ex.printStackTrace();
+            System.exit(1);
         }
-        if (dstDir.isDirectory() == false) {
-            System.out.println("Destination is not a directory: " + dstDir);
-            return;
-        }
-        process(srcDirs, srcFileNames, dstDir, version, verbose);
         System.exit(0);
     }
 
@@ -206,145 +205,35 @@
     private static void outputHelp() {
         System.out.println("Usage: TzdbZoneRulesCompiler <options> <tzdb source filenames>");
         System.out.println("where options include:");
-        System.out.println("   -srcdir <directory>   Where to find source directories (required)");
-        System.out.println("   -dstdir <directory>   Where to output generated files (default srcdir)");
-        System.out.println("   -version <version>    Specify the version, such as 2009a (optional)");
+        System.out.println("   -srcdir  <directory>  Where to find tzdb source directory (required)");
+        System.out.println("   -dstfile <file>       Where to output generated file (default srcdir/tzdb.dat)");
         System.out.println("   -help                 Print this usage message");
         System.out.println("   -verbose              Output verbose information during compilation");
-        System.out.println(" There must be one directory for each version in srcdir");
-        System.out.println(" Each directory must have the name of the version, such as 2009a");
-        System.out.println(" Each directory must contain the unpacked tzdb files, such as asia or europe");
-        System.out.println(" Directories must match the regex [12][0-9][0-9][0-9][A-Za-z0-9._-]+");
-        System.out.println(" There will be one jar file for each version and one combined jar in dstdir");
-        System.out.println(" If the version is specified, only that version is processed");
-    }
-
-    /**
-     * Process to create the jar files.
-     */
-    private static void process(List<File> srcDirs, List<String> srcFileNames, File dstDir, String version, boolean verbose) {
-        // build actual jar files
-        Map<String, SortedMap<String, ZoneRules>> allBuiltZones = new TreeMap<>();
-        Set<String> allRegionIds = new TreeSet<String>();
-        Set<ZoneRules> allRules = new HashSet<ZoneRules>();
-        Map<String, Map<String, String>> allLinks = new TreeMap<>();
-
-        for (File srcDir : srcDirs) {
-            // source files in this directory
-            List<File> srcFiles = new ArrayList<>();
-            for (String srcFileName : srcFileNames) {
-                File file = new File(srcDir, srcFileName);
-                if (file.exists()) {
-                    srcFiles.add(file);
-                }
-            }
-            if (srcFiles.isEmpty()) {
-                continue;  // nothing to process
-            }
-
-            // compile
-            String loopVersion = (srcDirs.size() == 1 && version != null)
-                                 ? version : srcDir.getName();
-            TzdbZoneRulesCompiler compiler = new TzdbZoneRulesCompiler(loopVersion, srcFiles, verbose);
-            try {
-                // compile
-                compiler.compile();
-                SortedMap<String, ZoneRules> builtZones = compiler.getZones();
-
-                // output version-specific file
-                File dstFile = version == null ? new File(dstDir, "tzdb" + loopVersion + ".jar")
-                                               : new File(dstDir, "tzdb.jar");
-                if (verbose) {
-                    System.out.println("Outputting file: " + dstFile);
-                }
-                outputFile(dstFile, loopVersion, builtZones, compiler.links);
-
-                // create totals
-                allBuiltZones.put(loopVersion, builtZones);
-                allRegionIds.addAll(builtZones.keySet());
-                allRules.addAll(builtZones.values());
-                allLinks.put(loopVersion, compiler.links);
-            } catch (Exception ex) {
-                System.out.println("Failed: " + ex.toString());
-                ex.printStackTrace();
-                System.exit(1);
-            }
-        }
-
-        // output merged file
-        if (version == null) {
-            File dstFile = new File(dstDir, "tzdb-all.jar");
-            if (verbose) {
-                System.out.println("Outputting combined file: " + dstFile);
-            }
-            outputFile(dstFile, allBuiltZones, allRegionIds, allRules, allLinks);
-        }
+        System.out.println(" The source directory must contain the unpacked tzdb files, such as asia or europe");
     }
 
     /**
      * Outputs the file.
      */
-    private static void outputFile(File dstFile,
-                                   String version,
-                                   SortedMap<String, ZoneRules> builtZones,
-                                   Map<String, String> links) {
-        Map<String, SortedMap<String, ZoneRules>> loopAllBuiltZones = new TreeMap<>();
-        loopAllBuiltZones.put(version, builtZones);
-        Set<String> loopAllRegionIds = new TreeSet<String>(builtZones.keySet());
-        Set<ZoneRules> loopAllRules = new HashSet<ZoneRules>(builtZones.values());
-        Map<String, Map<String, String>> loopAllLinks = new TreeMap<>();
-        loopAllLinks.put(version, links);
-        outputFile(dstFile, loopAllBuiltZones, loopAllRegionIds, loopAllRules, loopAllLinks);
-    }
-
-    /**
-     * Outputs the file.
-     */
-    private static void outputFile(File dstFile,
-                                   Map<String, SortedMap<String, ZoneRules>> allBuiltZones,
-                                   Set<String> allRegionIds,
-                                   Set<ZoneRules> allRules,
-                                   Map<String, Map<String, String>> allLinks) {
-        try (JarOutputStream jos = new JarOutputStream(new FileOutputStream(dstFile))) {
-            outputTZEntry(jos, allBuiltZones, allRegionIds, allRules, allLinks);
-        } catch (Exception ex) {
-            System.out.println("Failed: " + ex.toString());
-            ex.printStackTrace();
-            System.exit(1);
-        }
-    }
-
-    /**
-     * Outputs the timezone entry in the JAR file.
-     */
-    private static void outputTZEntry(JarOutputStream jos,
-                                      Map<String, SortedMap<String, ZoneRules>> allBuiltZones,
-                                      Set<String> allRegionIds,
-                                      Set<ZoneRules> allRules,
-                                      Map<String, Map<String, String>> allLinks) {
-        // this format is not publicly specified
-        try {
-            jos.putNextEntry(new ZipEntry("TZDB.dat"));
-            DataOutputStream out = new DataOutputStream(jos);
-
+    private void outputFile(Path dstFile, String version,
+                            SortedMap<String, ZoneRules> builtZones,
+                            Map<String, String> links) {
+        try (DataOutputStream out = new DataOutputStream(Files.newOutputStream(dstFile))) {
             // file version
             out.writeByte(1);
             // group
             out.writeUTF("TZDB");
             // versions
-            String[] versionArray = allBuiltZones.keySet().toArray(new String[allBuiltZones.size()]);
-            out.writeShort(versionArray.length);
-            for (String version : versionArray) {
-                out.writeUTF(version);
-            }
+            out.writeShort(1);
+            out.writeUTF(version);
             // regions
-            String[] regionArray = allRegionIds.toArray(new String[allRegionIds.size()]);
+            String[] regionArray = builtZones.keySet().toArray(new String[builtZones.size()]);
             out.writeShort(regionArray.length);
             for (String regionId : regionArray) {
                 out.writeUTF(regionId);
             }
-            // rules
-            List<ZoneRules> rulesList = new ArrayList<>(allRules);
+            // rules  -- hashset -> remove the dup
+            List<ZoneRules> rulesList = new ArrayList<>(new HashSet<>(builtZones.values()));
             out.writeShort(rulesList.size());
             ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
             for (ZoneRules rules : rulesList) {
@@ -357,27 +246,22 @@
                 out.write(bytes);
             }
             // link version-region-rules
-            for (String version : allBuiltZones.keySet()) {
-                out.writeShort(allBuiltZones.get(version).size());
-                for (Map.Entry<String, ZoneRules> entry : allBuiltZones.get(version).entrySet()) {
-                     int regionIndex = Arrays.binarySearch(regionArray, entry.getKey());
-                     int rulesIndex = rulesList.indexOf(entry.getValue());
-                     out.writeShort(regionIndex);
-                     out.writeShort(rulesIndex);
-                }
+            out.writeShort(builtZones.size());
+            for (Map.Entry<String, ZoneRules> entry : builtZones.entrySet()) {
+                 int regionIndex = Arrays.binarySearch(regionArray, entry.getKey());
+                 int rulesIndex = rulesList.indexOf(entry.getValue());
+                 out.writeShort(regionIndex);
+                 out.writeShort(rulesIndex);
             }
             // alias-region
-            for (String version : allLinks.keySet()) {
-                out.writeShort(allLinks.get(version).size());
-                for (Map.Entry<String, String> entry : allLinks.get(version).entrySet()) {
-                     int aliasIndex = Arrays.binarySearch(regionArray, entry.getKey());
-                     int regionIndex = Arrays.binarySearch(regionArray, entry.getValue());
-                     out.writeShort(aliasIndex);
-                     out.writeShort(regionIndex);
-                }
+            out.writeShort(links.size());
+            for (Map.Entry<String, String> entry : links.entrySet()) {
+                 int aliasIndex = Arrays.binarySearch(regionArray, entry.getKey());
+                 int regionIndex = Arrays.binarySearch(regionArray, entry.getValue());
+                 out.writeShort(aliasIndex);
+                 out.writeShort(regionIndex);
             }
             out.flush();
-            jos.closeEntry();
         } catch (Exception ex) {
             System.out.println("Failed: " + ex.toString());
             ex.printStackTrace();
@@ -385,76 +269,30 @@
         }
     }
 
-    //-----------------------------------------------------------------------
+    private static final Pattern YEAR = Pattern.compile("(?i)(?<min>min)|(?<max>max)|(?<only>only)|(?<year>[0-9]+)");
+    private static final Pattern MONTH = Pattern.compile("(?i)(jan)|(feb)|(mar)|(apr)|(may)|(jun)|(jul)|(aug)|(sep)|(oct)|(nov)|(dec)");
+    private static final Matcher DOW = Pattern.compile("(?i)(mon)|(tue)|(wed)|(thu)|(fri)|(sat)|(sun)").matcher("");
+    private static final Matcher TIME = Pattern.compile("(?<neg>-)?+(?<hour>[0-9]{1,2})(:(?<minute>[0-5][0-9]))?+(:(?<second>[0-5][0-9]))?+").matcher("");
+
     /** The TZDB rules. */
     private final Map<String, List<TZDBRule>> rules = new HashMap<>();
 
     /** The TZDB zones. */
     private final Map<String, List<TZDBZone>> zones = new HashMap<>();
+
     /** The TZDB links. */
-
     private final Map<String, String> links = new HashMap<>();
 
     /** The built zones. */
     private final SortedMap<String, ZoneRules> builtZones = new TreeMap<>();
 
-
-    /** The version to produce. */
-    private final String version;
-
-    /** The source files. */
-
-    private final List<File> sourceFiles;
-
-    /** The version to produce. */
-    private final boolean verbose;
+    /** Whether to output verbose messages. */
+    private boolean verbose;
 
     /**
-     * Creates an instance if you want to invoke the compiler manually.
-     *
-     * @param version  the version, such as 2009a, not null
-     * @param sourceFiles  the list of source files, not empty, not null
-     * @param verbose  whether to output verbose messages
+     * private contructor
      */
-    public TzdbZoneRulesCompiler(String version, List<File> sourceFiles, boolean verbose) {
-        this.version = version;
-        this.sourceFiles = sourceFiles;
-        this.verbose = verbose;
-    }
-
-    /**
-     * Compile the rules file.
-     * <p>
-     * Use {@link #getZones()} to retrieve the parsed data.
-     *
-     * @throws Exception if an error occurs
-     */
-    public void compile() throws Exception {
-        printVerbose("Compiling TZDB version " + version);
-        parseFiles();
-        buildZoneRules();
-        printVerbose("Compiled TZDB version " + version);
-    }
-
-    /**
-     * Gets the parsed zone rules.
-     *
-     * @return the parsed zone rules, not null
-     */
-    public SortedMap<String, ZoneRules> getZones() {
-        return builtZones;
-    }
-
-    /**
-     * Parses the source files.
-     *
-     * @throws Exception if an error occurs
-     */
-    private void parseFiles() throws Exception {
-        for (File file : sourceFiles) {
-            printVerbose("Parsing file: " + file);
-            parseFile(file);
-        }
+    private TzdbZoneRulesCompiler() {
     }
 
     /**
@@ -463,14 +301,14 @@
      * @param file  the file being read, not null
      * @throws Exception if an error occurs
      */
-    private void parseFile(File file) throws Exception {
+    private void parseFile(Path file) throws Exception {
         int lineNumber = 1;
         String line = null;
-        BufferedReader in = null;
         try {
-            in = new BufferedReader(new FileReader(file));
+            List<String> lines = Files.readAllLines(file, StandardCharsets.ISO_8859_1);
             List<TZDBZone> openZone = null;
-            for ( ; (line = in.readLine()) != null; lineNumber++) {
+            for (; lineNumber < lines.size(); lineNumber++) {
+                line = lines.get(lineNumber);
                 int index = line.indexOf('#');  // remove comments (doesn't handle # in quotes)
                 if (index >= 0) {
                     line = line.substring(0, index);
@@ -478,41 +316,43 @@
                 if (line.trim().length() == 0) {  // ignore blank lines
                     continue;
                 }
-                StringTokenizer st = new StringTokenizer(line, " \t");
-                if (openZone != null && Character.isWhitespace(line.charAt(0)) && st.hasMoreTokens()) {
-                    if (parseZoneLine(st, openZone)) {
+                Scanner s = new Scanner(line);
+                if (openZone != null && Character.isWhitespace(line.charAt(0)) && s.hasNext()) {
+                    if (parseZoneLine(s, openZone)) {
                         openZone = null;
                     }
                 } else {
-                    if (st.hasMoreTokens()) {
-                        String first = st.nextToken();
+                    if (s.hasNext()) {
+                        String first = s.next();
                         if (first.equals("Zone")) {
-                            if (st.countTokens() < 3) {
+                            openZone = new ArrayList<>();
+                            try {
+                                zones.put(s.next(), openZone);
+                                if (parseZoneLine(s, openZone)) {
+                                    openZone = null;
+                                }
+                            } catch (NoSuchElementException x) {
                                 printVerbose("Invalid Zone line in file: " + file + ", line: " + line);
                                 throw new IllegalArgumentException("Invalid Zone line");
                             }
-                            openZone = new ArrayList<>();
-                            zones.put(st.nextToken(), openZone);
-                            if (parseZoneLine(st, openZone)) {
-                                openZone = null;
-                            }
                         } else {
                             openZone = null;
                             if (first.equals("Rule")) {
-                                if (st.countTokens() < 9) {
+                                try {
+                                    parseRuleLine(s);
+                                } catch (NoSuchElementException x) {
                                     printVerbose("Invalid Rule line in file: " + file + ", line: " + line);
                                     throw new IllegalArgumentException("Invalid Rule line");
                                 }
-                                parseRuleLine(st);
-
                             } else if (first.equals("Link")) {
-                                if (st.countTokens() < 2) {
+                                try {
+                                    String realId = s.next();
+                                    String aliasId = s.next();
+                                    links.put(aliasId, realId);
+                                } catch (NoSuchElementException x) {
                                     printVerbose("Invalid Link line in file: " + file + ", line: " + line);
                                     throw new IllegalArgumentException("Invalid Link line");
                                 }
-                                String realId = st.nextToken();
-                                String aliasId = st.nextToken();
-                                links.put(aliasId, realId);
 
                             } else {
                                 throw new IllegalArgumentException("Unknown line");
@@ -522,52 +362,44 @@
                 }
             }
         } catch (Exception ex) {
-            throw new Exception("Failed while processing file '" + file + "' on line " + lineNumber + " '" + line + "'", ex);
-        } finally {
-            try {
-                if (in != null) {
-                    in.close();
-                }
-            } catch (Exception ex) {
-                // ignore NPE and IOE
-            }
+            throw new Exception("Failed while parsing file '" + file + "' on line " + lineNumber + " '" + line + "'", ex);
         }
     }
 
     /**
      * Parses a Rule line.
      *
-     * @param st  the tokenizer, not null
+     * @param s  the line scanner, not null
      */
-    private void parseRuleLine(StringTokenizer st) {
+    private void parseRuleLine(Scanner s) {
         TZDBRule rule = new TZDBRule();
-        String name = st.nextToken();
+        String name = s.next();
         if (rules.containsKey(name) == false) {
             rules.put(name, new ArrayList<TZDBRule>());
         }
         rules.get(name).add(rule);
-        rule.startYear = parseYear(st.nextToken(), 0);
-        rule.endYear = parseYear(st.nextToken(), rule.startYear);
+        rule.startYear = parseYear(s, 0);
+        rule.endYear = parseYear(s, rule.startYear);
         if (rule.startYear > rule.endYear) {
             throw new IllegalArgumentException("Year order invalid: " + rule.startYear + " > " + rule.endYear);
         }
-        parseOptional(st.nextToken());  // type is unused
-        parseMonthDayTime(st, rule);
-        rule.savingsAmount = parsePeriod(st.nextToken());
-        rule.text = parseOptional(st.nextToken());
+        parseOptional(s.next());  // type is unused
+        parseMonthDayTime(s, rule);
+        rule.savingsAmount = parsePeriod(s.next());
+        rule.text = parseOptional(s.next());
     }
 
     /**
      * Parses a Zone line.
      *
-     * @param st  the tokenizer, not null
+     * @param s  the line scanner, not null
      * @return true if the zone is complete
      */
-    private boolean parseZoneLine(StringTokenizer st, List<TZDBZone> zoneList) {
+    private boolean parseZoneLine(Scanner s, List<TZDBZone> zoneList) {
         TZDBZone zone = new TZDBZone();
         zoneList.add(zone);
-        zone.standardOffset = parseOffset(st.nextToken());
-        String savingsRule = parseOptional(st.nextToken());
+        zone.standardOffset = parseOffset(s.next());
+        String savingsRule = parseOptional(s.next());
         if (savingsRule == null) {
             zone.fixedSavingsSecs = 0;
             zone.savingsRule = null;
@@ -580,11 +412,11 @@
                 zone.savingsRule = savingsRule;
             }
         }
-        zone.text = st.nextToken();
-        if (st.hasMoreTokens()) {
-            zone.year = Integer.parseInt(st.nextToken());
-            if (st.hasMoreTokens()) {
-                parseMonthDayTime(st, zone);
+        zone.text = s.next();
+        if (s.hasNext()) {
+            zone.year = Integer.parseInt(s.next());
+            if (s.hasNext()) {
+                parseMonthDayTime(s, zone);
             }
             return false;
         } else {
@@ -595,13 +427,13 @@
     /**
      * Parses a Rule line.
      *
-     * @param st  the tokenizer, not null
+     * @param s  the line scanner, not null
      * @param mdt  the object to parse into, not null
      */
-    private void parseMonthDayTime(StringTokenizer st, TZDBMonthDayTime mdt) {
-        mdt.month = parseMonth(st.nextToken());
-        if (st.hasMoreTokens()) {
-            String dayRule = st.nextToken();
+    private void parseMonthDayTime(Scanner s, TZDBMonthDayTime mdt) {
+        mdt.month = parseMonth(s);
+        if (s.hasNext()) {
+            String dayRule = s.next();
             if (dayRule.startsWith("last")) {
                 mdt.dayOfMonth = -1;
                 mdt.dayOfWeek = parseDayOfWeek(dayRule.substring(4));
@@ -621,8 +453,8 @@
                 }
                 mdt.dayOfMonth = Integer.parseInt(dayRule);
             }
-            if (st.hasMoreTokens()) {
-                String timeStr = st.nextToken();
+            if (s.hasNext()) {
+                String timeStr = s.next();
                 int secsOfDay = parseSecs(timeStr);
                 if (secsOfDay == 86400) {
                     mdt.endOfDay = true;
@@ -635,30 +467,43 @@
         }
     }
 
-    private int parseYear(String str, int defaultYear) {
-        if (YEAR.reset(str).matches()) {
-            if (YEAR.group("min") != null) {
+    private int parseYear(Scanner s, int defaultYear) {
+        if (s.hasNext(YEAR)) {
+            s.next(YEAR);
+            MatchResult mr = s.match();
+            if (mr.group(1) != null) {
+                return 1900;  // systemv has min
+            } else if (mr.group(2) != null) {
+                return YEAR_MAX_VALUE;
+            } else if (mr.group(3) != null) {
+                return defaultYear;
+            }
+            return Integer.parseInt(mr.group(4));
+            /*
+            if (mr.group("min") != null) {
                 //return YEAR_MIN_VALUE;
                 return 1900;  // systemv has min
-            } else if (YEAR.group("max") != null) {
+            } else if (mr.group("max") != null) {
                 return YEAR_MAX_VALUE;
-            } else if (YEAR.group("only") != null) {
+            } else if (mr.group("only") != null) {
                 return defaultYear;
             }
-            return Integer.parseInt(YEAR.group("year"));
+            return Integer.parseInt(mr.group("year"));
+            */
         }
-        throw new IllegalArgumentException("Unknown year: " + str);
+        throw new IllegalArgumentException("Unknown year: " + s.next());
     }
 
-    private int parseMonth(String str) {
-        if (MONTH.reset(str).matches()) {
+    private int parseMonth(Scanner s) {
+        if (s.hasNext(MONTH)) {
+            s.next(MONTH);
             for (int moy = 1; moy < 13; moy++) {
-                if (MONTH.group(moy) != null) {
+                if (s.match().group(moy) != null) {
                     return moy;
                 }
             }
         }
-        throw new IllegalArgumentException("Unknown month: " + str);
+        throw new IllegalArgumentException("Unknown month: " + s.next());
     }
 
     private int parseDayOfWeek(String str) {
@@ -729,7 +574,6 @@
         }
     }
 
-    //-----------------------------------------------------------------------
     /**
      * Build the rules, zones and links into real zones.
      *
@@ -744,8 +588,7 @@
             for (TZDBZone tzdbZone : tzdbZones) {
                 bld = tzdbZone.addToBuilder(bld, rules);
             }
-            ZoneRules buildRules = bld.toRules(zoneId);
-            builtZones.put(zoneId, buildRules);
+            builtZones.put(zoneId, bld.toRules(zoneId));
         }
 
         // build aliases
@@ -758,25 +601,25 @@
                 printVerbose("Relinking alias " + aliasId + " to " + realId);
                 realRules = builtZones.get(realId);
                 if (realRules == null) {
-                    throw new IllegalArgumentException("Alias '" + aliasId + "' links to invalid zone '" + realId + "' for '" + version + "'");
+                    throw new IllegalArgumentException("Alias '" + aliasId + "' links to invalid zone '" + realId);
                 }
                 links.put(aliasId, realId);
-
             }
             builtZones.put(aliasId, realRules);
         }
-
         // remove UTC and GMT
-        //builtZones.remove("UTC");
-        //builtZones.remove("GMT");
-        //builtZones.remove("GMT0");
+        // builtZones.remove("UTC");
+        // builtZones.remove("GMT");
+        // builtZones.remove("GMT0");
         builtZones.remove("GMT+0");
         builtZones.remove("GMT-0");
         links.remove("GMT+0");
         links.remove("GMT-0");
+        // remove ROC, which is not supported in j.u.tz
+        builtZones.remove("ROC");
+        links.remove("ROC");
     }
 
-    //-----------------------------------------------------------------------
     /**
      * Prints a verbose message.
      *
@@ -788,7 +631,6 @@
         }
     }
 
-    //-----------------------------------------------------------------------
     /**
      * Class representing a month-day-time in the TZDB file.
      */
@@ -893,5 +735,4 @@
             return ldt;
         }
     }
-
 }
--- a/makefiles/CompileDemos.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/CompileDemos.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -136,8 +136,7 @@
 			$$(wildcard $$(addprefix $(JDK_TOPDIR)/src/$6share/demo/$2/$1/,$7)))
     ifneq ($7,)
         $(JDK_OUTPUTDIR)/demo/$2/$1/% : $(JDK_TOPDIR)/src/$6share/demo/$2/$1/%
-		$(MKDIR) -p $$(@D)
-		$(CP) $$< $$@
+		$$(call install-file)
 		$(CHMOD) -f ug+w $$@
 
         BUILD_DEMOS += $$($1_COPY_TARGETS)
@@ -190,8 +189,7 @@
 			$(JDK_OUTPUTDIR)/demo/nbproject/%,\
 			$(call CacheFind,$(JDK_TOPDIR)/src/closed/share/demo/nbproject))
     $(JDK_OUTPUTDIR)/demo/nbproject/% : $(JDK_TOPDIR)/src/closed/share/demo/nbproject/%
-		$(MKDIR) -p $(@D)
-		$(CP) $< $@
+		$(call install-file)
 		$(CHMOD) -f ug+w $@
 endif
 
@@ -268,8 +266,7 @@
 		ZIP:=$(JDK_OUTPUTDIR)/demo/jvmti/$1/src.zip))
 
      $(JDK_OUTPUTDIR)/demo/jvmti/$1/README.txt : $(JDK_TOPDIR)/src/share/demo/jvmti/$1/README.txt
-		$(MKDIR) -p $$(@D)
-		$(CP) $$< $$@
+		$$(call install-file)
 		$(CHMOD) -f ug+w $$@
 
      ifneq (,$$(wildcard $(JDK_TOPDIR)/src/share/demo/jvmti/$1/*.java))
@@ -325,23 +322,22 @@
 JPDA_FILES:=$(subst $(JDK_TOPDIR)/src/share/classes/,,$(JPDA_SOURCES))
 
 $(JDK_OUTPUTDIR)/demo/jpda/src.zip : $(JPDA_SOURCES)
-		$(MKDIR) -p $(@D)
-		(cd $(JDK_TOPDIR)/src/share/classes && $(ZIP) -qru $@ com -i "com/sun/tools/example/*")
+	$(MKDIR) -p $(@D)
+	(cd $(JDK_TOPDIR)/src/share/classes && $(ZIP) -qru $@ com -i "com/sun/tools/example/*")
 
 $(JDK_OUTPUTDIR)/demo/jpda/examples.jar : $(JPDA_SOURCES)
-		$(MKDIR) -p $(@D)
-		$(RM) $(@D)/_the.sources
-		$(call ListPathsSafely,JPDA_FILES,\n, >> $(@D)/_the.sources)
-		$(SED) -e "s#@@RELEASE@@#$(RELEASE)#" 		\
-		       -e "s#@@COMPANY_NAME@@#$(COMPANY_NAME)#" $(JDK_TOPDIR)/make/tools/manifest.mf > $(@D)/_the.manifest
-		$(ECHO) "Main-Class: " >> $(@D)/_the.manifest
-		(cd $(JDK_TOPDIR)/src/share/classes && $(JAR) cfm  $@ $(@D)/_the.manifest @$(@D)/_the.sources)
-		(cd $(JDK_TOPDIR)/src/share/classes/com/sun/tools/example && $(JAR) uf $@ README)
+	$(MKDIR) -p $(@D)
+	$(RM) $(@D)/_the.sources
+	$(call ListPathsSafely,JPDA_FILES,\n, >> $(@D)/_the.sources)
+	$(SED) -e "s#@@RELEASE@@#$(RELEASE)#" 		\
+	       -e "s#@@COMPANY_NAME@@#$(COMPANY_NAME)#" $(JDK_TOPDIR)/make/tools/manifest.mf > $(@D)/_the.manifest
+	$(ECHO) "Main-Class: " >> $(@D)/_the.manifest
+	(cd $(JDK_TOPDIR)/src/share/classes && $(JAR) cfm  $@ $(@D)/_the.manifest @$(@D)/_the.sources)
+	(cd $(JDK_TOPDIR)/src/share/classes/com/sun/tools/example && $(JAR) uf $@ README)
 
 $(JDK_OUTPUTDIR)/demo/jpda/com/sun/tools/example/README : $(JDK_TOPDIR)/src/share/classes/com/sun/tools/example/README
-		$(MKDIR) -p $(@D)
-		$(CP) $< $@
-		$(CHMOD) -f ug+w $@
+	$(call install-file)
+	$(CHMOD) -f ug+w $@
 
 BUILD_DEMOS += $(JDK_OUTPUTDIR)/demo/jpda/src.zip $(JDK_OUTPUTDIR)/demo/jpda/examples.jar \
 		$(JDK_OUTPUTDIR)/demo/jpda/com/sun/tools/example/README
@@ -349,14 +345,12 @@
 ##################################################################################################
 
 $(JDK_OUTPUTDIR)/demo/management/index.html : $(JDK_TOPDIR)/src/share/demo/management/index.html
-		$(MKDIR) -p $(@D)
-		$(CP) $< $@
-		$(CHMOD) -f ug+w $@
+	$(call install-file)
+	$(CHMOD) -f ug+w $@
 
 $(JDK_OUTPUTDIR)/demo/jvmti/index.html : $(JDK_TOPDIR)/src/share/demo/jvmti/index.html
-		$(MKDIR) -p $(@D)
-		$(CP) $< $@
-		$(CHMOD) -f ug+w $@
+	$(call install-file)
+	$(CHMOD) -f ug+w $@
 
 BUILD_DEMOS += $(JDK_OUTPUTDIR)/demo/management/index.html \
 		$(JDK_OUTPUTDIR)/demo/jvmti/index.html
@@ -369,15 +363,13 @@
 		$(call CacheFind,$(JDK_TOPDIR)/src/share/demo/nbproject))
 
 $(JDK_OUTPUTDIR)/demo/nbproject/% : $(JDK_TOPDIR)/src/share/demo/nbproject/%
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+	$(call install-file)
 	$(CHMOD) -f ug+w $@
 
 ##################################################################################################
 
 $(JDK_OUTPUTDIR)/demo/README: $(JDK_TOPDIR)/src/share/demo/README
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+	$(call install-file)
 
 BUILD_DEMOS += $(JDK_OUTPUTDIR)/demo/README
 
@@ -386,14 +378,12 @@
 ifeq ($(OPENJDK_TARGET_OS), solaris)
 
 $(JDK_OUTPUTDIR)/democlasses/jni/Poller/% : $(JDK_TOPDIR)/src/solaris/demo/jni/Poller/%
-		$(MKDIR) -p $(@D)
-		$(CP) $< $@
-		$(CHMOD) -f ug+w $@
+	$(call install-file)
+	$(CHMOD) -f ug+w $@
 
 $(JDK_OUTPUTDIR)/demo/jni/Poller/README.txt : $(JDK_TOPDIR)/src/solaris/demo/jni/Poller/README.txt
-		$(MKDIR) -p $(@D)
-		$(CP) $< $@
-		$(CHMOD) -f ug+w $@
+	$(call install-file)
+	$(CHMOD) -f ug+w $@
 
 $(JDK_OUTPUTDIR)/demo/jni/Poller/Poller.jar : \
   $(JDK_OUTPUTDIR)/democlasses/jni/Poller/README.txt $(JDK_OUTPUTDIR)/democlasses/jni/Poller/Poller.c
@@ -433,8 +423,7 @@
 
 $(JDK_OUTPUTDIR)/demo/jni/Poller/lib/$(LIBRARY_PREFIX)Poller$(SHARED_LIBRARY_SUFFIX) : \
   $(JDK_OUTPUTDIR)/demoobjs/$(LIBRARY_PREFIX)Poller$(SHARED_LIBRARY_SUFFIX)
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+	$(call install-file)
 
 BUILD_DEMOS += $(JDK_OUTPUTDIR)/demo/jni/Poller/lib/$(LIBRARY_PREFIX)Poller$(SHARED_LIBRARY_SUFFIX)
 
@@ -456,8 +445,8 @@
      $(JDK_OUTPUTDIR)/demo/db/README-JDK-DEMOS.html: \
 		$(JDK_TOPDIR)/src/closed/share/db/README-JDK-DEMOS.html \
 		| $(JDK_OUTPUTDIR)/demo/_the.db.unzipped
-	$(MKDIR) -p $(@D)
-	$(CP) '$<' '$@'
+	$(call install-file)
+
      BUILD_DEMOS += $(JDK_OUTPUTDIR)/demo/_the.db.unzipped $(JDK_OUTPUTDIR)/demo/db/README-JDK-DEMOS.html
 endif
 
--- a/makefiles/CompileJavaClasses.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/CompileJavaClasses.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -281,8 +281,7 @@
 # These resources violates the convention of having code and resources together under
 # $(JDK_TOPDIR)/src/.../classes directories
 $(JDK_OUTPUTDIR)/classes/javax/swing/beaninfo/images/%.gif: $(JDK_TOPDIR)/make/tools/swing-beans/beaninfo/images/%.gif
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+	$(call install-file)
 
 # The JDK_USER_DEFINED_FILTER is a poor man's incremental build: by specifying
 # JDK_FILTER at the make command line, only a subset of the JDK java files will
--- a/makefiles/CompileLaunchers.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/CompileLaunchers.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -489,8 +489,7 @@
 # -link -incremental:no
 # like all other launchers.
 $(JDK_OUTPUTDIR)/bin$(OUTPUT_SUBDIR)/unpack200$(EXE_SUFFIX): $(BUILD_UNPACKEXE)
-	$(MKDIR) -p $(@D)
-	$(CP) '$<' '$@'
+	$(call install-file)
 
 BUILD_LAUNCHERS += $(JDK_OUTPUTDIR)/bin$(OUTPUT_SUBDIR)/unpack200$(EXE_SUFFIX)
 
@@ -588,8 +587,7 @@
         $(call SET_SHARED_LIBRARY_MAPFILE,$(JDK_TOPDIR)/makefiles/java/main/java/mapfile-$(OPENJDK_TARGET_CPU))))
 else
     $(JAVA_RMI_CGI): $(JDK_TOPDIR)/src/solaris/bin/java-rmi.cgi.sh
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+	$(call install-file)
 	$(CHMOD) a+x $@
 endif
 
--- a/makefiles/CompileNativeLibraries.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/CompileNativeLibraries.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -109,7 +109,7 @@
 
 BUILD_LIBFDLIBM := $(JDK_OUTPUTDIR)/objs/$(LIBRARY_PREFIX)fdlibm$(STATIC_LIBRARY_SUFFIX)
 $(BUILD_LIBFDLIBM) : $(BUILD_LIBFDLIBM_MAC)
-	$(CP) -a $< $@
+	$(call install-file)
 
 endif
 BUILD_LIBRARIES += $(BUILD_LIBFDLIBM)
@@ -1838,16 +1838,14 @@
 
 $(JDK_OUTPUTDIR)/lib/net.properties: $(JDK_TOPDIR)/src/share/lib/net.properties
 	$(ECHO) $(LOG_INFO) Copying $(@F)
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(JDK_OUTPUTDIR)/lib/net.properties
 
 ifeq ($(OPENJDK_TARGET_OS), solaris)
 $(JDK_OUTPUTDIR)/lib/sdp/sdp.conf.template : $(JDK_TOPDIR)/src/${OPENJDK_TARGET_OS_API_DIR}/lib/sdp/sdp.conf.template
 	$(ECHO) $(LOG_INFO) Copying $(@F)
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(JDK_OUTPUTDIR)/lib/sdp/sdp.conf.template
 endif
@@ -2168,7 +2166,7 @@
 		OBJECT_DIR:=$(JDK_OUTPUTDIR)/objs/libjli_static))
 
 $(JDK_OUTPUTDIR)/objs/libjli_static.a : $(BUILD_LIBJLI_STATIC)
-	$(CP) -a $< $@
+	$(call install-file)
 
 BUILD_LIBRARIES += $(JDK_OUTPUTDIR)/objs/libjli_static.a
 endif
--- a/makefiles/CopyFiles.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/CopyFiles.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -46,14 +46,10 @@
 		$(OPENJDK_TARGET_OS_INCLUDE)/jawt_md.h
 
 $(INCLUDEDIR)/%.h: $(JDK_TOPDIR)/src/share/javavm/export/%.h
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 $(OPENJDK_TARGET_OS_INCLUDE)/%.h: $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/javavm/export/%.h
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES = $(H_TARGET_FILES)
 
@@ -88,22 +84,16 @@
 MGMT_TARGET_FILES = $(subst $(MGMT_LIB_SRC),$(MGMT_LIBDIR),$(MGMT_SRC_FILES))
 
 $(MGMT_LIBDIR)/management.properties: $(MGMT_LIB_SRC)/management.properties
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 	$(CHMOD) 644 $@
 
 # this file has different permissions...don't know why...
 $(MGMT_LIBDIR)/jmxremote.access: $(MGMT_LIB_SRC)/jmxremote.access
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 	$(CHMOD) 644 $@
 
 $(MGMT_LIBDIR)/%: $(MGMT_LIB_SRC)/%
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 	$(CHMOD) 444 $@
 
 COPY_FILES += $(MGMT_TARGET_FILES)
@@ -113,9 +103,7 @@
 LOGGING_LIB_SRC = $(JDK_TOPDIR)/src/share/lib
 
 $(LIBDIR)/logging.properties: $(LOGGING_LIB_SRC)/logging.properties
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(LIBDIR)/logging.properties
 
@@ -128,9 +116,7 @@
 PSFONTPROPFILE_TARGET_FILES = $(subst $(PSFONTPROPFILE_SRC_DIR),$(LIBDIR),$(PSFONTPROPFILE_SRCS))
 
 $(LIBDIR)/%: $(PSFONTPROPFILE_SRC_DIR)/%
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(PSFONTPROPFILE_TARGET_FILES)
 
@@ -145,9 +131,7 @@
 endif
 
 $(LIBDIR)/flavormap.properties: $(OPENJDK_TARGET_OS_LIB_SRC)/flavormap.properties
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(LIBDIR)/flavormap.properties
 
@@ -155,9 +139,7 @@
 CURSORS_OPENJDK_TARGET_OS_LIB_SRC = $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/lib/images/cursors
 
 $(CURSORS_DEST_DIR)/cursors.properties: $(CURSORS_OPENJDK_TARGET_OS_LIB_SRC)/cursors.properties
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(CURSORS_DEST_DIR)/cursors.properties
 
@@ -170,9 +152,7 @@
 CURSORS_TARGET_FILES =  $(subst $(CURSORS_LIB_SRC),$(CURSORS_DEST_DIR),$(CURSORS_SRC_FILES))
 
 $(CURSORS_DEST_DIR)/%: $(CURSORS_LIB_SRC)/%
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(CURSORS_TARGET_FILES)
 
@@ -181,9 +161,7 @@
 CONTENT_TYPES_SRC=$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/lib
 
 $(LIBDIR)/content-types.properties: $(CONTENT_TYPES_SRC)/content-types.properties
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(LIBDIR)/content-types.properties
 
@@ -192,11 +170,16 @@
 CALENDARS_SRC := $(JDK_TOPDIR)/src/share/lib
 
 $(LIBDIR)/calendars.properties: $(CALENDARS_SRC)/calendars.properties
+	$(call install-file)
+
+COPY_FILES += $(LIBDIR)/calendars.properties
+
+$(LIBDIR)/hijrah-config-umalqura.properties: $(CALENDARS_SRC)/hijrah-config-umalqura.properties
 	$(MKDIR) -p $(@D)
 	$(RM) $@
 	$(CP) $< $@
 
-COPY_FILES += $(LIBDIR)/calendars.properties
+COPY_FILES += $(LIBDIR)/hijrah-config-umalqura.properties
 
 ##########################################################################################
 
@@ -205,9 +188,7 @@
 TZMAPPINGS_SRC := $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/lib
 
 $(LIBDIR)/tzmappings: $(TZMAPPINGS_SRC)/tzmappings
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(LIBDIR)/tzmappings
 
@@ -227,9 +208,7 @@
 ICCPROFILE_TARGET_FILES:=$(subst $(ICCPROFILE_SRC_DIR),$(ICCPROFILE_DEST_DIR),$(ICCPROFILE_SRCS))
 
 $(ICCPROFILE_DEST_DIR)%.pf: $(ICCPROFILE_SRC_DIR)%.pf
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 	$(CHMOD) 444 $@
 
 COPY_FILES += $(ICCPROFILE_TARGET_FILES)
@@ -279,9 +258,7 @@
     MSVCR_TARGET := $(JDK_OUTPUTDIR)/bin/$(notdir $(MSVCR_DLL))
     # Chmod to avoid permission issues if bundles are unpacked on unix platforms.
     $(MSVCR_TARGET): $(MSVCR_DLL)
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 	$(CHMOD) a+rx $@
 
     COPY_FILES += $(MSVCR_TARGET)
@@ -292,9 +269,7 @@
 HPROF_SRC=$(JDK_TOPDIR)/src/share/demo/jvmti/hprof/jvm.hprof.txt
 
 $(LIBDIR)/jvm.hprof.txt : $(HPROF_SRC)
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(LIBDIR)/jvm.hprof.txt
 
@@ -351,17 +326,13 @@
         else
             # Use the default jvm.cfg for this 32 bit setup. 
             $(JVMCFG): $(JVMCFG_SRC)
-	    	$(MKDIR) -p $(@D)
-		$(RM) $@
-		$(CP) $< $@
+	    	$(call install-file)
         endif
     endif
 else
     # Use the default jvm.cfg for this 64 bit setup.
     $(JVMCFG): $(JVMCFG_SRC)
-		$(MKDIR) -p $(@D)
-		$(RM) $@
-		$(CP) $< $@
+		$(call install-file)
 endif
 
 COPY_FILES += $(JVMCFG)
@@ -372,9 +343,7 @@
 PROPS_DST := $(JDK_OUTPUTDIR)/lib/security/java.security
 
 $(PROPS_DST): $(PROPS_SRC)
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(PROPS_DST)
 
@@ -384,9 +353,7 @@
 POLICY_DST := $(JDK_OUTPUTDIR)/lib/security/java.policy
 
 $(POLICY_DST): $(POLICY_SRC)
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(POLICY_DST)
 
@@ -396,9 +363,7 @@
 CACERTS_DST := $(JDK_OUTPUTDIR)/lib/security/cacerts
 
 $(CACERTS_DST): $(CACERTS_SRC)
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(CACERTS_DST)
 
@@ -413,16 +378,12 @@
 TRUSTEDLIBS_DST := $(JDK_OUTPUTDIR)/lib/security/trusted.libraries
 
 $(BLACKLIST_DST): $(BLACKLIST_SRC)
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(BLACKLIST_DST)
 
 $(TRUSTEDLIBS_DST): $(TRUSTEDLIBS_SRC)
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(TRUSTEDLIBS_DST)
 
@@ -448,14 +409,10 @@
 SHARED_FONTS_DST := $(foreach F,$(SHARED_FONTS_FILES),$(SHARED_FONTS_DST_DIR)/$(F))
 
 $(SHARED_FONTS_DST_DIR)/%.ttf : $(SHARED_FONTS_SRC_DIR)/%.ttf
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 $(SHARED_FONTS_DST_DIR)/fonts.dir : $(JDK_TOPDIR)/src/solaris/classes/sun/awt/motif/java.fonts.dir
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(SHARED_FONTS_DST)
 
@@ -476,14 +433,10 @@
 OBL_FONTS_DST := $(foreach F,$(OBL_FONTS_FILES),$(OBL_FONTS_DST_DIR)/$(F))
 
 $(OBL_FONTS_DST_DIR)/%.ttf : $(OBL_FONTS_SRC_DIR)/%.ttf
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 $(OBL_FONTS_DST_DIR)/fonts.dir : $(JDK_TOPDIR)/src/solaris/classes/sun/awt/motif/java.oblique-fonts.dir
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(OBL_FONTS_DST) $(OBL_FONTS_DST_DIR)/fonts.dir
 
@@ -502,9 +455,7 @@
 JS_RESOURCES_DST := $(foreach F,$(JS_RESOURCES_FILES),$(JS_RESOURCES_DST_DIR)/$(F))
 
 $(JS_RESOURCES_DST_DIR)/% : $(JS_RESOURCES_SRC_DIR)/%
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(JS_RESOURCES_DST)
 
@@ -539,15 +490,11 @@
 DGALIBS = $(_DGALIBS_$(OPENJDK_TARGET_CPU_LEGACY):%=$(JDK_OUTPUTDIR)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/%)
 
 $(JDK_OUTPUTDIR)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libxinerama.so: $(JDK_TOPDIR)/src/closed/solaris/lib/$(OPENJDK_TARGET_CPU_LEGACY)/libxinerama.so
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 	$(CHMOD) 755 $@
 
 $(JDK_OUTPUTDIR)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjdgaSUNW%.so: $(JDK_TOPDIR)/src/closed/solaris/lib/$(OPENJDK_TARGET_CPU_LEGACY)/libjdgaSUNW%.so
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 	$(CHMOD) 755 $@
 
 $(JDK_OUTPUTDIR)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjdgaSUNWafb.so: $(JDK_OUTPUTDIR)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjdgaSUNWffb.so
@@ -567,9 +514,7 @@
 SUNPKCS11_CFG_DST := $(JDK_OUTPUTDIR)/lib/security/sunpkcs11-solaris.cfg
 
 $(SUNPKCS11_CFG_DST) : $(SUNPKCS11_CFG_SRC)
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(SUNPKCS11_CFG_DST)
 
@@ -584,9 +529,7 @@
 UCRYPTO_CFG_DST := $(JDK_OUTPUTDIR)/lib/security/ucrypto-solaris.cfg
 
 $(UCRYPTO_CFG_DST) : $(UCRYPTO_CFG_SRC)
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(UCRYPTO_CFG_DST)
 
@@ -596,9 +539,7 @@
 ##########################################################################################
 
 $(JDK_OUTPUTDIR)/lib/sound.properties : $(JDK_TOPDIR)/src/share/lib/sound.properties
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $(@)
+	$(call install-file)
 
 COPY_FILES += $(JDK_OUTPUTDIR)/lib/sound.properties
 
--- a/makefiles/CopyIntoClasses.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/CopyIntoClasses.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -223,9 +223,7 @@
 ###
 
 $(JDK_OUTPUTDIR)/classes/sun/nio/cs/ext/sjis0213.dat : $(JDK_OUTPUTDIR)/gensrc/sun/nio/cs/ext/sjis0213.dat
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $(@)
+	$(call install-file)
 
 COPY_EXTRA += $(JDK_OUTPUTDIR)/classes/sun/nio/cs/ext/sjis0213.dat
 
--- a/makefiles/CopySamples.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/CopySamples.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -53,19 +53,13 @@
 endif
 
 $(SAMPLE_TARGET_DIR)/dtrace/%: $(SAMPLE_SOLARIS_SOURCE_DIR)/dtrace/%
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 $(SAMPLE_TARGET_DIR)/webservices/%: $(SAMPLE_CLOSED_SOURCE_DIR)/webservices/%
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 $(SAMPLE_TARGET_DIR)/%: $(SAMPLE_SOURCE_DIR)/%
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 
 COPY_FILES += $(SAMPLE_TARGET)
 
--- a/makefiles/CreateJars.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/CreateJars.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -73,11 +73,6 @@
 
 ##########################################################################################
 
-$(IMAGES_OUTPUTDIR)/lib/tzdb.jar: $(JDK_OUTPUTDIR)/lib/tzdb.jar
-	$(install-file)
-
-##########################################################################################
-
 LOCALEDATA_INCLUDE_LOCALES := ar be bg ca cs da de el es et fi fr ga hi hr hu in is it \
                               iw ja ko lt lv mk ms mt nl no pl pt ro ru sk sl sq sr sv \
                               th tr uk vi zh
--- a/makefiles/GendataFontConfig.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/GendataFontConfig.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -72,9 +72,7 @@
 
 $(GENDATA_FONT_CONFIG_DST)/%.src : \
     $(GENDATA_FONT_CONFIG_SRC_DIR)/$(GENDATA_FONT_CONFIG_SRC_PREFIX)%
-	$(RM) $@
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+	$(call install-file)
 
 $(GENDATA_FONT_CONFIG_DST)/%.bfc : \
     $(GENDATA_FONT_CONFIG_SRC_DIR)/$(GENDATA_FONT_CONFIG_SRC_PREFIX)%.properties
--- a/makefiles/GendataTZDB.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/GendataTZDB.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -29,16 +29,13 @@
 # Time zone data file creation
 #
 TZDATA_DIR := $(JDK_TOPDIR)/make/sun/javazic/tzdata
-TZDATA_VER := $(subst tzdata,,$(shell $(GREP) '^tzdata' $(TZDATA_DIR)/VERSION))
 TZDATA_TZFILE := africa antarctica asia australasia europe northamerica pacificnew southamerica backward etcetera gmt jdk11_backward
 TZDATA_TZFILES := $(addprefix $(TZDATA_DIR)/,$(TZDATA_TZFILE))
 
-GENDATA_TZDB_DST := $(JDK_OUTPUTDIR)/lib
-GENDATA_TZDB_JAR := tzdb.jar
+GENDATA_TZDB_DAT := $(JDK_OUTPUTDIR)/lib/tzdb.dat
 
-$(GENDATA_TZDB_DST)/$(GENDATA_TZDB_JAR) : $(TZDATA_TZFILES)
-	$(RM) $(GENDATA_TZDB_DST)/$(GENDATA_TZDB_JAR)
-	echo building tzdb from version $(TZDATA_VER)
-	$(TOOL_TZDB) -version $(TZDATA_VER) -srcdir $(TZDATA_DIR) -dstdir $(GENDATA_TZDB_DST) $(TZDATA_TZFILE)
+$(GENDATA_TZDB_DAT) : $(TZDATA_TZFILES)
+	$(RM) $(GENDATA_TZDB_DAT)
+	$(TOOL_TZDB) -srcdir $(TZDATA_DIR) -dstfile $(GENDATA_TZDB_DAT) $(TZDATA_TZFILE)
 
-GENDATA_TZDB += $(GENDATA_TZDB_DST)/$(GENDATA_TZDB_JAR)
+GENDATA_TZDB += $(GENDATA_TZDB_DAT)
--- a/makefiles/GensrcCharacterData.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/GensrcCharacterData.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -55,9 +55,8 @@
 
 # Copy two Java files that need no preprocessing.
 $(JDK_OUTPUTDIR)/gensrc/java/lang/%.java : $(CHARACTERDATA)/%.java.template
-	$(MKDIR) -p $(@D)
 	$(ECHO) $(LOG_INFO) Generating $(@F)
-	$(CP) -f $< $@
+	$(call install-file)
 
 GENSRC_CHARACTERDATA += $(JDK_OUTPUTDIR)/gensrc/java/lang/CharacterDataUndefined.java \
                        $(JDK_OUTPUTDIR)/gensrc/java/lang/CharacterDataPrivateUse.java
--- a/makefiles/GensrcMisc.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/GensrcMisc.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -72,9 +72,8 @@
 
     $(JDK_OUTPUTDIR)/gensrc/java/lang/UNIXProcess.java : \
               $(JDK_TOPDIR)/src/solaris/classes/java/lang/UNIXProcess.java.$(UPSUFFIX)
-	$(MKDIR) -p $(@D)
 	$(ECHO) $(LOG_INFO) Copying UNIXProcess.java.$(OPENJDK_TARGET_OS) to java/lang/UNIXProcess.java
-	$(CP) $< $@
+	$(call install-file)
 	$(CHMOD) u+rw $@
 
     GENSRC_MISC += $(JDK_OUTPUTDIR)/gensrc/java/lang/UNIXProcess.java
@@ -114,9 +113,7 @@
 	$(MV) $@.tmp $@
 else
 $(JDK_OUTPUTDIR)/gensrc/sun/nio/ch/SocketOptionRegistry.java : $(JDK_TOPDIR)/src/closed/solaris/classes/sun/nio/ch/SocketOptionRegistry-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH).java
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 endif
 
 ##########################################################################################
@@ -156,9 +153,7 @@
 	$(MV) $@.tmp $@
 else
 $(JDK_OUTPUTDIR)/gensrc/sun/nio/fs/UnixConstants.java : $(JDK_TOPDIR)/src/closed/solaris/classes/sun/nio/fs/UnixConstants-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH).java
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+	$(call install-file)
 endif
 
 endif
--- a/makefiles/GensrcSwing.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/GensrcSwing.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -85,14 +85,12 @@
 # For some reason it is under $(JDK_TOPDIR)/make/tools/swing-beans/javax/swing
 # Should it be moved under $(JDK_TOPDIR)/src/share/classes/javax/swing instead?
 $(JDK_OUTPUTDIR)/gensrc_no_srczip/javax/swing/SwingBeanInfoBase.java: $(DOCLETSRC_DIR)/javax/swing/SwingBeanInfoBase.java
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+	$(call install-file)
 
 # This file is the part of dt.jar 
 # For some reason it is under $(JDK_TOPDIR)/make/tools/swing-beans/sun/swing
 # Should it be moved under $(JDK_TOPDIR)/src/share/classes/sun/swing instead?
 $(JDK_OUTPUTDIR)/gensrc/sun/swing/BeanInfoUtils.java: $(DOCLETSRC_DIR)/sun/swing/BeanInfoUtils.java
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+	$(call install-file)
 
 GENSRC_SWING_BEANINFO = $(JDK_OUTPUTDIR)/gensrc_no_srczip/_the.generated_beaninfo
--- a/makefiles/Profiles.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/Profiles.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -93,8 +93,11 @@
         $(IMAGES_OUTPUTDIR)/lib/dt.jar \
         $(IMAGES_OUTPUTDIR)/lib/tools.jar \
         $(IMAGES_OUTPUTDIR)/lib/ct.sym \
-        $(IMAGES_OUTPUTDIR)/src.zip \
-        $(IMAGES_OUTPUTDIR)/lib/sa-jdi.jar
+        $(IMAGES_OUTPUTDIR)/src.zip
+
+ifeq ($(INCLUDE_SA),true)
+    ALL_JARS += $(IMAGES_OUTPUTDIR)/lib/sa-jdi.jar
+endif
 
 ifeq ($(OPENJDK_TARGET_OS),solaris)
     ifndef OPENJDK
--- a/makefiles/SignJars.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/SignJars.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -79,8 +79,7 @@
 	fi
 
 $(JCE_OUTPUTDIR)/%: $(IMAGES_OUTPUTDIR)/unsigned/%
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+	$(call install-file)
 	$(JARSIGNER) -keystore $(SIGNING_KEYSTORE) \
 	    $@ $(SIGNING_ALIAS) < $(SIGNING_PASSPHRASE)
 	@$(PRINTF) "\nJar codesigning finished.\n"
--- a/makefiles/Tools.gmk	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/Tools.gmk	Fri Apr 12 10:42:50 2013 -0700
@@ -47,17 +47,15 @@
 endif
 
 $(JDK_OUTPUTDIR)/btclasses/build/tools/generatenimbus/resources/%.template : \
-	$(JDK_TOPDIR)/src/share/classes/javax/swing/plaf/nimbus/%.template
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+		$(JDK_TOPDIR)/src/share/classes/javax/swing/plaf/nimbus/%.template
+	$(call install-file)
 
 BUILD_TOOLS += $(foreach i,$(wildcard $(JDK_TOPDIR)/src/share/classes/javax/swing/plaf/nimbus/*.template),$(JDK_OUTPUTDIR)/btclasses/build/tools/generatenimbus/resources/$(notdir $i))
 
 # Resources used by CheckDeps tool
 $(JDK_OUTPUTDIR)/btclasses/build/tools/deps/% : \
-	$(JDK_TOPDIR)/make/tools/src/build/tools/deps/%
-	$(MKDIR) -p $(@D)
-	$(CP) $< $@
+		$(JDK_TOPDIR)/make/tools/src/build/tools/deps/%
+	$(call install-file)
 
 BUILD_TOOLS += $(JDK_OUTPUTDIR)/btclasses/build/tools/deps/refs.allowed
 
--- a/makefiles/profile-includes.txt	Thu Apr 11 21:03:24 2013 -0700
+++ b/makefiles/profile-includes.txt	Fri Apr 12 10:42:50 2013 -0700
@@ -66,6 +66,7 @@
     ext/sunec.jar \
     ext/sunjce_provider.jar \
     ext/sunpkcs11.jar \
+    hijrah-config-umalqura.properties \
     jce.jar \
     jsse.jar \
     logging.properties \
@@ -80,7 +81,7 @@
     security/java.security \
     security/local_policy.jar \
     security/trusted.libraries \
-    tzdb.jar
+    tzdb.dat
 
 PROFILE_1_JRE_OTHER_FILES := \
     COPYRIGHT \
@@ -100,9 +101,7 @@
     resources.jar \
     rt.jar \
     security/US_export_policy.jar \
-    security/local_policy.jar \
-    tzdb.jar
-
+    security/local_policy.jar
 
 PROFILE_2_JRE_BIN_FILES := \
     rmid$(EXE_SUFFIX) \
--- a/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Fri Apr 12 10:42:50 2013 -0700
@@ -184,7 +184,7 @@
         for (int i=0; i<markerInterfaces.length; i++) {
             interfaces[i+1] = markerInterfaces[i].getName().replace('.', '/');
         }
-        cw.visit(CLASSFILE_VERSION, ACC_SUPER,
+        cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL,
                  lambdaClassName, null,
                  NAME_MAGIC_ACCESSOR_IMPL, interfaces);
 
--- a/src/share/classes/java/time/DayOfWeek.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/DayOfWeek.java	Fri Apr 12 10:42:50 2013 -0700
@@ -61,13 +61,13 @@
  */
 package java.time;
 
+import java.time.temporal.UnsupportedTemporalTypeException;
 import static java.time.temporal.ChronoField.DAY_OF_WEEK;
 import static java.time.temporal.ChronoUnit.DAYS;
 
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.TextStyle;
 import java.time.temporal.ChronoField;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -259,7 +259,7 @@
      * <p>
      * If the field is {@link ChronoField#DAY_OF_WEEK DAY_OF_WEEK} then the
      * range of the day-of-week, from 1 to 7, will be returned.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -269,6 +269,7 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override
     public ValueRange range(TemporalField field) {
@@ -288,7 +289,7 @@
      * <p>
      * If the field is {@link ChronoField#DAY_OF_WEEK DAY_OF_WEEK} then the
      * value of the day-of-week, from 1 to 7, will be returned.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -297,7 +298,10 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field, within the valid range of values
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -317,7 +321,7 @@
      * <p>
      * If the field is {@link ChronoField#DAY_OF_WEEK DAY_OF_WEEK} then the
      * value of the day-of-week, from 1 to 7, will be returned.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -327,6 +331,7 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -334,7 +339,7 @@
         if (field == DAY_OF_WEEK) {
             return getValue();
         } else if (field instanceof ChronoField) {
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.getFrom(this);
     }
@@ -393,7 +398,7 @@
     @SuppressWarnings("unchecked")
     @Override
     public <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.precision()) {
+        if (query == TemporalQuery.precision()) {
             return (R) DAYS;
         }
         return TemporalAccessor.super.query(query);
@@ -409,8 +414,8 @@
      * passing {@link ChronoField#DAY_OF_WEEK} as the field.
      * Note that this adjusts forwards or backwards within a Monday to Sunday week.
      * See {@link WeekFields#dayOfWeek} for localized week start days.
-     * See {@link java.time.temporal.Adjusters Adjusters} for other adjusters
-     * with more control, such as {@code next(MONDAY)}.
+     * See {@code TemporalAdjuster} for other adjusters with more control,
+     * such as {@code next(MONDAY)}.
      * <p>
      * In most cases, it is clearer to reverse the calling pattern by using
      * {@link Temporal#with(TemporalAdjuster)}:
--- a/src/share/classes/java/time/Duration.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/Duration.java	Fri Apr 12 10:42:50 2013 -0700
@@ -85,6 +85,7 @@
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAmount;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -302,31 +303,32 @@
 
     //-----------------------------------------------------------------------
     /**
-     * Obtains a {@code Duration} representing the duration between two instants.
+     * Obtains an instance of {@code Duration} from a temporal amount.
      * <p>
-     * This calculates the duration between two temporal objects of the same type.
-     * The difference in seconds is calculated using
-     * {@link Temporal#periodUntil(Temporal, TemporalUnit)}.
-     * The difference in nanoseconds is calculated using by querying the
-     * {@link ChronoField#NANO_OF_SECOND NANO_OF_SECOND} field.
+     * This obtains a duration based on the specified amount.
+     * A {@code TemporalAmount} represents an  amount of time, which may be
+     * date-based or time-based, which this factory extracts to a duration.
      * <p>
-     * The result of this method can be a negative period if the end is before the start.
-     * To guarantee to obtain a positive duration call {@link #abs()} on the result.
+     * The conversion loops around the set of units from the amount and uses
+     * the {@linkplain TemporalUnit#getDuration() duration} of the unit to
+     * calculate the total {@code Duration}.
+     * Only a subset of units are accepted by this method. The unit must either
+     * have an {@linkplain TemporalUnit#isDurationEstimated() exact duration}
+     * or be {@link ChronoUnit#DAYS} which is treated as 24 hours.
+     * If any other units are found then an exception is thrown.
      *
-     * @param startInclusive  the start instant, inclusive, not null
-     * @param endExclusive  the end instant, exclusive, not null
-     * @return a {@code Duration}, not null
-     * @throws ArithmeticException if the calculation exceeds the capacity of {@code Duration}
+     * @param amount  the temporal amount to convert, not null
+     * @return the equivalent duration, not null
+     * @throws DateTimeException if unable to convert to a {@code Duration}
+     * @throws ArithmeticException if numeric overflow occurs
      */
-    public static  Duration between(Temporal startInclusive, Temporal endExclusive) {
-        long secs = startInclusive.periodUntil(endExclusive, SECONDS);
-        long nanos;
-        try {
-            nanos = endExclusive.getLong(NANO_OF_SECOND) - startInclusive.getLong(NANO_OF_SECOND);
-        } catch (DateTimeException ex) {
-            nanos = 0;
+    public static Duration from(TemporalAmount amount) {
+        Objects.requireNonNull(amount, "amount");
+        Duration duration = ZERO;
+        for (TemporalUnit unit : amount.getUnits()) {
+            duration = duration.plus(amount.get(unit), unit);
         }
-        return ofSeconds(secs, nanos);
+        return duration;
     }
 
     //-----------------------------------------------------------------------
@@ -360,14 +362,14 @@
      * <p>
      * Examples:
      * <pre>
-     *    "PT20.345S" -> parses as "20.345 seconds"
-     *    "PT15M"     -> parses as "15 minutes" (where a minute is 60 seconds)
-     *    "PT10H"     -> parses as "10 hours" (where an hour is 3600 seconds)
-     *    "P2D"       -> parses as "2 days" (where a day is 24 hours or 86400 seconds)
-     *    "P2DT3H4M"  -> parses as "2 days, 3 hours and 4 minutes"
-     *    "P-6H3M"    -> parses as "-6 hours and +3 minutes"
-     *    "-P6H3M"    -> parses as "-6 hours and -3 minutes"
-     *    "-P-6H+3M"  -> parses as "+6 hours and -3 minutes"
+     *    "PT20.345S" -- parses as "20.345 seconds"
+     *    "PT15M"     -- parses as "15 minutes" (where a minute is 60 seconds)
+     *    "PT10H"     -- parses as "10 hours" (where an hour is 3600 seconds)
+     *    "P2D"       -- parses as "2 days" (where a day is 24 hours or 86400 seconds)
+     *    "P2DT3H4M"  -- parses as "2 days, 3 hours and 4 minutes"
+     *    "P-6H3M"    -- parses as "-6 hours and +3 minutes"
+     *    "-P6H3M"    -- parses as "-6 hours and -3 minutes"
+     *    "-P-6H+3M"  -- parses as "+6 hours and -3 minutes"
      * </pre>
      *
      * @param text  the text to parse, not null
@@ -439,6 +441,44 @@
 
     //-----------------------------------------------------------------------
     /**
+     * Obtains a {@code Duration} representing the duration between two instants.
+     * <p>
+     * This calculates the duration between two temporal objects of the same type.
+     * The specified temporal objects must support the {@link ChronoUnit#SECONDS SECONDS} unit.
+     * For full accuracy, either the {@link ChronoUnit#NANOS NANOS} unit or the
+     * {@link ChronoField#NANO_OF_SECOND NANO_OF_SECOND} field should be supported.
+     * <p>
+     * The result of this method can be a negative period if the end is before the start.
+     * To guarantee to obtain a positive duration call {@link #abs()} on the result.
+     *
+     * @param startInclusive  the start instant, inclusive, not null
+     * @param endExclusive  the end instant, exclusive, not null
+     * @return a {@code Duration}, not null
+     * @throws DateTimeException if the seconds between the temporals cannot be obtained
+     * @throws ArithmeticException if the calculation exceeds the capacity of {@code Duration}
+     */
+    public static Duration between(Temporal startInclusive, Temporal endExclusive) {
+        try {
+            return ofNanos(startInclusive.periodUntil(endExclusive, NANOS));
+        } catch (DateTimeException | ArithmeticException ex) {
+            long secs = startInclusive.periodUntil(endExclusive, SECONDS);
+            long nanos;
+            try {
+                nanos = endExclusive.getLong(NANO_OF_SECOND) - startInclusive.getLong(NANO_OF_SECOND);
+                if (secs > 0 && nanos < 0) {
+                    secs++;
+                } else if (secs < 0 && nanos > 0) {
+                    secs--;
+                }
+            } catch (DateTimeException ex2) {
+                nanos = 0;
+            }
+            return ofSeconds(secs, nanos);
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    /**
      * Obtains an instance of {@code Duration} using seconds and nanoseconds.
      *
      * @param seconds  the length of the duration in seconds, positive or negative
@@ -474,6 +514,7 @@
      * @param unit the {@code TemporalUnit} for which to return the value
      * @return the long value of the unit
      * @throws DateTimeException if the unit is not supported
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      */
     @Override
     public long get(TemporalUnit unit) {
@@ -482,7 +523,7 @@
         } else if (unit == NANOS) {
             return nanos;
         } else {
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
     }
 
@@ -637,6 +678,7 @@
      * @param amountToAdd  the amount of the period, measured in terms of the unit, positive or negative
      * @param unit  the unit that the period is measured in, must have an exact duration, not null
      * @return a {@code Duration} based on this duration with the specified duration added, not null
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     public Duration plus(long amountToAdd, TemporalUnit unit) {
@@ -645,7 +687,7 @@
             return plus(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY), 0);
         }
         if (unit.isDurationEstimated()) {
-            throw new DateTimeException("Unit must not have an estimated duration");
+            throw new UnsupportedTemporalTypeException("Unit must not have an estimated duration");
         }
         if (amountToAdd == 0) {
             return this;
@@ -1130,9 +1172,9 @@
      * @throws ArithmeticException if numeric overflow occurs
      */
     public long toNanos() {
-        long millis = Math.multiplyExact(seconds, NANOS_PER_SECOND);
-        millis = Math.addExact(millis, nanos);
-        return millis;
+        long totalNanos = Math.multiplyExact(seconds, NANOS_PER_SECOND);
+        totalNanos = Math.addExact(totalNanos, nanos);
+        return totalNanos;
     }
 
     //-----------------------------------------------------------------------
@@ -1199,10 +1241,10 @@
      * <p>
      * Examples:
      * <pre>
-     *    "20.345 seconds"                 -> "PT20.345S
-     *    "15 minutes" (15 * 60 seconds)   -> "PT15M"
-     *    "10 hours" (10 * 3600 seconds)   -> "PT10H"
-     *    "2 days" (2 * 86400 seconds)     -> "PT48H"
+     *    "20.345 seconds"                 -- "PT20.345S
+     *    "15 minutes" (15 * 60 seconds)   -- "PT15M"
+     *    "10 hours" (10 * 3600 seconds)   -- "PT10H"
+     *    "2 days" (2 * 86400 seconds)     -- "PT48H"
      * </pre>
      * Note that multiples of 24 hours are not output as days to avoid confusion
      * with {@code Period}.
--- a/src/share/classes/java/time/Instant.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/Instant.java	Fri Apr 12 10:42:50 2013 -0700
@@ -81,7 +81,6 @@
 import java.time.format.DateTimeParseException;
 import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -89,6 +88,7 @@
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.util.Objects;
 
@@ -148,6 +148,8 @@
  * <li>other times during the day will be broadly in line with the agreed international civil time</li>
  * <li>the day will be divided into exactly 86400 subdivisions, referred to as "seconds"</li>
  * <li>the Java "second" may differ from an SI second</li>
+ * <li>a well-defined algorithm must be specified to map each second in the accurate agreed
+ *  international civil time to each "second" in this time-scale</li>
  * </ul><p>
  * Agreed international civil time is the base time-scale agreed by international convention,
  * which in 2012 is UTC (with leap-seconds).
@@ -155,6 +157,14 @@
  * In 2012, the definition of the Java time-scale is the same as UTC for all days except
  * those where a leap-second occurs. On days where a leap-second does occur, the time-scale
  * effectively eliminates the leap-second, maintaining the fiction of 86400 seconds in the day.
+ * The approved well-defined algorithm to eliminate leap-seconds is specified as
+ * <a href="http://www.cl.cam.ac.uk/~mgk25/time/utc-sls/">UTC-SLS</a>.
+ * <p>
+ * UTC-SLS is a simple algorithm that smoothes the leap-second over the last 1000 seconds of
+ * the day, making each of the last 1000 seconds 1/1000th longer or shorter than an SI second.
+ * Implementations built on an accurate leap-second aware time source should use UTC-SLS.
+ * Use of a different algorithm risks confusion and misinterpretation of instants around a
+ * leap-second and is discouraged.
  * <p>
  * The main benefit of always dividing the day into 86400 subdivisions is that it matches the
  * expectations of most users of the API. The alternative is to force every user to understand
@@ -163,16 +173,10 @@
  * Most applications also do not have a problem with a second being a very small amount longer or
  * shorter than a real SI second during a leap-second.
  * <p>
- * If an application does have access to an accurate clock that reports leap-seconds, then the
- * recommended technique to implement the Java time-scale is to use the UTC-SLS convention.
- * <a href="http://www.cl.cam.ac.uk/~mgk25/time/utc-sls/">UTC-SLS</a> effectively smoothes the
- * leap-second over the last 1000 seconds of the day, making each of the last 1000 "seconds"
- * 1/1000th longer or shorter than a real SI second.
- * <p>
  * One final problem is the definition of the agreed international civil time before the
  * introduction of modern UTC in 1972. This includes the Java epoch of {@code 1970-01-01}.
  * It is intended that instants before 1972 be interpreted based on the solar day divided
- * into 86400 subdivisions.
+ * into 86400 subdivisions, as per the principles of UT1.
  * <p>
  * The Java time-scale is used for all date-time classes.
  * This includes {@code Instant}, {@code LocalDate}, {@code LocalTime}, {@code OffsetDateTime},
@@ -210,7 +214,7 @@
      */
     public static final Instant MIN = Instant.ofEpochSecond(MIN_SECOND, 0);
     /**
-     * The minimum supported {@code Instant}, '-1000000000-01-01T00:00Z'.
+     * The maximum supported {@code Instant}, '1000000000-12-31T23:59:59.999999999Z'.
      * This could be used by an application as a "far future" instant.
      * <p>
      * This is one year later than the maximum {@code LocalDateTime}.
@@ -292,9 +296,9 @@
      * to ensure that the stored nanosecond is in the range 0 to 999,999,999.
      * For example, the following will result in the exactly the same instant:
      * <pre>
-     *  Instant.ofSeconds(3, 1);
-     *  Instant.ofSeconds(4, -999_999_999);
-     *  Instant.ofSeconds(2, 1000_000_001);
+     *  Instant.ofEpochSecond(3, 1);
+     *  Instant.ofEpochSecond(4, -999_999_999);
+     *  Instant.ofEpochSecond(2, 1000_000_001);
      * </pre>
      *
      * @param epochSecond  the number of seconds from 1970-01-01T00:00:00Z
@@ -441,7 +445,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return
      * appropriate range instances.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -451,6 +455,7 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override  // override for Javadoc
     public ValueRange range(TemporalField field) {
@@ -469,7 +474,7 @@
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time, except {@code INSTANT_SECONDS} which is too
      * large to fit in an {@code int} and throws a {@code DateTimeException}.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -478,7 +483,10 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override  // override for Javadoc and performance
@@ -490,7 +498,7 @@
                 case MILLI_OF_SECOND: return nanos / 1000_000;
                 case INSTANT_SECONDS: INSTANT_SECONDS.checkValidIntValue(seconds);
             }
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return range(field).checkValidIntValue(field.getFrom(this), field);
     }
@@ -505,7 +513,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -515,6 +523,7 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -526,7 +535,7 @@
                 case MILLI_OF_SECOND: return nanos / 1000_000;
                 case INSTANT_SECONDS: return seconds;
             }
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.getFrom(this);
     }
@@ -610,7 +619,7 @@
      * In all cases, if the new value is outside the valid range of values for the field
      * then a {@code DateTimeException} will be thrown.
      * <p>
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
@@ -623,6 +632,7 @@
      * @param newValue  the new value of the field in the result
      * @return an {@code Instant} based on {@code this} with the specified field set, not null
      * @throws DateTimeException if the field cannot be set
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -642,7 +652,7 @@
                 case NANO_OF_SECOND: return (newValue != nanos ? create(seconds, (int) newValue) : this);
                 case INSTANT_SECONDS: return (newValue != seconds ? create(newValue, nanos) : this);
             }
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.adjustInto(this, newValue);
     }
@@ -668,6 +678,7 @@
      * @param unit  the unit to truncate to, not null
      * @return an {@code Instant} based on this instant with the time truncated, not null
      * @throws DateTimeException if the unit is invalid for truncation
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      */
     public Instant truncatedTo(TemporalUnit unit) {
         if (unit == ChronoUnit.NANOS) {
@@ -675,11 +686,11 @@
         }
         Duration unitDur = unit.getDuration();
         if (unitDur.getSeconds() > LocalTime.SECONDS_PER_DAY) {
-            throw new DateTimeException("Unit is too large to be used for truncation");
+            throw new UnsupportedTemporalTypeException("Unit is too large to be used for truncation");
         }
         long dur = unitDur.toNanos();
         if ((LocalTime.NANOS_PER_DAY % dur) != 0) {
-            throw new DateTimeException("Unit must divide into a standard day without remainder");
+            throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder");
         }
         long nod = (seconds % LocalTime.SECONDS_PER_DAY) * LocalTime.NANOS_PER_SECOND + nanos;
         long result = (nod / dur) * dur;
@@ -754,7 +765,7 @@
      *  multiplied by 86,400 (24 hours).
      * </ul>
      * <p>
-     * All other {@code ChronoUnit} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoUnit} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoUnit}, then the result of this method
      * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
@@ -767,6 +778,7 @@
      * @param unit  the unit of the amount to add, not null
      * @return an {@code Instant} based on this instant with the specified amount added, not null
      * @throws DateTimeException if the addition cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -782,7 +794,7 @@
                 case HALF_DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY / 2));
                 case DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY));
             }
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return unit.addTo(this, amountToAdd);
     }
@@ -894,6 +906,7 @@
      * @param unit  the unit of the amount to subtract, not null
      * @return an {@code Instant} based on this instant with the specified amount subtracted, not null
      * @throws DateTimeException if the subtraction cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -975,11 +988,12 @@
     @SuppressWarnings("unchecked")
     @Override
     public <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.precision()) {
+        if (query == TemporalQuery.precision()) {
             return (R) NANOS;
         }
         // inline TemporalAccessor.super.query(query) as an optimization
-        if (query == Queries.chronology() || query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
+        if (query == TemporalQuery.chronology() || query == TemporalQuery.zoneId() ||
+                query == TemporalQuery.zone() || query == TemporalQuery.offset()) {
             return null;
         }
         return query.queryFrom(this);
@@ -1028,14 +1042,15 @@
      * For example, the period in days between two dates can be calculated
      * using {@code startInstant.periodUntil(endInstant, SECONDS)}.
      * <p>
-     * This method operates in association with {@link TemporalUnit#between}.
-     * The result of this method is a {@code long} representing the amount of
-     * the specified unit. By contrast, the result of {@code between} is an
-     * object that can be used directly in addition/subtraction:
+     * There are two equivalent ways of using this method.
+     * The first is to invoke this method.
+     * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
      * <pre>
-     *   long period = start.periodUntil(end, SECONDS);   // this method
-     *   dateTime.plus(SECONDS.between(start, end));      // use in plus/minus
+     *   // these two lines are equivalent
+     *   amount = start.periodUntil(end, SECONDS);
+     *   amount = SECONDS.between(start, end);
      * </pre>
+     * The choice should be made based on which makes the code more readable.
      * <p>
      * The calculation is implemented in this method for {@link ChronoUnit}.
      * The units {@code NANOS}, {@code MICROS}, {@code MILLIS}, {@code SECONDS},
@@ -1053,6 +1068,7 @@
      * @param unit  the unit to measure the period in, not null
      * @return the amount of the period between this date and the end date
      * @throws DateTimeException if the period cannot be calculated
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1074,18 +1090,26 @@
                 case HALF_DAYS: return secondsUntil(end) / (12 * SECONDS_PER_HOUR);
                 case DAYS: return secondsUntil(end) / (SECONDS_PER_DAY);
             }
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return unit.between(this, endInstant);
     }
 
     private long nanosUntil(Instant end) {
-        long secs = Math.multiplyExact(secondsUntil(end), NANOS_PER_SECOND);
-        return Math.addExact(secs, end.nanos - nanos);
+        long secsDiff = Math.subtractExact(end.seconds, seconds);
+        long totalNanos = Math.multiplyExact(secsDiff, NANOS_PER_SECOND);
+        return Math.addExact(totalNanos, end.nanos - nanos);
     }
 
     private long secondsUntil(Instant end) {
-        return Math.subtractExact(end.seconds, seconds);
+        long secsDiff = Math.subtractExact(end.seconds, seconds);
+        long nanosDiff = end.nanos - nanos;
+        if (secsDiff > 0 && nanosDiff < 0) {
+            secsDiff--;
+        } else if (secsDiff < 0 && nanosDiff > 0) {
+            secsDiff++;
+        }
+        return secsDiff;
     }
 
     //-----------------------------------------------------------------------
--- a/src/share/classes/java/time/LocalDate.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/LocalDate.java	Fri Apr 12 10:42:50 2013 -0700
@@ -69,9 +69,9 @@
 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
 import static java.time.temporal.ChronoField.DAY_OF_YEAR;
 import static java.time.temporal.ChronoField.EPOCH_DAY;
-import static java.time.temporal.ChronoField.EPOCH_MONTH;
 import static java.time.temporal.ChronoField.ERA;
 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
+import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
 import static java.time.temporal.ChronoField.YEAR;
 
 import java.io.DataInput;
@@ -87,7 +87,6 @@
 import java.time.format.DateTimeParseException;
 import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -95,6 +94,7 @@
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.time.zone.ZoneOffsetTransition;
 import java.time.zone.ZoneRules;
@@ -238,7 +238,7 @@
         YEAR.checkValidValue(year);
         Objects.requireNonNull(month, "month");
         DAY_OF_MONTH.checkValidValue(dayOfMonth);
-        return create(year, month, dayOfMonth);
+        return create(year, month.getValue(), dayOfMonth);
     }
 
     /**
@@ -258,7 +258,7 @@
         YEAR.checkValidValue(year);
         MONTH_OF_YEAR.checkValidValue(month);
         DAY_OF_MONTH.checkValidValue(dayOfMonth);
-        return create(year, Month.of(month), dayOfMonth);
+        return create(year, month, dayOfMonth);
     }
 
     //-----------------------------------------------------------------------
@@ -287,7 +287,7 @@
             moy = moy.plus(1);
         }
         int dom = dayOfYear - moy.firstDayOfYear(leap) + 1;
-        return create(year, moy, dom);
+        return new LocalDate(year, moy.getValue(), dom);
     }
 
     //-----------------------------------------------------------------------
@@ -342,7 +342,7 @@
      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
      * which this factory converts to an instance of {@code LocalDate}.
      * <p>
-     * The conversion uses the {@link Queries#localDate()} query, which relies
+     * The conversion uses the {@link TemporalQuery#localDate()} query, which relies
      * on extracting the {@link ChronoField#EPOCH_DAY EPOCH_DAY} field.
      * <p>
      * This method matches the signature of the functional interface {@link TemporalQuery}
@@ -353,7 +353,7 @@
      * @throws DateTimeException if unable to convert to a {@code LocalDate}
      */
     public static LocalDate from(TemporalAccessor temporal) {
-        LocalDate date = temporal.query(Queries.localDate());
+        LocalDate date = temporal.query(TemporalQuery.localDate());
         if (date == null) {
             throw new DateTimeException("Unable to obtain LocalDate from TemporalAccessor: " + temporal.getClass());
         }
@@ -395,20 +395,34 @@
      * Creates a local date from the year, month and day fields.
      *
      * @param year  the year to represent, validated from MIN_YEAR to MAX_YEAR
-     * @param month  the month-of-year to represent, validated not null
+     * @param month  the month-of-year to represent, from 1 to 12, validated
      * @param dayOfMonth  the day-of-month to represent, validated from 1 to 31
      * @return the local date, not null
      * @throws DateTimeException if the day-of-month is invalid for the month-year
      */
-    private static LocalDate create(int year, Month month, int dayOfMonth) {
-        if (dayOfMonth > 28 && dayOfMonth > month.length(IsoChronology.INSTANCE.isLeapYear(year))) {
-            if (dayOfMonth == 29) {
-                throw new DateTimeException("Invalid date 'February 29' as '" + year + "' is not a leap year");
-            } else {
-                throw new DateTimeException("Invalid date '" + month.name() + " " + dayOfMonth + "'");
+    private static LocalDate create(int year, int month, int dayOfMonth) {
+        if (dayOfMonth > 28) {
+            int dom = 31;
+            switch (month) {
+                case 2:
+                    dom = (IsoChronology.INSTANCE.isLeapYear(year) ? 29 : 28);
+                    break;
+                case 4:
+                case 6:
+                case 9:
+                case 11:
+                    dom = 30;
+                    break;
+            }
+            if (dayOfMonth > dom) {
+                if (dayOfMonth == 29) {
+                    throw new DateTimeException("Invalid date 'February 29' as '" + year + "' is not a leap year");
+                } else {
+                    throw new DateTimeException("Invalid date '" + Month.of(month).name() + " " + dayOfMonth + "'");
+                }
             }
         }
-        return new LocalDate(year, month.getValue(), dayOfMonth);
+        return new LocalDate(year, month, dayOfMonth);
     }
 
     /**
@@ -431,7 +445,7 @@
                 day = Math.min(day, 30);
                 break;
         }
-        return LocalDate.of(year, month, day);
+        return new LocalDate(year, month, day);
     }
 
     /**
@@ -467,7 +481,7 @@
      * <li>{@code ALIGNED_WEEK_OF_MONTH}
      * <li>{@code ALIGNED_WEEK_OF_YEAR}
      * <li>{@code MONTH_OF_YEAR}
-     * <li>{@code EPOCH_MONTH}
+     * <li>{@code PROLEPTIC_MONTH}
      * <li>{@code YEAR_OF_ERA}
      * <li>{@code YEAR}
      * <li>{@code ERA}
@@ -498,7 +512,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return
      * appropriate range instances.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -508,12 +522,13 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override
     public ValueRange range(TemporalField field) {
         if (field instanceof ChronoField) {
             ChronoField f = (ChronoField) field;
-            if (f.isDateField()) {
+            if (f.isDateBased()) {
                 switch (f) {
                     case DAY_OF_MONTH: return ValueRange.of(1, lengthOfMonth());
                     case DAY_OF_YEAR: return ValueRange.of(1, lengthOfYear());
@@ -523,7 +538,7 @@
                 }
                 return field.range();
             }
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.rangeRefinedBy(this);
     }
@@ -538,9 +553,9 @@
      * <p>
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
-     * values based on this date, except {@code EPOCH_DAY} and {@code EPOCH_MONTH}
+     * values based on this date, except {@code EPOCH_DAY} and {@code PROLEPTIC_MONTH}
      * which are too large to fit in an {@code int} and throw a {@code DateTimeException}.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -549,7 +564,10 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override  // override for Javadoc and performance
@@ -570,7 +588,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -580,6 +598,7 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -588,8 +607,8 @@
             if (field == EPOCH_DAY) {
                 return toEpochDay();
             }
-            if (field == EPOCH_MONTH) {
-                return getEpochMonth();
+            if (field == PROLEPTIC_MONTH) {
+                return getProlepticMonth();
             }
             return get0(field);
         }
@@ -603,20 +622,20 @@
             case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1;
             case DAY_OF_MONTH: return day;
             case DAY_OF_YEAR: return getDayOfYear();
-            case EPOCH_DAY: throw new DateTimeException("Field too large for an int: " + field);
+            case EPOCH_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'EpochDay' for get() method, use getLong() instead");
             case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1;
             case ALIGNED_WEEK_OF_YEAR: return ((getDayOfYear() - 1) / 7) + 1;
             case MONTH_OF_YEAR: return month;
-            case EPOCH_MONTH: throw new DateTimeException("Field too large for an int: " + field);
+            case PROLEPTIC_MONTH: throw new UnsupportedTemporalTypeException("Invalid field 'ProlepticMonth' for get() method, use getLong() instead");
             case YEAR_OF_ERA: return (year >= 1 ? year : 1 - year);
             case YEAR: return year;
             case ERA: return (year >= 1 ? 1 : 0);
         }
-        throw new DateTimeException("Unsupported field: " + field.getName());
+        throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
     }
 
-    private long getEpochMonth() {
-        return ((year - 1970) * 12L) + (month - 1);
+    private long getProlepticMonth() {
+        return (year * 12L + month - 1);
     }
 
     //-----------------------------------------------------------------------
@@ -626,7 +645,7 @@
      * The {@code Chronology} represents the calendar system in use.
      * The ISO-8601 calendar system is the modern civil calendar system used today
      * in most of the world. It is equivalent to the proleptic Gregorian calendar
-     * system, in which todays's rules for leap years are applied for all time.
+     * system, in which today's rules for leap years are applied for all time.
      *
      * @return the ISO chronology, not null
      */
@@ -810,7 +829,7 @@
      * <p>
      * A simple adjuster might simply set the one of the fields, such as the year field.
      * A more complex adjuster might set the date to the last day of the month.
-     * A selection of common adjustments is provided in {@link java.time.temporal.Adjusters}.
+     * A selection of common adjustments is provided in {@link TemporalAdjuster}.
      * These include finding the "last day of the month" and "next Wednesday".
      * Key date-time classes also implement the {@code TemporalAdjuster} interface,
      * such as {@link Month} and {@link java.time.MonthDay MonthDay}.
@@ -908,8 +927,8 @@
      *  The year will be unchanged. The day-of-month will also be unchanged,
      *  unless it would be invalid for the new month and year. In that case, the
      *  day-of-month is adjusted to the maximum valid value for the new month and year.
-     * <li>{@code EPOCH_MONTH} -
-     *  Returns a {@code LocalDate} with the specified epoch-month.
+     * <li>{@code PROLEPTIC_MONTH} -
+     *  Returns a {@code LocalDate} with the specified proleptic-month.
      *  The day-of-month will be unchanged, unless it would be invalid for the new month
      *  and year. In that case, the day-of-month is adjusted to the maximum valid value
      *  for the new month and year.
@@ -933,7 +952,7 @@
      * In all cases, if the new value is outside the valid range of values for the field
      * then a {@code DateTimeException} will be thrown.
      * <p>
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
@@ -946,6 +965,7 @@
      * @param newValue  the new value of the field in the result
      * @return a {@code LocalDate} based on {@code this} with the specified field set, not null
      * @throws DateTimeException if the field cannot be set
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -963,12 +983,12 @@
                 case ALIGNED_WEEK_OF_MONTH: return plusWeeks(newValue - getLong(ALIGNED_WEEK_OF_MONTH));
                 case ALIGNED_WEEK_OF_YEAR: return plusWeeks(newValue - getLong(ALIGNED_WEEK_OF_YEAR));
                 case MONTH_OF_YEAR: return withMonth((int) newValue);
-                case EPOCH_MONTH: return plusMonths(newValue - getLong(EPOCH_MONTH));
+                case PROLEPTIC_MONTH: return plusMonths(newValue - getProlepticMonth());
                 case YEAR_OF_ERA: return withYear((int) (year >= 1 ? newValue : 1 - newValue));
                 case YEAR: return withYear((int) newValue);
                 case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year));
             }
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.adjustInto(this, newValue);
     }
@@ -1137,7 +1157,7 @@
      *  valid value for the new month and year.
      * </ul>
      * <p>
-     * All other {@code ChronoUnit} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoUnit} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoUnit}, then the result of this method
      * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
@@ -1150,6 +1170,7 @@
      * @param unit  the unit of the amount to add, not null
      * @return a {@code LocalDate} based on this date with the specified amount added, not null
      * @throws DateTimeException if the addition cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1166,7 +1187,7 @@
                 case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000));
                 case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd));
             }
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return unit.addTo(this, amountToAdd);
     }
@@ -1315,6 +1336,7 @@
      * @param unit  the unit of the amount to subtract, not null
      * @return a {@code LocalDate} based on this date with the specified amount subtracted, not null
      * @throws DateTimeException if the subtraction cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1431,7 +1453,7 @@
     @SuppressWarnings("unchecked")
     @Override
     public <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.localDate()) {
+        if (query == TemporalQuery.localDate()) {
             return (R) this;
         }
         return ChronoLocalDate.super.query(query);
@@ -1508,10 +1530,12 @@
      * @param unit  the unit to measure the period in, not null
      * @return the amount of the period between this date and the end date
      * @throws DateTimeException if the period cannot be calculated
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
     public long periodUntil(Temporal endDate, TemporalUnit unit) {
+        Objects.requireNonNull(unit, "unit");
         if (endDate instanceof LocalDate == false) {
             Objects.requireNonNull(endDate, "endDate");
             throw new DateTimeException("Unable to calculate period between objects of two different types");
@@ -1528,7 +1552,7 @@
                 case MILLENNIA: return monthsUntil(end) / 12000;
                 case ERAS: return end.getLong(ERA) - getLong(ERA);
             }
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return unit.between(this, endDate);
     }
@@ -1538,8 +1562,8 @@
     }
 
     private long monthsUntil(LocalDate end) {
-        long packed1 = getEpochMonth() * 32L + getDayOfMonth();  // no overflow
-        long packed2 = end.getEpochMonth() * 32L + end.getDayOfMonth();  // no overflow
+        long packed1 = getProlepticMonth() * 32L + getDayOfMonth();  // no overflow
+        long packed2 = end.getProlepticMonth() * 32L + end.getDayOfMonth();  // no overflow
         return (packed2 - packed1) / 32;
     }
 
@@ -1549,6 +1573,7 @@
      * This calculates the period between two dates in terms of years, months and days.
      * The start and end points are {@code this} and the specified date.
      * The result will be negative if the end is before the start.
+     * The negative sign will be the same in each of year, month and day.
      * <p>
      * The calculation is performed using the ISO calendar system.
      * If necessary, the input date will be converted to ISO.
@@ -1561,9 +1586,6 @@
      * than or equal to the start day-of-month.
      * For example, from {@code 2010-01-15} to {@code 2011-03-18} is "1 year, 2 months and 3 days".
      * <p>
-     * The result of this method can be a negative period if the end is before the start.
-     * The negative sign will be the same in each of year, month and day.
-     * <p>
      * There are two equivalent ways of using this method.
      * The first is to invoke this method.
      * The second is to use {@link Period#between(LocalDate, LocalDate)}:
@@ -1580,7 +1602,7 @@
     @Override
     public Period periodUntil(ChronoLocalDate<?> endDate) {
         LocalDate end = LocalDate.from(endDate);
-        long totalMonths = end.getEpochMonth() - this.getEpochMonth();  // safe
+        long totalMonths = end.getProlepticMonth() - this.getProlepticMonth();  // safe
         int days = end.day - this.day;
         if (totalMonths > 0 && days < 0) {
             totalMonths--;
@@ -1595,6 +1617,21 @@
         return Period.of(Math.toIntExact(years), months, days);
     }
 
+    /**
+     * Formats this date using the specified formatter.
+     * <p>
+     * This date will be passed to the formatter to produce a string.
+     *
+     * @param formatter  the formatter to use, not null
+     * @return the formatted date string, not null
+     * @throws DateTimeException if an error occurs during printing
+     */
+    @Override  // override for Javadoc and performance
+    public String format(DateTimeFormatter formatter) {
+        Objects.requireNonNull(formatter, "formatter");
+        return formatter.format(this);
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Combines this date with a time to create a {@code LocalDateTime}.
@@ -1800,7 +1837,7 @@
      * This method only considers the position of the two dates on the local time-line.
      * It does not take into account the chronology, or calendar system.
      * This is different from the comparison in {@link #compareTo(ChronoLocalDate)},
-     * but is the same approach as {@link #DATE_COMPARATOR}.
+     * but is the same approach as {@link ChronoLocalDate#timeLineOrder()}.
      *
      * @param other  the other date to compare to, not null
      * @return true if this date is after the specified date
@@ -1829,7 +1866,7 @@
      * This method only considers the position of the two dates on the local time-line.
      * It does not take into account the chronology, or calendar system.
      * This is different from the comparison in {@link #compareTo(ChronoLocalDate)},
-     * but is the same approach as {@link #DATE_COMPARATOR}.
+     * but is the same approach as {@link ChronoLocalDate#timeLineOrder()}.
      *
      * @param other  the other date to compare to, not null
      * @return true if this date is before the specified date
@@ -1858,7 +1895,7 @@
      * This method only considers the position of the two dates on the local time-line.
      * It does not take into account the chronology, or calendar system.
      * This is different from the comparison in {@link #compareTo(ChronoLocalDate)}
-     * but is the same approach as {@link #DATE_COMPARATOR}.
+     * but is the same approach as {@link ChronoLocalDate#timeLineOrder()}.
      *
      * @param other  the other date to compare to, not null
      * @return true if this date is equal to the specified date
@@ -1912,7 +1949,7 @@
     /**
      * Outputs this date as a {@code String}, such as {@code 2007-12-03}.
      * <p>
-     * The output will be in the ISO-8601 format {@code yyyy-MM-dd}.
+     * The output will be in the ISO-8601 format {@code uuuu-MM-dd}.
      *
      * @return a string representation of this date, not null
      */
@@ -1942,21 +1979,6 @@
             .toString();
     }
 
-    /**
-     * Outputs this date as a {@code String} using the formatter.
-     * <p>
-     * This date will be passed to the formatter
-     * {@link DateTimeFormatter#format(TemporalAccessor) format method}.
-     *
-     * @param formatter  the formatter to use, not null
-     * @return the formatted date string, not null
-     * @throws DateTimeException if an error occurs during printing
-     */
-    @Override  // override for Javadoc
-    public String toString(DateTimeFormatter formatter) {
-        return ChronoLocalDate.super.toString(formatter);
-    }
-
     //-----------------------------------------------------------------------
     /**
      * Writes the object using a
--- a/src/share/classes/java/time/LocalDateTime.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/LocalDateTime.java	Fri Apr 12 10:42:50 2013 -0700
@@ -79,12 +79,10 @@
 import java.io.ObjectStreamException;
 import java.io.Serializable;
 import java.time.chrono.ChronoLocalDateTime;
-import java.time.chrono.IsoChronology;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -92,6 +90,7 @@
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.time.zone.ZoneRules;
 import java.util.Objects;
@@ -546,7 +545,7 @@
      * <li>{@code ALIGNED_WEEK_OF_MONTH}
      * <li>{@code ALIGNED_WEEK_OF_YEAR}
      * <li>{@code MONTH_OF_YEAR}
-     * <li>{@code EPOCH_MONTH}
+     * <li>{@code PROLEPTIC_MONTH}
      * <li>{@code YEAR_OF_ERA}
      * <li>{@code YEAR}
      * <li>{@code ERA}
@@ -565,7 +564,7 @@
     public boolean isSupported(TemporalField field) {
         if (field instanceof ChronoField) {
             ChronoField f = (ChronoField) field;
-            return f.isDateField() || f.isTimeField();
+            return f.isDateBased() || f.isTimeBased();
         }
         return field != null && field.isSupportedBy(this);
     }
@@ -581,7 +580,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return
      * appropriate range instances.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -591,12 +590,13 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override
     public ValueRange range(TemporalField field) {
         if (field instanceof ChronoField) {
             ChronoField f = (ChronoField) field;
-            return (f.isTimeField() ? time.range(field) : date.range(field));
+            return (f.isTimeBased() ? time.range(field) : date.range(field));
         }
         return field.rangeRefinedBy(this);
     }
@@ -612,9 +612,9 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time, except {@code NANO_OF_DAY}, {@code MICRO_OF_DAY},
-     * {@code EPOCH_DAY} and {@code EPOCH_MONTH} which are too large to fit in
+     * {@code EPOCH_DAY} and {@code PROLEPTIC_MONTH} which are too large to fit in
      * an {@code int} and throw a {@code DateTimeException}.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -623,14 +623,17 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
     public int get(TemporalField field) {
         if (field instanceof ChronoField) {
             ChronoField f = (ChronoField) field;
-            return (f.isTimeField() ? time.get(field) : date.get(field));
+            return (f.isTimeBased() ? time.get(field) : date.get(field));
         }
         return ChronoLocalDateTime.super.get(field);
     }
@@ -645,7 +648,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -655,13 +658,14 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
     public long getLong(TemporalField field) {
         if (field instanceof ChronoField) {
             ChronoField f = (ChronoField) field;
-            return (f.isTimeField() ? time.getLong(field) : date.getLong(field));
+            return (f.isTimeBased() ? time.getLong(field) : date.getLong(field));
         }
         return field.getFrom(this);
     }
@@ -822,7 +826,7 @@
      * <p>
      * A simple adjuster might simply set the one of the fields, such as the year field.
      * A more complex adjuster might set the date to the last day of the month.
-     * A selection of common adjustments is provided in {@link java.time.temporal.Adjusters}.
+     * A selection of common adjustments is provided in {@link TemporalAdjuster}.
      * These include finding the "last day of the month" and "next Wednesday".
      * Key date-time classes also implement the {@code TemporalAdjuster} interface,
      * such as {@link Month} and {@link java.time.MonthDay MonthDay}.
@@ -886,7 +890,7 @@
      * The {@link #isSupported(TemporalField) supported fields} will behave as per
      * the matching method on {@link LocalDate#with(TemporalField, long) LocalDate}
      * or {@link LocalTime#with(TemporalField, long) LocalTime}.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
@@ -899,13 +903,14 @@
      * @param newValue  the new value of the field in the result
      * @return a {@code LocalDateTime} based on {@code this} with the specified field set, not null
      * @throws DateTimeException if the field cannot be set
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
     public LocalDateTime with(TemporalField field, long newValue) {
         if (field instanceof ChronoField) {
             ChronoField f = (ChronoField) field;
-            if (f.isTimeField()) {
+            if (f.isTimeBased()) {
                 return with(date, time.with(field, newValue));
             } else {
                 return with(date.with(field, newValue), time);
@@ -1052,6 +1057,7 @@
      * @param unit  the unit to truncate to, not null
      * @return a {@code LocalDateTime} based on this date-time with the time truncated, not null
      * @throws DateTimeException if unable to truncate
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     public LocalDateTime truncatedTo(TemporalUnit unit) {
         return with(date, time.truncatedTo(unit));
@@ -1106,6 +1112,7 @@
      * @param unit  the unit of the amount to add, not null
      * @return a {@code LocalDateTime} based on this date-time with the specified amount added, not null
      * @throws DateTimeException if the addition cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1312,6 +1319,7 @@
      * @param unit  the unit of the amount to subtract, not null
      * @return a {@code LocalDateTime} based on this date-time with the specified amount subtracted, not null
      * @throws DateTimeException if the subtraction cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1517,7 +1525,7 @@
     @SuppressWarnings("unchecked")
     @Override  // override for Javadoc
     public <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.localDate()) {
+        if (query == TemporalQuery.localDate()) {
             return (R) date;
         }
         return ChronoLocalDateTime.super.query(query);
@@ -1597,6 +1605,7 @@
      * @param unit  the unit to measure the period in, not null
      * @return the amount of the period between this date-time and the end date-time
      * @throws DateTimeException if the period cannot be calculated
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1610,31 +1619,79 @@
             ChronoUnit f = (ChronoUnit) unit;
             if (f.isTimeUnit()) {
                 long amount = date.daysUntil(end.date);
+                if (amount == 0) {
+                    return time.periodUntil(end.time, unit);
+                }
+                long timePart = end.time.toNanoOfDay() - time.toNanoOfDay();
+                if (amount > 0) {
+                    amount--;  // safe
+                    timePart += NANOS_PER_DAY;  // safe
+                } else {
+                    amount++;  // safe
+                    timePart -= NANOS_PER_DAY;  // safe
+                }
                 switch (f) {
-                    case NANOS: amount = Math.multiplyExact(amount, NANOS_PER_DAY); break;
-                    case MICROS: amount = Math.multiplyExact(amount, MICROS_PER_DAY); break;
-                    case MILLIS: amount = Math.multiplyExact(amount, MILLIS_PER_DAY); break;
-                    case SECONDS: amount = Math.multiplyExact(amount, SECONDS_PER_DAY); break;
-                    case MINUTES: amount = Math.multiplyExact(amount, MINUTES_PER_DAY); break;
-                    case HOURS: amount = Math.multiplyExact(amount, HOURS_PER_DAY); break;
-                    case HALF_DAYS: amount = Math.multiplyExact(amount, 2); break;
+                    case NANOS:
+                        amount = Math.multiplyExact(amount, NANOS_PER_DAY);
+                        break;
+                    case MICROS:
+                        amount = Math.multiplyExact(amount, MICROS_PER_DAY);
+                        timePart = timePart / 1000;
+                        break;
+                    case MILLIS:
+                        amount = Math.multiplyExact(amount, MILLIS_PER_DAY);
+                        timePart = timePart / 1_000_000;
+                        break;
+                    case SECONDS:
+                        amount = Math.multiplyExact(amount, SECONDS_PER_DAY);
+                        timePart = timePart / NANOS_PER_SECOND;
+                        break;
+                    case MINUTES:
+                        amount = Math.multiplyExact(amount, MINUTES_PER_DAY);
+                        timePart = timePart / NANOS_PER_MINUTE;
+                        break;
+                    case HOURS:
+                        amount = Math.multiplyExact(amount, HOURS_PER_DAY);
+                        timePart = timePart / NANOS_PER_HOUR;
+                        break;
+                    case HALF_DAYS:
+                        amount = Math.multiplyExact(amount, 2);
+                        timePart = timePart / (NANOS_PER_HOUR * 12);
+                        break;
                 }
-                return Math.addExact(amount, time.periodUntil(end.time, unit));
+                return Math.addExact(amount, timePart);
             }
             LocalDate endDate = end.date;
-            if (end.time.isBefore(time)) {
+            if (endDate.isAfter(date) && end.time.isBefore(time)) {
                 endDate = endDate.minusDays(1);
+            } else if (endDate.isBefore(date) && end.time.isAfter(time)) {
+                endDate = endDate.plusDays(1);
             }
             return date.periodUntil(endDate, unit);
         }
         return unit.between(this, endDateTime);
     }
 
+    /**
+     * Formats this date-time using the specified formatter.
+     * <p>
+     * This date-time will be passed to the formatter to produce a string.
+     *
+     * @param formatter  the formatter to use, not null
+     * @return the formatted date-time string, not null
+     * @throws DateTimeException if an error occurs during printing
+     */
+    @Override  // override for Javadoc and performance
+    public String format(DateTimeFormatter formatter) {
+        Objects.requireNonNull(formatter, "formatter");
+        return formatter.format(this);
+    }
+
     //-----------------------------------------------------------------------
     /**
-     * Combines this time with a date to create an {@code OffsetTime}.
+     * Combines this date-time with an offset to create an {@code OffsetDateTime}.
      * <p>
-     * This returns an {@code OffsetTime} formed from this time at the specified offset.
+     * This returns an {@code OffsetDateTime} formed from this date-time at the specified offset.
      * All possible combinations of date-time and offset are valid.
      *
      * @param offset  the offset to combine with, not null
@@ -1645,7 +1702,7 @@
     }
 
     /**
-     * Combines this time with a time-zone to create a {@code ZonedDateTime}.
+     * Combines this date-time with a time-zone to create a {@code ZonedDateTime}.
      * <p>
      * This returns a {@code ZonedDateTime} formed from this date-time at the
      * specified time-zone. The result will match this date-time as closely as possible.
@@ -1725,7 +1782,7 @@
      * This method only considers the position of the two date-times on the local time-line.
      * It does not take into account the chronology, or calendar system.
      * This is different from the comparison in {@link #compareTo(ChronoLocalDateTime)},
-     * but is the same approach as {@link #DATE_TIME_COMPARATOR}.
+     * but is the same approach as {@link ChronoLocalDateTime#timeLineOrder()}.
      *
      * @param other  the other date-time to compare to, not null
      * @return true if this date-time is after the specified date-time
@@ -1754,7 +1811,7 @@
      * This method only considers the position of the two date-times on the local time-line.
      * It does not take into account the chronology, or calendar system.
      * This is different from the comparison in {@link #compareTo(ChronoLocalDateTime)},
-     * but is the same approach as {@link #DATE_TIME_COMPARATOR}.
+     * but is the same approach as {@link ChronoLocalDateTime#timeLineOrder()}.
      *
      * @param other  the other date-time to compare to, not null
      * @return true if this date-time is before the specified date-time
@@ -1783,7 +1840,7 @@
      * This method only considers the position of the two date-times on the local time-line.
      * It does not take into account the chronology, or calendar system.
      * This is different from the comparison in {@link #compareTo(ChronoLocalDateTime)},
-     * but is the same approach as {@link #DATE_TIME_COMPARATOR}.
+     * but is the same approach as {@link ChronoLocalDateTime#timeLineOrder()}.
      *
      * @param other  the other date-time to compare to, not null
      * @return true if this date-time is equal to the specified date-time
@@ -1834,11 +1891,11 @@
      * <p>
      * The output will be one of the following ISO-8601 formats:
      * <p><ul>
-     * <li>{@code yyyy-MM-dd'T'HH:mm}</li>
-     * <li>{@code yyyy-MM-dd'T'HH:mm:ss}</li>
-     * <li>{@code yyyy-MM-dd'T'HH:mm:ss.SSS}</li>
-     * <li>{@code yyyy-MM-dd'T'HH:mm:ss.SSSSSS}</li>
-     * <li>{@code yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS}</li>
+     * <li>{@code uuuu-MM-dd'T'HH:mm}</li>
+     * <li>{@code uuuu-MM-dd'T'HH:mm:ss}</li>
+     * <li>{@code uuuu-MM-dd'T'HH:mm:ss.SSS}</li>
+     * <li>{@code uuuu-MM-dd'T'HH:mm:ss.SSSSSS}</li>
+     * <li>{@code uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS}</li>
      * </ul><p>
      * The format used will be the shortest that outputs the full value of
      * the time where the omitted parts are implied to be zero.
@@ -1850,21 +1907,6 @@
         return date.toString() + 'T' + time.toString();
     }
 
-    /**
-     * Outputs this date-time as a {@code String} using the formatter.
-     * <p>
-     * This date-time will be passed to the formatter
-     * {@link DateTimeFormatter#format(TemporalAccessor) format method}.
-     *
-     * @param formatter  the formatter to use, not null
-     * @return the formatted date-time string, not null
-     * @throws DateTimeException if an error occurs during printing
-     */
-    @Override  // override for Javadoc
-    public String toString(DateTimeFormatter formatter) {
-        return ChronoLocalDateTime.super.toString(formatter);
-    }
-
     //-----------------------------------------------------------------------
     /**
      * Writes the object using a
--- a/src/share/classes/java/time/LocalTime.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/LocalTime.java	Fri Apr 12 10:42:50 2013 -0700
@@ -80,7 +80,6 @@
 import java.time.format.DateTimeParseException;
 import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -88,6 +87,7 @@
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.util.Objects;
 
@@ -383,7 +383,7 @@
      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
      * which this factory converts to an instance of {@code LocalTime}.
      * <p>
-     * The conversion uses the {@link Queries#localTime()} query, which relies
+     * The conversion uses the {@link TemporalQuery#localTime()} query, which relies
      * on extracting the {@link ChronoField#NANO_OF_DAY NANO_OF_DAY} field.
      * <p>
      * This method matches the signature of the functional interface {@link TemporalQuery}
@@ -394,7 +394,7 @@
      * @throws DateTimeException if unable to convert to a {@code LocalTime}
      */
     public static LocalTime from(TemporalAccessor temporal) {
-        LocalTime time = temporal.query(Queries.localTime());
+        LocalTime time = temporal.query(TemporalQuery.localTime());
         if (time == null) {
             throw new DateTimeException("Unable to obtain LocalTime from TemporalAccessor: " + temporal.getClass());
         }
@@ -505,7 +505,7 @@
     @Override
     public boolean isSupported(TemporalField field) {
         if (field instanceof ChronoField) {
-            return ((ChronoField) field).isTimeField();
+            return field.isTimeBased();
         }
         return field != null && field.isSupportedBy(this);
     }
@@ -521,7 +521,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return
      * appropriate range instances.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -531,6 +531,7 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override  // override for Javadoc
     public ValueRange range(TemporalField field) {
@@ -549,7 +550,7 @@
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this time, except {@code NANO_OF_DAY} and {@code MICRO_OF_DAY}
      * which are too large to fit in an {@code int} and throw a {@code DateTimeException}.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -558,7 +559,10 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override  // override for Javadoc and performance
@@ -579,7 +583,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this time.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -589,6 +593,7 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -608,9 +613,9 @@
     private int get0(TemporalField field) {
         switch ((ChronoField) field) {
             case NANO_OF_SECOND: return nano;
-            case NANO_OF_DAY: throw new DateTimeException("Field too large for an int: " + field);
+            case NANO_OF_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'NanoOfDay' for get() method, use getLong() instead");
             case MICRO_OF_SECOND: return nano / 1000;
-            case MICRO_OF_DAY: throw new DateTimeException("Field too large for an int: " + field);
+            case MICRO_OF_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'MicroOfDay' for get() method, use getLong() instead");
             case MILLI_OF_SECOND: return nano / 1000_000;
             case MILLI_OF_DAY: return (int) (toNanoOfDay() / 1000_000);
             case SECOND_OF_MINUTE: return second;
@@ -623,7 +628,7 @@
             case CLOCK_HOUR_OF_DAY: return (hour == 0 ? 24 : hour);
             case AMPM_OF_DAY: return hour / 12;
         }
-        throw new DateTimeException("Unsupported field: " + field.getName());
+        throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
     }
 
     //-----------------------------------------------------------------------
@@ -760,7 +765,7 @@
      * In all cases, if the new value is outside the valid range of values for the field
      * then a {@code DateTimeException} will be thrown.
      * <p>
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
@@ -773,6 +778,7 @@
      * @param newValue  the new value of the field in the result
      * @return a {@code LocalTime} based on {@code this} with the specified field set, not null
      * @throws DateTimeException if the field cannot be set
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -797,7 +803,7 @@
                 case CLOCK_HOUR_OF_DAY: return withHour((int) (newValue == 24 ? 0 : newValue));
                 case AMPM_OF_DAY: return plusHours((newValue - (hour / 12)) * 12);
             }
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.adjustInto(this, newValue);
     }
@@ -890,6 +896,7 @@
      * @param unit  the unit to truncate to, not null
      * @return a {@code LocalTime} based on this time with the time truncated, not null
      * @throws DateTimeException if unable to truncate
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      */
     public LocalTime truncatedTo(TemporalUnit unit) {
         if (unit == ChronoUnit.NANOS) {
@@ -897,11 +904,11 @@
         }
         Duration unitDur = unit.getDuration();
         if (unitDur.getSeconds() > SECONDS_PER_DAY) {
-            throw new DateTimeException("Unit is too large to be used for truncation");
+            throw new UnsupportedTemporalTypeException("Unit is too large to be used for truncation");
         }
         long dur = unitDur.toNanos();
         if ((NANOS_PER_DAY % dur) != 0) {
-            throw new DateTimeException("Unit must divide into a standard day without remainder");
+            throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder");
         }
         long nod = toNanoOfDay();
         return ofNanoOfDay((nod / dur) * dur);
@@ -972,7 +979,7 @@
      *  This returns {@code this} time.
      * </ul>
      * <p>
-     * All other {@code ChronoUnit} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoUnit} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoUnit}, then the result of this method
      * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
@@ -985,6 +992,7 @@
      * @param unit  the unit of the amount to add, not null
      * @return a {@code LocalTime} based on this time with the specified amount added, not null
      * @throws DateTimeException if the addition cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1001,7 +1009,7 @@
                 case HALF_DAYS: return plusHours((amountToAdd % 2) * 12);
                 case DAYS: return this;
             }
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return unit.addTo(this, amountToAdd);
     }
@@ -1147,6 +1155,7 @@
      * @param unit  the unit of the amount to subtract, not null
      * @return a {@code LocalTime} based on this time with the specified amount subtracted, not null
      * @throws DateTimeException if the subtraction cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1237,13 +1246,14 @@
     @SuppressWarnings("unchecked")
     @Override
     public <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.chronology() || query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
+        if (query == TemporalQuery.chronology() || query == TemporalQuery.zoneId() ||
+                query == TemporalQuery.zone() || query == TemporalQuery.offset()) {
             return null;
-        } else if (query == Queries.localTime()) {
+        } else if (query == TemporalQuery.localTime()) {
             return (R) this;
-        } else if (query == Queries.localDate()) {
+        } else if (query == TemporalQuery.localDate()) {
             return null;
-        } else if (query == Queries.precision()) {
+        } else if (query == TemporalQuery.precision()) {
             return (R) NANOS;
         }
         // inline TemporalAccessor.super.query(query) as an optimization
@@ -1322,6 +1332,7 @@
      * @param unit  the unit to measure the period in, not null
      * @return the amount of the period between this time and the end time
      * @throws DateTimeException if the period cannot be calculated
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1342,11 +1353,25 @@
                 case HOURS: return nanosUntil / NANOS_PER_HOUR;
                 case HALF_DAYS: return nanosUntil / (12 * NANOS_PER_HOUR);
             }
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return unit.between(this, endTime);
     }
 
+    /**
+     * Formats this time using the specified formatter.
+     * <p>
+     * This time will be passed to the formatter to produce a string.
+     *
+     * @param formatter  the formatter to use, not null
+     * @return the formatted time string, not null
+     * @throws DateTimeException if an error occurs during printing
+     */
+    public String format(DateTimeFormatter formatter) {
+        Objects.requireNonNull(formatter, "formatter");
+        return formatter.format(this);
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Combines this time with a date to create a {@code LocalDateTime}.
@@ -1362,7 +1387,7 @@
     }
 
     /**
-     * Combines this time with a date to create an {@code OffsetTime}.
+     * Combines this time with an offset to create an {@code OffsetTime}.
      * <p>
      * This returns an {@code OffsetTime} formed from this time at the specified offset.
      * All possible combinations of time and offset are valid.
@@ -1533,21 +1558,6 @@
         return buf.toString();
     }
 
-    /**
-     * Outputs this time as a {@code String} using the formatter.
-     * <p>
-     * This time will be passed to the formatter
-     * {@link DateTimeFormatter#format(TemporalAccessor) format method}.
-     *
-     * @param formatter  the formatter to use, not null
-     * @return the formatted time string, not null
-     * @throws DateTimeException if an error occurs during printing
-     */
-    public String toString(DateTimeFormatter formatter) {
-        Objects.requireNonNull(formatter, "formatter");
-        return formatter.format(this);
-    }
-
     //-----------------------------------------------------------------------
     /**
      * Writes the object using a
--- a/src/share/classes/java/time/Month.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/Month.java	Fri Apr 12 10:42:50 2013 -0700
@@ -61,6 +61,7 @@
  */
 package java.time;
 
+import java.time.temporal.UnsupportedTemporalTypeException;
 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
 import static java.time.temporal.ChronoUnit.MONTHS;
 
@@ -69,7 +70,6 @@
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.TextStyle;
 import java.time.temporal.ChronoField;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -290,7 +290,7 @@
      * <p>
      * If the field is {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} then the
      * range of the month-of-year, from 1 to 12, will be returned.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -300,6 +300,7 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override
     public ValueRange range(TemporalField field) {
@@ -319,7 +320,7 @@
      * <p>
      * If the field is {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} then the
      * value of the month-of-year, from 1 to 12, will be returned.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -328,7 +329,10 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field, within the valid range of values
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -348,7 +352,7 @@
      * <p>
      * If the field is {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} then the
      * value of the month-of-year, from 1 to 12, will be returned.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -358,6 +362,7 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -365,7 +370,7 @@
         if (field == MONTH_OF_YEAR) {
             return getValue();
         } else if (field instanceof ChronoField) {
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.getFrom(this);
     }
@@ -554,9 +559,9 @@
     @SuppressWarnings("unchecked")
     @Override
     public <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.chronology()) {
+        if (query == TemporalQuery.chronology()) {
             return (R) IsoChronology.INSTANCE;
-        } else if (query == Queries.precision()) {
+        } else if (query == TemporalQuery.precision()) {
             return (R) MONTHS;
         }
         return TemporalAccessor.super.query(query);
--- a/src/share/classes/java/time/MonthDay.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/MonthDay.java	Fri Apr 12 10:42:50 2013 -0700
@@ -76,12 +76,12 @@
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.DateTimeParseException;
 import java.time.temporal.ChronoField;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.util.Objects;
 
@@ -354,7 +354,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return
      * appropriate range instances.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -364,6 +364,7 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override
     public ValueRange range(TemporalField field) {
@@ -386,7 +387,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this month-day.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -395,7 +396,10 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override  // override for Javadoc
@@ -413,7 +417,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this month-day.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -423,6 +427,7 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -433,7 +438,7 @@
                 case DAY_OF_MONTH: return day;
                 case MONTH_OF_YEAR: return month;
             }
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.getFrom(this);
     }
@@ -575,7 +580,7 @@
     @SuppressWarnings("unchecked")
     @Override
     public <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.chronology()) {
+        if (query == TemporalQuery.chronology()) {
             return (R) IsoChronology.INSTANCE;
         }
         return TemporalAccessor.super.query(query);
@@ -617,6 +622,20 @@
         return temporal.with(DAY_OF_MONTH, Math.min(temporal.range(DAY_OF_MONTH).getMaximum(), day));
     }
 
+    /**
+     * Formats this month-day using the specified formatter.
+     * <p>
+     * This month-day will be passed to the formatter to produce a string.
+     *
+     * @param formatter  the formatter to use, not null
+     * @return the formatted month-day string, not null
+     * @throws DateTimeException if an error occurs during printing
+     */
+    public String format(DateTimeFormatter formatter) {
+        Objects.requireNonNull(formatter, "formatter");
+        return formatter.format(this);
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Combines this month-day with a year to create a {@code LocalDate}.
@@ -722,21 +741,6 @@
             .toString();
     }
 
-    /**
-     * Outputs this month-day as a {@code String} using the formatter.
-     * <p>
-     * This month-day will be passed to the formatter
-     * {@link DateTimeFormatter#format(TemporalAccessor) format method}.
-     *
-     * @param formatter  the formatter to use, not null
-     * @return the formatted month-day string, not null
-     * @throws DateTimeException if an error occurs during printing
-     */
-    public String toString(DateTimeFormatter formatter) {
-        Objects.requireNonNull(formatter, "formatter");
-        return formatter.format(this);
-    }
-
     //-----------------------------------------------------------------------
     /**
      * Writes the object using a
--- a/src/share/classes/java/time/OffsetDateTime.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/OffsetDateTime.java	Fri Apr 12 10:42:50 2013 -0700
@@ -78,7 +78,6 @@
 import java.time.format.DateTimeParseException;
 import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -86,6 +85,7 @@
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.time.zone.ZoneRules;
 import java.util.Comparator;
@@ -436,7 +436,7 @@
      * <li>{@code ALIGNED_WEEK_OF_MONTH}
      * <li>{@code ALIGNED_WEEK_OF_YEAR}
      * <li>{@code MONTH_OF_YEAR}
-     * <li>{@code EPOCH_MONTH}
+     * <li>{@code PROLEPTIC_MONTH}
      * <li>{@code YEAR_OF_ERA}
      * <li>{@code YEAR}
      * <li>{@code ERA}
@@ -469,7 +469,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return
      * appropriate range instances.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -479,6 +479,7 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override
     public ValueRange range(TemporalField field) {
@@ -502,9 +503,9 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time, except {@code NANO_OF_DAY}, {@code MICRO_OF_DAY},
-     * {@code EPOCH_DAY}, {@code EPOCH_MONTH} and {@code INSTANT_SECONDS} which are too
+     * {@code EPOCH_DAY}, {@code PROLEPTIC_MONTH} and {@code INSTANT_SECONDS} which are too
      * large to fit in an {@code int} and throw a {@code DateTimeException}.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -513,15 +514,20 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
     public int get(TemporalField field) {
         if (field instanceof ChronoField) {
             switch ((ChronoField) field) {
-                case INSTANT_SECONDS: throw new DateTimeException("Field too large for an int: " + field);
-                case OFFSET_SECONDS: return getOffset().getTotalSeconds();
+                case INSTANT_SECONDS:
+                    throw new UnsupportedTemporalTypeException("Invalid field 'InstantSeconds' for get() method, use getLong() instead");
+                case OFFSET_SECONDS:
+                    return getOffset().getTotalSeconds();
             }
             return dateTime.get(field);
         }
@@ -538,7 +544,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -548,6 +554,7 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -790,7 +797,7 @@
      * <p>
      * A simple adjuster might simply set the one of the fields, such as the year field.
      * A more complex adjuster might set the date to the last day of the month.
-     * A selection of common adjustments is provided in {@link java.time.temporal.Adjusters}.
+     * A selection of common adjustments is provided in {@link TemporalAdjuster}.
      * These include finding the "last day of the month" and "next Wednesday".
      * Key date-time classes also implement the {@code TemporalAdjuster} interface,
      * such as {@link Month} and {@link java.time.MonthDay MonthDay}.
@@ -867,7 +874,7 @@
      * the matching method on {@link LocalDateTime#with(TemporalField, long) LocalDateTime}.
      * In this case, the offset is not part of the calculation and will be unchanged.
      * <p>
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
@@ -880,6 +887,7 @@
      * @param newValue  the new value of the field in the result
      * @return an {@code OffsetDateTime} based on {@code this} with the specified field set, not null
      * @throws DateTimeException if the field cannot be set
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1041,6 +1049,7 @@
      * @param unit  the unit to truncate to, not null
      * @return an {@code OffsetDateTime} based on this date-time with the time truncated, not null
      * @throws DateTimeException if unable to truncate
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      */
     public OffsetDateTime truncatedTo(TemporalUnit unit) {
         return with(dateTime.truncatedTo(unit), offset);
@@ -1094,6 +1103,7 @@
      * @param unit  the unit of the amount to add, not null
      * @return an {@code OffsetDateTime} based on this date-time with the specified amount added, not null
      * @throws DateTimeException if the addition cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1285,6 +1295,7 @@
      * @param unit  the unit of the amount to subtract, not null
      * @return an {@code OffsetDateTime} based on this date-time with the specified amount subtracted, not null
      * @throws DateTimeException if the subtraction cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1453,17 +1464,17 @@
     @SuppressWarnings("unchecked")
     @Override
     public <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.offset() || query == Queries.zone()) {
+        if (query == TemporalQuery.offset() || query == TemporalQuery.zone()) {
             return (R) getOffset();
-        } else if (query == Queries.zoneId()) {
+        } else if (query == TemporalQuery.zoneId()) {
             return null;
-        } else if (query == Queries.localDate()) {
+        } else if (query == TemporalQuery.localDate()) {
             return (R) toLocalDate();
-        } else if (query == Queries.localTime()) {
+        } else if (query == TemporalQuery.localTime()) {
             return (R) toLocalTime();
-        } else if (query == Queries.chronology()) {
+        } else if (query == TemporalQuery.chronology()) {
             return (R) IsoChronology.INSTANCE;
-        } else if (query == Queries.precision()) {
+        } else if (query == TemporalQuery.precision()) {
             return (R) NANOS;
         }
         // inline TemporalAccessor.super.query(query) as an optimization
@@ -1479,8 +1490,8 @@
      * with the offset, date and time changed to be the same as this.
      * <p>
      * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}
-     * three times, passing {@link ChronoField#OFFSET_SECONDS},
-     * {@link ChronoField#EPOCH_DAY} and {@link ChronoField#NANO_OF_DAY} as the fields.
+     * three times, passing {@link ChronoField#EPOCH_DAY},
+     * {@link ChronoField#NANO_OF_DAY} and {@link ChronoField#OFFSET_SECONDS} as the fields.
      * <p>
      * In most cases, it is clearer to reverse the calling pattern by using
      * {@link Temporal#with(TemporalAdjuster)}:
@@ -1499,10 +1510,14 @@
      */
     @Override
     public Temporal adjustInto(Temporal temporal) {
+        // OffsetDateTime is treated as three separate fields, not an instant
+        // this produces the most consistent set of results overall
+        // the offset is set after the date and time, as it is typically a small
+        // tweak to the result, with ZonedDateTime frequently ignoring the offset
         return temporal
-                .with(OFFSET_SECONDS, getOffset().getTotalSeconds())
                 .with(EPOCH_DAY, toLocalDate().toEpochDay())
-                .with(NANO_OF_DAY, toLocalTime().toNanoOfDay());
+                .with(NANO_OF_DAY, toLocalTime().toNanoOfDay())
+                .with(OFFSET_SECONDS, getOffset().getTotalSeconds());
     }
 
     /**
@@ -1552,6 +1567,7 @@
      * @param unit  the unit to measure the period in, not null
      * @return the amount of the period between this date-time and the end date-time
      * @throws DateTimeException if the period cannot be calculated
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1568,6 +1584,20 @@
         return unit.between(this, endDateTime);
     }
 
+    /**
+     * Formats this date-time using the specified formatter.
+     * <p>
+     * This date-time will be passed to the formatter to produce a string.
+     *
+     * @param formatter  the formatter to use, not null
+     * @return the formatted date-time string, not null
+     * @throws DateTimeException if an error occurs during printing
+     */
+    public String format(DateTimeFormatter formatter) {
+        Objects.requireNonNull(formatter, "formatter");
+        return formatter.format(this);
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Combines this date-time with a time-zone to create a {@code ZonedDateTime}
@@ -1796,11 +1826,11 @@
      * <p>
      * The output will be one of the following ISO-8601 formats:
      * <p><ul>
-     * <li>{@code yyyy-MM-dd'T'HH:mmXXXXX}</li>
-     * <li>{@code yyyy-MM-dd'T'HH:mm:ssXXXXX}</li>
-     * <li>{@code yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX}</li>
-     * <li>{@code yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXXXX}</li>
-     * <li>{@code yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSXXXXX}</li>
+     * <li>{@code uuuu-MM-dd'T'HH:mmXXXXX}</li>
+     * <li>{@code uuuu-MM-dd'T'HH:mm:ssXXXXX}</li>
+     * <li>{@code uuuu-MM-dd'T'HH:mm:ss.SSSXXXXX}</li>
+     * <li>{@code uuuu-MM-dd'T'HH:mm:ss.SSSSSSXXXXX}</li>
+     * <li>{@code uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSXXXXX}</li>
      * </ul><p>
      * The format used will be the shortest that outputs the full value of
      * the time where the omitted parts are implied to be zero.
@@ -1812,21 +1842,6 @@
         return dateTime.toString() + offset.toString();
     }
 
-    /**
-     * Outputs this date-time as a {@code String} using the formatter.
-     * <p>
-     * This date-time will be passed to the formatter
-     * {@link DateTimeFormatter#format(TemporalAccessor) format method}.
-     *
-     * @param formatter  the formatter to use, not null
-     * @return the formatted date-time string, not null
-     * @throws DateTimeException if an error occurs during printing
-     */
-    public String toString(DateTimeFormatter formatter) {
-        Objects.requireNonNull(formatter, "formatter");
-        return formatter.format(this);
-    }
-
     //-----------------------------------------------------------------------
     /**
      * Writes the object using a
--- a/src/share/classes/java/time/OffsetTime.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/OffsetTime.java	Fri Apr 12 10:42:50 2013 -0700
@@ -79,7 +79,6 @@
 import java.time.format.DateTimeParseException;
 import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -87,6 +86,7 @@
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.time.zone.ZoneRules;
 import java.util.Objects;
@@ -384,7 +384,7 @@
     @Override
     public boolean isSupported(TemporalField field) {
         if (field instanceof ChronoField) {
-            return ((ChronoField) field).isTimeField() || field == OFFSET_SECONDS;
+            return field.isTimeBased() || field == OFFSET_SECONDS;
         }
         return field != null && field.isSupportedBy(this);
     }
@@ -400,7 +400,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return
      * appropriate range instances.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -410,6 +410,7 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override
     public ValueRange range(TemporalField field) {
@@ -434,7 +435,7 @@
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this time, except {@code NANO_OF_DAY} and {@code MICRO_OF_DAY}
      * which are too large to fit in an {@code int} and throw a {@code DateTimeException}.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -443,7 +444,10 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override  // override for Javadoc
@@ -461,7 +465,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this time.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -471,6 +475,7 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -655,7 +660,7 @@
      * the matching method on {@link LocalTime#with(TemporalField, long)} LocalTime}.
      * In this case, the offset is not part of the calculation and will be unchanged.
      * <p>
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
@@ -668,6 +673,7 @@
      * @param newValue  the new value of the field in the result
      * @return an {@code OffsetTime} based on {@code this} with the specified field set, not null
      * @throws DateTimeException if the field cannot be set
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -764,6 +770,7 @@
      * @param unit  the unit to truncate to, not null
      * @return an {@code OffsetTime} based on this time with the time truncated, not null
      * @throws DateTimeException if unable to truncate
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      */
     public OffsetTime truncatedTo(TemporalUnit unit) {
         return with(time.truncatedTo(unit), offset);
@@ -817,6 +824,7 @@
      * @param unit  the unit of the amount to add, not null
      * @return an {@code OffsetTime} based on this time with the specified amount added, not null
      * @throws DateTimeException if the addition cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -930,6 +938,7 @@
      * @param unit  the unit of the amount to subtract, not null
      * @return an {@code OffsetTime} based on this time with the specified amount subtracted, not null
      * @throws DateTimeException if the subtraction cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1020,13 +1029,13 @@
     @SuppressWarnings("unchecked")
     @Override
     public <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.offset() || query == Queries.zone()) {
+        if (query == TemporalQuery.offset() || query == TemporalQuery.zone()) {
             return (R) offset;
-        } else if (query == Queries.zoneId() | query == Queries.chronology() || query == Queries.localDate()) {
+        } else if (query == TemporalQuery.zoneId() | query == TemporalQuery.chronology() || query == TemporalQuery.localDate()) {
             return null;
-        } else if (query == Queries.localTime()) {
+        } else if (query == TemporalQuery.localTime()) {
             return (R) time;
-        } else if (query == Queries.precision()) {
+        } else if (query == TemporalQuery.precision()) {
             return (R) NANOS;
         }
         // inline TemporalAccessor.super.query(query) as an optimization
@@ -1042,8 +1051,8 @@
      * with the offset and time changed to be the same as this.
      * <p>
      * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}
-     * twice, passing {@link ChronoField#OFFSET_SECONDS} and
-     * {@link ChronoField#NANO_OF_DAY} as the fields.
+     * twice, passing {@link ChronoField#NANO_OF_DAY} and
+     * {@link ChronoField#OFFSET_SECONDS} as the fields.
      * <p>
      * In most cases, it is clearer to reverse the calling pattern by using
      * {@link Temporal#with(TemporalAdjuster)}:
@@ -1063,8 +1072,8 @@
     @Override
     public Temporal adjustInto(Temporal temporal) {
         return temporal
-                .with(OFFSET_SECONDS, offset.getTotalSeconds())
-                .with(NANO_OF_DAY, time.toNanoOfDay());
+                .with(NANO_OF_DAY, time.toNanoOfDay())
+                .with(OFFSET_SECONDS, offset.getTotalSeconds());
     }
 
     /**
@@ -1112,6 +1121,7 @@
      * @param unit  the unit to measure the period in, not null
      * @return the amount of the period between this time and the end time
      * @throws DateTimeException if the period cannot be calculated
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1132,14 +1142,28 @@
                 case HOURS: return nanosUntil / NANOS_PER_HOUR;
                 case HALF_DAYS: return nanosUntil / (12 * NANOS_PER_HOUR);
             }
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return unit.between(this, endTime);
     }
 
+    /**
+     * Formats this time using the specified formatter.
+     * <p>
+     * This time will be passed to the formatter to produce a string.
+     *
+     * @param formatter  the formatter to use, not null
+     * @return the formatted time string, not null
+     * @throws DateTimeException if an error occurs during printing
+     */
+    public String format(DateTimeFormatter formatter) {
+        Objects.requireNonNull(formatter, "formatter");
+        return formatter.format(this);
+    }
+
     //-----------------------------------------------------------------------
     /**
-     * Combines this date with a time to create an {@code OffsetDateTime}.
+     * Combines this time with a date to create an {@code OffsetDateTime}.
      * <p>
      * This returns an {@code OffsetDateTime} formed from this time and the specified date.
      * All possible combinations of date and time are valid.
@@ -1307,27 +1331,12 @@
         return time.toString() + offset.toString();
     }
 
-    /**
-     * Outputs this time as a {@code String} using the formatter.
-     * <p>
-     * This time will be passed to the formatter
-     * {@link DateTimeFormatter#format(TemporalAccessor) format method}.
-     *
-     * @param formatter  the formatter to use, not null
-     * @return the formatted time string, not null
-     * @throws DateTimeException if an error occurs during printing
-     */
-    public String toString(DateTimeFormatter formatter) {
-        Objects.requireNonNull(formatter, "formatter");
-        return formatter.format(this);
-    }
-
-    // -----------------------------------------------------------------------
+    //-----------------------------------------------------------------------
     /**
      * Writes the object using a
      * <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
      * <pre>
-     *  out.writeByte(9);  // identifies this as a OffsetDateTime
+     *  out.writeByte(9);  // identifies this as a OffsetTime
      *  out.writeObject(time);
      *  out.writeObject(offset);
      * </pre>
--- a/src/share/classes/java/time/Period.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/Period.java	Fri Apr 12 10:42:50 2013 -0700
@@ -79,6 +79,7 @@
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAmount;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.util.Arrays;
 import java.util.Collections;
@@ -215,26 +216,40 @@
 
     //-----------------------------------------------------------------------
     /**
-     * Obtains a {@code Period} consisting of the number of years, months,
-     * and days between two dates.
+     * Obtains an instance of {@code Period} from a temporal amount.
      * <p>
-     * The start date is included, but the end date is not.
-     * The period is calculated by removing complete months, then calculating
-     * the remaining number of days, adjusting to ensure that both have the same sign.
-     * The number of months is then split into years and months based on a 12 month year.
-     * A month is considered if the end day-of-month is greater than or equal to the start day-of-month.
-     * For example, from {@code 2010-01-15} to {@code 2011-03-18} is one year, two months and three days.
+     * This obtains a period based on the specified amount.
+     * A {@code TemporalAmount} represents an  amount of time, which may be
+     * date-based or time-based, which this factory extracts to a period.
      * <p>
-     * The result of this method can be a negative period if the end is before the start.
-     * The negative sign will be the same in each of year, month and day.
+     * The conversion loops around the set of units from the amount and uses
+     * the {@link ChronoUnit#YEARS YEARS}, {@link ChronoUnit#MONTHS MONTHS}
+     * and {@link ChronoUnit#DAYS DAYS} units to create a period.
+     * If any other units are found then an exception is thrown.
      *
-     * @param startDate  the start date, inclusive, not null
-     * @param endDate  the end date, exclusive, not null
-     * @return the period between this date and the end date, not null
-     * @see ChronoLocalDate#periodUntil(ChronoLocalDate)
+     * @param amount  the temporal amount to convert, not null
+     * @return the equivalent period, not null
+     * @throws DateTimeException if unable to convert to a {@code Period}
+     * @throws ArithmeticException if the amount of years, months or days exceeds an int
      */
-    public static Period between(LocalDate startDate, LocalDate endDate) {
-        return startDate.periodUntil(endDate);
+    public static Period from(TemporalAmount amount) {
+        Objects.requireNonNull(amount, "amount");
+        int years = 0;
+        int months = 0;
+        int days = 0;
+        for (TemporalUnit unit : amount.getUnits()) {
+            long unitAmount = amount.get(unit);
+            if (unit == ChronoUnit.YEARS) {
+                years = Math.toIntExact(unitAmount);
+            } else if (unit == ChronoUnit.MONTHS) {
+                months = Math.toIntExact(unitAmount);
+            } else if (unit == ChronoUnit.DAYS) {
+                days = Math.toIntExact(unitAmount);
+            } else {
+                throw new DateTimeException("Unit must be Years, Months or Days, but was " + unit);
+            }
+        }
+        return create(years, months, days);
     }
 
     //-----------------------------------------------------------------------
@@ -298,6 +313,30 @@
 
     //-----------------------------------------------------------------------
     /**
+     * Obtains a {@code Period} consisting of the number of years, months,
+     * and days between two dates.
+     * <p>
+     * The start date is included, but the end date is not.
+     * The period is calculated by removing complete months, then calculating
+     * the remaining number of days, adjusting to ensure that both have the same sign.
+     * The number of months is then split into years and months based on a 12 month year.
+     * A month is considered if the end day-of-month is greater than or equal to the start day-of-month.
+     * For example, from {@code 2010-01-15} to {@code 2011-03-18} is one year, two months and three days.
+     * <p>
+     * The result of this method can be a negative period if the end is before the start.
+     * The negative sign will be the same in each of year, month and day.
+     *
+     * @param startDate  the start date, inclusive, not null
+     * @param endDate  the end date, exclusive, not null
+     * @return the period between this date and the end date, not null
+     * @see ChronoLocalDate#periodUntil(ChronoLocalDate)
+     */
+    public static Period between(LocalDate startDate, LocalDate endDate) {
+        return startDate.periodUntil(endDate);
+    }
+
+    //-----------------------------------------------------------------------
+    /**
      * Creates an instance.
      *
      * @param years  the amount
@@ -336,6 +375,7 @@
      * @param unit the {@code TemporalUnit} for which to return the value
      * @return the long value of the unit
      * @throws DateTimeException if the unit is not supported
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      */
     @Override
     public long get(TemporalUnit unit) {
@@ -346,7 +386,7 @@
         } else if (unit == ChronoUnit.DAYS) {
             return getDays();
         } else {
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
     }
 
@@ -499,8 +539,7 @@
     /**
      * Returns a copy of this period with the specified period added.
      * <p>
-     * This operates separately on the years, months, days and the normalized time.
-     * There is no further normalization beyond the normalized time.
+     * This operates separately on the years, months and days.
      * <p>
      * For example, "1 year, 6 months and 3 days" plus "2 years, 2 months and 2 days"
      * returns "3 years, 8 months and 5 days".
@@ -582,8 +621,7 @@
     /**
      * Returns a copy of this period with the specified period subtracted.
      * <p>
-     * This operates separately on the years, months, days and the normalized time.
-     * There is no further normalization beyond the normalized time.
+     * This operates separately on the years, months and days.
      * <p>
      * For example, "1 year, 6 months and 3 days" minus "2 years, 2 months and 2 days"
      * returns "-1 years, 4 months and 1 day".
@@ -845,9 +883,11 @@
      * @return the month range, negative if not fixed range
      */
     private long monthRange(Temporal temporal) {
-        ValueRange startRange = Chronology.from(temporal).range(MONTH_OF_YEAR);
-        if (startRange.isFixed() && startRange.isIntValue()) {
-            return startRange.getMaximum() - startRange.getMinimum() + 1;
+        if (temporal.isSupported(MONTH_OF_YEAR)) {
+            ValueRange startRange = Chronology.from(temporal).range(MONTH_OF_YEAR);
+            if (startRange.isFixed() && startRange.isIntValue()) {
+                return startRange.getMaximum() - startRange.getMinimum() + 1;
+            }
         }
         return -1;
     }
--- a/src/share/classes/java/time/Year.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/Year.java	Fri Apr 12 10:42:50 2013 -0700
@@ -80,7 +80,6 @@
 import java.time.format.SignStyle;
 import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -88,6 +87,7 @@
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.util.Objects;
 
@@ -368,7 +368,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return
      * appropriate range instances.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -378,6 +378,7 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override
     public ValueRange range(TemporalField field) {
@@ -398,7 +399,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this year.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -407,7 +408,10 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override  // override for Javadoc
@@ -425,7 +429,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this year.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -435,6 +439,7 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -445,7 +450,7 @@
                 case YEAR: return year;
                 case ERA: return (year < 1 ? 0 : 1);
             }
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.getFrom(this);
     }
@@ -544,7 +549,7 @@
      * In all cases, if the new value is outside the valid range of values for the field
      * then a {@code DateTimeException} will be thrown.
      * <p>
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
@@ -557,6 +562,7 @@
      * @param newValue  the new value of the field in the result
      * @return a {@code Year} based on {@code this} with the specified field set, not null
      * @throws DateTimeException if the field cannot be set
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -569,7 +575,7 @@
                 case YEAR: return Year.of((int) newValue);
                 case ERA: return (getLong(ERA) == newValue ? this : Year.of(1 - year));
             }
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.adjustInto(this, newValue);
     }
@@ -632,7 +638,7 @@
      *  is unchanged.
      * </ul>
      * <p>
-     * All other {@code ChronoUnit} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoUnit} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoUnit}, then the result of this method
      * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
@@ -645,6 +651,7 @@
      * @param unit  the unit of the amount to add, not null
      * @return a {@code Year} based on this year with the specified amount added, not null
      * @throws DateTimeException if the addition cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -657,7 +664,7 @@
                 case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000));
                 case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd));
             }
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return unit.addTo(this, amountToAdd);
     }
@@ -705,9 +712,9 @@
     }
 
     /**
-     * Returns a copy of this year-month with the specified amount subtracted.
+     * Returns a copy of this year with the specified amount subtracted.
      * <p>
-     * This returns a {@code YearMonth}, based on this one, with the amount
+     * This returns a {@code Year}, based on this one, with the amount
      * in terms of the unit subtracted. If it is not possible to subtract the amount,
      * because the unit is not supported or for some other reason, an exception is thrown.
      * <p>
@@ -718,8 +725,9 @@
      *
      * @param amountToSubtract  the amount of the unit to subtract from the result, may be negative
      * @param unit  the unit of the amount to subtract, not null
-     * @return a {@code YearMonth} based on this year-month with the specified amount subtracted, not null
+     * @return a {@code Year} based on this year with the specified amount subtracted, not null
      * @throws DateTimeException if the subtraction cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -762,9 +770,9 @@
     @SuppressWarnings("unchecked")
     @Override
     public <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.chronology()) {
+        if (query == TemporalQuery.chronology()) {
             return (R) IsoChronology.INSTANCE;
-        } else if (query == Queries.precision()) {
+        } else if (query == TemporalQuery.precision()) {
             return (R) YEARS;
         }
         return Temporal.super.query(query);
@@ -846,6 +854,7 @@
      * @param unit  the unit to measure the period in, not null
      * @return the amount of the period between this year and the end year
      * @throws DateTimeException if the period cannot be calculated
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -864,11 +873,25 @@
                 case MILLENNIA: return yearsUntil / 1000;
                 case ERAS: return end.getLong(ERA) - getLong(ERA);
             }
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return unit.between(this, endYear);
     }
 
+    /**
+     * Formats this year using the specified formatter.
+     * <p>
+     * This year will be passed to the formatter to produce a string.
+     *
+     * @param formatter  the formatter to use, not null
+     * @return the formatted year string, not null
+     * @throws DateTimeException if an error occurs during printing
+     */
+    public String format(DateTimeFormatter formatter) {
+        Objects.requireNonNull(formatter, "formatter");
+        return formatter.format(this);
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Combines this year with a day-of-year to create a {@code LocalDate}.
@@ -1014,21 +1037,6 @@
         return Integer.toString(year);
     }
 
-    /**
-     * Outputs this year as a {@code String} using the formatter.
-     * <p>
-     * This year will be passed to the formatter
-     * {@link DateTimeFormatter#format(TemporalAccessor) format method}.
-     *
-     * @param formatter  the formatter to use, not null
-     * @return the formatted year string, not null
-     * @throws DateTimeException if an error occurs during printing
-     */
-    public String toString(DateTimeFormatter formatter) {
-        Objects.requireNonNull(formatter, "formatter");
-        return formatter.format(this);
-    }
-
     //-----------------------------------------------------------------------
     /**
      * Writes the object using a
--- a/src/share/classes/java/time/YearMonth.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/YearMonth.java	Fri Apr 12 10:42:50 2013 -0700
@@ -61,9 +61,9 @@
  */
 package java.time;
 
-import static java.time.temporal.ChronoField.EPOCH_MONTH;
 import static java.time.temporal.ChronoField.ERA;
 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
+import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
 import static java.time.temporal.ChronoField.YEAR;
 import static java.time.temporal.ChronoField.YEAR_OF_ERA;
 import static java.time.temporal.ChronoUnit.MONTHS;
@@ -82,7 +82,6 @@
 import java.time.format.SignStyle;
 import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -90,6 +89,7 @@
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.util.Objects;
 
@@ -255,7 +255,7 @@
      * Obtains an instance of {@code YearMonth} from a text string such as {@code 2007-12}.
      * <p>
      * The string must represent a valid year-month.
-     * The format must be {@code yyyy-MM}.
+     * The format must be {@code uuuu-MM}.
      * Years outside the range 0000 to 9999 must be prefixed by the plus or minus symbol.
      *
      * @param text  the text to parse such as "2007-12", not null
@@ -320,7 +320,7 @@
      * The supported fields are:
      * <ul>
      * <li>{@code MONTH_OF_YEAR}
-     * <li>{@code EPOCH_MONTH}
+     * <li>{@code PROLEPTIC_MONTH}
      * <li>{@code YEAR_OF_ERA}
      * <li>{@code YEAR}
      * <li>{@code ERA}
@@ -339,7 +339,7 @@
     public boolean isSupported(TemporalField field) {
         if (field instanceof ChronoField) {
             return field == YEAR || field == MONTH_OF_YEAR ||
-                    field == EPOCH_MONTH || field == YEAR_OF_ERA || field == ERA;
+                    field == PROLEPTIC_MONTH || field == YEAR_OF_ERA || field == ERA;
         }
         return field != null && field.isSupportedBy(this);
     }
@@ -355,7 +355,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return
      * appropriate range instances.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -365,6 +365,7 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override
     public ValueRange range(TemporalField field) {
@@ -384,9 +385,9 @@
      * <p>
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
-     * values based on this year-month, except {@code EPOCH_MONTH} which is too
+     * values based on this year-month, except {@code PROLEPTIC_MONTH} which is too
      * large to fit in an {@code int} and throw a {@code DateTimeException}.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -395,7 +396,10 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override  // override for Javadoc
@@ -413,7 +417,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this year-month.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -423,6 +427,7 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -430,18 +435,18 @@
         if (field instanceof ChronoField) {
             switch ((ChronoField) field) {
                 case MONTH_OF_YEAR: return month;
-                case EPOCH_MONTH: return getEpochMonth();
+                case PROLEPTIC_MONTH: return getProlepticMonth();
                 case YEAR_OF_ERA: return (year < 1 ? 1 - year : year);
                 case YEAR: return year;
                 case ERA: return (year < 1 ? 0 : 1);
             }
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.getFrom(this);
     }
 
-    private long getEpochMonth() {
-        return ((year - 1970) * 12L) + (month - 1);
+    private long getProlepticMonth() {
+        return (year * 12L + month - 1);
     }
 
     //-----------------------------------------------------------------------
@@ -589,8 +594,8 @@
      * <li>{@code MONTH_OF_YEAR} -
      *  Returns a {@code YearMonth} with the specified month-of-year.
      *  The year will be unchanged.
-     * <li>{@code EPOCH_MONTH} -
-     *  Returns a {@code YearMonth} with the specified epoch-month.
+     * <li>{@code PROLEPTIC_MONTH} -
+     *  Returns a {@code YearMonth} with the specified proleptic-month.
      *  This completely replaces the year and month of this object.
      * <li>{@code YEAR_OF_ERA} -
      *  Returns a {@code YearMonth} with the specified year-of-era
@@ -606,7 +611,7 @@
      * In all cases, if the new value is outside the valid range of values for the field
      * then a {@code DateTimeException} will be thrown.
      * <p>
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
@@ -619,6 +624,7 @@
      * @param newValue  the new value of the field in the result
      * @return a {@code YearMonth} based on {@code this} with the specified field set, not null
      * @throws DateTimeException if the field cannot be set
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -628,12 +634,12 @@
             f.checkValidValue(newValue);
             switch (f) {
                 case MONTH_OF_YEAR: return withMonth((int) newValue);
-                case EPOCH_MONTH: return plusMonths(newValue - getLong(EPOCH_MONTH));
+                case PROLEPTIC_MONTH: return plusMonths(newValue - getProlepticMonth());
                 case YEAR_OF_ERA: return withYear((int) (year < 1 ? 1 - newValue : newValue));
                 case YEAR: return withYear((int) newValue);
                 case ERA: return (getLong(ERA) == newValue ? this : withYear(1 - year));
             }
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.adjustInto(this, newValue);
     }
@@ -728,7 +734,7 @@
      *  is unchanged.
      * </ul>
      * <p>
-     * All other {@code ChronoUnit} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoUnit} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoUnit}, then the result of this method
      * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
@@ -741,6 +747,7 @@
      * @param unit  the unit of the amount to add, not null
      * @return a {@code YearMonth} based on this year-month with the specified amount added, not null
      * @throws DateTimeException if the addition cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -754,7 +761,7 @@
                 case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000));
                 case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd));
             }
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return unit.addTo(this, amountToAdd);
     }
@@ -838,6 +845,7 @@
      * @param unit  the unit of the amount to subtract, not null
      * @return a {@code YearMonth} based on this year-month with the specified amount subtracted, not null
      * @throws DateTimeException if the subtraction cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -893,9 +901,9 @@
     @SuppressWarnings("unchecked")
     @Override
     public <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.chronology()) {
+        if (query == TemporalQuery.chronology()) {
             return (R) IsoChronology.INSTANCE;
-        } else if (query == Queries.precision()) {
+        } else if (query == TemporalQuery.precision()) {
             return (R) MONTHS;
         }
         return Temporal.super.query(query);
@@ -908,7 +916,7 @@
      * with the year and month changed to be the same as this.
      * <p>
      * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}
-     * passing {@link ChronoField#EPOCH_MONTH} as the field.
+     * passing {@link ChronoField#PROLEPTIC_MONTH} as the field.
      * If the specified temporal object does not use the ISO calendar system then
      * a {@code DateTimeException} is thrown.
      * <p>
@@ -932,7 +940,7 @@
         if (Chronology.from(temporal).equals(IsoChronology.INSTANCE) == false) {
             throw new DateTimeException("Adjustment only supported on ISO date-time");
         }
-        return temporal.with(EPOCH_MONTH, getEpochMonth());
+        return temporal.with(PROLEPTIC_MONTH, getProlepticMonth());
     }
 
     /**
@@ -977,6 +985,7 @@
      * @param unit  the unit to measure the period in, not null
      * @return the amount of the period between this year-month and the end year-month
      * @throws DateTimeException if the period cannot be calculated
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -987,7 +996,7 @@
         }
         YearMonth end = (YearMonth) endYearMonth;
         if (unit instanceof ChronoUnit) {
-            long monthsUntil = end.getEpochMonth() - getEpochMonth();  // no overflow
+            long monthsUntil = end.getProlepticMonth() - getProlepticMonth();  // no overflow
             switch ((ChronoUnit) unit) {
                 case MONTHS: return monthsUntil;
                 case YEARS: return monthsUntil / 12;
@@ -996,11 +1005,25 @@
                 case MILLENNIA: return monthsUntil / 12000;
                 case ERAS: return end.getLong(ERA) - getLong(ERA);
             }
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return unit.between(this, endYearMonth);
     }
 
+    /**
+     * Formats this year-month using the specified formatter.
+     * <p>
+     * This year-month will be passed to the formatter to produce a string.
+     *
+     * @param formatter  the formatter to use, not null
+     * @return the formatted year-month string, not null
+     * @throws DateTimeException if an error occurs during printing
+     */
+    public String format(DateTimeFormatter formatter) {
+        Objects.requireNonNull(formatter, "formatter");
+        return formatter.format(this);
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Combines this year-month with a day-of-month to create a {@code LocalDate}.
@@ -1115,7 +1138,7 @@
     /**
      * Outputs this year-month as a {@code String}, such as {@code 2007-12}.
      * <p>
-     * The output will be in the format {@code yyyy-MM}:
+     * The output will be in the format {@code uuuu-MM}:
      *
      * @return a string representation of this year-month, not null
      */
@@ -1137,21 +1160,6 @@
             .toString();
     }
 
-    /**
-     * Outputs this year-month as a {@code String} using the formatter.
-     * <p>
-     * This year-month will be passed to the formatter
-     * {@link DateTimeFormatter#format(TemporalAccessor) format method}.
-     *
-     * @param formatter  the formatter to use, not null
-     * @return the formatted year-month string, not null
-     * @throws DateTimeException if an error occurs during printing
-     */
-    public String toString(DateTimeFormatter formatter) {
-        Objects.requireNonNull(formatter, "formatter");
-        return formatter.format(this);
-    }
-
     //-----------------------------------------------------------------------
     /**
      * Writes the object using a
--- a/src/share/classes/java/time/ZoneId.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/ZoneId.java	Fri Apr 12 10:42:50 2013 -0700
@@ -66,10 +66,10 @@
 import java.io.Serializable;
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.TextStyle;
-import java.time.temporal.Queries;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.zone.ZoneRules;
 import java.time.zone.ZoneRulesException;
 import java.time.zone.ZoneRulesProvider;
@@ -78,6 +78,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.TimeZone;
 
 /**
@@ -93,6 +94,8 @@
  *  the offset from UTC/Greenwich apply
  * </ul><p>
  * Most fixed offsets are represented by {@link ZoneOffset}.
+ * Calling {@link #normalized()} on any {@code ZoneId} will ensure that a
+ * fixed offset ID will be represented as a {@code ZoneOffset}.
  * <p>
  * The actual rules, describing when and how the offset changes, are defined by {@link ZoneRules}.
  * This class is simply an ID used to obtain the underlying rules.
@@ -103,28 +106,29 @@
  * the ID, whereas serializing the rules sends the entire data set.
  * Similarly, a comparison of two IDs only examines the ID, whereas
  * a comparison of two rules examines the entire data set.
- * <p>
- * The code supports loading a {@code ZoneId} on a JVM which does not have available rules
- * for that ID. This allows the date-time object, such as {@link ZonedDateTime},
- * to still be queried.
  *
  * <h3>Time-zone IDs</h3>
  * The ID is unique within the system.
- * The formats for offset and region IDs differ.
+ * There are three types of ID.
  * <p>
- * An ID is parsed as an offset ID if it starts with 'UTC', 'GMT', 'UT' '+' or '-', or
- * is a single letter. For example, 'Z', '+02:00', '-05:00', 'UTC+05', 'GMT-6' and
- * 'UT+01:00' are all valid offset IDs.
- * Note that some IDs, such as 'D' or '+ABC' meet the criteria to be parsed as offset IDs,
- * but have an invalid offset.
+ * The simplest type of ID is that from {@code ZoneOffset}.
+ * This consists of 'Z' and IDs starting with '+' or '-'.
  * <p>
- * All other IDs are considered to be region IDs.
+ * The next type of ID are offset-style IDs with some form of prefix,
+ * such as 'GMT+2' or 'UTC+01:00'.
+ * The recognised prefixes are 'UTC', 'GMT' and 'UT'.
+ * The offset is the suffix and will be normalized during creation.
+ * These IDs can be normalized to a {@code ZoneOffset} using {@code normalized()}.
  * <p>
- * Region IDs are defined by configuration, which can be thought of as a {@code Map}
- * from region ID to {@code ZoneRules}, see {@link ZoneRulesProvider}.
+ * The third type of ID are region-based IDs. A region-based ID must be of
+ * two or more characters, and not start with 'UTC', 'GMT', 'UT' '+' or '-'.
+ * Region-based IDs are defined by configuration, see {@link ZoneRulesProvider}.
+ * The configuration focuses on providing the lookup from the ID to the
+ * underlying {@code ZoneRules}.
  * <p>
- * Time-zones are defined by governments and change frequently. There are a number of
- * organizations, known here as groups, that monitor time-zone changes and collate them.
+ * Time-zone rules are defined by governments and change frequently.
+ * There are a number of organizations, known here as groups, that monitor
+ * time-zone changes and collate them.
  * The default group is the IANA Time Zone Database (TZDB).
  * Other organizations include IATA (the airline industry body) and Microsoft.
  * <p>
@@ -139,6 +143,20 @@
  * The recommended format for region IDs from groups other than TZDB is 'group~region'.
  * Thus if IATA data were defined, Utrecht airport would be 'IATA~UTC'.
  *
+ * <h3>Serialization</h3>
+ * This class can be serialized and stores the string zone ID in the external form.
+ * The {@code ZoneOffset} subclass uses a dedicated format that only stores the
+ * offset from UTC/Greenwich.
+ * <p>
+ * A {@code ZoneId} can be deserialized in a Java Runtime where the ID is unknown.
+ * For example, if a server-side Java Runtime has been updated with a new zone ID, but
+ * the client-side Java Runtime has not been updated. In this case, the {@code ZoneId}
+ * object will exist, and can be queried using {@code getId}, {@code equals},
+ * {@code hashCode}, {@code toString}, {@code getDisplayName} and {@code normalized}.
+ * However, any call to {@code getRules} will fail with {@code ZoneRulesException}.
+ * This approach is designed to allow a {@link ZonedDateTime} to be loaded and
+ * queried, but not modified, on a Java Runtime with incomplete time-zone information.
+ *
  * <h3>Specification for implementors</h3>
  * This abstract class has two implementations, both of which are immutable and thread-safe.
  * One implementation models region-based IDs, the other is {@code ZoneOffset} modelling
@@ -149,7 +167,15 @@
 public abstract class ZoneId implements Serializable {
 
     /**
-     * A map of zone overrides to enable the older US time-zone names to be used.
+     * A map of zone overrides to enable the older short time-zone names to be used.
+     * <p>
+     * Use of short zone IDs has been deprecated in {@code java.util.TimeZone}.
+     * This map allows the IDs to continue to be used via the
+     * {@link #of(String, Map)} factory method.
+     * <p>
+     * This map contains an older mapping of the IDs, where 'EST', 'MST' and 'HST'
+     * map to IDs which include daylight savings.
+     * This is in line with versions of TZDB before 2005r.
      * <p>
      * This maps as follows:
      * <p><ul>
@@ -184,9 +210,17 @@
      * </ul><p>
      * The map is unmodifiable.
      */
-    public static final Map<String, String> OLD_IDS_PRE_2005;
+    public static final Map<String, String> OLD_SHORT_IDS;
     /**
-     * A map of zone overrides to enable the older US time-zone names to be used.
+     * A map of zone overrides to enable the short time-zone names to be used.
+     * <p>
+     * Use of short zone IDs has been deprecated in {@code java.util.TimeZone}.
+     * This map allows the IDs to continue to be used via the
+     * {@link #of(String, Map)} factory method.
+     * <p>
+     * This map contains a newer mapping of the IDs, where 'EST', 'MST' and 'HST'
+     * map to IDs which do not include daylight savings
+     * This is in line with TZDB 2005r and later.
      * <p>
      * This maps as follows:
      * <p><ul>
@@ -221,7 +255,7 @@
      * </ul><p>
      * The map is unmodifiable.
      */
-    public static final Map<String, String> OLD_IDS_POST_2005;
+    public static final Map<String, String> SHORT_IDS;
     static {
         Map<String, String> base = new HashMap<>();
         base.put("ACT", "Australia/Darwin");
@@ -253,12 +287,12 @@
         pre.put("EST", "America/New_York");
         pre.put("MST", "America/Denver");
         pre.put("HST", "Pacific/Honolulu");
-        OLD_IDS_PRE_2005 = Collections.unmodifiableMap(pre);
+        OLD_SHORT_IDS = Collections.unmodifiableMap(pre);
         Map<String, String> post = new HashMap<>(base);
         post.put("EST", "-05:00");
         post.put("MST", "-07:00");
         post.put("HST", "-10:00");
-        OLD_IDS_POST_2005 = Collections.unmodifiableMap(post);
+        SHORT_IDS = Collections.unmodifiableMap(post);
     }
     /**
      * Serialization version.
@@ -278,7 +312,23 @@
      * @throws ZoneRulesException if the converted zone region ID cannot be found
      */
     public static ZoneId systemDefault() {
-        return ZoneId.of(TimeZone.getDefault().getID(), OLD_IDS_POST_2005);
+        return ZoneId.of(TimeZone.getDefault().getID(), SHORT_IDS);
+    }
+
+    /**
+     * Gets the set of available zone IDs.
+     * <p>
+     * This set includes the string form of all available region-based IDs.
+     * Offset-based zone IDs are not included in the returned set.
+     * The ID can be passed to {@link #of(String)} to create a {@code ZoneId}.
+     * <p>
+     * The set of zone IDs can increase over time, although in a typical application
+     * the set of IDs is fixed. Each call to this method is thread-safe.
+     *
+     * @return a modifiable copy of the set of zone IDs, not null
+     */
+    public static Set<String> getAvailableZoneIds() {
+        return ZoneRulesProvider.getAvailableZoneIds();
     }
 
     //-----------------------------------------------------------------------
@@ -310,31 +360,36 @@
      * Obtains an instance of {@code ZoneId} from an ID ensuring that the
      * ID is valid and available for use.
      * <p>
-     * This method parses the ID, applies any appropriate normalization, and validates it
-     * against the known set of IDs for which rules are available.
+     * This method parses the ID producing a {@code ZoneId} or {@code ZoneOffset}.
+     * A {@code ZoneOffset} is returned if the ID is 'Z', or starts with '+' or '-'.
+     * The result will always be a valid ID for which {@link ZoneRules} can be obtained.
      * <p>
-     * An ID is parsed as though it is an offset ID if it starts with 'UTC', 'GMT', 'UT', '+'
-     * or '-', or if it has less then two letters.
-     * The offset of {@linkplain ZoneOffset#UTC zero} may be represented in multiple ways,
-     * including 'Z', 'UTC', 'GMT', 'UT', 'UTC0', 'GMT0', 'UT0', '+00:00', '-00:00' and 'UTC+00:00'.
-     * <p>
-     * Six forms of ID are recognized:
-     * <p><ul>
-     * <li><code>Z</code> - an offset of zero, which is {@code ZoneOffset.UTC}
-     * <li><code>{offset}</code> - a {@code ZoneOffset} ID, such as '+02:00'
-     * <li><code>{utcPrefix}</code> - a {@code ZoneOffset} ID equal to 'Z'
-     * <li><code>{utcPrefix}0</code> - a {@code ZoneOffset} ID equal to 'Z'
-     * <li><code>{utcPrefix}{offset}</code> - a {@code ZoneOffset} ID equal to '{offset}'
-     * <li><code>{regionID}</code> - full region ID, loaded from configuration
-     * </ul><p>
-     * The {offset} is a valid format for {@link ZoneOffset#of(String)}, excluding 'Z'.
-     * The {utcPrefix} is 'UTC', 'GMT' or 'UT'.
-     * Region IDs must match the regular expression <code>[A-Za-z][A-Za-z0-9~/._+-]+</code>.
-     * <p>
-     * The detailed format of the region ID depends on the group supplying the data.
-     * The default set of data is supplied by the IANA Time Zone Database (TZDB)
-     * This has region IDs of the form '{area}/{city}', such as 'Europe/Paris' or 'America/New_York'.
-     * This is compatible with most IDs from {@link java.util.TimeZone}.
+     * Parsing matches the zone ID step by step as follows.
+     * <ul>
+     * <li>If the zone ID equals 'Z', the result is {@code ZoneOffset.UTC}.
+     * <li>If the zone ID consists of a single letter, the zone ID is invalid
+     *  and {@code DateTimeException} is thrown.
+     * <li>If the zone ID starts with '+' or '-', the ID is parsed as a
+     *  {@code ZoneOffset} using {@link ZoneOffset#of(String)}.
+     * <li>If the zone ID equals 'GMT', 'UTC' or 'UT' then the result is a {@code ZoneId}
+     *  with the same ID and rules equivalent to {@code ZoneOffset.UTC}.
+     * <li>If the zone ID starts with 'UTC+', 'UTC-', 'GMT+', 'GMT-', 'UT+' or 'UT-'
+     *  then the ID is a prefixed offset-based ID. The ID is split in two, with
+     *  a two or three letter prefix and a suffix starting with the sign.
+     *  The suffix is parsed as a {@link ZoneOffset#of(String) ZoneOffset}.
+     *  The result will be a {@code ZoneId} with the specified UTC/GMT/UT prefix
+     *  and the normalized offset ID as per {@link ZoneOffset#getId()}.
+     *  The rules of the returned {@code ZoneId} will be equivalent to the
+     *  parsed {@code ZoneOffset}.
+     * <li>All other IDs are parsed as region-based zone IDs. Region IDs must
+     *  match the regular expression <code>[A-Za-z][A-Za-z0-9~/._+-]+</code>
+     *  otherwise a {@code DateTimeException} is thrown. If the zone ID is not
+     *  in the configured set of IDs, {@code ZoneRulesException} is thrown.
+     *  The detailed format of the region ID depends on the group supplying the data.
+     *  The default set of data is supplied by the IANA Time Zone Database (TZDB).
+     *  This has region IDs of the form '{area}/{city}', such as 'Europe/Paris' or 'America/New_York'.
+     *  This is compatible with most IDs from {@link java.util.TimeZone}.
+     * </ul>
      *
      * @param zoneId  the time-zone ID, not null
      * @return the zone ID, not null
@@ -342,15 +397,29 @@
      * @throws ZoneRulesException if the zone ID is a region ID that cannot be found
      */
     public static ZoneId of(String zoneId) {
+        return of(zoneId, true);
+    }
+
+    /**
+     * Parses the ID, taking a flag to indicate whether {@code ZoneRulesException}
+     * should be thrown or not, used in deserialization.
+     *
+     * @param zoneId  the time-zone ID, not null
+     * @param checkAvailable  whether to check if the zone ID is available
+     * @return the zone ID, not null
+     * @throws DateTimeException if the ID format is invalid
+     * @throws ZoneRulesException if checking availability and the ID cannot be found
+     */
+    static ZoneId of(String zoneId, boolean checkAvailable) {
         Objects.requireNonNull(zoneId, "zoneId");
         if (zoneId.length() <= 1 || zoneId.startsWith("+") || zoneId.startsWith("-")) {
             return ZoneOffset.of(zoneId);
         } else if (zoneId.startsWith("UTC") || zoneId.startsWith("GMT")) {
-            return ofWithPrefix(zoneId, 3);
+            return ofWithPrefix(zoneId, 3, checkAvailable);
         } else if (zoneId.startsWith("UT")) {
-            return ofWithPrefix(zoneId, 2);
+            return ofWithPrefix(zoneId, 2, checkAvailable);
         }
-        return ZoneRegion.ofId(zoneId, true);
+        return ZoneRegion.ofId(zoneId, checkAvailable);
     }
 
     /**
@@ -359,22 +428,25 @@
      * @param zoneId  the time-zone ID, not null
      * @param prefixLength  the length of the prefix, 2 or 3
      * @return the zone ID, not null
-     * @return the zone ID, not null
      * @throws DateTimeException if the zone ID has an invalid format
      */
-    private static ZoneId ofWithPrefix(String zoneId, int prefixLength) {
-        if (zoneId.length() == prefixLength ||
-                (zoneId.length() == prefixLength + 1 && zoneId.charAt(prefixLength) == '0')) {
-            return ZoneOffset.UTC;
+    private static ZoneId ofWithPrefix(String zoneId, int prefixLength, boolean checkAvailable) {
+        String prefix = zoneId.substring(0, prefixLength);
+        if (zoneId.length() == prefixLength) {
+            return ZoneRegion.ofPrefixedOffset(prefix, ZoneOffset.UTC);
         }
-        if (zoneId.charAt(prefixLength) == '+' || zoneId.charAt(prefixLength) == '-') {
-            try {
-                return ZoneOffset.of(zoneId.substring(prefixLength));
-            } catch (DateTimeException ex) {
-                throw new DateTimeException("Invalid ID for offset-based ZoneId: " + zoneId, ex);
+        if (zoneId.charAt(prefixLength) != '+' && zoneId.charAt(prefixLength) != '-') {
+            return ZoneRegion.ofId(zoneId, checkAvailable);  // drop through to ZoneRulesProvider
+        }
+        try {
+            ZoneOffset offset = ZoneOffset.of(zoneId.substring(prefixLength));
+            if (offset == ZoneOffset.UTC) {
+                return ZoneRegion.ofPrefixedOffset(prefix, offset);
             }
+            return ZoneRegion.ofPrefixedOffset(prefix + offset.toString(), offset);
+        } catch (DateTimeException ex) {
+            throw new DateTimeException("Invalid ID for offset-based ZoneId: " + zoneId, ex);
         }
-        throw new DateTimeException("Invalid ID for offset-based ZoneId: " + zoneId);
     }
 
     //-----------------------------------------------------------------------
@@ -389,7 +461,7 @@
      * This factory converts the arbitrary temporal object to an instance of {@code ZoneId}.
      * <p>
      * The conversion will try to obtain the zone in a way that favours region-based
-     * zones over offset-based zones using {@link Queries#zone()}.
+     * zones over offset-based zones using {@link TemporalQuery#zone()}.
      * <p>
      * This method matches the signature of the functional interface {@link TemporalQuery}
      * allowing it to be used in queries via method reference, {@code ZoneId::from}.
@@ -399,7 +471,7 @@
      * @throws DateTimeException if unable to convert to a {@code ZoneId}
      */
     public static ZoneId from(TemporalAccessor temporal) {
-        ZoneId obj = temporal.query(Queries.zone());
+        ZoneId obj = temporal.query(TemporalQuery.zone());
         if (obj == null) {
             throw new DateTimeException("Unable to obtain ZoneId from TemporalAccessor: " + temporal.getClass());
         }
@@ -429,29 +501,6 @@
 
     //-----------------------------------------------------------------------
     /**
-     * Gets the time-zone rules for this ID allowing calculations to be performed.
-     * <p>
-     * The rules provide the functionality associated with a time-zone,
-     * such as finding the offset for a given instant or local date-time.
-     * <p>
-     * A time-zone can be invalid if it is deserialized in a JVM which does not
-     * have the same rules loaded as the JVM that stored it. In this case, calling
-     * this method will throw an exception.
-     * <p>
-     * The rules are supplied by {@link ZoneRulesProvider}. An advanced provider may
-     * support dynamic updates to the rules without restarting the JVM.
-     * If so, then the result of this method may change over time.
-     * Each individual call will be still remain thread-safe.
-     * <p>
-     * {@link ZoneOffset} will always return a set of rules where the offset never changes.
-     *
-     * @return the rules, not null
-     * @throws ZoneRulesException if no rules are available for this ID
-     */
-    public abstract ZoneRules getRules();
-
-    //-----------------------------------------------------------------------
-    /**
      * Gets the textual representation of the zone, such as 'British Time' or
      * '+02:00'.
      * <p>
@@ -466,24 +515,88 @@
      * @return the text value of the zone, not null
      */
     public String getDisplayName(TextStyle style, Locale locale) {
-        return new DateTimeFormatterBuilder().appendZoneText(style).toFormatter(locale).format(new TemporalAccessor() {
+        return new DateTimeFormatterBuilder().appendZoneText(style).toFormatter(locale).format(toTemporal());
+    }
+
+    /**
+     * Converts this zone to a {@code TemporalAccessor}.
+     * <p>
+     * A {@code ZoneId} can be fully represented as a {@code TemporalAccessor}.
+     * However, the interface is not implemented by this class as most of the
+     * methods on the interface have no meaning to {@code ZoneId}.
+     * <p>
+     * The returned temporal has no supported fields, with the query method
+     * supporting the return of the zone using {@link TemporalQuery#zoneId()}.
+     *
+     * @return a temporal equivalent to this zone, not null
+     */
+    private TemporalAccessor toTemporal() {
+        return new TemporalAccessor() {
             @Override
             public boolean isSupported(TemporalField field) {
                 return false;
             }
             @Override
             public long getLong(TemporalField field) {
-                throw new DateTimeException("Unsupported field: " + field);
+                throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
             }
             @SuppressWarnings("unchecked")
             @Override
             public <R> R query(TemporalQuery<R> query) {
-                if (query == Queries.zoneId()) {
+                if (query == TemporalQuery.zoneId()) {
                     return (R) ZoneId.this;
                 }
                 return TemporalAccessor.super.query(query);
             }
-        });
+        };
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the time-zone rules for this ID allowing calculations to be performed.
+     * <p>
+     * The rules provide the functionality associated with a time-zone,
+     * such as finding the offset for a given instant or local date-time.
+     * <p>
+     * A time-zone can be invalid if it is deserialized in a Java Runtime which
+     * does not have the same rules loaded as the Java Runtime that stored it.
+     * In this case, calling this method will throw a {@code ZoneRulesException}.
+     * <p>
+     * The rules are supplied by {@link ZoneRulesProvider}. An advanced provider may
+     * support dynamic updates to the rules without restarting the Java Runtime.
+     * If so, then the result of this method may change over time.
+     * Each individual call will be still remain thread-safe.
+     * <p>
+     * {@link ZoneOffset} will always return a set of rules where the offset never changes.
+     *
+     * @return the rules, not null
+     * @throws ZoneRulesException if no rules are available for this ID
+     */
+    public abstract ZoneRules getRules();
+
+    /**
+     * Normalizes the time-zone ID, returning a {@code ZoneOffset} where possible.
+     * <p>
+     * The returns a normalized {@code ZoneId} that can be used in place of this ID.
+     * The result will have {@code ZoneRules} equivalent to those returned by this object,
+     * however the ID returned by {@code getId()} may be different.
+     * <p>
+     * The normalization checks if the rules of this {@code ZoneId} have a fixed offset.
+     * If they do, then the {@code ZoneOffset} equal to that offset is returned.
+     * Otherwise {@code this} is returned.
+     *
+     * @return the time-zone unique ID, not null
+     */
+    public ZoneId normalized() {
+        try {
+            ZoneRules rules = getRules();
+            if (rules.isFixedOffset()) {
+                return rules.getOffset(Instant.EPOCH);
+            }
+        } catch (ZoneRulesException ex) {
+            // invalid ZoneRegion is not important to this method
+        }
+        return this;
     }
 
     //-----------------------------------------------------------------------
@@ -536,6 +649,10 @@
      *  out.writeByte(7);  // identifies this as a ZoneId (not ZoneOffset)
      *  out.writeUTF(zoneId);
      * </pre>
+     * <p>
+     * When read back in, the {@code ZoneId} will be created as though using
+     * {@link #of(String)}, but without any exception in the case where the
+     * ID has a valid format, but is not in the known set of region-based IDs.
      *
      * @return the instance of {@code Ser}, not null
      */
--- a/src/share/classes/java/time/ZoneOffset.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/ZoneOffset.java	Fri Apr 12 10:42:50 2013 -0700
@@ -61,6 +61,7 @@
  */
 package java.time;
 
+import java.time.temporal.UnsupportedTemporalTypeException;
 import static java.time.LocalTime.MINUTES_PER_HOUR;
 import static java.time.LocalTime.SECONDS_PER_HOUR;
 import static java.time.LocalTime.SECONDS_PER_MINUTE;
@@ -73,7 +74,6 @@
 import java.io.ObjectStreamException;
 import java.io.Serializable;
 import java.time.temporal.ChronoField;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -322,7 +322,7 @@
      * A {@code TemporalAccessor} represents some form of date and time information.
      * This factory converts the arbitrary temporal object to an instance of {@code ZoneOffset}.
      * <p>
-     * The conversion uses the {@link Queries#offset()} query, which relies
+     * The conversion uses the {@link TemporalQuery#offset()} query, which relies
      * on extracting the {@link ChronoField#OFFSET_SECONDS OFFSET_SECONDS} field.
      * <p>
      * This method matches the signature of the functional interface {@link TemporalQuery}
@@ -333,7 +333,7 @@
      * @throws DateTimeException if unable to convert to an {@code ZoneOffset}
      */
     public static ZoneOffset from(TemporalAccessor temporal) {
-        ZoneOffset offset = temporal.query(Queries.offset());
+        ZoneOffset offset = temporal.query(TemporalQuery.offset());
         if (offset == null) {
             throw new DateTimeException("Unable to obtain ZoneOffset from TemporalAccessor: " + temporal.getClass());
         }
@@ -534,7 +534,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return
      * appropriate range instances.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -544,6 +544,7 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override  // override for Javadoc
     public ValueRange range(TemporalField field) {
@@ -560,7 +561,7 @@
      * <p>
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@code OFFSET_SECONDS} field returns the value of the offset.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -569,7 +570,10 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override  // override for Javadoc and performance
@@ -577,7 +581,7 @@
         if (field == OFFSET_SECONDS) {
             return totalSeconds;
         } else if (field instanceof ChronoField) {
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return range(field).checkValidIntValue(getLong(field), field);
     }
@@ -591,7 +595,7 @@
      * <p>
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@code OFFSET_SECONDS} field returns the value of the offset.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -601,6 +605,7 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -608,7 +613,7 @@
         if (field == OFFSET_SECONDS) {
             return totalSeconds;
         } else if (field instanceof ChronoField) {
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.getFrom(this);
     }
@@ -635,7 +640,7 @@
     @SuppressWarnings("unchecked")
     @Override
     public <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.offset() || query == Queries.zone()) {
+        if (query == TemporalQuery.offset() || query == TemporalQuery.zone()) {
             return (R) this;
         }
         return TemporalAccessor.super.query(query);
--- a/src/share/classes/java/time/ZoneRegion.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/ZoneRegion.java	Fri Apr 12 10:42:50 2013 -0700
@@ -95,11 +95,6 @@
      */
     private static final long serialVersionUID = 8386373296231747096L;
     /**
-     * The regex pattern for region IDs.
-     */
-    private static final Pattern PATTERN = Pattern.compile("[A-Za-z][A-Za-z0-9~/._+-]+");
-
-    /**
      * The time-zone ID, not null.
      */
     private final String id;
@@ -109,26 +104,6 @@
     private final transient ZoneRules rules;
 
     /**
-     * Obtains an instance of {@code ZoneRegion} from an identifier without checking
-     * if the time-zone has available rules.
-     * <p>
-     * This method parses the ID and applies any appropriate normalization.
-     * It does not validate the ID against the known set of IDs for which rules are available.
-     * <p>
-     * This method is intended for advanced use cases.
-     * For example, consider a system that always retrieves time-zone rules from a remote server.
-     * Using this factory would allow a {@code ZoneRegion}, and thus a {@code ZonedDateTime},
-     * to be created without loading the rules from the remote server.
-     *
-     * @param zoneId  the time-zone ID, not null
-     * @return the zone ID, not null
-     * @throws DateTimeException if the ID format is invalid
-     */
-    private static ZoneRegion ofLenient(String zoneId) {
-        return ofId(zoneId, false);
-    }
-
-    /**
      * Obtains an instance of {@code ZoneId} from an identifier.
      *
      * @param zoneId  the time-zone ID, not null
@@ -139,12 +114,7 @@
      */
     static ZoneRegion ofId(String zoneId, boolean checkAvailable) {
         Objects.requireNonNull(zoneId, "zoneId");
-        if (zoneId.length() < 2 ||
-                zoneId.startsWith("UT") ||  // includes UTC
-                zoneId.startsWith("GMT") ||
-                (PATTERN.matcher(zoneId).matches() == false)) {
-            throw new DateTimeException("Invalid ID for region-based ZoneId, invalid format: " + zoneId);
-        }
+        checkName(zoneId);
         ZoneRules rules = null;
         try {
             // always attempt load for better behavior after deserialization
@@ -157,6 +127,45 @@
         return new ZoneRegion(zoneId, rules);
     }
 
+    /**
+     * Checks that the given string is a legal ZondId name.
+     *
+     * @param zoneId  the time-zone ID, not null
+     * @throws DateTimeException if the ID format is invalid
+     */
+    private static void checkName(String zoneId) {
+        int n = zoneId.length();
+        if (n < 2) {
+           throw new DateTimeException("Invalid ID for region-based ZoneId, invalid format: " + zoneId);
+        }
+        for (int i = 0; i < n; i++) {
+            char c = zoneId.charAt(i);
+            if (c >= 'a' && c <= 'z') continue;
+            if (c >= 'A' && c <= 'Z') continue;
+            if (c == '/' && i != 0) continue;
+            if (c >= '0' && c <= '9' && i != 0) continue;
+            if (c == '~' && i != 0) continue;
+            if (c == '.' && i != 0) continue;
+            if (c == '_' && i != 0) continue;
+            if (c == '+' && i != 0) continue;
+            if (c == '-' && i != 0) continue;
+            throw new DateTimeException("Invalid ID for region-based ZoneId, invalid format: " + zoneId);
+        }
+    }
+
+    /**
+     * Obtains an instance of {@code ZoneId} wrapping an offset.
+     * <p>
+     * For example, zone IDs like 'UTC', 'GMT', 'UT' and 'UTC+01:30' will be setup here.
+     *
+     * @param zoneId  the time-zone ID, not null
+     * @param offset  the offset, not null
+     * @return the zone ID, not null
+     */
+    static ZoneRegion ofPrefixedOffset(String zoneId, ZoneOffset offset) {
+        return new ZoneRegion(zoneId, offset.getRules());
+    }
+
     //-------------------------------------------------------------------------
     /**
      * Constructor.
@@ -218,7 +227,7 @@
 
     static ZoneId readExternal(DataInput in) throws IOException {
         String id = in.readUTF();
-        return ofLenient(id);
+        return ZoneId.of(id, false);
     }
 
 }
--- a/src/share/classes/java/time/ZonedDateTime.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/ZonedDateTime.java	Fri Apr 12 10:42:50 2013 -0700
@@ -72,7 +72,6 @@
 import java.io.ObjectStreamException;
 import java.io.Serializable;
 import java.time.chrono.ChronoZonedDateTime;
-import java.time.chrono.IsoChronology;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
 import java.time.temporal.ChronoField;
@@ -84,6 +83,7 @@
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.time.zone.ZoneOffsetTransition;
 import java.time.zone.ZoneRules;
@@ -136,6 +136,11 @@
  * used, typically "summer" time.. Two additional methods,
  * {@link #withEarlierOffsetAtOverlap()} and {@link #withLaterOffsetAtOverlap()},
  * help manage the case of an overlap.
+ * <p>
+ * In terms of design, this class should be viewed primarily as the combination
+ * of a {@code LocalDateTime} and a {@code ZoneId}. The {@code ZoneOffset} is
+ * a vital, but secondary, piece of information, used to ensure that the class
+ * represents an instant, especially during a daylight savings overlap.
  *
  * <h3>Specification for implementors</h3>
  * A {@code ZonedDateTime} holds state equivalent to three separate objects,
@@ -420,6 +425,9 @@
         Objects.requireNonNull(localDateTime, "localDateTime");
         Objects.requireNonNull(offset, "offset");
         Objects.requireNonNull(zone, "zone");
+        if (zone.getRules().isValidOffset(localDateTime, offset)) {
+            return new ZonedDateTime(localDateTime, offset, zone);
+        }
         return create(localDateTime.toEpochSecond(offset), localDateTime.getNano(), zone);
     }
 
@@ -615,17 +623,18 @@
     }
 
     /**
-     * Resolves the offset into this zoned date-time.
+     * Resolves the offset into this zoned date-time for the with methods.
      * <p>
-     * This will use the new offset to find the instant, which is then looked up
-     * using the zone ID to find the actual offset to use.
+     * This typically ignores the offset, unless it can be used to switch offset in a DST overlap.
      *
      * @param offset  the offset, not null
      * @return the zoned date-time, not null
      */
     private ZonedDateTime resolveOffset(ZoneOffset offset) {
-        long epSec = dateTime.toEpochSecond(offset);
-        return create(epSec, dateTime.getNano(), zone);
+        if (offset.equals(this.offset) == false && zone.getRules().isValidOffset(dateTime, offset)) {
+            return new ZonedDateTime(dateTime, offset, zone);
+        }
+        return this;
     }
 
     //-----------------------------------------------------------------------
@@ -663,7 +672,7 @@
      * <li>{@code ALIGNED_WEEK_OF_MONTH}
      * <li>{@code ALIGNED_WEEK_OF_YEAR}
      * <li>{@code MONTH_OF_YEAR}
-     * <li>{@code EPOCH_MONTH}
+     * <li>{@code PROLEPTIC_MONTH}
      * <li>{@code YEAR_OF_ERA}
      * <li>{@code YEAR}
      * <li>{@code ERA}
@@ -696,7 +705,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return
      * appropriate range instances.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
@@ -706,6 +715,7 @@
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      */
     @Override
     public ValueRange range(TemporalField field) {
@@ -729,9 +739,9 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time, except {@code NANO_OF_DAY}, {@code MICRO_OF_DAY},
-     * {@code EPOCH_DAY}, {@code EPOCH_MONTH} and {@code INSTANT_SECONDS} which are too
+     * {@code EPOCH_DAY}, {@code PROLEPTIC_MONTH} and {@code INSTANT_SECONDS} which are too
      * large to fit in an {@code int} and throw a {@code DateTimeException}.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -740,15 +750,20 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override  // override for Javadoc and performance
     public int get(TemporalField field) {
         if (field instanceof ChronoField) {
             switch ((ChronoField) field) {
-                case INSTANT_SECONDS: throw new DateTimeException("Field too large for an int: " + field);
-                case OFFSET_SECONDS: return getOffset().getTotalSeconds();
+                case INSTANT_SECONDS:
+                    throw new UnsupportedTemporalTypeException("Invalid field 'InstantSeconds' for get() method, use getLong() instead");
+                case OFFSET_SECONDS:
+                    return getOffset().getTotalSeconds();
             }
             return dateTime.get(field);
         }
@@ -765,7 +780,7 @@
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@link #isSupported(TemporalField) supported fields} will return valid
      * values based on this date-time.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -775,6 +790,7 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1115,7 +1131,7 @@
      * <p>
      * A simple adjuster might simply set the one of the fields, such as the year field.
      * A more complex adjuster might set the date to the last day of the month.
-     * A selection of common adjustments is provided in {@link java.time.temporal.Adjusters}.
+     * A selection of common adjustments is provided in {@link TemporalAdjuster}.
      * These include finding the "last day of the month" and "next Wednesday".
      * Key date-time classes also implement the {@code TemporalAdjuster} interface,
      * such as {@link Month} and {@link java.time.MonthDay MonthDay}.
@@ -1137,15 +1153,12 @@
      *  result = zonedDateTime.with(time);
      * </pre>
      * <p>
-     * {@link ZoneOffset} also implements {@code TemporalAdjuster} however it is less likely
-     * that setting the offset will have the effect you expect. When an offset is passed in,
-     * the local date-time is combined with the new offset to form an {@code Instant}.
-     * The instant and original zone are then used to create the result.
-     * This algorithm means that it is quite likely that the output has a different offset
-     * to the specified offset. It will however work correctly when passing in the offset
-     * applicable for the instant of the zoned date-time, and will work correctly if passing
-     * one of the two valid offsets during a daylight savings overlap when the same local time
-     * occurs twice.
+     * {@link ZoneOffset} also implements {@code TemporalAdjuster} however using it
+     * as an argument typically has no effect. The offset of a {@code ZonedDateTime} is
+     * controlled primarily by the time-zone. As such, changing the offset does not generally
+     * make sense, because there is only one valid offset for the local date-time and zone.
+     * If the zoned date-time is in a daylight savings overlap, then the offset is used
+     * to switch between the two valid offsets. In all other cases, the offset is ignored.
      * <p>
      * The result of this method is obtained by invoking the
      * {@link TemporalAdjuster#adjustInto(Temporal)} method on the
@@ -1167,6 +1180,9 @@
             return resolveLocal(LocalDateTime.of(dateTime.toLocalDate(), (LocalTime) adjuster));
         } else if (adjuster instanceof LocalDateTime) {
             return resolveLocal((LocalDateTime) adjuster);
+        } else if (adjuster instanceof OffsetDateTime) {
+            OffsetDateTime odt = (OffsetDateTime) adjuster;
+            return ofLocal(odt.toLocalDateTime(), zone, odt.getOffset());
         } else if (adjuster instanceof Instant) {
             Instant instant = (Instant) adjuster;
             return create(instant.getEpochSecond(), instant.getNano(), zone);
@@ -1197,15 +1213,13 @@
      * The result will have an offset derived from the new instant and original zone.
      * If the new instant value is outside the valid range then a {@code DateTimeException} will be thrown.
      * <p>
-     * The {@code OFFSET_SECONDS} field will return a date-time calculated using the specified offset.
-     * The local date-time is combined with the new offset to form an {@code Instant}.
-     * The instant and original zone are then used to create the result.
-     * This algorithm means that it is quite likely that the output has a different offset
-     * to the specified offset. It will however work correctly when passing in the offset
-     * applicable for the instant of the zoned date-time, and will work correctly if passing
-     * one of the two valid offsets during a daylight savings overlap when the same local time
-     * occurs twice. If the new offset value is outside the valid range then a
-     * {@code DateTimeException} will be thrown.
+     * The {@code OFFSET_SECONDS} field will typically be ignored.
+     * The offset of a {@code ZonedDateTime} is controlled primarily by the time-zone.
+     * As such, changing the offset does not generally make sense, because there is only
+     * one valid offset for the local date-time and zone.
+     * If the zoned date-time is in a daylight savings overlap, then the offset is used
+     * to switch between the two valid offsets. In all other cases, the offset is ignored.
+     * If the new offset value is outside the valid range then a {@code DateTimeException} will be thrown.
      * <p>
      * The other {@link #isSupported(TemporalField) supported fields} will behave as per
      * the matching method on {@link LocalDateTime#with(TemporalField, long) LocalDateTime}.
@@ -1214,7 +1228,7 @@
      * then the offset will be retained if possible, otherwise the earlier offset will be used.
      * If in a gap, the local date-time will be adjusted forward by the length of the gap.
      * <p>
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
@@ -1227,6 +1241,7 @@
      * @param newValue  the new value of the field in the result
      * @return a {@code ZonedDateTime} based on {@code this} with the specified field set, not null
      * @throws DateTimeException if the field cannot be set
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1234,11 +1249,11 @@
         if (field instanceof ChronoField) {
             ChronoField f = (ChronoField) field;
             switch (f) {
-                case INSTANT_SECONDS: return create(newValue, getNano(), zone);
-                case OFFSET_SECONDS: {
+                case INSTANT_SECONDS:
+                    return create(newValue, getNano(), zone);
+                case OFFSET_SECONDS:
                     ZoneOffset offset = ZoneOffset.ofTotalSeconds(f.checkValidIntValue(newValue));
                     return resolveOffset(offset);
-                }
             }
             return resolveLocal(dateTime.with(field, newValue));
         }
@@ -1453,6 +1468,7 @@
      * @param unit  the unit to truncate to, not null
      * @return a {@code ZonedDateTime} based on this date-time with the time truncated, not null
      * @throws DateTimeException if unable to truncate
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      */
     public ZonedDateTime truncatedTo(TemporalUnit unit) {
         return resolveLocal(dateTime.truncatedTo(unit));
@@ -1518,6 +1534,7 @@
      * @param unit  the unit of the amount to add, not null
      * @return a {@code ZonedDateTime} based on this date-time with the specified amount added, not null
      * @throws DateTimeException if the addition cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -1761,6 +1778,7 @@
      * @param unit  the unit of the amount to subtract, not null
      * @return a {@code ZonedDateTime} based on this date-time with the specified amount subtracted, not null
      * @throws DateTimeException if the subtraction cannot be made
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -2025,6 +2043,7 @@
      * @param unit  the unit to measure the period in, not null
      * @return the amount of the period between this date-time and the end date-time
      * @throws DateTimeException if the period cannot be calculated
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
@@ -2046,6 +2065,21 @@
         return unit.between(this, endDateTime);
     }
 
+    /**
+     * Formats this date-time using the specified formatter.
+     * <p>
+     * This date-time will be passed to the formatter to produce a string.
+     *
+     * @param formatter  the formatter to use, not null
+     * @return the formatted date-time string, not null
+     * @throws DateTimeException if an error occurs during printing
+     */
+    @Override  // override for Javadoc and performance
+    public String format(DateTimeFormatter formatter) {
+        Objects.requireNonNull(formatter, "formatter");
+        return formatter.format(this);
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Converts this date-time to an {@code OffsetDateTime}.
@@ -2113,21 +2147,6 @@
         return str;
     }
 
-    /**
-     * Outputs this date-time as a {@code String} using the formatter.
-     * <p>
-     * This date will be passed to the formatter
-     * {@link DateTimeFormatter#format(TemporalAccessor) format method}.
-     *
-     * @param formatter  the formatter to use, not null
-     * @return the formatted date-time string, not null
-     * @throws DateTimeException if an error occurs during printing
-     */
-    @Override  // override for Javadoc
-    public String toString(DateTimeFormatter formatter) {
-        return ChronoZonedDateTime.super.toString(formatter);
-    }
-
     //-----------------------------------------------------------------------
     /**
      * Writes the object using a
--- a/src/share/classes/java/time/chrono/ChronoDateImpl.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/chrono/ChronoDateImpl.java	Fri Apr 12 10:42:50 2013 -0700
@@ -59,19 +59,18 @@
 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
 import static java.time.temporal.ChronoField.ERA;
 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
+import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
 import static java.time.temporal.ChronoField.YEAR_OF_ERA;
 
 import java.io.Serializable;
 import java.time.DateTimeException;
-import java.time.LocalDate;
-import java.time.LocalTime;
-import java.time.chrono.Chronology;
-import java.time.chrono.ChronoLocalDate;
-import java.time.chrono.ChronoLocalDateTime;
 import java.time.temporal.ChronoUnit;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAdjuster;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
+import java.time.temporal.ValueRange;
+import java.util.Objects;
 
 /**
  * A date expressed in terms of a standard year-month-day calendar system.
@@ -97,12 +96,12 @@
  *        // Enumerate the list of available calendars and print today for each
  *        Set&lt;Chronology&gt; chronos = Chronology.getAvailableChronologies();
  *        for (Chronology chrono : chronos) {
- *            ChronoLocalDate<?> date = chrono.dateNow();
+ *            ChronoLocalDate&lt;?&gt; date = chrono.dateNow();
  *            System.out.printf("   %20s: %s%n", chrono.getID(), date.toString());
  *        }
  *
  *        // Print the Hijrah date and calendar
- *        ChronoLocalDate<?> date = Chronology.of("Hijrah").dateNow();
+ *        ChronoLocalDate&lt;?&gt; date = Chronology.of("Hijrah").dateNow();
  *        int day = date.get(ChronoField.DAY_OF_MONTH);
  *        int dow = date.get(ChronoField.DAY_OF_WEEK);
  *        int month = date.get(ChronoField.MONTH_OF_YEAR);
@@ -111,10 +110,10 @@
  *                dow, day, month, year);
 
  *        // Print today's date and the last day of the year
- *        ChronoLocalDate<?> now1 = Chronology.of("Hijrah").dateNow();
- *        ChronoLocalDate<?> first = now1.with(ChronoField.DAY_OF_MONTH, 1)
+ *        ChronoLocalDate&lt;?&gt; now1 = Chronology.of("Hijrah").dateNow();
+ *        ChronoLocalDate&lt;?&gt; first = now1.with(ChronoField.DAY_OF_MONTH, 1)
  *                .with(ChronoField.MONTH_OF_YEAR, 1);
- *        ChronoLocalDate<?> last = first.plus(1, ChronoUnit.YEARS)
+ *        ChronoLocalDate&lt;?&gt; last = first.plus(1, ChronoUnit.YEARS)
  *                .minus(1, ChronoUnit.DAYS);
  *        System.out.printf("  Today is %s: start: %s; end: %s%n", last.getChronology().getID(),
  *                first, last);
@@ -168,7 +167,7 @@
                 case MILLENNIA: return plusYears(Math.multiplyExact(amountToAdd, 1000));
                 case ERAS: return with(ERA, Math.addExact(getLong(ERA), amountToAdd));
             }
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return ChronoLocalDate.super.plus(amountToAdd, unit);
     }
@@ -323,6 +322,8 @@
      */
     @Override
     public long periodUntil(Temporal endDateTime, TemporalUnit unit) {
+        Objects.requireNonNull(endDateTime, "endDateTime");
+        Objects.requireNonNull(unit, "unit");
         if (endDateTime instanceof ChronoLocalDate == false) {
             throw new DateTimeException("Unable to calculate period between objects of two different types");
         }
@@ -331,11 +332,35 @@
             throw new DateTimeException("Unable to calculate period between two different chronologies");
         }
         if (unit instanceof ChronoUnit) {
-            return LocalDate.from(this).periodUntil(end, unit);  // TODO: this is wrong
+            switch ((ChronoUnit) unit) {
+                case DAYS: return daysUntil(end);
+                case WEEKS: return daysUntil(end) / 7;
+                case MONTHS: return monthsUntil(end);
+                case YEARS: return monthsUntil(end) / 12;
+                case DECADES: return monthsUntil(end) / 120;
+                case CENTURIES: return monthsUntil(end) / 1200;
+                case MILLENNIA: return monthsUntil(end) / 12000;
+                case ERAS: return end.getLong(ERA) - getLong(ERA);
+            }
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return unit.between(this, endDateTime);
     }
 
+    private long daysUntil(ChronoLocalDate<?> end) {
+        return end.toEpochDay() - toEpochDay();  // no overflow
+    }
+
+    private long monthsUntil(ChronoLocalDate<?> end) {
+        ValueRange range = getChronology().range(MONTH_OF_YEAR);
+        if (range.getMaximum() != 12) {
+            throw new IllegalStateException("ChronoDateImpl only supports Chronologies with 12 months per year");
+        }
+        long packed1 = getLong(PROLEPTIC_MONTH) * 32L + get(DAY_OF_MONTH);  // no overflow
+        long packed2 = end.getLong(PROLEPTIC_MONTH) * 32L + end.get(DAY_OF_MONTH);  // no overflow
+        return (packed2 - packed1) / 32;
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (this == obj) {
--- a/src/share/classes/java/time/chrono/ChronoLocalDate.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/chrono/ChronoLocalDate.java	Fri Apr 12 10:42:50 2013 -0700
@@ -73,7 +73,6 @@
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -81,6 +80,7 @@
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.util.Comparator;
 import java.util.Objects;
 
@@ -249,25 +249,55 @@
         extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDate<?>> {
 
     /**
-     * Comparator for two {@code ChronoLocalDate}s ignoring the chronology.
+     * Gets a comparator that compares {@code ChronoLocalDate} in
+     * time-line order ignoring the chronology.
      * <p>
      * This comparator differs from the comparison in {@link #compareTo} in that it
      * only compares the underlying date and not the chronology.
      * This allows dates in different calendar systems to be compared based
-     * on the time-line position.
-     * This is equivalent to using {@code Long.compare(date1.toEpochDay(),  date2.toEpochDay())}.
+     * on the position of the date on the local time-line.
+     * The underlying comparison is equivalent to comparing the epoch-day.
      *
      * @see #isAfter
      * @see #isBefore
      * @see #isEqual
      */
-    public static final Comparator<ChronoLocalDate<?>> DATE_COMPARATOR =
-            new Comparator<ChronoLocalDate<?>>() {
-        @Override
-        public int compare(ChronoLocalDate<?> date1, ChronoLocalDate<?> date2) {
-            return Long.compare(date1.toEpochDay(), date2.toEpochDay());
+    static Comparator<ChronoLocalDate<?>> timeLineOrder() {
+        return Chronology.DATE_ORDER;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Obtains an instance of {@code ChronoLocalDate} from a temporal object.
+     * <p>
+     * This obtains a local date based on the specified temporal.
+     * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
+     * which this factory converts to an instance of {@code ChronoLocalDate}.
+     * <p>
+     * The conversion extracts and combines the chronology and the date
+     * from the temporal object. The behavior is equivalent to using
+     * {@link Chronology#date(TemporalAccessor)} with the extracted chronology.
+     * Implementations are permitted to perform optimizations such as accessing
+     * those fields that are equivalent to the relevant objects.
+     * <p>
+     * This method matches the signature of the functional interface {@link TemporalQuery}
+     * allowing it to be used as a query via method reference, {@code ChronoLocalDate::from}.
+     *
+     * @param temporal  the temporal object to convert, not null
+     * @return the date, not null
+     * @throws DateTimeException if unable to convert to a {@code ChronoLocalDate}
+     * @see Chronology#date(TemporalAccessor)
+     */
+    static ChronoLocalDate<?> from(TemporalAccessor temporal) {
+        if (temporal instanceof ChronoLocalDate) {
+            return (ChronoLocalDate<?>) temporal;
         }
-    };
+        Chronology chrono = temporal.query(TemporalQuery.chronology());
+        if (chrono == null) {
+            throw new DateTimeException("Unable to obtain ChronoLocalDate from TemporalAccessor: " + temporal.getClass());
+        }
+        return chrono.date(temporal);
+    }
 
     //-----------------------------------------------------------------------
     /**
@@ -295,7 +325,7 @@
      *
      * @return the chronology specific era constant applicable at this date, not null
      */
-    public default Era getEra() {
+    default Era getEra() {
         return getChronology().eraOf(get(ERA));
     }
 
@@ -310,7 +340,7 @@
      *
      * @return true if this date is in a leap year, false otherwise
      */
-    public default boolean isLeapYear() {
+    default boolean isLeapYear() {
         return getChronology().isLeapYear(getLong(YEAR));
     }
 
@@ -332,14 +362,14 @@
      *
      * @return the length of the year in days
      */
-    public default int lengthOfYear() {
+    default int lengthOfYear() {
         return (isLeapYear() ? 366 : 365);
     }
 
     @Override
-    public default boolean isSupported(TemporalField field) {
+    default boolean isSupported(TemporalField field) {
         if (field instanceof ChronoField) {
-            return ((ChronoField) field).isDateField();
+            return field.isDateBased();
         }
         return field != null && field.isSupportedBy(this);
     }
@@ -352,19 +382,20 @@
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default D with(TemporalAdjuster adjuster) {
+    default D with(TemporalAdjuster adjuster) {
         return (D) getChronology().ensureChronoLocalDate(Temporal.super.with(adjuster));
     }
 
     /**
      * {@inheritDoc}
      * @throws DateTimeException {@inheritDoc}
+     * @throws UnsupportedTemporalTypeException {@inheritDoc}
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default D with(TemporalField field, long newValue) {
+    default D with(TemporalField field, long newValue) {
         if (field instanceof ChronoField) {
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return (D) getChronology().ensureChronoLocalDate(field.adjustInto(this, newValue));
     }
@@ -375,7 +406,7 @@
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default D plus(TemporalAmount amount) {
+    default D plus(TemporalAmount amount) {
         return (D) getChronology().ensureChronoLocalDate(Temporal.super.plus(amount));
     }
 
@@ -385,9 +416,9 @@
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default D plus(long amountToAdd, TemporalUnit unit) {
+    default D plus(long amountToAdd, TemporalUnit unit) {
         if (unit instanceof ChronoUnit) {
-            throw new DateTimeException("Unsupported unit: " + unit.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit.getName());
         }
         return (D) getChronology().ensureChronoLocalDate(unit.addTo(this, amountToAdd));
     }
@@ -398,17 +429,18 @@
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default D minus(TemporalAmount amount) {
+    default D minus(TemporalAmount amount) {
         return (D) getChronology().ensureChronoLocalDate(Temporal.super.minus(amount));
     }
 
     /**
      * {@inheritDoc}
      * @throws DateTimeException {@inheritDoc}
+     * @throws UnsupportedTemporalTypeException {@inheritDoc}
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default D minus(long amountToSubtract, TemporalUnit unit) {
+    default D minus(long amountToSubtract, TemporalUnit unit) {
         return (D) getChronology().ensureChronoLocalDate(Temporal.super.minus(amountToSubtract, unit));
     }
 
@@ -433,14 +465,14 @@
      */
     @SuppressWarnings("unchecked")
     @Override
-    public default <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
+    default <R> R query(TemporalQuery<R> query) {
+        if (query == TemporalQuery.zoneId() || query == TemporalQuery.zone() || query == TemporalQuery.offset()) {
             return null;
-        } else if (query == Queries.localTime()) {
+        } else if (query == TemporalQuery.localTime()) {
             return null;
-        } else if (query == Queries.chronology()) {
+        } else if (query == TemporalQuery.chronology()) {
             return (R) getChronology();
-        } else if (query == Queries.precision()) {
+        } else if (query == TemporalQuery.precision()) {
             return (R) DAYS;
         }
         // inline TemporalAccessor.super.query(query) as an optimization
@@ -473,7 +505,7 @@
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
-    public default Temporal adjustInto(Temporal temporal) {
+    default Temporal adjustInto(Temporal temporal) {
         return temporal.with(EPOCH_DAY, toEpochDay());
     }
 
@@ -522,7 +554,7 @@
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override  // override for Javadoc
-    public abstract long periodUntil(Temporal endDate, TemporalUnit unit);
+    long periodUntil(Temporal endDate, TemporalUnit unit);
 
     /**
      * Calculates the period between this date and another date as a {@code Period}.
@@ -530,13 +562,11 @@
      * This calculates the period between two dates in terms of years, months and days.
      * The start and end points are {@code this} and the specified date.
      * The result will be negative if the end is before the start.
+     * The negative sign will be the same in each of year, month and day.
      * <p>
-     * The calculation is performed using the the chronology of this date.
+     * The calculation is performed using the chronology of this date.
      * If necessary, the input date will be converted to match.
      * <p>
-     * The result of this method can be a negative period if the end is before the start.
-     * The negative sign will be the same in each of year, month and day.
-     * <p>
      * This instance is immutable and unaffected by this method call.
      *
      * @param endDate  the end date, exclusive, which may be in any chronology, not null
@@ -544,7 +574,26 @@
      * @throws DateTimeException if the period cannot be calculated
      * @throws ArithmeticException if numeric overflow occurs
      */
-    public abstract Period periodUntil(ChronoLocalDate<?> endDate);
+    Period periodUntil(ChronoLocalDate<?> endDate);
+
+    /**
+     * Formats this date using the specified formatter.
+     * <p>
+     * This date will be passed to the formatter to produce a string.
+     * <p>
+     * The default implementation must behave as follows:
+     * <pre>
+     *  return formatter.format(this);
+     * </pre>
+     *
+     * @param formatter  the formatter to use, not null
+     * @return the formatted date string, not null
+     * @throws DateTimeException if an error occurs during printing
+     */
+    default String format(DateTimeFormatter formatter) {
+        Objects.requireNonNull(formatter, "formatter");
+        return formatter.format(this);
+    }
 
     //-----------------------------------------------------------------------
     /**
@@ -556,7 +605,7 @@
      * @param localTime  the local time to use, not null
      * @return the local date-time formed from this date and the specified time, not null
      */
-    public default ChronoLocalDateTime<D> atTime(LocalTime localTime) {
+    default ChronoLocalDateTime<D> atTime(LocalTime localTime) {
         return (ChronoLocalDateTime<D>)ChronoLocalDateTimeImpl.of(this, localTime);
     }
 
@@ -572,7 +621,7 @@
      *
      * @return the Epoch Day equivalent to this date
      */
-    public default long toEpochDay() {
+    default long toEpochDay() {
         return getLong(EPOCH_DAY);
     }
 
@@ -606,7 +655,7 @@
      * @return the comparator value, negative if less, positive if greater
      */
     @Override
-    public default int compareTo(ChronoLocalDate<?> other) {
+    default int compareTo(ChronoLocalDate<?> other) {
         int cmp = Long.compare(toEpochDay(), other.toEpochDay());
         if (cmp == 0) {
             cmp = getChronology().compareTo(other.getChronology());
@@ -628,7 +677,7 @@
      * @param other  the other date to compare to, not null
      * @return true if this is after the specified date
      */
-    public default boolean isAfter(ChronoLocalDate<?> other) {
+    default boolean isAfter(ChronoLocalDate<?> other) {
         return this.toEpochDay() > other.toEpochDay();
     }
 
@@ -646,7 +695,7 @@
      * @param other  the other date to compare to, not null
      * @return true if this is before the specified date
      */
-    public default boolean isBefore(ChronoLocalDate<?> other) {
+    default boolean isBefore(ChronoLocalDate<?> other) {
         return this.toEpochDay() < other.toEpochDay();
     }
 
@@ -664,7 +713,7 @@
      * @param other  the other date to compare to, not null
      * @return true if the underlying date is equal to the specified date
      */
-    public default boolean isEqual(ChronoLocalDate<?> other) {
+    default boolean isEqual(ChronoLocalDate<?> other) {
         return this.toEpochDay() == other.toEpochDay();
     }
 
@@ -695,28 +744,11 @@
     /**
      * Outputs this date as a {@code String}.
      * <p>
-     * The output will include the full local date and the chronology ID.
+     * The output will include the full local date.
      *
      * @return the formatted date, not null
      */
     @Override
     String toString();
 
-    /**
-     * Outputs this date as a {@code String} using the formatter.
-     * <p>
-     * The default implementation must behave as follows:
-     * <pre>
-     *  return formatter.format(this);
-     * </pre>
-     *
-     * @param formatter  the formatter to use, not null
-     * @return the formatted date string, not null
-     * @throws DateTimeException if an error occurs during printing
-     */
-    public default String toString(DateTimeFormatter formatter) {
-        Objects.requireNonNull(formatter, "formatter");
-        return formatter.format(this);
-    }
-
 }
--- a/src/share/classes/java/time/chrono/ChronoLocalDateTime.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/chrono/ChronoLocalDateTime.java	Fri Apr 12 10:42:50 2013 -0700
@@ -73,7 +73,6 @@
 import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoField;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -119,29 +118,57 @@
         extends Temporal, TemporalAdjuster, Comparable<ChronoLocalDateTime<?>> {
 
     /**
-     * Comparator for two {@code ChronoLocalDateTime} instances ignoring the chronology.
+     * Gets a comparator that compares {@code ChronoLocalDateTime} in
+     * time-line order ignoring the chronology.
      * <p>
-     * This method differs from the comparison in {@link #compareTo} in that it
-     * only compares the underlying date and not the chronology.
+     * This comparator differs from the comparison in {@link #compareTo} in that it
+     * only compares the underlying date-time and not the chronology.
      * This allows dates in different calendar systems to be compared based
-     * on the time-line position.
+     * on the position of the date-time on the local time-line.
+     * The underlying comparison is equivalent to comparing the epoch-day and nano-of-day.
      *
      * @see #isAfter
      * @see #isBefore
      * @see #isEqual
      */
-    Comparator<ChronoLocalDateTime<?>> DATE_TIME_COMPARATOR =
-            new Comparator<ChronoLocalDateTime<?>>() {
-        @Override
-        public int compare(ChronoLocalDateTime<?> datetime1, ChronoLocalDateTime<?> datetime2) {
-            int cmp = Long.compare(datetime1.toLocalDate().toEpochDay(), datetime2.toLocalDate().toEpochDay());
-            if (cmp == 0) {
-                cmp = Long.compare(datetime1.toLocalTime().toNanoOfDay(), datetime2.toLocalTime().toNanoOfDay());
-            }
-            return cmp;
+    static Comparator<ChronoLocalDateTime<?>> timeLineOrder() {
+        return Chronology.DATE_TIME_ORDER;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Obtains an instance of {@code ChronoLocalDateTime} from a temporal object.
+     * <p>
+     * This obtains a local date-time based on the specified temporal.
+     * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
+     * which this factory converts to an instance of {@code ChronoLocalDateTime}.
+     * <p>
+     * The conversion extracts and combines the chronology and the date-time
+     * from the temporal object. The behavior is equivalent to using
+     * {@link Chronology#localDateTime(TemporalAccessor)} with the extracted chronology.
+     * Implementations are permitted to perform optimizations such as accessing
+     * those fields that are equivalent to the relevant objects.
+     * <p>
+     * This method matches the signature of the functional interface {@link TemporalQuery}
+     * allowing it to be used as a query via method reference, {@code ChronoLocalDateTime::from}.
+     *
+     * @param temporal  the temporal object to convert, not null
+     * @return the date-time, not null
+     * @throws DateTimeException if unable to convert to a {@code ChronoLocalDateTime}
+     * @see Chronology#localDateTime(TemporalAccessor)
+     */
+    static ChronoLocalDateTime<?> from(TemporalAccessor temporal) {
+        if (temporal instanceof ChronoLocalDateTime) {
+            return (ChronoLocalDateTime<?>) temporal;
         }
-    };
+        Chronology chrono = temporal.query(TemporalQuery.chronology());
+        if (chrono == null) {
+            throw new DateTimeException("Unable to obtain ChronoLocalDateTime from TemporalAccessor: " + temporal.getClass());
+        }
+        return chrono.localDateTime(temporal);
+    }
 
+    //-----------------------------------------------------------------------
     /**
      * Gets the local date part of this date-time.
      * <p>
@@ -163,7 +190,7 @@
     LocalTime toLocalTime();
 
     @Override   // Override to provide javadoc
-    public boolean isSupported(TemporalField field);
+    boolean isSupported(TemporalField field);
 
     //-----------------------------------------------------------------------
     // override for covariant return type
@@ -173,7 +200,7 @@
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default ChronoLocalDateTime<D> with(TemporalAdjuster adjuster) {
+    default ChronoLocalDateTime<D> with(TemporalAdjuster adjuster) {
         return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.with(adjuster)));
     }
 
@@ -191,7 +218,7 @@
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default ChronoLocalDateTime<D> plus(TemporalAmount amount) {
+    default ChronoLocalDateTime<D> plus(TemporalAmount amount) {
         return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.plus(amount)));
     }
 
@@ -209,7 +236,7 @@
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default ChronoLocalDateTime<D> minus(TemporalAmount amount) {
+    default ChronoLocalDateTime<D> minus(TemporalAmount amount) {
         return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.minus(amount)));
     }
 
@@ -219,7 +246,7 @@
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default ChronoLocalDateTime<D> minus(long amountToSubtract, TemporalUnit unit) {
+    default ChronoLocalDateTime<D> minus(long amountToSubtract, TemporalUnit unit) {
         return (ChronoLocalDateTime<D>)(toLocalDate().getChronology().ensureChronoLocalDateTime(Temporal.super.minus(amountToSubtract, unit)));
     }
 
@@ -244,14 +271,14 @@
      */
     @SuppressWarnings("unchecked")
     @Override
-    public default <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) {
+    default <R> R query(TemporalQuery<R> query) {
+        if (query == TemporalQuery.zoneId() || query == TemporalQuery.zone() || query == TemporalQuery.offset()) {
             return null;
-        } else if (query == Queries.localTime()) {
+        } else if (query == TemporalQuery.localTime()) {
             return (R) toLocalTime();
-        } else if (query == Queries.chronology()) {
+        } else if (query == TemporalQuery.chronology()) {
             return (R) toLocalDate().getChronology();
-        } else if (query == Queries.precision()) {
+        } else if (query == TemporalQuery.precision()) {
             return (R) NANOS;
         }
         // inline TemporalAccessor.super.query(query) as an optimization
@@ -285,12 +312,31 @@
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
-    public default Temporal adjustInto(Temporal temporal) {
+    default Temporal adjustInto(Temporal temporal) {
         return temporal
                 .with(EPOCH_DAY, toLocalDate().toEpochDay())
                 .with(NANO_OF_DAY, toLocalTime().toNanoOfDay());
     }
 
+    /**
+     * Formats this date-time using the specified formatter.
+     * <p>
+     * This date-time will be passed to the formatter to produce a string.
+     * <p>
+     * The default implementation must behave as follows:
+     * <pre>
+     *  return formatter.format(this);
+     * </pre>
+     *
+     * @param formatter  the formatter to use, not null
+     * @return the formatted date-time string, not null
+     * @throws DateTimeException if an error occurs during printing
+     */
+    default String format(DateTimeFormatter formatter) {
+        Objects.requireNonNull(formatter, "formatter");
+        return formatter.format(this);
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Combines this time with a time-zone to create a {@code ChronoZonedDateTime}.
@@ -334,7 +380,7 @@
      * @param offset  the offset to use for the conversion, not null
      * @return an {@code Instant} representing the same instant, not null
      */
-    public default Instant toInstant(ZoneOffset offset) {
+    default Instant toInstant(ZoneOffset offset) {
         return Instant.ofEpochSecond(toEpochSecond(offset), toLocalTime().getNano());
     }
 
@@ -352,7 +398,7 @@
      * @param offset  the offset to use for the conversion, not null
      * @return the number of seconds from the epoch of 1970-01-01T00:00:00Z
      */
-    public default long toEpochSecond(ZoneOffset offset) {
+    default long toEpochSecond(ZoneOffset offset) {
         Objects.requireNonNull(offset, "offset");
         long epochDay = toLocalDate().toEpochDay();
         long secs = epochDay * 86400 + toLocalTime().toSecondOfDay();
@@ -388,7 +434,7 @@
      * @return the comparator value, negative if less, positive if greater
      */
     @Override
-    public default int compareTo(ChronoLocalDateTime<?> other) {
+    default int compareTo(ChronoLocalDateTime<?> other) {
         int cmp = toLocalDate().compareTo(other.toLocalDate());
         if (cmp == 0) {
             cmp = toLocalTime().compareTo(other.toLocalTime());
@@ -413,7 +459,7 @@
      * @param other  the other date-time to compare to, not null
      * @return true if this is after the specified date-time
      */
-    public default boolean isAfter(ChronoLocalDateTime<?> other) {
+    default boolean isAfter(ChronoLocalDateTime<?> other) {
         long thisEpDay = this.toLocalDate().toEpochDay();
         long otherEpDay = other.toLocalDate().toEpochDay();
         return thisEpDay > otherEpDay ||
@@ -434,7 +480,7 @@
      * @param other  the other date-time to compare to, not null
      * @return true if this is before the specified date-time
      */
-    public default boolean isBefore(ChronoLocalDateTime<?> other) {
+    default boolean isBefore(ChronoLocalDateTime<?> other) {
         long thisEpDay = this.toLocalDate().toEpochDay();
         long otherEpDay = other.toLocalDate().toEpochDay();
         return thisEpDay < otherEpDay ||
@@ -455,7 +501,7 @@
      * @param other  the other date-time to compare to, not null
      * @return true if the underlying date-time is equal to the specified date-time on the timeline
      */
-    public default boolean isEqual(ChronoLocalDateTime<?> other) {
+    default boolean isEqual(ChronoLocalDateTime<?> other) {
         // Do the time check first, it is cheaper than computing EPOCH day.
         return this.toLocalTime().toNanoOfDay() == other.toLocalTime().toNanoOfDay() &&
                this.toLocalDate().toEpochDay() == other.toLocalDate().toEpochDay();
@@ -484,27 +530,11 @@
     /**
      * Outputs this date-time as a {@code String}.
      * <p>
-     * The output will include the full local date-time and the chronology ID.
+     * The output will include the full local date-time.
      *
      * @return a string representation of this date-time, not null
      */
     @Override
     String toString();
 
-    /**
-     * Outputs this date-time as a {@code String} using the formatter.
-     * <p>
-     * The default implementation must behave as follows:
-     * <pre>
-     *  return formatter.format(this);
-     * </pre>
-     *
-     * @param formatter  the formatter to use, not null
-     * @return the formatted date-time string, not null
-     * @throws DateTimeException if an error occurs during printing
-     */
-    public default String toString(DateTimeFormatter formatter) {
-        Objects.requireNonNull(formatter, "formatter");
-        return formatter.format(this);
-    }
 }
--- a/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/chrono/ChronoLocalDateTimeImpl.java	Fri Apr 12 10:42:50 2013 -0700
@@ -171,6 +171,7 @@
      * @param time  the local time, not null
      * @return the local date-time, not null
      */
+    @SuppressWarnings("rawtypes")
     static ChronoLocalDateTimeImpl<?> of(ChronoLocalDate<?> date, LocalTime time) {
         return new ChronoLocalDateTimeImpl(date, time);
     }
@@ -201,8 +202,8 @@
             return this;
         }
         // Validate that the new Temporal is a ChronoLocalDate (and not something else)
-        D cd = (D)date.getChronology().ensureChronoLocalDate(newDate);
-        return new ChronoLocalDateTimeImpl<>((D)cd, newTime);
+        D cd = (D) date.getChronology().ensureChronoLocalDate(newDate);
+        return new ChronoLocalDateTimeImpl<>(cd, newTime);
     }
 
     //-----------------------------------------------------------------------
@@ -221,7 +222,7 @@
     public boolean isSupported(TemporalField field) {
         if (field instanceof ChronoField) {
             ChronoField f = (ChronoField) field;
-            return f.isDateField() || f.isTimeField();
+            return f.isDateBased() || f.isTimeBased();
         }
         return field != null && field.isSupportedBy(this);
     }
@@ -230,7 +231,7 @@
     public ValueRange range(TemporalField field) {
         if (field instanceof ChronoField) {
             ChronoField f = (ChronoField) field;
-            return (f.isTimeField() ? time.range(field) : date.range(field));
+            return (f.isTimeBased() ? time.range(field) : date.range(field));
         }
         return field.rangeRefinedBy(this);
     }
@@ -239,7 +240,7 @@
     public int get(TemporalField field) {
         if (field instanceof ChronoField) {
             ChronoField f = (ChronoField) field;
-            return (f.isTimeField() ? time.get(field) : date.get(field));
+            return (f.isTimeBased() ? time.get(field) : date.get(field));
         }
         return range(field).checkValidIntValue(getLong(field), field);
     }
@@ -248,7 +249,7 @@
     public long getLong(TemporalField field) {
         if (field instanceof ChronoField) {
             ChronoField f = (ChronoField) field;
-            return (f.isTimeField() ? time.getLong(field) : date.getLong(field));
+            return (f.isTimeBased() ? time.getLong(field) : date.getLong(field));
         }
         return field.getFrom(this);
     }
@@ -272,7 +273,7 @@
     public ChronoLocalDateTimeImpl<D> with(TemporalField field, long newValue) {
         if (field instanceof ChronoField) {
             ChronoField f = (ChronoField) field;
-            if (f.isTimeField()) {
+            if (f.isTimeBased()) {
                 return with(date, time.with(field, newValue));
             } else {
                 return with(date.with(field, newValue), time);
@@ -376,7 +377,7 @@
             }
             D endDate = end.toLocalDate();
             if (end.toLocalTime().isBefore(time)) {
-                endDate = (D)endDate.minus(1, ChronoUnit.DAYS);
+                endDate = endDate.minus(1, ChronoUnit.DAYS);
             }
             return date.periodUntil(endDate, unit);
         }
@@ -403,7 +404,7 @@
     }
 
     static ChronoLocalDateTime<?> readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-        ChronoLocalDate date = (ChronoLocalDate) in.readObject();
+        ChronoLocalDate<?> date = (ChronoLocalDate<?>) in.readObject();
         LocalTime time = (LocalTime) in.readObject();
         return date.atTime(time);
     }
--- a/src/share/classes/java/time/chrono/ChronoZonedDateTime.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/chrono/ChronoZonedDateTime.java	Fri Apr 12 10:42:50 2013 -0700
@@ -73,7 +73,6 @@
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoField;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -81,6 +80,7 @@
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
 import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
 import java.util.Comparator;
 import java.util.Objects;
@@ -119,30 +119,59 @@
         extends Temporal, Comparable<ChronoZonedDateTime<?>> {
 
     /**
-     * Comparator for two {@code ChronoZonedDateTime} instances ignoring the chronology.
+     * Gets a comparator that compares {@code ChronoZonedDateTime} in
+     * time-line order ignoring the chronology.
      * <p>
-     * This method differs from the comparison in {@link #compareTo} in that it
-     * only compares the underlying date and not the chronology.
+     * This comparator differs from the comparison in {@link #compareTo} in that it
+     * only compares the underlying instant and not the chronology.
      * This allows dates in different calendar systems to be compared based
-     * on the time-line position.
+     * on the position of the date-time on the instant time-line.
+     * The underlying comparison is equivalent to comparing the epoch-second and nano-of-second.
      *
      * @see #isAfter
      * @see #isBefore
      * @see #isEqual
      */
-    Comparator<ChronoZonedDateTime<?>> INSTANT_COMPARATOR = new Comparator<ChronoZonedDateTime<?>>() {
-        @Override
-        public int compare(ChronoZonedDateTime<?> datetime1, ChronoZonedDateTime<?> datetime2) {
-            int cmp = Long.compare(datetime1.toEpochSecond(), datetime2.toEpochSecond());
-            if (cmp == 0) {
-                cmp = Long.compare(datetime1.toLocalTime().toNanoOfDay(), datetime2.toLocalTime().toNanoOfDay());
-            }
-            return cmp;
+    static Comparator<ChronoZonedDateTime<?>> timeLineOrder() {
+        return Chronology.INSTANT_ORDER;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Obtains an instance of {@code ChronoZonedDateTime} from a temporal object.
+     * <p>
+     * This creates a zoned date-time based on the specified temporal.
+     * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
+     * which this factory converts to an instance of {@code ChronoZonedDateTime}.
+     * <p>
+     * The conversion extracts and combines the chronology, date, time and zone
+     * from the temporal object. The behavior is equivalent to using
+     * {@link Chronology#zonedDateTime(TemporalAccessor)} with the extracted chronology.
+     * Implementations are permitted to perform optimizations such as accessing
+     * those fields that are equivalent to the relevant objects.
+     * <p>
+     * This method matches the signature of the functional interface {@link TemporalQuery}
+     * allowing it to be used as a query via method reference, {@code ChronoZonedDateTime::from}.
+     *
+     * @param temporal  the temporal objec t to convert, not null
+     * @return the date-time, not null
+     * @throws DateTimeException if unable to convert to a {@code ChronoZonedDateTime}
+     * @see Chronology#zonedDateTime(TemporalAccessor)
+     */
+    static ChronoZonedDateTime<?> from(TemporalAccessor temporal) {
+        if (temporal instanceof ChronoZonedDateTime) {
+            return (ChronoZonedDateTime<?>) temporal;
         }
-    };
+        Chronology chrono = temporal.query(TemporalQuery.chronology());
+        if (chrono == null) {
+            throw new DateTimeException("Unable to obtain ChronoZonedDateTime from TemporalAccessor: " + temporal.getClass());
+        }
+        return chrono.zonedDateTime(temporal);
+    }
 
+    //-----------------------------------------------------------------------
     @Override
-    public default ValueRange range(TemporalField field) {
+    default ValueRange range(TemporalField field) {
         if (field instanceof ChronoField) {
             if (field == INSTANT_SECONDS || field == OFFSET_SECONDS) {
                 return field.range();
@@ -153,11 +182,13 @@
     }
 
     @Override
-    public default int get(TemporalField field) {
+    default int get(TemporalField field) {
         if (field instanceof ChronoField) {
             switch ((ChronoField) field) {
-                case INSTANT_SECONDS: throw new DateTimeException("Field too large for an int: " + field);
-                case OFFSET_SECONDS: return getOffset().getTotalSeconds();
+                case INSTANT_SECONDS:
+                    throw new UnsupportedTemporalTypeException("Invalid field 'InstantSeconds' for get() method, use getLong() instead");
+                case OFFSET_SECONDS:
+                    return getOffset().getTotalSeconds();
             }
             return toLocalDateTime().get(field);
         }
@@ -165,7 +196,7 @@
     }
 
     @Override
-    public default long getLong(TemporalField field) {
+    default long getLong(TemporalField field) {
         if (field instanceof ChronoField) {
             switch ((ChronoField) field) {
                 case INSTANT_SECONDS: return toEpochSecond();
@@ -184,7 +215,7 @@
      *
      * @return the date part of this date-time, not null
      */
-    public default D toLocalDate() {
+    default D toLocalDate() {
         return toLocalDateTime().toLocalDate();
     }
 
@@ -196,7 +227,7 @@
      *
      * @return the time part of this date-time, not null
      */
-    public default LocalTime toLocalTime() {
+    default LocalTime toLocalTime() {
         return toLocalDateTime().toLocalTime();
     }
 
@@ -306,7 +337,7 @@
     ChronoZonedDateTime<D> withZoneSameInstant(ZoneId zone);
 
     @Override   // Override to provide javadoc
-    public boolean isSupported(TemporalField field);
+    boolean isSupported(TemporalField field);
 
     //-----------------------------------------------------------------------
     // override for covariant return type
@@ -316,7 +347,7 @@
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default ChronoZonedDateTime<D> with(TemporalAdjuster adjuster) {
+    default ChronoZonedDateTime<D> with(TemporalAdjuster adjuster) {
         return (ChronoZonedDateTime<D>)(toLocalDate().getChronology().ensureChronoZonedDateTime(Temporal.super.with(adjuster)));
     }
 
@@ -334,7 +365,7 @@
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default ChronoZonedDateTime<D> plus(TemporalAmount amount) {
+    default ChronoZonedDateTime<D> plus(TemporalAmount amount) {
         return (ChronoZonedDateTime<D>)(toLocalDate().getChronology().ensureChronoZonedDateTime(Temporal.super.plus(amount)));
     }
 
@@ -352,7 +383,7 @@
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default ChronoZonedDateTime<D> minus(TemporalAmount amount) {
+    default ChronoZonedDateTime<D> minus(TemporalAmount amount) {
         return (ChronoZonedDateTime<D>)(toLocalDate().getChronology().ensureChronoZonedDateTime(Temporal.super.minus(amount)));
     }
 
@@ -362,7 +393,7 @@
      * @throws ArithmeticException {@inheritDoc}
      */
     @Override
-    public default ChronoZonedDateTime<D> minus(long amountToSubtract, TemporalUnit unit) {
+    default ChronoZonedDateTime<D> minus(long amountToSubtract, TemporalUnit unit) {
         return (ChronoZonedDateTime<D>)(toLocalDate().getChronology().ensureChronoZonedDateTime(Temporal.super.minus(amountToSubtract, unit)));
     }
 
@@ -387,16 +418,16 @@
      */
     @SuppressWarnings("unchecked")
     @Override
-    public default <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.zone() || query == Queries.zoneId()) {
+    default <R> R query(TemporalQuery<R> query) {
+        if (query == TemporalQuery.zone() || query == TemporalQuery.zoneId()) {
             return (R) getZone();
-        } else if (query == Queries.offset()) {
+        } else if (query == TemporalQuery.offset()) {
             return (R) getOffset();
-        } else if (query == Queries.localTime()) {
+        } else if (query == TemporalQuery.localTime()) {
             return (R) toLocalTime();
-        } else if (query == Queries.chronology()) {
+        } else if (query == TemporalQuery.chronology()) {
             return (R) toLocalDate().getChronology();
-        } else if (query == Queries.precision()) {
+        } else if (query == TemporalQuery.precision()) {
             return (R) NANOS;
         }
         // inline TemporalAccessor.super.query(query) as an optimization
@@ -404,6 +435,25 @@
         return query.queryFrom(this);
     }
 
+    /**
+     * Formats this date-time using the specified formatter.
+     * <p>
+     * This date-time will be passed to the formatter to produce a string.
+     * <p>
+     * The default implementation must behave as follows:
+     * <pre>
+     *  return formatter.format(this);
+     * </pre>
+     *
+     * @param formatter  the formatter to use, not null
+     * @return the formatted date-time string, not null
+     * @throws DateTimeException if an error occurs during printing
+     */
+    default String format(DateTimeFormatter formatter) {
+        Objects.requireNonNull(formatter, "formatter");
+        return formatter.format(this);
+    }
+
     //-----------------------------------------------------------------------
     /**
      * Converts this date-time to an {@code Instant}.
@@ -415,7 +465,7 @@
      *
      * @return an {@code Instant} representing the same instant, not null
      */
-    public default Instant toInstant() {
+    default Instant toInstant() {
         return Instant.ofEpochSecond(toEpochSecond(), toLocalTime().getNano());
     }
 
@@ -430,7 +480,7 @@
      *
      * @return the number of seconds from the epoch of 1970-01-01T00:00:00Z
      */
-    public default long toEpochSecond() {
+    default long toEpochSecond() {
         long epochDay = toLocalDate().toEpochDay();
         long secs = epochDay * 86400 + toLocalTime().toSecondOfDay();
         secs -= getOffset().getTotalSeconds();
@@ -454,7 +504,7 @@
      * @return the comparator value, negative if less, positive if greater
      */
     @Override
-    public default int compareTo(ChronoZonedDateTime<?> other) {
+    default int compareTo(ChronoZonedDateTime<?> other) {
         int cmp = Long.compare(toEpochSecond(), other.toEpochSecond());
         if (cmp == 0) {
             cmp = toLocalTime().getNano() - other.toLocalTime().getNano();
@@ -484,7 +534,7 @@
      * @param other  the other date-time to compare to, not null
      * @return true if this point is before the specified date-time
      */
-    public default boolean isBefore(ChronoZonedDateTime<?> other) {
+    default boolean isBefore(ChronoZonedDateTime<?> other) {
         long thisEpochSec = toEpochSecond();
         long otherEpochSec = other.toEpochSecond();
         return thisEpochSec < otherEpochSec ||
@@ -504,7 +554,7 @@
      * @param other  the other date-time to compare to, not null
      * @return true if this is after the specified date-time
      */
-    public default boolean isAfter(ChronoZonedDateTime<?> other) {
+    default boolean isAfter(ChronoZonedDateTime<?> other) {
         long thisEpochSec = toEpochSecond();
         long otherEpochSec = other.toEpochSecond();
         return thisEpochSec > otherEpochSec ||
@@ -524,7 +574,7 @@
      * @param other  the other date-time to compare to, not null
      * @return true if the instant equals the instant of the specified date-time
      */
-    public default boolean isEqual(ChronoZonedDateTime<?> other) {
+    default boolean isEqual(ChronoZonedDateTime<?> other) {
         return toEpochSecond() == other.toEpochSecond() &&
                 toLocalTime().getNano() == other.toLocalTime().getNano();
     }
@@ -555,28 +605,11 @@
     /**
      * Outputs this date-time as a {@code String}.
      * <p>
-     * The output will include the full zoned date-time and the chronology ID.
+     * The output will include the full zoned date-time.
      *
      * @return a string representation of this date-time, not null
      */
     @Override
     String toString();
 
-    /**
-     * Outputs this date-time as a {@code String} using the formatter.
-     * <p>
-     * The default implementation must behave as follows:
-     * <pre>
-     *  return formatter.format(this);
-     * </pre>
-     *
-     * @param formatter  the formatter to use, not null
-     * @return the formatted date-time string, not null
-     * @throws DateTimeException if an error occurs during printing
-     */
-    public default String toString(DateTimeFormatter formatter) {
-        Objects.requireNonNull(formatter, "formatter");
-        return formatter.format(this);
-    }
-
 }
--- a/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/chrono/ChronoZonedDateTimeImpl.java	Fri Apr 12 10:42:50 2013 -0700
@@ -167,6 +167,7 @@
      * @param zone  the zone identifier, not null
      * @return the zoned date-time, not null
      */
+    @SuppressWarnings("rawtypes")
     static ChronoZonedDateTimeImpl<?> ofInstant(Chronology chrono, Instant instant, ZoneId zone) {
         ZoneRules rules = zone.getRules();
         ZoneOffset offset = rules.getOffset(instant);
--- a/src/share/classes/java/time/chrono/Chronology.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/chrono/Chronology.java	Fri Apr 12 10:42:50 2013 -0700
@@ -61,38 +61,57 @@
  */
 package java.time.chrono;
 
+import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH;
+import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR;
+import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH;
+import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR;
+import static java.time.temporal.ChronoField.DAY_OF_MONTH;
+import static java.time.temporal.ChronoField.DAY_OF_WEEK;
+import static java.time.temporal.ChronoField.DAY_OF_YEAR;
+import static java.time.temporal.ChronoField.EPOCH_DAY;
+import static java.time.temporal.ChronoField.ERA;
+import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
+import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
+import static java.time.temporal.ChronoField.YEAR;
+import static java.time.temporal.ChronoField.YEAR_OF_ERA;
+import static java.time.temporal.TemporalAdjuster.nextOrSame;
+
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
 import java.io.InvalidObjectException;
 import java.io.ObjectStreamException;
+import java.io.Serializable;
 import java.time.Clock;
 import java.time.DateTimeException;
+import java.time.DayOfWeek;
 import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalTime;
 import java.time.ZoneId;
-import java.time.chrono.HijrahChronology;
-import java.time.chrono.JapaneseChronology;
-import java.time.chrono.MinguoChronology;
-import java.time.chrono.ThaiBuddhistChronology;
 import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.ResolverStyle;
 import java.time.format.TextStyle;
 import java.time.temporal.ChronoField;
-import java.time.temporal.Queries;
+import java.time.temporal.ChronoUnit;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalField;
 import java.time.temporal.TemporalQuery;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.temporal.ValueRange;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Objects;
 import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
+import sun.util.logging.PlatformLogger;
+
 /**
  * A calendar system, used to organize and identify dates.
  * <p>
@@ -106,7 +125,7 @@
  * for use by any {@code Chronology} implementation:
  * <pre>
  *   LocalDate isoDate = ...
- *   ChronoLocalDate&lt;ThaiBuddhistChronology&gt; thaiDate = ...
+ *   ThaiBuddhistDate thaiDate = ...
  *   int isoYear = isoDate.get(ChronoField.YEAR);
  *   int thaiYear = thaiDate.get(ChronoField.YEAR);
  * </pre>
@@ -154,8 +173,8 @@
  * <p>
  * Each chronology must define a chronology ID that is unique within the system.
  * If the chronology represents a calendar system defined by the
- * <em>Unicode Locale Data Markup Language (LDML)</em> specification then that
- * calendar type should also be specified.
+ * CLDR specification then the calendar type is the concatenation of the
+ * CLDR type and, if applicable, the CLDR variant,
  *
  * <h3>Specification for implementors</h3>
  * This class must be implemented with care to ensure other classes operate correctly.
@@ -167,6 +186,36 @@
 public abstract class Chronology implements Comparable<Chronology> {
 
     /**
+     * ChronoLocalDate order constant.
+     */
+    static final Comparator<ChronoLocalDate<?>> DATE_ORDER =
+        (Comparator<ChronoLocalDate<?>> & Serializable) (date1, date2) -> {
+            return Long.compare(date1.toEpochDay(), date2.toEpochDay());
+        };
+    /**
+     * ChronoLocalDateTime order constant.
+     */
+    static final Comparator<ChronoLocalDateTime<?>> DATE_TIME_ORDER =
+        (Comparator<ChronoLocalDateTime<?>> & Serializable) (dateTime1, dateTime2) -> {
+            int cmp = Long.compare(dateTime1.toLocalDate().toEpochDay(), dateTime2.toLocalDate().toEpochDay());
+            if (cmp == 0) {
+                cmp = Long.compare(dateTime1.toLocalTime().toNanoOfDay(), dateTime2.toLocalTime().toNanoOfDay());
+            }
+            return cmp;
+        };
+    /**
+     * ChronoZonedDateTime order constant.
+     */
+    static final Comparator<ChronoZonedDateTime<?>> INSTANT_ORDER =
+            (Comparator<ChronoZonedDateTime<?>> & Serializable) (dateTime1, dateTime2) -> {
+                int cmp = Long.compare(dateTime1.toEpochSecond(), dateTime2.toEpochSecond());
+                if (cmp == 0) {
+                    cmp = Long.compare(dateTime1.toLocalTime().getNano(), dateTime2.toLocalTime().getNano());
+                }
+                return cmp;
+            };
+
+    /**
      * Map of available calendars by ID.
      */
     private static final ConcurrentHashMap<String, Chronology> CHRONOS_BY_ID = new ConcurrentHashMap<>();
@@ -176,19 +225,35 @@
     private static final ConcurrentHashMap<String, Chronology> CHRONOS_BY_TYPE = new ConcurrentHashMap<>();
 
     /**
+     * Register a Chronology by its ID and type for lookup by {@link #of(java.lang.String)}.
+     * Chronologies must not be registered until they are completely constructed.
+     * Specifically, not in the constructor of Chronology.
+     *
+     * @param chrono the chronology to register; not null
+     * @return the already registered Chronology if any, may be null
+     */
+    static Chronology registerChrono(Chronology chrono) {
+        return registerChrono(chrono, chrono.getId());
+    }
+
+    /**
      * Register a Chronology by ID and type for lookup by {@link #of(java.lang.String)}.
      * Chronos must not be registered until they are completely constructed.
      * Specifically, not in the constructor of Chronology.
+     *
      * @param chrono the chronology to register; not null
+     * @param id the ID to register the chronology; not null
+     * @return the already registered Chronology if any, may be null
      */
-    private static void registerChrono(Chronology chrono) {
-        Chronology prev = CHRONOS_BY_ID.putIfAbsent(chrono.getId(), chrono);
+    static Chronology registerChrono(Chronology chrono, String id) {
+        Chronology prev = CHRONOS_BY_ID.putIfAbsent(id, chrono);
         if (prev == null) {
             String type = chrono.getCalendarType();
             if (type != null) {
                 CHRONOS_BY_TYPE.putIfAbsent(type, chrono);
             }
         }
+        return prev;
     }
 
     /**
@@ -209,18 +274,25 @@
     private static boolean initCache() {
         if (CHRONOS_BY_ID.get("ISO") == null) {
             // Initialization is incomplete
-            @SuppressWarnings("rawtypes")
-            ServiceLoader<Chronology> loader =  ServiceLoader.load(Chronology.class, null);
-            for (Chronology chrono : loader) {
-                registerChrono(chrono);
-            }
 
-            // Register these calendars; the ServiceLoader configuration is not used
+            // Register built-in Chronologies
             registerChrono(HijrahChronology.INSTANCE);
             registerChrono(JapaneseChronology.INSTANCE);
             registerChrono(MinguoChronology.INSTANCE);
             registerChrono(ThaiBuddhistChronology.INSTANCE);
 
+            // Register Chronologies from the ServiceLoader
+            @SuppressWarnings("rawtypes")
+            ServiceLoader<Chronology> loader =  ServiceLoader.load(Chronology.class, null);
+            for (Chronology chrono : loader) {
+                String id = chrono.getId();
+                if (id.equals("ISO") || registerChrono(chrono) != null) {
+                    // Log the attempt to replace an existing Chronology
+                    PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono");
+                    logger.warning("Ignoring duplicate Chronology, from ServiceLoader configuration "  + id);
+                }
+            }
+
             // finally, register IsoChronology to mark initialization is complete
             registerChrono(IsoChronology.INSTANCE);
             return true;
@@ -236,7 +308,7 @@
      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
      * which this factory converts to an instance of {@code Chronology}.
      * <p>
-     * The conversion will obtain the chronology using {@link Queries#chronology()}.
+     * The conversion will obtain the chronology using {@link TemporalQuery#chronology()}.
      * If the specified temporal object does not have a chronology, {@link IsoChronology} is returned.
      * <p>
      * This method matches the signature of the functional interface {@link TemporalQuery}
@@ -248,7 +320,7 @@
      */
     public static Chronology from(TemporalAccessor temporal) {
         Objects.requireNonNull(temporal, "temporal");
-        Chronology obj = temporal.query(Queries.chronology());
+        Chronology obj = temporal.query(TemporalQuery.chronology());
         return (obj != null ? obj : IsoChronology.INSTANCE);
     }
 
@@ -266,13 +338,16 @@
      * <p>
      * The {@code Locale} class also supports an extension mechanism that
      * can be used to identify a calendar system. The mechanism is a form
-     * of key-value pairs, where the calendar system has the key "ca".
+     * of key-value pairs, where the calendar system has the key "ca"
+     * and an optional variant key "cv".
      * For example, the locale "en-JP-u-ca-japanese" represents the English
      * language as used in Japan with the Japanese calendar system.
      * <p>
      * This method finds the desired calendar system by in a manner equivalent
      * to passing "ca" to {@link Locale#getUnicodeLocaleType(String)}.
      * If the "ca" key is not present, then {@code IsoChronology} is returned.
+     * The variant, if present, is appended to the "ca" value separated by  "-"
+     * and the concatenated value is used to find the calendar system by type.
      * <p>
      * Note that the behavior of this method differs from the older
      * {@link java.util.Calendar#getInstance(Locale)} method.
@@ -299,6 +374,10 @@
         if (type == null || "iso".equals(type) || "iso8601".equals(type)) {
             return IsoChronology.INSTANCE;
         }
+        String variant = locale.getUnicodeLocaleType("cv");
+        if (variant != null && !variant.isEmpty()) {
+            type = type + '-' + variant;
+        }
         // Not pre-defined; lookup by the type
         do {
             Chronology chrono = CHRONOS_BY_TYPE.get(type);
@@ -307,6 +386,16 @@
             }
             // If not found, do the initialization (once) and repeat the lookup
         } while (initCache());
+
+        // Look for a Chronology using ServiceLoader of the Thread's ContextClassLoader
+        // Application provided Chronologies must not be cached
+        @SuppressWarnings("rawtypes")
+        ServiceLoader<Chronology> loader = ServiceLoader.load(Chronology.class);
+        for (Chronology chrono : loader) {
+            if (type.equals(chrono.getCalendarType())) {
+                return chrono;
+            }
+        }
         throw new DateTimeException("Unknown calendar system: " + type);
     }
 
@@ -317,7 +406,8 @@
      * <p>
      * This returns a chronology based on either the ID or the type.
      * The {@link #getId() chronology ID} uniquely identifies the chronology.
-     * The {@link #getCalendarType() calendar system type} is defined by the LDML specification.
+     * The {@link #getCalendarType() calendar system type} is defined by the
+     * CLDR specification.
      * <p>
      * The chronology may be a system chronology or a chronology
      * provided by the application via ServiceLoader configuration.
@@ -379,7 +469,7 @@
      */
     public static Set<Chronology> getAvailableChronologies() {
         initCache();       // force initialization
-        HashSet<Chronology> chronos = new HashSet(CHRONOS_BY_ID.values());
+        HashSet<Chronology> chronos = new HashSet<>(CHRONOS_BY_ID.values());
 
         /// Add in Chronologies from the ServiceLoader configuration
         @SuppressWarnings("rawtypes")
@@ -406,9 +496,9 @@
      * @throws ClassCastException if the date-time cannot be cast to ChronoLocalDate
      *  or the chronology is not equal this Chronology
      */
-    ChronoLocalDate ensureChronoLocalDate(Temporal temporal) {
+    ChronoLocalDate<?> ensureChronoLocalDate(Temporal temporal) {
         @SuppressWarnings("unchecked")
-        ChronoLocalDate other = (ChronoLocalDate) temporal;
+        ChronoLocalDate<?> other = (ChronoLocalDate<?>) temporal;
         if (this.equals(other.getChronology()) == false) {
             throw new ClassCastException("Chronology mismatch, expected: " + getId() + ", actual: " + other.getChronology().getId());
         }
@@ -464,15 +554,16 @@
     public abstract String getId();
 
     /**
-     * Gets the calendar type of the underlying calendar system.
+     * Gets the calendar type of the calendar system.
      * <p>
-     * The calendar type is an identifier defined by the
-     * <em>Unicode Locale Data Markup Language (LDML)</em> specification.
-     * It can be used to lookup the {@code Chronology} using {@link #of(String)}.
-     * It can also be used as part of a locale, accessible via
-     * {@link Locale#getUnicodeLocaleType(String)} with the key 'ca'.
+     * The calendar type is an identifier defined by the CLDR and
+     * <em>Unicode Locale Data Markup Language (LDML)</em> specifications
+     * to uniquely identification a calendar.
+     * The {@code getCalendarType} is the concatenation of the CLDR calendar type
+     * and the variant, if applicable, is appended separated by "-".
+     * The calendar type is used to lookup the {@code Chronology} using {@link #of(String)}.
      *
-     * @return the calendar system type, null if the calendar is not defined by LDML
+     * @return the calendar system type, null if the calendar is not defined
      * @see #getId()
      */
     public abstract String getCalendarType();
@@ -488,8 +579,9 @@
      * @param dayOfMonth  the chronology day-of-month
      * @return the local date in this chronology, not null
      * @throws DateTimeException if unable to create the date
+     * @throws ClassCastException if the {@code era} is not of the correct type for the chronology
      */
-    public ChronoLocalDate date(Era era, int yearOfEra, int month, int dayOfMonth) {
+    public ChronoLocalDate<?> date(Era era, int yearOfEra, int month, int dayOfMonth) {
         return date(prolepticYear(era, yearOfEra), month, dayOfMonth);
     }
 
@@ -503,7 +595,7 @@
      * @return the local date in this chronology, not null
      * @throws DateTimeException if unable to create the date
      */
-    public abstract ChronoLocalDate date(int prolepticYear, int month, int dayOfMonth);
+    public abstract ChronoLocalDate<?> date(int prolepticYear, int month, int dayOfMonth);
 
     /**
      * Obtains a local date in this chronology from the era, year-of-era and
@@ -514,8 +606,9 @@
      * @param dayOfYear  the chronology day-of-year
      * @return the local date in this chronology, not null
      * @throws DateTimeException if unable to create the date
+     * @throws ClassCastException if the {@code era} is not of the correct type for the chronology
      */
-    public ChronoLocalDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
+    public ChronoLocalDate<?> dateYearDay(Era era, int yearOfEra, int dayOfYear) {
         return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
     }
 
@@ -528,7 +621,19 @@
      * @return the local date in this chronology, not null
      * @throws DateTimeException if unable to create the date
      */
-    public abstract ChronoLocalDate dateYearDay(int prolepticYear, int dayOfYear);
+    public abstract ChronoLocalDate<?> dateYearDay(int prolepticYear, int dayOfYear);
+
+    /**
+     * Obtains a local date in this chronology from the epoch-day.
+     * <p>
+     * The definition of {@link ChronoField#EPOCH_DAY EPOCH_DAY} is the same
+     * for all calendar systems, thus it can be used for conversion.
+     *
+     * @param epochDay  the epoch day
+     * @return the local date in this chronology, not null
+     * @throws DateTimeException if unable to create the date
+     */
+    public abstract ChronoLocalDate<?> dateEpochDay(long epochDay);
 
     //-----------------------------------------------------------------------
     /**
@@ -545,7 +650,7 @@
      * @return the current local date using the system clock and default time-zone, not null
      * @throws DateTimeException if unable to create the date
      */
-    public ChronoLocalDate dateNow() {
+    public ChronoLocalDate<?> dateNow() {
         return dateNow(Clock.systemDefaultZone());
     }
 
@@ -562,7 +667,7 @@
      * @return the current local date using the system clock, not null
      * @throws DateTimeException if unable to create the date
      */
-    public ChronoLocalDate dateNow(ZoneId zone) {
+    public ChronoLocalDate<?> dateNow(ZoneId zone) {
         return dateNow(Clock.system(zone));
     }
 
@@ -577,7 +682,7 @@
      * @return the current local date, not null
      * @throws DateTimeException if unable to create the date
      */
-    public ChronoLocalDate dateNow(Clock clock) {
+    public ChronoLocalDate<?> dateNow(Clock clock) {
         Objects.requireNonNull(clock, "clock");
         return date(LocalDate.now(clock));
     }
@@ -586,7 +691,7 @@
     /**
      * Obtains a local date in this chronology from another temporal object.
      * <p>
-     * This creates a date in this chronology based on the specified temporal.
+     * This obtains a date in this chronology based on the specified temporal.
      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
      * which this factory converts to an instance of {@code ChronoLocalDate}.
      * <p>
@@ -599,13 +704,14 @@
      * @param temporal  the temporal object to convert, not null
      * @return the local date in this chronology, not null
      * @throws DateTimeException if unable to create the date
+     * @see ChronoLocalDate#from(TemporalAccessor)
      */
-    public abstract ChronoLocalDate date(TemporalAccessor temporal);
+    public abstract ChronoLocalDate<?> date(TemporalAccessor temporal);
 
     /**
      * Obtains a local date-time in this chronology from another temporal object.
      * <p>
-     * This creates a date-time in this chronology based on the specified temporal.
+     * This obtains a date-time in this chronology based on the specified temporal.
      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
      * which this factory converts to an instance of {@code ChronoLocalDateTime}.
      * <p>
@@ -621,6 +727,7 @@
      * @param temporal  the temporal object to convert, not null
      * @return the local date-time in this chronology, not null
      * @throws DateTimeException if unable to create the date-time
+     * @see ChronoLocalDateTime#from(TemporalAccessor)
      */
     public ChronoLocalDateTime<?> localDateTime(TemporalAccessor temporal) {
         try {
@@ -633,7 +740,7 @@
     /**
      * Obtains a {@code ChronoZonedDateTime} in this chronology from another temporal object.
      * <p>
-     * This creates a zoned date-time in this chronology based on the specified temporal.
+     * This obtains a zoned date-time in this chronology based on the specified temporal.
      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
      * which this factory converts to an instance of {@code ChronoZonedDateTime}.
      * <p>
@@ -652,6 +759,7 @@
      * @param temporal  the temporal object to convert, not null
      * @return the zoned date-time in this chronology, not null
      * @throws DateTimeException if unable to create the date-time
+     * @see ChronoZonedDateTime#from(TemporalAccessor)
      */
     public ChronoZonedDateTime<?> zonedDateTime(TemporalAccessor temporal) {
         try {
@@ -661,6 +769,7 @@
                 return zonedDateTime(instant, zone);
 
             } catch (DateTimeException ex1) {
+                @SuppressWarnings("rawtypes")
                 ChronoLocalDateTimeImpl cldt = ensureChronoLocalDateTime(localDateTime(temporal));
                 return ChronoZonedDateTimeImpl.ofBest(cldt, zone, null);
             }
@@ -672,7 +781,7 @@
     /**
      * Obtains a {@code ChronoZonedDateTime} in this chronology from an {@code Instant}.
      * <p>
-     * This creates a zoned date-time with the same instant as that specified.
+     * This obtains a zoned date-time with the same instant as that specified.
      *
      * @param instant  the instant to create the date-time from, not null
      * @param zone  the time-zone, not null
@@ -703,11 +812,17 @@
      * Calculates the proleptic-year given the era and year-of-era.
      * <p>
      * This combines the era and year-of-era into the single proleptic-year field.
+     * <p>
+     * If the chronology makes active use of eras, such as {@code JapaneseChronology}
+     * then the year-of-era will be validated against the era.
+     * For other chronologies, validation is optional.
      *
      * @param era  the era of the correct type for the chronology, not null
      * @param yearOfEra  the chronology year-of-era
      * @return the proleptic-year
-     * @throws DateTimeException if unable to convert
+     * @throws DateTimeException if unable to convert to a proleptic-year,
+     *  such as if the year is invalid for the era
+     * @throws ClassCastException if the {@code era} is not of the correct type for the chronology
      */
     public abstract int prolepticYear(Era era, int yearOfEra);
 
@@ -775,24 +890,175 @@
      * @return the text value of the chronology, not null
      */
     public String getDisplayName(TextStyle style, Locale locale) {
-        return new DateTimeFormatterBuilder().appendChronologyText(style).toFormatter(locale).format(new TemporalAccessor() {
+        return new DateTimeFormatterBuilder().appendChronologyText(style).toFormatter(locale).format(toTemporal());
+    }
+
+    /**
+     * Converts this chronology to a {@code TemporalAccessor}.
+     * <p>
+     * A {@code Chronology} can be fully represented as a {@code TemporalAccessor}.
+     * However, the interface is not implemented by this class as most of the
+     * methods on the interface have no meaning to {@code Chronology}.
+     * <p>
+     * The returned temporal has no supported fields, with the query method
+     * supporting the return of the chronology using {@link TemporalQuery#chronology()}.
+     *
+     * @return a temporal equivalent to this chronology, not null
+     */
+    private TemporalAccessor toTemporal() {
+        return new TemporalAccessor() {
             @Override
             public boolean isSupported(TemporalField field) {
                 return false;
             }
             @Override
             public long getLong(TemporalField field) {
-                throw new DateTimeException("Unsupported field: " + field);
+                throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
             }
             @SuppressWarnings("unchecked")
             @Override
             public <R> R query(TemporalQuery<R> query) {
-                if (query == Queries.chronology()) {
+                if (query == TemporalQuery.chronology()) {
                     return (R) Chronology.this;
                 }
                 return TemporalAccessor.super.query(query);
             }
-        });
+        };
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Resolves parsed {@code ChronoField} values into a date during parsing.
+     * <p>
+     * Most {@code TemporalField} implementations are resolved using the
+     * resolve method on the field. By contrast, the {@code ChronoField} class
+     * defines fields that only have meaning relative to the chronology.
+     * As such, {@code ChronoField} date fields are resolved here in the
+     * context of a specific chronology.
+     * <p>
+     * The default implementation is suitable for most calendar systems.
+     * If {@link ChronoField#YEAR_OF_ERA} is found without an {@link ChronoField#ERA}
+     * then the last era in {@link #eras()} is used.
+     * The implementation assumes a 7 day week, that the first day-of-month
+     * has the value 1, and that first day-of-year has the value 1.
+     *
+     * @param fieldValues  the map of fields to values, which can be updated, not null
+     * @param resolverStyle  the requested type of resolve, not null
+     * @return the resolved date, null if insufficient information to create a date
+     * @throws DateTimeException if the date cannot be resolved, typically
+     *  because of a conflict in the input data
+     */
+    public ChronoLocalDate<?> resolveDate(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
+        // check epoch-day before inventing era
+        if (fieldValues.containsKey(EPOCH_DAY)) {
+            return dateEpochDay(fieldValues.remove(EPOCH_DAY));
+        }
+
+        // fix proleptic month before inventing era
+        Long pMonth = fieldValues.remove(PROLEPTIC_MONTH);
+        if (pMonth != null) {
+            // first day-of-month is likely to be safest for setting proleptic-month
+            // cannot add to year zero, as not all chronologies have a year zero
+            ChronoLocalDate<?> chronoDate = dateNow()
+                    .with(DAY_OF_MONTH, 1).with(PROLEPTIC_MONTH, pMonth);
+            addFieldValue(fieldValues, MONTH_OF_YEAR, chronoDate.get(MONTH_OF_YEAR));
+            addFieldValue(fieldValues, YEAR, chronoDate.get(YEAR));
+        }
+
+        // invent era if necessary to resolve year-of-era
+        Long yoeLong = fieldValues.remove(YEAR_OF_ERA);
+        if (yoeLong != null) {
+            Long eraLong = fieldValues.remove(ERA);
+            int yoe = range(YEAR_OF_ERA).checkValidIntValue(yoeLong, YEAR_OF_ERA);
+            if (eraLong != null) {
+                Era eraObj = eraOf(Math.toIntExact(eraLong));
+                addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe));
+            } else if (fieldValues.containsKey(YEAR)) {
+                int year = range(YEAR).checkValidIntValue(fieldValues.get(YEAR), YEAR);
+                ChronoLocalDate<?> chronoDate = dateYearDay(year, 1);
+                addFieldValue(fieldValues, YEAR, prolepticYear(chronoDate.getEra(), yoe));
+            } else {
+                List<Era> eras = eras();
+                if (eras.isEmpty()) {
+                    addFieldValue(fieldValues, YEAR, yoe);
+                } else {
+                    Era eraObj = eras.get(eras.size() - 1);
+                    addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe));
+                }
+            }
+        }
+
+        // build date
+        if (fieldValues.containsKey(YEAR)) {
+            if (fieldValues.containsKey(MONTH_OF_YEAR)) {
+                if (fieldValues.containsKey(DAY_OF_MONTH)) {
+                    int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
+                    int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
+                    int dom = range(DAY_OF_MONTH).checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
+                    return date(y, moy, dom);
+                }
+                if (fieldValues.containsKey(ALIGNED_WEEK_OF_MONTH)) {
+                    if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_MONTH)) {
+                        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
+                        int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
+                        int aw = range(ALIGNED_WEEK_OF_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), ALIGNED_WEEK_OF_MONTH);
+                        int ad = range(ALIGNED_DAY_OF_WEEK_IN_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), ALIGNED_DAY_OF_WEEK_IN_MONTH);
+                        ChronoLocalDate<?> chronoDate = date(y, moy, 1);
+                        return chronoDate.plus((aw - 1) * 7 + (ad - 1), ChronoUnit.DAYS);
+                    }
+                    if (fieldValues.containsKey(DAY_OF_WEEK)) {
+                        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
+                        int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
+                        int aw = range(ALIGNED_WEEK_OF_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), ALIGNED_WEEK_OF_MONTH);
+                        int dow = range(DAY_OF_WEEK).checkValidIntValue(fieldValues.remove(DAY_OF_WEEK), DAY_OF_WEEK);
+                        ChronoLocalDate<?> chronoDate = date(y, moy, 1);
+                        return chronoDate.plus((aw - 1) * 7, ChronoUnit.DAYS).with(nextOrSame(DayOfWeek.of(dow)));
+                    }
+                }
+            }
+            if (fieldValues.containsKey(DAY_OF_YEAR)) {
+                int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
+                int doy = range(DAY_OF_YEAR).checkValidIntValue(fieldValues.remove(DAY_OF_YEAR), DAY_OF_YEAR);
+                return dateYearDay(y, doy);
+            }
+            if (fieldValues.containsKey(ALIGNED_WEEK_OF_YEAR)) {
+                if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_YEAR)) {
+                    int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
+                    int aw = range(ALIGNED_WEEK_OF_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), ALIGNED_WEEK_OF_YEAR);
+                    int ad = range(ALIGNED_DAY_OF_WEEK_IN_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), ALIGNED_DAY_OF_WEEK_IN_YEAR);
+                    ChronoLocalDate<?> chronoDate = dateYearDay(y, 1);
+                    return chronoDate.plus((aw - 1) * 7 + (ad - 1), ChronoUnit.DAYS);
+                }
+                if (fieldValues.containsKey(DAY_OF_WEEK)) {
+                    int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
+                    int aw = range(ALIGNED_WEEK_OF_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), ALIGNED_WEEK_OF_YEAR);
+                    int dow = range(DAY_OF_WEEK).checkValidIntValue(fieldValues.remove(DAY_OF_WEEK), DAY_OF_WEEK);
+                    ChronoLocalDate<?> chronoDate = dateYearDay(y, 1);
+                    return chronoDate.plus((aw - 1) * 7, ChronoUnit.DAYS).with(nextOrSame(DayOfWeek.of(dow)));
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Adds a field-value pair to the map, checking for conflicts.
+     * <p>
+     * If the field is not already present, then the field-value pair is added to the map.
+     * If the field is already present and it has the same value as that specified, no action occurs.
+     * If the field is already present and it has a different value to that specified, then
+     * an exception is thrown.
+     *
+     * @param field  the field to add, not null
+     * @param value  the value to add, not null
+     * @throws DateTimeException if the field is already present with a different value
+     */
+    void addFieldValue(Map<TemporalField, Long> fieldValues, ChronoField field, long value) {
+        Long old = fieldValues.get(field);  // check first for better error message
+        if (old != null && old.longValue() != value) {
+            throw new DateTimeException("Conflict found: " + field + " " + old + " differs from " + field + " " + value);
+        }
+        fieldValues.put(field, value);
     }
 
     //-----------------------------------------------------------------------
@@ -861,16 +1127,16 @@
 
     //-----------------------------------------------------------------------
     /**
-     * Writes the object using a
-     * <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
+     * Writes the Chronology using a
+     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
      * <pre>
-     *  out.writeByte(7);  // identifies this as a Chronology
-     * out.writeUTF(chronoId);
+     *  out.writeByte(1);  // identifies this as a Chronology
+     *  out.writeUTF(getId());
      * </pre>
      *
      * @return the instance of {@code Ser}, not null
      */
-    private Object writeReplace() {
+    protected Object writeReplace() {
         return new Ser(Ser.CHRONO_TYPE, this);
     }
 
--- a/src/share/classes/java/time/chrono/Era.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/chrono/Era.java	Fri Apr 12 10:42:50 2013 -0700
@@ -65,10 +65,10 @@
 import static java.time.temporal.ChronoUnit.ERAS;
 
 import java.time.DateTimeException;
+import java.time.temporal.UnsupportedTemporalTypeException;
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.TextStyle;
 import java.time.temporal.ChronoField;
-import java.time.temporal.Queries;
 import java.time.temporal.Temporal;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjuster;
@@ -120,55 +120,6 @@
      */
     int getValue();
 
-    /**
-     * Gets the chronology of this era.
-     * <p>
-     * The {@code Chronology} represents the calendar system in use.
-     * This always returns the standard form of the chronology.
-     *
-     * @return the chronology, not null
-     */
-    Chronology getChronology();
-
-    //-----------------------------------------------------------------------
-    /**
-     * Obtains a date in this era given the year-of-era, month, and day.
-     * <p>
-     * This era is combined with the given date fields to form a date.
-     * The year specified must be the year-of-era.
-     * Methods to create a date from the proleptic-year are on {@code Chronology}.
-     * This always uses the standard form of the chronology.
-     * <p>
-     * This default implementation invokes the factory method on {@link Chronology}.
-     *
-     * @param yearOfEra  the calendar system year-of-era
-     * @param month  the calendar system month-of-year
-     * @param day  the calendar system day-of-month
-     * @return a local date based on this era and the specified year-of-era, month and day
-     */
-    public default ChronoLocalDate date(int yearOfEra, int month, int day) {
-        return getChronology().date(this, yearOfEra, month, day);
-    }
-
-
-    /**
-     * Obtains a date in this era given year-of-era and day-of-year fields.
-     * <p>
-     * This era is combined with the given date fields to form a date.
-     * The year specified must be the year-of-era.
-     * Methods to create a date from the proleptic-year are on {@code Chronology}.
-     * This always uses the standard form of the chronology.
-     * <p>
-     * This default implementation invokes the factory method on {@link Chronology}.
-     *
-     * @param yearOfEra  the calendar system year-of-era
-     * @param dayOfYear  the calendar system day-of-year
-     * @return a local date based on this era and the specified year-of-era and day-of-year
-     */
-    public default ChronoLocalDate dateYearDay(int yearOfEra, int dayOfYear) {
-        return getChronology().dateYearDay(this, yearOfEra, dayOfYear);
-    }
-
     //-----------------------------------------------------------------------
     /**
      * Checks if the specified field is supported.
@@ -190,7 +141,7 @@
      * @return true if the field is supported on this era, false if not
      */
     @Override
-    public default boolean isSupported(TemporalField field) {
+    default boolean isSupported(TemporalField field) {
         if (field instanceof ChronoField) {
             return field == ERA;
         }
@@ -207,19 +158,23 @@
      * <p>
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@code ERA} field returns the range.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
      * passing {@code this} as the argument.
      * Whether the range can be obtained is determined by the field.
+     * <p>
+     * The default implementation must return a range for {@code ERA} from
+     * zero to one, suitable for two era calendar systems such as ISO.
      *
      * @param field  the field to query the range for, not null
      * @return the range of valid values for the field, not null
      * @throws DateTimeException if the range for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the unit is not supported
      */
     @Override  // override for Javadoc
-    public default ValueRange range(TemporalField field) {
+    default ValueRange range(TemporalField field) {
         return TemporalAccessor.super.range(field);
     }
 
@@ -233,7 +188,7 @@
      * <p>
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@code ERA} field returns the value of the era.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -242,15 +197,18 @@
      *
      * @param field  the field to get, not null
      * @return the value for the field
-     * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws DateTimeException if a value for the field cannot be obtained or
+     *         the value is outside the range of valid values for the field
+     * @throws UnsupportedTemporalTypeException if the field is not supported or
+     *         the range of values exceeds an {@code int}
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override  // override for Javadoc and performance
-    public default int get(TemporalField field) {
+    default int get(TemporalField field) {
         if (field == ERA) {
             return getValue();
         }
-        return range(field).checkValidIntValue(getLong(field), field);
+        return TemporalAccessor.super.get(field);
     }
 
     /**
@@ -262,7 +220,7 @@
      * <p>
      * If the field is a {@link ChronoField} then the query is implemented here.
      * The {@code ERA} field returns the value of the era.
-     * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
+     * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
      * <p>
      * If the field is not a {@code ChronoField}, then the result of this method
      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
@@ -272,14 +230,15 @@
      * @param field  the field to get, not null
      * @return the value for the field
      * @throws DateTimeException if a value for the field cannot be obtained
+     * @throws UnsupportedTemporalTypeException if the field is not supported
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
-    public default long getLong(TemporalField field) {
+    default long getLong(TemporalField field) {
         if (field == ERA) {
             return getValue();
         } else if (field instanceof ChronoField) {
-            throw new DateTimeException("Unsupported field: " + field.getName());
+            throw new UnsupportedTemporalTypeException("Unsupported field: " + field.getName());
         }
         return field.getFrom(this);
     }
@@ -305,10 +264,8 @@
      */
     @SuppressWarnings("unchecked")
     @Override
-    public default <R> R query(TemporalQuery<R> query) {
-        if (query == Queries.chronology()) {
-            return (R) getChronology();
-        } else if (query == Queries.precision()) {
+    default <R> R query(TemporalQuery<R> query) {
+        if (query == TemporalQuery.precision()) {
             return (R) ERAS;
         }
         return TemporalAccessor.super.query(query);
@@ -339,7 +296,7 @@
      * @throws ArithmeticException if numeric overflow occurs
      */
     @Override
-    public default Temporal adjustInto(Temporal temporal) {
+    default Temporal adjustInto(Temporal temporal) {
         return temporal.with(ERA, getValue());
     }
 
@@ -359,7 +316,7 @@
      * @param locale  the locale to use, not null
      * @return the text value of the era, not null
      */
-    public default String getDisplayName(TextStyle style, Locale locale) {
+    default String getDisplayName(TextStyle style, Locale locale) {
         return new DateTimeFormatterBuilder().appendText(ERA, style).toFormatter(locale).format(this);
     }
 
--- a/src/share/classes/java/time/chrono/HijrahChronology.java	Thu Apr 11 21:03:24 2013 -0700
+++ b/src/share/classes/java/time/chrono/HijrahChronology.java	Fri Apr 12 10:42:50 2013 -0700
@@ -59,9 +59,13 @@
 
 import static java.time.temporal.ChronoField.EPOCH_DAY;
 
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.Serializable;
-import java.text.ParseException;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
 import java.time.Clock;
 import java.time.DateTimeException;
 import java.time.Instant;
@@ -73,106 +77,135 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+
+import sun.util.logging.PlatformLogger;
 
 /**
- * The Hijrah calendar system.
+ * The Hijrah calendar is a lunar calendar supporting Islamic calendars.
  * <p>
- * This chronology defines the rules of the Hijrah calendar system.
+ * The HijrahChronology follows the rules of the Hijrah calendar system. The Hijrah
+ * calendar has several variants based on differences in when the new moon is
+ * determined to have occurred and where the observation is made.
+ * In some variants the length of each month is
+ * computed algorithmically from the astronomical data for the moon and earth and
+ * in others the length of the month is determined by an authorized sighting
+ * of the new moon. For the algorithmically based calendars the calendar
+ * can project into the future.
+ * For sighting based calendars only historical data from past
+ * sightings is available.
  * <p>
- * The implementation follows the Freeman-Grenville algorithm (*1) and has following features.
- * <p><ul>
- * <li>A year has 12 months.</li>
- * <li>Over a cycle of 30 years there are 11 leap years.</li>
- * <li>There are 30 days in month number 1, 3, 5, 7, 9, and 11,
- * and 29 days in month number 2, 4, 6, 8, 10, and 12.</li>
- * <li>In a leap year month 12 has 30 days.</li>
- * <li>In a 30 year cycle, year 2, 5, 7, 10, 13, 16, 18, 21, 24,
- * 26, and 29 are leap years.</li>
- * <li>Total of 10631 days in a 30 years cycle.</li>
- * </ul><p>
- * <P>
- * The table shows the features described above.
- * <blockquote>
- * <table border="1">
- *   <caption>Hijrah Calendar Months</caption>
- *   <tbody>
- *     <tr>
- *       <th># of month</th>
- *       <th>Name of month</th>
- *       <th>Number of days</th>
- *     </tr>
- *     <tr>
- *       <td>1</td>
- *       <td>Muharram</td>
- *       <td>30</td>
- *     </tr>
- *     <tr>
- *       <td>2</td>
- *       <td>Safar</td>
- *       <td>29</td>
- *     </tr>
- *     <tr>
- *       <td>3</td>
- *       <td>Rabi'al-Awwal</td>
- *       <td>30</td>
- *     </tr>
- *     <tr>
- *       <td>4</td>
- *       <td>Rabi'ath-Thani</td>
- *       <td>29</td>
- *     </tr>
- *     <tr>
- *       <td>5</td>
- *       <td>Jumada l-Ula</td>
- *       <td>30</td>
- *     </tr>
- *     <tr>
- *       <td>6</td>
- *       <td>Jumada t-Tania</td>
- *       <td>29</td>
- *     </tr>
- *     <tr>
- *       <td>7</td>
- *       <td>Rajab</td>
- *       <td>30</td>
- *     </tr>
- *     <tr>
- *       <td>8</td>
- *       <td>Sha`ban</td>
- *       <td>29</td>
- *     </tr>
- *     <tr>
- *       <td>9</td>
- *       <td>Ramadan</td>
- *       <td>30</td>
- *     </tr>
- *     <tr>
- *       <td>10</td>
- *       <td>Shawwal</td>
- *       <td>29</td>
- *     </tr>
- *     <tr>
- *       <td>11</td>
- *       <td>Dhu 'l-Qa`da</td>
- *       <td>30</td>
- *     </tr>
- *     <tr>
- *       <td>12</td>
- *       <td>Dhu 'l-Hijja</td>
- *       <td>29, but 30 days in years 2, 5, 7, 10,<br>
- * 13, 16, 18, 21, 24, 26, and 29</td>
- *     </tr>
- *   </tbody>
+ * The length of each month is 29 or 30 days.
+ * Ordinary years have 354 days; leap years have 355 days.
+ *
+ * <p>
+ * CLDR and LDML identify variants:
+ * <table cellpadding="2" summary="Variants of Hijrah Calendars">
+ * <thead>
+ * <tr class="tableSubHeadingColor">
+ * <th class="colFirst" align="left" >Chronology ID</th>
+ * <th class="colFirst" align="left" >Calendar Type</th>
+ * <th class="colFirst" align="left" >Locale extension, see {@link java.util.Locale}</th>
+ * <th class="colLast" align="left" >Description</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr class="altColor">
+ * <td>Hijrah-umalqura</td>
+ * <td>islamic-umalqura</td>
+ * <td>ca-islamic-cv-umalqura</td>
+ * <td>Islamic - Umm Al-Qura calendar of Saudi Arabia</td>
+ * </tr>
+ * </tbody>
  * </table>
- * </blockquote>
+ * <p>Additional variants may be available through {@link Chronology#getAvailableChronologies()}.
+ *
+ * <p>Example</p>
  * <p>
- * (*1) The algorithm is taken from the book,
- * The Muslim and Christian Calendars by G.S.P. Freeman-Grenville.
- * <p>
+ * Selecting the chronology from the locale uses {@link Chronology#ofLocale}
+ * to find the Chronology based on Locale supported BCP 47 extension mechanism
+ * to request a specific calendar ("ca") and variant ("cv"). For example,
+ * </p>
+ * <pre>
+ *      Locale locale = Locale.forLanguageTag("en-US-u-ca-islamic-cv-umalqura");
+ *      Chronology chrono = Chronology.ofLocale(locale);
+ * </pre>
  *
  * <h3>Specification for implementors</h3>
  * This class is immutable and thread-safe.
+ * <h3>Implementation Note for Hijrah Calendar Variant Configuration</h3>
+ * Each Hijrah variant is configured individually. Each variant is defined by a
+ * property resource that defines the {@code ID}, the {@code calendar type},
+ * the start of the calendar, the alignment with the
+ * ISO calendar, and the length of each month for a range of years.
+ * The variants are identified in the {@code calendars.properties} file.
+ * The new properties are prefixed with {@code "calendars.hijrah."}:
+ * <table cellpadding="2" border="0" summary="Configuration of Hijrah Calendar Variants">
+ * <thead>
+ * <tr class="tableSubHeadingColor">
+ * <th class="colFirst" align="left">Property Name</th>
+ * <th class="colFirst" align="left">Property value</th>
+ * <th class="colLast" align="left">Description </th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr class="altColor">
+ * <td>calendars.hijrah.{ID}</td>
+ * <td>The property resource defining the {@code {ID}} variant</td>
+ * <td>The property resource is located with the {@code calendars.properties} file</td>
+ * </tr>
+ * <tr class="rowColor">
+ * <td>calendars.hijrah.{ID}.type</td>
+ * <td>The