package core.util;

import java.sql.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

/**
 * TestDateUtil
 *
 */
public class TestDateUtil {

	/**
	 * 絶対日変換０基準
	 */
	@Test
	@DisplayName("絶対日変換０基準")
	public void toAbsoluteTest1() {
		final String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
		Assertions.assertEquals(date, DateUtil.toAbsolute("本日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("当日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("今日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("今週"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("今月"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("今年"));
	}

	/**
	 * 絶対日変換プラス１プラス２基準
	 */
	@Test
	@DisplayName("絶対日変換プラス１プラス２基準")
	public void toAbsoluteTest2() {
		final Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, 1);
		String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("翌日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("後日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("明日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("次日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("来日"));

		cal.add(Calendar.DATE, 1);
		date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("翌々日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("明後日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("二日後"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("２日後"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("2日後"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("再来日"));
	}

	/**
	 * 絶対日変換マイナス１マイナス２変換
	 */
	@Test
	@DisplayName("絶対日変換マイナス１マイナス２変換")
	public void toAbsoluteTest3() {
		final Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, -1);
		String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("先日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("前日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("昨日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("去日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("一日前"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("１日前"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("1日前"));

		cal.add(Calendar.DATE, -1);
		date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("二日前"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("２日前"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("2日前"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("一昨日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("１昨日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("1昨日"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("先々日"));
	}

	/**
	 * 絶対日変換週おわり
	 */
	@Test
	@DisplayName("絶対日変換週おわり")
	public void toAbsoluteTest4() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, 7 - cal.get(Calendar.DAY_OF_WEEK));
		String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("週末"));

		cal = Calendar.getInstance();
		cal.add(Calendar.WEEK_OF_MONTH, -1);
		cal.add(Calendar.DATE, 7 - cal.get(Calendar.DAY_OF_WEEK));
		date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("先週末"));

		cal.add(Calendar.WEEK_OF_MONTH, -2);
		date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("三週間前末"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("３週間前末"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("3週間前末"));
	}

	/**
	 * 絶対日変換月おわり
	 */
	@Test
	@DisplayName("絶対日変換月おわり")
	public void toAbsoluteTest5() {
		final Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DATE, 1);
		cal.add(Calendar.MONTH, -1);
		cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
		final String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("先月末"));

		Assertions.assertEquals(date, DateUtil.toAbsolute("先月終わり"));
	}

	/**
	 * 絶対日変換年おわり
	 */
	@Test
	@DisplayName("絶対日変換年おわり")
	public void toAbsoluteTest6() {
		final Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DATE, 1);
		cal.add(Calendar.YEAR, -1);
		cal.set(Calendar.MONTH, 12);
		cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
		String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("去年末"));

		cal.add(Calendar.YEAR, -1);
		date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("一昨年末"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("昨昨年末"));

		cal.add(Calendar.YEAR, 3);
		date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("来年末"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("翌年終"));
	}

	/**
	 * 絶対日変換週はじめ
	 */
	@Test
	@DisplayName("絶対日変換週はじめ")
	public void toAbsoluteTest7() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, -1 * (cal.get(Calendar.DAY_OF_WEEK) - 1));
		String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("週初め"));

		cal = Calendar.getInstance();
		cal.add(Calendar.WEEK_OF_MONTH, -1);
		cal.add(Calendar.DATE, -1 * (cal.get(Calendar.DAY_OF_WEEK) - 1));
		date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("先週初"));

		cal.add(Calendar.WEEK_OF_MONTH, -2);
		date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("三週間前始"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("３週間前始"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("3週間前始"));
	}

	/**
	 * 絶対日変換月はじめ
	 */
	@Test
	@DisplayName("絶対日変換月はじめ")
	public void toAbsoluteTest8() {
		final Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MONTH, -1);
		cal.set(Calendar.DATE, 1);
		final String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("先月初"));
	}

	/**
	 * 絶対日変換年はじめ
	 */
	@Test
	@DisplayName("絶対日変換年はじめ")
	public void toAbsoluteTest9() {
		final Calendar cal = Calendar.getInstance();
		cal.add(Calendar.YEAR, -1);
		cal.set(Calendar.MONTH, 1);
		cal.set(Calendar.DATE, 1);
		String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("去年始"));

