private ScalarOperator reduceDateToDatetimeCast(BinaryPredicateOperator operator) {
        ScalarOperator castChild = operator.getChild(0).getChild(0);
        ConstantOperator child2 = (ConstantOperator) operator.getChild(1);

        if (child2.isNull()) {
            return operator;
        }

        LocalDateTime originalDateTime = child2.getDatetime();
        LocalDateTime bottomDateTime = child2.getDatetime().truncatedTo(ChronoUnit.DAYS);

        LocalDateTime targetDateTime;
        BinaryType binaryType = operator.getBinaryType();
        int offset;
        BinaryPredicateOperator resultBinaryPredicateOperator;
        ConstantOperator newDate;
        switch (binaryType) {
            case GE:
                // when the BinaryType is >= ,cast dateTime to minimum date type；
                // Eg:cast dateTime(2021-12-28 00:00:00.0) to date(2021-12-28)
                // Eg:cast dateTime(2021-12-28 00:00:00.1) to date(2021-12-29)
                offset = originalDateTime.isEqual(bottomDateTime) ? 0 : 1;
                targetDateTime = bottomDateTime.plusDays(offset);
                newDate = ConstantOperator.createDate(targetDateTime);
                resultBinaryPredicateOperator = BinaryPredicateOperator.ge(castChild, newDate);
                break;
            case GT:
                // when the BinaryType is > ,cast dateTime to minimum date type；
                // Eg:cast dateTime(2021-12-28 00:00:00.0) to date(2021-12-29)
                // Eg:cast dateTime(2021-12-28 00:00:00.1) to date(2021-12-29)
                offset = 1;
                targetDateTime = bottomDateTime.plusDays(offset);
                newDate = ConstantOperator.createDate(targetDateTime);
                resultBinaryPredicateOperator = BinaryPredicateOperator.ge(castChild, newDate);
                break;
            case LE:
                // when the BinaryType is <= ,cast dateTime to maximum date type；
                // Eg:cast dateTime(2021-12-28 00:00:00.0) to date(2021-12-28)
                // Eg:cast dateTime(2021-12-28 00:00:00.1) to date(2021-12-27)
                offset = 0;
                targetDateTime = bottomDateTime.plusDays(offset);
                newDate = ConstantOperator.createDate(targetDateTime);
                resultBinaryPredicateOperator = BinaryPredicateOperator.le(castChild, newDate);
                break;
            case LT:
                // when the BinaryType is < ,cast dateTime to maximum date type；
                // Eg:cast dateTime(2021-12-28 00:00:00.0) to date(2021-12-27)
                // Eg:cast dateTime(2021-12-28 00:00:00.1) to date(2021-12-28)
                offset = originalDateTime.isEqual(bottomDateTime) ? -1 : 0;
                targetDateTime = bottomDateTime.plusDays(offset);
                newDate = ConstantOperator.createDate(targetDateTime);
                resultBinaryPredicateOperator = BinaryPredicateOperator.le(castChild, newDate);
                break;
            case EQ:
                // when the BinaryType is = ,cast dateTime to equivalent date type；
                // Eg:cast dateTime(2021-12-28 00:00:00.0) to date(2021-12-28)
                if (!originalDateTime.isEqual(bottomDateTime)) {
                    resultBinaryPredicateOperator = operator;
                } else {
                    newDate = ConstantOperator.createDate(bottomDateTime);
                    resultBinaryPredicateOperator = BinaryPredicateOperator.eq(castChild, newDate);
                }
                break;
            default:
                // current not support !=
                resultBinaryPredicateOperator = operator;
                break;
        }
        return resultBinaryPredicateOperator;
    }
