Querying dates within months using only numerical values months

206 Views Asked by At

I have 2 date values and a set of rows which have a range defined as discount_start_month and discount_end_month. The current situation is that I only have month information as below, there is no year data to compare the input 2 dates values with these months.

The goal is to take the date and see in between which range of months they fall into. At any given point of time they may fall into any of discount_code

For Eg: A date 01 January 2022 would come under DEC_JAN row. A date 01 December 2021 would still come uder DEC_JAN row

Problem:

  1. The problem statement is without year information how would you check in which range do the input dates lie ?
  2. Once I figure out (1), I need to generate 2 dates with the values advance_start_month and advance_end_month, so for the above it would be ,

2 dates would be named as startDateGeneration and endDateGeneration

startDateGeneration would be generated from the discount_code's advance_start_month,

considering example 01 January 2022, the startDateGeneration would be generated from DEC_JAN's advance_start_month and advance_end_month

day -> first day of the month of October (from advance_start_month)

Month -> October

Year -> Previous year

startDateGeneration would be 01 October 2021

Same for endDateGeneration, we would use the advance_end_month so it would be 01 January 2022

enter image description here

Inputs are start date and end date.

Code to find the dates in range by iterating over the above dataset.

private static boolean isInRange(
      LocalDate discountDate, Integer fromMonth, Integer toMonth) {
    YearMonth fromMonthDiscount = YearMonth.of(discountDate.getYear(), fromMonth);
    YearMonth toMonthDiscount = YearMonth.of(discountDate.getYear(), toMonth);
    YearMonth yearMonthDiscountDate =
        YearMonth.of(discountDate.getYear(), discountDate.getMonthValue());

    if (fromMonth > toMonth) {
      if (discountDate.getMonthValue() == Constants.DEC_MONTH) {
        toMonthDiscount = YearMonth.of(discountDate.getYear() + 1, toMonth);
      } else if (discountDate.getMonthValue() == Constants.JAN_MONTH) {
        fromMonthDiscount = YearMonth.of(discountDate.getYear() - 1, fromMonth);
      }
    }

    return (yearMonthDiscountDate.isAfter(fromMonthDiscount)
            || yearMonthDiscountDate.equals(fromMonthDiscount))
        && (yearMonthDiscountDate.isBefore(toMonthDiscount)
            || yearMonthDiscountDate.equals(toMonthDiscount));
  }

Logic to find the problem statement (2) part,

 int startYear = fromDate.getYear();
    int endYear = toDate.getYear();
    
    // Get the advance_start_month from the DB iterating object of the start date
    int advanceStartMonth = ....
    
    if(advanceStartMonth >= Constants.OCT_MONTH &&
        advanceStartMonth <= Constants.DEC_MONTH &&
        startYear == endYear) {
        startYear = startYear - 1;
    }
    
    // Get the advance_start_month and advance_end_month from the DB iterating object of the end date  
    int discountResultStartMonth = //.......
        int discountResultEndMonth = //........
    
        if (discountResultStartMonth > discountResultEndMonth) {
            if (toDate.getMonthValue() == Constants.DEC_MONTH) {
                endYear = endYear + 1;
            }
        }

Logic for forming the dates to generate a range out of these,

fromDateSeasonMap -> Dataset for 1 row from the above dataset(for start date) toDateSeasonMap -> Dataset for 1 row from the above dataset(for end date)

LocalDate startDateGeneration =
          fromDate
              .withMonth((Integer) fromDateSeasonMap.get(Constants.ADVANCE_START_MONTH))
              .withYear(startYear);
      LocalDate endDateGeneration =
          toDate
              .withMonth((Integer) toDateSeasonMap.get(Constants.ADVANCE_END_MONTH))
              .withYear(endYear)
              .withDayOfMonth(
                  YearMonth.of(endYear, (Integer) toDateSeasonMap.get(Constants.ADVANCE_END_MONTH))
                      .atEndOfMonth()
                      .getDayOfMonth());

