为了账号安全,请及时绑定邮箱和手机立即绑定

如何比较实例化的 DateTime 对象?

如何比较实例化的 DateTime 对象?

呼如林 2022-01-19 12:35:37
我正在编写一个程序来按日期对日期时间进行排序。有一个 DateTime 开始和一个 DateTime 结束。这些从用户输入中放入它们自己的对象中。DateTime 开始和 DateTime 结束组成了它们自己的术语。因此,每个术语都有自己的对象,以 DateTime 开头和 DateTime 结尾。我想要做的是按日期对所有 DateTime 开始和所有 DateTime 结束进行排序。我怎样才能做到这一点?我正在考虑一个比较器,但我似乎无法在自定义对象上执行此操作。因此,假设用户输入 onebeginning date of 01/01/2000和 one end date of 01/01/2002。这构成了一个术语。然后,用户输入由 abeginning date of 01/01/2001和 an组成的第二项end date of 01/01/2003。我现在要做的是对日期进行排序并创建三个新术语,即:beginning 01/01/2000 end 01/01/2001beginning 01/01/2001 end 01/01/2002beginning 01/01/2002 end 01/01/2003我被困在如何继续这个问题上,有什么想法吗?
查看完整描述

3 回答

?
大话西游666

TA贡献1817条经验 获得超14个赞

将每个日期放入一个新集合中,按日期对其进行排序,然后创建包含集合中相邻日期的新对象。


尝试:


public static void main(String[] args) {

    List<YourClass> list = new ArrayList<>();


    list.add(new YourClass(new Date(100000000), new Date(200000000)));

    list.add(new YourClass(new Date(150000000), new Date(250000000)));

    list.add(new YourClass(new Date(50000000), new Date(300000000)));


    System.out.println(list);


    List<Date> dates = new ArrayList<>();

    for (YourClass yc : list){

        if (!dates.contains(yc.beginning)) dates.add(yc.beginning);

        if (!dates.contains(yc.end)) dates.add(yc.end);

    }


    Collections.sort(dates);


    List<YourClass> list2 = new ArrayList<>();


    for (int i=0; i < dates.size() -1; i++){

        list2.add(new YourClass(dates.get(i), dates.get(i+1)));

    }


    System.out.println(list2);


}


public static class YourClass {

    Date beginning;

    Date end;


    public YourClass(Date beginning, Date end) {

        this.beginning = beginning;

        this.end = end;

    }


    @Override

    public String toString() {

        return "\n" + beginning  + " -> " + end ;

    }

}


查看完整回答
反对 回复 2022-01-19
?
小怪兽爱吃肉

TA贡献1852条经验 获得超1个赞

我想要做的是按日期对所有 DateTime 开始和所有 DateTime 结束进行排序。


你可以做一个或另一个,但不能同时做。


要按开始日期排序(在实践中似乎很明智),请实现compareTo方法。


return this.getDateRange().getStart().compareTo( thatStart );

要按停止日期排序(我认为这没有任何意义),请实现Comparator接口。


return 

    t1.getDateRange().getEnd().compareTo( 

        t2.getDateRange().getEnd() 

    )

;

LocalDate

正如其他人所指出的,您应该使用现代java.time类,而不是可怕的旧Date//类Calendar。SimpleDateFormat对于仅日期值,没有时间和时区,请使用LocalDate.


LocalDateRange

正如jbx 的答案所讨论的,您应该将您的学期的开始日期和结束日期表示为一对。但是当一个类已经存在时不要写一个类。使用ThreeTen-Extra项目中LocalDateRange的类。该项目为java.time类添加了功能。


Comparable

在您的Term类上,实现Comparable接口以启用简单轻松的排序。添加方法compareTo。显而易见的方法是比较LocalDate每个Term对象的LocalDateRange对象的开始。


该类LocalDate实现compareTo了,不,我们不必这样做。


@Override

public int compareTo ( Object o ) {

    if ( this == o ) return 0;

    if ( o == null || getClass() != o.getClass() ) return 0;

    LocalDate thatStart = ( ( Term ) o ).getDateRange().getStart();

    return this.getDateRange().getStart().compareTo( thatStart );

}