@Test
    public void testReduceDateToDatetimeCast() {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        ReduceCastRule reduceCastRule = new ReduceCastRule();
        {
            CastOperator castOperator =
                    new CastOperator(Type.DATETIME, new ColumnRefOperator(0, Type.DATE, "id_date", false));
            ConstantOperator constantOperator =
                    ConstantOperator.createDatetime(LocalDateTime.parse("2021-12-28 11:11:11", dateTimeFormatter));
            BinaryPredicateOperator beforeOptimize =
                    new BinaryPredicateOperator(BinaryType.GE, castOperator, constantOperator);
            ScalarOperator afterOptimize = reduceCastRule.apply(
                    beforeOptimize,
                    null);

            Assert.assertTrue(afterOptimize instanceof BinaryPredicateOperator);
            Assert.assertEquals(BinaryType.GE,
                    ((BinaryPredicateOperator) afterOptimize).getBinaryType());
            Assert.assertTrue(afterOptimize.getChild(0) instanceof ColumnRefOperator);
            Assert.assertTrue(afterOptimize.getChild(1) instanceof ConstantOperator);
            Assert.assertEquals("2021-12-29",
                    ((ConstantOperator) afterOptimize.getChild(1)).getDate().format(dateFormat));
        }
        {
            CastOperator castOperator =
                    new CastOperator(Type.DATETIME, new ColumnRefOperator(0, Type.DATE, "id_date", false));
            ConstantOperator constantOperator =
                    ConstantOperator.createDatetime(LocalDateTime.parse("2021-12-28 00:00:00", dateTimeFormatter));
            BinaryPredicateOperator beforeOptimize =
                    new BinaryPredicateOperator(BinaryType.GE, castOperator, constantOperator);
            ScalarOperator afterOptimize = reduceCastRule.apply(
                    beforeOptimize,
                    null);

            Assert.assertTrue(afterOptimize instanceof BinaryPredicateOperator);
            Assert.assertEquals(BinaryType.GE,
                    ((BinaryPredicateOperator) afterOptimize).getBinaryType());
            Assert.assertTrue(afterOptimize.getChild(0) instanceof ColumnRefOperator);
            Assert.assertTrue(afterOptimize.getChild(1) instanceof ConstantOperator);
            Assert.assertEquals("2021-12-28",
                    ((ConstantOperator) afterOptimize.getChild(1)).getDate().format(dateFormat));
        }
        {
            CastOperator castOperator =
                    new CastOperator(Type.DATETIME, new ColumnRefOperator(0, Type.DATE, "id_date", false));
            ConstantOperator constantOperator =
                    ConstantOperator.createDatetime(LocalDateTime.parse("2021-12-28 00:00:00", dateTimeFormatter));
            BinaryPredicateOperator beforeOptimize =
                    new BinaryPredicateOperator(BinaryType.LE, castOperator, constantOperator);
            ScalarOperator afterOptimize = reduceCastRule.apply(
                    beforeOptimize,
                    null);

            Assert.assertTrue(afterOptimize instanceof BinaryPredicateOperator);
            Assert.assertEquals(BinaryType.LE,
                    ((BinaryPredicateOperator) afterOptimize).getBinaryType());
            Assert.assertTrue(afterOptimize.getChild(0) instanceof ColumnRefOperator);
            Assert.assertTrue(afterOptimize.getChild(1) instanceof ConstantOperator);
            Assert.assertEquals("2021-12-28",
                    ((ConstantOperator) afterOptimize.getChild(1)).getDate().format(dateFormat));
        }
        {
            CastOperator castOperator =
                    new CastOperator(Type.DATETIME, new ColumnRefOperator(0, Type.DATE, "id_date", false));
            ConstantOperator constantOperator =
                    ConstantOperator.createDatetime(LocalDateTime.parse("2021-12-28 11:11:11", dateTimeFormatter));
            BinaryPredicateOperator beforeOptimize =
                    new BinaryPredicateOperator(BinaryType.LT, castOperator, constantOperator);
            ScalarOperator afterOptimize = reduceCastRule.apply(
                    beforeOptimize,
                    null);

            Assert.assertTrue(afterOptimize instanceof BinaryPredicateOperator);
            Assert.assertEquals(BinaryType.LE,
                    ((BinaryPredicateOperator) afterOptimize).getBinaryType());
            Assert.assertTrue(afterOptimize.getChild(0) instanceof ColumnRefOperator);
            Assert.assertTrue(afterOptimize.getChild(1) instanceof ConstantOperator);
            Assert.assertEquals("2021-12-28",
                    ((ConstantOperator) afterOptimize.getChild(1)).getDate().format(dateFormat));
        }
        {
            CastOperator castOperator =
                    new CastOperator(Type.DATETIME, new ColumnRefOperator(0, Type.DATE, "id_date", false));
            ConstantOperator constantOperator =
                    ConstantOperator.createDatetime(LocalDateTime.parse("2021-12-28 00:00:00", dateTimeFormatter));
            BinaryPredicateOperator beforeOptimize =
                    new BinaryPredicateOperator(BinaryType.LT, castOperator, constantOperator);
            ScalarOperator afterOptimize = reduceCastRule.apply(
                    beforeOptimize,
                    null);

            Assert.assertTrue(afterOptimize instanceof BinaryPredicateOperator);
            Assert.assertEquals(BinaryType.LE,
                    ((BinaryPredicateOperator) afterOptimize).getBinaryType());
            Assert.assertTrue(afterOptimize.getChild(0) instanceof ColumnRefOperator);
            Assert.assertTrue(afterOptimize.getChild(1) instanceof ConstantOperator);
            Assert.assertEquals("2021-12-27",
                    ((ConstantOperator) afterOptimize.getChild(1)).getDate().format(dateFormat));
        }
        {
            CastOperator castOperator =
                    new CastOperator(Type.DATETIME, new ColumnRefOperator(0, Type.DATE, "id_date", false));
            ConstantOperator constantOperator =
                    ConstantOperator.createDatetime(LocalDateTime.parse("2021-12-28 00:00:00", dateTimeFormatter));
            BinaryPredicateOperator beforeOptimize =
                    new BinaryPredicateOperator(BinaryType.EQ, castOperator, constantOperator);
            ScalarOperator afterOptimize = reduceCastRule.apply(
                    beforeOptimize,
                    null);

            Assert.assertTrue(afterOptimize instanceof BinaryPredicateOperator);
            Assert.assertEquals(BinaryType.EQ,
                    ((BinaryPredicateOperator) afterOptimize).getBinaryType());
            Assert.assertTrue(afterOptimize.getChild(0) instanceof ColumnRefOperator);
            Assert.assertTrue(afterOptimize.getChild(1) instanceof ConstantOperator);
            Assert.assertEquals("2021-12-28",
                    ((ConstantOperator) afterOptimize.getChild(1)).getDate().format(dateFormat));
        }
        {
            CastOperator castOperator =
                    new CastOperator(Type.DATETIME, new ColumnRefOperator(0, Type.DATE, "id_date", false));
            ConstantOperator constantOperator =
                    ConstantOperator.createDatetime(LocalDateTime.parse("2021-12-29 11:11:11", dateTimeFormatter));
            BinaryPredicateOperator beforeOptimize =
                    new BinaryPredicateOperator(BinaryType.EQ, castOperator, constantOperator);
            ScalarOperator afterOptimize = reduceCastRule.apply(
                    beforeOptimize,
                    null);

            Assert.assertSame(beforeOptimize, afterOptimize);
        }
        {
            CastOperator castOperator =
                    new CastOperator(Type.DATETIME, new ColumnRefOperator(0, Type.DATE, "id_date", false));
            ConstantOperator constantOperator = ConstantOperator.createNull(Type.DATETIME);
            BinaryPredicateOperator beforeOptimize = BinaryPredicateOperator.ge(castOperator, constantOperator);
            ScalarOperator afterOptimize = reduceCastRule.apply(
                    beforeOptimize,
                    null);
            Assert.assertSame(beforeOptimize, afterOptimize);
        }
    }