code: public ZonedDateTime atStartOfDay(ZoneId zone) {
          Objects.requireNonNull(zone, "zone");
          // need to handle case where there is a gap from 11:30 to 00:30
          // standard ZDT factory would result in 01:00 rather than 00:30
          LocalDateTime ldt = atTime(LocalTime.MIDNIGHT);
          if (zone instanceof ZoneOffset == false) {
              ZoneRules rules = zone.getRules();
              ZoneOffsetTransition trans = rules.getTransition(ldt);
              if (trans != null && trans.isGap()) {
                  ldt = trans.getDateTimeAfter();
              }
          }
          return ZonedDateTime.of(ldt, zone);
      }
docs: Returns a zoned date-time from this date at the earliest valid time according
  to the rules in the time-zone.
  <p>
  Time-zone rules, such as daylight savings, mean that not every local date-time
  is valid for the specified zone, thus the local date-time may not be midnight.
  <p>
  In most cases, there is only one valid offset for a local date-time.
  In the case of an overlap, there are two valid offsets, and the earlier one is used,
  corresponding to the first occurrence of midnight on the date.
  In the case of a gap, the zoned date-time will represent the instant just after the gap.
  <p>
  If the zone ID is a {@link ZoneOffset}, then the result always has a time of midnight.
  <p>
  To convert to a specific time in a given time-zone call {@link #atTime(LocalTime)}
  followed by {@link LocalDateTime#atZone(ZoneId)}.
  
  @param zone  the zone ID to use, not null
  @return the zoned date-time formed from this date and the earliest valid time for the zone, not null