版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42528266/article/details/102622081
写作初衷:由于日常开发经常需要用到很多工具类,经常根据需求自己写也比较麻烦 网上好了一些工具类例如commom.lang3或者hutool或者Jodd这样的开源工具,但是 发现他们之中虽然设计不错,但是如果我想要使用,就必须要引入依赖并且去维护依赖,有些 甚至会有存在版本编译不通过问题,故此想要写作一个每个类都可以作为独立工具类使用 每个使用者只需要复制该类,到任何项目当中都可以使用,所以需要尊从以下两个原则才能 做到.在此诚邀各位大佬参与.可以把各自用过的工具,整合成只依赖JDK,每个类都能够单独 使用的工具.每个人当遇到业务需求需要使用的时候,只需要到这里单独拷贝一个即可使用. 抛弃传统的需要引入依赖的烦恼.让大家一起来解决你所面临的业务问题吧!
遵从两大原则
package *;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.TimeZone;
/**
* @program: simple_tools
* @description:
* @author: ChenWenLong
* @create: 2019-06-04 16:19
**/
public class DateUtils {
//无时区的格式化
public static final FastDateFormat ISO_DATETIME_FORMAT
= FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
//带时区的格式化
public static final FastDateFormat ISO_DATETIME_TIME_ZONE_FORMAT
= FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZZ");
//纯日期格式化
public static final FastDateFormat ISO_DATE_FORMAT
= FastDateFormat.getInstance("yyyy-MM-dd");
//带时区的日期格式化
public static final FastDateFormat ISO_DATE_TIME_ZONE_FORMAT
= FastDateFormat.getInstance("yyyy-MM-ddZZ");
//不带时区的时间格式化
public static final FastDateFormat ISO_TIME_FORMAT
= FastDateFormat.getInstance("'T'HH:mm:ss");
//带时区的时间格式化
public static final FastDateFormat ISO_TIME_TIME_ZONE_FORMAT
= FastDateFormat.getInstance("'T'HH:mm:ssZZ");
//没有T前缀的,非ISO8601规范的时间格式化
public static final FastDateFormat ISO_TIME_NO_T_FORMAT
= FastDateFormat.getInstance("HH:mm:ss");
//带时区的,非ISO8601规范的时间格式化
public static final FastDateFormat ISO_TIME_NO_T_TIME_ZONE_FORMAT
= FastDateFormat.getInstance("HH:mm:ssZZ");
public static final FastDateFormat SMTP_DATETIME_FORMAT
= FastDateFormat.getInstance("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
private static String[] parsePatterns = {
"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
//世界时间格式
public static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("GMT");
//每秒=1000毫秒
public static final long MILLIS_PER_SECOND = 1000;
//每分钟=60秒
public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
//每小时=60分钟
public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
//每天=24小时
public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR;
//表示半个月,这个表示是上半旬还是下半旬
public final static int SEMI_MONTH = 1001;
public final static int RANGE_WEEK_SUNDAY = 1;
public final static int RANGE_WEEK_MONDAY = 2;
public final static int RANGE_WEEK_RELATIVE = 3;
public final static int RANGE_WEEK_CENTER = 4;
public final static int RANGE_MONTH_SUNDAY = 5;
public final static int RANGE_MONTH_MONDAY = 6;
private static final int[][] fields = {
{Calendar.MILLISECOND},
{Calendar.SECOND},
{Calendar.MINUTE},
{Calendar.HOUR_OF_DAY, Calendar.HOUR},
{Calendar.DATE, Calendar.DAY_OF_MONTH, Calendar.AM_PM},
{Calendar.MONTH, SEMI_MONTH},
{Calendar.YEAR},
{Calendar.ERA}};
/**
* 功能描述:
* 〈判断是否是同一天,接受Date类型〉
*
* @params : [date1, date2]
* @return : boolean
* @author : cwl
* @date : 2019/6/6 11:00
*/
public static boolean isSameDay(Date date1, Date date2) {
if (date1 == null || date2 == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar cal1 = Calendar.getInstance();
cal1.setTime(date1);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(date2);
return isSameDay(cal1, cal2);
}
/**
* 功能描述:
* 〈判断是否是同一天,接受Calendar〉
*
* @params : [cal1, cal2]
* @return : boolean
* @author : cwl
* @date : 2019/6/6 11:01
*/
public static boolean isSameDay(Calendar cal1, Calendar cal2) {
if (cal1 == null || cal2 == null) {
throw new IllegalArgumentException("The date must not be null");
}
return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
}
/**
* 功能描述:
* 〈判断是否是同一时间,接受Date类型〉
*
* @params : [date1, date2]
* @return : boolean
* @author : cwl
* @date : 2019/6/6 11:02
*/
public static boolean isSameTime(Date date1, Date date2) {
if (date1 == null || date2 == null) {
throw new IllegalArgumentException("The date must not be null");
}
return date1.getTime() == date2.getTime();
}
/**
* 功能描述:
* 〈判断是否是同一时间,接受Calendar〉
*
* @params : [cal1, cal2]
* @return : boolean
* @author : cwl
* @date : 2019/6/6 11:03
*/
public static boolean isSameTime(Calendar cal1, Calendar cal2) {
if (cal1 == null || cal2 == null) {
throw new IllegalArgumentException("The date must not be null");
}
return cal1.getTime().getTime() == cal2.getTime().getTime();
}
/**
* 功能描述:
* 〈是否是同一地区是时间,即将二手Calendar类型.Date类型并没有地区这种说法〉
*
* @params : [cal1, cal2]
* @return : boolean
* @author : cwl
* @date : 2019/6/6 11:07
*/
public static boolean isSameLocalTime(Calendar cal1, Calendar cal2) {
if (cal1 == null || cal2 == null) {
throw new IllegalArgumentException("The date must not be null");
}
return (cal1.get(Calendar.MILLISECOND) == cal2.get(Calendar.MILLISECOND) &&
cal1.get(Calendar.SECOND) == cal2.get(Calendar.SECOND) &&
cal1.get(Calendar.MINUTE) == cal2.get(Calendar.MINUTE) &&
cal1.get(Calendar.HOUR) == cal2.get(Calendar.HOUR) &&
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) &&
cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
cal1.getClass() == cal2.getClass());
}
/**
* 功能描述:
* 〈尝试用不同的格式去格式化字符串日期〉
*
* @params : [str, parsePatterns]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:19
*/
public static Date parseDate(String str, String[] parsePatterns) throws ParseException {
if (str == null || parsePatterns == null) {
throw new IllegalArgumentException("Date and Patterns must not be null");
}
SimpleDateFormat parser = null;
ParsePosition pos = new ParsePosition(0);
for (int i = 0; i < parsePatterns.length; i++) {
if (i == 0) {
parser = new SimpleDateFormat(parsePatterns[0]);
} else {
parser.applyPattern(parsePatterns[i]);
}
pos.setIndex(0);
Date date = parser.parse(str, pos);
if (date != null && pos.getIndex() == str.length()) {
return date;
}
}
throw new ParseException("Unable to parse the date: " + str, -1);
}
/**
* 功能描述:
* 〈解析时间格式〉
*
* @params : [str]
* @return : java.util.Date
* @author : cwl
* @date : 2019/10/17 16:47
*/
public static Date parseDate(Object str) {
if (str == null) {
return null;
}
try {
return parseDate(str.toString(), parsePatterns);
} catch (ParseException e) {
return null;
}
}
/**
* 功能描述:
* 〈加amount年〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:22
*/
public static Date addYears(Date date, int amount) {
return add(date, Calendar.YEAR, amount);
}
/**
* 功能描述:
* 〈加amount月〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:22
*/
public static Date addMonths(Date date, int amount) {
return add(date, Calendar.MONTH, amount);
}
/**
* 功能描述:
* 〈加amount月〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:23
*/
public static Date addWeeks(Date date, int amount) {
return add(date, Calendar.WEEK_OF_YEAR, amount);
}
/**
* 功能描述:
* 〈加amount天〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:23
*/
public static Date addDays(Date date, int amount) {
return add(date, Calendar.DAY_OF_MONTH, amount);
}
/**
* 功能描述:
* 〈标准格式化时间.传入毫秒数mills和pattern格式〉
*
* @params : [millis, pattern]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 17:29
*/
public static String formatUTC(long millis, String pattern) {
return format(new Date(millis), pattern, UTC_TIME_ZONE, null);
}
/**
* 功能描述:
* 〈加amount小时〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:24
*/
public static Date addHours(Date date, int amount) {
return add(date, Calendar.HOUR_OF_DAY, amount);
}
/**
* 功能描述:
* 〈标准格式化时间,传入date时间格式,pattern格式〉
*
* @params : [date, pattern]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 17:30
*/
public static String formatUTC(Date date, String pattern) {
return format(date, pattern, UTC_TIME_ZONE, null);
}
/**
* 功能描述:
* 〈加amount分钟〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:24
*/
public static Date addMinutes(Date date, int amount) {
return add(date, Calendar.MINUTE, amount);
}
/**
* 功能描述:
* 〈加amount秒〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:24
*/
public static Date addSeconds(Date date, int amount) {
return add(date, Calendar.SECOND, amount);
}
/**
* 功能描述:
* 〈加amount毫秒〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:33
*/
public static Date addMilliseconds(Date date, int amount) {
return add(date, Calendar.MILLISECOND, amount);
}
/**
* 功能描述:
* 〈添加年/月/日/时/分/秒/毫秒 amount为添加量〉
*
* @params : [date, calendarField, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:34
*/
public static Date add(Date date, int calendarField, int amount) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(calendarField, amount);
return c.getTime();
}
/**
* 功能描述:
* 〈设置date年份,并返回一个新的日期〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:35
*/
public static Date setYears(Date date, int amount) {
return set(date, Calendar.YEAR, amount);
}
/**
* 功能描述:
* 〈设置date月份,返回一个新的日期〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:36
*/
public static Date setMonths(Date date, int amount) {
return set(date, Calendar.MONTH, amount);
}
/**
* 功能描述:
* 〈设置date日期,返回一个新的日期〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:37
*/
public static Date setDays(Date date, int amount) {
return set(date, Calendar.DAY_OF_MONTH, amount);
}
/**
* 功能描述:
* 〈设置时间,返回一个新的时间〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:38
*/
public static Date setHours(Date date, int amount) {
return set(date, Calendar.HOUR_OF_DAY, amount);
}
/**
* 功能描述:
* 〈设置时间,返回一个新的时间〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:38
*/
public static Date setMinutes(Date date, int amount) {
return set(date, Calendar.MINUTE, amount);
}
/**
* 功能描述:
* 〈设置时间,返回一个新的时间〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:39
*/
public static Date setSeconds(Date date, int amount) {
return set(date, Calendar.SECOND, amount);
}
/**
* 功能描述:
* 〈设置时间,返回一个新的时间〉
*
* @params : [date, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:39
*/
public static Date setMilliseconds(Date date, int amount) {
return set(date, Calendar.MILLISECOND, amount);
}
/**
* 功能描述:
* 〈设置时间〉
*
* @params : [date, calendarField, amount]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 11:40
*/
private static Date set(Date date, int calendarField, int amount) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
// getInstance() returns a new object, so this method is thread safe.
Calendar c = Calendar.getInstance();
c.setLenient(false);
c.setTime(date);
c.set(calendarField, amount);
return c.getTime();
}
/**
* 功能描述:
* 〈对日期Date类型进行四舍五入〉
*
* @params : [date, field]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 13:58
*/
public static Date round(Date date, int field) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar gval = Calendar.getInstance();
gval.setTime(date);
modify(gval, field, true);
return gval.getTime();
}
/**
* 功能描述:
* 〈对日历类Calander类型进行四舍五入〉
*
* @params : [date, field]
* @return : java.util.Calendar
* @author : cwl
* @date : 2019/6/6 13:58
*/
public static Calendar round(Calendar date, int field) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar rounded = (Calendar) date.clone();
modify(rounded, field, true);
return rounded;
}
/**
* 功能描述:
* 〈对Date类型或者Calendar类型进行四舍五入〉
*
* @params : [date, field]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 14:02
*/
public static Date round(Object date, int field) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
if (date instanceof Date) {
return round((Date) date, field);
} else if (date instanceof Calendar) {
return round((Calendar) date, field).getTime();
} else {
throw new ClassCastException("Could not round " + date);
}
}
/**
* 功能描述:
* 〈截断日期,例如可以对分钟数进行取整截断,或者对小时进行取整截断,或者对秒数取整截断.仅接受日期类Date〉
*
* @params : [date, field]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 14:04
*/
public static Date truncate(Date date, int field) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar gval = Calendar.getInstance();
gval.setTime(date);
modify(gval, field, false);
return gval.getTime();
}
/**
* 功能描述:
* 〈截断日期,例如可以对分钟数进行取整截断,或者对小时进行取整截断,或者对秒数取整截断.仅接受日历类Calendar〉
*
* @params : [date, field]
* @return : java.util.Calendar
* @author : cwl
* @date : 2019/6/6 14:06
*/
public static Calendar truncate(Calendar date, int field) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar truncated = (Calendar) date.clone();
modify(truncated, field, false);
return truncated;
}
/**
* 功能描述:
* 〈截断日期,例如可以对分钟数进行取整截断,或者对小时进行取整截断,或者对秒数取整截断.接受日历类和日期类〉
*
* @params : [date, field]
* @return : java.util.Date
* @author : cwl
* @date : 2019/6/6 14:09
*/
public static Date truncate(Object date, int field) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
if (date instanceof Date) {
return truncate((Date) date, field);
} else if (date instanceof Calendar) {
return truncate((Calendar) date, field).getTime();
} else {
throw new ClassCastException("Could not truncate " + date);
}
}
private static void modify(Calendar val, int field, boolean round) {
if (val.get(Calendar.YEAR) > 280000000) {
throw new ArithmeticException("Calendar value too large for accurate calculations");
}
if (field == Calendar.MILLISECOND) {
return;
}
// 手动截断毫秒、秒和分钟,而不是使用日历方法。
Date date = val.getTime();
long time = date.getTime();
boolean done = false;
// 截断毫秒
int millisecs = val.get(Calendar.MILLISECOND);
if (!round || millisecs < 500) {
time = time - millisecs;
}
if (field == Calendar.SECOND) {
done = true;
}
// 截断秒
int seconds = val.get(Calendar.SECOND);
if (!done && (!round || seconds < 30)) {
time = time - (seconds * 1000L);
}
if (field == Calendar.MINUTE) {
done = true;
}
// 截断分钟
int minutes = val.get(Calendar.MINUTE);
if (!done && (!round || minutes < 30)) {
time = time - (minutes * 60000L);
}
// 重新设置时间
if (date.getTime() != time) {
date.setTime(time);
val.setTime(date);
}
// ----------------- Fix for LANG-59 ----------------------- END ----------------
boolean roundUp = false;
for (int i = 0; i < fields.length; i++) {
for (int j = 0; j < fields[i].length; j++) {
if (fields[i][j] == field) {
//This is our field... we stop looping
if (round && roundUp) {
if (field == SEMI_MONTH) {
//判断这是每个月的上半旬还是下半旬,如果是上半旬,那么就加上15天减去1个月
if (val.get(Calendar.DATE) == 1) {
val.add(Calendar.DATE, 15);
} else {
val.add(Calendar.DATE, -15);
val.add(Calendar.MONTH, 1);
}
} else {
//这里需要+1,因为最后一个数字是四舍五入的
val.add(fields[i][0], 1);
}
}
return;
}
}
// 对各种不同的类型进行四舍五入
int offset = 0;
boolean offsetSet = false;
switch (field) {
case SEMI_MONTH:
if (fields[i][0] == Calendar.DATE) {
offset = val.get(Calendar.DATE) - 1;
//如果offset大于15,那么说明是在下半个月
if (offset >= 15) {
offset -= 15;
}
//记录下我们是在这个范围的上半部分还是下半部分
roundUp = offset > 7;
offsetSet = true;
}
break;
case Calendar.AM_PM:
if (fields[i][0] == Calendar.HOUR_OF_DAY) {
//对小时字段的值进行处理
offset = val.get(Calendar.HOUR_OF_DAY);
if (offset >= 12) {
offset -= 12;
}
roundUp = offset > 6;
offsetSet = true;
}
break;
}
if (!offsetSet) {
int min = val.getActualMinimum(fields[i][0]);
int max = val.getActualMaximum(fields[i][0]);
//从允许的最小值计算偏移量
offset = val.get(fields[i][0]) - min;
//如果这是介于最小值和最大值之间的一半以上,则设置汇总
roundUp = offset > ((max - min) / 2);
}
//我们需要移除这个字段
if (offset != 0) {
val.set(fields[i][0], val.get(fields[i][0]) - offset);
}
}
throw new IllegalArgumentException("The field " + field + " is not supported");
}
/**
* 功能描述:
* 〈通过毫秒数millis,指定地区Locale,指定格式pattern 标准格式化时间〉
*
* @params : [millis, pattern, locale]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 17:31
*/
public static String formatUTC(long millis, String pattern, Locale locale) {
return format(new Date(millis), pattern, UTC_TIME_ZONE, locale);
}
/**
* 功能描述:
* 〈返回一个从focus开始的迭代器〉
*
* @params : [focus, rangeStyle]
* @return : java.util.Iterator
* @author : cwl
* @date : 2019/6/6 14:38
*/
public static Iterator iterator(Date focus, int rangeStyle) {
if (focus == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar gval = Calendar.getInstance();
gval.setTime(focus);
return iterator(gval, rangeStyle);
}
/**
* 功能描述:
* 〈返回一个从focus开始的迭代器〉
*
* @params : [focus, rangeStyle]
* @return : java.util.Iterator
* @author : cwl
* @date : 2019/6/6 14:54
*/
public static Iterator iterator(Calendar focus, int rangeStyle) {
if (focus == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar start = null;
Calendar end = null;
int startCutoff = Calendar.SUNDAY;
int endCutoff = Calendar.SATURDAY;
switch (rangeStyle) {
case RANGE_MONTH_SUNDAY:
case RANGE_MONTH_MONDAY:
// 从fucus当中截取它的月份作为起始月
start = truncate(focus, Calendar.MONTH);
// 拷贝起始月作为结束月,并且对结束月进行加一个月减一天的操作
end = (Calendar) start.clone();
end.add(Calendar.MONTH, 1);
end.add(Calendar.DATE, -1);
// 循环开始到开始到开始时间的前一个周一或者是周日
if (rangeStyle == RANGE_MONTH_MONDAY) {
startCutoff = Calendar.MONDAY;
endCutoff = Calendar.SUNDAY;
}
break;
case RANGE_WEEK_SUNDAY:
case RANGE_WEEK_MONDAY:
case RANGE_WEEK_RELATIVE:
case RANGE_WEEK_CENTER:
// 从fucus当中截取它的月份作为起始月
start = truncate(focus, Calendar.DATE);
end = truncate(focus, Calendar.DATE);
switch (rangeStyle) {
case RANGE_WEEK_SUNDAY:
// already set by default
break;
case RANGE_WEEK_MONDAY:
startCutoff = Calendar.MONDAY;
endCutoff = Calendar.SUNDAY;
break;
case RANGE_WEEK_RELATIVE:
startCutoff = focus.get(Calendar.DAY_OF_WEEK);
endCutoff = startCutoff - 1;
break;
case RANGE_WEEK_CENTER:
startCutoff = focus.get(Calendar.DAY_OF_WEEK) - 3;
endCutoff = focus.get(Calendar.DAY_OF_WEEK) + 3;
break;
}
break;
default:
throw new IllegalArgumentException("The range style " + rangeStyle + " is not valid.");
}
if (startCutoff < Calendar.SUNDAY) {
startCutoff += 7;
}
if (startCutoff > Calendar.SATURDAY) {
startCutoff -= 7;
}
if (endCutoff < Calendar.SUNDAY) {
endCutoff += 7;
}
if (endCutoff > Calendar.SATURDAY) {
endCutoff -= 7;
}
while (start.get(Calendar.DAY_OF_WEEK) != startCutoff) {
start.add(Calendar.DATE, -1);
}
while (end.get(Calendar.DAY_OF_WEEK) != endCutoff) {
end.add(Calendar.DATE, 1);
}
return new DateIterator(start, end);
}
/**
* 功能描述:
* 〈获取一个日期类date或者是日历类Calendar迭代器对象〉
*
* @params : [focus, rangeStyle]
* @return : java.util.Iterator
* @author : cwl
* @date : 2019/6/6 14:59
*/
public static Iterator iterator(Object focus, int rangeStyle) {
if (focus == null) {
throw new IllegalArgumentException("The date must not be null");
}
if (focus instanceof Date) {
return iterator((Date) focus, rangeStyle);
} else if (focus instanceof Calendar) {
return iterator((Calendar) focus, rangeStyle);
} else {
throw new ClassCastException("Could not iterate based on " + focus);
}
}
//============================分割时间-仅Date类型==============================
/**
* 功能描述:
* 〈分割出对应时间点的毫秒数〉
*
* @params : [date, fragment]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:03
*/
public static long getFragmentInMilliseconds(Date date, int fragment) {
return getFragment(date, fragment, Calendar.MILLISECOND);
}
/**
* 功能描述:
* 〈分割出对应时间的秒数〉
*
* @params : [date, fragment]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:03
*/
public static long getFragmentInSeconds(Date date, int fragment) {
return getFragment(date, fragment, Calendar.SECOND);
}
/**
* 功能描述:
* 〈分割出对应时间的秒数〉
*
* @params : [date, fragment]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:08
*/
public static long getFragmentInMinutes(Date date, int fragment) {
return getFragment(date, fragment, Calendar.MINUTE);
}
/**
* 功能描述:
* 〈分割出对应时间段的小时数〉
*
* @params : [date, fragment]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:08
*/
public static long getFragmentInHours(Date date, int fragment) {
return getFragment(date, fragment, Calendar.HOUR_OF_DAY);
}
/**
* 功能描述:
* 〈分割出对应时间的天数〉
*
* @params : [date, fragment]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:10
*/
public static long getFragmentInDays(Date date, int fragment) {
return getFragment(date, fragment, Calendar.DAY_OF_YEAR);
}
//============================分割时间-仅Date类型==============================
//==========================分割时间-仅Calendar类型============================
/**
* 功能描述:
* 〈分割时间毫秒数〉
*
* @params : [calendar, fragment]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:12
*/
public static long getFragmentInMilliseconds(Calendar calendar, int fragment) {
return getFragment(calendar, fragment, Calendar.MILLISECOND);
}
/**
* 功能描述:
* 〈分割时间秒数〉
*
* @params : [calendar, fragment]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:13
*/
public static long getFragmentInSeconds(Calendar calendar, int fragment) {
return getFragment(calendar, fragment, Calendar.SECOND);
}
/**
* 功能描述:
* 〈分割时间分钟数〉
*
* @params : [calendar, fragment]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:13
*/
public static long getFragmentInMinutes(Calendar calendar, int fragment) {
return getFragment(calendar, fragment, Calendar.MINUTE);
}
/**
* 功能描述:
* 〈分割时间小时数〉
*
* @params : [calendar, fragment]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:14
*/
public static long getFragmentInHours(Calendar calendar, int fragment) {
return getFragment(calendar, fragment, Calendar.HOUR_OF_DAY);
}
/**
* 功能描述:
* 〈分割时间天数〉
*
* @params : [calendar, fragment]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:14
*/
public static long getFragmentInDays(Calendar calendar, int fragment) {
return getFragment(calendar, fragment, Calendar.DAY_OF_YEAR);
}
/**
* 功能描述:
* 〈任意单元碎片的进行切割日期〉
*
* @params : [date, fragment, unit]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:16
*/
private static long getFragment(Date date, int fragment, int unit) {
if(date == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return getFragment(calendar, fragment, unit);
}
/**
* 功能描述:
* 〈任意单元碎片的进行切割日历类时间〉
*
* @params : [calendar, fragment, unit]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:17
*/
private static long getFragment(Calendar calendar, int fragment, int unit) {
if(calendar == null) {
throw new IllegalArgumentException("The date must not be null");
}
long millisPerUnit = getMillisPerUnit(unit);
long result = 0;
// 大于一天的情况都分解成天来计算
switch (fragment) {
case Calendar.YEAR:
result += (calendar.get(Calendar.DAY_OF_YEAR) * MILLIS_PER_DAY) / millisPerUnit;
break;
case Calendar.MONTH:
result += (calendar.get(Calendar.DAY_OF_MONTH) * MILLIS_PER_DAY) / millisPerUnit;
break;
}
switch (fragment) {
// Number of days already calculated for these cases
case Calendar.YEAR:
case Calendar.MONTH:
// The rest of the valid cases
case Calendar.DAY_OF_YEAR:
case Calendar.DATE:
result += (calendar.get(Calendar.HOUR_OF_DAY) * MILLIS_PER_HOUR) / millisPerUnit;
case Calendar.HOUR_OF_DAY:
result += (calendar.get(Calendar.MINUTE) * MILLIS_PER_MINUTE) / millisPerUnit;
case Calendar.MINUTE:
result += (calendar.get(Calendar.SECOND) * MILLIS_PER_SECOND) / millisPerUnit;
case Calendar.SECOND:
result += (calendar.get(Calendar.MILLISECOND) * 1) / millisPerUnit;
break;
case Calendar.MILLISECOND: break;//never useful
default: throw new IllegalArgumentException("The fragment " + fragment + " is not supported");
}
return result;
}
/**
* 功能描述:
* 〈返回任意单元对应的毫秒数〉
*
* @params : [unit]
* @return : long
* @author : cwl
* @date : 2019/6/6 15:19
*/
private static long getMillisPerUnit(int unit) {
long result;
switch (unit) {
case Calendar.DAY_OF_YEAR:
case Calendar.DATE:
result = MILLIS_PER_DAY;
break;
case Calendar.HOUR_OF_DAY:
result = MILLIS_PER_HOUR;
break;
case Calendar.MINUTE:
result = MILLIS_PER_MINUTE;
break;
case Calendar.SECOND:
result = MILLIS_PER_SECOND;
break;
case Calendar.MILLISECOND:
result = 1;
break;
default: throw new IllegalArgumentException("The unit " + unit + " cannot be represented is milleseconds");
}
return result;
}
/**
* 功能描述:
* 〈指定日期date格式化〉
*
* @params : [date, pattern, locale]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 17:32
*/
public static String formatUTC(Date date, String pattern, Locale locale) {
return format(date, pattern, UTC_TIME_ZONE, locale);
}
/**
* 功能描述:
* 〈指定格式pattern进行毫秒数格式化〉
*
* @params : [millis, pattern]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 17:32
*/
public static String format(long millis, String pattern) {
return format(new Date(millis), pattern, null, null);
}
/**
* 功能描述:
* 〈指定pattern格式化date日期〉
*
* @params : [date, pattern]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 17:33
*/
public static String format(Date date, String pattern) {
return format(date, pattern, null, null);
}
/**
* 功能描述:
* 〈指定格式化Calendar日历类〉
*
* @params : [calendar, pattern]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 17:33
*/
public static String format(Calendar calendar, String pattern) {
return format(calendar, pattern, null, null);
}
/**
* 功能描述:
* 〈指定时区和格式pattern格式化millis〉
*
* @params : [millis, pattern, timeZone]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 17:34
*/
public static String format(long millis, String pattern, TimeZone timeZone) {
return format(new Date(millis), pattern, timeZone, null);
}
/**
* 功能描述:
* 〈指定日期date和timeZone时区以及格式pattern进行格式化〉
*
* @params : [date, pattern, timeZone]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 17:35
*/
public static String format(Date date, String pattern, TimeZone timeZone) {
return format(date, pattern, timeZone, null);
}
/**
* 功能描述:
* 〈指定时区timeZone,格式pattern,日历类calendar格式化时间〉
*
* @params : [calendar, pattern, timeZone]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 17:35
*/
public static String format(Calendar calendar, String pattern, TimeZone timeZone) {
return format(calendar, pattern, timeZone, null);
}
/**
* 功能描述:
* 〈指定格式和地区格式化date〉
*
* @params : [date, pattern, locale]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 18:00
*/
public static String format(Date date, String pattern, Locale locale) {
return format(date, pattern, null, locale);
}
/**
* 功能描述:
* 〈指定地区和格式,格式化毫秒数〉
*
* @params : [millis, pattern, locale]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 17:37
*/
public static String format(long millis, String pattern, Locale locale) {
return format(new Date(millis), pattern, null, locale);
}
/**
* 功能描述:
* 〈指定格式和地区格式化日历类〉
*
* @params : [calendar, pattern, locale]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 18:01
*/
public static String format(Calendar calendar, String pattern, Locale locale) {
return format(calendar, pattern, null, locale);
}
/**
* 功能描述:
* 〈指定格式时区和地区格式化毫秒数〉
*
* @params : [millis, pattern, timeZone, locale]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 18:02
*/
public static String format(long millis, String pattern, TimeZone timeZone, Locale locale) {
return format(new Date(millis), pattern, timeZone, locale);
}
/**
* 功能描述:
* 〈指定格式/时区/地区格式化日期〉
*
* @params : [date, pattern, timeZone, locale]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 18:04
*/
public static String format(Date date, String pattern, TimeZone timeZone, Locale locale) {
FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
return df.format(date);
}
/**
* 功能描述:
* 〈指定格式/时区/地区格式化日历类〉
*
* @params : [calendar, pattern, timeZone, locale]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/5 18:05
*/
public static String format(Calendar calendar, String pattern, TimeZone timeZone, Locale locale) {
FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
return df.format(calendar);
}
//迭代日期的构造器
static class DateIterator implements Iterator {
private final Calendar endFinal;
private final Calendar spot;
/**
* 功能描述:
* 〈从开始日期startFinal到结束日期endFinal的迭代器〉
*
* @params : [startFinal, endFinal]
* @return :
* @author : cwl
* @date : 2019/6/6 14:43
*/
DateIterator(Calendar startFinal, Calendar endFinal) {
super();
this.endFinal = endFinal;
spot = startFinal;
spot.add(Calendar.DATE, -1);
}
/**
* 功能描述:
* 〈迭代器是否已经达到了结束日期〉
*
* @params : []
* @return : boolean
* @author : cwl
* @date : 2019/6/6 14:44
*/
public boolean hasNext() {
return spot.before(endFinal);
}
/**
* 功能描述:
* 〈在迭代器循环当中,返回下一个日历对象〉
*
* @params : []
* @return : java.lang.Object
* @author : cwl
* @date : 2019/6/6 14:45
*/
public Object next() {
if (spot.equals(endFinal)) {
throw new NoSuchElementException();
}
spot.add(Calendar.DATE, 1);
return spot.clone();
}
/**
* 功能描述:
* 〈覆盖于父类的方法,用于抛出一个不可操作的异常〉
*
* @params : []
* @return : void
* @author : cwl
* @date : 2019/6/6 14:46
*/
public void remove() {
throw new UnsupportedOperationException();
}
}
//快速日期格式化
public static class FastDateFormat extends Format{
//支持序列化
private static final long serialVersionUID = 1L;
//全样式模式的常量,表示日期格式为全样式
public static final int FULL = DateFormat.FULL;
//长区域的时间样式
public static final int LONG = DateFormat.LONG;
//中间地区地区的时间样式
public static final int MEDIUM = DateFormat.MEDIUM;
//短区域的时间样式
public static final int SHORT = DateFormat.SHORT;
//默认的时间样式
private static String cDefaultPattern;
//对象缓存
private static final Map cInstanceCache = new HashMap(7);
private static final Map cDateInstanceCache = new HashMap(7);
private static final Map cTimeInstanceCache = new HashMap(7);
private static final Map cDateTimeInstanceCache = new HashMap(7);
private static final Map cTimeZoneDisplayCache = new HashMap(7);
private final String mPattern;//日期样式
private final TimeZone mTimeZone;//时区
private final boolean mTimeZoneForced;//是否使用默认时区
private final Locale mLocale;//地区
private final boolean mLocaleForced;//是否使用默认地区
private transient int mMaxLengthEstimate;//预计的最大长度
private transient Rule[] mRules;
/**
* 功能描述:
* 〈获取一个默认的日期格式化对象〉
*
* @params : []
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:21
*/
public static FastDateFormat getInstance() {
return getInstance(getDefaultPattern(), null, null);
}
/**
* 功能描述:
* 〈获取一个指定的日期格式化对象,指定格式为pattern〉
*
* @params : [pattern]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:22
*/
public static FastDateFormat getInstance(String pattern) {
return getInstance(pattern, null, null);
}
/**
* 功能描述:
* 〈创建一个指定格式pattern与时区timeZone的日期格式化对象〉
*
* @params : [pattern, timeZone]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:23
*/
public static FastDateFormat getInstance(String pattern, TimeZone timeZone) {
return getInstance(pattern, timeZone, null);
}
/**
* 功能描述:
* 〈创建一个指定格式pattern和指定地区locale的日期格式化对象〉
*
* @params : [pattern, locale]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:24
*/
public static FastDateFormat getInstance(String pattern, Locale locale) {
return getInstance(pattern, null, locale);
}
/**
* 功能描述:
* 〈创建一个指定格式pattern,指定时区timeZone,指定地区locale的日期格式化对象,为了避免重复创建,使用synchronize同步方法〉
*
* @params : [pattern, timeZone, locale]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:25
*/
public static synchronized FastDateFormat getInstance(String pattern, TimeZone timeZone, Locale locale) {
FastDateFormat emptyFormat = new FastDateFormat(pattern, timeZone, locale);
FastDateFormat format = (FastDateFormat) cInstanceCache.get(emptyFormat);
if (format == null) {
format = emptyFormat;
format.init(); // convert shell format into usable one
cInstanceCache.put(format, format); // this is OK!
}
return format;
}
/**
* 功能描述:
* 〈获得指定日期样式的日期格式化对象〉
*
* @params : [style]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:26
*/
public static FastDateFormat getDateInstance(int style) {
return getDateInstance(style, null, null);
}
/**
* 功能描述:
* 〈获得指定日期样式style和地区locale的日期格式化对象〉
*
* @params : [style, locale]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:27
*/
public static FastDateFormat getDateInstance(int style, Locale locale) {
return getDateInstance(style, null, locale);
}
/**
* 功能描述:
* 〈获得指定日期样式style和时区timeZone的日期格式化对象〉
*
* @params : [style, timeZone]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:28
*/
public static FastDateFormat getDateInstance(int style, TimeZone timeZone) {
return getDateInstance(style, timeZone, null);
}
/**
* 功能描述:
* 〈获得指定日期样式style和时区timeZone以及指定地区locale的日期格式化对象〉
*
* @params : [style, timeZone, locale]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:29
*/
public static synchronized FastDateFormat getDateInstance(int style, TimeZone timeZone, Locale locale) {
Object key = new Integer(style);
if (timeZone != null) {
key = new Pair(key, timeZone);
}
if (locale == null) {
locale = Locale.getDefault();
}
key = new Pair(key, locale);
FastDateFormat format = (FastDateFormat) cDateInstanceCache.get(key);
if (format == null) {
try {
SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getDateInstance(style, locale);
String pattern = formatter.toPattern();
format = getInstance(pattern, timeZone, locale);
cDateInstanceCache.put(key, format);
} catch (ClassCastException ex) {
throw new IllegalArgumentException("No date pattern for locale: " + locale);
}
}
return format;
}
/**
* 功能描述:
* 〈获得指定时间样式style的日期格式化对象〉
*
* @params : [style]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:30
*/
public static FastDateFormat getTimeInstance(int style) {
return getTimeInstance(style, null, null);
}
/**
* 功能描述:
* 〈获得指定地区locale和样式style的时间格式化对象〉
*
* @params : [style, locale]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:31
*/
public static FastDateFormat getTimeInstance(int style, Locale locale) {
return getTimeInstance(style, null, locale);
}
/**
* 功能描述:
* 〈获得指定样式style和指定时区timeZone的时间格式化对象〉
*
* @params : [style, timeZone]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:31
*/
public static FastDateFormat getTimeInstance(int style, TimeZone timeZone) {
return getTimeInstance(style, timeZone, null);
}
/**
* 功能描述:
* 〈获得指定样式style和指定时区timeZone以及指定地区locale的时间格式化对象〉
*
* @params : [style, timeZone, locale]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:32
*/
public static synchronized FastDateFormat getTimeInstance(int style, TimeZone timeZone, Locale locale) {
Object key = new Integer(style);
if (timeZone != null) {
key = new Pair(key, timeZone);
}
if (locale != null) {
key = new Pair(key, locale);
}
FastDateFormat format = (FastDateFormat) cTimeInstanceCache.get(key);
if (format == null) {
if (locale == null) {
locale = Locale.getDefault();
}
try {
SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getTimeInstance(style, locale);
String pattern = formatter.toPattern();
format = getInstance(pattern, timeZone, locale);
cTimeInstanceCache.put(key, format);
} catch (ClassCastException ex) {
throw new IllegalArgumentException("No date pattern for locale: " + locale);
}
}
return format;
}
/**
* 功能描述:
* 〈获得时间与日期格式化对象,指定日期样式dateStyle和指定时间样式timeStyle〉
*
* @params : [dateStyle, timeStyle]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:33
*/
public static FastDateFormat getDateTimeInstance(
int dateStyle, int timeStyle) {
return getDateTimeInstance(dateStyle, timeStyle, null, null);
}
/**
* 功能描述:
* 〈获得时间与日期格式化对象,指定日期样式dateStyle和指定时间样式timeStyle,指定地区locale〉
*
* @params : [dateStyle, timeStyle, locale]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:34
*/
public static FastDateFormat getDateTimeInstance(
int dateStyle, int timeStyle, Locale locale) {
return getDateTimeInstance(dateStyle, timeStyle, null, locale);
}
/**
* 功能描述:
* 〈获得时间与日期格式化对象,指定日期样式dateStyle和指定时间样式timeStyle,指定时区timeZone〉
*
* @params : [dateStyle, timeStyle, timeZone]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:34
*/
public static FastDateFormat getDateTimeInstance(
int dateStyle, int timeStyle, TimeZone timeZone) {
return getDateTimeInstance(dateStyle, timeStyle, timeZone, null);
}
/**
* 功能描述:
* 〈获得时间与日期格式化对象,指定日期样式dateStyle和指定时间样式timeStyle,指定时区timeZone,指定地区locale〉
*
* @params : [dateStyle, timeStyle, timeZone, locale]
* @return : com.simple.util.time.DateUtils.FastDateFormat
* @author : cwl
* @date : 2019/6/4 17:35
*/
public static synchronized FastDateFormat getDateTimeInstance(int dateStyle, int timeStyle, TimeZone timeZone,
Locale locale) {
Object key = new Pair(new Integer(dateStyle), new Integer(timeStyle));
if (timeZone != null) {
key = new Pair(key, timeZone);
}
if (locale == null) {
locale = Locale.getDefault();
}
key = new Pair(key, locale);
FastDateFormat format = (FastDateFormat) cDateTimeInstanceCache.get(key);
if (format == null) {
try {
SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getDateTimeInstance(dateStyle, timeStyle,
locale);
String pattern = formatter.toPattern();
format = getInstance(pattern, timeZone, locale);
cDateTimeInstanceCache.put(key, format);
} catch (ClassCastException ex) {
throw new IllegalArgumentException("No date time pattern for locale: " + locale);
}
}
return format;
}
/**
* 功能描述:
* 〈获取时区显示名称,使用缓存以提高性能.daylight为是否是白天,style选择样式,locale选择地区〉
*
* @params : [tz, daylight, style, locale]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/4 17:37
*/
public static synchronized String getTimeZoneDisplay(TimeZone tz, boolean daylight, int style, Locale locale) {
Object key = new TimeZoneDisplayKey(tz, daylight, style, locale);
String value = (String) cTimeZoneDisplayCache.get(key);
if (value == null) {
// This is a very slow call, so cache the results.
value = tz.getDisplayName(daylight, style, locale);
cTimeZoneDisplayCache.put(key, value);
}
return value;
}
/**
* 功能描述:
* 〈获得默认的日期格式〉
*
* @params : []
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/4 17:38
*/
private static synchronized String getDefaultPattern() {
if (cDefaultPattern == null) {
cDefaultPattern = new SimpleDateFormat().toPattern();
}
return cDefaultPattern;
}
/**
* 功能描述:
* 〈创建一个指定样式pattern,指定时区timeZone,指定地区locale的日期格式化对象〉
*
* @params : [pattern, timeZone, locale]
* @return :
* @author : cwl
* @date : 2019/6/4 17:39
*/
private FastDateFormat(String pattern, TimeZone timeZone, Locale locale) {
super();
if (pattern == null) {
throw new IllegalArgumentException("The pattern must not be null");
}
mPattern = pattern;
mTimeZoneForced = (timeZone != null);
if (timeZone == null) {
timeZone = TimeZone.getDefault();
}
mTimeZone = timeZone;
mLocaleForced = (locale != null);
if (locale == null) {
locale = Locale.getDefault();
}
mLocale = locale;
}
/**
* 功能描述:
* 〈初始化日期格式〉
*
* @params : []
* @return : void
* @author : cwl
* @date : 2019/6/4 17:44
*/
private void init() {
List rulesList = parsePattern();
mRules = (Rule[]) rulesList.toArray(new Rule[rulesList.size()]);
int len = 0;
for (int i=mRules.length; --i >= 0; ) {
len += mRules[i].estimateLength();
}
mMaxLengthEstimate = len;
}
/**
* 功能描述:
* 〈获得给定模式的规则集合〉
*
* @params : []
* @return : java.util.List
* @author : cwl
* @date : 2019/6/4 17:45
*/
private List parsePattern() {
DateFormatSymbols symbols = new DateFormatSymbols(mLocale);
List rules = new ArrayList();
String[] ERAs = symbols.getEras();
String[] months = symbols.getMonths();
String[] shortMonths = symbols.getShortMonths();
String[] weekdays = symbols.getWeekdays();
String[] shortWeekdays = symbols.getShortWeekdays();
String[] AmPmStrings = symbols.getAmPmStrings();
int length = mPattern.length();
int[] indexRef = new int[1];
for (int i = 0; i < length; i++) {
indexRef[0] = i;
String token = parseToken(mPattern, indexRef);
i = indexRef[0];
int tokenLen = token.length();
if (tokenLen == 0) {
break;
}
Rule rule;
char c = token.charAt(0);
switch (c) {
case 'G': // era designator (text)
rule = new TextField(Calendar.ERA, ERAs);
break;
case 'y': // year (number)
if (tokenLen >= 4) {
rule = selectNumberRule(Calendar.YEAR, tokenLen);
} else {
rule = TwoDigitYearField.INSTANCE;
}
break;
case 'M': // month in year (text and number)
if (tokenLen >= 4) {
rule = new TextField(Calendar.MONTH, months);
} else if (tokenLen == 3) {
rule = new TextField(Calendar.MONTH, shortMonths);
} else if (tokenLen == 2) {
rule = TwoDigitMonthField.INSTANCE;
} else {
rule = UnpaddedMonthField.INSTANCE;
}
break;
case 'd': // day in month (number)
rule = selectNumberRule(Calendar.DAY_OF_MONTH, tokenLen);
break;
case 'h': // hour in am/pm (number, 1..12)
rule = new TwelveHourField(selectNumberRule(Calendar.HOUR, tokenLen));
break;
case 'H': // hour in day (number, 0..23)
rule = selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen);
break;
case 'm': // minute in hour (number)
rule = selectNumberRule(Calendar.MINUTE, tokenLen);
break;
case 's': // second in minute (number)
rule = selectNumberRule(Calendar.SECOND, tokenLen);
break;
case 'S': // millisecond (number)
rule = selectNumberRule(Calendar.MILLISECOND, tokenLen);
break;
case 'E': // day in week (text)
rule = new TextField(Calendar.DAY_OF_WEEK, tokenLen < 4 ? shortWeekdays : weekdays);
break;
case 'D': // day in year (number)
rule = selectNumberRule(Calendar.DAY_OF_YEAR, tokenLen);
break;
case 'F': // day of week in month (number)
rule = selectNumberRule(Calendar.DAY_OF_WEEK_IN_MONTH, tokenLen);
break;
case 'w': // week in year (number)
rule = selectNumberRule(Calendar.WEEK_OF_YEAR, tokenLen);
break;
case 'W': // week in month (number)
rule = selectNumberRule(Calendar.WEEK_OF_MONTH, tokenLen);
break;
case 'a': // am/pm marker (text)
rule = new TextField(Calendar.AM_PM, AmPmStrings);
break;
case 'k': // hour in day (1..24)
rule = new TwentyFourHourField(selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen));
break;
case 'K': // hour in am/pm (0..11)
rule = selectNumberRule(Calendar.HOUR, tokenLen);
break;
case 'z': // time zone (text)
if (tokenLen >= 4) {
rule = new TimeZoneNameRule(mTimeZone, mTimeZoneForced, mLocale, TimeZone.LONG);
} else {
rule = new TimeZoneNameRule(mTimeZone, mTimeZoneForced, mLocale, TimeZone.SHORT);
}
break;
case 'Z': // time zone (value)
if (tokenLen == 1) {
rule = TimeZoneNumberRule.INSTANCE_NO_COLON;
} else {
rule = TimeZoneNumberRule.INSTANCE_COLON;
}
break;
case '\'': // literal text
String sub = token.substring(1);
if (sub.length() == 1) {
rule = new CharacterLiteral(sub.charAt(0));
} else {
rule = new StringLiteral(sub);
}
break;
default:
throw new IllegalArgumentException("Illegal pattern component: " + token);
}
rules.add(rule);
}
return rules;
}
/**
* 功能描述:
* 〈解析格式pattern〉
*
* @params : [pattern, indexRef]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/4 17:47
*/
private String parseToken(String pattern, int[] indexRef) {
StringBuffer buf = new StringBuffer();
int i = indexRef[0];
int length = pattern.length();
char c = pattern.charAt(i);
if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') {
// Scan a run of the same character, which indicates a time
// pattern.
buf.append(c);
while (i + 1 < length) {
char peek = pattern.charAt(i + 1);
if (peek == c) {
buf.append(c);
i++;
} else {
break;
}
}
} else {
// This will identify token as text.
buf.append('\'');
boolean inLiteral = false;
for (; i < length; i++) {
c = pattern.charAt(i);
if (c == '\'') {
if (i + 1 < length && pattern.charAt(i + 1) == '\'') {
// '' is treated as escaped '
i++;
buf.append(c);
} else {
inLiteral = !inLiteral;
}
} else if (!inLiteral &&
(c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')) {
i--;
break;
} else {
buf.append(c);
}
}
}
indexRef[0] = i;
return buf.toString();
}
/**
* 功能描述:
* 〈获取所需要的数字规则〉
*
* @params : [field, padding]
* @return : com.simple.util.time.DateUtils.FastDateFormat.NumberRule
* @author : cwl
* @date : 2019/6/4 17:48
*/
private NumberRule selectNumberRule(int field, int padding) {
switch (padding) {
case 1:
return new UnpaddedNumberField(field);
case 2:
return new TwoDigitNumberField(field);
default:
return new PaddedNumberField(field, padding);
}
}
/**
* 功能描述:
* 〈格式化Date或者Calender日期类〉
*
* @params : [obj, toAppendTo, pos]
* @return : java.lang.StringBuffer
* @author : cwl
* @date : 2019/6/4 17:50
*/
@Override
public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
if (obj instanceof Date) {
return format((Date) obj, toAppendTo);
} else if (obj instanceof Calendar) {
return format((Calendar) obj, toAppendTo);
} else if (obj instanceof Long) {
return format(((Long) obj).longValue(), toAppendTo);
} else {
throw new IllegalArgumentException("Unknown class: " +
(obj == null ? "<null>" : obj.getClass().getName()));
}
}
/**
* 功能描述:
* 〈格式化毫秒数〉
*
* @params : [millis]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/4 17:50
*/
public String format(long millis) {
return format(new Date(millis));
}
/**
* 功能描述:
* 〈格式化date日期类〉
*
* @params : [date]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/4 17:51
*/
public String format(Date date) {
Calendar c = new GregorianCalendar(mTimeZone);
c.setTime(date);
return applyRules(c, new StringBuffer(mMaxLengthEstimate)).toString();
}
/**
* 功能描述:
* 〈格式化Clalendar日期〉
*
* @params : [calendar]
* @return : java.lang.String
* @author : cwl
* @date : 2019/6/4 17:52
*/
public String format(Calendar calendar) {
return format(calendar, new StringBuffer(mMaxLengthEstimate)).toString();
}
/**
* 功能描述:
* 〈格式化毫秒数,结果缓存到buf当中〉
*
* @params : [millis, buf]
* @return : java.lang.StringBuffer
* @author : cwl
* @date : 2019/6/4 17:52
*/
public StringBuffer format(long millis, StringBuffer buf) {
return format(new Date(millis), buf);
}
/**
* 功能描述:
* 〈格式化Date日期类型,并且将结果缓存到buf当中〉
*
* @params : [date, buf]
* @return : java.lang.StringBuffer
* @author : cwl
* @date : 2019/6/4 17:53
*/
public StringBuffer format(Date date, StringBuffer buf) {
Calendar c = new GregorianCalendar(mTimeZone);
c.setTime(date);
return applyRules(c, buf);
}
/**
* 功能描述:
* 〈格式化Calendar日期类型,并且将结果缓存到buf当中〉
*
* @params : [calendar, buf]
* @return : java.lang.StringBuffer
* @author : cwl
* @date : 2019/6/4 17:54
*/
public StringBuffer format(Calendar calendar, StringBuffer buf) {
if (mTimeZoneForced) {
calendar = (Calendar) calendar.clone();
calendar.setTimeZone(mTimeZone);
}
return applyRules(calendar, buf);
}
/**
* 功能描述:
* 〈通过将规则应用于指定的日历来执行格式化〉
*
* @params : [calendar, buf]
* @return : java.lang.StringBuffer
* @author : cwl
* @date : 2019/6/4 17:55
*/
private StringBuffer applyRules(Calendar calendar, StringBuffer buf) {
Rule[] rules = mRules;
int len = mRules.length;
for (int i = 0; i < len; i++) {
rules[i].appendTo(buf, calendar);
}
return buf;
}
public String getmPattern() {
return mPattern;
}
public TimeZone getmTimeZone() {
return mTimeZone;
}
public boolean ismTimeZoneForced() {
return mTimeZoneForced;
}
public Locale getmLocale() {
return mLocale;
}
public boolean ismLocaleForced() {
return mLocaleForced;
}
public int getmMaxLengthEstimate() {
return mMaxLengthEstimate;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof FastDateFormat == false) {
return false;
}
FastDateFormat other = (FastDateFormat) obj;
if (
(mPattern == other.mPattern || mPattern.equals(other.mPattern)) &&
(mTimeZone == other.mTimeZone || mTimeZone.equals(other.mTimeZone)) &&
(mLocale == other.mLocale || mLocale.equals(other.mLocale)) &&
(mTimeZoneForced == other.mTimeZoneForced) &&
(mLocaleForced == other.mLocaleForced)
) {
return true;
}
return false;
}
@Override
public int hashCode() {
int total = 0;
total += mPattern.hashCode();
total += mTimeZone.hashCode();
total += (mTimeZoneForced ? 1 : 0);
total += mLocale.hashCode();
total += (mLocaleForced ? 1 : 0);
return total;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
init();
}
@Override
public String toString() {
return "FastDateFormat[" + mPattern + "]";
}
//用于定义一个规则的接口
private interface Rule {
/**
* 功能描述:
* 〈返回预计的长度〉
*
* @params : []
* @return : int
* @author : cwl
* @date : 2019/6/4 16:47
*/
int estimateLength();
/**
* 功能描述:
* 〈根据规则实现将指定日历的值添加到StringBuffer缓存当中〉
*
* @params : [buffer, calendar]
* @return : void
* @author : cwl
* @date : 2019/6/4 16:48
*/
void appendTo(StringBuffer buffer, Calendar calendar);
}
//定义一个数字的规则
private interface NumberRule extends Rule {
/**
* 功能描述:
* 〈将指定值添加到buffer当中〉
*
* @params : [buffer, value]
* @return : void
* @author : cwl
* @date : 2019/6/4 16:50
*/
void appendTo(StringBuffer buffer, int value);
}
//输出一个常量的字符
private static class CharacterLiteral implements Rule {
private final char mValue;
CharacterLiteral(char value) {
mValue = value;
}
public int estimateLength() {
return 1;
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
buffer.append(mValue);
}
}
@Override
public Object parseObject(String source, ParsePosition pos) {
pos.setIndex(0);
pos.setErrorIndex(0);
return null;
}
//用于输出一个常量字符
private static class StringLiteral implements Rule {
private final String mValue;
StringLiteral(String value) {
mValue = value;
}
public int estimateLength() {
return mValue.length();
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
buffer.append(mValue);
}
}
//输出一组值当中的一个
private static class TextField implements Rule {
private final int mField;
private final String[] mValues;
TextField(int field, String[] values) {
mField = field;
mValues = values;
}
public int estimateLength() {
int max = 0;
for (int i=mValues.length; --i >= 0; ) {
int len = mValues[i].length();
if (len > max) {
max = len;
}
}
return max;
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
buffer.append(mValues[calendar.get(mField)]);
}
}
//输出年份
private static class UnpaddedNumberField implements NumberRule {
static final UnpaddedNumberField INSTANCE_YEAR = new UnpaddedNumberField(Calendar.YEAR);
private final int mField;
UnpaddedNumberField(int field) {
mField = field;
}
public int estimateLength() {
return 4;
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
appendTo(buffer, calendar.get(mField));
}
public final void appendTo(StringBuffer buffer, int value) {
if (value < 10) {
buffer.append((char)(value + '0'));
} else if (value < 100) {
buffer.append((char)(value / 10 + '0'));
buffer.append((char)(value % 10 + '0'));
} else {
buffer.append(Integer.toString(value));
}
}
}
//输出月份
private static class UnpaddedMonthField implements NumberRule {
static final UnpaddedMonthField INSTANCE = new UnpaddedMonthField();
UnpaddedMonthField() {
super();
}
public int estimateLength() {
return 2;
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
}
public final void appendTo(StringBuffer buffer, int value) {
if (value < 10) {
buffer.append((char)(value + '0'));
} else {
buffer.append((char)(value / 10 + '0'));
buffer.append((char)(value % 10 + '0'));
}
}
}
//用于填充两位数的内部类
private static class PaddedNumberField implements NumberRule {
private final int mField;
private final int mSize;
PaddedNumberField(int field, int size) {
if (size < 3) {
// Should use UnpaddedNumberField or TwoDigitNumberField.
throw new IllegalArgumentException();
}
mField = field;
mSize = size;
}
public int estimateLength() {
return 4;
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
appendTo(buffer, calendar.get(mField));
}
public final void appendTo(StringBuffer buffer, int value) {
if (value < 100) {
for (int i = mSize; --i >= 2; ) {
buffer.append('0');
}
buffer.append((char)(value / 10 + '0'));
buffer.append((char)(value % 10 + '0'));
} else {
int digits;
if (value < 1000) {
digits = 3;
} else {
if(value <= -1){
throw new IllegalArgumentException("Negative values should not be possible" + value);
}
digits = Integer.toString(value).length();
}
for (int i = mSize; --i >= digits; ) {
buffer.append('0');
}
buffer.append(Integer.toString(value));
}
}
}
//用来输出两位数的内部类
private static class TwoDigitNumberField implements NumberRule {
private final int mField;
TwoDigitNumberField(int field) {
mField = field;
}
public int estimateLength() {
return 2;
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
appendTo(buffer, calendar.get(mField));
}
public final void appendTo(StringBuffer buffer, int value) {
if (value < 100) {
buffer.append((char)(value / 10 + '0'));
buffer.append((char)(value % 10 + '0'));
} else {
buffer.append(Integer.toString(value));
}
}
}
//用来输出两位数字的年份的内部类
private static class TwoDigitYearField implements NumberRule {
static final TwoDigitYearField INSTANCE = new TwoDigitYearField();
TwoDigitYearField() {
super();
}
public int estimateLength() {
return 2;
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
appendTo(buffer, calendar.get(Calendar.YEAR) % 100);
}
public final void appendTo(StringBuffer buffer, int value) {
buffer.append((char)(value / 10 + '0'));
buffer.append((char)(value % 10 + '0'));
}
}
//用来输出两位数字的月份的内部类
private static class TwoDigitMonthField implements NumberRule {
static final TwoDigitMonthField INSTANCE = new TwoDigitMonthField();
TwoDigitMonthField() {
super();
}
public int estimateLength() {
return 2;
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
}
public final void appendTo(StringBuffer buffer, int value) {
buffer.append((char)(value / 10 + '0'));
buffer.append((char)(value % 10 + '0'));
}
}
//用来输出12小时字段的内部类
private static class TwelveHourField implements NumberRule {
private final NumberRule mRule;
TwelveHourField(NumberRule rule) {
mRule = rule;
}
public int estimateLength() {
return mRule.estimateLength();
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
int value = calendar.get(Calendar.HOUR);
if (value == 0) {
value = calendar.getLeastMaximum(Calendar.HOUR) + 1;
}
mRule.appendTo(buffer, value);
}
public void appendTo(StringBuffer buffer, int value) {
mRule.appendTo(buffer, value);
}
}
//用来输出24小时字段的内部类
private static class TwentyFourHourField implements NumberRule {
private final NumberRule mRule;
TwentyFourHourField(NumberRule rule) {
mRule = rule;
}
public int estimateLength() {
return mRule.estimateLength();
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
int value = calendar.get(Calendar.HOUR_OF_DAY);
if (value == 0) {
value = calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1;
}
mRule.appendTo(buffer, value);
}
public void appendTo(StringBuffer buffer, int value) {
mRule.appendTo(buffer, value);
}
}
//用来输出时区名称的内部类
private static class TimeZoneNameRule implements Rule {
private final TimeZone mTimeZone;
private final boolean mTimeZoneForced;
private final Locale mLocale;
private final int mStyle;
private final String mStandard;
private final String mDaylight;
TimeZoneNameRule(TimeZone timeZone, boolean timeZoneForced, Locale locale, int style) {
mTimeZone = timeZone;
mTimeZoneForced = timeZoneForced;
mLocale = locale;
mStyle = style;
if (timeZoneForced) {
mStandard = getTimeZoneDisplay(timeZone, false, style, locale);
mDaylight = getTimeZoneDisplay(timeZone, true, style, locale);
} else {
mStandard = null;
mDaylight = null;
}
}
public int estimateLength() {
if (mTimeZoneForced) {
return Math.max(mStandard.length(), mDaylight.length());
} else if (mStyle == TimeZone.SHORT) {
return 4;
} else {
return 40;
}
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
if (mTimeZoneForced) {
if (mTimeZone.useDaylightTime() && calendar.get(Calendar.DST_OFFSET) != 0) {
buffer.append(mDaylight);
} else {
buffer.append(mStandard);
}
} else {
TimeZone timeZone = calendar.getTimeZone();
if (timeZone.useDaylightTime() && calendar.get(Calendar.DST_OFFSET) != 0) {
buffer.append(getTimeZoneDisplay(timeZone, true, mStyle, mLocale));
} else {
buffer.append(getTimeZoneDisplay(timeZone, false, mStyle, mLocale));
}
}
}
}
//将时区作为数字输出的内部类
private static class TimeZoneNumberRule implements Rule {
static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true);
static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false);
final boolean mColon;
TimeZoneNumberRule(boolean colon) {
mColon = colon;
}
public int estimateLength() {
return 5;
}
public void appendTo(StringBuffer buffer, Calendar calendar) {
int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
if (offset < 0) {
buffer.append('-');
offset = -offset;
} else {
buffer.append('+');
}
int hours = offset / (60 * 60 * 1000);
buffer.append((char)(hours / 10 + '0'));
buffer.append((char)(hours % 10 + '0'));
if (mColon) {
buffer.append(':');
}
int minutes = offset / (60 * 1000) - 60 * hours;
buffer.append((char)(minutes / 10 + '0'));
buffer.append((char)(minutes % 10 + '0'));
}
}
//时区名称作为Key值的内部类
private static class TimeZoneDisplayKey {
private final TimeZone mTimeZone;
private final int mStyle;
private final Locale mLocale;
TimeZoneDisplayKey(TimeZone timeZone,
boolean daylight, int style, Locale locale) {
mTimeZone = timeZone;
if (daylight) {
style |= 0x80000000;
}
mStyle = style;
mLocale = locale;
}
public int hashCode() {
return mStyle * 31 + mLocale.hashCode();
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof TimeZoneDisplayKey) {
TimeZoneDisplayKey other = (TimeZoneDisplayKey)obj;
return
mTimeZone.equals(other.mTimeZone) &&
mStyle == other.mStyle &&
mLocale.equals(other.mLocale);
}
return false;
}
}
// 用于创建复合对象的Helper类
private static class Pair {
private final Object mObj1;
private final Object mObj2;
public Pair(Object obj1, Object obj2) {
mObj1 = obj1;
mObj2 = obj2;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Pair)) {
return false;
}
Pair key = (Pair)obj;
return
(mObj1 == null ?
key.mObj1 == null : mObj1.equals(key.mObj1)) &&
(mObj2 == null ?
key.mObj2 == null : mObj2.equals(key.mObj2));
}
public int hashCode() {
return (mObj1 == null ? 0 : mObj1.hashCode()) + (mObj2 == null ? 0 : mObj2.hashCode());
}
public String toString() {
return "[" + mObj1 + ':' + mObj2 + ']';
}
}
}
}
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有