【问题标题】:Sort date and time values对日期和时间值进行排序
【发布时间】:2017-02-03 14:48:42
【问题描述】:

简单地说,我有一个包含不同日期和时间的字符串数组。每个元素都采用这种格式:

2015-08-27T22:24:31.903

即YYYY-MM-DDTHH:MM:SS.MMM

我正在整理它们。是否有可用的默认方法对这种格式进行排序?

我现在正在做的是在 T 处拆分字符串,将日期和时间转换为相应的时间戳,添加它们,然后对时间戳值进行排序。是否有这种格式的直接解析器可用?更好的解决方案是最受欢迎的。

【问题讨论】:

  • 您可以简单地对字符串进行排序,因为它们采用ISO-8601 格式,这使得它们易于排序。无需转换。
  • 不要将日期和时间保存为字符串。就像您不将数字保留为字符串一样(我希望!)保留正确的日期时间对象,例如 LocalDateTime(来自 java.time, the modern Java date and time API)。此类实现Comparable,即具有与时间顺序一致的自然顺序,因此易于排序。

标签: java sorting date time timestamp


【解决方案1】:

我有一个字符串数组。每个元素都采用这种格式:2015-08-27T22:24:31.903。是否有可用的默认方法对这种格式进行排序?

是的。由于 ISO 字符串有按数量级降序排列的日期字段,并且字段是固定宽度的,因此您可以直接使用 Arrays.sort(Object[] a) 简单地对字符串进行排序: 将指定的对象数组按照自然顺序升序排序它的元素。

是否有适用于这种格式的直接解析器?

是的。 LocalDateTime.parse(CharSequence text)2007-12-03T10:15:30等文本字符串中获取LocalDateTime的实例。

【讨论】:

  • 这个程序是否可以用来对这种格式的时间戳进行排序2016-08-16T06:31:34Z
【解决方案2】:

我认为这些是字符串。如果您不想做明显的事情(将它们转换为 LocalDateTime¹ 并比较结果),您可以将它们作为字符串进行比较,即特定的日期时间格式(几乎完整的 ISO-8601 时间戳,只是缺少时区指示器)在您使用字符串比较时正常工作。

免费示例 (live copy):

import java.util.*;

class Example
{
    public static void main (String[] args)
    {
        String[] strings = {
            "2002-10-24T13:51:25.417",
            "2001-03-25T23:41:24.234",
            "2008-10-05T04:41:56.004",
            "2013-04-10T22:14:06.852",
            "2005-08-24T05:05:01.080",
            "2015-11-20T17:32:27.303",
            "2003-07-16T06:32:07.703",
            "2005-03-20T08:28:18.440",
            "2009-04-17T13:20:09.499",
            "2002-11-04T06:39:55.287"
        };
        Arrays.sort(strings);
        for (String s : strings) {
            System.out.println(s);
        }
    }
}

输出:

2001-03-25T23:41:24.234 2002-10-24T13:51:25.417 2002-11-04T06:39:55.287 2003-07-16T06:32:07.703 2005-03-20T08:28:18.440 2005-08-24T05:05:01.080 2008-10-05T04:41:56.004 2009-04-17T13:20:09.499 2013-04-10T22:14:06.852 2015-11-20T17:32:27.303

当然,如果您需要不同的顺序(例如逆序),您可以提供Comparator


¹ 或 Instant,如果这些实际上是 UTC 日期/时间,但您需要在解析之前将 Z 添加到字符串的末尾。

【讨论】:

  • 实际上,您可以将这些特定值转换为 java.time.LocalDateTime 而不是 Instant
  • @BasilBourque - 啊,是的,确实如此——Instant 想要在字符串上使用 Z,这可能是不正确的。谢谢!
【解决方案3】:

使用现代 Java

Answer by Andreas 是正确的。这是一个变体,它使用了添加到更高版本 Java 中的新功能。

使用List.of 制作一些示例数据。结果列表是不可修改的。因此,将不可修改的列表提供给ArrayList 的构造函数,以获得我们可以排序的可修改列表。

List < String > strings = new ArrayList <>(
        List.of(
                "2015-08-27T22:24:31.903" ,
                "2018-08-27T22:24:31.903" ,
                "2016-08-27T22:24:31.903" ,
                "2017-08-27T22:24:31.903"
        )
);

按文本排序

如其他答案中所述,您的字符串采用标准 ISO 8601 格式。该特定格式设计为按字母顺序排序时按时间顺序排列。因此,如果此任务是您获取此数据的唯一目标,则无需将其解析为日期时间对象。只需按文本排序,如String 对象。

List 接口没有使用Collections 实用程序类,而是获得了sort 方法。该方法需要Comparator。我们可以调用Comparator.naturalOrder() 来生成实例,而不是实现该接口。

strings.sort( Comparator.naturalOrder() );

转储到控制台。

System.out.println( "strings = " + strings );

看到这个code run live at IdeOne.com

字符串 = [2015-08-27T22:24:31.903, 2016-08-27T22:24:31.903, 2017-08-27T22:24:31.903, 2018-08-27T22:24:31.903]

按日期时间对象排序

如果您将进一步使用此输入,则将其解析为日期时间对象。

现代方法使用 java.time 类。

我们可以简化示例数据,因为我们可以直接使用由List.of 生成的不可修改的List

