java日期工具類DateUtil-續二
該版本是一次較大的升級,農曆相比公曆複雜太多(真佩服古人的智慧),雖然有規律,但涉及到的取捨、近似的感念太多,況且本身的概念就已經很多了,我在網上也是查閱了很多的資料,雖然找到一些計算的方法,但都有些計算缺陷,後來才終於找到“壽天星文歷”:一個十分精準的萬年曆。雖然它的功能十分強大,但相對的涉及到的計算也很多,邏輯和思路都相當的複雜了,維護成本很大,有時候專案中並不一定要用到這麼強大的農曆,因此該版本目前僅提供了農曆的一些基本功能,在下一版本中,我會引入“壽天星文歷”,以適合更多的大眾需求。
原始碼:
DateUtil類
/** * 獲取簡單農曆物件 * @param date 日期字串 * @return 簡單農曆物件 */ public static SimpleLunarCalendar getSimpleLunarCalendar(String date) { return new SimpleLunarCalendar(DateUtil.StringToDate(date)); } /** * 獲取簡單農曆物件 * @param date 日期 * @return 簡單農曆物件 */ public static SimpleLunarCalendar getSimpleLunarCalendar(Date date) { return new SimpleLunarCalendar(date); }
SimpleLunarCalendar類
package com.util; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; public class SimpleLunarCalendar { /** 最小時間1900-1-31*/ private final static long minTimeInMillis = -2206425952001L; /** 最大時間2099-12-31 */ private final static long maxTimeInMillis = 4102416000000L; /** * 農曆年資料表(1900-2099年)<br> * <br> * 每個農曆年用16進位制來表示,解析時轉為2進位制<br> * 前12位分別表示12個農曆月份的大小月,1是大月,0是小月<br> * 最後4位表示閏月,轉為十進位制後即為閏月值,例如0110,則為閏6月 */ 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 String[] Animals = { "鼠", "牛", "虎", "兔", "龍", "蛇", "馬", "羊", "猴", "雞", "狗", "豬" }; /** 農曆中文字串一 */ private final static String[] lunarString1 = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" }; /** 農曆中文字串二 */ private final static String[] lunarString2 = { "初", "十", "廿", "卅", "正", "臘", "冬", "閏" }; /** 農曆年 */ private int lunarYear; /** 農曆月 */ private int lunarMonth; /** 農曆日 */ private int lunarDay; /** 是否是閏月 */ private boolean isLeap; /** 是否是閏年 */ private boolean isLeapYear; /** 某農曆月的最大天數 */ private int maxDayInMonth = 29; /** * 通過 TimeInMillis 構建農曆資訊 * @param TimeInMillis */ public SimpleLunarCalendar(long TimeInMillis) { this.init(TimeInMillis); } /** * 通過 Date 物件構建農曆資訊 * @param date 指定日期物件 */ public SimpleLunarCalendar(Date date) { if (date == null) date = new Date(); this.init(date.getTime()); } /** * 農曆初始化 * @param timeInMillis 時間毫秒數 */ private void init(long timeInMillis) { if (timeInMillis > minTimeInMillis && timeInMillis < maxTimeInMillis) { // 以農曆為1900年正月一日的1900-1-31作為起始日期 Calendar baseDate = new GregorianCalendar(1900, 0, 31); // 距離起始日期間隔的總天數 long offset = (timeInMillis - baseDate.getTimeInMillis()) / 86400000; // 預設農曆年為1900年,且由此開始推算農曆年份 this.lunarYear = 1900; int daysInLunarYear = SimpleLunarCalendar.getLunarYearDays(this.lunarYear); // 遞減每個農曆年的總天數,確定農曆年份 while (this.lunarYear < 2100 && offset >= daysInLunarYear) { offset -= daysInLunarYear; daysInLunarYear = SimpleLunarCalendar.getLunarYearDays(++this.lunarYear); } // 獲取該農曆年的閏月月份 int leapMonth = SimpleLunarCalendar.getLunarLeapMonth(this.lunarYear); // 沒有閏月則不是閏年 this.isLeapYear = leapMonth > 0; // 預設農曆月為正月,且由此開始推薦農曆月 int lunarMonth = 1; // 是否遞減農曆月 boolean isDecrease = true; boolean isLeap = false; int daysInLunarMonth = 0; // 遞減每個農曆月的總天數,確定農曆月份 while (lunarMonth < 13 && offset > 0) { if (isLeap && !isDecrease) { // 該農曆年閏月的總天數 daysInLunarMonth = SimpleLunarCalendar.getLunarLeapDays(this.lunarYear); isDecrease = true; } else { // 該農曆年正常農曆月份的天數 daysInLunarMonth = SimpleLunarCalendar.getLunarMonthDays(this.lunarYear, lunarMonth); } if (offset < daysInLunarMonth) { break; } offset -= daysInLunarMonth; // 如果農曆月是閏月,則不遞增農曆月份 if (leapMonth == lunarMonth && isLeap == false) { isDecrease = false; isLeap = true; } else { lunarMonth++; } } // 如果daysInLunarMonth為0則說明預設農曆月即為返回的農曆月 this.maxDayInMonth = daysInLunarMonth != 0 ? daysInLunarMonth : SimpleLunarCalendar.getLunarMonthDays(this.lunarYear, lunarMonth); this.lunarMonth = lunarMonth; this.isLeap = (lunarMonth == leapMonth && isLeap); this.lunarDay = (int) offset + 1; } } /** * 獲取某農曆年的總天數 * @param lunarYear 農曆年份 * @return 該農曆年的總天數 */ private static int getLunarYearDays(int lunarYear) { // 按小月計算,農曆年最少有12 * 29 = 348天 int daysInLunarYear = 348; // 遍歷前12位 for (int i = 0x8000; i > 0x8; i >>= 1) { // 每個大月累加一天 daysInLunarYear += ((SimpleLunarCalendar.lunarInfo[lunarYear - 1900] & i) != 0) ? 1 : 0; } // 加上閏月天數 daysInLunarYear += SimpleLunarCalendar.getLunarLeapDays(lunarYear); return daysInLunarYear; } /** * 獲取某農曆年閏月的總天數 * @param lunarYear 農曆年份 * @return 該農曆年閏月的總天數,沒有閏月返回0 */ private static int getLunarLeapDays(int lunarYear) { // 下一年最後4bit為1111,返回30(大月) // 下一年最後4bit不為1111,返回29(小月) // 若該年沒有閏月,返回0 return SimpleLunarCalendar.getLunarLeapMonth(lunarYear) > 0 ? ((SimpleLunarCalendar.lunarInfo[lunarYear - 1899] & 0xf) == 0xf ? 30 : 29) : 0; } /** * 獲取某農曆年閏月月份 * @param lunarYear 農曆年份 * @return 該農曆年閏月的月份,沒有閏月返回0 */ private static int getLunarLeapMonth(int lunarYear) { // 匹配後4位 int leapMonth = SimpleLunarCalendar.lunarInfo[lunarYear - 1900] & 0xf; // 若最後4位全為1或全為0,表示沒閏 leapMonth = (leapMonth == 0xf ? 0 : leapMonth); return leapMonth; } /** * 獲取某農曆年某農曆月份的總天數 * @param lunarYear 農曆年份 * @param lunarMonth 農曆月份 * @return 該農曆年該農曆月的總天數 */ private static int getLunarMonthDays(int lunarYear, int lunarMonth) { // 匹配前12位代表的相應農曆月份的大小月,大月30天,小月29天 int daysInLunarMonth = ((SimpleLunarCalendar.lunarInfo[lunarYear - 1900] & (0x10000 >> lunarMonth)) != 0) ? 30 : 29; return daysInLunarMonth; } /** * 返回指定數字的農曆年份表示字串 * @param lunarYear 農曆年份(數字,0為甲子) * @return 農曆年份字串 */ private static String getLunarYearString(int lunarYear) { String lunarYearString = ""; String year = String.valueOf(lunarYear); for (int i = 0; i < year.length(); i++) { char yearChar = year.charAt(i); int index = Integer.parseInt(String.valueOf(yearChar)); lunarYearString += lunarString1[index]; } return lunarYearString; } /** * 返回指定數字的農曆月份表示字串 * @param lunarMonth 農曆月份(數字) * @return 農曆月份字串 (例:正) */ private static String getLunarMonthString(int lunarMonth) { String lunarMonthString = ""; if (lunarMonth == 1) { lunarMonthString = SimpleLunarCalendar.lunarString2[4]; } else { if (lunarMonth > 9) lunarMonthString += SimpleLunarCalendar.lunarString2[1]; if (lunarMonth % 10 > 0) lunarMonthString += SimpleLunarCalendar.lunarString1[lunarMonth % 10]; } return lunarMonthString; } /** * 返回指定數字的農曆日表示字串 * @param lunarDay 農曆日(數字) * @return 農曆日字串 (例: 廿一) */ private static String getLunarDayString(int lunarDay) { if (lunarDay < 1 || lunarDay > 30) return ""; int i1 = lunarDay / 10; int i2 = lunarDay % 10; String c1 = SimpleLunarCalendar.lunarString2[i1]; String c2 = SimpleLunarCalendar.lunarString1[i2]; if (lunarDay < 11) c1 = SimpleLunarCalendar.lunarString2[0]; if (i2 == 0) c2 = SimpleLunarCalendar.lunarString2[1]; return c1 + c2; } /** * 取農曆年生肖 * @return 農曆年生肖(例:龍) */ public String getAnimalString() { if (lunarYear == 0) return null; return SimpleLunarCalendar.Animals[(this.lunarYear - 4) % 12]; } /** * 返回農曆日期字串 * @return 農曆日期字串 */ public String getDayString() { if (lunarDay == 0) return null; return SimpleLunarCalendar.getLunarDayString(this.lunarDay); } /** * 返回農曆日期字串 * @return 農曆日期字串 */ public String getMonthString() { if (lunarMonth == 0) return null; return (this.isLeap() ? "閏" : "") + SimpleLunarCalendar.getLunarMonthString(this.lunarMonth); } /** * 返回農曆日期字串 * @return 農曆日期字串 */ public String getYearString() { if (lunarYear == 0) return null; return SimpleLunarCalendar.getLunarYearString(this.lunarYear); } /** * 返回農曆表示字串 * @return 農曆字串(例:甲子年正月初三) */ public String getDateString() { if (lunarYear == 0) return null; return this.getYearString() + "年" + this.getMonthString() + "月" + this.getDayString() + "日"; } /** * 農曆年是否是閏月 * @return 農曆年是否是閏月 */ public boolean isLeap() { return isLeap; } /** * 農曆年是否是閏年 * @return 農曆年是否是閏年 */ public boolean isLeapYear() { return isLeapYear; } /** * 當前農曆月是否是大月 * @return 當前農曆月是大月 */ public boolean isBigMonth() { return this.getMaxDayInMonth() > 29; } /** * 當前農曆月有多少天 * @return 天數 */ public int getMaxDayInMonth() { if (lunarYear == 0) return 0; return this.maxDayInMonth; } /** * 農曆日期 * @return 農曆日期 */ public int getDay() { return lunarDay; } /** * 農曆月份 * @return 農曆月份 */ public int getMonth() { return lunarMonth; } /** * 農曆年份 * @return 農曆年份 */ public int getYear() { return lunarYear; } }
說明:該農曆核心演算法是從網上尋找而來,但我進行了完善,適用的年份為:1900年——2099年,我去掉了不精準的部分(如天干地支),目前該簡單農曆只能滿足顯示陰曆資訊,適合需要較為簡單的使用者適用。另外若想支援的年限範圍更廣,則需要修改lunarInfo(農曆年資料表),並做適當的調整(預設農曆年)即可。
============友情連結============
相關推薦
java日期工具類DateUtil-續二
該版本是一次較大的升級,農曆相比公曆複雜太多(真佩服古人的智慧),雖然有規律,但涉及到的取捨、近似的感念太多,況且本身的概念就已經很多了,我在網上也是查閱了很多的資料,雖然找到一些計算的方法,但都有些計算缺陷,後來才終於找到“壽天星文歷”:一個十分精準的萬年曆。雖然它的功能
Java日期工具類
multipl efault 簡體中文 類型 分鐘 sub dateutil 表示 exception public class DateUtil { //默認顯示日期的格式 public static final String DATAFORMAT_ST
SimpleDateFormatUtils-java日期工具類
寫了個日期工具類 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * 格式化日期的工具類 * @author * */ public
日期工具類 DateUtil
工作中需要用到各種日期格式化,以下為平時常用的格式化。 獲取當前時間 Date getCurrentDateTime() 通用日期格式化 String getDateString 通用日期時間格式化,
java date 工具類 DateUtil 格式轉換
package systems.baseutil.tool; /** * <p>Title: 時間和日期的工具類</p> * <p>Description: DateUtil類包含了標準的時間和日期格式,以及這些格式在字串及日期之間
Java 常用工具類(19) : 生成二維碼base64編碼,帶logo版
import java.awt.AlphaComposite; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; imp
(八)Java日期工具類DateUtils日期轉Calendar及TimeZone 詳解(三)
public static Calendar toCalendar(Date date) 說明:將一個日期Date型別轉換為Calendar型別; 引數:date-轉換為Calendar的日期; 返回值:建立的Calendar物件; 丟擲異常:NullPoi
(八)Java日期工具類DateUtils詳解(一)
一、 對指定的日期新增年、月、周、日、小時、分鐘、秒、毫秒 public static Date addDays(Date date, int amount) Dat
java DateUtil日期工具類,獲取當前日期幾天前的日期,一週前的日期
import java.util.Calendar;import java.text.SimpleDateFormat;import java.util.Date;public class DateUtil{/** * 獲取指定日期間隔天數的起始值 * @param date
java開發中常用的日期時間工具類 DateUtil
java開發中常會用到的 日期時間工具類。 package org.demo; import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateForm
java 日期處理工具類 DateUtil
http://bjtdeyx.iteye.com/blog/1551946 Java 日期時間 Date型別,long型別,String型別表現形式的轉換 http://www.xuebuyuan.com/1756921.html
DateUtil日期工具類
gettime ack mes pos time() catch rec 格式 ebe import java.sql.Timestamp; import java.text.DateFormat; import java.text.ParseException;
java之日期工具類DATE
java日期工具類 import java.text.SimpleDateFormat; import java.util.*; public class DateUtil { /** * 獲取SimpleDateFormat * @param parttern 日
java常用工具類(二)—— JSON處理工具類
tor ast val simple sta 轉換 local pass password package com.springboot.commons.utils; import com.springboot.commons.scan.JacksonObjectMapp
JAVA常用工具類(二) ArrayUtils類
該工具類主要運算元組。 以下陣列的型別使用T代替,同一函式中T代表相同型別。T可包含的型別有:Object、boolean、int、byte、char、double、float、long、short。 陣列判斷函式: 1.判斷是否存在,返回boolean: ArrayUtils.co
java工具類-日期工具類
1、獲得時間戳 為了統一其他語言的如php和unix系統獲取的時間戳是10位長度的,精確到秒。 java時間戳長度是13位,精確到毫秒 我們獲取時間戳需要相應處理。 //獲取當前時間戳,除以1000,獲取到長度為10位的,精確到秒 public s
Java原始碼分析——java.util工具包解析(二)——HashSet、TreeSet、LinkedHashSet類解析
Set,即集合,與數學上的定義一樣,集合具有三個特點: 無序性:一個集合中,每個元素的地位都是相同的,元素之間是無序的。 互異性:一個集合中,任何兩個元素都認為是不相同的,即每個元素只能出現一次。 確定性:給定一個集
java時間日期工具類
package com.bigname.common; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date;
java Calendar 工具類(幾天前的日期,幾天後的日期)(持續補充)
public class DateTest { public static void main(String[] args) { Date date = new Date(); // 新建一個日期 SimpleDateFormat sdf = new Sim
Java基於apache.commons.lang的日期工具類簡單封裝
package cn.lettleprincess.util; import java.text.ParseException; import java.util.ArrayList; import java.util.Calendar; import java.util