private RowFilter createTimeRangeFilter(TimeRange timeRange) {
    TimestampRange.Builder rangeBuilder = TimestampRange.newBuilder();

    long lowerBound =
        BigtableConstants.BIGTABLE_TIMEUNIT.convert(
            timeRange.getMin(), BigtableConstants.HBASE_TIMEUNIT);
    rangeBuilder.setStartTimestampMicros(lowerBound);

    if (timeRange.getMax() != Long.MAX_VALUE) {
      long upperBound =
          BigtableConstants.BIGTABLE_TIMEUNIT.convert(
              timeRange.getMax(), BigtableConstants.HBASE_TIMEUNIT);
      rangeBuilder.setEndTimestampMicros(upperBound);
    }

    return RowFilter.newBuilder().setTimestampRangeFilter(rangeBuilder).build();
  }
 @Override
 public RowFilter adapt(FilterAdapterContext context, TimestampsFilter filter) {
   Interleave.Builder interleaveBuilder = RowFilter.Interleave.newBuilder();
   for (long timestamp : filter.getTimestamps()) {
     // HBase TimestampsFilters are of the form: [N, M], however; bigtable
     // uses [N, M) to express timestamp ranges. In order to express an HBase
     // single point timestamp [M, M], we need to specify [M, M+1) to bigtable.
     long bigtableStartTimestamp =
         BigtableConstants.BIGTABLE_TIMEUNIT.convert(timestamp, BigtableConstants.HBASE_TIMEUNIT);
     long bigtableEndTimestamp =
         BigtableConstants.BIGTABLE_TIMEUNIT.convert(
             timestamp + 1, BigtableConstants.HBASE_TIMEUNIT);
     interleaveBuilder.addFilters(
         RowFilter.newBuilder()
             .setTimestampRangeFilter(
                 TimestampRange.newBuilder()
                     .setStartTimestampMicros(bigtableStartTimestamp)
                     .setEndTimestampMicros(bigtableEndTimestamp)));
   }
   return RowFilter.newBuilder().setInterleave(interleaveBuilder).build();
 }