code: private static Long findPreviousZoneTransitionTime(TimeZone tz, int upperOffset, long upper, long lower) {
          boolean onUnitTime = false;
          long mid = 0;
  
          for (int unit : FIND_ZONE_TRANSITION_TIME_UNITS) {
              long lunits = lower/unit;
              long uunits = upper/unit;
              if (uunits > lunits) {
                  mid = ((lunits + uunits + 1) >>> 1) * unit;
                  onUnitTime = true;
                  break;
              }
          }
  
          int midOffset;
          if (!onUnitTime) {
              mid = (upper + lower) >>> 1;
          }
  
          if (onUnitTime) {
              if (mid != upper) {
                  midOffset  = tz.getOffset(mid);
                  if (midOffset != upperOffset) {
                      return findPreviousZoneTransitionTime(tz, upperOffset, upper, mid);
                  }
                  upper = mid;
              }
              // check mid-1
              mid--;
          } else {
              mid = (upper + lower) >>> 1;
          }
  
          if (mid == lower) {
              return Long.valueOf(upper);
          }
          midOffset = tz.getOffset(mid);
          if (midOffset != upperOffset) {
              if (onUnitTime) {
                  return Long.valueOf(upper);
              }
              return findPreviousZoneTransitionTime(tz, upperOffset, upper, mid);
          }
          return findPreviousZoneTransitionTime(tz, upperOffset, mid, lower);
      }
docs: Implementing binary search for zone transtion detection, used by {@link #getPreviousZoneTransitionTime(TimeZone, long, long)}
  @param tz The time zone.
  @param upperOffset The zone offset at <code>upper</code>
  @param upper The upper bound, inclusive.
  @param lower The lower bound, exclusive.
  @return The time of the previous zone transition, or null if not available.