Notes:

  1. At any given point of time there would be no overlapping months in the dataset.
  2. Only Months numerical data is present.
  3. There would be no values greater than 12 as there are only 12 months in a year.

Expected Input and output

Begin Input
Start Date: 2023-08-01
End Date: 2023-10-01
startDateGeneration: 2023-06-01
endDateGeneration: 2023-11-30
===================================
Begin Input
Start Date: 2023-09-01
End Date: 2023-12-01
startDateGeneration: 2023-07-01
endDateGeneration: 2024-01-31
===================================
Begin Input
Start Date: 2023-01-30
End Date: 2023-02-01
startDateGeneration: 2022-11-30
endDateGeneration: 2023-03-31
===================================
Begin Input
Start Date: 2023-01-30
End Date: 2023-02-01
startDateGeneration: 2022-11-30
endDateGeneration: 2023-03-31
===================================
Begin Input
Start Date: 2022-10-30
End Date: 2023-02-01
startDateGeneration: 2022-08-30
endDateGeneration: 2023-03-31
===================================
Begin Input
Start Date: 2022-08-30
End Date: 2022-10-01
startDateGeneration: 2022-06-30
endDateGeneration: 2022-12-31
===================================
Begin Input
Start Date: 2022-08-30
End Date: 2023-02-01
startDateGeneration: 2022-06-30
endDateGeneration: 2023-03-31
===================================
Begin Input
Start Date: 2023-04-30
End Date: 2023-07-01
startDateGeneration: 2023-02-28
endDateGeneration: 2023-07-31
===================================
Begin Input
Start Date: 2023-06-30
End Date: 2023-07-01
startDateGeneration: 2023-04-30
endDateGeneration: 2023-07-31
===================================
Begin Input
Start Date: 2023-08-30
End Date: 2023-10-01
startDateGeneration: 2023-06-30
endDateGeneration: 2023-12-31
===================================
Begin Input
Start Date: 2023-10-30
End Date: 2024-01-01
startDateGeneration: 2023-08-30
endDateGeneration: 2024-03-31
===================================
Begin Input
Start Date: 2022-12-30
End Date: 2023-02-01
startDateGeneration: 2022-10-30
endDateGeneration: 2023-03-31
===================================
Begin Input
Start Date: 2023-01-30
End Date: 2023-02-01
startDateGeneration: 2022-10-30
endDateGeneration: 2023-03-31
===================================
Begin Input
Start Date: 2022-10-01
End Date: 2023-02-01
startDateGeneration: 2022-07-01
endDateGeneration: 2023-03-31
===================================
Begin Input
Start Date: 2022-12-01
End Date: 2023-02-01
startDateGeneration: 2022-10-01
endDateGeneration: 2023-03-31
===================================
Begin Input
Start Date: 2023-02-01
End Date: 2023-04-01
startDateGeneration: 2022-12-01
endDateGeneration: 2023-05-31
===================================
Begin Input
Start Date: 2023-02-01
End Date: 2023-03-01
startDateGeneration: 2022-12-01
endDateGeneration: 2023-03-31
===================================
Begin Input
Start Date: 2023-04-30
End Date: 2023-06-01
startDateGeneration: 2023-02-28
endDateGeneration: 2023-07-31
===================================
Begin Input
Start Date: 2023-06-30
End Date: 2023-08-01
startDateGeneration: 2023-04-30
endDateGeneration: 2023-08-31
===================================
2

There are 2 best solutions below

1
1 1 On
private static boolean isInRange(
    LocalDate discountDate, Integer fromMonth, Integer toMonth) {
  int discountYear = discountDate.getYear();

  if (fromMonth > toMonth) {
    if (discountDate.getMonthValue() == Constants.DEC_MONTH) {
      toMonth += 12;
    } else if (discountDate.getMonthValue() == Constants.JAN_MONTH) {
      fromMonth -= 12;
    }
  }

  return discountDate.getMonthValue() >= fromMonth && discountDate.getMonthValue() <= toMonth;
}

