【问题标题】:i have set of date ranges, i need to get the combined date range ,if any of the date overlaps in java [duplicate]我有一组日期范围,我需要获取组合的日期范围,如果 java 中的任何日期重叠 [重复]
【发布时间】:2018-02-19 06:11:47
【问题描述】:

我有一组日期范围,如果任何日期在 Java 中重叠,我需要获取组合日期范围。

给定三组日期范围,如果任何日期与另一个日期范围重叠,则需要合并。

示例:

20170101-20170331
20170101-20170430
20170430-20170501

预期结果是:

20170101-20170430
20170430-20170501

我在字符串变量中有所有日期。可以请任何人帮助我如何编写代码。我已粘贴在我的代码下方。

我想达到预期的效果。我不知道我需要如何修改此代码。我是初学者,请帮助我做到这一点。我从 StackOverflow 获得了这个示例程序。

package com.kkkkk.Combine;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;

public class Ideone {
    public static void main(String[] args) throws java.lang.Exception {
        ArrayList<Interval> x = new ArrayList<>();
        x.add(new Interval("20170430", "20170501")); // "20170101", "20170430"
        x.add(new Interval("20170101", "20170430"));// 20170101-20170430
                x.add(new Interval("20170101", "20170331"));
                x = merge(x);

        for (Interval i1 : x) {
            System.out.println(i1.getStartDate() + " " + i1.getEndDate());

        }

    }

    public static ArrayList<Interval> merge(ArrayList<Interval> intervals) {


        if (intervals.size() == 0 || intervals.size() == 1)
            return intervals;

        ArrayList<Interval> result = new ArrayList<Interval>();

        Collections.sort(intervals, new IntervalComparator());


        System.out.println("intervals ggggg\n" + intervals + "\n");

        Interval first = intervals.get(0);

        String start = first.getStartDate();
        String end = first.getEndDate();
        Date startDateF = null;
        Date endDateF = null;

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            startDateF = sdf.parse(start);
            endDateF = sdf.parse(end);


            // ArrayList<Interval> result = new ArrayList<Interval>();

            for (int i = 1; i < intervals.size(); i++) {

                Interval current = intervals.get(i);

                Date currentEndDate = sdf.parse(current.getEndDate());
                Date currentStartDate = sdf.parse(current.getStartDate());

                // if ((current.getStartDate().after(endDateF)) ||
                                Date d1 = minDate(endDateF, currentStartDate);

                                if ((currentStartDate).compareTo(endDateF) <= 0) {
                    endDateF = maxDate(currentEndDate, endDateF);

                                                        } else {

                                                            result.add(new Interval(start, (sdf.format(endDateF))));

                    // start = current.start;
                    // end = current.end;

                    start = sdf.format(currentStartDate);
                    endDateF = (currentEndDate);



    enter code here

                }

            }
            result.add(new Interval(start, end));
            // result.add(new Interval(start, (sdf.format(endDateF))));
        }

        catch (ParseException ex) {
            ex.printStackTrace();
        }

        // result.add(new Interval(start, end));

        return result;
        // return intervals;

    }

    public static Date minDate(Date date1, Date date2) {
        // if date1 before date2 then return date1 else return date2

        return date1.before(date2) ? date1 : date2;
    }

    /**
     * find Max Dates
     * 
     * @param date1
     * @param date2
     * @return
     */
    public static Date maxDate(Date date1, Date date2) {
        // if date1 after date2 then return date1 else return date2
        System.out.println("date max");
        return date1.after(date2) ? date1 : date2;
    }
}

