154 */ 155 static final long NANOS_PER_DAY = NANOS_PER_HOUR * HOURS_PER_DAY; 156 157 /** 158 * The date part. 159 */ 160 private final D date; 161 /** 162 * The time part. 163 */ 164 private final LocalTime time; 165 166 //----------------------------------------------------------------------- 167 /** 168 * Obtains an instance of {@code ChronoLocalDateTime} from a date and time. 169 * 170 * @param date the local date, not null 171 * @param time the local time, not null 172 * @return the local date-time, not null 173 */ 174 static ChronoLocalDateTimeImpl<?> of(ChronoLocalDate<?> date, LocalTime time) { 175 return new ChronoLocalDateTimeImpl(date, time); 176 } 177 178 /** 179 * Constructor. 180 * 181 * @param date the date part of the date-time, not null 182 * @param time the time part of the date-time, not null 183 */ 184 private ChronoLocalDateTimeImpl(D date, LocalTime time) { 185 Objects.requireNonNull(date, "date"); 186 Objects.requireNonNull(time, "time"); 187 this.date = date; 188 this.time = time; 189 } 190 191 /** 192 * Returns a copy of this date-time with the new date and time, checking 193 * to see if a new object is in fact required. 194 * 195 * @param newDate the date of the new date-time, not null 196 * @param newTime the time of the new date-time, not null 197 * @return the date-time, not null 198 */ 199 private ChronoLocalDateTimeImpl<D> with(Temporal newDate, LocalTime newTime) { 200 if (date == newDate && time == newTime) { 201 return this; 202 } 203 // Validate that the new Temporal is a ChronoLocalDate (and not something else) 204 D cd = (D)date.getChronology().ensureChronoLocalDate(newDate); 205 return new ChronoLocalDateTimeImpl<>((D)cd, newTime); 206 } 207 208 //----------------------------------------------------------------------- 209 @Override 210 public D toLocalDate() { 211 return date; 212 } 213 214 @Override 215 public LocalTime toLocalTime() { 216 return time; 217 } 218 219 //----------------------------------------------------------------------- 220 @Override 221 public boolean isSupported(TemporalField field) { 222 if (field instanceof ChronoField) { 223 ChronoField f = (ChronoField) field; 224 return f.isDateField() || f.isTimeField(); 225 } 226 return field != null && field.isSupportedBy(this); 227 } 228 229 @Override 230 public ValueRange range(TemporalField field) { 231 if (field instanceof ChronoField) { 232 ChronoField f = (ChronoField) field; 233 return (f.isTimeField() ? time.range(field) : date.range(field)); 234 } 235 return field.rangeRefinedBy(this); 236 } 237 238 @Override 239 public int get(TemporalField field) { 240 if (field instanceof ChronoField) { 241 ChronoField f = (ChronoField) field; 242 return (f.isTimeField() ? time.get(field) : date.get(field)); 243 } 244 return range(field).checkValidIntValue(getLong(field), field); 245 } 246 247 @Override 248 public long getLong(TemporalField field) { 249 if (field instanceof ChronoField) { 250 ChronoField f = (ChronoField) field; 251 return (f.isTimeField() ? time.getLong(field) : date.getLong(field)); 252 } 253 return field.getFrom(this); 254 } 255 256 //----------------------------------------------------------------------- 257 @SuppressWarnings("unchecked") 258 @Override 259 public ChronoLocalDateTimeImpl<D> with(TemporalAdjuster adjuster) { 260 if (adjuster instanceof ChronoLocalDate) { 261 // The Chronology is checked in with(date,time) 262 return with((ChronoLocalDate<D>) adjuster, time); 263 } else if (adjuster instanceof LocalTime) { 264 return with(date, (LocalTime) adjuster); 265 } else if (adjuster instanceof ChronoLocalDateTimeImpl) { 266 return (ChronoLocalDateTimeImpl<D>)(date.getChronology().ensureChronoLocalDateTime((ChronoLocalDateTimeImpl<?>) adjuster)); 267 } 268 return (ChronoLocalDateTimeImpl<D>)(date.getChronology().ensureChronoLocalDateTime((ChronoLocalDateTimeImpl<?>) adjuster.adjustInto(this))); 269 } 270 271 @Override 272 public ChronoLocalDateTimeImpl<D> with(TemporalField field, long newValue) { 273 if (field instanceof ChronoField) { 274 ChronoField f = (ChronoField) field; 275 if (f.isTimeField()) { 276 return with(date, time.with(field, newValue)); 277 } else { 278 return with(date.with(field, newValue), time); 279 } 280 } 281 return (ChronoLocalDateTimeImpl<D>)(date.getChronology().ensureChronoLocalDateTime(field.adjustInto(this, newValue))); 282 } 283 284 //----------------------------------------------------------------------- 285 @Override 286 public ChronoLocalDateTimeImpl<D> plus(long amountToAdd, TemporalUnit unit) { 287 if (unit instanceof ChronoUnit) { 288 ChronoUnit f = (ChronoUnit) unit; 289 switch (f) { 290 case NANOS: return plusNanos(amountToAdd); 291 case MICROS: return plusDays(amountToAdd / MICROS_PER_DAY).plusNanos((amountToAdd % MICROS_PER_DAY) * 1000); 292 case MILLIS: return plusDays(amountToAdd / MILLIS_PER_DAY).plusNanos((amountToAdd % MILLIS_PER_DAY) * 1000000); 293 case SECONDS: return plusSeconds(amountToAdd); 294 case MINUTES: return plusMinutes(amountToAdd); 295 case HOURS: return plusHours(amountToAdd); 359 if (toLocalDate().getChronology().equals(end.toLocalDate().getChronology()) == false) { 360 throw new DateTimeException("Unable to calculate period between two different chronologies"); 361 } 362 if (unit instanceof ChronoUnit) { 363 ChronoUnit f = (ChronoUnit) unit; 364 if (f.isTimeUnit()) { 365 long amount = end.getLong(EPOCH_DAY) - date.getLong(EPOCH_DAY); 366 switch (f) { 367 case NANOS: amount = Math.multiplyExact(amount, NANOS_PER_DAY); break; 368 case MICROS: amount = Math.multiplyExact(amount, MICROS_PER_DAY); break; 369 case MILLIS: amount = Math.multiplyExact(amount, MILLIS_PER_DAY); break; 370 case SECONDS: amount = Math.multiplyExact(amount, SECONDS_PER_DAY); break; 371 case MINUTES: amount = Math.multiplyExact(amount, MINUTES_PER_DAY); break; 372 case HOURS: amount = Math.multiplyExact(amount, HOURS_PER_DAY); break; 373 case HALF_DAYS: amount = Math.multiplyExact(amount, 2); break; 374 } 375 return Math.addExact(amount, time.periodUntil(end.toLocalTime(), unit)); 376 } 377 D endDate = end.toLocalDate(); 378 if (end.toLocalTime().isBefore(time)) { 379 endDate = (D)endDate.minus(1, ChronoUnit.DAYS); 380 } 381 return date.periodUntil(endDate, unit); 382 } 383 return unit.between(this, endDateTime); 384 } 385 386 //----------------------------------------------------------------------- 387 private Object writeReplace() { 388 return new Ser(Ser.CHRONO_LOCAL_DATE_TIME_TYPE, this); 389 } 390 391 /** 392 * Defend against malicious streams. 393 * @return never 394 * @throws InvalidObjectException always 395 */ 396 private Object readResolve() throws ObjectStreamException { 397 throw new InvalidObjectException("Deserialization via serialization delegate"); 398 } 399 400 void writeExternal(ObjectOutput out) throws IOException { 401 out.writeObject(date); 402 out.writeObject(time); 403 } 404 405 static ChronoLocalDateTime<?> readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 406 ChronoLocalDate date = (ChronoLocalDate) in.readObject(); 407 LocalTime time = (LocalTime) in.readObject(); 408 return date.atTime(time); 409 } 410 411 //----------------------------------------------------------------------- 412 @Override 413 public boolean equals(Object obj) { 414 if (this == obj) { 415 return true; 416 } 417 if (obj instanceof ChronoLocalDateTime) { 418 return compareTo((ChronoLocalDateTime<?>) obj) == 0; 419 } 420 return false; 421 } 422 423 @Override 424 public int hashCode() { 425 return toLocalDate().hashCode() ^ toLocalTime().hashCode(); 426 } | 154 */ 155 static final long NANOS_PER_DAY = NANOS_PER_HOUR * HOURS_PER_DAY; 156 157 /** 158 * The date part. 159 */ 160 private final D date; 161 /** 162 * The time part. 163 */ 164 private final LocalTime time; 165 166 //----------------------------------------------------------------------- 167 /** 168 * Obtains an instance of {@code ChronoLocalDateTime} from a date and time. 169 * 170 * @param date the local date, not null 171 * @param time the local time, not null 172 * @return the local date-time, not null 173 */ 174 @SuppressWarnings("rawtypes") 175 static ChronoLocalDateTimeImpl<?> of(ChronoLocalDate<?> date, LocalTime time) { 176 return new ChronoLocalDateTimeImpl(date, time); 177 } 178 179 /** 180 * Constructor. 181 * 182 * @param date the date part of the date-time, not null 183 * @param time the time part of the date-time, not null 184 */ 185 private ChronoLocalDateTimeImpl(D date, LocalTime time) { 186 Objects.requireNonNull(date, "date"); 187 Objects.requireNonNull(time, "time"); 188 this.date = date; 189 this.time = time; 190 } 191 192 /** 193 * Returns a copy of this date-time with the new date and time, checking 194 * to see if a new object is in fact required. 195 * 196 * @param newDate the date of the new date-time, not null 197 * @param newTime the time of the new date-time, not null 198 * @return the date-time, not null 199 */ 200 private ChronoLocalDateTimeImpl<D> with(Temporal newDate, LocalTime newTime) { 201 if (date == newDate && time == newTime) { 202 return this; 203 } 204 // Validate that the new Temporal is a ChronoLocalDate (and not something else) 205 D cd = (D) date.getChronology().ensureChronoLocalDate(newDate); 206 return new ChronoLocalDateTimeImpl<>(cd, newTime); 207 } 208 209 //----------------------------------------------------------------------- 210 @Override 211 public D toLocalDate() { 212 return date; 213 } 214 215 @Override 216 public LocalTime toLocalTime() { 217 return time; 218 } 219 220 //----------------------------------------------------------------------- 221 @Override 222 public boolean isSupported(TemporalField field) { 223 if (field instanceof ChronoField) { 224 ChronoField f = (ChronoField) field; 225 return f.isDateBased() || f.isTimeBased(); 226 } 227 return field != null && field.isSupportedBy(this); 228 } 229 230 @Override 231 public ValueRange range(TemporalField field) { 232 if (field instanceof ChronoField) { 233 ChronoField f = (ChronoField) field; 234 return (f.isTimeBased() ? time.range(field) : date.range(field)); 235 } 236 return field.rangeRefinedBy(this); 237 } 238 239 @Override 240 public int get(TemporalField field) { 241 if (field instanceof ChronoField) { 242 ChronoField f = (ChronoField) field; 243 return (f.isTimeBased() ? time.get(field) : date.get(field)); 244 } 245 return range(field).checkValidIntValue(getLong(field), field); 246 } 247 248 @Override 249 public long getLong(TemporalField field) { 250 if (field instanceof ChronoField) { 251 ChronoField f = (ChronoField) field; 252 return (f.isTimeBased() ? time.getLong(field) : date.getLong(field)); 253 } 254 return field.getFrom(this); 255 } 256 257 //----------------------------------------------------------------------- 258 @SuppressWarnings("unchecked") 259 @Override 260 public ChronoLocalDateTimeImpl<D> with(TemporalAdjuster adjuster) { 261 if (adjuster instanceof ChronoLocalDate) { 262 // The Chronology is checked in with(date,time) 263 return with((ChronoLocalDate<D>) adjuster, time); 264 } else if (adjuster instanceof LocalTime) { 265 return with(date, (LocalTime) adjuster); 266 } else if (adjuster instanceof ChronoLocalDateTimeImpl) { 267 return (ChronoLocalDateTimeImpl<D>)(date.getChronology().ensureChronoLocalDateTime((ChronoLocalDateTimeImpl<?>) adjuster)); 268 } 269 return (ChronoLocalDateTimeImpl<D>)(date.getChronology().ensureChronoLocalDateTime((ChronoLocalDateTimeImpl<?>) adjuster.adjustInto(this))); 270 } 271 272 @Override 273 public ChronoLocalDateTimeImpl<D> with(TemporalField field, long newValue) { 274 if (field instanceof ChronoField) { 275 ChronoField f = (ChronoField) field; 276 if (f.isTimeBased()) { 277 return with(date, time.with(field, newValue)); 278 } else { 279 return with(date.with(field, newValue), time); 280 } 281 } 282 return (ChronoLocalDateTimeImpl<D>)(date.getChronology().ensureChronoLocalDateTime(field.adjustInto(this, newValue))); 283 } 284 285 //----------------------------------------------------------------------- 286 @Override 287 public ChronoLocalDateTimeImpl<D> plus(long amountToAdd, TemporalUnit unit) { 288 if (unit instanceof ChronoUnit) { 289 ChronoUnit f = (ChronoUnit) unit; 290 switch (f) { 291 case NANOS: return plusNanos(amountToAdd); 292 case MICROS: return plusDays(amountToAdd / MICROS_PER_DAY).plusNanos((amountToAdd % MICROS_PER_DAY) * 1000); 293 case MILLIS: return plusDays(amountToAdd / MILLIS_PER_DAY).plusNanos((amountToAdd % MILLIS_PER_DAY) * 1000000); 294 case SECONDS: return plusSeconds(amountToAdd); 295 case MINUTES: return plusMinutes(amountToAdd); 296 case HOURS: return plusHours(amountToAdd); 360 if (toLocalDate().getChronology().equals(end.toLocalDate().getChronology()) == false) { 361 throw new DateTimeException("Unable to calculate period between two different chronologies"); 362 } 363 if (unit instanceof ChronoUnit) { 364 ChronoUnit f = (ChronoUnit) unit; 365 if (f.isTimeUnit()) { 366 long amount = end.getLong(EPOCH_DAY) - date.getLong(EPOCH_DAY); 367 switch (f) { 368 case NANOS: amount = Math.multiplyExact(amount, NANOS_PER_DAY); break; 369 case MICROS: amount = Math.multiplyExact(amount, MICROS_PER_DAY); break; 370 case MILLIS: amount = Math.multiplyExact(amount, MILLIS_PER_DAY); break; 371 case SECONDS: amount = Math.multiplyExact(amount, SECONDS_PER_DAY); break; 372 case MINUTES: amount = Math.multiplyExact(amount, MINUTES_PER_DAY); break; 373 case HOURS: amount = Math.multiplyExact(amount, HOURS_PER_DAY); break; 374 case HALF_DAYS: amount = Math.multiplyExact(amount, 2); break; 375 } 376 return Math.addExact(amount, time.periodUntil(end.toLocalTime(), unit)); 377 } 378 D endDate = end.toLocalDate(); 379 if (end.toLocalTime().isBefore(time)) { 380 endDate = endDate.minus(1, ChronoUnit.DAYS); 381 } 382 return date.periodUntil(endDate, unit); 383 } 384 return unit.between(this, endDateTime); 385 } 386 387 //----------------------------------------------------------------------- 388 private Object writeReplace() { 389 return new Ser(Ser.CHRONO_LOCAL_DATE_TIME_TYPE, this); 390 } 391 392 /** 393 * Defend against malicious streams. 394 * @return never 395 * @throws InvalidObjectException always 396 */ 397 private Object readResolve() throws ObjectStreamException { 398 throw new InvalidObjectException("Deserialization via serialization delegate"); 399 } 400 401 void writeExternal(ObjectOutput out) throws IOException { 402 out.writeObject(date); 403 out.writeObject(time); 404 } 405 406 static ChronoLocalDateTime<?> readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 407 ChronoLocalDate<?> date = (ChronoLocalDate<?>) in.readObject(); 408 LocalTime time = (LocalTime) in.readObject(); 409 return date.atTime(time); 410 } 411 412 //----------------------------------------------------------------------- 413 @Override 414 public boolean equals(Object obj) { 415 if (this == obj) { 416 return true; 417 } 418 if (obj instanceof ChronoLocalDateTime) { 419 return compareTo((ChronoLocalDateTime<?>) obj) == 0; 420 } 421 return false; 422 } 423 424 @Override 425 public int hashCode() { 426 return toLocalDate().hashCode() ^ toLocalTime().hashCode(); 427 } |