Search code examples
javamysqlspringzoneddatetime

Specification CriteriaBuilder converting ZonedDateTime To LocalDate for comparing


I need to compare that an entity has a date that is between two dates, unfortunately I'm not getting the results I need. Instead of comparing dates, criteria builder has created a query that compares date and time which results in no results being returned. I'm using Spring Specification to invoke criteria builder. My problem is that I'm using ZoneDateTime (I need this) to compare the dates, I'm just wondering if there's away if there's away I can convert both the dates to LocalDate so It would compare '2018-01-12' instead of '2018-01-12 09:45:00'.

Criteria Builder:

 public static Specification<Activity> activityDateBetween(ZonedDateTime from, ZonedDateTime to) {
        return new Specification<Activity>() {
            @Override
            public Predicate toPredicate(Root<Activity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Predicate startingFrom =  criteriaBuilder.greaterThanOrEqualTo(root.get(Activity_.date), from);
                Predicate endingAt = criteriaBuilder.lessThanOrEqualTo(root.get(Activity_.date), to);
                return criteriaBuilder.and(startingFrom, endingAt);
            }
        };
    }

MySQL:

SELECT activity0_.id                  AS id1_5_, 
       activity0_.activity_type       AS activity2_5_, 
       activity0_.activity_date       AS activity3_5_, 
       activity0_.tracker_job_item_id AS tracker_5_5_, 
       activity0_.work_type           AS work_typ4_5_, 
       activity0_.tracker_worker_id   AS tracker_6_5_ 
FROM   tracker_job_item_activity activity0_ 
WHERE  activity0_.tracker_job_item_id = 71 
       AND ( activity0_.work_type IN ( 'BUTTONHOLING', 'SEWING', 'CUTTING' ) ) 
       AND ( activity0_.activity_type IN ( 'RECEIVE', 'SEND' ) ) 
       AND activity0_.activity_date >= '2018-01-12 09:29:43' 
       AND activity0_.activity_date <= '2018-01-12 09:29:43'

As you can see the above query is comparing date time, which is not what I want.


Solution

  • Alright, I've managed to get the results I want, by subtracting the time portion from ZonedDateTime. Now the search is inclusive of current date.

       public static Specification<Activity> activityDateBetween(ZonedDateTime from, ZonedDateTime to) {
                return new Specification<Activity>() {
                    @Override
                    public Predicate toPredicate(Root<Activity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                        Predicate startingFrom =  criteriaBuilder.greaterThanOrEqualTo(root.get(Activity_.date),
                            from.minusHours(from.getHour()).minusMinutes(from.getMinute()).minusSeconds(from.getSecond()));
                        Predicate endingAt = criteriaBuilder.lessThanOrEqualTo(root.get(Activity_.date), to);
                        return criteriaBuilder.and(startingFrom, endingAt);
                    }
                };
            }