【问题讨论】:

  • 顺便说一句,我建议您废弃早已过时的课程DateSimpleDateFormat。现代 Java 日期和时间 API 要好得多,使用起来也好得多。现代的LocalDate 类也非常适合您的需求,而使用Date,您正在拖着一天中的某个时间,而您确实希望避免这种情况。参见例如tutorial by Oracle
  • 进一步建议:您的 Interval 类可以保存 LocalDate 对象而不是字符串(如果您真的坚持,甚至可以保存 Date 对象)。构造函数仍然可以接受字符串并解析它们。这样,您只需解析字符串一次,而不是每次都需要比较它们(黑客版本将直接比较字符串,因为它们是 yyyyMMdd 也可以)。
  • 查看 ThreeTen-Extra 项目中的 LocalDateRange 类。
  • 假设你想要半开区间,为什么你不希望你的示例区间为一个区间 [2017-01-01/2017-05-01)习惯于看到封闭的日期间隔)?您应该真正澄清区间边界的状态以及为什么不合并相邻区间(没有间隙!)。
  • 是的,你是对的! .我错误地提到了预期的结果。结果应该像一个间隔[2017-01-01/2017-05-01]

标签: java string date intervals localtime


【解决方案1】:

ISO 8601

将日期时间值序列化为文本时使用标准 ISO 8601 格式。您的格式符合标准的“基本”版本,但最好尽可能使用完整格式:

YYYY-MM-DD

使用标准格式的日期范围,使用斜杠字符作为分隔符:

YYYY-MM-DD/YYYY-MM-DD

如果您无法更改输入字符串,请在连字符上拆分字符串。将每个部分解析为LocalDate。使用这些对象来实例化 LocalDateRange

LocalDate ld = LocalDate.parse( "20170101" , DateTimeFormatter.BASIC_ISO_DATE ) ; 

LocalDateRange

使用来自ThreeTen-Extra 项目的LocalDateRange 类,它扩展了 java.time 类的功能。解析和生成文本时使用标准格式。

LocalDateRange range = LocalDateRange.parse( "2017-01-01/2017-03-31" ) ;

收集到List&lt;LocalDateRange&gt;

要进行排序,请编写一个调用 LocalDateRange::getStart 的比较器。

与另一个范围比较,看看它们是否重叠。如果是这样,请结合致电union

if ( range.overlaps( otherRange ) ) {
    range = range.union( otherRange ) ;
}

如果它们不重叠,则您已完成该回合。将此结果存储在另一个 List&lt;LocalDateRange&gt; 中。用下一个范围开始另一轮。

起泡、冲洗、重复。