		cal.add(Calendar.YEAR, -1);
		date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("一昨年始"));

		cal.add(Calendar.YEAR, -1);
		date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("去昨昨年初"));
	}

	/**
	 * 絶対日変換n日前
	 */
	@Test
	@DisplayName("絶対日変換n日前")
	public void toAbsoluteTest10() {
		final Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DATE, -3);
		final String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("三日前"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("３日前"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("3日前"));
	}

	/**
	 * 絶対日変換０基準クオータはじめ
	 */
	@Test
	@DisplayName("絶対日変換０基準クオータはじめ")
	public void toAbsoluteTest11() {
		final Calendar cal = Calendar.getInstance();
		final int month = cal.get(Calendar.MONTH);
		if (0 <= month && month <= 2) {
			cal.set(Calendar.MONTH, 0);
		} else if (3 <= month && month <= 5) {
			cal.set(Calendar.MONTH, 3);
		} else if (6 <= month && month <= 8) {
			cal.set(Calendar.MONTH, 6);
		} else {
			cal.set(Calendar.MONTH, 9);
		}
		cal.set(Calendar.DATE, 1);
		final String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("当Ｑ初"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("当ｑ初"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("当Q初"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("当q初"));
	}

	/**
	 * 絶対日変換０基準クオータおわり
	 */
	@Test
	@DisplayName("絶対日変換０基準クオータおわり")
	public void toAbsoluteTest12() {
		final Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DATE, 1);
		final int month = cal.get(Calendar.MONTH);
		if (0 <= month && month <= 2) {
			cal.set(Calendar.MONTH, 2);
		} else if (3 <= month && month <= 5) {
			cal.set(Calendar.MONTH, 5);
		} else if (6 <= month && month <= 8) {
			cal.set(Calendar.MONTH, 8);
		} else {
			cal.set(Calendar.MONTH, 11);
		}
		cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
		final String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("当Ｑ末"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("当ｑ末"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("当Q末"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("当q末"));
	}

	/**
	 * 絶対日変換四半期はじめ
	 */
	@Test
	@DisplayName("絶対日変換四半期はじめ")
	public void toAbsoluteTest13() {
		final Calendar cal = Calendar.getInstance();
		final int month = cal.get(Calendar.MONTH);
		if (3 <= month && month <= 8) {
			cal.set(Calendar.MONTH, 3);
		} else if (9 <= month && month <= 11) {
			cal.set(Calendar.MONTH, 9);
		} else if (month <= 2) {
			cal.set(Calendar.MONTH, 0);
			cal.add(Calendar.MONTH, -3);
		}
		cal.set(Calendar.DATE, 1);
		final String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("当期初"));
	}

	/**
	 * 絶対日変換四半期おわり
	 */
	@Test
	@DisplayName("絶対日変換四半期おわり")
	public void toAbsoluteTest14() {
		final Calendar cal = Calendar.getInstance();
		cal.set(Calendar.DATE, 1);
		final int month = cal.get(Calendar.MONTH);
		if (3 <= month && month <= 8) {
			cal.set(Calendar.MONTH, 8);
		} else if (9 <= month && month <= 11) {
			cal.set(Calendar.MONTH, 11);
			cal.add(Calendar.MONTH, 3);
		} else if (month <= 2) {
			cal.set(Calendar.MONTH, 2);
		}
		cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
		final String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("当期末"));
	}

	/**
	 * 絶対日変換クオータ前はじめ
	 */
	@Test
	@DisplayName("絶対日変換クオータ前はじめ")
	public void toAbsoluteTest15() {
		final Calendar cal = Calendar.getInstance();
		cal.add(Calendar.MONTH, -9);
		final int month = cal.get(Calendar.MONTH);
		if (0 <= month && month <= 2) {
			cal.set(Calendar.MONTH, 0);
		} else if (3 <= month && month <= 5) {
			cal.set(Calendar.MONTH, 3);
		} else if (6 <= month && month <= 8) {
			cal.set(Calendar.MONTH, 6);
		} else {
			cal.set(Calendar.MONTH, 9);
		}
		cal.set(Calendar.DATE, 1);
		final String date = new SimpleDateFormat("yyyyMMdd").format(cal.getTime());
		Assertions.assertEquals(date, DateUtil.toAbsolute("３Ｑ前初"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("３ｑ前初"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("3Q前初"));
		Assertions.assertEquals(date, DateUtil.toAbsolute("3q前初"));
	}

	/**
	 * 絶対日変換変換不可全角文字
	 */
	@Test
	@DisplayName("絶対日変換変換不可全角文字")
	public void toAbsoluteTest16() {
		Assertions.assertEquals(
				new SimpleDateFormat("yyyyMMdd").format(new Date()), DateUtil.toAbsolute("あ"));
	}

	/**
	 * 絶対日変換変換不可文字
	 */
	@Test
	@DisplayName("絶対日変換変換不可文字")
	public void parseDateTest1() {
		Assertions.assertNull(DateUtil.parseDate("20101233", "yyyyMMdd"));
		Assertions.assertNull(DateUtil.parseDate("201a1233", "yyyyMMdd"));
	}

	/**
	 * 絶対日変換入力絶対日の場合
	 */
	@Test
	@DisplayName("絶対日変換入力絶対日の場合")
	public void normalizeDateTest1() {
		Assertions.assertEquals("20100102", DateUtil.normalizeDate("201012"));
		Assertions.assertEquals("20100131", DateUtil.normalizeDate("2010131"));
		Assertions.assertEquals("20101203", DateUtil.normalizeDate("2010123"));
		Assertions.assertEquals("20100123", DateUtil.normalizeDate("20101/23"));
		Assertions.assertEquals("20101203", DateUtil.normalizeDate("201012/3"));
		Assertions.assertEquals("20101203", DateUtil.normalizeDate("20101/2/3"));
		Assertions.assertEquals("2010/11/", DateUtil.normalizeDate("2010/11/"));
		Assertions.assertEquals("20100101", DateUtil.normalizeDate("2010/1/1"));
	}

	/**
	 * 日付オブジェクト変換
	 */
	@Test
	@DisplayName("日付オブジェクト変換")
	public void toDateObjectTest1() {
		final Date date = new Date();
		final Time time = DateUtil.toTime(date);
		final java.sql.Date day = DateUtil.toDate(date);
		Assertions.assertEquals(
				date,
				DateUtil.toDateObject(DateUtil.format(date, DateUtil.FORMAT_DATE_TIME),
				Timestamp.class));
		Assertions.assertEquals(
				date,
				DateUtil.toDateObject(DateUtil.format(date, DateUtil.FORMAT_DATE_TIME),
				Date.class));
		Assertions.assertEquals(
				day,
				DateUtil.toDateObject(DateUtil.format(day, DateUtil.FORMAT_DATE),
				java.sql.Date.class));
		Assertions.assertEquals(
				time,
				DateUtil.toDateObject(DateUtil.format(time, "HHmmssSSS"),
				Time.class));
	}

	/**
	 * セパレータ削除
	 */
	@Test
	@DisplayName("セパレータ削除")
	public void removeSeparatorTest1() {
		Assertions.assertEquals("123", DateUtil.removeSeparator("1.2+3"));
	}
}
