DateUtils

/*
 * @(#)DateUtils.java 2020年4月5日上午9:40:16
 * Copyright All rights reserved.
 */
package com.zhuning.isim.util;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

import com.zhuning.isim.excp.InvalidDataException;

/**
 * 日期工具类
 * @author: wangyf
 * @version: 1.0 Date: 2020年4月5日 上午9:40:16
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

	private static String[] parsePatterns = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM" };

	public final static String[] WEEKS = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

	public final static String PATTERN_HOUR_MINUTES = "HH:mm";

	/**
	 * 获取指定的年份,格式为yyyy
	 * @param amount -1:昨天, 0:今天 ,1:明天
	 * @return
	 */
	public static String getYear(int amount) {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.YEAR, amount);
		return String.format("%tY", calendar.getTime());
	}

	/**
	 * 获取指定的年月,格式为yyyy-MM
	 * @param amount -1:昨天, 0:今天 ,1:明天
	 * @return
	 */
	public static String getYearMonth(int amount) {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MONTH, amount);
		return String.format("%tY-%<tm", calendar.getTime());
	}

	/**
	 * 获取指定的日期,格式为yyyy-MM-dd
	 * @param amount -1:昨天, 0:今天 ,1:明天
	 * @return
	 */
	public static String getDate(int amount) {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DATE, amount);
		return String.format("%tY-%<tm-%<td", calendar.getTime());
	}

	/**
	 * 获取指定日期
	 * @param amount
	 * @return
	 */
	public static Date getCustDate(int amount) {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DATE, amount);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 获取指定月份
	 *
	 * @param amount
	 * @return
	 */
	public static Date getCustMonthDate(int amount) {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MONTH, amount);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 获取指定的日期,格式为yyyy-MM-dd HH:mm:ss
	 *
	 * @param amount -1:昨天, 0:今天 ,1:明天
	 * @return
	 */
	public static String getDateTime(int amount) {
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DATE, amount);
		return String.format("%tF %<tT", calendar.getTime());
	}

	/*
	 * 获取当前日期时间戳
	 */
	public static long getCurrentDateMillis() {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTimeInMillis();
	}

	/*
	 * 获取当前日期
	 */
	public static Date getCurrentDate() {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	public static Date dateToDate(Date date) {
		return dateToDate(date, parsePatterns[0]);
	}

	public static String date2Date(Date date) {
		return dateToStr(date, "yyyyMMdd");
	}

	public static Date dateToDate(Date date, String format) {
		String str = dateToStr(date, format);
		return strToDate(str, format);
	}

	/**
	 * 字符串转化为日期
	 *
	 * @param dateStr
	 * @param pattern
	 * @return
	 */
	public static Date strToDate(String dateStr, String pattern) {
		if (StringUtils.isEmpty(dateStr)) {
			return null;
		}
		SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
		try {
			return dateFormat.parse(dateStr);
		} catch (ParseException e) {
			e.printStackTrace();
			throw new InvalidDataException(e.getMessage());
		}
	}

	/**
	 * 字符转换为指定日期格式的字符
	 *
	 * @param dateStr
	 * @param format
	 * @return
	 */
	public static String strToDateStr(String dateStr, String format) {
		String strDate = "";
		if (!StringUtils.isEmpty(dateStr)) {
			Date date = strToDateAll(dateStr);
			strDate = dateToStr(date, format);
		}
		return strDate;
	}

	/**
	 * 日期转换为字符串
	 *
	 * @param format
	 * @return
	 */
	public static String dateToStr(String format) {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(System.currentTimeMillis());
	}

	/**
	 * 日期转换为字符串
	 *
	 * @param format
	 * @return
	 */
	public static String dateToStr(Date date) {
		if (null == date) {
			return "";
		}
		SimpleDateFormat sdf = new SimpleDateFormat(parsePatterns[0]);
		return sdf.format(date);
	}

	/**
	 * 日期转换为字符串
	 *
	 * @param date
	 * @param format
	 * @return
	 */
	public static String dateToStr(Date date, String format) {
		if (null == date) {
			return "";
		}
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(date);
	}

	/**
	 * 日期转字符串
	 *
	 * @param date
	 * @return
	 */
	public static String dateTimeToStr(Date date) {
		if (null == date) {
			return "";
		}
		return dateToStr(date, "yyyy-MM-dd HH:mm:ss");
	}

	/**
	 * 格式化为中文日期格式
	 *
	 * @param date
	 * @return
	 */
	public static String formatChineseDate(Date date) {
		if (null == date) {
			return StringUtils.EMPTY;
		}
		return dateToStr(date, "yyyy年MM月dd日HH时mm分");
	}

	/**
	 * 日期转字符串
	 *
	 * @param date
	 * @return
	 */
	public static String toDateHourMinute(Date date) {
		if (null == date) {
			return "";
		}
		return dateToStr(date, parsePatterns[2]);
	}

	/**
	 * 日期转字符串-yyyy-MM-dd HH:mm
	 *
	 * @param date
	 * @return
	 */
	public static String toHourMinute(Date date) {
		if (null == date) {
			return "";
		}
		return dateToStr(date, PATTERN_HOUR_MINUTES);
	}

	/**
	 * 得到时间字符串-HH:mm
	 *
	 * @param dateStr
	 * @return
	 */
	public static String toHourMinute(String dateStr) {
		int len = StringUtils.isEmpty(dateStr) ? 0 : dateStr.trim().length();
		if (len >= 16) {
			return dateStr.substring(11, 16);
		} else if (len == 13) {
			return dateStr.substring(11) + ":00";
		} else {
			return "00:00";
		}
	}

	/**
	 * 字符转日期
	 *
	 * @param dateStr
	 * @return
	 */
	public static Date strToDateTime(String dateStr) {
		if (StringUtils.isEmpty(dateStr)) {
			return null;
		}
		return strToDate(dateStr, "yyyy-MM-dd HH:mm:ss");
	}

	/**
	 * 字符转日期
	 *
	 * @param dateStr
	 * @return
	 */
	public static Date strToDateTime(Object dateStr) {
		if (null == dateStr || StringUtils.isEmpty(dateStr.toString())) {
			return null;
		}
		return strToDate(dateStr.toString(), "yyyy-MM-dd HH:mm:ss");
	}

	/**
	 * 字符转日期
	 *
	 * @param dateStr
	 * @return
	 */
	public static Date strToDateHour(String dateStr) {
		if (StringUtils.isEmpty(dateStr)) {
			return null;
		}
		return strToDate(dateStr, "yyyy-MM-dd HH:mm");
	}

	/**
	 * 字符转日期
	 * @param dateStr
	 * @return
	 */
	public static Date strToDate(String dateStr) {
		if (StringUtils.isEmpty(dateStr)) {
			return null;
		}
		String pattern = dateStr.indexOf("-") != -1 ? parsePatterns[0] : parsePatterns[4];
		return strToDate(dateStr, pattern);
	}

	/**
	 * 字符转日期
	 * @param dateStr
	 * @return
	 */
	public static Date strToHourMinute(String dateStr) {
		if (StringUtils.isEmpty(dateStr)) {
			return null;
		}
		return strToDate(dateStr, PATTERN_HOUR_MINUTES);
	}

	/**
	 * 字符转日期
	 *
	 * @param dateStr
	 * @return
	 */
	public static Date strToDateAll(String dateStr) {
		if (StringUtils.isEmpty(dateStr)) {
			return null;
		}
		int len = dateStr.length();
		SimpleDateFormat dateFormat = null;
		if (len == 8) {
			dateFormat = new SimpleDateFormat("yyyyMMdd");
		} else if (len == 10) {
			dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		} else if (len == 14) {
			dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		} else if (len == 16) {
			dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		} else if (len == 19) {
			dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		} else if (dateStr.contains("CST")) {
			dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss 'CST' yyyy", Locale.ENGLISH);// CST格式
		} else if (dateStr.contains("UTC")) {
			dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss 'UTC 0800' yyyy", Locale.ENGLISH);// UTC格式
		} else {
			return null;
		}
		try {
			return dateFormat.parse(dateStr);
		} catch (ParseException e) {
			e.printStackTrace();
			throw new InvalidDataException(e.getMessage());
		}
	}

	public static Date parseDate(String str) {
		if (str == null) {
			return null;
		}
		try {
			return parseDate(str, parsePatterns);
		} catch (ParseException e) {
			throw new InvalidDataException(e.getMessage());
		}
	}

	/**
	 * 获取过去的分钟
	 *
	 * @param date
	 * @return
	 */
	public static long pastMinutes(Date date) {
		long time = System.currentTimeMillis() - date.getTime();
		return time / (60 * 1000);
	}

	/**
	 * 计算相差天数(包括当天)
	 *
	 * @param startDate
	 * @param endDate
	 */
	public static int calcDiffDays(String startDate, String endDate) {
		SimpleDateFormat sf = new SimpleDateFormat(parsePatterns[0]);
		double nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
		try {
			double diff = sf.parse(startDate).getTime() - sf.parse(endDate).getTime();
			return new BigDecimal(new Double(diff / nd) + 1).setScale(0, BigDecimal.ROUND_UP).intValue();
		} catch (ParseException e) {
			throw new InvalidDataException("计算相差天数出错:" + e.getMessage());
		}
	}

	/**
	 * 计算相差天数(包括当天)
	 *
	 * @param startDate
	 * @param endDate
	 */
	public static int calcDiffDays(Date startDate, Date endDate) {
		double nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
		double diff = endDate.getTime() - startDate.getTime();
		return new BigDecimal(new Double(diff / nd) + 1).setScale(0, BigDecimal.ROUND_UP).intValue();
	}

	public static Date add(Date date, int calendarField, int amount) {
		if (date == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(calendarField, amount);
		return c.getTime();
	}

	public static Date addDays(Date date, int days) {
		if (days == 0) {
			return date;
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, days);
		return calendar.getTime();
	}

	public static Date addMinutes(int minutes, Date dt) {
		Calendar c = Calendar.getInstance();
		c.setTime(dt);
		c.add(Calendar.MINUTE, minutes);
		return c.getTime();
	}

	/**
	 * 获取当前日期是星期几
	 *
	 * @param date
	 * @return 当前日期是星期几
	 */
	public static String getWeekOfDate(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
		if (w < 0) {
			w = 0;
		}
		return WEEKS[w];
	}

	/**
	 * 得到本月第一天的日期
	 *
	 * @param date
	 * @return
	 */
	public static Date getFirstDayOfMonth(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		return calendar.getTime();
	}

	/**
	 * 得到本月最后一天的日期
	 *
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfMonth(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		return calendar.getTime();
	}

	/**
	 * 获取某年第一天日期
	 *
	 * @param year 年份
	 * @return Date
	 */
	public static Date getCurrYearFirst(int year) {
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR, year);
		return calendar.getTime();
	}

	/**
	 * 获取某年最后一天日期
	 *
	 * @param year 年份
	 * @return Date
	 */
	public static Date getCurrYearLast(int year) {
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR, year);
		calendar.roll(Calendar.DAY_OF_YEAR, -1);
		return calendar.getTime();
	}

	/**
	 * 获取某年某月一共多少天
	 */
	public static int getSomeMonthOwnDayCount(int year, int month) {
		Calendar c = Calendar.getInstance();
		// 输入类型为int类型
		c.set(year, month, 0);
		return c.get(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 获取某年某月最后一天
	 */
	public static Date getSomeMonthLastDay(int year, int month) {
		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, month - 1);
		cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DATE));
		return cal.getTime();
	}

	// 获得本周一与当前日期相差的天数
	public static int getMondayPlus() {
		Calendar cd = Calendar.getInstance();
		int dayOfWeek = cd.get(Calendar.DAY_OF_WEEK);
		if (dayOfWeek == 1) {
			return -6;
		} else {
			return 2 - dayOfWeek;
		}
	}

	// 获得当前周周一的日期
	public static Date getCurrentMonday() {
		int mondayPlus = getMondayPlus();
		GregorianCalendar currentDate = new GregorianCalendar();
		currentDate.add(GregorianCalendar.DATE, mondayPlus);
		currentDate.set(Calendar.HOUR, 0);
		currentDate.set(Calendar.MINUTE, 0);
		currentDate.set(Calendar.SECOND, 0);
		currentDate.set(Calendar.MILLISECOND, 0);
		return currentDate.getTime();
	}

	// 获得当前周周日的日期
	public static Date getCurrentSunday() {
		int mondayPlus = getMondayPlus();
		GregorianCalendar currentDate = new GregorianCalendar();
		currentDate.add(GregorianCalendar.DATE, mondayPlus + 6);
		currentDate.set(Calendar.HOUR, 0);
		currentDate.set(Calendar.MINUTE, 0);
		currentDate.set(Calendar.SECOND, 0);
		currentDate.set(Calendar.MILLISECOND, 0);
		return currentDate.getTime();
	}

	public static Date asDate(LocalDate localDate) {
		return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
	}

	public static Date asDate(LocalDateTime localDateTime) {
		return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
	}

	public static LocalDate asLocalDate(Date date) {
		return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
	}

	public static LocalDateTime asLocalDateTime(Date date) {
		return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
	}

	/**
	 * 根据 某年第几天时间
	 * @param count
	 * @param year
	 * @return
	 */
	public static Date getSomeYearTimeByCount(int count, int year) {
		Calendar cal = Calendar.getInstance();
		int nowYear = cal.get(Calendar.YEAR);
		Calendar c = Calendar.getInstance();
		c.add(Calendar.YEAR, year - nowYear);
		c.set(Calendar.DAY_OF_YEAR, count);
		return c.getTime();
	}

	/**
	 * 根据 某年某周的开始时间
	 * @param count
	 * @param year
	 * @return
	 */
	public static Date getSomeWeekStartTimeByCount(int count, int year) {
		Calendar cal = Calendar.getInstance();
		cal.set(year, 0, 1);
		int dayOfWeek = 7 - cal.get(Calendar.DAY_OF_WEEK) + 1;
		count = count - 2;
		cal.add(Calendar.DAY_OF_WEEK, count * 7 + dayOfWeek);
		return cal.getTime();
	}

	/**
	 * 根据 某年某周的结束时间
	 * @param count
	 * @param year
	 * @return
	 */
	public static Date getSomeWeekEndTimeByCount(int count, int year) {
		Calendar cal = Calendar.getInstance();
		cal.set(year, 0, 1);
		int dayOfWeek = 7 - cal.get(Calendar.DAY_OF_WEEK) + 1;
		count = count - 2;
		cal.add(Calendar.DAY_OF_WEEK, count * 7 + dayOfWeek);
		cal.add(Calendar.DAY_OF_YEAR, 6);
		return cal.getTime();
	}

}