【问题标题】:Comparing a date of type String比较字符串类型的日期
【发布时间】:2015-11-04 20:55:30
【问题描述】:

我有一个包含名称和日期的任务对象。日期值必须是 String。一个例子是11/9/2015 23:0011/24/2015 12:00 进行比较。 我需要帮助为此编写compareTo(),以便首先显示日期最快的任务。我所拥有的是不正确的,因为它没有正确比较。我知道有其他选择,但我需要使用 String 执行此操作。我考虑过使用.split() 将mm/dd/yyyy 分解为"/",但不知道该怎么做。

public class Task implements Comparable<Task> {
    /** Task name. */
    private String name;
    /** Task due date. */
    private String dueDate;

    /**
     * Initializes a tasks name and due date.
     * @param n Name
     * @param d due date
     */
    public Task(String n, String d) {
        name = n;
        dueDate = d;
    }

    /**
     * Accessor for task name.
     * @return Task name.
     */
    public String getName() {
        return name;
    }

    /**
     * Accessor for task due date.
     * @return Task due date.
     */
    public String getDueDate() {
        return dueDate;
    }

    /**
     * Compares the due dates of the tasks to get the soonest to the front of the list.
     * @param t The task to compare.
     * @return The tasks in chronological order.
     */
    @Override
    public int compareTo(Task t) { //Need help here.
        int val = dueDate.compareTo(t.getDueDate());

        if(val == 0) {
            val = name.compareTo(t.getName());
        }
        if(dueDate.compareTo(t.getDueDate()) > 0) {
            val = -1;
        }
        if(dueDate.compareTo(t.getDueDate()) < 0) {
            val = 1;
        }   
        return val;
    }

【问题讨论】:

  • 能否转换为 Date 对象,然后进行比较?
  • @AbtPst 不,我必须使用String
  • @AlexShesterov 不太重复,因为这个问题是关于日期时间的,而您的链接是关于日期的。这是另一个几乎重复但仅限日期的内容:How to get date in string and compare it using java
  • 您能解释一下为什么您必须使用字符串而不是日期吗?

标签: java string date comparable compareto


【解决方案1】:

您必须将日期作为字符串这一事实并不意味着您不能将其转换为 Date 并使用该类的自然顺序:

@Override
public int compareTo(Task t) {
    // Handling ParseExceptions omitted for bravity's sake
    SimpleDateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm");
    Date d1 = df.parse(dueDate);
    Date d2 = df.parse(t.getDueDate());

    int val = d1.compareTo(d2);

    if(val != 0) {
        return val;    
    }
    return name.compareTo(t.getName());
}

【讨论】:

    【解决方案2】:

    日期时间对象

    我建议您在班级中使用日期时间对象而不是字符串作为成员。

    Java 8 及更高版本包含非常有用的java.time 框架。使用这些新类(灵感来自 Joda-Time)而不是臭名昭著的老类 java.util.Date/.Calendar。

    无需解析日期时间输入字符串。 java.time 框架默认解析ISO 8601 格式的任何字符串。对于其他格式,请定义您预期输入的格式化程序模式,并让 java.time 完成工作。

    时区

    您无法在不知道时区的情况下比较此类日期时间字符串。也许是UTC?或者您是否假设您的所有数据都指的是特定时区?

    在下面的示例中,我任意假设时区为America/Los_Angeles

    示例代码。

    Java 8 中的此示例代码使用 java.time.format 包来解析您的字符串以在构造函数中输入,并再次在 dueDateTimeAsAmericaLosAngeles 方法中生成字符串表示形式。

    通常最好将日期时间值保持在 UTC 时区。然后根据用户或其他软件的预期调整到时区。所以我们在课堂上存储了一个Instant,这是UTC时间线上的一个时刻。对于特定时区,创建一个ZonedDateTime 对象。

    如果您不同意我的建议,坚持将日期时间值存储为字符串,那么您可以通过移动字符串解析到即时发生的位置来修改此代码。

    package timestuff;
    
    import java.time.Instant;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    
    public class Task implements Comparable<Task> {
    
        String title;
        Instant due;
    
        public Task ( String title , String dateTimeAssumedToBeAmericaLosAngles ) {
            this.title = title;
            ZoneId zoneId = ZoneId.of ( "America/Los_Angeles" );
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "M/d/yyyy HH:mm" ).withZone ( zoneId ); // Example data: 11/24/2015 12:00
            this.due = formatter.parse ( dateTimeAssumedToBeAmericaLosAngles , Instant :: from );
        }
    
        @Override
        public String toString () {
            return "Task{ " + "title=" + title + " | instant=" + due + " }";
        }
    
        @Override
        public int compareTo ( Task t ) {
            // Sort by the date-time of when this task is due.
            int result = this.due.compareTo ( t.due );
            return result;
        }
    
        String dueDateTimeAsAmericaLosAngeles () {
            ZoneId zoneId = ZoneId.of ( "America/Los_Angeles" );
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "M/d/yyyy HH:mm" ).withZone ( zoneId ); // Example data: 11/24/2015 12:00
            ZonedDateTime zdt = ZonedDateTime.ofInstant ( this.due , zoneId );
            String output = zdt.format ( formatter );
            return output;
        }
    
        public static void main ( String[] args ) {
            Task t1 = new Task ( "x" , "11/9/2015 23:00" );
            Task t2 = new Task ( "y" , "11/24/2015 12:00" );
            int compared = t1.compareTo ( t2 );
            System.out.println ( "t1: " + t1 + " & t2: " + t2 + " compared: " + compared );
        }
    
    }
    

    运行时:

    t1: 任务{ title=x |即时=2015-11-10T07:00:00Z } & t2: 任务{ 标题=y |即时=2015-11-24T20:00:00Z } 比较:-1

    【讨论】:

      猜你喜欢
      • 2012-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多