@Test
  public void startInEvening() {
    Moment moment = PlainTimestamp.of(2015, 7, 17, 18, 1).atUTC();
    HijriCalendar hijri = HijriCalendar.ofUmalqura(1436, 10, 2);

    assertThat(hijri.atTime(18, 1).at(ZonalOffset.UTC, StartOfDay.EVENING), is(moment));
    GeneralTimestamp<HijriCalendar> tsp =
        moment.toGeneralTimestamp(
            HijriCalendar.family(),
            HijriCalendar.VARIANT_UMALQURA,
            ZonalOffset.UTC,
            StartOfDay.EVENING);
    assertThat(tsp.toDate(), is(hijri));
    assertThat(tsp.toTime(), is(PlainTime.of(18, 1)));
  }
 @Test
 public void plusNanos() {
   assertThat(
       PlainTimestamp.of(2012, 1, 31, 12, 45, 30).plus(123456789, NANOS),
       is(PlainDate.of(2012, 1, 31).at(PlainTime.of(12, 45, 30, 123456789))));
 }
  @Override
  public TransitionHistory load(String zoneID) {

    try {
      ZoneRules zoneRules = ZoneId.of(zoneID).getRules();
      ZonalOffset initialOffset =
          ZonalOffset.ofTotalSeconds(zoneRules.getOffset(Instant.MIN).getTotalSeconds());
      List<ZonalTransition> transitions = new ArrayList<>();
      List<DaylightSavingRule> rules = new ArrayList<>();

      for (ZoneOffsetTransition zot : zoneRules.getTransitions()) {
        Instant instant = zot.getInstant();
        long posixTime = instant.getEpochSecond();
        int previousOffset = zot.getOffsetBefore().getTotalSeconds();
        int totalOffset = zot.getOffsetAfter().getTotalSeconds();
        int dst = Math.toIntExact(zoneRules.getDaylightSavings(instant).getSeconds());
        transitions.add(new ZonalTransition(posixTime, previousOffset, totalOffset, dst));
      }

      for (ZoneOffsetTransitionRule zotr : zoneRules.getTransitionRules()) {
        DaylightSavingRule rule;

        int dom = zotr.getDayOfMonthIndicator(); // -28 bis +31 (ohne 0)
        DayOfWeek dayOfWeek = zotr.getDayOfWeek();

        Month month = Month.valueOf(zotr.getMonth().getValue());

        PlainTime timeOfDay =
            (zotr.isMidnightEndOfDay()
                ? PlainTime.midnightAtEndOfDay()
                : TemporalType.LOCAL_TIME.translate(zotr.getLocalTime()));

        OffsetIndicator indicator;
        switch (zotr.getTimeDefinition()) {
          case STANDARD:
            indicator = OffsetIndicator.STANDARD_TIME;
            break;
          case UTC:
            indicator = OffsetIndicator.UTC_TIME;
            break;
          case WALL:
            indicator = OffsetIndicator.WALL_TIME;
            break;
          default:
            throw new UnsupportedOperationException(zotr.getTimeDefinition().name());
        }

        int dst =
            (zotr.getOffsetAfter().getTotalSeconds() - zotr.getStandardOffset().getTotalSeconds());

        if (dayOfWeek == null) {
          rule = GregorianTimezoneRule.ofFixedDay(month, dom, timeOfDay, indicator, dst);
        } else {
          Weekday wd = Weekday.valueOf(dayOfWeek.getValue());
          if (dom == -1) {
            rule = GregorianTimezoneRule.ofLastWeekday(month, wd, timeOfDay, indicator, dst);
          } else if (dom < 0) {
            rule = new NegativeDayOfMonthPattern(month, dom, wd, timeOfDay, indicator, dst);
          } else {
            rule =
                GregorianTimezoneRule.ofWeekdayAfterDate(month, dom, wd, timeOfDay, indicator, dst);
          }
        }

        rules.add(rule);
      }

      return TransitionModel.of(initialOffset, transitions, rules);

    } catch (ZoneRulesException ex) {
      throw new IllegalArgumentException(ex);
    }
  }
 @Test
 public void plusMillis() {
   assertThat(
       PlainTimestamp.of(2012, 1, 31, 12, 45).plus(36000001, MILLIS),
       is(PlainDate.of(2012, 1, 31).at(PlainTime.of(22, 45, 0, 1000000))));
 }