package cc.smtweb.framework.core.util;

import org.apache.commons.lang3.time.DateUtils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

/**
 * 日期工具类
 */
public class DateUtil {
    //	private static ThreadLocal<DateFormat> stdTimeFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("HH:mm:ss"));
    private static ThreadLocal<DateFormat> stdDateFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
    private static ThreadLocal<DateFormat> stdDatetimeFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
//	private static ThreadLocal<DateFormat> stdLongDatetimeFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));

    private static ThreadLocal<DateFormat> simpleWeekFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("EEEE"));
    private static ThreadLocal<DateFormat> simpleTimeFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("HHmmss"));
    private static ThreadLocal<DateFormat> simpleDateFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd"));
    private static ThreadLocal<DateFormat> simpleDatetimeFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMddHHmmss"));
    private static ThreadLocal<DateFormat> simpleLongDatetimeFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMddHHmmssSSS"));

    private static ThreadLocal<DateFormat> stdTimeFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("HH:mm:ss"));
    private static ThreadLocal<DateFormat> stdLongDatetimeFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));
    final static int[] m_seasonBeginTable = new int[]{
            Calendar.JANUARY, Calendar.JANUARY, Calendar.JANUARY,
            Calendar.APRIL, Calendar.APRIL, Calendar.APRIL,
            Calendar.JULY, Calendar.JULY, Calendar.JULY,
            Calendar.OCTOBER, Calendar.OCTOBER, Calendar.OCTOBER
    };

    private static TimeZone mTimeZone = TimeZone.getTimeZone("Asia/Shanghai");

    private DateUtil() {
    }

    /**
     * 取得系统今天的时间串
     *
     * @return current datetime, pattern: "yyyy-MM-dd HH:mm:ss".
     */
    public static String nowStdDateTimeString() {
        return stdDatetimeFormat.get().format(nowTimestamp());
    }

    /**
     * Return a Timestamp for right now
     *
     * @return Timestamp for right now
     */
    public static Timestamp nowTimestamp() {
        return new Timestamp(System.currentTimeMillis());
    }

    /**
     * 得到如下格式字符串 "YYYY-MM-DD"
     *
     * @param d 时间戳 如果传入为null,则返回“”；
     * @return 日期时间串
     */
    public static String toStdDateString(Date d) {
        if (d == null) return "";
        return stdDateFormat.get().format(d);
    }

    /**
     * 比较两个日期是否相等
     */
    public static int compareDate(Date a, Date b) {
        // java.sql.Date date = new java.sql.Date(System.currentTimeMillis());
        // date中,会保留有时间秒数.
        // java.sql.Date a = java.sql.Date.valueOf("2007-01-01");
        // a中,就没有时间秒数
        // 所以,在比较时就统一按字符串[yyyy-MM-dd]进行比较而不直接用a.compareTo(b)
        String stra = toStdDateString(a);
        String strb = toStdDateString(b);
        return stra.compareTo(strb);
    }

    /**
     * 获取当前时间数字串，例如20100909121359 标识2010年09月09日 12时13分59秒
     *
     * @return Long
     */
    public static Long nowDateTimeNumber() {
        return Long.valueOf(nowDateTimeString());
    }

    /**
     * 取得系统今天的时间串
     *
     * @return current datetime, pattern:"yyyyMMddHHmmss"
     */
    public static String nowDateTimeString() {
        return simpleDatetimeFormat.get().format(nowTimestamp());
    }

    /**
     * 将yyyyMMdd变为yyyy-mm-dd
     *
     * @param s 原日期串，默认用-进行分割
     * @return yyyy-mm-dd
     */
    public static String toStdDateString(String s) {
        if (StringUtil.isEmpty(s)) return "";
        if (s.contains("-")) return s;
        return toStdDateString(s, "-", false);
    }

    /**
     * 将yyyyMMdd日期串用分隔符进行分割
     *
     * @param s                    原日期串，默认用-进行分割
     * @param split                分隔符；
     * @param returnEmptyIfErrDate 如果不是8位的日期串，则控制是反馈“”，还是返回原串；
     * @return 用分隔符，如“-”，“.”进行分割后的日期串；
     */
    public static String toStdDateString(String s, String split, boolean returnEmptyIfErrDate) {
        if (StringUtil.isEmpty(s)) return "";
        try {
            if (s == null || s.length() < 8) {
                return returnEmptyIfErrDate ? "": s;
            }
            return s.substring(0, 4) + split + s.substring(4, 6) + split + s.substring(6, 8);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 得到如下字符串 "YYYY-dd
     *
     * @param d String, 例如20110304131101
     * @return 日期时间串，如：2011-03
     */
    public static String toStdYd(String d) {
        if (d == null || d.length() < 6) return "";
        return d.substring(0, 4) + "-" + d.substring(4, 6);
    }

    /**
     * @param datetime 时间戳，例如20110304131101；
     * @return 毫秒数
     */
    public static long getTimeInMillis(String datetime) {
        if (datetime == null) return 0L;
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(stdDatetimeFormat.get().parse(datetime));
            return calendar.getTimeInMillis();
        } catch (Exception e) {
            return 0L;
        }
    }

    /**
     * a是否小于当前日期
     */
    public static boolean isLessThanCurrentDate(java.sql.Date a) {
        int i = compareDate(a, new java.sql.Date(System.currentTimeMillis()));
        return i < 0;
    }

    /**
     * a是否小于b
     */
    public static boolean isLessThanCurrentDate(java.sql.Date a, java.sql.Date b) {
        int i = compareDate(a, b);
        return i < 0;
    }

    /**
     * 检查beging + days 是否在end前[包括end];(如:招行开始日期与结束日期之差只能在100以内)
     *
     * @return false 大于了end
     */
    public synchronized static boolean isBeforeDate(Date beging, int days, Date end) {
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTimeZone(mTimeZone);
        gc.setTime(beging);
        gc.add(GregorianCalendar.DATE, days - 1);
        Date addDate = gc.getTime();
        return (end.compareTo(addDate) <= 0);
    }

    /**
     * 得到如下字符串 "YYYY-MM-DD HH:MM:SS"
     *
     * @param d 时间戳，如果传入为null,则返回“”；
     * @return 日期时间串
     */
    public static String toStdDateTimeString(Date d) {
        if (d == null) return "";
        return stdDatetimeFormat.get().format(d);
    }

    /**
     * 得到如下字符串 "YYYY-MM-DD HH:MM:SS"
     *
     * @param d long, 例如20110304131101
     * @return 日期时间串，如：2011-03-04 13:11:01
     */
    public static String toStdDateTimeString(long d) {
        return toStdDateTimeString(String.valueOf(d));
    }

    /**
     * 得到如下字符串 "YYYY-MM-DD HH:MM:SS"
     *
     * @param d String, 例如20110304131101
     * @return 日期时间串，如：2011-03-04 13:11:01
     */
    public static String toStdDateTimeString(String d) {
        if (d == null || d.length() != 14) return "";
        return toStdDateString(d.substring(0, 8)) + " " + d.substring(8, 10) + ":" + d.substring(10, 12) + ":" + d.substring(12);
    }

    /**
     * 得到如下字符串 "MM-DD HH:MM"
     *
     * @param d String, 例如20110304131101
     * @return 日期时间串，如：03-04 13:11
     */
    public static String toStdDateTime3String(String d) {
        if (d == null || d.length() != 14) return "";
        return toStdDateString(d.substring(0, 8)).substring(5) + " " + d.substring(8, 10) + ":" + d.substring(10, 12);
    }

    /**
     * 得到如下字符串 "YYYY-MM-DD HH:MM"
     *
     * @param d String, 例如20110304131101
     * @return 日期时间串，如：2011-03-04 13:11
     */
    public static String toStdDateTime2String(String d) {
        if (d == null || d.length() != 14) return "";
        return toStdDateString(d.substring(0, 8)) + " " + d.substring(8, 10) + ":" + d.substring(10, 12);
    }

    /**
     * 获取星期几
     */
    public static String getWeekOfDay() {
        return simpleWeekFormat.get().format(nowTimestamp());
    }

    /**
     * 获取当前时间
     *
     * @return
     */
    public static Date now() {
        return new Date(System.currentTimeMillis());
    }

    /**
     * 按yyyy-MM-dd格式化
     *
     * @param date
     * @return
     */
    public static String formatDate(Date date) {
        return stdDateFormat.get().format(date);
    }

    /**
     * 按yyyy-MM-dd HH:mm:ss格式化
     *
     * @param date
     * @return
     */
    public static String formatDateTime(Date date) {
        return stdDatetimeFormat.get().format(date);
    }

    /**
     * 格式化
     *
     * @param date YYYYMMDD格式
     * @return
     */
    public static String formatDate(long date) {
        return formatDate(String.valueOf(date));
    }

    public static String formatDate(String d) {
        if (d.length() < 8) return d; //就是2011-03-04 13:11:01这种形式
        return d.substring(0, 4) + "-" + d.substring(4, 6) + "-" + d.substring(6, 8);
    }

    public static String formatDateTime(long date) {
        return formatDateTime(String.valueOf(date));
    }

    public static String formatDateTime(String d) {
        if (d.length() < 8) return d; //就是2011-03-04 13:11:01这种形式
        if (d.length() < 14) return d.substring(0, 4) + "-" + d.substring(4, 6) + "-" + d.substring(6, 8);
        return d.substring(0, 4) + "-" + d.substring(4, 6) + "-" + d.substring(6, 8) + " " + d.substring(8, 10) + ":" + d.substring(10, 12) + ":" + d.substring(12);
    }

    public static String formatTime(long date) {
        return formatTime(String.valueOf(date));
    }

    public static String formatTime(String d) {
        if (d.length() < 6) return d; //就是13:11:01这种形式
        return d.substring(0, 2) + ":" + d.substring(2, 4) + ":" + d.substring(4);
    }

    /**
     * 按yyyyMMdd格式化
     *
     * @param date
     * @return
     */
    public static String formatSimpleDate(Date date) {
        return simpleDateFormat.get().format(date);
    }

    /**
     * 按yyyyMMddHHmmss格式化
     *
     * @param date
     * @return
     */
    public static String formatSimpleDateTime(Date date) {
        return simpleDatetimeFormat.get().format(date);
    }

    /**
     * 按yyyyMMddHHmmssSSS格式化
     *
     * @param date
     * @return
     */
    public static String formatSimpleDateTimeS(Date date) {
        return simpleLongDatetimeFormat.get().format(date);
    }

    /**
     * 按yyyyMMdd格式化
     *
     * @param date
     * @return
     */
    public static long date2Long(Date date) {
        return Long.parseLong(formatSimpleDate(date));
    }

    /**
     * 按yyyyMMddHHmmss格式化
     *
     * @param date
     * @return
     */
    public static long dateTime2Long(Date date) {
        return Long.parseLong(formatSimpleDateTime(date));
    }

    public static String nowDate() {
        return formatDate(now());
    }

    public static String nowDateTime() {
        return formatDateTime(now());
    }

    public static long nowDateLong() {
        return date2Long(now());
    }

    public static long nowDateTimeLong() {
        return dateTime2Long(now());
    }

    // 获得当天0点时间
    public static long getTimesmorning() {
        return getTimesmorning(System.currentTimeMillis());
    }

    // 获得指定时间0点时间
    public static long getTimesmorning(long time) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(time);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTimeInMillis();
    }

    // 获得昨天0点时间
    public static long getYesterdaymorning() {
        return getTimesmorning() - DateUtils.MILLIS_PER_DAY;
    }

    // 获得当天近7天时间
    public static long getWeekFromNow() {
        return getTimesmorning() - DateUtils.MILLIS_PER_DAY * 7;
    }

    // 获得当天24点时间
    public static long getTimesnight() {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 24);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTimeInMillis();
    }

    public static long getTimesnight(long time) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(time);
        cal.set(Calendar.HOUR_OF_DAY, 24);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTimeInMillis();
    }

    // 获得本周一0点时间
    public static long getTimesWeekmorning() {
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        return cal.getTimeInMillis();
    }

    // 获得本周日24点时间
    public static long getTimesWeeknight() {
        return getTimesWeekmorning() + DateUtils.MILLIS_PER_DAY * 7;
    }

    // 获得本月第一天0点时间
    public static long getTimesMonthMorning() {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(System.currentTimeMillis());
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
        return cal.getTimeInMillis();
    }

    // 获得本月最后一天24点时间
    public static long getTimesMontgHight() {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(System.currentTimeMillis());
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, 24);
        return cal.getTimeInMillis();
    }

    public static long getLastMonthStartMorning() {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(getTimesMonthMorning());
        cal.add(Calendar.MONTH, -1);
        return cal.getTimeInMillis();
    }

    public static long getLastMonthStartMorning(long timeInMillis) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(timeInMillis);
        cal.add(Calendar.MONTH, -1);
        return cal.getTimeInMillis();
    }

    public static Date getCurrentQuarterStartTime() {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(getTimesMonthMorning());
        int currentMonth = c.get(Calendar.MONTH) + 1;
        SimpleDateFormat longSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
        Date now = null;
        try {
            if (currentMonth <= 3) {
                c.set(Calendar.MONTH, 0);
            } else if (currentMonth <= 6) {
                c.set(Calendar.MONTH, 3);
            } else if (currentMonth <= 9) {
                c.set(Calendar.MONTH, 4);
            } else if (currentMonth <= 12) {
                c.set(Calendar.MONTH, 9);
            }

            c.set(Calendar.DATE, 1);
            now = longSdf.parse(shortSdf.format(c.getTime()) + " 00:00:00");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return now;
    }

    /**
     * 当前季度的结束时间，即2012-03-31 23:59:59
     *
     * @return
     */
    public static Date getCurrentQuarterEndTime() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getCurrentQuarterStartTime());
        cal.add(Calendar.MONTH, 3);
        return cal.getTime();
    }

    public static long getCurrentYearStartTime() {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(getTimesMonthMorning());
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONDAY), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.YEAR));
        return cal.getTimeInMillis();
    }

    public static long getCurrentYearEndTime() {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(getCurrentYearStartTime());
        cal.add(Calendar.YEAR, 1);
        return cal.getTimeInMillis();
    }

    public static long getLastYearStartTime() {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(getCurrentYearStartTime());
        cal.add(Calendar.YEAR, -1);
        return cal.getTimeInMillis();
    }

    public static long getLastYearStartTime(long timeInMillis) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(timeInMillis);
        cal.add(Calendar.YEAR, -1);
        return cal.getTimeInMillis();
    }

    public static String parseTimeTag(Date date) {
        if (date == null) {
            return "";
        }
        int now = date2Day(new Date());
        int day = date2Day(date);
        int deDay = now - day;
//		int deMonth = now/100 - day/100;
        int deYear = now / 10000 - day / 10000;
        if (deYear < 1) {
            switch (deDay) {
                case 0:
                    return new SimpleDateFormat("HH:mm").format(date);
                case 1:
                    return "昨天";
                default:
                    return new SimpleDateFormat("MM-dd").format(date);
            }
        }
        return new SimpleDateFormat("yyyy-MM-dd").format(date);
    }

    private static int date2Day(Date date) {
        return Integer.parseInt(new SimpleDateFormat("yyyyMMdd").format(date));
    }

    /**
     * 获取标准今日日期串
     *
     * @return 今日日期字符串 yyyy-MM-dd；
     */
    public static String nowStdDateString() {
        return parseTimeTag(now());
    }

    public static String nowYear() {
        return nowStdDateString().substring(0, 4);
    }

    //两位的月
    public static String nowMonth2() {
        return nowStdDateString().substring(5, 7);
    }

    /**
     * 取得当月第一天日期串
     *
     * @return String
     */
    public static String getMonthFirstDay() {
        return nowYear() + "-" + nowMonth2() + "-01";
    }

    public static String getMonthFirstDay(String ym) {
        return ym.substring(0, 4) + "-" + ym.substring(4, 6) + "-01";
    }

    public static String getMonthLastDay(String ym) {
        return getAfterDays(getAfterMonth(getMonthFirstDay(ym), 1), -1);
    }


    public static Long getMonthLastDayLong(String ym) {
        return Long.parseLong(getMonthLastDay(ym).replaceAll("-", ""));
    }


    /**
     * 取与指定日期间隔月的日期(yyyy-mm-dd)
     *
     * @return String java.sql.Date.toString()
     */
    public synchronized static String getAfterMonth(java.util.Date dt, int months) {
        if (dt == null) return "";
        if (months == 0) return dt.toString();
        GregorianCalendar dy = new GregorianCalendar();
        dy.setTime(dt);
        dy.add(GregorianCalendar.MONTH, months);
        java.sql.Date ret = new java.sql.Date(dy.getTimeInMillis());
        return ret.toString();
    }

    /**
     * 取与指定日期间隔月的日期(yyyy-mm-dd)
     *
     * @param dt     (yyyy-mm-dd)
     * @param months 间隔月
     * @return java.sql.Date.toString()
     */
    public static String getAfterMonth(String dt, int months) {
        return getAfterMonth(java.sql.Date.valueOf(dt), months);
    }

    /**
     * 得到date + days的日期
     *
     * @param dt   日期
     * @param days 间隔天数，正数往前，负数往后
     * @return String java.sql.Date.toString()
     */
    public synchronized static String getAfterDays(java.util.Date dt, int days) {
        if (dt == null) return "";
        if (days == 0) return dt.toString();
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTimeZone(mTimeZone);
        gc.setTime(dt);
        gc.add(GregorianCalendar.DATE, days);
        java.sql.Date ret = new java.sql.Date(gc.getTimeInMillis());
        return ret.toString();
    }


    /**
     * 得到date + days的日期
     *
     * @param dt   日期(yyyy-mm-dd)
     * @param days 间隔天数，正数往前，负数往后
     * @return String java.sql.Date.toString()
     */
    public static String getAfterDays(String dt, int days) {
        if (days == 0) return dt;
        try {
            return getAfterDays(java.sql.Date.valueOf(dt), days);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 取与指定日期间隔年的日期
     *
     * @return String java.sql.Date.toString()
     */
    public synchronized static String getAfterYear(Date dt, int years) {
        if (dt == null) return "";
        if (years == 0) return dt.toString();
        GregorianCalendar dy = new GregorianCalendar();
        dy.setTime(dt);
        dy.add(GregorianCalendar.YEAR, years);
        java.sql.Date ret = new java.sql.Date(dy.getTimeInMillis());
        return ret.toString();
    }

    /**
     * 取与指定日期间隔年的日期
     *
     * @param dt    (yyyy-mm-dd)
     * @param years 间隔年         j
     * @return java.sql.Date.toString()
     */
    public static String getAfterYear(String dt, int years) {
        return getAfterYear(java.sql.Date.valueOf(dt), years);
    }

    /**
     * get days between fromDate and thruDate
     *
     * @return the days between fromDate and thruDate
     */
    public static int getDifferDays(Date f, Date t) throws IllegalArgumentException {
        return getDifferSeconds(f, t) / (24 * 60 * 60);
    }

    public static int getDifferMinutes(Date f, Date t) throws IllegalArgumentException {
        return getDifferSeconds(f, t) / 60;
    }

    public static int getDifferMinutes(String f, String t) throws IllegalArgumentException {
        return getDifferSeconds(Timestamp.valueOf(f), Timestamp.valueOf(t)) / 60;
    }

    public static int getDifferMinutes(long f, long t) throws IllegalArgumentException {
        return getDifferSeconds(new Date(f), new Date(t)) / 60;
    }

    public static int getDifferSeconds(Date f, Date t) throws IllegalArgumentException {
        if (f == null || t == null) return 0;
        if (t.compareTo(f) < 0) {
            String msg = "[" + t + "] 比" + "[" + f + "] 早, 应该相反!";
            throw new IllegalArgumentException(msg);
        }
        return (int) ((t.getTime() - f.getTime()) / 1000);
    }


    /**
     * 判断strDate 是否是日期格式的字符串(支持如 yyyy-mm-dd)。
     *
     * @param strDate 字符串，判断其是否为日期格式。
     * @return boolean 如果为日期格式则返回=true;
     */
    public static boolean isDateFormat(String strDate) {
        return isDateFormat(strDate, "YYYY-MM-DD");
    }

    /**
     * 判断strDate 是否是日期格式的字符串。
     *
     * @param strDate 字符串，判断其是否为日期格式。
     * @param format  字符串，YYYY-MM,YYYYMM,YYYYMMDD,YYYY-MM-DD,YYYY-MM-DD:HH, 空表示所有上述格式,非上述内容将默认为YYYY-MM-DD；
     * @return boolean 如果为日期格式则返回=true;
     */
    public static boolean isDateFormat(String strDate, String format) {
        if (StringUtil.isEmpty(strDate)) {
            return false;
        }
        if (StringUtil.isEmpty(format)) {
            format = "YYYY-MM-DD";
        }
        switch (format) {
            case "YYYY-MM":
                return strDate.matches("\\d{4}-\\d{2}") && isDateValue(strDate.substring(0, 4), strDate.substring(5), "01");
            case "YYYYMM":
                return strDate.matches("\\d{6}") && isDateValue(strDate.substring(0, 4), strDate.substring(4), "01");
            case "YYYYMMDD":
                return strDate.matches("\\d{8}") && isDateValue(strDate.substring(0, 4), strDate.substring(4, 6), strDate.substring(6));
            case "YYYY-MM-DD":
                return strDate.matches("\\d{4}-\\d{2}-\\d{2}") && isDateValue(strDate.substring(0, 4), strDate.substring(5, 7), strDate.substring(8));
            case "YYYY-MM-DD:HH":
                return strDate.matches("\\d{4}-\\d{2}-\\d{2}:[0-5][0-9]") && isDateValue(strDate.substring(0, 4), strDate.substring(5, 7), strDate.substring(8, 10));
            case "HHmmss":
                return strDate.matches("[0-5][0-9][0-5][0-9][0-5][0-9]") && isTimeValue(strDate.substring(0, 2), strDate.substring(2, 4), strDate.substring(4));
            default:
                return false;
        }
    }

    public static boolean isDateValue(String year, String month, String day) {
        SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
        s.setLenient(false);//这个的功能是不把1996-13-3 转换为1997-1-3
        try {
            s.parse(year + "-" + month + "-" + day);
            return true;
        } catch (ParseException e) {
            return false;
        }
    }

    public static boolean isTimeValue(String hour, String min, String sec) {
        SimpleDateFormat s = new SimpleDateFormat("HH:mm:ss");
        s.setLenient(false);
        try {
            s.parse(hour + ":" + min + ":" + sec);
            return true;
        } catch (ParseException e) {
            return false;
        }
    }

    /**
     * 将日期变为"yyyyMMdd"
     *
     * @param date 日期
     * @return 字符串，如果传入参数为null,则返回当前日期；
     */
    public static String toDateString(Date date) {
        if (date == null) date = new java.sql.Date(System.currentTimeMillis());
        return simpleDateFormat.get().format(date);
    }

    /**
     * 得到如下字符串 "HHmmss"
     *
     * @param date 时间戳 如果传入为NULL,则返回当前日期；
     * @return 时间串
     */
    public static String toTimeString(Date date) {
        if (date == null) new java.sql.Date(System.currentTimeMillis());
        synchronized (simpleTimeFormat) {
            return simpleTimeFormat.get().format(date);
        }
    }

    /**
     * 得到长日期时间字符[yyyyMMddHHmmss]
     *
     * @param date 时间戳，如果传入为null,则返回当前日期
     * @return 日期时间串
     */
    public static String toDateTimeString(Date date) {
        if (date == null) date = new java.sql.Date(System.currentTimeMillis());
        return simpleDatetimeFormat.get().format(date);
    }

    public static java.sql.Date toDate(Timestamp datetime) {
        if (datetime == null) return null;
        return new java.sql.Date(datetime.getTime());
    }

    //获取当前日期所处月,却掉了前置的0.
    public static String nowMonth() {
        String month = nowMonth2();
        if (month.charAt(0) == '0') {
            return String.valueOf(month.charAt(1));
        }
        return month;
    }

    /**
     * 将字符串转换成Java.sql.Date,不能转换，这返回null
     *
     * @param src 源串
     * @return java.sql.Date
     */
    public static java.sql.Date toDate(String src) {
        try {
            if (StringUtil.isEmpty(src)) return null;
            return java.sql.Date.valueOf(src);
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 得到长日期时间字符[yyyyMMddHHmmss]
     *
     * @param date yyyy-mm-dd hh:mm:ss格式
     * @return
     */
    public static String toDateTimeString(String date) {
        return toDateTimeString(toDate(date));
    }

    public static String toDateTimeString(Timestamp date) {
        return toDateTimeString(toDate(date));
    }

    /**
     * 得到长日期时间字符[yyyyMMddHHmmss]
     *
     * @param date yyyy-mm-dd hh:mm:ss格式
     * @return
     */
    public static long toDateTimeLong(String date) {
        return Long.parseLong(toDateTimeString(date));
    }

    public static long toDateTimeLong(Timestamp date) {
        return Long.parseLong(toDateTimeString(date));
    }

    /**
     * 得到长日期时间字符[yyyyMMddHHmmssS]
     *
     * @param date 时间戳，如果传入为null,则返回当前日期
     * @return 日期时间串，长
     */
    public static String toLongDateTimeString(Date date) {
        if (date == null) date = new java.sql.Date(System.currentTimeMillis());
        synchronized (simpleLongDatetimeFormat) {
            return simpleLongDatetimeFormat.get().format(date);
        }
    }
//    /**
//     * 将字符串转换成Java.sql.Date,不能转换，这返回null
//     *
//     * @param src 源串
//     * @return java.sql.Date
//     */
//    public static java.sql.Date toDate(String src) {
//        try {
//            if (PubUtil.isEmpty(src)) return null;
//            return java.sql.Date.valueOf(src);
//        } catch (Exception e) {
//            return null;
//        }
//    }

    /**
     * 用中方格式化年月日
     *
     * @param yearMonth YYYYMM
     */
    public static String fmtCNYearMonth(String yearMonth) {
        if (NumberUtil.getIntIgnoreErr(yearMonth) > 190000)
            return String.format("%s年%s月", yearMonth.substring(0, 4), yearMonth.substring(4));
        return "";
    }

    /**
     * 用中方格式化年月日
     *
     * @param yearMonth YYYYMMDD
     */
    public static String fmtCNYearMonthDay(String yearMonth) {
        if (StringUtil.isEmpty(yearMonth) || yearMonth.length() != 8) return yearMonth;
        return String.format("%s年%s月%s日", yearMonth.substring(0, 4), yearMonth.substring(4, 6), yearMonth.substring(6));
    }

    /**
     * 用中方格式化年月日
     *
     * @param stdYearMonthDay YYYY-MM-DD
     */
    public static String fmtZHCNYearMonthDay(String stdYearMonthDay) {
        return String.format("%s年%s月%s日", stdYearMonthDay.substring(0, 4), stdYearMonthDay.substring(5, 7), stdYearMonthDay.substring(8));
    }

    public synchronized static Date getSeasonBegin(Calendar now) {
        int curYear = now.get(Calendar.YEAR);
        int curMonth = now.get(Calendar.MONTH);
        int seasonMonth = m_seasonBeginTable[curMonth];

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, curYear);
        calendar.set(Calendar.MONTH, seasonMonth);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.AM_PM, Calendar.AM);
        return new Timestamp(calendar.getTime().getTime());
    }

    //季度开始
    public synchronized static Date getSeasonBegin() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        return getSeasonBegin(calendar);
    }

    public synchronized static java.sql.Date getAfterDate(Date dt, int days) {
        if (dt == null) return null;
        GregorianCalendar gc = new GregorianCalendar();
        gc.setTime(dt);
        gc.add(GregorianCalendar.DATE, days);
        return new java.sql.Date(gc.getTimeInMillis());
    }

    //获取季度结束年月，YYYYMM格式
    public static String getSeasonEndYm() {
        return getDateYm(getAfterDate(getNextSeasonBegin(), -1));
    }

    //获取年度开始年月，YYYYMM格式
    public static String getYearBeginYm() {
        return nowYear() + "01";
    }

    public static String getYearBeginYm(String ymPeriod) {
        try {
            return ymPeriod.substring(0, 4) + "01";
        } catch (Exception e) {
            return nowYear() + "01";
        }
    }

    /**
     * 获取今日日期串，不带分隔符
     *
     * @return 今日日期字符串 yyyyMMdd；
     */
    public static String nowDateString() {
        return simpleDateFormat.get().format(nowTimestamp());
    }

    //获取年度结束年月，YYYYMM格式
    public static String getYearEndYm() {
        return nowYear() + "12";
    }

    public static String getYearEndYm(String ymPeriod) {
        try {
            return ymPeriod.substring(0, 4) + "12";
        } catch (Exception e) {
            return nowYear() + "12";
        }
    }

    /**
     * 得到本季度的第一天
     *
     * @return
     */
    public static String getSeasonFirstDay() {
        return toStdDateString(getSeasonBegin());
    }

    public static String getYearFirstDay() {
        return nowYear() + "-01-01";
    }

    public static String getYearLastDay() {
        return nowYear() + "-12-31";
    }

    /**
     * 取得当月最后一天YYYY-MM-DD
     *
     * @return 当前月最后一天的日期串；
     */
    public static String getMonthEnd() {
        return getAfterDays(getAfterMonth(getMonthStart(), 1), -1);
    }

    /**
     * 取得指定日期所在月最后一天YYYY-MM-DD
     *
     * @return 所在前月最后一天的日期串；
     */
    public static String getMonthEnd(Date d) {
        return getAfterDays(getAfterMonth(getMonthStart(d), 1), -1);
    }

    /**
     * 返回当前标准年月
     *
     * @return YYYY-MM
     */
    public static String nowStdYearMonth() {
        return nowStdDateString().substring(0, 7);
    }

    /**
     * 取得当月第一天日期串YYYY-MM-DD
     *
     * @return 月第一天的标准日期串
     */
    public static String getMonthStart() {
        return nowStdYearMonth() + "-01";
    }

    /**
     * 取得指定日期所在月第一天日期串YYYY-MM-DD
     *
     * @return 月第一天的标准日期串
     */
    public static String getMonthStart(Date d) {
        if (d == null) return "";
        return toStdDateString(d).substring(0, 7) + "-01";
    }

    /**
     * 取得当月最后一天
     *
     * @return String
     */
    public static String getMonthLastDay() {
        return getAfterDays(getAfterMonth(getMonthFirstDay(), 1), -1);
    }

    /**
     * 得到本季度最后一天
     *
     * @return
     */
    public static String getSeasonLastDay() {
        String s = toStdDateString(getNextSeasonBegin());
        return getAfterDays(s, -1);
    }

    //下个季度开始
    public synchronized static Date getNextSeasonBegin() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        return getNextSeasonBegin(calendar);
    }

    public synchronized static Date getNextSeasonBegin(Calendar now) {
        int curYear = now.get(Calendar.YEAR);
        int curMonth = now.get(Calendar.MONTH);
        int seasonMonth = m_seasonBeginTable[curMonth] + 3;

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, curYear);
        calendar.set(Calendar.MONTH, seasonMonth);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.AM_PM, Calendar.AM);
        return new Timestamp(calendar.getTime().getTime());
    }

    //获取季度开始年月，YYYYMM格式
    public static String getSeasonBeginYm() {
        return getDateYm(getSeasonBegin());
    }

    //获取年月，YYYYMM格式
    public static String getNowYm() {
        return getDateYm(nowTimestamp());
    }

    public static String getNextYear(String year, int add) {
        if (StringUtil.isEmpty(year)) return year;
        int curYear = Integer.parseInt(year) - 1;
        return curYear + "";
    }

    //获取上一月，YYYYMM格式
    public static String getPrevYear(String year) {
        return getNextYear(year, -1);
    }

    //获取上一月，YYYYMM格式
    public static String getPrevYm(String period_id) {
        return getNextYm(period_id, -1);
    }


    //获取下一月，YYYYMM格式
    public static String getNextYm(String period_id) {
        return getNextYm(period_id, 1);
    }

    //获取年月，YYYYMM格式
    public static String getPrevYm() {
        return getPrevYm(getNowYm());
    }

    //获取上一年 YYYY格式
    public static String getPrevYear() {
        return getPrevYear(nowYear());
    }

    //获取年月，YYYYMM格式
    public static String getNextYm() {
        return getNextYm(getNowYm());
    }

    public static String getNextYm(String period_id, int add) {
        if (StringUtil.isEmpty(period_id)) return period_id;
        int curYear = Integer.parseInt(period_id.substring(0, 4));
        int curMonth = Integer.parseInt(period_id.substring(4)) + add;
        if (curMonth > 12) {
            do {
                curYear++;
                curMonth -= 12;
            } while (curMonth > 12);
        } else if (curMonth <= 0) {
            do {
                curYear--;
                curMonth += 12;
            } while (curMonth <= 0);
        }
        return curYear + StringUtil.getRight("00" + curMonth, 2);
    }

    /**
     * 得到当前日期所在周次的星期一
     *
     * @return 返回的时间戳
     */
    public static Timestamp getWeekStart() {
        return getWeekStart(new Timestamp(System.currentTimeMillis()));
    }

    /**
     * 得到日期所在周次的星期一
     *
     * @param stamp 参数时间戳，如果传入为null,则返回为null
     * @return 返回时间戳
     */
    public synchronized static Timestamp getWeekStart(Timestamp stamp) {
        if (stamp == null) return null;
        GregorianCalendar tempCal = new GregorianCalendar(mTimeZone);
        tempCal.setTime(stamp);
        tempCal.set(tempCal.get(Calendar.YEAR), tempCal.get(Calendar.MONTH), tempCal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        if (tempCal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            // AKzz fix bug:
            // 如果今天是星期天, 天数再减1,找到上周(外国人的星期天是本周).
            tempCal.add(Calendar.DATE, -1);                 // 再将天数减一
        }
        tempCal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); // 设为星期一.

        Timestamp retStamp = new Timestamp(tempCal.getTime().getTime());
        retStamp.setNanos(0);
        return retStamp;
    }

    /**
     * 当前日期的下周星期一
     */
    public static Timestamp getNextWeekStart() {
        return getNextWeekStart(new Timestamp(System.currentTimeMillis()));
    }

    /**
     * 当前日期的下周星期一,如果传入null,则返回为null
     *
     * @param t 要计算的时间戳
     * @return 返回的时间戳
     */
    public synchronized static Timestamp getNextWeekStart(Timestamp t) {
        if (t == null) return null;
        Calendar tempCal = new GregorianCalendar(mTimeZone);
        tempCal.setTime(t);
        tempCal.set(tempCal.get(Calendar.YEAR), tempCal.get(Calendar.MONTH), tempCal.get(Calendar.DAY_OF_MONTH),
                // 没有时,分,秒
                0, 0, 0);
        tempCal.add(Calendar.WEEK_OF_MONTH, 1);             // 周数加1
        tempCal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); // 设为星期一.

        Timestamp retStamp = new Timestamp(tempCal.getTime().getTime());
        retStamp.setNanos(0);
        return retStamp;
    }

    public static String getHalfEndYm(String ymPeriod) {
        try {
            String year = ymPeriod.substring(0, 4);
            String month = ymPeriod.substring(4);
            if (month.startsWith("0")) {
                int m = Integer.parseInt(month.substring(1));
                if (m > 6) {
                    ymPeriod = year + "12";
                } else {
                    ymPeriod = year + "06";
                }
            } else {
                ymPeriod = year + "12";
            }
            return ymPeriod;
        } catch (Exception e) {
            return ymPeriod;
        }
    }

    public static String getHalfEndYm() {
        return getHalfEndYm(DateUtil.getNowYm());
    }

    //获取年月，YYYYMM格式
    public static String getDateYm(Date dt) {
        String s = simpleDateFormat.get().format(dt);
        return s.substring(0, 6);
    }

    //获取年月，YYYY-MM-DD格式
    public static String getDateYm(String dt) {
        if (dt == null || dt.length() < 6) return null;
        if (dt.contains("-")) {
            return dt.substring(0, 4) + dt.substring(5, 7);
        }
        return dt.substring(0, 6);
    }

    public static void main(String[] args) {
        System.out.println(getTimesmorning());
    }

    /**
     * 转日期时间long
     *
     * @param dateStr
     * @return
     */
    public static long getDateTimeLong(String dateStr) {
        if (StringUtil.isEmpty(dateStr)) {
            return -1L;
        }
        String _dateTime = dateStr.replaceAll("-", "").replaceAll(" ", "").replaceAll(":", "");
        _dateTime = StringUtil.getLeft(_dateTime + "00000000000000", 14);
        return NumberUtil.getLongIgnoreErr(_dateTime);
    }

    public static long getDateLong(String dateStr) {
        if (StringUtil.isEmpty(dateStr) || dateStr.length() != 10) {
            return -1L;
        }
        String _dateTime = dateStr.replaceAll("-", "");
        return NumberUtil.getLongIgnoreErr(_dateTime);
    }

    /**
     * 转日期时间long
     *
     * @param dateStr
     * @return
     */
    public static long getEndDateTimeLong(String dateStr) {
        if (StringUtil.isEmpty(dateStr)) {
            return -1L;
        }
        String _dateTime = dateStr.replaceAll("-", "").replaceAll(" ", "").replaceAll(":", "");
        _dateTime = StringUtil.getLeft(_dateTime + "00000000", 8) + "235959";
        return NumberUtil.getLongIgnoreErr(_dateTime);
    }

}