List < String > strings =
        List.of(
                "2015-08-27T22:24:31.903" ,
                "2018-08-27T22:24:31.903" ,
                "2016-08-27T22:24:31.903" ,
                "2017-08-27T22:24:31.903"
        );

LocalDateTime 对象中的List 设为空。

List < LocalDateTime > ldts = new ArrayList <>( strings.size() );

通过一次解析一个输入字符串来填充该列表,生成一个LocalDateTime 对象。将该对象添加到我们的列表中。

请注意,java.time 类默认使用 ISO 8601 格式。所以不需要指定格式模式。

for ( String string : strings )
{
    ldts.add( LocalDateTime.parse( string ) );  // Parsing text in ISO 8601 format needs no formatting pattern to be specified.
}

排序,就像我们在上面所做的那样。致电List::sort,传递Comparator

ldts.sort( Comparator.naturalOrder() ) ;

看到code run live at IdeOne.com

System.out.println( "ldts = " + ldts );

如果我们想要花哨的话,我们可以用Stream 替换for 循环。我们可以单线完成这项工作。

List < String > strings =
        List.of(
                "2015-08-27T22:24:31.903" ,
                "2018-08-27T22:24:31.903" ,
                "2016-08-27T22:24:31.903" ,
                "2017-08-27T22:24:31.903"
        );

List < LocalDateTime > ldts = 
    strings
    .stream()
    .map( s -> LocalDateTime.parse( s ) )
    .sorted()
    .collect( Collectors.toList() )
;

System.out.println( "ldts = " + ldts );

ldts = [2015-08-27T22:24:31.903, 2016-08-27T22:24:31.903, 2017-08-27T22:24:31.903, 2018-08-27T22:24:31.903]

【讨论】:

    【解决方案4】:

    1) 使用适当的 SimpleDateFormat 解析字符串:

    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-ddTHH:mm:ss.SSS");
    try {
        Date date = formatter.parse(dateInString);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    

    2) 将每个日期存储在一个列表中。为此,首先实例化一个新列表...

    ArrayList<Date> myDates = new ArrayList<Date>();
    

    ...在解析命令之后将每个日期添加到列表中:

    myDates.add(date);
    

    3) 使用以下方法对它们进行排序:

    Collections.sort(myDates); // Ascending
    

    Collections.sort(myDates, Collections.reverseOrder()); // Descending
    

    【讨论】:

    • 无需解析为Date,因为字符串是可排序的。
    【解决方案5】:

    使用日历 API 对日期和时间进行排序

    import java.util.ArrayList;
    import java.util.Collections;
    
    public class SortMain {
    
        public static void main(String[] args) {
    
            ArrayList<SomeObj> al= new ArrayList();
    
            SomeObj s1 = new SomeObj("9", "2020-02-05");
            al.add(s1);
            s1 = new SomeObj("7", "2020-02-05");
            al.add(s1);
            /*s1 = new SomeObj("15", "2019-12-25");
            al.add(s1);
            s1 = new SomeObj("6", "2019-12-25");
            al.add(s1);*/
    
            printArrayList(al);
    
            Collections.sort(al);
    
            System.out.println("*************");
    
            printArrayList(al);
    
        }
    
        private static void printArrayList(ArrayList<SomeObj> al) {
            for(SomeObj someObj: al) {
                System.out.println(someObj.getDate() + " ** " + someObj.getTime());
            }
        }
    }
    

    还有,

    package com.karthik.sorting;
    
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    
    public class SomeObj implements Comparable<SomeObj>{
    
        private String time;
        private String date;
    
        public SomeObj(String time, String date) {
            super();
            this.time = time;
            this.date = date;
        }
        public String getTime() {
            return time;
        }
        public void setTime(String time) {
            this.time = time;
        }
        public String getDate() {
            return date;
        }
        public void setDate(String date) {
            this.date = date;
        }
    
         @Override
         public int compareTo(SomeObj siteHealthGraphItem) {
             String receivedPattern = "yyyy-MM-dd";
             SimpleDateFormat simpleDateFormat = new SimpleDateFormat(receivedPattern);
             try {
                 Date date1 = simpleDateFormat.parse(getDate().toString());
                 Date date2 = simpleDateFormat.parse(siteHealthGraphItem.getDate().toString());
    
                 if (getTime() == null) {
                     return date1.compareTo(date2);
                 } else if (getTime() != null) {
    
                     Calendar cal1 = Calendar.getInstance();
                     cal1.setTime(date1);
                     cal1.set(Calendar.HOUR_OF_DAY, Integer.parseInt(getTime()));
    
                     Calendar cal2 = Calendar.getInstance();
                     cal2.setTime(date2);
                     cal2.set(Calendar.HOUR_OF_DAY, Integer.parseInt(siteHealthGraphItem.getTime()));
    
                     return cal1.compareTo(cal2);
                 }
             } catch (Exception e) {
                 System.out.println("Data is improper - Sorting Did not work..!");
                 e.printStackTrace();
             }
             System.out.println("Sorting Did not work..!");
             return 0;
         }
    
    
    }
    

    【讨论】:

    • 请不要教年轻人使用早已过时且臭名昭著的SimpleDateFormat类。至少不是第一选择。而且不是没有任何保留。今天我们在java.time, the modern Java date and time API, 和它的DateTimeFormatter 中做得更好。
    猜你喜欢
    • 2022-01-14
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多