Algorithm to create X number of dates

253 views Asked by At

Currently I have a list of Strings that represent a date in a yyyyMM format, something like this:

  • 202008
  • 202009
  • 202010

I need to create x number of entries in this list with each entry increasing the month by one, so if I were to create 3 new entries they would look like this:

  • 202011
  • 202012
  • 202101

Currently my idea is to create a method to pick the latest date, parse the String to separate month and year, increase the month value by 1 if it is < 12 otherwise set it to 1 and increase the year instead. Then I would add that value to a list and set it as the most recent, repeating x number of times.

What I want to know is if there is a more elegant solution that I could use, maybe using an existing date library (I'm using Java).

3

There are 3 answers

0
Arvind Kumar Avinash On BEST ANSWER

YearMonth And DateTimeFormatter

I recommend you do it using these modern date-time classes as shown below:

import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        // Test
        List<String> list = getYearMonths("202011", 3);
        System.out.println(list);

        // Bonus: Print each entry of the obtained list, in a new line
        list.forEach(System.out::println);
    }

    public static List<String> getYearMonths(String startWith, int n) {
        List<String> list = new ArrayList<>();

        // Define Formatter
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMM");

        // Parse the year-month string using the defined formatter
        YearMonth ym = YearMonth.parse(startWith, formatter);

        for (int i = 1; i <= n; i++) {
            list.add(ym.format(formatter));
            ym = ym.plusMonths(1);// Increase YearMonth by one month
        }
        return list;
    }
}

Output:

[202011, 202012, 202101]
202011
202012
202101

Learn more about the modern date-time API at Trail: Date Time.

0
DevilsHnd - 退した On

Since you're just dealing with strings you could just create a method to produce the string dates for you and return all those string dates in a String Array, like this:

public static String[] addMonthsToDateString(String startDate, int monthsToAdd) {
    // Break the string date down to integers Year and month.
    int year = Integer.valueOf(startDate.substring(0, 4));
    int month = Integer.valueOf(startDate.substring(4));
    // Calculate the number of iterations we need.
    int loopCount = ((month + monthsToAdd) - month);
    // Declare and initialize the String Array we will return.
    String[] stringDates = new String[loopCount];
    
    // Generate the required Date Strings
    for (int i = 0; i < loopCount; i++) {
        stringDates[i] = new StringBuilder("").append(year)
                         .append(String.format("%02d", month)).toString();
        month++;
        if (month == 13) {
            year++;
            month = 1;
        }
    }
    return stringDates;
}

To use this method you would need to supply a string start date ("202008") and the integer number of months you want to list (24):

// Get the desired list of string dates:
String[] desiredDates = addMonthsToDateString("202008", 24);

// Display the string dates produced into the Console Window:
for (String strg : desiredDates) {
    System.out.println(strg);
}

The Console Window will display:

202008
202009
202010
202011
202012
202101
202102
202103
202104
202105
202106
202107
202108
202109
202110
202111
202112
202201
202202
202203
202204
202205
202206
202207
0
Anonymous On

Use proper date-time objects: YearMonth

Don’t store your dates as strings in your list. Just as you use int for numbers and boolean for Boolean values (I hope!), use proper date-time objects for dates and times. For your use case the YearMonth class is appropriate.

And just as it’s easy to format an int into a format with or without thousand separators and a boolean into yes or no, for example, formatting your YearMonth objects into strings is trivial. So do that when you need a string, not before.

A method for extending such a list of YearMonth objects would be:

public static void extendDateList(List<YearMonth> dates, int numberOfNewDates) {
    if (dates.isEmpty()) {
        throw new IllegalArgumentException("List is empty; don’t know where to pick up");
        // Or may start from some fixed date or current month
    } else {
        YearMonth current = Collections.max(dates);
        for (int i = 0; i < numberOfNewDates; i++) {
            current = current.plusMonths(1);
            dates.add(current);
        }
    }
}

Let’s try it out:

    List<YearMonth> dates = new ArrayList<YearMonth>(List.of(
            YearMonth.of(2020, Month.AUGUST), 
            YearMonth.of(2020, Month.SEPTEMBER),
            YearMonth.of(2020, Month.OCTOBER)));
    
    extendDateList(dates, 3);
    
    System.out.println(dates);

Output is:

[2020-08, 2020-09, 2020-10, 2020-11, 2020-12, 2021-01]

Formatting into strings

I promised you you could easily have your strings. I would suggest using the format with a hyphen printed above for two reasons: (1) it’s more readable, and (2) it’s ISO 8601 format, the international standard. In any case, to demonstrate that you can have it just the way you want, I am using a formatter to produce the hyphen-less format that you used:

private static final DateTimeFormatter YEAR_MONTH_FORMATTER
        = DateTimeFormatter.ofPattern("uuuuMM");

Now converting to a list of strings is a one-liner (if your editor window is wide enough):

    List<String> datesAsStrings = dates.stream()
            .map(YEAR_MONTH_FORMATTER::format)
            .collect(Collectors.toList());
    System.out.println(datesAsStrings);

[202008, 202009, 202010, 202011, 202012, 202101]

Links