65 import static java.time.temporal.ChronoField.INSTANT_SECONDS; |
65 import static java.time.temporal.ChronoField.INSTANT_SECONDS; |
66 |
66 |
67 import java.time.DateTimeException; |
67 import java.time.DateTimeException; |
68 import java.time.Instant; |
68 import java.time.Instant; |
69 import java.time.ZoneId; |
69 import java.time.ZoneId; |
70 import java.time.temporal.Chrono; |
70 import java.time.chrono.Chronology; |
71 import java.time.temporal.ChronoField; |
71 import java.time.temporal.ChronoField; |
72 import java.time.temporal.ChronoLocalDate; |
72 import java.time.chrono.ChronoLocalDate; |
73 import java.time.temporal.Queries; |
73 import java.time.temporal.Queries; |
74 import java.time.temporal.TemporalAccessor; |
74 import java.time.temporal.TemporalAccessor; |
75 import java.time.temporal.TemporalField; |
75 import java.time.temporal.TemporalField; |
76 import java.time.temporal.TemporalQuery; |
76 import java.time.temporal.TemporalQuery; |
77 import java.time.temporal.ValueRange; |
77 import java.time.temporal.ValueRange; |
79 import java.util.Objects; |
79 import java.util.Objects; |
80 |
80 |
81 /** |
81 /** |
82 * Context object used during date and time printing. |
82 * Context object used during date and time printing. |
83 * <p> |
83 * <p> |
84 * This class provides a single wrapper to items used in the print. |
84 * This class provides a single wrapper to items used in the format. |
85 * |
85 * |
86 * <h3>Specification for implementors</h3> |
86 * <h3>Specification for implementors</h3> |
87 * This class is a mutable context intended for use from a single thread. |
87 * This class is a mutable context intended for use from a single thread. |
88 * Usage of the class is thread-safe within standard printing as the framework creates |
88 * Usage of the class is thread-safe within standard printing as the framework creates |
89 * a new instance of the class for each print and printing is single-threaded. |
89 * a new instance of the class for each format and printing is single-threaded. |
90 * |
90 * |
91 * @since 1.8 |
91 * @since 1.8 |
92 */ |
92 */ |
93 final class DateTimePrintContext { |
93 final class DateTimePrintContext { |
94 |
94 |
107 |
107 |
108 /** |
108 /** |
109 * Creates a new instance of the context. |
109 * Creates a new instance of the context. |
110 * |
110 * |
111 * @param temporal the temporal object being output, not null |
111 * @param temporal the temporal object being output, not null |
112 * @param formatter the formatter controlling the print, not null |
112 * @param formatter the formatter controlling the format, not null |
113 */ |
113 */ |
114 DateTimePrintContext(TemporalAccessor temporal, DateTimeFormatter formatter) { |
114 DateTimePrintContext(TemporalAccessor temporal, DateTimeFormatter formatter) { |
115 super(); |
115 super(); |
116 this.temporal = adjust(temporal, formatter); |
116 this.temporal = adjust(temporal, formatter); |
117 this.formatter = formatter; |
117 this.formatter = formatter; |
118 } |
118 } |
119 |
119 |
120 private static TemporalAccessor adjust(final TemporalAccessor temporal, DateTimeFormatter formatter) { |
120 private static TemporalAccessor adjust(final TemporalAccessor temporal, DateTimeFormatter formatter) { |
121 // normal case first |
121 // normal case first |
122 Chrono<?> overrideChrono = formatter.getChrono(); |
122 Chronology overrideChrono = formatter.getChronology(); |
123 ZoneId overrideZone = formatter.getZone(); |
123 ZoneId overrideZone = formatter.getZone(); |
124 if (overrideChrono == null && overrideZone == null) { |
124 if (overrideChrono == null && overrideZone == null) { |
125 return temporal; |
125 return temporal; |
126 } |
126 } |
127 |
127 |
128 // ensure minimal change |
128 // ensure minimal change |
129 Chrono<?> temporalChrono = Chrono.from(temporal); // default to ISO, handles Instant |
129 Chronology temporalChrono = Chronology.from(temporal); // default to ISO, handles Instant |
130 ZoneId temporalZone = temporal.query(Queries.zone()); // zone then offset, handles OffsetDateTime |
130 ZoneId temporalZone = temporal.query(Queries.zone()); // zone then offset, handles OffsetDateTime |
131 if (temporal.isSupported(EPOCH_DAY) == false || Objects.equals(overrideChrono, temporalChrono)) { |
131 if (temporal.isSupported(EPOCH_DAY) == false || Objects.equals(overrideChrono, temporalChrono)) { |
132 overrideChrono = null; |
132 overrideChrono = null; |
133 } |
133 } |
134 if (temporal.isSupported(INSTANT_SECONDS) == false || Objects.equals(overrideZone, temporalZone)) { |
134 if (temporal.isSupported(INSTANT_SECONDS) == false || Objects.equals(overrideZone, temporalZone)) { |
142 if (overrideChrono != null && overrideZone != null) { |
142 if (overrideChrono != null && overrideZone != null) { |
143 return overrideChrono.zonedDateTime(Instant.from(temporal), overrideZone); |
143 return overrideChrono.zonedDateTime(Instant.from(temporal), overrideZone); |
144 } else if (overrideZone != null) { |
144 } else if (overrideZone != null) { |
145 return temporalChrono.zonedDateTime(Instant.from(temporal), overrideZone); |
145 return temporalChrono.zonedDateTime(Instant.from(temporal), overrideZone); |
146 } else { // overrideChrono != null |
146 } else { // overrideChrono != null |
147 // need class here to handle non-standard cases like OffsetDate |
147 // need class here to handle non-standard cases |
148 final ChronoLocalDate<?> date = overrideChrono.date(temporal); |
148 final ChronoLocalDate date = overrideChrono.date(temporal); |
149 return new TemporalAccessor() { |
149 return new TemporalAccessor() { |
150 @Override |
150 @Override |
151 public boolean isSupported(TemporalField field) { |
151 public boolean isSupported(TemporalField field) { |
152 return temporal.isSupported(field); |
152 return temporal.isSupported(field); |
153 } |
153 } |
158 return date.range(field); |
158 return date.range(field); |
159 } else { |
159 } else { |
160 return temporal.range(field); |
160 return temporal.range(field); |
161 } |
161 } |
162 } |
162 } |
163 return field.doRange(this); |
163 return field.rangeRefinedBy(this); |
164 } |
164 } |
165 @Override |
165 @Override |
166 public long getLong(TemporalField field) { |
166 public long getLong(TemporalField field) { |
167 if (field instanceof ChronoField) { |
167 if (field instanceof ChronoField) { |
168 if (((ChronoField) field).isDateField()) { |
168 if (((ChronoField) field).isDateField()) { |
169 return date.getLong(field); |
169 return date.getLong(field); |
170 } else { |
170 } else { |
171 return temporal.getLong(field); |
171 return temporal.getLong(field); |
172 } |
172 } |
173 } |
173 } |
174 return field.doGet(this); |
174 return field.getFrom(this); |
175 } |
175 } |
|
176 @SuppressWarnings("unchecked") |
176 @Override |
177 @Override |
177 public <R> R query(TemporalQuery<R> query) { |
178 public <R> R query(TemporalQuery<R> query) { |
178 if (query == Queries.zoneId() || query == Queries.chrono() || query == Queries.precision()) { |
179 if (query == Queries.chronology()) { |
|
180 return (R) date.getChronology(); |
|
181 } |
|
182 if (query == Queries.zoneId() || query == Queries.precision()) { |
179 return temporal.query(query); |
183 return temporal.query(query); |
180 } |
184 } |
181 return query.queryFrom(this); |
185 return query.queryFrom(this); |
182 } |
186 } |
183 }; |
187 }; |