and

int startYear = fromDate.getYear();
int endYear = toDate.getYear();
int advanceStartMonth = fromDateSeasonMap.get(Constants.ADVANCE_START_MONTH);
int advanceEndMonth = toDateSeasonMap.get(Constants.ADVANCE_END_MONTH);

if (advanceStartMonth >= Constants.OCT_MONTH && advanceStartMonth <= Constants.DEC_MONTH && startYear == endYear) {
  startYear -= 1;
}

if (advanceEndMonth >= Constants.OCT_MONTH && advanceEndMonth <= Constants.DEC_MONTH && startYear == endYear) {
  endYear -= 1;
}

if (advanceEndMonth < advanceStartMonth) {
  if (toDate.getMonthValue() == Constants.DEC_MONTH) {
    endYear += 1;
  }
}

LocalDate startDateGeneration = fromDate.withMonth(advanceStartMonth).withYear(startYear);
LocalDate endDateGeneration = toDate.withMonth(advanceEndMonth).withYear(endYear);

// Adjust the end day of the month for endDateGeneration
int lastDayOfMonth = YearMonth.of(endYear, advanceEndMonth).lengthOfMonth();
endDateGeneration = endDateGeneration.withDayOfMonth(lastDayOfMonth);

Hope that helps, the question isn't very clear, but this could help you.

0
I.sh. On

To handle the logic for isInRange when the start month is greater than the end month, you can modify the logic as follows:

private static boolean isInRange(LocalDate discountDate, Integer fromMonth, Integer toMonth) {
    int discountYear = discountDate.getYear();
    int discountMonth = discountDate.getMonthValue();

    if (fromMonth <= toMonth) {
        return discountMonth >= fromMonth && discountMonth <= toMonth;
    } else {
        if (discountMonth >= fromMonth || discountMonth <= toMonth) {
            return true;
        } else {
            if (discountMonth == Constants.JAN_MONTH && toMonth == Constants.DEC_MONTH) {
                return true;
            }
            if (discountMonth == Constants.DEC_MONTH && fromMonth == Constants.JAN_MONTH) {
                return true;
            }
        }
    }

    return false;
}

This logic handles the case when the start month is greater than the end month by considering the special cases of December (12) and January (1).

To handle the year generation logic based on the dataset, you can use the following approach:

  1. Get the start year from the fromDate object.
  2. Get the end year from the toDate object.
  3. Retrieve the advance_start_month and advance_end_month from the dataset.
  4. Check if the advance_start_month falls between October (10) and December (12) inclusive, and the start year is the same as the end year. If true, decrement the start year by 1.
  5. Check if the advance_end_month is less than the advance_start_month. If true, check if the toDate month is December (12) and increment the end year by 1.

Here's an example implementation of the year generation logic:

int startYear = fromDate.getYear();
int endYear = toDate.getYear();

// Get the advance_start_month from the DB iterating object of the start date
int advanceStartMonth = ...; // Retrieve the value from the dataset

if (advanceStartMonth >= Constants.OCT_MONTH && advanceStartMonth <= Constants.DEC_MONTH && startYear == endYear) {
    startYear = startYear - 1;
}

// Get the advance_start_month and advance_end_month from the DB iterating object of the end date
int advanceEndMonth = ...; // Retrieve the value from the dataset

if (advanceEndMonth < advanceStartMonth) {
    if (toDate.getMonthValue() == Constants.DEC_MONTH) {
        endYear = endYear + 1;
    }
}

By following this approach, you can generate the correct start and end years for the startDateGeneration and endDateGeneration objects.

Please note that you need to retrieve the corresponding values from the dataset for advance_start_month and advance_end_month as mentioned in the code comments.

I hope I've understand the question correctly, it was hard to follow.