suraha
suraha

Reputation: 387

how can i get last 7 days from current day in ascending order in java?

I am using following code to get the last 7 days:

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);
}

And this is giving the following output:

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

But I want this instead:

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

If I use the following line below the code it will give me the correct order:

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

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

But is there any other way to get the last 7 days in ascending order in one shot?

Upvotes: 11

Views: 14052

Answers (10)

MC Emperor
MC Emperor

Reputation: 23047

Here's my two cents, using Streams:

LocalDate start = LocalDate.now().minusDays(6);
Stream.iterate(start, date -> date.plusDays(1))
    .limit(7)
    .toList();

Here's a working example.

As Ole V.V. mentioned in the comments, since Java 9, they've added a convenience method to get a stream of dates: LocalDate::datesUntil.

It then would look like something like this:

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

Because you want the end date to be today, we need to provide now.plusDays(1) as argument to datesUntil. That is because the given date is exclusive.

Upvotes: 2

Basil Bourque
Basil Bourque

Reputation: 340098

The other answers use old outmoded classes or are overly complicated.

java.time

The old date-time classes have been supplanted by the java.time framework built into Java 8 and later, with back-ports to Java 6 & 7 and to Android. The old classes have proven to be poorly designed, confusing, and troublesome. Avoid them.

LocalDate

Among the new classes is LocalDate to represent a date-only value without time-of-day and without time zone. While not stored, a time zone is required to determine “today”. A new dawns earlier in the east, so the date can vary between time zones, “tomorrow” in Paris while “yesterday” in Montréal.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( zoneId );

You can add and subtract. We want to go back a week, so subtract a week.

LocalDate limit = today.minusWeeks( 1 );

Loop a day at a time until we reach the limit. Collect each date as we increment.

A List is an ordered collection, a sequence. The ArrayList class is an appropriate implementation for our needs.

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

Loop while each decremented date is still later than our stopping point (a week ago).

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

Sort

Lastly, sort your list in either direction you desire.

The Collections class (note the plural 's' in name) provides many utility methods. Call sort for natural order. Call reverse for the opposite of natural order.

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

Upvotes: 1

LearningPhase
LearningPhase

Reputation: 1287

Collections.sort

You can use Collections.sort method. It's a static method. You pass it the list and a comparator. It uses a modified mergesort algorithm over the list. That's why you must pass it a comparator to do the pair comparisons. This has been answered before as well.

Sort objects in ArrayList by date?

Upvotes: 1

Jordi Castilla
Jordi Castilla

Reputation: 27003

I would simplify your method a bit, if you want this output you don't need to create an String[] array, either loop twice, you can achieve same with a single for-loop, one Calendar and the 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()));
}

OUTPUT:

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

Working IDEONE demo

Upvotes: 14

Adil
Adil

Reputation: 4623

If the numbers of days is constant you can simply start filling the array from the end (Of course after allocating the table: 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);
}

Upvotes: 0

g-t
g-t

Reputation: 1533

Using java8 and joda you can write something like:

LocalDate weekBeforeToday = LocalDate.now().minusDays(7);
IntStream.rangeClosed(1, 7)
    .mapToObj(weekBeforeToday::plusDays)
    .forEach(System.out::println);

It prints:

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

If you need collection you have to use collector.

In your example you're printing 6 days so I don't now if it's your mistake or you need 6 days instead of 7.

Upvotes: 6

Mr.Turtle
Mr.Turtle

Reputation: 3090

Just loop the other way:

    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]);
    }

This is the output:

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

Upvotes: 2

Kevin Cruijssen
Kevin Cruijssen

Reputation: 9336

Instead of a loop going forward, you can try to use a loop going backwards. Replace the following two lines of your code:

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

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

with:

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

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

OUTPUT:

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

EDIT: Better yet, use Jordi Castilla's solution.

Upvotes: 0

assylias
assylias

Reputation: 328863

Here is a suggestion:

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);
}

And possibly even clearer, using a list:

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);
}

Upvotes: 2

Guillaume Barr&#233;
Guillaume Barr&#233;

Reputation: 4228

Try this :

Change daysto an array of Date and then convert it to list and sort the list with 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));
    }

}

Upvotes: 0

Related Questions