Created
April 24, 2019 01:58
-
-
Save xtulnx/06abf575cf585ef677764759b93847ac to your computer and use it in GitHub Desktop.
辅助工具,日期计算
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.jar.tools.util; | |
import java.text.ParseException; | |
import java.text.SimpleDateFormat; | |
import java.util.Calendar; | |
import java.util.Date; | |
import java.util.regex.Matcher; | |
import java.util.regex.Pattern; | |
/** | |
* 日期操作: 性能不高. 线程安全 | |
*/ | |
public class DateUtil { | |
protected static final ThreadLocal<Calendar> CALENDAR = new ThreadLocal<Calendar>() { | |
@Override | |
protected Calendar initialValue() { | |
return Calendar.getInstance(); | |
} | |
}; | |
protected static final ThreadLocal<Date> DATE = new ThreadLocal<Date>() { | |
@Override | |
protected Date initialValue() { | |
return new Date(); | |
} | |
}; | |
static final ThreadLocal<SimpleDateFormat> _buildSDF(final String fmt) { | |
return new ThreadLocal<SimpleDateFormat>() { | |
@Override | |
protected SimpleDateFormat initialValue() { | |
return new SimpleDateFormat(fmt); | |
} | |
}; | |
} | |
protected static final ThreadLocal<SimpleDateFormat> DATE_FORMAT_YYYYMM = _buildSDF("yyyyMM"); | |
protected static final ThreadLocal<SimpleDateFormat> DATE_FORMAT_DAY_ONLY = _buildSDF("yyyyMMdd"); | |
protected static final ThreadLocal<SimpleDateFormat> DATE_FORMAT_YYYY_MM_DD = _buildSDF("yyyy-MM-dd"); | |
protected static final ThreadLocal<SimpleDateFormat> DATE_FORMAT_YYYY_MM = _buildSDF("yyyy-MM"); | |
protected static final ThreadLocal<SimpleDateFormat> DATE_FORMAT_FULL = _buildSDF("yyyy/MM/dd HH:mm:ss"); | |
protected static final ThreadLocal<SimpleDateFormat> DATE_FORMAT_FULL2 = _buildSDF("yyyy-MM-dd HH:mm:ss"); | |
protected static final ThreadLocal<SimpleDateFormat> DATE_FORMAT_FULL3 = _buildSDF("yyyyMMddHHmmss"); | |
/** 当前月的天数 */ | |
public static int kit_daysOfMonth(Date date) { | |
return kit_daysOfMonth(date, true); | |
} | |
/** | |
* 指定日期所在月的天数 | |
* | |
* @param date 日期 | |
* @param resetEarly 是否初始化到月初 | |
* @return 天数 | |
*/ | |
public static int kit_daysOfMonth(Date date, boolean resetEarly) { | |
Calendar c = CALENDAR.get(); | |
c.setTime(date); | |
if (resetEarly) | |
c.set(Calendar.DAY_OF_MONTH, 1); | |
final long t1 = c.getTimeInMillis(); | |
c.add(Calendar.MONTH, 1); | |
c.set(Calendar.DAY_OF_MONTH, 1); | |
final long t2 = c.getTimeInMillis(); | |
return (int) ((t2 - t1) / DateTimeUtil.MILLIS_ONE_DAY); | |
} | |
/** 获取加减后的日期 */ | |
public static Date kit_dateAdd(Date date, int year, int month, int days) { | |
Calendar c = CALENDAR.get(); | |
c.setTime(date); | |
c.add(Calendar.YEAR, year); | |
c.add(Calendar.MONTH, month); | |
c.add(Calendar.DAY_OF_MONTH, days); | |
return c.getTime(); | |
} | |
/** | |
* 日期增加,并截断尾巴(以非0字段截断) | |
* | |
* @param date 当前日期 | |
* @param year 年 | |
* @param month 月 | |
* @param days 日 | |
*/ | |
public static Date kit_dateAddToStart(Date date, int year, int month, int days) { | |
Calendar c = CALENDAR.get(); | |
c.setTime(date); | |
int level = 0; | |
boolean last = false; | |
if (year != 0) { | |
c.add(Calendar.YEAR, year); | |
level = Calendar.YEAR; | |
last = year < 0 && c.get(Calendar.MONTH) != 0; | |
} | |
if (month != 0) { | |
c.add(Calendar.MONTH, month); | |
level = Calendar.MONTH; | |
//inc = month; | |
last = month < 0 && c.get(Calendar.DAY_OF_MONTH) != 1; | |
} | |
if (days != 0) { | |
c.add(Calendar.DAY_OF_MONTH, days); | |
level = Calendar.DAY_OF_MONTH; | |
last = false; | |
} | |
if (level != 0) { | |
if (last) | |
c.add(level, 1); | |
if (level <= Calendar.DAY_OF_MONTH) { | |
c.set(Calendar.HOUR_OF_DAY, 0); | |
c.set(Calendar.MINUTE, 0); | |
c.set(Calendar.SECOND, 0); | |
} | |
if (level <= Calendar.MONTH) | |
c.set(Calendar.DAY_OF_MONTH, 1); | |
if (level <= Calendar.YEAR) | |
c.set(Calendar.MONTH, 0); | |
} | |
return c.getTime(); | |
} | |
/** 获取下一个月的月初日期(1号) */ | |
public static Date kit_dateNextMonthStart(Date date) { | |
Calendar c = CALENDAR.get(); | |
c.setTime(date); | |
c.add(Calendar.MONTH, 1); | |
c.set(Calendar.DAY_OF_MONTH, 1); | |
return c.getTime(); | |
} | |
/** 获取下一个季度 */ | |
public static Date kit_dateNextQuarterlyStart(Date date) { | |
Calendar c = CALENDAR.get(); | |
c.setTime(date); | |
int m = c.get(Calendar.MONTH); | |
m += 3 - m % 3; | |
c.set(Calendar.MONTH, m); | |
c.set(Calendar.DAY_OF_MONTH, 1); | |
return c.getTime(); | |
} | |
/** 获取下一年初始日期 */ | |
public static Date kit_dateNextYearStart(Date date) { | |
Calendar c = CALENDAR.get(); | |
c.setTime(date); | |
c.add(Calendar.YEAR, 1); | |
c.set(Calendar.MONTH, 0); | |
c.set(Calendar.DAY_OF_MONTH, 1); | |
return c.getTime(); | |
} | |
public static String kit_nextMonthStart_yyyyMMdd(String s) { | |
Date d1 = kit_parseYYYYMMdd(s); | |
if (d1 != null) { | |
Date d2 = kit_dateNextMonthStart(d1); | |
return kit_dateYYYYMMdd(d2); | |
} | |
return null; | |
} | |
/** 获取当月初始日期 */ | |
public static Date kit_dateMonthStart(Date date) { | |
Calendar c = CALENDAR.get(); | |
c.setTime(date); | |
c.set(Calendar.DAY_OF_MONTH, 1); | |
return c.getTime(); | |
} | |
/** 获取当年初始日期 */ | |
public static Date kit_dateYearStart(Date date) { | |
Calendar c = CALENDAR.get(); | |
c.setTime(date); | |
c.set(Calendar.MONTH, 0); | |
c.set(Calendar.DAY_OF_MONTH, 1); | |
return c.getTime(); | |
} | |
/** 返回 b-a 的天数 */ | |
public static int kit_daysDiff(Date a, Date b) { | |
long s_day = DateTimeUtil.second2Day(a.getTime()); | |
long e_day = DateTimeUtil.second2Day(b.getTime()); | |
return (int) (e_day - s_day); | |
} | |
/** 返回 b-a 的月份(不足1月也凑整) */ | |
public static int kit_monthDiff(Date a, Date b) { | |
Calendar c = CALENDAR.get(); | |
c.setTime(a); | |
int aY = c.get(Calendar.YEAR); | |
int aM = c.get(Calendar.MONTH); | |
int aD = c.get(Calendar.DAY_OF_MONTH); | |
c.setTime(b); | |
int bY = c.get(Calendar.YEAR); | |
int bM = c.get(Calendar.MONTH); | |
int bD = c.get(Calendar.DAY_OF_MONTH); | |
int sum = (bY - aY) * 12 + (bM - aM); | |
if (sum >= 0 && bD > aD) sum++; | |
if (sum <= 0 && bD < aD) sum--; | |
return sum; | |
} | |
/** 返回 b-a 的季度(不足1月也凑整) */ | |
// public static int kit_quarterlyDiff(Date a, Date b) { | |
// return 0; | |
// } | |
/** 返回 b-a 的年份(不足1年也凑整) */ | |
public static int kit_yearDiff(Date a, Date b) { | |
Calendar c = CALENDAR.get(); | |
c.setTime(a); | |
int aY = c.get(Calendar.YEAR); | |
int aD = c.get(Calendar.DAY_OF_YEAR); | |
c.setTime(b); | |
int bY = c.get(Calendar.YEAR); | |
int bD = c.get(Calendar.DAY_OF_YEAR); | |
int sum = bY - aY; | |
if (aD != bD) { | |
if (aD < bD && sum > 0) sum++; | |
if (aD > bD && sum < 0) sum--; | |
} | |
return sum; | |
} | |
/** 日期加减 */ | |
public static Date kit_addDay(Date date, int days) { | |
return kit_dateAdd(date, 0, 0, days); | |
} | |
public static Date kit_addMonth(Date date, int months) { | |
return kit_dateAdd(date, 0, months, 0); | |
} | |
public static int get_hour(Date date) { | |
Calendar c = CALENDAR.get(); | |
c.setTime(date); | |
return c.get(Calendar.HOUR_OF_DAY); | |
} | |
public static int get_day(Date date) { | |
Calendar c = CALENDAR.get(); | |
c.setTime(date); | |
return c.get(Calendar.DAY_OF_MONTH); | |
} | |
/** 取较早的日期 */ | |
public static Date min(Date a, Date b) { | |
return a.before(b) ? a : b; | |
} | |
public static Date max(Date a, Date b) { | |
return b.after(a) ? b : a; | |
} | |
/*- - - - - - - - - - - - - - - - - 日期解析 - - - - - - - - - - - - - - - -*/ | |
private static Pattern PATTERN_DATA_ONLY_DAY = Pattern.compile("^(\\d{1,2})\\D(\\d{1,2})\\D?$"); | |
/** | |
* 按 月?日? 格式解析 | |
*/ | |
protected static Date kit_dateParseMissYear(int year, String sDay) { | |
Matcher m = PATTERN_DATA_ONLY_DAY.matcher(sDay); | |
if (m.find()) { | |
Calendar c = CALENDAR.get(); | |
int month = Integer.parseInt(m.group(1)) - 1; | |
int date = Integer.parseInt(m.group(2)); | |
c.set(year, month, date, 0, 0, 0); | |
return c.getTime(); | |
} | |
return null; | |
} | |
protected static String kit_dateFormat(SimpleDateFormat sdf, Date date) { | |
return sdf.format(date); | |
} | |
protected static String kit_dateFormat(ThreadLocal<SimpleDateFormat> sdf, Date date) { | |
return kit_dateFormat(sdf.get(), date); | |
} | |
protected static Date kit_dateParse(SimpleDateFormat sdf, String s) { | |
if (s != null && s.length() > 0) { | |
try { | |
return sdf.parse(s.trim()); | |
} catch (ParseException e) { | |
System.err.println("s=" + s); | |
e.printStackTrace(); | |
} | |
} | |
return null; | |
} | |
protected static Date kit_dateParse(ThreadLocal<SimpleDateFormat> sdf, String s) { | |
return kit_dateParse(sdf.get(), s); | |
} | |
/** 格式: yyyyMMdd */ | |
public static String kit_dateYYYYMMdd(Date date) { | |
return kit_dateFormat(DATE_FORMAT_DAY_ONLY, date); | |
} | |
/** 格式: yyyyMMdd */ | |
public static Date kit_parseYYYYMMdd(String s) { | |
return kit_dateParse(DATE_FORMAT_DAY_ONLY, s); | |
} | |
/** 按天解析 yyyy-MM-dd */ | |
public static String kit_dateYYYY_MM_dd(Date date) { | |
return kit_dateFormat(DATE_FORMAT_YYYY_MM_DD, date); | |
} | |
/** 格式: yyyy-MM-dd */ | |
public static Date kit_parseYYYY_MM_dd(String s) { | |
return kit_dateParse(DATE_FORMAT_YYYY_MM_DD, s); | |
} | |
/** 按月,格式: yyyyMM */ | |
public static String kit_dateYYYYMM(Date date) { | |
return kit_dateFormat(DATE_FORMAT_YYYYMM, date); | |
} | |
/** 按月解析,格式: yyyyMM */ | |
public static Date kit_parseYYYYMM(String s) { | |
return kit_dateParse(DATE_FORMAT_YYYYMM, s); | |
} | |
/** 按月,格式: yyyy-MM */ | |
public static String kit_dateYYYY_MM(Date date) { | |
return kit_dateFormat(DATE_FORMAT_YYYY_MM, date); | |
} | |
/** 按月解析,格式: yyyy-MM */ | |
public static Date kit_parseYYYY_MM(String s) { | |
return kit_dateParse(DATE_FORMAT_YYYY_MM, s); | |
} | |
/** 完整时间,格式: yyyy/MM/dd HH:mm:ss */ | |
public static Date parseDate_Full(String s) { | |
return kit_dateParse(DATE_FORMAT_FULL, s); | |
} | |
/** 完整时间,格式: yyyy/MM/dd HH:mm:ss */ | |
public static String kit_dateFull(Date date) { | |
return kit_dateFormat(DATE_FORMAT_FULL, date); | |
} | |
/** 完整时间,格式: yyyy/MM/dd HH:mm:ss */ | |
public static String kit_dateFull(long tick) { | |
Date d = DATE.get(); | |
d.setTime(tick); | |
return kit_dateFull(d); | |
} | |
/** 完整时间2,格式: yyyy-MM-dd HH:mm:ss */ | |
public static Date parseDate_Full2(String s) { | |
return kit_dateParse(DATE_FORMAT_FULL2, s); | |
} | |
/** 完整时间2,格式: yyyy-MM-dd HH:mm:ss */ | |
public static String kit_dateFull2(Date date) { | |
return kit_dateFormat(DATE_FORMAT_FULL2, date); | |
} | |
/** 完整时间3,格式: yyyyMMddHHmmss */ | |
public static Date parseDate_Full3(String s) { | |
return kit_dateParse(DATE_FORMAT_FULL3, s); | |
} | |
/** 完整时间3,格式: yyyyMMddHHmmss */ | |
public static String kit_dateFull3(Date date) { | |
return kit_dateFormat(DATE_FORMAT_FULL3, date); | |
} | |
/** 完整时间3,格式: yyyyMMddHHmmss */ | |
public static String kit_dateFull3(long tick) { | |
Date d = DATE.get(); | |
d.setTime(tick); | |
return kit_dateFull3(d); | |
} | |
/** 解析紧凑型日期,如 yyyy(年) 或 yyyyMM(月) 或 yyyyMMdd(天),如果 wantNext 为 true,则根据类型,找到下一周期的日期 */ | |
public static Date parseDate_compact(String s, boolean wantNext) { | |
if (s != null) { | |
if (s.length() == 8) { // yyyyMMdd | |
Date d = DateUtil.kit_parseYYYYMMdd(s); | |
if (wantNext) | |
d = DateUtil.kit_addDay(d, 1); | |
return d; | |
} | |
if (s.length() == 6) { // yyyyMM | |
Date d = DateUtil.kit_parseYYYYMM(s); | |
if (wantNext) | |
d = DateUtil.kit_dateNextMonthStart(d); | |
return d; | |
} | |
if (s.length() == 4) { // yyyy | |
Calendar c = CALENDAR.get(); | |
c.clear(); | |
c.set(Integer.parseInt(s), 0, 1); | |
if (wantNext) | |
c.add(Calendar.YEAR, 1); | |
return c.getTime(); | |
} | |
} | |
return null; | |
} | |
public static Date kit_parseDate(String fmt, String s) { | |
return kit_dateParse(new SimpleDateFormat(fmt), s); | |
} | |
public static String kit_formatDate(String fmt, Date d) { | |
return kit_dateFormat(new SimpleDateFormat(fmt), d); | |
} | |
/*- - - - - - - - - - - - - - - - - 调试辅助 - - - - - - - - - - - - - - - - */ | |
public static long debug_tick() { | |
return System.currentTimeMillis(); | |
} | |
public static float debug_tick(long t0) { | |
return (System.currentTimeMillis() - t0) / 1000f; | |
} | |
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ | |
public static void main(String[] args) { | |
// System.out.println(kit_dateFlag(kit_parseYYYYMM("201501"), kit_parseYYYYMM("201709"), DATE_FORMAT_DAY_ONLY.get())); | |
// System.out.println("days="+kit_daysOfMonth(kit_parseYYYYMMdd("20180229"),false)); | |
// System.out.println("month="+kit_monthDiff( kit_parseYYYYMMdd("20171128"),kit_parseYYYYMMdd("20180321"))); | |
// System.out.println("month="+kit_monthDiff( kit_parseYYYYMMdd("20171128"),kit_parseYYYYMMdd("20180328"))); | |
// System.out.println("month="+kit_monthDiff( kit_parseYYYYMMdd("20171128"),kit_parseYYYYMMdd("20180329"))); | |
// System.out.println("month="+kit_monthDiff( kit_parseYYYYMMdd("20180430"),kit_parseYYYYMMdd("20180329"))); | |
// System.out.println("month=" + kit_dateYYYYMMdd(kit_dateNextQuarterlyStart(kit_parseYYYYMMdd("20180129")))); | |
// System.out.println("month=" + kit_dateYYYYMMdd(kit_dateNextQuarterlyStart(kit_parseYYYYMMdd("20180429")))); | |
// System.out.println("month=" + kit_dateYYYYMMdd(kit_dateNextQuarterlyStart(kit_parseYYYYMMdd("20181129")))); | |
System.out.println("day=" + kit_dateYYYYMMdd(kit_dateAddToStart(kit_parseYYYYMMdd("20181129"), 1, 0, 0))); | |
System.out.println("day=" + kit_dateYYYYMMdd(kit_dateAddToStart(kit_parseYYYYMMdd("20181129"), 0, -1, 0))); | |
System.out.println("day=" + kit_dateYYYYMMdd(kit_dateAddToStart(kit_parseYYYYMMdd("20181129"), 5, -2, 0))); | |
System.out.println("day=" + kit_dateYYYYMMdd(kit_dateAddToStart(kit_parseYYYYMMdd("20180601"), 0, 2, 0))); | |
System.out.println("day=" + kit_dateYYYYMMdd(kit_dateAddToStart(kit_parseYYYYMMdd("20180611"), 0, -2, 0))); | |
System.out.println("day=" + kit_dateYYYYMMdd(kit_dateAddToStart(kit_parseYYYYMMdd("20180601"), 0, -2, 0))); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment