diff --git a/.gitignore b/.gitignore
index e057863..df74b90 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,6 @@ target
*.springBeans
.gradle
build
+.buildpath
dependency-reduced-pom.xml
-/src
-
+/src
\ No newline at end of file
diff --git a/aimeizi-tutorials/pom.xml b/aimeizi-tutorials/pom.xml
index f6cc179..8276ff5 100644
--- a/aimeizi-tutorials/pom.xml
+++ b/aimeizi-tutorials/pom.xml
@@ -88,5 +88,30 @@
17.0
+
+
+ org.jsoup
+ jsoup
+ 1.7.3
+
+
+
+ commons-io
+ commons-io
+ 2.4
+
+
+
+ commons-lang
+ commons-lang
+ 2.6
+
+
+
+ com.ning
+ async-http-client
+ 1.8.13
+
+
diff --git a/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/CalendarToLauar.java b/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/CalendarToLauar.java
new file mode 100644
index 0000000..f5a0038
--- /dev/null
+++ b/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/CalendarToLauar.java
@@ -0,0 +1,280 @@
+package net.aimeizi.tutorials;
+
+import java.util.Calendar;
+import java.util.Date;
+
+
+/**
+ * 转农历
+ * @author
+ */
+public class CalendarToLauar {
+
+ private static int monCyl, dayCyl, yearCyl;
+
+ private static int year, month, day;
+
+ private static boolean isLeap;
+
+ private static int[] lunarInfo = { 0x04bd8, 0x04ae0, 0x0a570, 0x054d5,
+ 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0,
+ 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2,
+ 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40,
+ 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0,
+ 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7,
+ 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0,
+ 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355,
+ 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0,
+ 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263,
+ 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0,
+ 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6, 0x095b0,
+ 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46,
+ 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50,
+ 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960, 0x0d954,
+ 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0,
+ 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0,
+ 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50,
+ 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,
+ 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6,
+ 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0,
+ 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0 };
+
+ private static int[] solarMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31,30, 31 };
+
+ private static String[] Gan = { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛",
+ "壬", "癸" };
+
+ private static String[] Zhi = { "子", "丑", "寅", "卯", "辰", "巳", "午", "未",
+ "申", "酉", "戌", "亥" };
+
+ private static String[] Animals = { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊",
+ "猴", "鸡", "狗", "猪" };
+
+ private static int[] sTermInfo = { 0, 21208, 42467, 63836, 85337, 107014,
+ 128867, 150921, 173149, 195551, 218072, 240693, 263343, 285989,
+ 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224,
+ 483532, 504758 };
+
+ private static String[] nStr1 = { "日", "一", "二", "三", "四", "五", "六", "七",
+ "八", "九", "十" };
+
+ private static String[] nStr2 = { "初", "十", "廿十", "卅十", " " };
+
+ private static String[] monthNong = { "正", "正", "二", "三", "四", "五", "六",
+ "七", "八", "九", "十", "十一", "十二" };
+
+ private static String[] yearName = { "零", "壹", "贰", "叁", "肆", "伍", "陆",
+ "柒", "捌", "玖" };
+
+
+
+ //====================================== 传回农历 y年的总天数
+ private static int lYearDays(int y) {
+ int i;
+ int sum = 348; //29*12
+ for (i = 0x8000; i > 0x8; i >>= 1) {
+ //OurLog.debug("i="+i);
+ sum += (lunarInfo[y - 1900] & i) == 0 ? 0 : 1; //大月+1天
+ }
+ return (sum + leapDays(y)); //+闰月的天数
+ }
+
+ //====================================== 传回农历 y年闰月的天数
+ private static int leapDays(int y) {
+ if (leapMonth(y) != 0)
+ return ((lunarInfo[y - 1900] & 0x10000) == 0 ? 29 : 30);
+ else
+ return (0);
+ }
+
+ //====================================== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
+ private static int leapMonth(int y) {
+ return (lunarInfo[y - 1900] & 0xf);
+ }
+
+ //====================================== 传回农历 y年m月的总天数
+ private static int monthDays(int y, int m) {
+ return ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0 ? 29 : 30);
+ }
+
+ //====================================== 算出农历, 传入日期物件, 传回农历日期物件
+ // 该物件属性有 .year .month .day .isLeap .yearCyl .dayCyl .monCyl
+ private static void Lunar1(Date objDate) {
+ int i, leap = 0, temp = 0;
+ Calendar cl = Calendar.getInstance();
+ cl.set(1900, 0, 31);
+ Date baseDate = cl.getTime();
+
+ int offset = (int) ((objDate.getTime() - baseDate.getTime()) / 86400000); //天数(86400000=24*60*60*1000)
+ dayCyl = offset + 40;
+ monCyl = 14;
+ //得到年数
+ for (i = 1900; i < 2050 && offset > 0; i++) {
+ temp = lYearDays(i); //农历每年天数
+ offset -= temp;
+ monCyl += 12;
+ }
+ if (offset < 0) {
+ offset += temp;
+ i--;
+ monCyl -= 12;
+ }
+ year = i; //农历年份
+ yearCyl = i - 1864; //1864年是甲子年
+ leap = leapMonth(i); //闰哪个月
+ isLeap = false;
+ for (i = 1; i < 13 && offset > 0; i++) {
+ //闰月
+ if (leap > 0 && i == (leap + 1) && isLeap == false) {
+ --i;
+ isLeap = true;
+ temp = leapDays(year);
+ } else {
+ temp = monthDays(year, i);
+ }
+ //解除闰月
+ if (isLeap == true && i == (leap + 1))
+ isLeap = false;
+ offset -= temp;
+ if (isLeap == false)
+ monCyl++;
+ }
+ if (offset == 0 && leap > 0 && i == leap + 1)
+ if (isLeap) {
+ isLeap = false;
+ } else {
+ isLeap = true;
+ --i;
+ --monCyl;
+ }
+ if (offset < 0) {
+ offset += temp;
+ --i;
+ --monCyl;
+ }
+ month = i; //农历月份
+ day = offset + 1; //农历天份
+ //System.out.println(day);
+ }
+
+ private static int getYear() {
+ return (year);
+ }
+
+ private static int getMonth() {
+ return (month);
+ }
+
+ private static int getDay() {
+ return (day);
+ }
+
+ private static int getMonCyl() {
+ return (monCyl);
+ }
+
+ private static int getYearCyl() {
+ return (yearCyl);
+ }
+
+ private static int getDayCyl() {
+ return (dayCyl);
+ }
+
+ private static boolean getIsLeap() {
+ return (isLeap);
+ }
+
+ //============================== 传入 offset 传回干支, 0=甲子
+ private static String cyclical(int num) {
+ return (Gan[num % 10] + Zhi[num % 12]);
+ }
+
+ //====================== 中文日期
+ private static String cDay(int d) {
+ String s;
+ switch (d) {
+ case 10:
+ s = "初十";
+ break;
+ case 20:
+ s = "二十";
+ break;
+ case 30:
+ s = "三十";
+ break;
+ default:
+ s = nStr2[(int) (d / 10)];//取商
+ s += nStr1[d % 10];//取余
+ }
+ return (s);
+ }
+
+ private static String cYear(int y) {
+ String s = " ";
+ int d;
+ while (y > 0) {
+ d = y % 10;
+ y = (y - d) / 10;
+ s = yearName[d] + s;
+ }
+ return (s);
+ }
+
+ public static String getLunar(String year, String month, String day) {
+
+ Date sDObj;
+ String s;
+ int SY, SM, SD;
+
+ int sy;
+ SY = Integer.parseInt(year);
+ SM = Integer.parseInt(month);
+ SD = Integer.parseInt(day);
+ sy = (SY - 4) % 12;
+ Calendar cl = Calendar.getInstance();
+ cl.set(SY, SM - 1, SD);
+ sDObj = cl.getTime();
+
+ //日期
+ Lunar1(sDObj); //农历
+ s = "农历 " + "【" + Animals[sy] + "】" + cYear(getYear()) + "年" + " ";
+
+ s += (getIsLeap() ? "闰" : "") + monthNong[getMonth()] + "月"
+ + (monthDays(getYear(), getMonth()) == 29 ? "小" : "大");
+ s += cDay(getDay()) + " ";
+ s += cyclical(getYearCyl()) + "年" + cyclical(getMonCyl()) + "月"
+ + cyclical(getDayCyl()) + "日";
+ return s;
+ }
+ public static String getSimpleLunar(String year, String month, String day)
+ {
+
+ Date sDObj;
+ String s;
+ int SY, SM, SD;
+
+ int sy;
+
+ SY = Integer.parseInt(year);
+ SM = Integer.parseInt(month);
+ SD = Integer.parseInt(day);
+ sy = (SY - 4) % 12;
+ Calendar cl = Calendar.getInstance();
+ cl.set(SY, SM - 1, SD);
+ sDObj = cl.getTime();
+
+ //日期
+ Lunar1(sDObj); //农历
+ s =monthNong[getMonth()] + "月" + cDay(getDay()) + "";
+
+ return s;
+ }
+
+ public static void main(String[] args) {
+ System.out.println(getLunar("2014", "8", "1"));//含天干地支的农历格式 (农历 【马】贰零壹肆 年 七月小初六 甲午年壬申月甲辰日)
+ System.out.println(CalendarToLauar.getSimpleLunar("2014", "8", "1"));//简短的农历格式 (七月初六)
+ System.out.println(SolarTerm.getSoralTerm(2014,8,7));//获取节气 (立秋)
+ }
+
+}
diff --git a/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/HTMLImageFetcher.java b/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/HTMLImageFetcher.java
new file mode 100644
index 0000000..5374c60
--- /dev/null
+++ b/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/HTMLImageFetcher.java
@@ -0,0 +1,146 @@
+package net.aimeizi.tutorials;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+
+/**
+ * 下载HTML中的非本地图片,并替换内容
+ * @author 冯靖
+ *
+ */
+public class HTMLImageFetcher {
+
+ protected final static String img_path = "target/";//下载后图片存放目录
+
+ private final static String user_agent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0";
+
+ protected final static SimpleDateFormat FMT_FN = new SimpleDateFormat("yyyyMM/ddHHmmss_");
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ String html = "这张图片很漂亮啊!"
+ + "
"//演示远程图片,抓取到本地,并修改为本地图片路径
+ + "
"
+ + " ,太帅了!
";//本地图片,则不做处理
+ System.out.println(fetchHTML_Images(html));
+ }
+
+ /**
+ * 下载HTML文档中的所有图片
+ * @param html
+ * @return
+ */
+ protected static String fetchHTML_Images(String html) {
+ if (StringUtils.isBlank(html)) {
+ return html;
+ }
+ HashMap img_urls = new HashMap();
+ Document doc = Jsoup.parse(html);
+ Elements imgs = doc.select("img");
+ for (int i = 0; i < imgs.size(); i++) {
+ Element img = imgs.get(i);
+ String src = img.attr("src");
+ if (!src.startsWith("/")) {
+ try {
+ URL imgUrl = new URL(src);
+ String imgHost = imgUrl.getHost().toLowerCase();
+ if (!imgHost.endsWith(".oschina.net")) {//排除域名为oschina.net的图片(如果图片地址中包含oschina.net,则不进行抓取)
+ String new_src = img_urls.get(src);
+ if (new_src == null) {
+ new_src = fetchImageViaHttp(imgUrl);
+ img_urls.put(src, new_src);
+ }
+ img.attr("src", new_src);
+ }
+ } catch (MalformedURLException e) {
+ img.remove();
+ } catch (Exception e) {
+ e.printStackTrace();
+ img.remove();
+ }
+ }
+ }
+ return doc.body().html();
+ }
+
+ private static String fetchImageViaHttp(URL imgUrl) throws IOException {
+ String sURL = imgUrl.toString();
+ String imgFile = imgUrl.getPath();
+ HttpURLConnection conn = (HttpURLConnection) imgUrl.openConnection();
+ String uri = null;
+ try {
+ conn.setAllowUserInteraction(false);
+ conn.setDoOutput(true);
+ conn.addRequestProperty("Cache-Control", "no-cache");
+ conn.addRequestProperty("User-Agent", user_agent);
+ conn.addRequestProperty("Referer", sURL.substring(0, sURL.indexOf('/', sURL.indexOf('.')) + 1));
+ conn.connect();
+
+ if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
+ return null;
+ }
+
+ InputStream imgData = conn.getInputStream();
+ String ext = FilenameUtils.getExtension(imgFile).toLowerCase();
+
+ if (!isImageFile("aa." + ext)) {
+ ext = "jpg";
+ }
+
+ uri = FMT_FN.format(new Date()) + RandomStringUtils.randomAlphanumeric(4) + '.' + ext;
+
+ System.err.println(uri);
+
+ File fileDest = new File(img_path + uri);
+ if (!fileDest.getParentFile().exists()) {
+ fileDest.getParentFile().mkdirs();
+ }
+
+ FileOutputStream fos = new FileOutputStream(fileDest);
+
+ try {
+ IOUtils.copy(imgData, fos);
+ } finally {
+ IOUtils.closeQuietly(imgData);
+ IOUtils.closeQuietly(fos);
+ }
+
+ } finally {
+ conn.disconnect();
+ }
+ return img_path + uri;
+ }
+
+ private static boolean isImageFile(String fileName) {
+ String[] imgSuffixs = {
+ ".gif", ".jpg", ".jpeg", ".png",
+ ".tiff", ".bmp",
+ };
+ for(String suffix : imgSuffixs) {
+ if(fileName.endsWith(suffix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/LunarCalendar.java b/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/LunarCalendar.java
new file mode 100644
index 0000000..ea615e4
--- /dev/null
+++ b/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/LunarCalendar.java
@@ -0,0 +1,341 @@
+package net.aimeizi.tutorials;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class LunarCalendar {
+
+ private int year; //农历的年份
+ private int month;
+ private int day;
+ private String lunarMonth; //农历的月份
+ private boolean leap;
+ public int leapMonth = 0; //闰的是哪个月
+
+ final static String chineseNumber[] = { "一", "二", "三", "四", "五", "六", "七","八", "九", "十", "十一", "十二" };
+
+ static SimpleDateFormat chineseDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
+
+ final static long[] lunarInfo = new long[] { 0x04bd8, 0x04ae0, 0x0a570,
+ 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,
+ 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0,
+ 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50,
+ 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566,
+ 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0,
+ 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4,
+ 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550,
+ 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950,
+ 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260,
+ 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0,
+ 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,
+ 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40,
+ 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3,
+ 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960,
+ 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0,
+ 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9,
+ 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0,
+ 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65,
+ 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0,
+ 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2,
+ 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0 };
+
+ //农历部分假日
+ final static String[] lunarHoliday = new String[]{
+ "0101 春节",
+ "0115 元宵",
+ "0505 端午",
+ "0707 七夕情人",
+ "0715 中元",
+ "0815 中秋",
+ "0909 重阳",
+ "1208 腊八",
+ "1224 小年",
+ "0100 除夕"
+ };
+
+ //公历部分节假日
+ final static String[] solarHoliday = new String[]{
+ "0101 元旦",
+ "0214 情人",
+ "0308 妇女",
+ "0312 植树",
+ "0315 消费者权益日",
+ "0401 愚人",
+ "0501 劳动",
+ "0504 青年",
+ "0512 护士",
+ "0601 儿童",
+ "0701 建党",
+ "0801 建军",
+ "0808 父亲",
+ "0909 毛泽东逝世纪念",
+ "0910 教师",
+ "0928 孔子诞辰",
+ "1001 国庆",
+ "1006 老人",
+ "1024 联合国日",
+ "1112 孙中山诞辰纪念",
+ "1220 澳门回归纪念",
+ "1225 圣诞",
+ "1226 毛泽东诞辰纪念"
+ };
+
+ // ====== 传回农历 y年的总天数
+ final private static int yearDays(int y) {
+ int i, sum = 348;
+ for (i = 0x8000; i > 0x8; i >>= 1) {
+ if ((lunarInfo[y - 1900] & i) != 0)
+ sum += 1;
+ }
+ return (sum + leapDays(y));
+ }
+
+ // ====== 传回农历 y年闰月的天数
+ final private static int leapDays(int y) {
+ if (leapMonth(y) != 0) {
+ if ((lunarInfo[y - 1900] & 0x10000) != 0)
+ return 30;
+ else
+ return 29;
+ } else
+ return 0;
+ }
+
+ // ====== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
+ final private static int leapMonth(int y) {
+ return (int) (lunarInfo[y - 1900] & 0xf);
+ }
+
+ // ====== 传回农历 y年m月的总天数
+ final private static int monthDays(int y, int m) {
+ if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0)
+ return 29;
+ else
+ return 30;
+ }
+
+ // ====== 传回农历 y年的生肖
+ final public String animalsYear(int year) {
+ final String[] Animals = new String[] { "鼠", "牛", "虎", "兔", "龙", "蛇",
+ "马", "羊", "猴", "鸡", "狗", "猪" };
+ return Animals[(year - 4) % 12];
+ }
+
+ // ====== 传入 月日的offset 传回干支, 0=甲子
+ final private static String cyclicalm(int num) {
+ final String[] Gan = new String[] { "甲", "乙", "丙", "丁", "戊", "己", "庚",
+ "辛", "壬", "癸" };
+ final String[] Zhi = new String[] { "子", "丑", "寅", "卯", "辰", "巳", "午",
+ "未", "申", "酉", "戌", "亥" };
+ return (Gan[num % 10] + Zhi[num % 12]);
+ }
+
+ // ====== 传入 offset 传回干支, 0=甲子
+ final public String cyclical(int year) {
+ int num = year - 1900 + 36;
+ return (cyclicalm(num));
+ }
+
+ public static String getChinaDayString(int day) {
+ String chineseTen[] = { "初", "十", "廿", "卅" };
+ int n = day % 10 == 0 ? 9 : day % 10 - 1;
+ if (day > 30)
+ return "";
+ if (day == 10)
+ return "初十";
+ else
+ return chineseTen[day / 10] + chineseNumber[n];
+ }
+
+ /**
+ * 传出y年m月d日对应的农历.
+ * yearCyl3:农历年与1864的相差数
+ * monCyl4:从1900年1月31日以来,闰月数
+ * dayCyl5:与1900年1月31日相差的天数,再加40
+ * isday: 这个参数为false---日期为节假日时,阴历日期就返回节假日 ,true---不管日期是否为节假日依然返回这天对应的阴历日期
+ * @param cal
+ * @return
+ */
+ public String getLunarDate(int year_log, int month_log, int day_log, boolean isday) {
+ int yearCyl, monCyl, dayCyl;
+ String nowadays;
+ Date baseDate = null;
+ Date nowaday = null;
+ try {
+ baseDate = chineseDateFormat.parse("1900年1月31日");
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+
+ nowadays = year_log + "年" + month_log + "月" + day_log + "日";
+ try {
+ nowaday = chineseDateFormat.parse(nowadays);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+
+ // 求出和1900年1月31日相差的天数
+ int offset = (int) ((nowaday.getTime() - baseDate.getTime()) / 86400000L);
+ dayCyl = offset + 40;
+ monCyl = 14;
+
+ // 用offset减去每农历年的天数
+ // 计算当天是农历第几天
+ // i最终结果是农历的年份
+ // offset是当年的第几天
+ int iYear, daysOfYear = 0;
+ for (iYear = 1900; iYear < 10000 && offset > 0; iYear++) {
+ daysOfYear = yearDays(iYear);
+ offset -= daysOfYear;
+ monCyl += 12;
+ }
+ if (offset < 0) {
+ offset += daysOfYear;
+ iYear--;
+ monCyl -= 12;
+ }
+ // 农历年份
+ year = iYear;
+ setYear(year); //设置公历对应的农历年份
+
+ yearCyl = iYear - 1864;
+ leapMonth = leapMonth(iYear); // 闰哪个月,1-12
+ leap = false;
+
+ // 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
+ int iMonth, daysOfMonth = 0;
+ for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) {
+ // 闰月
+ if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) {
+ --iMonth;
+ leap = true;
+ daysOfMonth = leapDays(year);
+ } else
+ daysOfMonth = monthDays(year, iMonth);
+
+ offset -= daysOfMonth;
+ // 解除闰月
+ if (leap && iMonth == (leapMonth + 1))
+ leap = false;
+ if (!leap)
+ monCyl++;
+ }
+ // offset为0时,并且刚才计算的月份是闰月,要校正
+ if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {
+ if (leap) {
+ leap = false;
+ } else {
+ leap = true;
+ --iMonth;
+ --monCyl;
+ }
+ }
+ // offset小于0时,也要校正
+ if (offset < 0) {
+ offset += daysOfMonth;
+ --iMonth;
+ --monCyl;
+ }
+ month = iMonth;
+ setLunarMonth(chineseNumber[month - 1] + "月"); //设置对应的阴历月份
+ day = offset + 1;
+
+ if(!isday){
+ //如果日期为节假日则阴历日期则返回节假日
+ for(int i = 0; i < solarHoliday.length; i++){
+ //返回公历节假日名称
+ String sd = solarHoliday[i].split(" ")[0]; //节假日的日期
+ String sdv = solarHoliday[i].split(" ")[1]; //节假日的名称
+ String smonth_v = month_log+"";
+ String sday_v = day_log+"";
+ String smd = "";
+ if(month_log < 10){
+ smonth_v = "0"+month_log;
+ }
+ if(day_log < 10){
+ sday_v = "0"+day_log;
+ }
+ smd = smonth_v+sday_v;
+ if(sd.trim().equals(smd.trim())){
+ return sdv;
+ }
+ }
+
+ for(int i = 0; i < lunarHoliday.length; i++){
+ //返回农历节假日名称
+ String ld =lunarHoliday[i].split(" ")[0]; //节假日的日期
+ String ldv = lunarHoliday[i].split(" ")[1]; //节假日的名称
+ String lmonth_v = month+"";
+ String lday_v = day+"";
+ String lmd = "";
+ if(month < 10){
+ lmonth_v = "0"+month;
+ }
+ if(day < 10){
+ lday_v = "0"+day;
+ }
+ lmd = lmonth_v+lday_v;
+ if(ld.trim().equals(lmd.trim())){
+ return ldv;
+ }
+ }
+ }
+ if (day == 1)
+ return chineseNumber[month - 1] + "月";
+ else
+ return getChinaDayString(day);
+
+ }
+
+
+ public static void main(String[] args) {
+ System.out.println(new LunarCalendar().getLunarDate(2014, 8, 2,false));
+ }
+
+
+ public String toString() {
+ if (chineseNumber[month - 1] == "一" && getChinaDayString(day) == "初一")
+ return "农历" + year + "年";
+ else if (getChinaDayString(day) == "初一")
+ return chineseNumber[month - 1] + "月";
+ else
+ return getChinaDayString(day);
+ // return year + "年" + (leap ? "闰" : "") + chineseNumber[month - 1] + "月" + getChinaDayString(day);
+ }
+
+
+
+ public int getLeapMonth() {
+ return leapMonth;
+ }
+
+ public void setLeapMonth(int leapMonth) {
+ this.leapMonth = leapMonth;
+ }
+
+ /**
+ * 得到当前日期对应的阴历月份
+ * @return
+ */
+ public String getLunarMonth() {
+ return lunarMonth;
+ }
+
+ public void setLunarMonth(String lunarMonth) {
+ this.lunarMonth = lunarMonth;
+ }
+
+ /**
+ * 得到当前年对应的农历年份
+ * @return
+ */
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+
+}
diff --git a/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/RelativeTime.java b/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/RelativeTime.java
new file mode 100644
index 0000000..377070d
--- /dev/null
+++ b/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/RelativeTime.java
@@ -0,0 +1,64 @@
+package net.aimeizi.tutorials;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * 显示友好的时间
+ *
+ * @author 冯靖
+ *
+ */
+public class RelativeTime {
+
+
+ public static String timeAgo(String timeStr) {
+ Date date = null;
+ try {
+ SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+ date = format.parse(timeStr);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ return "";
+ }
+
+ long timeStamp = date.getTime();
+
+ Date currentTime = new Date();
+ long currentTimeStamp = currentTime.getTime();
+ long seconds = (currentTimeStamp - timeStamp) / 1000;
+
+ long minutes = Math.abs(seconds / 60);
+ long hours = Math.abs(minutes / 60);
+ long days = Math.abs(hours / 24);
+
+ if (seconds <= 15) {
+ return "刚刚";
+ } else if (seconds < 60) {
+ return seconds + "秒前";
+ } else if (seconds < 120) {
+ return "1分钟前";
+ } else if (minutes < 60) {
+ return minutes + "分钟前";
+ } else if (minutes < 120) {
+ return "1小时前";
+ } else if (hours < 24) {
+ return hours + "小时前";
+ } else if (hours < 24 * 2) {
+ return "1天前";
+ } else if (days < 7) {//一周以内
+ return days + "天前";
+ } else {
+ SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日");
+ String dateString = formatter.format(date);
+ return dateString;
+ }
+
+ }
+
+ public static void main(String[] args) throws Exception {
+ System.out.println(timeAgo("2014/07/31 22:35:59"));
+ }
+
+}
diff --git a/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/SensitiveWord.java b/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/SensitiveWord.java
new file mode 100644
index 0000000..52394c2
--- /dev/null
+++ b/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/SensitiveWord.java
@@ -0,0 +1,104 @@
+package net.aimeizi.tutorials;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.LineIterator;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Java敏感词过滤
+ * @author 冯靖
+ *
+ */
+public class SensitiveWord {
+
+ private final static File wordfilter = new File("src/main/resources/wordfilter.txt");
+
+ private static long lastModified = 0L;
+
+ private static List words = new ArrayList();
+
+ private static void _CheckReload(){
+ if(wordfilter.lastModified() > lastModified){
+ synchronized(SensitiveWord.class){
+ try{
+ lastModified = wordfilter.lastModified();
+ LineIterator lines = FileUtils.lineIterator(wordfilter, "utf-8");
+ while(lines.hasNext()){
+ String line = lines.nextLine();
+ if(StringUtils.isNotBlank(line))
+ words.add(StringUtils.trim(line).toLowerCase());
+ }
+ }catch(IOException e){
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * 检查敏感字内容
+ * @param contents
+ */
+ public static String Check(String...contents) {
+ if(!wordfilter.exists())
+ return null;
+ _CheckReload();
+ for(String word : words){
+ for(String content : contents)
+ if(content!=null && content.indexOf(word) >= 0)
+ return word;
+ }
+ return null;
+ }
+
+ public static List List() {
+ _CheckReload();
+ return words;
+ }
+
+ public static void Add(String word) throws IOException {
+ word = word.toLowerCase();
+ if(!words.contains(word)){
+ words.add(word);
+ FileUtils.writeLines(wordfilter, "UTF-8", words);
+ lastModified = wordfilter.lastModified();
+ }
+ }
+
+ public static void Delete(String word) throws IOException {
+ word = word.toLowerCase();
+ words.remove(word);
+ FileUtils.writeLines(wordfilter, "UTF-8", words);
+ lastModified = wordfilter.lastModified();
+ }
+
+
+ public static void main(String[] args) throws Exception{
+
+ String mgz = "法论功大法好!苍井空是世界的!";
+
+ System.out.println("-----------------------敏感字列表----------------------------");
+ System.out.println(Arrays.toString(SensitiveWord.List().toArray()));
+ System.out.println("----------------------------------------------------------");
+ System.out.println("检查敏感字:"+SensitiveWord.Check(mgz));
+ System.out.println("-----------------------敏感字词替换----------------------------");
+ System.out.println(mgz.replace(SensitiveWord.Check(mgz), "*"));
+ System.out.println("----------------------------------------------------------");
+ System.out.println("添加敏感字:法论功");
+ SensitiveWord.Add("法论功");
+ System.out.println("-----------------------敏感字列表----------------------------");
+ System.out.println(Arrays.toString(SensitiveWord.List().toArray()));
+ System.out.println("----------------------------------------------------------");
+ System.out.println("删除敏感字:法论功");
+ SensitiveWord.Delete("法论功");
+ System.out.println("-----------------------敏感字列表----------------------------");
+ System.out.println(Arrays.toString(SensitiveWord.List().toArray()));
+ }
+
+}
diff --git a/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/SolarTerm.java b/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/SolarTerm.java
new file mode 100644
index 0000000..f47bb34
--- /dev/null
+++ b/aimeizi-tutorials/src/main/java/net/aimeizi/tutorials/SolarTerm.java
@@ -0,0 +1,62 @@
+package net.aimeizi.tutorials;
+
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * 二十四节气
+ * @author welcome
+ *
+ */
+public class SolarTerm {
+
+ final static long[] STermInfo = new long[] { 0, 21208, 42467, 63836, 85337,
+ 107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343,
+ 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795,
+ 462224, 483532, 504758 };
+
+ private static final String[] SolarTerm = new String[] { "小寒", "大寒", "立春",
+ "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑",
+ "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至" };
+
+
+ /** 核心方法 根据日期得到节气 */
+ public static String getSoralTerm(Date Date) {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(Date);
+
+ int y = cal.get(Calendar.YEAR);
+ int m = cal.get(Calendar.MONTH) + 1;
+ int d = cal.get(Calendar.DAY_OF_MONTH);
+
+ return getSoralTerm(y, m, d);
+ }
+
+ /** 核心方法 根据日期(y年m月d日得到节气 */
+ public static String getSoralTerm(int y, int m, int d) {
+ String solarTerms;
+ if (d == sTerm(y, (m - 1) * 2))
+ solarTerms = SolarTerm[(m - 1) * 2];
+ else if (d == sTerm(y, (m - 1) * 2 + 1))
+ solarTerms = SolarTerm[(m - 1) * 2 + 1];
+ else {
+ // 到这里说明非节气时间
+ solarTerms = "";
+ }
+ return solarTerms;
+ }
+
+ // ===== y年的第n个节气为几日(从小寒起算)
+ private static int sTerm(int y, int n) {
+ Calendar cal = Calendar.getInstance();
+ cal.set(1900, 0, 6, 2, 5, 0);
+ long temp = cal.getTime().getTime();
+ cal.setTime(new Date((long) ((31556925974.7 * (y - 1900) + STermInfo[n] * 60000L) + temp)));
+ return cal.get(Calendar.DAY_OF_MONTH);
+ }
+
+
+ public static void main(String[] args) {
+ System.out.println(getSoralTerm(2014,8,7));//获取节气 (立秋)
+ }
+}
diff --git a/aimeizi-tutorials/src/main/resources/wordfilter.txt b/aimeizi-tutorials/src/main/resources/wordfilter.txt
new file mode 100644
index 0000000..26cfb67
--- /dev/null
+++ b/aimeizi-tutorials/src/main/resources/wordfilter.txt
@@ -0,0 +1,4 @@
+毛
+毛线
+毛泽东
+苍井空