Permalink
Browse files

Add appendZoneRegionId() to formatter

This handles ZoneOffset now being a ZoneId subclass
  • Loading branch information...
1 parent f8dbf78 commit 29e9e66f9e1eea7ba75d19177fae5eb9ed745bf5 @jodastephen jodastephen committed Dec 2, 2012
@@ -617,15 +617,34 @@ public DateTimeFormatterBuilder appendOffset(String pattern, String noOffsetText
//-----------------------------------------------------------------------
/**
- * Appends the time-zone ID, such as 'Europe/Paris', to the formatter.
+ * Appends the time-zone ID, such as 'Europe/Paris' or '+02:00', to the formatter.
* <p>
- * The time-zone ID will be output during a print.
+ * A {@link ZoneId} can be either a {@code ZoneOffset} or an ID of a region
+ * such as 'America/New_York'. This prints and parses both types.
* If the zone cannot be obtained then an exception will be thrown.
*
* @return this, for chaining, not null
+ * @see #appendZoneRegionId()
*/
public DateTimeFormatterBuilder appendZoneId() {
- appendInternal(new ZoneIdPrinterParser(null));
+ appendInternal(new ZoneIdPrinterParser(false));
+ return this;
+ }
+
+ /**
+ * Appends the time-zone region ID, such as 'Europe/Paris', to the formatter,
+ * printing nothing if the zone ID is a {@code ZoneOffset}.
+ * <p>
+ * A {@link ZoneId} can be either a {@code ZoneOffset} or an ID of a region
+ * such as 'America/New_York'. This only prints if the ID is a region.
+ * Both types are parsed, however the parsing of the offset is optional.
+ * If the zone cannot be obtained then an exception will be thrown.
+ *
+ * @return this, for chaining, not null
+ * @see #appendZoneId()
+ */
+ public DateTimeFormatterBuilder appendZoneRegionId() {
+ appendInternal(new ZoneIdPrinterParser(true));
return this;
}
@@ -646,8 +665,7 @@ public DateTimeFormatterBuilder appendZoneId() {
* @return this, for chaining, not null
*/
public DateTimeFormatterBuilder appendZoneText(TextStyle textStyle) {
- Objects.requireNonNull(textStyle, "textStyle");
- appendInternal(new ZoneIdPrinterParser(textStyle));
+ appendInternal(new ZoneTextPrinterParser(textStyle));
return this;
}
@@ -2414,13 +2432,13 @@ public String toString() {
/**
* Prints or parses a zone ID.
*/
- static final class ZoneIdPrinterParser implements DateTimePrinterParser {
- /** The text style to output, null means the ID. */
+ static final class ZoneTextPrinterParser implements DateTimePrinterParser {
+ // TODO: remove this as it is incomplete
+ /** The text style to output. */
private final TextStyle textStyle;
- ZoneIdPrinterParser(TextStyle textStyle) {
- // validated by caller
- this.textStyle = textStyle;
+ ZoneTextPrinterParser(TextStyle textStyle) {
+ this.textStyle = Objects.requireNonNull(textStyle, "textStyle");
}
//-----------------------------------------------------------------------
@@ -2430,12 +2448,41 @@ public boolean print(DateTimePrintContext context, StringBuilder buf) {
if (zone == null) {
return false;
}
- if (textStyle == null) {
- buf.append(zone.getId());
- } else {
- // TODO: fix getText(textStyle, context.getLocale())
- buf.append(zone.getId()); // TODO: Use symbols
+ // TODO: fix getText(textStyle, context.getLocale())
+ buf.append(zone.getId()); // TODO: Use symbols
+ return true;
+ }
+
+ @Override
+ public int parse(DateTimeParseContext context, CharSequence text, int position) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String toString() {
+ return "ZoneText(" + textStyle + ")";
+ }
+ }
+
+ //-----------------------------------------------------------------------
+ /**
+ * Prints or parses a zone ID.
+ */
+ static final class ZoneIdPrinterParser implements DateTimePrinterParser {
+ private final boolean regionOnly;
+
+ ZoneIdPrinterParser(boolean regionOnly) {
+ this.regionOnly = regionOnly;
+ }
+
+ //-----------------------------------------------------------------------
+ @Override
+ public boolean print(DateTimePrintContext context, StringBuilder buf) {
+ ZoneId zone = context.getValue(Query.ZONE_ID);
+ if (zone == null || (regionOnly && zone instanceof ZoneOffset)) {
+ return false;
}
+ buf.append(zone.getId());
return true;
}
@@ -2619,10 +2666,7 @@ private static SubstringTree prepareParser(Set<String> availableIDs) {
//-----------------------------------------------------------------------
@Override
public String toString() {
- if (textStyle == null) {
- return "ZoneId()";
- }
- return "ZoneText(" + textStyle + ")";
+ return (regionOnly ? "ZoneRegionId()" : "ZoneId()");
}
}
@@ -601,6 +601,7 @@ public static DateTimeFormatter isoOffsetDateTime() {
* The format consists of:
* <p><ul>
* <li>The {@link #isoOffsetDateTime()}
+ * <li>If the zone ID is not available or is a {@code ZoneOffset} then the format is complete.
* <li>An open square bracket '['.
* <li>The {@link ZoneId#getId() zone ID}. This is not part of the ISO-8601 standard.
* <li>A close square bracket ']'.
@@ -617,9 +618,9 @@ public static DateTimeFormatter isoZonedDateTime() {
static {
ISO_ZONED_DATE_TIME = new DateTimeFormatterBuilder()
.append(ISO_OFFSET_DATE_TIME)
- .optionalStart() // TODO: remove
+ .optionalStart()
.appendLiteral('[')
- .appendZoneId()
+ .appendZoneRegionId()
.appendLiteral(']')
.toFormatter();
}
@@ -639,7 +640,7 @@ public static DateTimeFormatter isoZonedDateTime() {
* <li>If the offset is not available to print/parse then the format is complete.
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
* they will be handled even though this is not part of the ISO-8601 standard.
- * <li>If the zone is not available to print/parse then the format is complete.
+ * <li>If the zone ID is not available or is a {@code ZoneOffset} then the format is complete.
* <li>An open square bracket '['.
* <li>The {@link ZoneId#getId() zone ID}. This is not part of the ISO-8601 standard.
* <li>A close square bracket ']'.
@@ -662,7 +663,7 @@ public static DateTimeFormatter isoDateTime() {
.appendOffsetId()
.optionalStart()
.appendLiteral('[')
- .appendZoneId()
+ .appendZoneRegionId()
.appendLiteral(']')
.toFormatter();
}
@@ -682,21 +682,25 @@ public void test_parse_isoOffsetDateTime(
{2008, 6, 30, 11, 5, 30, 500000000, null, null, null, DateTimeException.class},
{2008, 6, 30, 11, 5, 30, 1, null, null, null, DateTimeException.class},
- {2008, 6, 30, 11, 5, null, null, "+01:00", null, null, DateTimeException.class},
- {2008, 6, 30, 11, 5, 30, null, "+01:00", null, null, DateTimeException.class},
- {2008, 6, 30, 11, 5, 30, 500000000, "+01:00", null, null, DateTimeException.class},
- {2008, 6, 30, 11, 5, 30, 1, "+01:00", null, null, DateTimeException.class},
+ // allow OffsetDateTime (no harm comes of this AFAICT)
+ {2008, 6, 30, 11, 5, null, null, "+01:00", null, "2008-06-30T11:05+01:00", null},
+ {2008, 6, 30, 11, 5, 30, null, "+01:00", null, "2008-06-30T11:05:30+01:00", null},
+ {2008, 6, 30, 11, 5, 30, 500000000, "+01:00", null, "2008-06-30T11:05:30.5+01:00", null},
+ {2008, 6, 30, 11, 5, 30, 1, "+01:00", null, "2008-06-30T11:05:30.000000001+01:00", null},
+ // ZonedDateTime with ZoneId of ZoneOffset
{2008, 6, 30, 11, 5, null, null, "+01:00", "+01:00", "2008-06-30T11:05+01:00", null},
{2008, 6, 30, 11, 5, 30, null, "+01:00", "+01:00", "2008-06-30T11:05:30+01:00", null},
{2008, 6, 30, 11, 5, 30, 500000000, "+01:00", "+01:00", "2008-06-30T11:05:30.5+01:00", null},
{2008, 6, 30, 11, 5, 30, 1, "+01:00", "+01:00", "2008-06-30T11:05:30.000000001+01:00", null},
+ // ZonedDateTime with ZoneId of ZoneRegion
{2008, 6, 30, 11, 5, null, null, "+01:00", "Europe/Paris", "2008-06-30T11:05+01:00[Europe/Paris]", null},
{2008, 6, 30, 11, 5, 30, null, "+01:00", "Europe/Paris", "2008-06-30T11:05:30+01:00[Europe/Paris]", null},
{2008, 6, 30, 11, 5, 30, 500000000, "+01:00", "Europe/Paris", "2008-06-30T11:05:30.5+01:00[Europe/Paris]", null},
{2008, 6, 30, 11, 5, 30, 1, "+01:00", "Europe/Paris", "2008-06-30T11:05:30.000000001+01:00[Europe/Paris]", null},
+ // offset required
{2008, 6, 30, 11, 5, null, null, null, "Europe/Paris", null, DateTimeException.class},
{2008, 6, 30, 11, 5, 30, null, null, "Europe/Paris", null, DateTimeException.class},
{2008, 6, 30, 11, 5, 30, 500000000, null, "Europe/Paris", null, DateTimeException.class},
@@ -731,7 +735,11 @@ public void test_parse_isoZonedDateTime(
String input, Class<?> invalid) {
if (input != null) {
DateTimeBuilder expected = createDateTime(year, month, day, hour, min, sec, nano);
- buildCalendrical(expected, offsetId, zoneId);
+ if (offsetId.equals(zoneId)) {
+ buildCalendrical(expected, offsetId, null);
+ } else {
+ buildCalendrical(expected, offsetId, zoneId);
+ }
assertParseMatch(DateTimeFormatters.isoZonedDateTime().parseToBuilder(input, new ParsePosition(0)), expected);
}
}
@@ -742,23 +750,23 @@ public void test_parse_isoZonedDateTime(
@DataProvider(name="sample_isoDateTime")
Object[][] provider_sample_isoDateTime() {
return new Object[][]{
-// {2008, null, null, null, null, null, null, null, null, null, DateTimeException.class},
-// {null, 6, null, null, null, null, null, null, null, null, DateTimeException.class},
-// {null, null, 30, null, null, null, null, null, null, null, DateTimeException.class},
-// {null, null, null, 11, null, null, null, null, null, null, DateTimeException.class},
-// {null, null, null, null, 5, null, null, null, null, null, DateTimeException.class},
-// {null, null, null, null, null, null, null, "+01:00", null, null, DateTimeException.class},
-// {null, null, null, null, null, null, null, null, "Europe/Paris", null, DateTimeException.class},
-// {2008, 6, 30, 11, null, null, null, null, null, null, DateTimeException.class},
-// {2008, 6, 30, null, 5, null, null, null, null, null, DateTimeException.class},
-// {2008, 6, null, 11, 5, null, null, null, null, null, DateTimeException.class},
-// {2008, null, 30, 11, 5, null, null, null, null, null, DateTimeException.class},
-// {null, 6, 30, 11, 5, null, null, null, null, null, DateTimeException.class},
-//
-// {2008, 6, 30, 11, 5, null, null, null, null, "2008-06-30T11:05", null},
-// {2008, 6, 30, 11, 5, 30, null, null, null, "2008-06-30T11:05:30", null},
-// {2008, 6, 30, 11, 5, 30, 500000000, null, null, "2008-06-30T11:05:30.5", null},
-// {2008, 6, 30, 11, 5, 30, 1, null, null, "2008-06-30T11:05:30.000000001", null},
+ {2008, null, null, null, null, null, null, null, null, null, DateTimeException.class},
+ {null, 6, null, null, null, null, null, null, null, null, DateTimeException.class},
+ {null, null, 30, null, null, null, null, null, null, null, DateTimeException.class},
+ {null, null, null, 11, null, null, null, null, null, null, DateTimeException.class},
+ {null, null, null, null, 5, null, null, null, null, null, DateTimeException.class},
+ {null, null, null, null, null, null, null, "+01:00", null, null, DateTimeException.class},
+ {null, null, null, null, null, null, null, null, "Europe/Paris", null, DateTimeException.class},
+ {2008, 6, 30, 11, null, null, null, null, null, null, DateTimeException.class},
+ {2008, 6, 30, null, 5, null, null, null, null, null, DateTimeException.class},
+ {2008, 6, null, 11, 5, null, null, null, null, null, DateTimeException.class},
+ {2008, null, 30, 11, 5, null, null, null, null, null, DateTimeException.class},
+ {null, 6, 30, 11, 5, null, null, null, null, null, DateTimeException.class},
+
+ {2008, 6, 30, 11, 5, null, null, null, null, "2008-06-30T11:05", null},
+ {2008, 6, 30, 11, 5, 30, null, null, null, "2008-06-30T11:05:30", null},
+ {2008, 6, 30, 11, 5, 30, 500000000, null, null, "2008-06-30T11:05:30.5", null},
+ {2008, 6, 30, 11, 5, 30, 1, null, null, "2008-06-30T11:05:30.000000001", null},
{2008, 6, 30, 11, 5, null, null, "+01:00", null, "2008-06-30T11:05+01:00", null},
{2008, 6, 30, 11, 5, 30, null, "+01:00", null, "2008-06-30T11:05:30+01:00", null},
Oops, something went wrong.

0 comments on commit 29e9e66

Please sign in to comment.