@Override
  public long periodUntil(DateTime endDateTime, PeriodUnit unit) {

    if (endDateTime instanceof ChronoLocalDateTime == false) {
      throw new DateTimeException("Unable to calculate period between objects of two different types");
    }
    @SuppressWarnings("unchecked")
    ChronoLocalDateTime<C> end = (ChronoLocalDateTime<C>) endDateTime;
    if (getDate().getChrono().equals(end.getDate().getChrono()) == false) {
      throw new DateTimeException("Unable to calculate period between two different chronologies");
    }
    if (unit instanceof ChronoUnit) {
      ChronoUnit f = (ChronoUnit) unit;
      if (f.isTimeUnit()) {
        long amount = end.getLong(EPOCH_DAY) - this.date.getLong(EPOCH_DAY);
        switch (f) {
          case NANOS:
            amount = Jdk8Methods.safeMultiply(amount, NANOS_PER_DAY);
            break;
          case MICROS:
            amount = Jdk8Methods.safeMultiply(amount, MICROS_PER_DAY);
            break;
          case MILLIS:
            amount = Jdk8Methods.safeMultiply(amount, MILLIS_PER_DAY);
            break;
          case SECONDS:
            amount = Jdk8Methods.safeMultiply(amount, SECONDS_PER_DAY);
            break;
          case MINUTES:
            amount = Jdk8Methods.safeMultiply(amount, MINUTES_PER_DAY);
            break;
          case HOURS:
            amount = Jdk8Methods.safeMultiply(amount, HOURS_PER_DAY);
            break;
          case HALF_DAYS:
            amount = Jdk8Methods.safeMultiply(amount, 2);
            break;
        }
        return Jdk8Methods.safeAdd(amount, this.time.periodUntil(end.getTime(), unit));
      }
      ChronoLocalDate<C> endDate = end.getDate();
      if (end.getTime().isBefore(this.time)) {
        endDate = endDate.minus(1, ChronoUnit.DAYS);
      }
      return this.date.periodUntil(endDate, unit);
    }
    return unit.between(this, endDateTime).getAmount();
  }