创建X个日期的算法



目前我有一个字符串列表,以yyyyMM格式表示日期,类似于以下内容:

  • 202008
  • 2009年
  • 2010年

我需要在这个列表中创建x个条目,每个条目每月增加一个,所以如果我要创建3个新条目,它们看起来像这样:

  • 202011
  • 2012年
  • 202101

目前我的想法是创建一个方法来选择最新日期,解析字符串以分隔月份和年份,如果月份值<12否则将其设置为1,并改为增加年份。然后,我会将该值添加到列表中,并将其设置为最近的值,重复x次。

我想知道的是,是否有一个更优雅的解决方案可以使用,也许可以使用现有的日期库(我使用的是Java(。

YearMonthDateTimeFormatter

我建议你使用如下所示的现代日期时间类:

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

输出:

[202011, 202012, 202101]
202011
202012
202101

有关现代日期时间API的更多信息,请访问跟踪:日期时间

使用正确的日期-时间对象:年月

不要将日期作为字符串存储在列表中。正如对数字使用int,对布尔值使用boolean一样(我希望如此!(,对日期和时间使用适当的日期-时间对象。对于您的用例,YearMonth类是合适的。

例如,正如将int格式化为包含或不包含千个分隔符的格式以及将boolean格式化为yesno一样,将YearMonth对象格式化为字符串也很简单。所以,当你需要一根绳子的时候就这样做,而不是之前。

扩展这样的YearMonth对象列表的方法是:

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

让我们试试:

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

输出为:

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

格式化为字符串

我答应过你,你可以很容易地掌握你的关系。我建议使用上面印有连字符的格式,原因有两个:(1(它更可读,(2(它是国际标准ISO 8601格式。无论如何,为了证明您可以随心所欲地使用它,我使用了一个格式化程序来生成您使用的无连字符格式:

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

现在,转换为字符串列表只需一行代码(如果编辑器窗口足够宽(:

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

[22008202009202010202011202012202101]

链接

  • Oracle教程:日期时间,解释如何使用java.Time
  • 维基百科文章:ISO 8601

由于您只是在处理字符串,您可以创建一个方法来为您生成字符串日期,并在字符串数组中返回所有这些字符串日期,如下所示:

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

要使用此方法,您需要提供一个字符串开始日期("202008"(和您想要列出的整数月数(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);
}

控制台窗口将显示:

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

最新更新