매달 자바에서 두 날짜 startTime을하고 ENDTIME 주어진 청크 분할에 대한 최선의 해결책은 무엇인가?

스테파노 :

나는 덩어리가 매달 두 날짜를 주어 계산하는 알고리즘을 만들어야합니다.

예 (형식 날짜 : YYYY-MM-DD HH : MM : SS) 주어진 두 날짜 :

  • startTime을 : 2020년 1월 10일 13시 0분 25초
  • endTime- 사용자 : 2020년 3월 19일 15시 0분 30초

나는 위의 기간 매월 덩어리로 나눌 수있다. 간단히 말해서 나는 덩어리가 될 것이다 계산하는 경우 :

  • chunk_1 ->에서 : 2020년 1월 10일 13시 0분 25초에 : 2020년 1월 31일 23시 59분 59초
  • chunk_2 ->에서 : 2020년 2월 1일 00:00:00 : 2020년 2월 29일 23시 59분 59초
  • chunk_3 ->에서 : 2020년 3월 1일 00:00:00 : 2020년 3월 19일 15시 0분 30초

내 첫 번째 솔루션은 다음에 :

public static List<ExportDateSegment> datesBetweenWithCalendar(Date d1, Date d2) {

    List<ExportDateSegment> dateSegments = new ArrayList<ExportDateSegment>();
    Calendar c1 = Calendar.getInstance();
    c1.setTime(d1);

    int monthsDiff = mounthsDiffbetween(d1, d2);
    LOGGER.debug("months between two dates: {} ",monthsDiff);

    int i = 1;

    while (c1.getTimeInMillis() < d2.getTime()) {

        Calendar calendar;

        ExportDateSegment exportDateSegment = new ExportDateSegment();

        LOGGER.debug("last day of the month: " + c1.getActualMaximum(Calendar.DATE) + " last hour of the month: "
                + c1.getActualMaximum(Calendar.HOUR_OF_DAY) + " first day of the month: "
                + c1.getActualMinimum(Calendar.DAY_OF_MONTH) + " month: " + (c1.get(Calendar.MONTH) + 1));
        // the logic is to separate the three cases: the start period, intermediate period and the end period   

        if (i == 1) {

            calendar = new GregorianCalendar(c1.get(Calendar.YEAR), c1.get(Calendar.MONTH),
                    c1.getActualMaximum(Calendar.DATE), 23, 59, 59);

            exportDateSegment.setStartDate(c1.getTime());
            exportDateSegment.setEndDate(calendar.getTime());

        } else if (i == monthsDiff) {

            calendar = new GregorianCalendar(c1.get(Calendar.YEAR), c1.get(Calendar.MONTH),
                    c1.getActualMinimum(Calendar.DATE), 00, 00, 00);

            exportDateSegment.setStartDate(calendar.getTime());
            exportDateSegment.setEndDate(d2);

        } else {

            Calendar startCalendar = new GregorianCalendar(c1.get(Calendar.YEAR), c1.get(Calendar.MONTH),
                    c1.getActualMinimum(Calendar.DATE), 00, 00, 00);
            Calendar endCalendar = new GregorianCalendar(c1.get(Calendar.YEAR), c1.get(Calendar.MONTH),
                    c1.getActualMaximum(Calendar.DATE), 23, 59, 59);

            exportDateSegment.setStartDate(startCalendar.getTime());
            exportDateSegment.setEndDate(endCalendar.getTime());
        }

        c1.add(Calendar.MONTH, 1);
        dateSegments.add(exportDateSegment);

        i = i + 1;

    }

    return dateSegments;
}


public static int mounthsDiffbetween(Date d1, Date d2) {

    int monthsDiff = 0;

    Calendar c1 = Calendar.getInstance();
    Calendar c2 = Calendar.getInstance();

    c1.setTime(d1);
    c2.setTime(d2);

    monthsDiff = (c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH)) + 1;

    return monthsDiff;
}

ExportDateSegment 다른 단어 덩어리입니다에 속성으로의 startDate와 endDate가 들어있는 콩입니다.

똑똑한 솔루션이 있습니까?

안드레아스 :

이 같은 자바 8 시간 API, 예를 사용해야합니다 :

static List<TemporalRange<LocalDateTime>> chunkMonthly(LocalDateTime start, LocalDateTime end) {
    List<TemporalRange<LocalDateTime>> list = new ArrayList<>();
    for (LocalDateTime chunkEnd = end, chunkStart; ! chunkEnd.isBefore(start); chunkEnd = chunkStart.minusSeconds(1)) {
        chunkStart = chunkEnd.toLocalDate().withDayOfMonth(1).atStartOfDay();
        if (chunkStart.isBefore(start))
            chunkStart = start;
        list.add(new TemporalRange<>(chunkStart, chunkEnd));
    }
    Collections.reverse(list);
    return list;
}
class TemporalRange<T extends TemporalAccessor> {
    private final T start;
    private final T end;

    public TemporalRange(T start, T end) {
        this.start = start;
        this.end = end;
    }

    public T getStart() {
        return this.start;
    }

    public T getEnd() {
        return this.end;
    }

    @Override
    public String toString() {
        return this.start + " to " + this.end;
    }

    public String toString(DateTimeFormatter fmt) {
        return fmt.format(this.start) + " to " + fmt.format(this.end);
    }
}

테스트

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
List<TemporalRange<LocalDateTime>> list = chunkMonthly(
        LocalDateTime.parse("2020-01-10 13:00:25", fmt),
        LocalDateTime.parse("2020-03-19 15:00:30", fmt));
list.forEach(r -> System.out.println(r.toString(fmt)));

산출

2020-01-10 13:00:25 to 2020-01-31 23:59:59
2020-02-01 00:00:00 to 2020-02-29 23:59:59
2020-03-01 00:00:00 to 2020-03-19 15:00:30

추천

출처http://43.154.161.224:23101/article/api/json?id=19650&siteId=1