package com.ssj.framework.weixin.util;

import java.text.DateFormat;
import java.text.ParseException;
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.List;
import java.util.Locale;
import java.util.Map;
import java.util.SimpleTimeZone;
import java.util.TimeZone;

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

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;

/**
 * Created with IntelliJ IDEA. User: leron Date: 13-8-21 Time: 下午12:09 日期辅助类
 */
public class DateUtil extends DateUtils {

    /**
     * Base ISO 8601 Date format yyyyMMdd i.e., 20021225 for the 25th day of December in the year 2002
     */
    public static final String ISO_DATE_FORMAT                 = "yyyyMMdd";

    /**
     * Expanded ISO 8601 Date format yyyy-MM-dd i.e., 2002-12-25 for the 25th day of December in the year 2002
     */
    public static final String ISO_EXPANDED_DATE_FORMAT        = "yyyy-MM-dd";

    /**
     * yyyy-MM-dd hh:mm:ss
     */
    public static String       DATETIME_PATTERN                = "yyyy-MM-dd HH:mm:ss";
    /**
     * yyyy-MM-dd hh:mm
     */
    public static String       DATETIME_PATTERN_MINUTE         = "yyyy-MM-dd HH:mm";
    /**
     * yyyyMMddHHmmss
     */
    public static String       DATETIME_PATTERN_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String       DATETIME_PATTERN_MMSS           = "mmss";

    /**
     * Default lenient setting for getDate.
     */
    private static boolean     LENIENT_DATE                    = false;

    public static String[]     TIME_RANGE_NAMES                = { "今天", "本周", "上周", "本月", "上月", "今年", "全部" };
    public static String[]     TIME_RANGE_VALUES               = { "today", "thisweek", "lastweek", "thismonth",
                                                                   "lastmonth", "thisyear", "all" };

    static String[]            yyyyMMddHHmmss                  = new String[] { "yyyy-MM-dd HH:mm:ss", "yyyyMMddHHmmss",
                                                                                "yyyy-MM-dd'T'HH:mm:ss" };

    static String[]            yyyyMMdd                        = new String[] { "yyyy-MM-dd", "yyyyMMdd" };
    static String              HHmmss                          = "HH:mm:ss";
    static String              HHmm                            = "HH:mm";
    static String              HHmmss_nosp                     = "HHmmss";

    public static final Date   MaxDateTime                     = parse_yyyyMMddHHmmss("9999-12-31 23:59:59",
                                                                                      new Date(0L));
    public static final Date   MinDateTime                     = parse_yyyyMMddHHmmss("0001-01-01 00:00:00",
                                                                                      new Date(0L));

