英文:
Algorithm to create X number of dates
问题
目前我有一个字符串列表,表示以yyyyMM格式表示的日期,类似于这样:
- 202008
- 202009
- 202010
我需要在这个列表中创建x个条目,每个条目的月份增加一,所以如果我要创建3个新条目,它们将如下所示:
- 202011
- 202012
- 202101
目前我的想法是创建一个方法来选择最新的日期,解析字符串以分离月份和年份,如果月份小于12,则将月份值增加1,否则将其设置为1并增加年份。
然后我会将该值添加到列表中,并将其设置为最新的日期,重复x次。
我想知道的是是否有更优雅的解决方案,也许可以使用现有的日期库(我正在使用Java)。
英文:
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).
答案1
得分: 2
YearMonth
与DateTimeFormatter
我建议您按照以下示例使用现代日期时间类来完成:
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) {
// 测试
List<String> list = getYearMonths("202011", 3);
System.out.println(list);
// 奖励:在新行中打印获得列表的每个条目
list.forEach(System.out::println);
}
public static List<String> getYearMonths(String startWith, int n) {
List<String> list = new ArrayList<>();
// 定义格式化器
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMM");
// 使用定义的格式化器解析年月字符串
YearMonth ym = YearMonth.parse(startWith, formatter);
for (int i = 1; i <= n; i++) {
list.add(ym.format(formatter));
ym = ym.plusMonths(1); // 增加一个月的YearMonth
}
return list;
}
}
输出:
[202011, 202012, 202101]
202011
202012
202101
在**日期时间教程**中了解更多关于现代日期时间 API 的内容。
英文:
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.
答案2
得分: 2
使用正确的日期时间对象:YearMonth
不要将日期存储为字符串在你的列表中。就像你使用 int
表示数字和 boolean
表示布尔值一样(我希望是这样的!),对于日期和时间,请使用正确的日期时间对象。在你的用例中,YearMonth
类是合适的选择。
就像将 int
格式化为带有千位分隔符或不带千位分隔符的格式,将 boolean
格式化为“是”或“否”一样,将你的 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");
// 或者可以从某个固定日期或当前月份开始
} 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);
输出结果是:
[202008, 202009, 202010, 202011, 202012, 202101]
链接
- Oracle 教程:Date Time 解释了如何使用 java.time。
- 维基百科文章:ISO 8601
英文:
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
- Oracle tutorial: Date Time explaining how to use java.time.
- Wikipedia article: ISO 8601
答案3
得分: 0
public static String[] addMonthsToDateString(String startDate, int monthsToAdd) {
int year = Integer.valueOf(startDate.substring(0, 4));
int month = Integer.valueOf(startDate.substring(4));
int loopCount = ((month + monthsToAdd) - month);
String[] stringDates = new String[loopCount];
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;
}
// Usage example:
String[] desiredDates = addMonthsToDateString("202008", 24);
for (String strg : desiredDates) {
System.out.println(strg);
}
Console Output:
202008
202009
202010
202011
202012
202101
202102
202103
202104
202105
202106
202107
202108
202109
202110
202111
202112
202201
202202
202203
202204
202205
202206
202207
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论