public static long timestampCeil(TimeUnitRange range, long ts, TimeZone tz) {
    // assume that we are at UTC timezone, just for algorithm performance
    long offset = tz.getOffset(ts);
    long utcTs = ts + offset;

    switch (range) {
      case HOUR:
        return ceil(utcTs, MILLIS_PER_HOUR) - offset;
      case DAY:
        return ceil(utcTs, MILLIS_PER_DAY) - offset;
      case MILLENNIUM:
      case CENTURY:
      case DECADE:
      case MONTH:
      case YEAR:
      case QUARTER:
      case WEEK:
        int days = (int) (utcTs / MILLIS_PER_DAY + EPOCH_JULIAN);
        return julianDateFloor(range, days, false) * MILLIS_PER_DAY - offset;
      default:
        // for MINUTE and SECONDS etc...,
        // it is more effective to use arithmetic Method
        throw new AssertionError(range);
    }
  }
Keep the algorithm consistent with Calcite DateTimeUtils.julianDateFloor, but here we take time
zone into account.
amoro-format-mixed/amoro-mixed-flink/amoro-mixed-flink-common/src/main/java/org/apache/amoro/flink/util/DateTimeUtils.java