时间戳转换 - 自定义WeekDays数组越界

318 阅读1分钟

项目中有个需求是时间戳转字符串,需要显示星期,且需要展示为周一、周二等。 SimpleDateFormat中有formatWeekday方法,内容如下:

private String formatWeekday(int count, int value, boolean useDateFormatSymbols,
                             boolean standalone) {
    if (useDateFormatSymbols) {
        final String[] weekdays;
        if (count == 4) {
            weekdays = standalone ? formatData.getStandAloneWeekdays() : formatData.getWeekdays();
        } else if (count == 5) {
            weekdays =
                    standalone ? formatData.getTinyStandAloneWeekdays() : formatData.getTinyWeekdays();

        } else { // count < 4, use abbreviated form if exists
            weekdays = standalone ? formatData.getShortStandAloneWeekdays() : formatData.getShortWeekdays();
        }

        return weekdays[value];
    }

    return null;
}

当时间类型中的周为EEEE时,weekdays的值会通过formatData.getWeekdays()获取,formatDataDateFormatSymbols实例,且DateFormatSymbols提供了设置weekdays方法,如下:

/**
 * Sets weekday strings. For example: "Sunday", "Monday", etc.
 * @param newWeekdays the new weekday strings. The array should
 * be indexed by <code>Calendar.SUNDAY</code>,
 * <code>Calendar.MONDAY</code>, etc.
 */
public void setWeekdays(String[] newWeekdays) {
    weekdays = Arrays.copyOf(newWeekdays, newWeekdays.length);
    cachedHashCode = 0;
}

然后我就提供了如下转换方法:

public static final String LONG_DATE_FORMAT_WEEK = "yyyy-MM-dd EEEE";
public static final String[] DAY_OF_WEEK_NAMES = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};

public static String timeMillis2String(long timeMillis) {
    Calendar c = Calendar.getInstance();
    c.setTimeInMillis(timeMillis);
    Date date = c.getTime();
    SimpleDateFormat sdf = new SimpleDateFormat(LONG_DATE_FORMAT_WEEK, Locale.getDefault());
    DateFormatSymbols dateFormatSymbols = sdf.getDateFormatSymbols();
    dateFormatSymbols.setWeekdays(DAY_OF_WEEK_NAMES);
    sdf.setDateFormatSymbols(dateFormatSymbols);
    return sdf.format(date);
}

但是当待解析的时间戳转换结果为周六时,会导致数据越界: image.png

原因是忽略了setWeekdays以及weekdays中的注释

/**
 * Weekday strings. For example: "Sunday", "Monday", etc.  An array
 * of 8 strings, indexed by <code>Calendar.SUNDAY</code>,
 * <code>Calendar.MONDAY</code>, etc.
 * The element <code>weekdays[0]</code> is ignored.
 * @serial
 */
String weekdays[] = null;

即,这个数组中的下标要与Calendar#SUNDAY等相同,且该数组长度需要八位,第0位是会被忽略的。解决办法就是将自定义的日期数组改为:

public static final String[] DAY_OF_WEEK_NAMES = {"", "周日", "周一", "周二", "周三", "周四", "周五", "周六"};