请参阅有关对象排序的 Java 教程。


按停止日期排序

您的问题不清楚,但您似乎要求按结束日期进行排序。我无法想象这在实际中是如何有用的。但无论如何,解决方案是通过提供Comparator接口的实现来进行排序。


    @Override

    public int compare ( Term t1 , Term t2 ) {

        return t1.getDateRange().getEnd().compareTo( t2.getDateRange().getEnd() );

    }

示例类

这是一个示例Term类。可能不是生产质量的代码,但应该让你朝着正确的方向前进。


package com.basilbourque.example;


import org.threeten.extra.LocalDateRange;


import java.time.LocalDate;

import java.time.Month;

import java.util.*;


public class Term implements Comparable {

    private UUID id;

    private LocalDateRange dateRange;


    // Constructor

    public Term ( LocalDate start , LocalDate stop , UUID id ) {

        Objects.requireNonNull( start ); // TODO: Add more such checks for all arguments.

        if ( start.getYear() < 2015 ) {  // TODO: Add more such checks for too far into the past or future, for both start and for stop.

            throw new IllegalArgumentException( "Year of start date is too far in the past. Message # afcd30a0-b639-4ccf-b064-18cc2ea8587b." );

        }

        this.id = id;

        this.dateRange = LocalDateRange.of( start , stop );

    }


    // Alternative constructor.

    public Term ( LocalDateRange dateRange , UUID id ) {

        this( dateRange.getStart() , dateRange.getEnd() , id );

    }




    // --------|  Object  |-------------------------

    @Override

    public String toString ( ) {

        return "Term{ " +

                "id=" + id +

                " | dateRange=" + dateRange +

                " }";

    }


    public UUID getId ( ) {

        return id;

    }


    public LocalDateRange getDateRange ( ) {

        return dateRange;

    }


    @Override

    public boolean equals ( Object o ) {

        if ( this == o ) return true;

        if ( o == null || getClass() != o.getClass() ) return false;

        Term term = ( Term ) o;

        return this.getId().equals( term.getId() );

    }


    @Override

    public int hashCode ( ) {

        return Objects.hash( this.getId() );

    }


    @Override

    public int compareTo ( Object o ) {

        if ( this == o ) return 0;  // If same object.

        if ( o == null || getClass() != o.getClass() ) return 0;

        LocalDate thatStart = ( ( Term ) o ).getDateRange().getStart();

        return this.getDateRange().getStart().compareTo( thatStart );

    }


    static public class StopDateComparator implements Comparator < Term > {


        @Override

        public int compare ( Term t1 , Term t2 ) {

            return t1.getDateRange().getEnd().compareTo( t2.getDateRange().getEnd() );

        }

    }


}

试试看。


public static void main ( String[] args ) {

    Term t1 = new Term( LocalDate.of( 2018 , Month.JUNE , 23 ) , LocalDate.of( 2018 , Month.JULY , 23 ) , UUID.randomUUID() );

    Term t2 = new Term( LocalDate.of( 2018 , Month.JANUARY , 23 ) , LocalDate.of( 2018 , Month.DECEMBER , 23 ) , UUID.randomUUID() );

    Term t3 = new Term( LocalDate.of( 2018 , Month.MARCH , 23 ) , LocalDate.of( 2018 , Month.APRIL , 23 ) , UUID.randomUUID() );

    List < Term > terms = new ArrayList <>( List.of( t1 , t2 , t3 ) );

    System.out.println( "Before natural sort: " + terms );

    Collections.sort( terms );

    System.out.println( "After natural sort: " + terms );

    Collections.sort( terms , new Term.StopDateComparator() );

    System.out.println( "After Comparator sort: " + terms );

}

自然排序前:[Term{ id=27c0b9e6-076f-4ded-9bbd-bf1a2c7914bc | 日期范围=2018-06-23/2018-07-23 },期限{ id=792bf365-eca4-460b-afad-c5cf62cf9a29 | 日期范围=2018-01-23/2018-12-23 },期限{ id=c49f79e1-11cd-4865-aa46-8fbf3c85dbfd | 日期范围=2018-03-23/2018-04-23 }]


