Search code examples
javajava-8localdate

What is the most efficient way to subtract/add the "zone diff time" from/to the LocalDateTime in java 8


My client is sitting in other Zone. On UI there is way to search by DateRange (start and end date). Client sends start and end date in String form. eg -> startDate = "DD/MM/YYYY", endDate = "DD/MM/YYYY". Server converts dates to searchStartDate = "DD/MM/YYYY 00:00:01" and searchEndDate = "DD/MM/YYYY 23:59:59". But before searching in DB I need to add "zone time difference" in these searchStartDate and searchEndDate. Different clients are sitting in different zones. How do we add/subtract the zone diff time using java 8 APIs?

eg - my server is running in UTC. and Client sitting in IST. I will subtract 5H:30M from both searchStartDate and searchEndDate before searching into DB.

What I have - LocalDateTime searchStartDate and searchEndDate. What I want searchStartDate = searchStartDate.plus(<UtcIstTimeZoneDiff>).

Edit - Server knows the timeZone of every client.


Solution

  •     DateTimeFormatter searchDateFormatter = DateTimeFormatter.ofPattern("dd/MM/uuuu");
        ZoneId clientZone = ZoneId.of("Asia/Colombo");
        String startDate = "29/01/2018";
        String endDate = "04/02/2018";
    
        Instant searchStartTime = LocalDate.parse(startDate, searchDateFormatter)
                .atStartOfDay(clientZone)
                .toInstant();
        Instant searchEndTime = LocalDate.parse(endDate, searchDateFormatter)
                .plusDays(1)
                .atStartOfDay(clientZone)
                .toInstant();
    
        System.out.println("" + searchStartTime + " inclusive to " 
                            + searchEndTime + " exclusive");
    

    This example prints

    2018-01-28T18:30:00Z inclusive to 2018-02-04T18:30:00Z exclusive
    

    Use a half-open interval: Instead of trying to decide the last clock hour in a day and consider whether you want how many decimals on the seconds, it’s better to set the search end time to the first moment of the following day and then just only retrieve records that come strictly before that time.

    I am giving you start and end times as Instants. Most JDBC drivers are happy to use them, and I consider it an advantage that they inherently represent points on the timeline, which is what you need them for. If for your search you do need LocalDateTime, here’s a way to obtain one:

        LocalDateTime searchStartTime = LocalDate.parse(startDate, searchDateFormatter)
                .atStartOfDay(clientZone)
                .toOffsetDateTime()
                .withOffsetSameInstant(ZoneOffset.UTC)
                .toLocalDateTime();
    

    The search end time case is similar.