Skip to content

Instantly share code, notes, and snippets.

@xtulnx
Created April 24, 2019 01:58
Show Gist options
  • Save xtulnx/06abf575cf585ef677764759b93847ac to your computer and use it in GitHub Desktop.
Save xtulnx/06abf575cf585ef677764759b93847ac to your computer and use it in GitHub Desktop.
辅助工具,日期计算
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