package com.cku.oa.sys.util;

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.Date;
import java.util.Locale;
import java.util.TimeZone;

import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.Months;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.util.StringUtils;

import com.cku.core.ZAErrorCode;
import com.cku.core.ZAException;

public class LocalDateUtils {

	public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

	public static final SimpleDateFormat sdf_hms = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	public static final java.time.format.DateTimeFormatter formatter_ymd = java.time.format.DateTimeFormatter
			.ofPattern("yyyy-MM-dd");

	public static final java.time.format.DateTimeFormatter formatter_ym_short = java.time.format.DateTimeFormatter
			.ofPattern("yyyyMM");

	public static final java.time.format.DateTimeFormatter formatter_ymd_short = java.time.format.DateTimeFormatter
			.ofPattern("yyyyMMdd");

	public static final java.time.format.DateTimeFormatter formatter_ymd_hms = java.time.format.DateTimeFormatter
			.ofPattern("yyyy-MM-dd HH:mm:ss");

	public static final SimpleDateFormat formatter_ymd_t_hms_z = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'",
			Locale.CHINESE);


	/**
	 * 时间戳转localDateTime
	 * @author yuanshuai
	 * @since 2023/11/22 14:10
	 */
	public static LocalDateTime getDateTimeOfTimestamp(long timestamp) {
		Instant instant = Instant.ofEpochMilli(timestamp);
		ZoneId zone = ZoneId.systemDefault();
		return LocalDateTime.ofInstant(instant, zone);
	}

	/**
	 * java.util.Date --> java.time.LocalDateTime
	 */

	public static LocalDateTime dateToLocalDateTime(Date date) {
		Instant instant = date.toInstant();
		ZoneId zone = ZoneId.systemDefault();
		return LocalDateTime.ofInstant(instant, zone);
	}

	/**
	 * java.util.Date --> java.time.LocalDate
	 */

	public static LocalDate dateToLocalDate(Date date) {
		return dateToLocalDateTime(date).toLocalDate();
	}

	/**
	 * java.time.LocalDateTime --> java.util.Date
	 */

	public static Date LocalDateTimeToDate(LocalDateTime localDateTime) {
		ZoneId zone = ZoneId.systemDefault();
		Instant instant = localDateTime.atZone(zone).toInstant();
		return Date.from(instant);
	}

	/**
	 * java.time.LocalDate --> java.util.Date
	 */
	public static Date LocalDateToDate(LocalDate localDate) {
		ZoneId zone = ZoneId.systemDefault();
		Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
		return Date.from(instant);
	}

	/**
	 * 格式化localDate为yyyyMM
	 * 
	 * @param localDate
	 * @return
	 */
	public static String formatLocalDateYM(LocalDate localDate) {
		return formatter_ym_short.format(localDate);
	}

	/**
	 * 格式化localDate为yyyyMMdd
	 * 
	 * @param localDate
	 * @return
	 */
	public static String formatLocalDateShort(LocalDate localDate) {
		return formatter_ymd_short.format(localDate);

	}

	/**
	 * 格式化localDate为yyyy-MM-dd
	 * 
	 * @param localDate
	 * @return
	 */
	public static String formatLocalDate(LocalDate localDate) {
		return formatter_ymd.format(localDate);

	}

	/**
	 * 格式化localDate为yyyy-MM-dd HH:mm:ss
	 * 
	 * @param localDate
	 * @return
	 */
	public static String formatLocalDateTime(LocalDate localDate) {
		return formatter_ymd_hms.format(localDate);
	}

	/**
	 * 格式化localDate为yyyy-MM-dd HH:mm:ss
	 *
	 * @param localDateTime
	 * @return
	 */
	public static String formatLocalDateTime(LocalDateTime localDateTime) {
		return formatter_ymd_hms.format(localDateTime);
	}

	/**
	 * 格式化yyyy-MM-dd 字符串 为 localDate
	 * 
	 * @param dateStr
	 * @return
	 */
	public static LocalDate parsetLocalDate(String dateStr) {
		return LocalDate.parse(dateStr, formatter_ymd);
	}

	/**
	 * 格式化yyyyMMdd 字符串 为 localDate
	 * 
	 * @param dateStr
	 * @return
	 */
	public static LocalDate parsetLocalDateShort(String dateStr) {
		return LocalDate.parse(dateStr, formatter_ymd_short);
	}

	/**
	 * 格式化yyyy-MM-dd HH:mm:ss 字符串 为 localDateTime
	 * 
	 * @param dateStr
	 * @return
	 */
	public static LocalDateTime parseLocalDateTime(String dateStr) {
		return LocalDateTime.parse(dateStr, formatter_ymd_hms);
	}

	/**
	 * 格式化yyyy-MM-dd'T'HH:mm:ss'Z' 字符串 为 Date
	 * 
	 * @param dateStr
	 * @return
	 * @throws ParseException
	 */
	public static Date parse(String dateStr) throws ParseException {
		formatter_ymd_t_hms_z.setTimeZone(TimeZone.getTimeZone("ETC/GMT-8"));
		return formatter_ymd_t_hms_z.parse(dateStr);
	}

	/**
	 * 计算两个日期相差月份
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static int monthsBetween(LocalDate date1, LocalDate date2) {
		int months = 0;
		if (date1 == null || date2 == null) {
			throw new ZAException(ZAErrorCode.ZA_ERC_PARAM_ERROR, "日期格式错误");
		}
		try {
			DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
			DateTime start = formatter.parseDateTime(formatLocalDate(date1));
			DateTime end = formatter.parseDateTime(formatLocalDate(date2));
			months = Months.monthsBetween(start, end).getMonths();
		} catch (Exception e) {
			throw new ZAException(ZAErrorCode.ZA_ERC_PARAM_ERROR, "日期格式错误");
		}
		return months > 0 ? months : 0;
	}

	/**
	 * 计算两个日期相差天数
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static int daysBetween(LocalDate date1, LocalDate date2) {
		int days = 0;
		if (date1 == null || date2 == null) {
			throw new ZAException(ZAErrorCode.ZA_ERC_PARAM_ERROR, "日期格式错误");
		}
		try {
			DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
			DateTime start = formatter.parseDateTime(formatLocalDate(date1));
			DateTime end = formatter.parseDateTime(formatLocalDate(date2));
			days = Days.daysBetween(start, end).getDays();
		} catch (Exception e) {
			throw new ZAException(ZAErrorCode.ZA_ERC_PARAM_ERROR, "日期格式错误");
		}
		return days > 0 ? days : 0;
	}

	public static String getStringDateFormatter(Date date, String format) {
		SimpleDateFormat formatter = new SimpleDateFormat(format);
		return formatter.format(date);
	}

	/**
	 * 判断当前日期是否在某个日期之前
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static boolean isBeforeMounth(LocalDate date1, String dateStr, boolean isIncludeJudgmentDate) {
		if (date1 == null || StringUtils.isEmpty(dateStr)) {
			throw new ZAException(ZAErrorCode.ZA_ERC_PARAM_ERROR, "日期为空");
		}
		LocalDate date2 = null;
		try {
			date2 = parsetLocalDate(dateStr);
		} catch (Exception e) {
			throw new ZAException(ZAErrorCode.ZA_ERC_PARAM_ERROR, "日期有误");
		}
		return date1.isBefore(date2)
				|| (date1.toEpochDay() == date2.toEpochDay() && isIncludeJudgmentDate ? true : false);
	}

	/**
	 * 判断当前日期是否在某个日期之前
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static boolean isBeforeMounth(LocalDate date1, LocalDate date2, boolean isIncludeJudgmentDate) {
		if (date1 == null || date2 == null) {
			throw new ZAException(ZAErrorCode.ZA_ERC_PARAM_ERROR, "日期为空");
		}
		return date1.isBefore(date2)
				|| (isIncludeJudgmentDate && date1.toEpochDay() == date2.toEpochDay() ? true : false);
	}

	/**
	 * 判断当前日期是否在某个日期之前
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static boolean isAfterMounth(LocalDate date1, String dateStr, boolean isIncludeJudgmentDate) {
		if (date1 == null || StringUtils.isEmpty(dateStr)) {
			throw new ZAException(ZAErrorCode.ZA_ERC_PARAM_ERROR, "日期为空");
		}
		LocalDate date2 = null;
		try {
			date2 = parsetLocalDate(dateStr);
		} catch (Exception e) {
			throw new ZAException(ZAErrorCode.ZA_ERC_PARAM_ERROR, "日期有误");
		}
		return date1.isAfter(date2) || isIncludeJudgmentDate && date1.toEpochDay() == date2.toEpochDay() ? true : false;
	}

	/**
	 * 判断当前日期是否在某个日期之前
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 */
	public static boolean isAfterMounth(LocalDate date1, LocalDate date2, boolean isIncludeJudgmentDate) {
		if (date1 == null || date2 == null) {
			throw new ZAException(ZAErrorCode.ZA_ERC_PARAM_ERROR, "日期为空");
		}
		return date1.isAfter(date2)
				|| (isIncludeJudgmentDate && date1.toEpochDay() == date2.toEpochDay() ? true : false);
	}

}
