package com.allynav.iefa.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.util.Log;
public class SolarTermsUtil {
private Calendar solar;
private int lunarYear;
private int lunarMonth;
private int lunarDay;
private boolean isLeap;
private boolean isLeapYear;
private int solarYear;
private int solarMonth;
private int solarDay;
private int cyclicalYear = 0;
private int cyclicalMonth = 0;
private int cyclicalDay = 0;
private int maxDayInMonth = 29;
private boolean isFinded = false;
private boolean isSFestival = false;
private boolean isLFestival = false;
private String sFestivalName = "";
private String lFestivalName = "";
private String description = "";
private boolean isHoliday = false;
private final static int[] lunarInfo = {0x4bd8, 0x4ae0, 0xa570, 0x54d5, 0xd260, 0xd950, 0x5554, 0x56af, 0x9ad0, 0x55d2, 0x4ae0, 0xa5b6, 0xa4d0, 0xd250, 0xd295, 0xb54f, 0xd6a0, 0xada2, 0x95b0, 0x4977, 0x497f, 0xa4b0, 0xb4b5, 0x6a50, 0x6d40, 0xab54, 0x2b6f, 0x9570, 0x52f2, 0x4970, 0x6566, 0xd4a0, 0xea50, 0x6a95,
0x5adf, 0x2b60, 0x86e3, 0x92ef, 0xc8d7, 0xc95f, 0xd4a0, 0xd8a6, 0xb55f, 0x56a0, 0xa5b4, 0x25df, 0x92d0, 0xd2b2, 0xa950, 0xb557, 0x6ca0, 0xb550, 0x5355, 0x4daf, 0xa5b0, 0x4573, 0x52bf, 0xa9a8, 0xe950, 0x6aa0, 0xaea6, 0xab50, 0x4b60, 0xaae4, 0xa570, 0x5260, 0xf263, 0xd950, 0x5b57, 0x56a0, 0x96d0, 0x4dd5,
0x4ad0, 0xa4d0, 0xd4d4, 0xd250, 0xd558, 0xb540, 0xb6a0, 0x95a6, 0x95bf, 0x49b0, 0xa974, 0xa4b0, 0xb27a, 0x6a50, 0x6d40, 0xaf46, 0xab60, 0x9570, 0x4af5, 0x4970, 0x64b0, 0x74a3, 0xea50, 0x6b58, 0x5ac0, 0xab60, 0x96d5, 0x92e0, 0xc960, 0xd954, 0xd4a0, 0xda50, 0x7552, 0x56a0, 0xabb7, 0x25d0, 0x92d0, 0xcab5,
0xa950, 0xb4a0, 0xbaa4, 0xad50, 0x55d9, 0x4ba0, 0xa5b0, 0x5176, 0x52bf, 0xa930, 0x7954, 0x6aa0, 0xad50, 0x5b52, 0x4b60, 0xa6e6, 0xa4e0, 0xd260, 0xea65, 0xd530, 0x5aa0, 0x76a3, 0x96d0, 0x4afb, 0x4ad0, 0xa4d0, 0xd0b6, 0xd25f, 0xd520, 0xdd45, 0xb5a0, 0x56d0, 0x55b2, 0x49b0, 0xa577, 0xa4b0, 0xaa50, 0xb255,
0x6d2f, 0xada0, 0x4b63, 0x937f, 0x49f8, 0x4970, 0x64b0, 0x68a6, 0xea5f, 0x6b20, 0xa6c4, 0xaaef, 0x92e0, 0xd2e3, 0xc960, 0xd557, 0xd4a0, 0xda50, 0x5d55, 0x56a0, 0xa6d0, 0x55d4, 0x52d0, 0xa9b8, 0xa950, 0xb4a0, 0xb6a6, 0xad50, 0x55a0, 0xaba4, 0xa5b0, 0x52b0, 0xb273, 0x6930, 0x7337, 0x6aa0, 0xad50, 0x4b55,
0x4b6f, 0xa570, 0x54e4, 0xd260, 0xe968, 0xd520, 0xdaa0, 0x6aa6, 0x56df, 0x4ae0, 0xa9d4, 0xa4d0, 0xd150, 0xf252, 0xd520};
private final static int[] solarTermInfo = {0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343, 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758};
public final static String[] Tianan = {"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};
public final static String[] Deqi = {"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};
public final static String[] Animals = {"鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"};
public final static String[] solarTerm = {"小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"};
public final static String[] lunarString1 = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
public final static String[] lunarString2 = {"初", "十", "廿", "卅", "正", "腊", "冬", "闰"};
public final static String[] weeks = {"星期六", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五"};
private final static String[] sFtv = {"0101 元旦", "0214 情人节", "0308 妇女节", "0312 植树节", "0401 愚人节", "0501 劳动节", "0504 青年节", "0601 儿童节", "0701 建党节", "0801 建军节", "0910 教师节", "1001 国庆节", "1225 圣诞节"};
private final static String[] lFtv = {"0101 春节", "0115 元宵节", "0505 端午节", "0707 七夕情人节", "0815 中秋节", "0909 重阳节", "1224 小年", "0100 除夕"};
private static String[] wFtv = {"0520 母亲节", "0716 合作节", "0730 被奴役国家周"};
private final static Pattern sFreg = Pattern.compile("^(\\d{2})(\\d{2})([\\s\\*])(.+)$");
private final static Pattern wFreg = Pattern.compile("^(\\d{2})(\\d)(\\d)([\\s\\*])(.+)$");
public static void main(String[] args) {
SolarTermsUtil l = new SolarTermsUtil(System.currentTimeMillis());
Log.e("128990", "Data" + l.getLunarDateString());
System.out.println("节气:" + l.getTermString());
System.out.println("干支历:" + l.getCyclicalDateString());
System.out.println("星期" + l.getDayOfWeek());
System.out.println("农历" + l.getLunarDateString());
Calendar t = Calendar.getInstance();
t.set(1985, 10, 17);
Date[] jieqi = jieqilist(1940);
for (int i = 0; i < solarTerm.length; i++) {
System.out.print(solarTerm[i]);
System.out.print(jieqi[i].getMonth() + "月");
System.out.println(jieqi[i].getDate());
}
}
public static List<Date> Alljieqi(int year) {
List<Date> jieqi = new ArrayList<Date>();
Date[] temp;
temp = jieqilist(year - 1);
jieqi.addAll(Arrays.asList(temp));
temp = jieqilist(year);
jieqi.addAll(Arrays.asList(temp));
temp = jieqilist(year + 1);
jieqi.addAll(Arrays.asList(temp));
return jieqi;
}
public static int[] getnearsolarTerm(int year, Date date) {
List<Date> jieqi = Alljieqi(year);
int[] returnValue = new int[2];
for (int i = 0; i < jieqi.size(); i++) {
if (date.getTime() > jieqi.get(i).getTime()) {
continue;
}
if ((i % 2) == 0) {
returnValue[0] = i - 2;
returnValue[1] = i;
} else {
returnValue[0] = i - 1;
returnValue[1] = i + 1;
}
break;
}
return returnValue;
}
public static Date[] jieqilist(int year) {
Date[] returnvalue = new Date[solarTerm.length];
for (int i = 0; i < solarTerm.length; i++) {
Date t = getSolarTermCalendar(year, i);
returnvalue[i] = t;
}
return returnvalue;
}
private static int toInt(String str) {
try {
return Integer.parseInt(str);
} catch (Exception e) {
return -1;
}
}
private synchronized void findFestival() {
int sM = this.getSolarMonth();
int sD = this.getSolarDay();
int lM = this.getLunarMonth();
int lD = this.getLunarDay();
int sy = this.getSolarYear();
Matcher m;
for (String element : SolarTermsUtil.sFtv) {
m = SolarTermsUtil.sFreg.matcher(element);
if (m.find()) {
if ((sM == SolarTermsUtil.toInt(m.group(1))) && (sD == SolarTermsUtil.toInt(m.group(2)))) {
this.isSFestival = true;
this.sFestivalName = m.group(4);
if ("*".equals(m.group(3))) {
this.isHoliday = true;
}
break;
}
}
}
for (String element : SolarTermsUtil.lFtv) {
m = SolarTermsUtil.sFreg.matcher(element);
if (m.find()) {
if ((lM == SolarTermsUtil.toInt(m.group(1))) && (lD == SolarTermsUtil.toInt(m.group(2)))) {
this.isLFestival = true;
this.lFestivalName = m.group(4);
if ("*".equals(m.group(3))) {
this.isHoliday = true;
}
break;
}
}
}
int w, d;
for (String element : SolarTermsUtil.wFtv) {
m = SolarTermsUtil.wFreg.matcher(element);
if (m.find()) {
if (this.getSolarMonth() == SolarTermsUtil.toInt(m.group(1))) {
w = SolarTermsUtil.toInt(m.group(2));
d = SolarTermsUtil.toInt(m.group(3));
if ((this.solar.get(Calendar.WEEK_OF_MONTH) == w) && (this.solar.get(Calendar.DAY_OF_WEEK) == d)) {
this.isSFestival = true;
this.sFestivalName += "|" + m.group(5);
if ("*".equals(m.group(4))) {
this.isHoliday = true;
}
}
}
}
}
if ((sy > 1874) && (sy < 1909)) {
this.description = "光绪" + (((sy - 1874) == 1) ? "元" : "" + (sy - 1874));
}
if ((sy > 1908) && (sy < 1912)) {
this.description = "宣统" + (((sy - 1908) == 1) ? "元" : String.valueOf(sy - 1908));
}
if ((sy > 1911) && (sy < 1950)) {
this.description = "民国" + (((sy - 1911) == 1) ? "元" : String.valueOf(sy - 1911));
}
if (sy > 1949) {
this.description = "共和国" + (((sy - 1949) == 1) ? "元" : String.valueOf(sy - 1949));
}
this.description += "年";
this.sFestivalName = this.sFestivalName.replaceFirst("^\\|", "");
this.isFinded = true;
}
private static int getLunarLeapMonth(int lunarYear) {
int leapMonth = SolarTermsUtil.lunarInfo[lunarYear - 1900] & 0xf;
leapMonth = (leapMonth == 0xf ? 0 : leapMonth);
return leapMonth;
}
private static int getLunarLeapDays(int lunarYear) {
return SolarTermsUtil.getLunarLeapMonth(lunarYear) > 0 ? ((SolarTermsUtil.lunarInfo[lunarYear - 1899] & 0xf) == 0xf ? 30 : 29) : 0;
}
private static int getLunarYearDays(int lunarYear) {
int daysInLunarYear = 348;
for (int i = 0x8000; i > 0x8; i >>= 1) {
daysInLunarYear += ((SolarTermsUtil.lunarInfo[lunarYear - 1900] & i) != 0) ? 1 : 0;
}
daysInLunarYear += SolarTermsUtil.getLunarLeapDays(lunarYear);
return daysInLunarYear;
}
private static int getLunarMonthDays(int lunarYear, int lunarMonth) {
int daysInLunarMonth = ((SolarTermsUtil.lunarInfo[lunarYear - 1900] & (0x10000 >> lunarMonth)) != 0) ? 30 : 29;
return daysInLunarMonth;
}
public static synchronized int getUTCDay(Date date) {
SolarTermsUtil.makeUTCCalendar();
synchronized (utcCal) {
utcCal.clear();
utcCal.setTimeInMillis(date.getTime());
return utcCal.get(Calendar.DAY_OF_MONTH);
}
}
private static GregorianCalendar utcCal = null;
private static synchronized void makeUTCCalendar() {
if (SolarTermsUtil.utcCal == null) {
SolarTermsUtil.utcCal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
}
}
public static synchronized long UTC(int y, int m, int d, int h, int min, int sec) {
SolarTermsUtil.makeUTCCalendar();
synchronized (utcCal) {
utcCal.clear();
utcCal.set(y, m, d, h, min, sec);
return utcCal.getTimeInMillis();
}
}
private static int getSolarTermDay(int solarYear, int index) {
return SolarTermsUtil.getUTCDay(getSolarTermCalendar(solarYear, index));
}
public static Date getSolarTermCalendar(int solarYear, int index) {
long l = ((long) 31556925974.7 * (solarYear - 1900)) + (solarTermInfo[index] * 60000L);
l = l + SolarTermsUtil.UTC(1900, 0, 6, 2, 5, 0);
return new Date(l);
}
public SolarTermsUtil(Date date) {
if (date == null) {
date = new Date();
}
this.init(date.getTime());
}
public SolarTermsUtil() {
this.init(System.currentTimeMillis());
}
public SolarTermsUtil(long TimeInMillis) {
this.init(TimeInMillis);
}
private void init(long TimeInMillis) {
this.solar = Calendar.getInstance();
this.solar.setTimeInMillis(TimeInMillis);
Calendar baseDate = new GregorianCalendar(1900, 0, 31);
long offset = (TimeInMillis - baseDate.getTimeInMillis()) / 86400000;
this.lunarYear = 1900;
int daysInLunarYear = SolarTermsUtil.getLunarYearDays(this.lunarYear);
while ((this.lunarYear < 2100) && (offset >= daysInLunarYear)) {
offset -= daysInLunarYear;
daysInLunarYear = SolarTermsUtil.getLunarYearDays(++this.lunarYear);
}
int lunarMonth = 1;
int leapMonth = SolarTermsUtil.getLunarLeapMonth(this.lunarYear);
this.isLeapYear = leapMonth > 0;
boolean leapDec = false;
boolean isLeap = false;
int daysInLunarMonth = 0;
while ((lunarMonth < 13) && (offset > 0)) {
if (isLeap && leapDec) {
daysInLunarMonth = SolarTermsUtil.getLunarLeapDays(this.lunarYear);
leapDec = false;
} else {
daysInLunarMonth = SolarTermsUtil.getLunarMonthDays(this.lunarYear, lunarMonth);
}
if (offset < daysInLunarMonth) {
break;
}
offset -= daysInLunarMonth;
if ((leapMonth == lunarMonth) && (isLeap == false)) {
leapDec = true;
isLeap = true;
} else {
lunarMonth++;
}
}
this.maxDayInMonth = daysInLunarMonth;
this.lunarMonth = lunarMonth;
this.isLeap = ((lunarMonth == leapMonth) && isLeap);
this.lunarDay = (int) offset + 1;
this.getCyclicalData();
}
private void getCyclicalData() {
this.solarYear = this.solar.get(Calendar.YEAR);
this.solarMonth = this.solar.get(Calendar.MONTH);
this.solarDay = this.solar.get(Calendar.DAY_OF_MONTH);
int cyclicalYear = 0;
int cyclicalMonth = 0;
int cyclicalDay = 0;
int term2 = SolarTermsUtil.getSolarTermDay(solarYear, 2);
if ((solarMonth < 1) || ((solarMonth == 1) && (solarDay < term2))) {
cyclicalYear = (((solarYear - 1900) + 36) - 1) % 60;
} else {
cyclicalYear = ((solarYear - 1900) + 36) % 60;
}
int firstNode = SolarTermsUtil.getSolarTermDay(solarYear, solarMonth * 2);
if (solarDay < firstNode) {
cyclicalMonth = (((solarYear - 1900) * 12) + solarMonth + 12) % 60;
} else {
cyclicalMonth = (((solarYear - 1900) * 12) + solarMonth + 13) % 60;
}
cyclicalDay = (int) ((SolarTermsUtil.UTC(solarYear, solarMonth, solarDay, 0, 0, 0) / 86400000) + 25567 + 10) % 60;
this.cyclicalYear = cyclicalYear;
this.cyclicalMonth = cyclicalMonth;
this.cyclicalDay = cyclicalDay;
}
public String getAnimalString() {
return SolarTermsUtil.Animals[(this.lunarYear - 4) % 12];
}
public String getTermString() {
String termString = "";
if (SolarTermsUtil.getSolarTermDay(solarYear, solarMonth * 2) == solarDay) {
termString = SolarTermsUtil.solarTerm[solarMonth * 2];
} else if (SolarTermsUtil.getSolarTermDay(solarYear, (solarMonth * 2) + 1) == solarDay) {
termString = SolarTermsUtil.solarTerm[(solarMonth * 2) + 1];
}
return termString;
}
public String getCyclicalDateString() {
return this.getCyclicaYear() + "年" + this.getCyclicaMonth() + "月" + this.getCyclicaDay() + "日";
}
public int getTiananY() {
return SolarTermsUtil.getTianan(this.cyclicalYear);
}
public int getTiananM() {
return SolarTermsUtil.getTianan(this.cyclicalMonth);
}
public int getTiananD() {
return SolarTermsUtil.getTianan(this.cyclicalDay);
}
public int getDeqiY() {
return SolarTermsUtil.getDeqi(this.cyclicalYear);
}
public int getDeqiM() {
return SolarTermsUtil.getDeqi(this.cyclicalMonth);
}
public int getDeqiD() {
return SolarTermsUtil.getDeqi(this.cyclicalDay);
}
public String getCyclicaYear() {
return SolarTermsUtil.getCyclicalString(this.cyclicalYear);
}
public String getCyclicaMonth() {
return SolarTermsUtil.getCyclicalString(this.cyclicalMonth);
}
public String getCyclicaDay() {
return SolarTermsUtil.getCyclicalString(this.cyclicalDay);
}
public String getLunarDayString() {
return SolarTermsUtil.getLunarDayString(this.lunarDay);
}
public String getLunarMonthString() {
return (this.isLeap() ? "闰" : "") + SolarTermsUtil.getLunarMonthString(this.lunarMonth);
}
public String getLunarYearString() {
return SolarTermsUtil.getLunarYearString(this.lunarYear);
}
public String getLunarDateString() {
return this.getLunarYearString() + "年" + this.getLunarMonthString() + "月" + this.getLunarDayString() + "日";
}
public String getLunarMonthDateString() {
return this.getLunarMonthString() + "月" + this.getLunarDayString() + "日";
}
public boolean isLeap() {
return isLeap;
}
public boolean isLeapYear() {
return isLeapYear;
}
public boolean isBigMonth() {
return this.getMaxDayInMonth() > 29;
}
public int getMaxDayInMonth() {
return this.maxDayInMonth;
}
public int getLunarDay() {
return lunarDay;
}
public int getLunarMonth() {
return lunarMonth;
}
public int getLunarYear() {
return lunarYear;
}
public int getSolarDay() {
return solarDay;
}
public int getSolarMonth() {
return solarMonth + 1;
}
public int getSolarYear() {
return solarYear;
}
public int getDayOfWeek() {
return this.solar.get(Calendar.DAY_OF_WEEK);
}
public String getDayOfWeekString() {
return weeks[this.solar.get(Calendar.DAY_OF_WEEK)];
}
public boolean isBlackFriday() {
return ((this.getSolarDay() == 13) && (this.solar.get(Calendar.DAY_OF_WEEK) == 6));
}
public boolean isToday() {
Calendar clr = Calendar.getInstance();
return (clr.get(Calendar.YEAR) == this.solarYear) && (clr.get(Calendar.MONTH) == this.solarMonth) && (clr.get(Calendar.DAY_OF_MONTH) == this.solarDay);
}
public String getSFestivalName() {
return this.sFestivalName;
}
public String getLFestivalName() {
return this.lFestivalName;
}
public boolean isLFestival() {
if (!this.isFinded) {
this.findFestival();
}
return this.isLFestival;
}
public boolean isSFestival() {
if (!this.isFinded) {
this.findFestival();
}
return this.isSFestival;
}
public boolean isFestival() {
return this.isSFestival() || this.isLFestival();
}
public boolean isHoliday() {
if (!this.isFinded) {
this.findFestival();
}
return this.isHoliday;
}
public String getDescription() {
if (!this.isFinded) {
this.findFestival();
}
return this.description;
}
private static String getCyclicalString(int cyclicalNumber) {
return SolarTermsUtil.Tianan[SolarTermsUtil.getTianan(cyclicalNumber)] + SolarTermsUtil.Deqi[SolarTermsUtil.getDeqi(cyclicalNumber)];
}
private static int getDeqi(int cyclicalNumber) {
return cyclicalNumber % 12;
}
private static int getTianan(int cyclicalNumber) {
return cyclicalNumber % 10;
}
private static String getLunarYearString(int lunarYear) {
return SolarTermsUtil.getCyclicalString((lunarYear - 1900) + 36);
}
private static String getLunarMonthString(int lunarMonth) {
String lunarMonthString = "";
if (lunarMonth == 1) {
lunarMonthString = SolarTermsUtil.lunarString2[4];
} else {
if (lunarMonth > 9) {
lunarMonthString += SolarTermsUtil.lunarString2[1];
}
if ((lunarMonth % 10) > 0) {
lunarMonthString += SolarTermsUtil.lunarString1[lunarMonth % 10];
}
}
return lunarMonthString;
}
private static String getLunarDayString(int lunarDay) {
if ((lunarDay < 1) || (lunarDay > 30)) {
return "";
}
int i1 = lunarDay / 10;
int i2 = lunarDay % 10;
String c1 = SolarTermsUtil.lunarString2[i1];
String c2 = SolarTermsUtil.lunarString1[i2];
if (lunarDay < 11) {
c1 = SolarTermsUtil.lunarString2[0];
}
if (i2 == 0) {
c2 = SolarTermsUtil.lunarString2[1];
}
return c1 + c2;
}
}