请用JAVA(或C++)实现以下函数,基于给定的起始日期,终止日期参数计算期限(Tenor):
JAVA:
String getTenor(Date startDate, Date endDate)
C++:
std::string getTenor(const Date& startDate, const Date& endDate)
要求:
1) Tenor是指起始日与终止日之间的时间长度,以:xD, xW, xM, xY的形式表示。其中x为正整数,D为日,W为周,M为月,Y为年单位,并且Tenor只能出现1个单位(最简形式)。
比如:
getTenor(2017/3/1, 2017/4/1)
正确答案:1M
错误答案:31D
getTenor(2017/3/1, 2018/9/1)
正确答案:18M
错误答案:1.5Y (x不为整数) 或 1Y6M(出现多个单位)
2) 代码需要体现出必要的边界检查,对JAVA或C++语法的准确性不做严格要求,代码整洁,清晰即可
3) 对于实现中需要的日期相关计算函数,可进行必要的假设,不要求提供正确的类库API名称
4) 基于方法实现尽可能多的写出相应的单元测试用例,给出输入参数和期望结果,无需给出具体测试代码实现
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class DateUtil {
/**
*
* @param year
* 年份
* @param month
* 月份
* @return 0不合法
*/
public static final int getCurrentDay(int year, int month) {
if (month == 0 || month == 2 || month == 4 || month == 6 || month == 7 || month == 9 || month == 11) {
return 31;
} else if (month == 3 || month == 5 || month == 8 || month == 10) {
return 30;
} else if (month == 1) {
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ? 29 : 28;
}
return 0;
}
public static final String getTenor(Date startDate, Date endDate) throws IllegalAccessException {
if (startDate == null || endDate == null) {
return null;
}
Calendar startCalendar = Calendar.getInstance();
startCalendar.setTime(startDate);
Calendar endCalendar = Calendar.getInstance();
endCalendar.setTime(endDate);
int startYear = startCalendar.get(Calendar.YEAR);
int endYear = endCalendar.get(Calendar.YEAR);
int startMonth = startCalendar.get(Calendar.MONTH);
int endMonth = endCalendar.get(Calendar.MONTH);
int startDay = startCalendar.get(Calendar.DATE);
int endDay = endCalendar.get(Calendar.DATE);
int diffMonth = 0;
int diffYear = 0;
int diffDay = 0;
String unit = null;
// 不同年
if (startYear != endYear) {
// 不同月
if (startMonth != endMonth) {
// 不同日
if (startDay != endDay) {
diffDay = Math.abs(endDay - startDay);
// 月份天数+年份天数+天数
diffDay = diffDay + addDays(startYear, endYear, startMonth, endMonth) + addDays(startYear, endYear);
unit = getWeekByDay(diffDay);
}
// 相同日
else if (startDay == endDay) {
diffYear = endYear - startYear;
diffMonth = endMonth - startMonth;
if ((diffYear > 0 && diffMonth > 0) || (diffYear < 0 && diffMonth < 0)) {
diffMonth = Math.abs(diffYear * 12 + diffMonth);
} else if (diffYear > 0 && diffMonth < 0) {
diffMonth = diffMonth + 12;
diffMonth = diffYear * 12 + diffMonth;
} else if (diffYear < 0 && diffMonth > 0) {
diffMonth = -diffMonth + 12;
diffMonth = -diffYear * 12 + diffMonth;
}
unit = getYearByMonth(diffMonth);
}
}
// 相同月
else if (startMonth == endMonth) {
// 不同日
if (startDay != endDay) {
diffDay = Math.abs(endDay - startDay);
diffDay = diffDay + addDays(startYear, endYear, startMonth, endMonth) + addDays(startYear, endYear);
unit = getWeekByDay(diffDay);
}
// 相同日
else if (startDay == endDay) {
diffYear = Math.abs(endYear - startYear);
unit = diffYear + "Y";
}
}
}
// 相同年
else if (startYear == endYear) {
// 不同月
if (startMonth != endMonth) {
// 不同日
if (startDay != endDay) {
diffDay = Math.abs(endDay - startDay);
diffDay += addDays(startYear, endYear, startMonth, endMonth);
unit = getWeekByDay(diffDay);
}
// 相同日
else if (startDay == endDay) {
diffMonth = Math.abs(endMonth - startMonth);
unit = diffMonth + "M";
}
}
// 相同月
else if (startMonth == endMonth) {
// 不同日
if (startDay != endDay) {
diffDay = Math.abs(endDay - startDay);
unit = getWeekByDay(diffDay);
}
// 相同日
else if (startDay == endDay) {
return "0D";
}
}
}
return unit;
}
/**
*
* @param startYear
* 开始年份
* @param endYear
* 结束年份
* @return 年份份返回天数
*/
public static final int addDays(int startYear, int endYear) {
int beginYear = Math.min(startYear, endYear);
int dueYear = Math.max(startYear, endYear);
int days = 0;
for (int i = beginYear; i < dueYear; ++i) {
days += leapYear(i);
}
return days;
}
/**
*
* @param startMonth
* 开始月份
* @param endMonth
* 结束月份
* @return 月份返回天数
*/
public static final int addDays(int startYear, int endYear, int startMonth, int endMonth) {
int beginYear = Math.min(startYear, endYear);
int dueYear = Math.max(startYear, endYear);
int beginMonth = Math.min(startMonth, endMonth);
int dueMonth = Math.max(startMonth, endMonth);
int days = 0;// 天数
while (beginYear < dueYear) {
for (int i = beginMonth; i < dueMonth; ++i) {
days += getCurrentDay(beginYear, i);
}
++beginYear;
}
return days;
}
/**
*
* @param start
* 开始日期
* @param end
* 结束日期
* @return 日期之间的时间 格式为xD, xW, xM, xY,并且只有一个单位
* @throws IllegalAccessException
*/
public static final String getTenor(String start, String end) throws IllegalAccessException {
if (start == null || end == null) {
return null;
}
Date startDate = strToDate(start);
Date endDate = strToDate(end);
return getTenor(startDate, endDate);
}
/**
*
* @param diffDay
* 天数
* @return 一周为7天
*/
public static String getWeekByDay(int diffDay) {
String unit = null;
if (diffDay % 7 == 0) {
unit = diffDay / 7 + "W";
} else {
unit = diffDay + "D";
}
return unit;
}
/**
*
* @param diffMonth
* 月份
* @return 一年12个月
*/
public static String getYearByMonth(int diffMonth) {
String unit = null;
if (diffMonth % 12 == 0) {
unit = diffMonth / 12 + "Y";
} else {
unit = diffMonth + "M";
}
return unit;
}
public static final void illegalDate(String strDate) {
if (strDate != null) {
String[] strDates = strDate.split("/");
illegalDate(strDates);
}
}
public static final void illegalDate(String strDate, String formart) {
if (strDate != null && formart != null) {
String[] strDates = strDate.split(formart);
illegalDate(strDates);
}
}
/**
*
* @param strDates
* 非法参数判断
*/
public static final void illegalDate(String[] strDates) {
if (strDates != null) {
int length = strDates.length;
if (length == 3) {
String yearStr = strDates[0];
if (!isNumeric(yearStr)) {
throw new IndexOutOfBoundsException("年份为" + yearStr + "是非法的");
}
int year = Integer.parseInt(yearStr);
String monthStr = strDates[1];
if (!isNumeric(monthStr)) {
throw new IndexOutOfBoundsException("月份为" + monthStr + "是非法的");
}
int month = Integer.parseInt(monthStr);
if (month < 1 || month > 12) {
throw new IndexOutOfBoundsException("月份为" + monthStr + "是非法的");
}
String dayStr = strDates[2];
if (!isNumeric(dayStr)) {
throw new IndexOutOfBoundsException("天数为" + dayStr + "是非法的");
}
int day = Integer.parseInt(dayStr);
if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
if (day < 0 || day > 31) {
throw new IndexOutOfBoundsException("月份为" + monthStr + ",天数为" + dayStr + "是非法的");
}
} else if (month == 4 || month == 6 || month == 9 || month == 10) {
if (day < 0 || day > 30) {
throw new IndexOutOfBoundsException("月份为" + monthStr + ",天数为" + dayStr + "是非法的");
}
} else if (month == 2) {
if (day < 0 || day > leapMonth(year)) {
throw new IndexOutOfBoundsException("月份为" + monthStr + ",天数为" + dayStr + "是非法的");
}
}
} else if (length != 3) {
throw new IndexOutOfBoundsException("参数个数为" + length + "是非法的");
}
}
}
/**
*
* @param str
* 日期字符串
* @return 日期是否是正数
*/
public static final boolean isNumeric(String str) {
Pattern pattern = Pattern.compile("[0-9]+");
Matcher isNum = pattern.matcher(str);
if (!isNum.matches()) {
return false;
}
return true;
}
/**
*
* @param year
* 年份
* @return 2月份的天数
*/
public static final int leapMonth(int year) {
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ? 29 : 28;
}
/**
*
* @param year
* 年份
* @return 闰年或平年天数
*/
public static final int leapYear(int year) {
return year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ? 366 : 365;
}
/**
*
* @param strDate
* 日期格式字符串 yyyy/M/d
* @return 日期
*/
public static final Date strToDate(String strDate) {
if (strDate != null) {
illegalDate(strDate);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/M/d");
ParsePosition pos = new ParsePosition(0);
Date strtodate = formatter.parse(strDate, pos);
return strtodate;
}
return null;
}
public static final Date strToDate(String strDate, String format) {
if (strDate != null && format != null) {
SimpleDateFormat formatter = new SimpleDateFormat(format);
ParsePosition pos = new ParsePosition(0);
Date strtodate = formatter.parse(strDate, pos);
return strtodate;
}
return null;
}
}
希望高人指点一下,看看还有什么逻辑错误,还有什么状况没有判断到,还有什么地方可以灵活点。还有什么地方是可以优化的
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