简体   繁体   English

Java 使用 SimpleDateFormat 比较日期

[英]Java Using SimpleDateFormat to compare dates

Now I am doing a small project.现在我正在做一个小项目。 And this project includes the compare among several dates.这个项目包括几个日期之间的比较。 So I convert "yyyy-MM-dd" to millisecond by using SimpleDateFormat.所以我使用 SimpleDateFormat 将“yyyy-MM-dd”转换为毫秒。 However, it did not work out.但是,它没有成功。 By the way, when I use more easy way, that is, compare year, month and day one by one, it works out.顺便说一句,当我使用更简单的方法时,即逐年比较年、月和日,就可以了。 So the problem is about the SimpleDateFormat.所以问题在于 SimpleDateFormat。

Here are the code:这是代码:

    package GenericsPractice;

public class Employee {
    private String name;
    private int age;
    private MyDate birthday;

    public Employee(String name, int age, MyDate birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public MyDate getBirthday() {
        return birthday;
    }

    public void setBirthday(MyDate birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birthday=" + birthday.toString();
    }

}
    package GenericsPractice;

import java.text.ParseException;
import java.text.SimpleDateFormat;

public class MyDate {
    private int month;
    private int day;
    private int year;

    public MyDate(int month, int day, int year) {
        this.month = month;
        this.day = day;
        this.year = year;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public int getDay() {
        return day;
    }

    public void setDay(int day) {
        this.day = day;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public long dateToMills() throws ParseException {
        String date = (getYear())+"-"+(getMonth())+"-"+(getDay());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        long time = sdf.parse(date).getTime();
        return time;
    }

    @Override
    public String toString() {
        return "month=" + month +
                ", day=" + day +
                ", year=" + year +
                '}';
    }
}

    import GenericsPractice.Employee;
import GenericsPractice.MyDate;

import java.text.ParseException;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class EmployeeTest {
    public static void main(String[] args) {
//        TreeSet<Employee> set = new TreeSet<>(new Comparator<Employee>() {
//            @Override
//            public int compare(Employee o1, Employee o2) {
//                int year = o1.getBirthday().getYear() - o2.getBirthday().getYear();
//                int month = o1.getBirthday().getMonth() - o2.getBirthday().getMonth();
//                int day = o1.getBirthday().getDay() - o2.getBirthday().getDay();
//                if(year != 0){
//                    return year;
//                }
//                if(month != 0){
//                    return month;
//                }
//                if(day != 0){
//                    return day;
//                }
//                return o1.getName().compareTo(o2.getName());
//            }
//        });

        TreeSet<Employee> set = new TreeSet<>(new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                try {
                    return (int)(o1.getBirthday().dateToMills()-o2.getBirthday().dateToMills());
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                throw new RuntimeException("输入类型不一致");
            }
        });

        set.add(new Employee("Chandler",23,new MyDate(10,18,1997)));
        set.add(new Employee("Ross",25,new MyDate(10,18,1992)));
        set.add(new Employee("Joey",20,new MyDate(3,15,1999)));
        set.add(new Employee("Monica",35,new MyDate(12,31,1990)));
        set.add(new Employee("Rachel",21,new MyDate(6,2,1998)));



        Iterator<Employee> iterator = set.iterator();
        while(iterator.hasNext()){
            Employee obj = iterator.next();
            System.out.println(obj);
        }
    }
}

When running, it did not sort by date:运行时,它没有按日期排序:

Employee{name='Chandler', age=23, birthday=month=10, day=18, year=1997}
Employee{name='Monica', age=35, birthday=month=12, day=31, year=1990}
Employee{name='Ross', age=25, birthday=month=10, day=18, year=1992}  
Employee{name='Joey', age=20, birthday=month=3, day=15, year=1999}
Employee{name='Rachel', age=21, birthday=month=6, day=2, year=1998}

You said:你说:

So I convert "yyyy-MM-dd" to millisecond by using SimpleDateFormat所以我使用 SimpleDateFormat 将“yyyy-MM-dd”转换为毫秒

No, do not represent a date as a count of milliseconds.不,不要将日期表示为毫秒数。 And, No, never use SimpleDateFormat .而且,不,永远不要使用SimpleDateFormat These terrible date-time classes were supplanted years ago.这些可怕的日期时间类在几年前就被取代了。 Use only the modern java.time classes defined in JSR 310.仅使用 JSR 310 中定义的现代java.time类。

Your code:你的代码:

private int age;

No, do not store age.不,不要存储年龄。 You can dynamically calculate an age by comparing their date of birth to the current date.您可以通过将他们的出生日期与当前日期进行比较来动态计算年龄。

Also, you need a time zone to calculate age.此外,您需要一个时区来计算年龄。 For any given moment, the current date varies around the globe by time zone.对于任何给定的时刻,当前日期在全球范围内因时区而异。 It is "tomorrow" in Tokyo Japan while simultaneously "yesterday" in Toledo Ohio US.日本东京是“明天”,而美国俄亥俄州托莱多则是“昨天”。

Your code:你的代码:

class MyDate class 我的日期

No, do not invent your own class to represent a date.不,不要发明自己的 class 来表示日期。 We have the java.time.LocalDate class for that.为此,我们有java.time.LocalDate class。

Note that LocalDate implements Comparable .请注意, LocalDate实现Comparable So LocalDate objects know how to compare and sort amongst themselves.所以LocalDate对象知道如何在它们之间进行比较和排序。 This behavior will be useful in code seen below.此行为将在下面看到的代码中很有用。

To simplify your class definition, let's make it a record .为了简化您的 class 定义,让我们record一下。 Records are a new feature in Java 16 , for a class whose main purpose is transparently and immutably carrying data.记录是 Java 16 中的一项新功能,用于 class 的主要目的是透明且不可变地携带数据。 The compiler implicitly creates the constructor, the getters, hashCode & equals , and toString .编译器隐式创建构造函数、getter、 hashCode & equalstoString You could just as well define a conventional class.您也可以定义一个传统的 class。

package org.example;

import java.time.LocalDate;

public record Person( String name , LocalDate dateOfBirth )
{
}

If you want an age-calculator as mentioned above, add a age method.如果您想要上面提到的年龄计算器,请添加age方法。

package org.example;

import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;

public record Person(String name , LocalDate dateOfBirth)
{
    public int age ( ZoneId zoneId ) { return Period.between( this.dateOfBirth , LocalDate.now( zoneId ) ).getYears(); }
}

In real work, I would add an explicit constructor that used Objects.requireNonNull to ensure no null arguments were received.在实际工作中,我会添加一个使用Objects.requireNonNull的显式构造函数,以确保没有收到null arguments。 Ditto for age method, verify ZoneId argument is not null.同上age方法,验证ZoneId参数不是 null。

For specifying our input objects, let's use Set.of syntax.为了指定我们的输入对象,让我们使用Set.of语法。 Then later feed the resulting unmodifiable Set object to our TreeSet .然后稍后将生成的不可修改的Set object 提供给我们的TreeSet

Set < Person > peopleInput =
        Set.of(
                new Person( "Chandler" , LocalDate.of( 1997 , 10 , 18 ) ) ,
                new Person( "Ross" , LocalDate.of( 1992 , 10 , 18 ) ) ,
                new Person( "Joey" , LocalDate.of( 1999 , 3 , 15 ) ) ,
                new Person( "Monica" , LocalDate.of( 1990 , 12 , 31 ) ) ,
                new Person( "Rachel" , LocalDate.of( 1998 , 6 , 2 ) )
        );

Much easier nowadays to use lambda/streams syntax for specifying a Comparator .现在更容易使用 lambda/streams 语法来指定Comparator You could write a conventional comparator as seen in your Question, but doing so is more likely to be incorrect, and less readable.您可以编写一个传统的比较器,如您的问题中所见,但这样做更有可能是不正确的,并且可读性较差。

As discussed in my Answer to your similar Question yesterday, the Comparator / Comparable implementation used in your NavigableSet must be consistent with equals .正如我昨天对您的类似问题的回答中所讨论的,您NavigableSet中使用的Comparator / Comparable实现必须equals一致 If two objects being compared are named a and b , then “consistent with equals” means that where a.equals(b) returns true , so must a.compareTo(b) == 0 return true .如果要比较的两个对象被命名为ab ,那么“与 equals 一致”意味着a.equals(b)返回true ,因此a.compareTo(b) == 0返回true So we must include both member fields name & dateOfBirth as those fields are used in our record's default implementation of equals .因此,我们必须同时包含成员字段namedateOfBirth ,因为这些字段用于我们记录的默认实现equals

Comparator < Person > comparingByDateOfBirthAndThenName =
        Comparator
                .comparing( Person :: dateOfBirth )
                .thenComparing( Person :: name );

Construct our TreeSet using that Comparator object.使用该Comparator器 object 构建我们的TreeSet

NavigableSet < Person > people = new TreeSet <>( comparingByDateOfBirthAndThenName );

Populate with the objects we instantiated via Set.of .填充我们通过Set.of实例化的对象。 As the objects are added, the TreeSet , being a NavigableSet , uses our Comparator object to sort them.添加对象时,作为NavigableSetTreeSet使用我们的Comparator器 object 对它们进行排序。

people.addAll( peopleInput );

Dump to console.转储到控制台。

System.out.println( "peopleInput = " + peopleInput );
System.out.println( "people = " + people );

When run.跑的时候。

peopleInput = [Person[name=Chandler, dateOfBirth=1997-10-18], Person[name=Rachel, dateOfBirth=1998-06-02], Person[name=Joey, dateOfBirth=1999-03-15], Person[name=Ross, dateOfBirth=1992-10-18], Person[name=Monica, dateOfBirth=1990-12-31]]
people = [Person[name=Monica, dateOfBirth=1990-12-31], Person[name=Ross, dateOfBirth=1992-10-18], Person[name=Chandler, dateOfBirth=1997-10-18], Person[name=Rachel, dateOfBirth=1998-06-02], Person[name=Joey, dateOfBirth=1999-03-15]]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM