问题描述
我正在尝试获取Java中两个日期之间的月份列表(实际上是该月份的第一天),但是我没有得到预期的结果。
开始日期为“ 3/17/2020”,结束日期为“ 3/17/2021”,预期结果如下:
"01-Mar-2020"
"01-Apr-2020"
"01-May-2020"
"01-Jun-2020"
"01-Jul-2020"
"01-Aug-2020"
"01-Sep-2020"
"01-Oct-2020"
"01-Nov-2020"
"01-Dec-2020"
"01-Jan-2021"
"01-Feb-2021"
"01-Mar-2021"
以下是我正在使用的代码:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class Main {
public static void main(String[] args) {
String date1 = "3/17/2020";
String date2 = "3/17/2021";
DateFormat formater = new SimpleDateFormat("MM/dd/yyyy");
Calendar beginCalendar = Calendar.getInstance();
Calendar finishCalendar = Calendar.getInstance();
try {
beginCalendar.setTime(formater.parse(date1));
finishCalendar.setTime(formater.parse(date2));
} catch (ParseException e) {
e.printstacktrace();
}
DateFormat formaterYd = new SimpleDateFormat("01-MMM-YYYY");
while (beginCalendar.before(finishCalendar)) {
// add one month to date per loop
String date = formaterYd.format(beginCalendar.getTime()).toupperCase();
System.out.println(date);
beginCalendar.add(Calendar.MONTH,1);
}
}
}
使用上面的代码,我得到以下结果:
"01-Jan-2020"
"01-Feb-2020"
"01-Mar-2020"
"01-Apr-2020"
"01-May-2020"
"01-Jun-2020"
"01-Jul-2020"
"01-Aug-2020"
"01-Sep-2020"
"01-Oct-2020"
"01-Nov-2020"
"01-Dec-2020"
请帮助我理解问题,并提出使用Java 7的解决方案。
解决方法
我建议您使用modern class B {
union Owner {
A* const ptr;
const A* const const_ptr;
Owner(A& a): ptr(&a) {}
Owner(const A& a): const_ptr(&a) {}
} owner;
public:
B(A& a,A::B_PrivateCreationToken): owner(a) {}
B(const A& a,A::B_PrivateCreationToken): owner(a) {}
// getOwner methods as in above version...
};
日期时间API和相应的格式API(软件包static String ConvertDigitsToLatin(String s) {
var sb = new StringBuffer();
for (int i = 0; i < s.length; i++) {
switch (s[i]) {
//Persian digits
case '\u06f0':
sb.write('0');
break;
case '\u06f1':
sb.write('1');
break;
case '\u06f2':
sb.write('2');
break;
case '\u06f3':
sb.write('3');
break;
case '\u06f4':
sb.write('4');
break;
case '\u06f5':
sb.write('5');
break;
case '\u06f6':
sb.write('6');
break;
case '\u06f7':
sb.write('7');
break;
case '\u06f8':
sb.write('8');
break;
case '\u06f9':
sb.write('9');
break;
//Arabic digits
case '\u0660':
sb.write('0');
break;
case '\u0661':
sb.write('1');
break;
case '\u0662':
sb.write('2');
break;
case '\u0663':
sb.write('3');
break;
case '\u0664':
sb.write('4');
break;
case '\u0665':
sb.write('5');
break;
case '\u0666':
sb.write('6');
break;
case '\u0667':
sb.write('7');
break;
case '\u0668':
sb.write('8');
break;
case '\u0669':
sb.write('9');
break;
default:
sb.write(s[i]);
break;
}
}
return sb.toString();
}
)来完成此操作。从 Trail: Date Time 了解有关现代日期时间API的更多信息。 java.time
日期时间API和java.time.format
已过时且容易出错。如果您不使用Java-8,则仍可以通过ThreeTenABP库使用Java-8日期时间API。
如果您是在Android上执行此操作,并且您的Android API级别仍不符合Java8,请选中Java 8+ APIs available through desugaring。
java.util
输出:
SimpleDateFormat
使用旧版API:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
// Test
System.out.println(getDateList("3/17/2020","3/17/2021"));
}
static List<String> getDateList(String strStartDate,String strEndDate) {
// Formatter for the input
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("M/d/u");
// Formatter for the output
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("dd-MMM-uuuu");
// Parse strings to LocalDate instances
LocalDate startDate = LocalDate.parse(strStartDate,inputFormatter);
LocalDate endDate = LocalDate.parse(strEndDate,inputFormatter);
return Stream.iterate(startDate.withDayOfMonth(1),date -> date.plusMonths(1))
.limit(ChronoUnit.MONTHS.between(startDate,endDate.plusMonths(1)))
.map(date -> date.format(outputFormatter))
.collect(Collectors.toList());
}
}
输出:
[01-Mar-2020,01-Apr-2020,01-May-2020,01-Jun-2020,01-Jul-2020,01-Aug-2020,01-Sep-2020,01-Oct-2020,01-Nov-2020,01-Dec-2020,01-Jan-2021,01-Feb-2021,01-Mar-2021]
,
使用java.time.LocalDate
:
public static List<LocalDate> diff(LocalDate start,LocalDate end) {
return start
.datesUntil(end)
.filter(e -> e.getDayOfMonth() == 1)
.collect(Collectors.toList());
}
diff(LocalDate.now(),LocalDate.of(2020,12,20))
输出:
[2020-10-01,2020-11-01,2020-12-01]
您可以将DateTimeFormatter
的字符串日期用于LocalDate
,反之亦然。
编辑
仅使用Java 7(正在修改的给定代码):
public static void main(String[] args) throws IOException {
String date1 = "3/17/2020";
String date2 = "3/17/2021";
DateFormat formater = new SimpleDateFormat("MM/dd/yyyy");
Calendar beginCalendar = Calendar.getInstance();
Calendar finishCalendar = Calendar.getInstance();
try {
beginCalendar.setTime(formater.parse(date1));
finishCalendar.setTime(formater.parse(date2));
} catch (ParseException e) {
e.printStackTrace();
}
DateFormat formaterYd = new SimpleDateFormat("dd-MMM-YYYY");
// mind this condition in while
while (beginCalendar.compareTo(finishCalendar) <= 0) {
Calendar tmp = (Calendar)beginCalendar.clone();
tmp.set(Calendar.DAY_OF_MONTH,1);
String date = formaterYd.format(tmp.getTime()).toUpperCase();
System.out.println(date);
beginCalendar.add(Calendar.MONTH,1);
}
}
,
Java7 解决方案:
public static void main(String[] args) throws ParseException {
DateFormat df1 = new SimpleDateFormat("MM/dd/yyyy",Locale.US);
Date dateFrom = df1.parse("3/17/2020");
Date dateTo = df1.parse("3/17/2021");
final Locale locale = Locale.US;
DateFormat df2 = new SimpleDateFormat("MMM-yyyy",Locale.US);
List<String> months = getListMonths(dateFrom,dateTo,locale,df2);
for (String month : months)
System.out.println(month.toUpperCase(locale));
}
public static List<String> getListMonths(Date dateFrom,Date dateTo,Locale locale,DateFormat df) {
Calendar calendar = Calendar.getInstance(locale);
calendar.setTime(dateFrom);
List<String> months = new ArrayList<>();
while (calendar.getTime().getTime() <= dateTo.getTime()) {
months.add(df.format(calendar.getTime()));
calendar.add(Calendar.MONTH,1);
}
return months;
}
输出:
MAR-2020
APR-2020
MAY-2020
JUN-2020
JUL-2020
AUG-2020
SEP-2020
OCT-2020
NOV-2020
DEC-2020
JAN-2021
FEB-2021
MAR-2021