自然排序后:[Term{ id=792bf365-eca4-460b-afad-c5cf62cf9a29 | 日期范围=2018-01-23/2018-12-23 },期限{ id=c49f79e1-11cd-4865-aa46-8fbf3c85dbfd | 日期范围=2018-03-23/2018-04-23 },期限{ id=27c0b9e6-076f-4ded-9bbd-bf1a2c7914bc | 日期范围=2018-06-23/2018-07-23 }]


比较器排序后:[Term{ id=c49f79e1-11cd-4865-aa46-8fbf3c85dbfd | 日期范围=2018-03-23/2018-04-23 },期限{ id=27c0b9e6-076f-4ded-9bbd-bf1a2c7914bc | 日期范围=2018-06-23/2018-07-23 },期限{ id=792bf365-eca4-460b-afad-c5cf62cf9a29 | 日期范围=2018-01-23/2018-12-23 }]


abuts

如果您的Term对象应该连续运行,您可以使用该LocalDateRange::abuts方法进行测试。


比较的方法是半开放式,开始是包容性的,结束是排斥性的。因此,一年从一年的第一天开始,一直到但不包括下一年的第一天。您在问题的示例中展示了这一点。


查看完整回答
反对 回复 2022-01-19
?
慕标5832272

TA贡献1966条经验 获得超4个赞

我认为这个问题不仅仅是关于排序,还有关于将重叠的间隔分成更小的部分。您必须经常使用Interval Arithmetic。


使用 Java 8,您可以首先将“术语”编码为时间间隔,它本身就是Comparable. 如果用户指定重叠的间隔,第二部分将把你的间隔分成多个。


class Interval implements Comparable<Interval> {

  private final LocalDateTime start;

  private final LocalDateTime end;


  public Interval(LocalDateTime start, LocalDateTime end) {

     this.start = start;

     this.end = end;

  }


  public int compareTo(Interval that) {

    return this.start.compareTo(that.start);

  }


  public boolean overlaps(Interval that) {

    return !this.isBefore(that) && !this.isAfter(that);

  }


  public boolean contains(Interval that) {

    return this.start.isBefore(that.start) && this.end.isAfter(that.end);

  }


  public boolean isBefore(Interval that) {

    return this.end.isBefore(that.start);

  }


  public boolean isAfter(Interval that) {

    return this.start.isAfter(that.end);

  }


  public Set<Interval> fragment(Interval that) {

    if (that.start.isBefore(this.start)) {

      return that.fragment(this);

    }


    Set<Interval> result = new HashSet<>();

    if (this.end.isBefore(that.start)) {

       result.add(this);

       result.add(that);

       result.add(new Interval(this.end, that.start));

    } else if ((this.end.isAfter(that.start) && this.end.isBefore(that.end)) {

       result.add(new Interval(this.start, that.start);

       result.add(new Interval(that.start, this.end);

       result.add(new Interval(this.end, that.end));

    } else if (this.end.isAfter(that.end)) {

       result.add(new Interval(this.start, that.start);

       result.add(new Interval(that);

       result.add(new Interval(that.end, this.end));

    }

  }

}

您现在可以对它们进行排序,因为Intervals 可以按开始日期进行比较。每当用户输入一个新的Interval(术语)时,您必须通过列表检查它是否contains()存在间隔,或者它是否在它之前,使用isBefore()或isAfter()。如果它overlaps()你必须小心是否还要检查它是否与列表中的下一个间隔重叠。


然后,您可以调用fragment()which 会将 2 个间隔组合成更小的间隔。您需要小心删除以前的。因此,只需浏览列表并检查它们是否重叠可能是有意义的。如果您到达终点,您仍然可以使用fragment()组合两个不相交的间隔。


查看完整回答
反对 回复 2022-01-19
  • 3 回答
  • 0 关注
  • 200 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号