一、问题描述
简单描述下问题:数据库有一个开始时间字段`start_time` varchar(20) NOT NULL DEFAULT '' COMMENT '开始日',存储形如"2022-04-25"年月日的字符串,业务中需要将其转换为指定小时的形如"2022-04-25 07:00:00.0"的Date对象。我是通过Calendar类来处理实现的,代码如下:
public static Date formatStartDate(String dateStr, int startHour) {
String[] split = date.split("-");
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, Integer.valueOf(split[0]));
calendar.set(Calendar.MONTH, Integer.valueOf(split[1]));
calendar.set(Calendar.DATE, Integer.valueOf(split[2]));
calendar.set(Calendar.HOUR_OF_DAY, startHour);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar.getTime();
}
public static void main(String[] args) {
Date date = formatStartDate("2022-04-25", 7);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = format.format(date);
System.out.println("dateStr:" + dateStr);
}
运行结果如下:
从运行结果可以看到,月份被加了一个月,4月变成了5月。
二、问题分析
查看Calendar源码可以看到,其关于月份的定义如下:
/**
* Value of the {@link #MONTH} field indicating the
* first month of the year in the Gregorian and Julian calendars.
*/
public final static int JANUARY = 0;
/**
* Value of the {@link #MONTH} field indicating the
* second month of the year in the Gregorian and Julian calendars.
*/
public final static int FEBRUARY = 1;
/**
* Value of the {@link #MONTH} field indicating the
* third month of the year in the Gregorian and Julian calendars.
*/
public final static int MARCH = 2;
/**
* Value of the {@link #MONTH} field indicating the
* fourth month of the year in the Gregorian and Julian calendars.
*/
public final static int APRIL = 3;
/**
* Value of the {@link #MONTH} field indicating the
* fifth month of the year in the Gregorian and Julian calendars.
*/
public final static int MAY = 4;
/**
* Value of the {@link #MONTH} field indicating the
* sixth month of the year in the Gregorian and Julian calendars.
*/
public final static int JUNE = 5;
/**
* Value of the {@link #MONTH} field indicating the
* seventh month of the year in the Gregorian and Julian calendars.
*/
public final static int JULY = 6;
/**
* Value of the {@link #MONTH} field indicating the
* eighth month of the year in the Gregorian and Julian calendars.
*/
public final static int AUGUST = 7;
/**
* Value of the {@link #MONTH} field indicating the
* ninth month of the year in the Gregorian and Julian calendars.
*/
public final static int SEPTEMBER = 8;
/**
* Value of the {@link #MONTH} field indicating the
* tenth month of the year in the Gregorian and Julian calendars.
*/
public final static int OCTOBER = 9;
/**
* Value of the {@link #MONTH} field indicating the
* eleventh month of the year in the Gregorian and Julian calendars.
*/
public final static int NOVEMBER = 10;
/**
* Value of the {@link #MONTH} field indicating the
* twelfth month of the year in the Gregorian and Julian calendars.
*/
public final static int DECEMBER = 11;
通过上面可以看到,4代表的是May(五月),所以通过上面代码中 calendar.set(Calendar.MONTH, Integer.valueOf(split[1]));设置月份的时候本质上是 calendar.set(Calendar.MONTH, 4);,即月份设置的是五月,故而出现这个问题。
三、解决方式
方式1
既然月份是从0-11,那么在设置月份的时候减1即可:
// 将上面的值减1作为月份
calendar.set(Calendar.MONTH, Integer.valueOf(split[1]) - 1);
方式2
也可以不使用Calendar类,而是使用如下方式,代码如下:
public static Date formatStartDate(String dateStr, int startHour) throws Exception{
Date date = DateUtils.parseDate(dateStr, "yyyy-MM-dd");
return DateUtils.setHours(date, startHour);
}
四、补充
除了月份外,Calendar类中也定义的一些关于星期的常量,如下:
/**
* Value of the {@link #DAY_OF_WEEK} field indicating
* Sunday.
*/
public final static int SUNDAY = 1;
/**
* Value of the {@link #DAY_OF_WEEK} field indicating
* Monday.
*/
public final static int MONDAY = 2;
/**
* Value of the {@link #DAY_OF_WEEK} field indicating
* Tuesday.
*/
public final static int TUESDAY = 3;
/**
* Value of the {@link #DAY_OF_WEEK} field indicating
* Wednesday.
*/
public final static int WEDNESDAY = 4;
/**
* Value of the {@link #DAY_OF_WEEK} field indicating
* Thursday.
*/
public final static int THURSDAY = 5;
/**
* Value of the {@link #DAY_OF_WEEK} field indicating
* Friday.
*/
public final static int FRIDAY = 6;
/**
* Value of the {@link #DAY_OF_WEEK} field indicating
* Saturday.
*/
public final static int SATURDAY = 7;
如果想通过calendar.get(Calendar.DAY_OF_WEEK);获取指定日期是星期几也需要特别处理。
比如想获取2022年4月25日是星期几,通过这种方式获取到的将是2,实际上这天是星期一。