在Java中如何按升序获取从当前日期起的最近7天?

11

我正在使用以下代码获取过去的 7 天:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd ");
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
String[] days = new String[6];
days[0] = sdf.format(date);

for(int i = 1; i < 6; i++){
    cal.add(Calendar.DAY_OF_MONTH, -1);
    date = cal.getTime();
    days[i] = sdf.format(date);
}

for(String x: days){
    System.out.println(x);
}

这将产生以下输出:

2016-04-14
2016-04-13
2016-04-12
2016-04-11
2016-04-10
2016-04-09

但是我想要这个:

2016-04-09
2016-04-10
2016-04-11
2016-04-12
2016-04-13
2016-04-14
如果我在代码下方使用以下行,它将给出正确的顺序:

如果我在代码下面加入以下这一行,就能按照正确的顺序排列:

List<String> list = Arrays.asList(days);
Collections.reverse(list);
days = (String[]) list.toArray();

for(String x: days){
    System.out.println(x);
}

但是否有其他方法可以一次性以升序获取过去7天的数据?


5
你可以先减去7天,然后在循环中每次加1,这样怎么样? - Peter Lawrey
在处理时间/日期时,请使用http://www.joda.org/joda-time/! - Exceptyon
10个回答

13

如果你想得到这个输出,我会稍微简化你的方法。你不需要创建一个String[]数组,也不必循环两次。你可以用一个单独的for-loop、一个Calendar和一个SimpleDateFormat来实现同样的效果。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd ");
Calendar cal = Calendar.getInstance();
// get starting date
cal.add(Calendar.DAY_OF_YEAR, -6);

// loop adding one day in each iteration
for(int i = 0; i< 6; i++){
    cal.add(Calendar.DAY_OF_YEAR, 1);
    System.out.println(sdf.format(cal.getTime()));
}

输出:

2016-04-09 
2016-04-10 
2016-04-11 
2016-04-12 
2016-04-13 
2016-04-14 

IDEONE工作演示


6
使用Java8和Joda,您可以编写类似以下内容的代码:
LocalDate weekBeforeToday = LocalDate.now().minusDays(7);
IntStream.rangeClosed(1, 7)
    .mapToObj(weekBeforeToday::plusDays)
    .forEach(System.out::println);

它打印出:

2016-04-08
2016-04-09
2016-04-10
2016-04-11
2016-04-12
2016-04-13
2016-04-14

如果您需要收集数据,则必须使用 collector。

在您的例子中,您输出了六天,所以我不知道是您的错误还是您确实需要六天而不是七天。


2

这里有一个建议:

String[] days = new String[6];

for (int i = 0; i < days.length; i++) {
  days[i] = LocalDate.now().minusDays(days.length - i - 1).toString();
}

for (String x : days) {
  System.out.println(x);
}

使用列表更加清晰明了:

List<String> days = new ArrayList<> ();
LocalDate now = LocalDate.now();

for (LocalDate d = now.minusDays(5); !d.isAfter(now); d = d.plusDays(1)) {
  days.add(d.toString());
}

for (String x : days) {
  System.out.println(x);
}

2

反向循环即可:

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd ");
    Calendar cal = Calendar.getInstance();
    Date date=cal.getTime();
    String[] days = new String[6];
    days[0]=sdf.format(date);

    for(int i = 1; i< 6; i++){
        cal.add(Calendar.DAY_OF_MONTH,-1);
           date=cal.getTime();
           days[i]=sdf.format(date);
    }

    for(int i = (days.length-1); i >= 0; i--){
        System.out.println(days[i]);
    }

这是输出结果:

2016-04-09 
2016-04-10 
2016-04-11 
2016-04-12 
2016-04-13 
2016-04-14 

1

1
这是我的建议,使用流(Streams):
LocalDate start = LocalDate.now().minusDays(6);
Stream.iterate(start, date -> date.plusDays(1))
    .limit(7)
    .collect(Collectors.toList());

这里是一个工作示例

正如Ole V.V.在评论中提到的那样,自Java 9以来,他们已经添加了一个方便的方法来获取日期流:LocalDate::datesUntil

然后它看起来会像这样:

LocalDate now = LocalDate.now();
now.minusDays(6).datesUntil(now.plusDays(1))
    .collect(Collectors.toList());

因为您希望结束日期是今天,所以我们需要将now.plusDays(1)作为参数提供给datesUntil。这是因为给定的日期是排除在外的。

@OleVV 我忘记了,你说得对。我会在答案中包含这个。 - MC Emperor

1
其他答案使用过时的类或过于复杂。

java.time

旧的日期时间类已被Java 8及更高版本内置的java.time框架所取代,可回溯到Java 6&7和Android。旧的类被证明设计不佳、令人困惑和麻烦。请避免使用它们。
其中一个新类是LocalDate,用于表示仅包含日期值而不包含时间和时区的数值。虽然没有存储,但需要时区来确定“今天”。新的一天在东部早些时候开始,因此日期可以在不同的时区之间变化,在巴黎可能是“明天”,而在蒙特利尔则可能是“昨天”。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( zoneId );

您可以进行加法和减法运算。我们想要回到一周前,因此需要减去一周。

LocalDate limit = today.minusWeeks( 1 );

循环每天直到达到限制,同时收集每个日期作为我们的递增。 List 是一个有序的集合,一个序列。 ArrayList 类是我们需求的适当实现。
List< LocalDate > list = new ArrayList<>();

当每个递减的日期仍晚于我们的停止点(一周前)时,循环。

LocalDate localDate = today;
while ( localDate.isAfter( limit ) ) {
    list.add( localDate );
    // Setup next loop.
    localDate = localDate.minusDays( 1 );
}

排序

最后,按照您需要的任何方向对列表进行排序。

Collections类(注意名称中的复数's')提供了许多实用方法。调用sort以进行自然排序。调用reverse以进行相反的自然排序。

Collections.sort( list );
Collections.reverse( list );

0
尝试这个:
days更改为Date数组,然后将其转换为列表,并使用Collections.sort(list);对列表进行排序。
public static void main(String[] args) {

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd ");
    Calendar cal = Calendar.getInstance();
    Date date=cal.getTime();
    Date[] days = new Date[6];
    days[0]= date;

    for(int i = 1; i< 6; i++){
        cal.add(Calendar.DAY_OF_MONTH,-1);
           date=cal.getTime();
           days[i]=date;
    }

    List<Date> list = Arrays.asList(days);
    Collections.sort(list);

    for(Date x: days){
        System.out.println(sdf.format(x));
    }

}

0

与其使用向前的循环,您可以尝试使用向后的循环。请替换您代码中以下两行:

days[0] = sdf.format(date);

for(int i = 1; i < 6; i++){

使用:

days[days.length - 1] = sdf.format(date);

for(int i = days.length - 2; i >= 0; i--){

输出:

2016-04-14
2016-04-13
2016-04-12
2016-04-11
2016-04-10
2016-04-09

编辑:更好的方法是使用Jordi Castilla的解决方案


0
如果天数是恒定的,您可以从数组末尾开始填充(当然,在分配表格后:new String[DAYS]):
private static final DAYS = 6;
//...
for(int i = DAYS; i >= 0; i--){
     cal.add(Calendar.DAY_OF_MONTH,-1);
     date = cal.getTime();
     days[i] = sdf.format(date);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接