0

This problem has been bugging me. I've googled around and found increment in java from current date but I want it starting from a certain date in the past.

For example, let's start with this date in this format:

"1986-09-20"

How can I increment the days so that the example above becomes "1986-09-27" and with one more increment it becomes "1986-10-4" all the way until the end of the year by which it becomes "1987-01-03"

I understand that I can just increment the date using += 7 on the day and if it surpasses say 30 then increment the month but I don't know how I can account for days that are either 30 or 31 or February's leap day.

I've been looking at the documentation for Calendar and notice that it may hold the solution but I don't know how/where to start.

I want to result format to be yyyy-mm-dd NOT the Java date format which is Day Month dd time time-zone yyyy

Aeternus
  • 346
  • 4
  • 15
  • Possible duplicate of [How can I increment a date by one day in Java?](http://stackoverflow.com/questions/428918/how-can-i-increment-a-date-by-one-day-in-java) – Jonny Henly Aug 09 '16 at 18:29
  • Do you have any example code to show? – Dominic Aug 09 '16 at 18:47
  • I tried this code from the link Jonny Henly gave and it didn't work: `String start = "1986-09-20"; LocalDate parsedDate = LocalDate.parse(start); LocalDate addedDate = parsedDate.plusDays(7); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-mm-dd"); String result = addedDate.format(formatter); System.out.println(result);` – Aeternus Aug 09 '16 at 19:02
  • Your question is confusing. Is day-of-week the issue? If the input date is a Tuesday, do you want the first Tuesday of the following month? – Basil Bourque Aug 09 '16 at 21:53
  • @BasilBourque No, not the first Tuesday of the following month. I want to increment by 7 days in the format that I put and keep doing that while incrementing the month once it reaches over the month's days. Then once it hits the maximum month, it will increment the year. – Aeternus Aug 09 '16 at 22:05
  • Isn't adding 7 days just another way of saying “the same day of week”? Important point as that wording points the way to the solution in [my Answer](http://stackoverflow.com/a/38861175/642706). – Basil Bourque Aug 09 '16 at 22:10
  • @BasilBourque Yes, it's another way of saying the same day of the week. However, I specifically said 7 days because I don't care about the day of the week (Monday, Tuesday, etc.) for the purposes of why I need the code. I was more concerned with the integer increments. – Aeternus Aug 09 '16 at 22:14
  • As I said, thinking in terms of "day of week" leads to the solution in java.time. Specifically, [`TemporalAdjusters.nextOrSame( DayOfWeek )`](http://docs.oracle.com/javase/8/docs/api/java/time/temporal/TemporalAdjusters.html#nextOrSame-java.time.DayOfWeek-). See [my Answer](http://stackoverflow.com/a/38861175/642706). – Basil Bourque Aug 09 '16 at 22:26
  • So java.time is the most up-to-date? Just read your answer. I may come back it as reference. Thanks – Aeternus Aug 09 '16 at 22:32
  • @flwy_h Yes, java.time is the preeminent date-time framework for Java. It supplants the old date-time classes bundled with the earliest versions of Java, and it supplants the Joda-Time framework, as noted in my answer. – Basil Bourque Aug 10 '16 at 06:54

3 Answers3

2

The other Answers are correct but outdated.

Strings != Date-Times

I want to result format to be yyyy-mm-dd NOT the Java date format which is Day Month dd time time-zone yyyy

You are confusing a date-time value with a String that represents that value. So there is no such thing as a “Java date format”. You can generate a String in any format you desire, or generate one automatically in a localized format.

The input string you desire is a standard ISO 8601 format. The java.time classes use these standard formats by default.

java.time

The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat. The Joda-Time team also advises migration to java.time.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

LocalDate

The LocalDate class represents a date-only value without time-of-day and without time zone.

LocalDate start = LocalDate.parse( "1986-09-20" );

This class can do math, adding years and weeks as you desire.

Apparently you want to start with the first occurrence of the day-of-week of your input date in the following month. The TemporalAdjuster interface and TemporalAdjusters class (note the plural) provide such assistance. In particular, TemporalAdjusters.nextOrSame( DayOfWeek ) where DayOfWeek is a handy enum for the seven days of the week.

DayOfWeek dow = start.getDayOfWeek();
LocalDate monthLater = start.plusMonths( 1 );  // If day 29-31 not found in following month, the last day of month is used instead. So always next month, not two months out.
LocalDate firstOfNextMonth = monthLater.withDayOfMonth( 1 );
TemporalAdjuster adjuster = TemporalAdjusters.nextOrSame( dow );
LocalDate firstDayOfWeekOfNextMonth = firstOfNextMonth.with( adjuster );

And a year later.

LocalDate yearLaterFromFirstDayOfWeekOfNextMonth = firstDayOfWeekOfNextMonth.plusYears( 1 );

Strings

To generate a String in your desired ISO 8601 standard format, simply call toString().

String output = yearLaterFromFirstDayOfWeekOfNextMonth.toString();

Looping

You can loop date-time values by testing with equals,compareTo, isEqual, isBefore, and isAfter methods found on the various java.time classes.

LocalDate ld = start;
while ( ! ld.isAfter( firstDayOfWeekOfNextMonth ) ) {
    String output = ld.toString();
    …
    // Prepare for next loop.
    ld = ld.plusWeeks( 1 );
}

I suggest determining your boundary dates first, to keep the business logic clear. Then afterwards do the looping week-by-week as that is incidental to the logic. Mixing the two issues (boundary dates & week-by-week) is what makes your Question confusing.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

Is the following what you are looking for?

Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(1986, 8, 20);
int year = cal.get(Calendar.YEAR);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
while (year >= cal.get(Calendar.YEAR)) {
    cal.add(Calendar.DAY_OF_MONTH, 7);
    System.out.println(sdf.format(cal.getTime()));
}

the output:

1986-09-27
1986-10-04
1986-10-11
1986-10-18
1986-10-25
1986-11-01
1986-11-08
1986-11-15
1986-11-22
1986-11-29
1986-12-06
1986-12-13
1986-12-20
1986-12-27
1987-01-03

ujulu
  • 3,289
  • 2
  • 11
  • 14
  • Just tried it and it works. Will it account for leap years and 30 or 31 end of month days? – Aeternus Aug 09 '16 at 19:19
  • As far as I know it should not play any role whether you have a leap year or a month is of 30 or 31 days. October and December are 31 days and November 30 days, and as you can see from the output it increases correctly. – ujulu Aug 09 '16 at 19:24
  • The reason I ask is because I'm going to use this for many years up to 2006. The example I posted above was a small scale one. – Aeternus Aug 09 '16 at 19:26
  • Would GregorianCalendar work just as well with the code you provided? Just in case of leap year, etc. – Aeternus Aug 09 '16 at 19:28
  • Never mind just tested the leap year outputs and it works! – Aeternus Aug 09 '16 at 19:38
  • You can just experiment with that, for example, year 2000 is a leap year. The GregorianCalendar will work too; just substitute it for `Calendar.getInstance()` with `new GregorianCalendar(2000, 8, 20)` and remove `cal.clear()` and cal.set(..)`. – ujulu Aug 09 '16 at 19:39
0

Use Joda Time if you can. It will make everything a lot easier and it deals with leap years etc.

here is an example of how simple it is:

DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MM-dd");
DateTime dateTime = dtf.parseDateTime("1986-09-20");

DateTime result = dateTime.plusDays(7);
System.out.println("Result: " + dtf.print(result));
rptmat57
  • 3,643
  • 1
  • 27
  • 38
  • 1
    That's not really an answer to OP's question, it's just a statement of library preference. Show how to do it in Joda Time. – Sameer Puri Aug 09 '16 at 18:37
  • I am going to try this one out, I'll come back to edit this comment – Aeternus Aug 09 '16 at 19:07
  • Just tried it out with this code: `org.joda.time.format.DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MM-dd"); DateTime dateTime = dtf.parseDateTime("1986-09-20"); Date result = dateTime.plusDays(7).toDate(); System.out.println("Result: " + result);` The result was this: `Result: Sat Sep 27 00:00:00 PDT 1986` which is not the format I was looking for. – Aeternus Aug 09 '16 at 19:15
  • use dtf.print(dateTime.plusDays(7)); – rptmat57 Aug 09 '16 at 19:18
  • the dtr.print method isn't working as it gives a not correct type error. – Aeternus Aug 09 '16 at 19:22