【讨论】:

    【解决方案2】:

    我假设你的 Interval 是这样的:

        private static class Interval {
        private String begin;
        private String end;
    
        public Interval(String begin, String end) {
            this.begin = begin;
            this.end = end;
        }
    
        public String getStartDate() {
            return begin;
        }
    
        public String getEndDate() {
            return end;
        }
    }
    

    您需要做的是合并一个Interval 列表。一个解决方案是sort 列出开始日期,然后是结束日期。然后将最早开始时间和最晚结束时间存储在游标变量中。一个例子:

        public List<Interval> merge(List<Interval> intervals) {
        Collections.sort(intervals, new Comparator<Interval>() {
            @Override
            public int compare(Interval o1, Interval o2) {
                if (o1.getStartDate().equals(o2.getStartDate())) {
                    return o1.getEndDate().compareTo(o2.getEndDate());
                }
                return o1.getStartDate().compareTo(o2.getStartDate());
            }
        });
        List<Interval> ret = new ArrayList<>();
        String MAX_VAL = "99999999";
        String MIN_VAL = "00000000";
        String start = MAX_VAL, end = MIN_VAL;
    
        for (Interval interval : intervals) {
            if (interval.getStartDate().compareTo(end) > 0) {
                if (start.compareTo(MAX_VAL) < 0) {
                    ret.add(new Interval(start, end));
                }
                start = interval.getStartDate();
                end = interval.getEndDate();
            } else {
                if (start.compareTo(interval.getStartDate()) < 0) {
                    start = interval.getStartDate();
                }
                if (end.compareTo(interval.getEndDate()) > 0) {
                    end = interval.getEndDate();
                }
            }
        }
        if (start.compareTo(MAX_VAL) < 0) {
            ret.add(new Interval(start, end));
        }
        return ret;
    }
    

    【讨论】:

      【解决方案3】:
      public static void main(String[] args) {
          // TODO Auto-generated method stub
      
      
          ArrayList<MainLab.Interval> list = new ArrayList<MainLab.Interval>();
      
      
          list.add(new MainLab.Interval("20170430", "20170501"));
          list.add(new MainLab.Interval("20170101", "20170430"));
          list.add(new MainLab.Interval("20170101", "20170331"));
      
      
      
      for (Iterator iterator = mergeInterval(list).iterator(); iterator.hasNext();) {
          Interval interval = (Interval) iterator.next();
      
          System.out.println(interval.getStart()+ "==="+interval.getEnd());
      }
      
      
      
      
      }
      
      public static List<Interval>  mergeInterval(ArrayList<MainLab.Interval> list){
      
          /*
           * Sort the list , Interval class have implemented Comparable Interface.
           *  So we will get sorted intervals. Intervals sorted based on start of interval
           */
          Collections.sort(list);
          Set<MainLab.Interval> resultlist = new TreeSet<MainLab.Interval>();
      
          List<MainLab.Interval> mergedIntervals = new ArrayList<MainLab.Interval>();
      
          //declare date formate to parse and format date from string to and from
          SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
          if(list.size() == 1){
              //resultlist = list
              return list;
          }
          if(list.size() > 1){
              // get first interval Object. conside it as first interval
              Interval mergeInterval = list.get(0);
      
              // loop other intervals from second in the list
              for(int i=1; i< list.size() ; i++){
      
                  Interval interval2 = list.get(i);
                  try{
      
      
                      Date startDate1  = sdf.parse(mergeInterval.getStart());
                      Date endDate1  = sdf.parse(mergeInterval.getEnd());
      
      
      
                      Date startDate2  = sdf.parse(interval2.getStart());
                      Date endDate2  = sdf.parse(interval2.getEnd());
      
      
                      // compare if current interval's start date is before merging interval's end date
                      // then the two intervals are overlaping
                      if(startDate2.compareTo(endDate1) < 0 ){
      
                          // check whether end date of current loop interval is after the merging interval.
                          // then we need to update the end date of merging interval with looping interval's end date
                          if(endDate2.compareTo(endDate1) > 0 ){
      
                              mergeInterval.setEnd(interval2.getEnd());
      
                          }
                      }else{
                          // compare if current interval's start date is after merging interval's end date
                          // then it must be a new interval start so swap mergInterval variable with  current looping interval
      
                           mergeInterval = interval2;
      
                      }
      
                      //add merge interval to set. 
                      resultlist.add(mergeInterval);
                  }catch(Exception ex){
                      ex.printStackTrace();
                  }
      
              }
      
          }
          mergedIntervals.addAll(resultlist);
          return mergedIntervals;
      
      }
      
      public static class Interval implements Comparable<Interval>{
      
          private String start;
          private String end;
      
          public String getStart() {
              return start;
          }
          public void setStart(String start) {
              this.start = start;
          }
          public String getEnd() {
              return end;
          }
          public void setEnd(String end) {
              this.end = end;
          }
          public Interval(){
      
      
      
                  }
          public Interval(String start,String end){
      
              this.start = start;
              this.end = end;
      
          }
              @Override
              public boolean equals(Object obj) {
                  // TODO Auto-generated method stub
                  Interval inteval = (Interval)obj;
                  return this.getStart().equals(inteval.getStart()) && this.getEnd().equals(inteval.getEnd()) ;
              }
      
          @Override
          public int compareTo(Interval o) {
              // TODO Auto-generated method stub
      
              SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
              try{
                  Date startDate  = sdf.parse(start);
                  Date endDate  = sdf.parse(end);
                  Date pstartDate  = sdf.parse(o.start);
                  Date pendDate  = sdf.parse(o.end);
      
      
                  return startDate.compareTo(pstartDate);
      
              }catch(Exception ex){
                  ex.printStackTrace();
              }
              return 0;
          }
      
      
      }
      

      【讨论】:

        猜你喜欢
        • 2015-11-18
        • 1970-01-01
        • 1970-01-01
        • 2013-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多