    public static Date AddMonth(Date beginDate, Integer addNum) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(beginDate);
        cal.add(Calendar.MONTH, 1);
        return cal.getTime();
    }

    public static Date AddDay(Date beginDate, Integer addNum) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(beginDate);
        cal.add(Calendar.DATE, addNum);
        return cal.getTime();
    }

    public static Date AddYear(Date beginDate, Integer addYear) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(beginDate);
        cal.add(Calendar.YEAR, 1);
        return cal.getTime();
    }

    public static String format_yyyyMM_nosp(Date date) {
        if (date == null) {
            return "";
        }
        return DateFormatUtils.format(date, "yyyyMM");
    }

    public static String format_yyyyMMdd(Date date) {
        if (date == null) {
            return "";
        }
        return DateFormatUtils.format(date, yyyyMMdd[0]);
    }

    public static String format_yyyyMMdd_nosp(Date date) {
        if (date == null) {
            return "";
        }
        return DateFormatUtils.format(date, yyyyMMdd[1]);
    }

    public static String parse_unix_yyyyMMdd(Long second) {
        Date theDate = new Date(second * 1000L);
        return format_yyyyMMdd_nosp(theDate);
    }

    public static String format_HHmmss(Date date) {
        if (date == null) {
            return "";
        }
        return DateFormatUtils.format(date, HHmmss);
    }

    public static String format_HHmmss_nosp(Date date) {
        if (date == null) {
            return "";
        }
        return DateFormatUtils.format(date, HHmmss_nosp);
    }
    
    public static String format_HHmm(Date date) {
        if (date == null) {
            return "";
        }
        return DateFormatUtils.format(date, HHmm);
    }

    public static String getNowTime_yyyyMMddHHmmss() {
        return DateFormatUtils.format(new Date(), yyyyMMddHHmmss[0]);
    }

    public static Integer getNow_Unix() {
        Long time = System.currentTimeMillis();
        return (int) (time / 1000);
    }

    public static Date parse_yyyyMMddHHmmss(String date, Date defaultDate) {
        if (date == null) {
            return defaultDate;
        }
        try {
            return DateUtils.parseDate(date, yyyyMMddHHmmss);
        } catch (Exception e) {
            return defaultDate;
        }
    }

    public static Date parse_yyyyMMddHHmmss(String date) {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(date));
        try {
            return DateUtils.parseDate(date, yyyyMMddHHmmss);
        } catch (Exception e) {
            Throwables.propagate(e);
        }
        // 不可能到此
        return null;
    }

    public static Long parse_unix_yyyyMMddHHmmss(String date) {
        Date thedate = parse_yyyyMMddHHmmss(date);
        return thedate.getTime() / 1000;
    }

    public static Date parse_yyyyMMdd(String date, Date defaultDate) {
        if (Strings.isNullOrEmpty(date)) {
            return defaultDate;
        }
        try {
            return DateUtils.parseDate(date, yyyyMMdd);
        } catch (Throwable e) {
            return defaultDate;
        }
    }

    public static Date parse_yyyyMMdd(String date) {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(date));
        try {
            return DateUtils.parseDate(date, yyyyMMdd);
        } catch (ParseException e) {
            Throwables.propagate(e);
        }
        // 不可能到此
        return null;
    }

    public static String format_yyyyMMddHHmmss(Date date) {
        if (date == null) {
            return "";
        }
        return DateFormatUtils.format(date, yyyyMMddHHmmss[0]);
    }

    public static String format_yyyyMMddHHmmss_nosp(Date date) {
        if (date == null) {
            return "";
        }
        return DateFormatUtils.format(date, yyyyMMddHHmmss[1]);
    }

    public static String format_yyyyMMddHHmmss_H(Date date) {
        if (date == null) {
            return "";
        }
        return DateFormatUtils.format(date, yyyyMMddHHmmss[2]);
    }

    public static String format_yyyyMMddHHmmss_H(Long second) {
        Date theDate = new Date(second * 1000L);
        return format_yyyyMMddHHmmss_H(theDate);
    }

    public static String format_unix_yyyyMMdd(Long second) {
        Date theDate = new Date(second * 1000L);
        return format_yyyyMMdd(theDate);
    }

    public static String format_unix_yyyyMMddHHmmss(Long second) {
        Date theDate = new Date(second * 1000L);
        return format_yyyyMMddHHmmss(theDate);
    }

    public static String format(Long millis, String format) {
        return DateFormatUtils.format(millis, format);
    }

    /**
     * 根据Unix时间转换为日期
     *
     * @param second
     * @return
     */
    public static String format_unix_yyyyMMddHHmmss_nosp(Long second) {
        Date theDate = new Date(second * 1000L);
        return format_yyyyMMddHHmmss_nosp(theDate);
    }

    /**
     * 暂时不用
     *
     * @param JD
     * @return
     */
    protected static final float normalizedJulian(float JD) {

        float f = Math.round(JD + 0.5f) - 0.5f;

        return f;
    }

    /**
     * 浮点值转换成日期格式<br>
     * 暂时不用 Returns the Date from a julian. The Julian date will be converted to noon GMT, such that it matches the
     * nearest half-integer (i.e., a julian date of 1.4 gets changed to 1.5, and 0.9 gets changed to 0.5.)
     *
     * @param JD the Julian date
     * @return the Gregorian date
     */
    public static final Date toDate(float JD) {

        /*
         * To convert a Julian Day Number to a Gregorian date, assume that it is for 0 hours, Greenwich time (so that it
         * ends in 0.5). Do the following calculations, again dropping the fractional part of all multiplicatons and
         * divisions. Note: This method will not give dates accurately on the Gregorian Proleptic Calendar, i.e., the
         * calendar you get by extending the Gregorian calendar backwards to years earlier than 1582. using the
         * Gregorian leap year rules. In particular, the method fails if Y<400.
         */
        float Z = (normalizedJulian(JD)) + 0.5f;
        float W = (int) ((Z - 1867216.25f) / 36524.25f);
        float X = (int) (W / 4f);
        float A = Z + 1 + W - X;
        float B = A + 1524;
        float C = (int) ((B - 122.1) / 365.25);
        float D = (int) (365.25f * C);
        float E = (int) ((B - D) / 30.6001);
        float F = (int) (30.6001f * E);
        int day = (int) (B - D - F);
        int month = (int) (E - 1);

        if (month > 12) {
            month = month - 12;
        }

        int year = (int) (C - 4715); // (if Month is January or February) or
        // C-4716 (otherwise)

        if (month > 2) {
            year--;
        }

        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month - 1); // damn 0 offsets
        c.set(Calendar.DATE, day);

        return c.getTime();
    }

    /**
     * Returns the days between two dates. Positive values indicate that the second date is after the first, and
     * negative values indicate, well, the opposite. Relying on specific times is problematic.
     *
     * @param early the "first date"
     * @param late the "second date"
     * @return the days between the two dates
     */
    public static final int daysBetween(Date early, Date late) {

        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(early);
        c2.setTime(late);

        return daysBetween(c1, c2);
    }

    /**
     * Returns the days between two dates. Positive values indicate that the second date is after the first, and
     * negative values indicate, well, the opposite.
     *
     * @param early
     * @param late
     * @return the days between two dates.
     */
    public static final int daysBetween(Calendar early, Calendar late) {

        return (int) (toJulian(late) - toJulian(early));
    }

    /**
     * Return a Julian date based on the input parameter. This is based from calculations found at
     * <a href="http://quasar.as.utexas.edu/BillInfo/JulianDatesG.html">Julian Day Calculations (Gregorian
     * Calendar)</a>, provided by Bill Jeffrys.
     *
     * @param c a calendar instance
     * @return the julian day number
     */
    public static final float toJulian(Calendar c) {

        int Y = c.get(Calendar.YEAR);
        int M = c.get(Calendar.MONTH);
        int D = c.get(Calendar.DATE);
        int A = Y / 100;
        int B = A / 4;
        int C = 2 - A + B;
        float E = (int) (365.25f * (Y + 4716));
        float F = (int) (30.6001f * (M + 1));
        float JD = C + D + E + F - 1524.5f;

        return JD;
    }

    /**
     * 暂时不用 Return a Julian date based on the input parameter. This is based from calculations found at
     * <a href="http://quasar.as.utexas.edu/BillInfo/JulianDatesG.html">Julian Day Calculations (Gregorian
     * Calendar)</a>, provided by Bill Jeffrys.
     *
     * @param date
     * @return the julian day number
     */
    public static final float toJulian(Date date) {

        Calendar c = Calendar.getInstance();
        c.setTime(date);

        return toJulian(c);
    }

    /**
     * 日期增加
     *
     * @param isoString 日期字符串
     * @param fmt 格式
     * @param field 年/月/日 Calendar.YEAR/Calendar.MONTH/Calendar.DATE
     * @param amount 增加数量
     * @return
     */
    public static final String dateIncrease(String isoString, String fmt, int field, int amount) {

        try {
            Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
            cal.setTime(stringToDate(isoString, fmt, true));
            cal.add(field, amount);

            return dateToString(cal.getTime(), fmt);

        } catch (Exception ex) {
            return null;
        }
    }

    /**
     * Time Field Rolling function. Rolls (up/down) a single unit of time on the given time field.
     *
     * @param isoString
     * @param field the time field.
     * @param up Indicates if rolling up or rolling down the field value. use formating char's
     * @throws ParseException if an unknown field value is given.
     */
    public static final String roll(String isoString, String fmt, int field, boolean up) throws ParseException {

        Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
        cal.setTime(stringToDate(isoString, fmt));
        cal.roll(field, up);

        return dateToString(cal.getTime(), fmt);
    }

    /**
     * Time Field Rolling function. Rolls (up/down) a single unit of time on the given time field.
     *
     * @param isoString
     * @param field the time field.
     * @param up Indicates if rolling up or rolling down the field value.
     * @throws ParseException if an unknown field value is given.
     */
    public static final String roll(String isoString, int field, boolean up) throws ParseException {

        return roll(isoString, DATETIME_PATTERN, field, up);
    }

    /**
     * 字符串转换为日期java.util.Date
     *
     * @param dateText 字符串
     * @param format 日期格式
     * @param lenient 日期越界标志
     * @return
     */
    public static Date stringToDate(String dateText, String format, boolean lenient) {

        if (dateText == null) {

            return null;
        }

        if (dateText.length() == 10) dateText = dateText + " 00:00:00";

        DateFormat df = null;

        try {

            if (format == null) {
                df = new SimpleDateFormat();
            } else {
                df = new SimpleDateFormat(format);
            }

            // setLenient avoids allowing dates like 9/32/2001
            // which would otherwise parse to 10/2/2001
            // df.setLenient(false);

            return df.parse(dateText);
        } catch (ParseException e) {

            return null;
        }
    }

    /**
     * 字符串转换为日期java.util.Date
     *
     * @param dateString 字符串
     * @param format 日期格式
     * @return
     */
    public static Date stringToDate(String dateString, String format) {

        return stringToDate(dateString, format, LENIENT_DATE);
    }

    /**
     * 字符串转换为日期java.util.Date
     *
     * @param dateString 字符串
     */
    public static Date stringToDate2(String dateString) {

        return stringToDate(dateString, DATETIME_PATTERN, LENIENT_DATE);
    }

    /**
     * 字符串转换为日期java.util.Date
     *
     * @param dateString 字符串
     */
    public static Date stringToDate(String dateString) {

        return stringToDate(dateString, ISO_EXPANDED_DATE_FORMAT, LENIENT_DATE);
    }

    /**
     * 根据时间变量返回时间字符串
     *
     * @param dateText 时间变量
     * @return 返回时间字符串
     */
    public static String stringToDateToString(String dateText) {
        if (dateText == null) {
            return null;
        }
        if (dateText.length() == 10) dateText = dateText + " 00:00:00";
        DateFormat df = null;
        try {
            df = new SimpleDateFormat(DATETIME_PATTERN);
            // setLenient avoids allowing dates like 9/32/2001
            // which would otherwise parse to 10/2/2001
            df.setLenient(false);
            return dateToString(df.parse(dateText), DATETIME_PATTERN);
        } catch (ParseException e) {

            return null;
        }

    }

    /**
     * 根据时间变量返回时间字符串
     *
     * @param pattern 时间字符串样式
     * @param date 时间变量
     * @return 返回时间字符串
     */
    public static String dateToString(Date date, String pattern) {

        if (date == null) {

            return null;
        }

        try {

            SimpleDateFormat sfDate = new SimpleDateFormat(pattern);
            sfDate.setLenient(false);

            return sfDate.format(date);
        } catch (Exception e) {

            return null;
        }
    }

    public static String dateToString(String s, String pattern) {

        if (StringUtils.isEmpty(s)) {
            return null;
        }

        try {
            SimpleDateFormat sfDate = new SimpleDateFormat(pattern);
            Long lt = new Long(s);
            Date date = new Date(lt);

            return sfDate.format(date);
        } catch (Exception e) {

            return null;
        }
    }

    /**
     * 根据时间变量返回时间字符串 yyyy-MM-dd
     *
     * @param date
     * @return
     */
    public static String dateToString(Date date) {
        return dateToString(date, ISO_EXPANDED_DATE_FORMAT);
    }

    /**
     * 根据时间变量返回时间字符串 yyyy-MM-dd HH:mm:ss
     *
     * @param date
     * @return
     */
    public static String dateTimeToString(Date date) {
        return dateToString(date, DATETIME_PATTERN);
    }

    /**
     * 根据时间变量返回时间字符串 yyyy-MM-dd HH:mm
     *
     * @param date
     * @return
     */
    public static String dateTimeToStringMinute(Date date) {
        return dateToString(date, DATETIME_PATTERN_MINUTE);
    }

    public static String dateTimeToStringMinute(String date) {
        return dateToString(date, DATETIME_PATTERN_MINUTE);
    }

    public static Date parse_yyyyMMddHHmm(String date) {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(date));
        try {
            return DateUtils.parseDate(date, DATETIME_PATTERN_MINUTE);
        } catch (Exception e) {
            Throwables.propagate(e);
        }
        return null;
    }

    /**
     * 返回当前时间
     *
     * @return 返回当前时间
     */
    public static Date getCurrentDateTime() {
        Calendar calNow = Calendar.getInstance();
        Date dtNow = calNow.getTime();

        return dtNow;
    }

    /**
     * 返回当前日期字符串
     *
     * @param pattern 日期字符串样式
     * @return
     */
    public static String getCurrentDateString(String pattern) {
        return dateToString(getCurrentDateTime(), pattern);
    }

    /**
     * 返回当前日期字符串 yyyy-MM-dd
     *
     * @return
     */
    public static String getCurrentDateString() {
        return dateToString(getCurrentDateTime(), ISO_EXPANDED_DATE_FORMAT);
    }

    /**
     * 返回当前日期+时间字符串 yyyy-MM-dd hh:mm:ss
     *
     * @param date
     * @return
     */
    public static String dateToStringWithTime(Date date) {

        return dateToString(date, DATETIME_PATTERN);
    }

    /**
     * 日期增加-按日增加
     *
     * @param date
     * @param days
     * @return java.util.Date
     */
    public static Date dateIncreaseByDay(Date date, int days) {

        Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
        cal.setTime(date);
        cal.add(Calendar.DATE, days);

        return cal.getTime();
    }

    /**
     * 日期减少-按日减少
     *
     * @param date
     * @param days
     * @return
     */
    public static Date dateDecreaseByDay(Date date, int days) {
        Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
        cal.setTime(date);
        cal.add(Calendar.DATE, -days);
        return cal.getTime();
    }

    /**
     * 日期增加-按月增加
     *
     * @param date
     * @param mnt
     * @return java.util.Date
     */
    public static Date dateIncreaseByMonth(Date date, int mnt) {
        Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
        cal.setTime(date);
        cal.add(Calendar.MONTH, mnt);

        return cal.getTime();
    }

    /**
     * 日期增加-按月增加
     *
     * @param date
     * @param mnt
     * @return java.util.Date
     */
    public static Date dateDecreaseByMonth(Date date, int mnt) {
        Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
        cal.setTime(date);
        cal.add(Calendar.MONTH, -mnt);

        return cal.getTime();
    }

    /**
     * 日期增加-按年增加
     *
     * @param date
     * @param mnt
     * @return java.util.Date
     */
    public static Date dateIncreaseByYear(Date date, int mnt) {

        Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
        cal.setTime(date);
        cal.add(Calendar.YEAR, mnt);

        return cal.getTime();
    }

    /**
     * 日期增加
     *
     * @param date 日期字符串 yyyy-MM-dd
     * @param days
     * @return 日期字符串 yyyy-MM-dd
     */
    public static String dateIncreaseByDay(String date, int days) {
        return dateIncreaseByDay(date, ISO_DATE_FORMAT, days);
    }

    /**
     * 日期增加
     *
     * @param date 日期字符串
     * @param fmt 日期格式
     * @param days
     * @return
     */
    public static String dateIncreaseByDay(String date, String fmt, int days) {
        return dateIncrease(date, fmt, Calendar.DATE, days);
    }

    /**
     * 日期字符串格式转换
     *
     * @param src 日期字符串
     * @param srcfmt 源日期格式
     * @param desfmt 目标日期格式
     * @return
     */
    public static String stringToString(String src, String srcfmt, String desfmt) {
        return dateToString(stringToDate(src, srcfmt), desfmt);
    }

    /**
     * 日期范围函数组 getBeginOfThisWeek 本周开始日期 getEndOfThisWeek 本周结束日期 getBeginOfLastWeek 上周开始日期 getEndOfLastWeek 上周结束日期
     * getBeginOfThisMonth 本月开始日期 getEndOfThisMonth 本月结束日期 getBeginOfLastMonth 上月开始日期 getEndOfLastMonth 上月结束日期
     * getBeginOfThisYear 今年开始日期 getEndOfThisYear 今年结束日期
     *
     * @return
     */
    public static Date getBeginOfThisWeek(Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);

        int todayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (todayOfWeek >= Calendar.MONDAY && todayOfWeek <= Calendar.SATURDAY) {
            calendar.add(Calendar.DATE, 2 - todayOfWeek);
        } else if (todayOfWeek == Calendar.SUNDAY) {
            calendar.add(Calendar.DATE, -6);
        }

        return calendar.getTime();
    }

    public static Date getEndOfThisWeek(Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);

        int todayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if (todayOfWeek >= Calendar.MONDAY && todayOfWeek <= Calendar.SATURDAY) {
            calendar.add(Calendar.DATE, 8 - todayOfWeek);
        } else if (todayOfWeek == Calendar.SUNDAY) {
            calendar.add(Calendar.DATE, 0);
        }

        return calendar.getTime();
    }

    public static Date getBeginOfLastWeek(Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);
        calendar.add(Calendar.DATE, -7);

        return getBeginOfThisWeek(calendar.getTime());
    }

    public static Date getEndOfLastWeek(Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);
        calendar.add(Calendar.DATE, -7);

        return getEndOfThisWeek(calendar.getTime());
    }

    public static Date getBeginOfThisMonth(Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);

        int todayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        calendar.add(Calendar.DATE, 1 - todayOfMonth);

        return calendar.getTime();
    }

    public static Date getEndOfThisMonth(Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);

        int todayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
        int maxOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        calendar.add(Calendar.DAY_OF_MONTH, maxOfMonth - todayOfMonth);

        return calendar.getTime();
    }

    public static Date getBeginOfLastMonth(Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);
        calendar.add(Calendar.MONTH, -1);

        return getBeginOfThisMonth(calendar.getTime());
    }

    public static Date getEndOfLastMonth(Date today) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);
        calendar.add(Calendar.MONTH, -1);

        return getEndOfThisMonth(calendar.getTime());
    }

    public static Date getBeginOfThisYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int thisYear = calendar.get(Calendar.YEAR);

        return stringToDate(thisYear + "-1-1");
    }

    public static Date getEndOfThisYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int thisYear = calendar.get(Calendar.YEAR);

        return stringToDate(thisYear + "-12-31");
    }

    public static String getEndDate(String range) {
        return getEndDate(null, range);
    }

    public static String getEndDate(Date date, String range) {

        if (date == null) {
            date = new Date();
        }
        if (range.trim().equals(TIME_RANGE_VALUES[0])) {// today
            return dateToString(date) + " 23:59:59";

        } else if (range.trim().equals(TIME_RANGE_VALUES[1])) {// this week
            return dateToString(getEndOfThisWeek(date)) + " 23:59:59";

        } else if (range.trim().equals(TIME_RANGE_VALUES[2])) {// last week
            return dateToString(getEndOfLastWeek(date)) + " 23:59:59";

        } else if (range.trim().equals(TIME_RANGE_VALUES[3])) {// this month
            return dateToString(getEndOfThisMonth(date)) + " 23:59:59";

        } else if (range.trim().equals(TIME_RANGE_VALUES[4])) {// last month
            return dateToString(getEndOfLastMonth(date)) + " 23:59:59";

        } else if (range.trim().equals(TIME_RANGE_VALUES[5])) {// this year
            return dateToString(getEndOfThisYear(date)) + " 23:59:59";

        } else if (range.trim().equals(TIME_RANGE_VALUES[6])) {// all
            return "";
        }

        return "";
    }

    public static String getBeginDate(String range) {
        return getBeginDate(null, range);
    }

    public static String getBeginDate(Date date, String range) {
        if (date == null) {
            date = new Date();
        }
        if (range.trim().equals(TIME_RANGE_VALUES[0])) {// today
            return dateToString(date) + " 00:00:00";

        } else if (range.trim().equals(TIME_RANGE_VALUES[1])) {// this week
            return dateToString(getBeginOfThisWeek(date)) + " 00:00:00";

        } else if (range.trim().equals(TIME_RANGE_VALUES[2])) {// last week
            return dateToString(getBeginOfLastWeek(date)) + " 00:00:00";

        } else if (range.trim().equals(TIME_RANGE_VALUES[3])) {// this month
            return dateToString(getBeginOfThisMonth(date)) + " 00:00:00";

        } else if (range.trim().equals(TIME_RANGE_VALUES[4])) {// last month
            return dateToString(getBeginOfLastMonth(date)) + " 00:00:00";

        } else if (range.trim().equals(TIME_RANGE_VALUES[5])) {// this year
            return dateToString(getBeginOfThisYear(date)) + " 00:00:00";
        } else if (range.trim().equals(TIME_RANGE_VALUES[6])) {// all
            return "";
        }

        return "";
    }

    public static String getFormatDate(String formatDate) {
        SimpleDateFormat format = new SimpleDateFormat(DATETIME_PATTERN);
        String date = format.format(stringToDate(formatDate, DATETIME_PATTERN));
        return date;
    }

    /**
     * YYYYMMDDHHMMSS
     */
    public static String parseLongTime(Date date) {
        String fmt = "yyyyMMddHHmmss";
        DateFormat df = new SimpleDateFormat(fmt);
        String str = df.format(date);
        return str;
    }

    /**
     * YYYYMMDD
     *
     * @param date
     * @return
     */
    public static String getDate(Date date) {
        String fmt = "yyyyMMdd";
        DateFormat df = new SimpleDateFormat(fmt);
        String str = df.format(date);
        return str;
    }

    /**
     * YYYYMM
     */
    public static String getShortParseDate(Date date) {
        String fmt = "yyyyMM";
        DateFormat df = new SimpleDateFormat(fmt);
        String str = df.format(date);
        return str;
    }

    /**
     * 返回年份
     *
     * @param date 日期
     * @return 返回年份
     */
    public static int getYear(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.YEAR);
    }

    /**
     * 返回月份
     *
     * @param date 日期
     * @return 返回月份
     */
    public static int getMonth(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.MONTH) + 1;
    }

    /**
     * 返回日份
     *
     * @param date 日期
     * @return 返回日份
     */
    public static int getDay(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 返回月份
     *
     * @param date 日期
     * @return 返回月份 补0
     */
    public static String getMonthForStr(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int month = c.get(Calendar.MONTH) + 1;
        return month < 10 ? "0" + month : String.valueOf(month);
    }

    /**
     * 返回小时
     *
     * @param date 日期
     * @return 返回小时
     */
    public static int getHour(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 返回日份
     *
     * @param date 日期
     * @return 返回日份 补0
     */
    public static String getDayForStr(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int day = c.get(Calendar.DAY_OF_MONTH);
        return day < 10 ? "0" + day : String.valueOf(day);
    }

    /**
     * 返回分钟
     *
     * @param date 日期
     * @return 返回分钟
     */
    public static int getMinute(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.MINUTE);
    }

    /**
     * 返回秒钟
     *
     * @param date 日期
     * @return 返回秒钟
     */
    public static int getSecond(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.SECOND);
    }

    /**
     * 返回毫秒
     *
     * @param date 日期
     * @return 返回毫秒
     */
    public static long getMillis(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.getTimeInMillis();
    }

    /**
     * 返回毫秒
     *
     * @param date 日期
     * @return 返回毫秒
     */
    public static long getHexTime(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return Long.parseLong(("0x" + Long.toHexString(c.getTimeInMillis())));
    }

    /**
     * 返回毫秒
     *
     * @param date 日期
     * @return 返回毫秒
     */
    public static long getHexTime() {
        return getHexTime(new Date());
    }

    /**
     * 对当前日期增加月份
     *
     * @param month
     * @return
     */
    public static Date addMonth(Integer month) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MONTH, month);
        return calendar.getTime();
    }

    /**
     * 输入两个日期中区间的所有点
     */

    static String           dateFormat = "yyyy-MM-dd";
    static SimpleDateFormat format     = new SimpleDateFormat(dateFormat);

    public static List<Date> process(String date1, String date2) {
        List<Date> dateList = new ArrayList<Date>();

        if (date1.equals(date2)) {
            // System.out.println("两个日期相等!");
            dateList.add(DateUtil.stringToDate(date2, "yyyy-MM-dd"));
            return dateList;
        }

        String tmp;
        if (date1.compareTo(date2) > 0) { // 确保 date1的日期不晚于date2
            tmp = date1;
            date1 = date2;
            date2 = tmp;
        }

        tmp = format.format(str2Date(date1).getTime() + 3600 * 24 * 1000);

        int num = 0;
        while (tmp.compareTo(date2) < 0) {
            // System.out.println(tmp);
            dateList.add(DateUtil.stringToDate(tmp, "yyyy-MM-dd"));
            num++;
            tmp = format.format(str2Date(tmp).getTime() + 3600 * 24 * 1000);
        }

        // if (num == 0)
        // System.out.println("两个日期相邻!");
        return dateList;
    }

    private static Date str2Date(String str) {
        if (str == null) return null;

        try {
            return format.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 得到本周周一
     *
     * @return yyyy-MM-dd
     */
    public static String getMondayOfThisWeek() {
        Calendar c = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        int day_of_week = c.get(Calendar.DAY_OF_WEEK) - 1;
        if (day_of_week == 0) day_of_week = 7;
        c.add(Calendar.DATE, -day_of_week + 1);
        return df.format(c.getTime());
    }

    /**
     * 得到本周周日
     *
     * @return yyyy-MM-dd
     */
    public static String getSundayOfThisWeek() {
        Calendar c = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        int day_of_week = c.get(Calendar.DAY_OF_WEEK) - 1;
        if (day_of_week == 0) day_of_week = 7;
        c.add(Calendar.DATE, -day_of_week + 7);
        return df.format(c.getTime());
    }

    /**
     * 获取本周开始时间、结束时间
     *
     * @return
     */
    public static Map<String, Date> getCurrentWeek() {
        Map<String, Date> dateMap = new HashMap<String, Date>();
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");

        // 本周开始时间
        cal.set(Calendar.DAY_OF_WEEK - 1, Calendar.MONDAY); // 获取本周一的日期
        dateMap.put("beginTime", DateUtil.stringToDate2(df.format(cal.getTime())));

        // 本周结束时间
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        cal.add(Calendar.WEEK_OF_YEAR, 1);
        dateMap.put("endTime", DateUtil.stringToDate2(df.format(cal.getTime())));
        return dateMap;
    }

    /**
     * 得到某年某周的第一天
     *
     * @param year
     * @param week
     * @return
     */
    public static Date getFirstDayOfWeek(int year, int week) {
        Calendar c = new GregorianCalendar();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, Calendar.JANUARY);
        c.set(Calendar.DATE, 1);

        Calendar cal = (GregorianCalendar) c.clone();
        cal.add(Calendar.DATE, week * 7);

        return getBeginOfThisWeek(cal.getTime());
    }

    /**
     * 判断比较日期compareDate 是否在一个时间范围内
     *
     * @param compareDate 要比较的日期
     * @param beginDate 起始日期 可以为空
     * @param endDate 结束日期 可以为空
     * @return
     */
    public static boolean timeInExpiryDate(Date compareDate, Date beginDate, Date endDate) {
        boolean flag = false;
        if (beginDate != null) {
            long l = compareDate.getTime() - beginDate.getTime();
            if (l > 0) {
                if (endDate != null) {
                    long ll = compareDate.getTime() - endDate.getTime();
                    return ll < 0;
                } else {
                    return true;
                }
            } else {
                return false;
            }
        } else {
            if (endDate != null) {
                long l = compareDate.getTime() - endDate.getTime();
                return l < 0;
            }
        }
        return flag;
    }

    /**
     * 得到某年某周的最后一天
     *
     * @param year
     * @param week
     * @return
     */
    public static Date getLastDayOfWeek(int year, int week) {
        Calendar c = new GregorianCalendar();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, Calendar.JANUARY);
        c.set(Calendar.DATE, 1);

        Calendar cal = (GregorianCalendar) c.clone();
        cal.add(Calendar.DATE, week * 7);

        return getEndOfThisWeek(cal.getTime());
    }

    public static Date getSomeDateLater(Integer afterDateNum) {
        try {
            Calendar c = Calendar.getInstance();
            c.setTimeInMillis(System.currentTimeMillis());
            c.add(Calendar.DATE, afterDateNum);// 天后的日期
            String dateStr = format.format(new Date(c.getTimeInMillis()));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");// 小写的mm表示的是分钟
            return sdf.parse(dateStr); // 将c转换成Date
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取当前日期是星期几<br>
     *
     * @param dt
     * @return 当前日期是星期几
     */
    public static int getWeekDateToNumber(Date dt) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(dt);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0) w = 0;
        return w + 1;
    }

    /**
     * 获取当前日期是星期几<br>
     *
     * @param dt
     * @return 当前日期是星期几
     */
    public static String getWeekDateToStr(Date dt) {
    	Locale localeCN = Locale.SIMPLIFIED_CHINESE;
        SimpleDateFormat dateFm = new SimpleDateFormat("EEEE",localeCN);
        return dateFm.format(dt);
    }

    /**
     * 得到几天后的时间
     *
     * @param d
     * @param day
     * @return
     */
    public static Date getDateAfter(Date d, int day) {
        Calendar now = Calendar.getInstance();
        now.setTime(d);
        now.set(Calendar.DATE, now.get(Calendar.DATE) + day);
        return now.getTime();
    }
    
    /**
	* 方法名称: getTodatDate
	* 方法描述：获得今天00：00：00的时间
	* 参数 :@return
	* 返回类型: String
	* @throws
	* 创建人：yagncan   
	* 创建时间：2016年12月28日 下午10:25:05     
	*/
	public static Date getTodatDate() {
		SimpleDateFormat dformat = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
		String todayDate = dformat.format(new Date());
		try {
			return dformat.parse(todayDate);
		} catch (ParseException e) {
			return null;
		}
	}
	
	/**
	 * @param date1 
	 * @param date2
	 * @return
	
	 * 方法说明:如果date1 <= date2 return true 否则return false
	
	 * 创立日期:2018年6月11日 下午4:52:27
	 * 创建人:yangcan
	
	 */
	public static boolean compareDate(Date date1,Date date2) {
		if(date1.getTime() < date2.getTime()) {
			return true;
		}
		return false;
	}
	
	
	/**
	 * @return
	
	 * 方法说明:获取当前时间的月初时间 返回格式yyyy-MM-dd
	
	 * 创立日期:2018年7月17日 下午4:40:05
	 * 创建人:yangcan
	
	 */
	public static String getCurrentMonthBegin() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cale = Calendar.getInstance();
        cale.add(Calendar.MONTH, 0);
        cale.set(Calendar.DAY_OF_MONTH, 1);
        return format.format(cale.getTime());
	}
	
	/**
	 * @return
	
	 * 方法说明:获取当前时间的月底时间 返回格式yyyy-MM-dd
	
	 * 创立日期:2018年7月17日 下午4:41:38
	 * 创建人:yangcan
	
	 */
	public static String getCurrentMonthEnd() {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cale = Calendar.getInstance();
        cale.add(Calendar.MONTH, 1);
        cale.set(Calendar.DAY_OF_MONTH, 0);
        return format.format(cale.getTime());
	}

    /**
     * 获取两个日期相差的月数
     * @param d1  较大的日期
     * @param d2  较小的日期
     * @return 如果d1>d2返回 月数差 否则返回0
     */
    public static int getMonthDiff(Date d1, Date d2) {
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(d1);
        c2.setTime(d2);
        if (c1.getTimeInMillis() < c2.getTimeInMillis()) {
            return 0;
        }
        int year1 = c1.get(Calendar.YEAR);
        int year2 = c2.get(Calendar.YEAR);
        int month1 = c1.get(Calendar.MONTH);
        int month2 = c2.get(Calendar.MONTH);
        int day1 = c1.get(Calendar.DAY_OF_MONTH);
        int day2 = c2.get(Calendar.DAY_OF_MONTH);
        // 获取年的差值 假设 d1 = 2015-8-16 d2 = 2011-9-30
        int yearInterval = year1 - year2;
        // 如果 d1的 月-日 小于 d2的 月-日 那么 yearInterval-- 这样就得到了相差的年数
        if (month1 < month2 || month1 == month2 && day1 < day2) {
            yearInterval--;
        }
        // 获取月数差值
        int monthInterval = (month1 + 12) - month2;
        if (day1 < day2) {
            monthInterval--;
        }
        monthInterval %= 12;
        return yearInterval * 12 + monthInterval;
    }
    
	//T代表后面跟着时间，Z代表UTC统一时间
	public static Date dateToISODate(String dateStr){
		try {
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATETIME_PATTERN);
		    Date date =simpleDateFormat.parse(dateStr);
		    SimpleDateFormat format =new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
		    format.setCalendar(new GregorianCalendar(new SimpleTimeZone(0, "GMT")));
		    String isoDate = format.format(date);
	        return format.parse(isoDate);
	    } catch (Exception e) {
	    }
	    return null;
	}
    
}
