Skip to content

Commit ea3130f

Browse files
author
hoangkien0705
committed
Tính lịch âm, lịch dương trong java
0 parents  commit ea3130f

3 files changed

Lines changed: 447 additions & 0 deletions

File tree

Time-Calc_java/Date.java

Lines changed: 380 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
1+
public class Date {
2+
3+
public static final String[] WEEKDAYS = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
4+
public static final String[] WEEKDAYS_SHORT = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
5+
public static final String[] CAN = {"Giap", "At", "Binh", "Dinh", "Mau", "Ky", "Canh", "Tan", "Nham", "Quy"};
6+
public static final String[] CHI = {"Ti", "Suu", "Dan", "Mao", "Thin", "Ty", "Ngo", "Mui", "Than", "Dau", "Tuat", "Hoi"};
7+
public static final double[] SUNLONG_MAJOR = new double[] {
8+
0, PI/6, 2*PI/6, 3*PI/6, 4*PI/6, 5*PI/6, PI, 7*PI/6, 8*PI/6, 9*PI/6, 10*PI/6, 11*PI/6
9+
};
10+
11+
public static final double PI = Math.PI;
12+
private static final double LOCAL_TIMEZONE = 7.0; // Hanoi, Jakarta timezone..
13+
14+
private int day;
15+
private int month;
16+
private int year;
17+
18+
public Date() {}
19+
20+
public Date(int day, int month, int year) {
21+
this.day = day;
22+
this.month = month;
23+
this.year = year;
24+
}
25+
26+
public double getCentury(int year) {
27+
return Math.floor(year / 100) + 1;
28+
}
29+
30+
public double getCentury() {
31+
return Math.floor(this.year / 100) + 1;
32+
}
33+
34+
public int getMonth4Zeller(int month) {
35+
if (month < 3)
36+
return (month + 10);
37+
return (month - 2);
38+
}
39+
40+
public int year4Zeller(int year) {
41+
return (year % 100);
42+
}
43+
44+
public double _zeller(int day, int month, int year, double century) {
45+
return ((13 * month - 1) / 5 + year / 4 + century/4 + day + year - 2 * century) % 7;
46+
}
47+
48+
// get the day of week.
49+
public String getWeekDay() {
50+
double i = _zeller(this.day, getMonth4Zeller(this.month), year4Zeller(this.year), getCentury(this.year));
51+
return WEEKDAYS[(int)i];
52+
}
53+
54+
public boolean isLeapYear() {
55+
if (((this.year % 4 == 0) && (this.year % 100 != 0)) || (this.year % 400 == 0))
56+
return true;
57+
return false;
58+
}
59+
60+
public int getDayInMonth() {
61+
return ((this.month == 2) ? (28 + (isLeapYear() ? 1 : 0)) : 31 - (this.month - 1) % 7 % 2);
62+
}
63+
64+
public int[] getCalendarTable() {
65+
int[] res = new int[42];
66+
int start = (int)(_zeller(1, getMonth4Zeller(this.month), year4Zeller(this.year), getCentury(this.year)));
67+
int end = getDayInMonth();
68+
for (int i = start; i < (end + start); i++) {
69+
res[i] = (i - start) + 1;
70+
}
71+
72+
return res;
73+
}
74+
75+
public void printCalendar() {
76+
int[] arr = getCalendarTable();
77+
78+
for (int i = 0; i < WEEKDAYS_SHORT.length; i++) {
79+
System.out.print(WEEKDAYS_SHORT[i] + " ");
80+
}
81+
System.out.println();
82+
for (int i = 0; i < arr.length; i++) {
83+
if (i % 7 == 0) {
84+
System.out.println();
85+
}
86+
System.out.print(arr[i] + " ");
87+
}
88+
}
89+
90+
public static int thisIsMagic(int y, int m, int d) {
91+
if (m < 3) {
92+
y--;
93+
m += 12;
94+
}
95+
return 365*y + y/4 - y/100 + y/400 + (153*m - 457)/5 + d - 306;
96+
}
97+
98+
public int getDay() {
99+
return this.day;
100+
}
101+
102+
public int getMonth() {
103+
return this.month;
104+
}
105+
106+
public int getYear() {
107+
return this.year;
108+
}
109+
110+
public int countDaysBetweenTwoDate(int year, int month, int day, int y, int m, int d) {
111+
return thisIsMagic(year, month, day) - thisIsMagic(y, m, d);
112+
}
113+
114+
public String CANCHI() {
115+
return CAN[(this.year + 6) % 10] + " " + CHI[(this.year + 8) % 12];
116+
}
117+
118+
public static int INT(double d) {
119+
return (int)Math.floor(d);
120+
}
121+
122+
public static int MOD(int x, int y) {
123+
int z = x - (int)(y * Math.floor(((double)x / y)));
124+
if (z == 0) {
125+
z = y;
126+
}
127+
return z;
128+
}
129+
130+
public double getJulius() {
131+
double res;
132+
if (this.year > 1582 || (this.year == 1582 && this.month > 10) || (this.year == 1582 && this.month == 10 && this.day > 14)) {
133+
res = 367 * this.year
134+
- INT(7 * (this.year + INT((this.month + 9) / 12)) / 4)
135+
- INT(3 * (INT((this.year + (this.month - 9) / 7) / 100) + 1) / 4)
136+
+ INT(275 * this.month / 9) + this.day + 1721028.5;
137+
} else {
138+
res = 367 * this.year
139+
- INT(7 * (this.year + 5001 + INT((this.month - 9) / 7)) / 4)
140+
+ INT(275 * this.month / 9) + this.day + 1729776.5;
141+
}
142+
return res;
143+
}
144+
145+
public static int[] UniversalFromJulius(double JD) {
146+
int Z, A, alpha, B, C, D, E, dd, mm, yyyy;
147+
double F;
148+
Z = INT(JD + 0.5);
149+
F = (JD + 0.5) - Z;
150+
if (Z < 2299161) {
151+
A = Z;
152+
} else {
153+
alpha = INT((Z - 1867216.25) / 36524.25);
154+
A = Z + 1 + alpha - INT(alpha / 4);
155+
}
156+
B = A + 1524;
157+
C = INT( (B - 122.1) / 365.25);
158+
D = INT( 365.25 * C );
159+
E = INT( (B - D) / 30.6001 );
160+
dd = INT(B - D - INT(30.6001 * E) + F);
161+
if (E < 14) {
162+
mm = E - 1;
163+
} else {
164+
mm = E - 13;
165+
}
166+
if (mm < 3) {
167+
yyyy = C - 4715;
168+
} else {
169+
yyyy = C - 4716;
170+
}
171+
return new int[]{dd, mm, yyyy};
172+
}
173+
174+
175+
176+
public static double SunLongitude(double jdn) {
177+
double T = (jdn - 2451545.0 ) / 36525; // Time in Julian centuries from 2000-01-01 12:00:00 GMT
178+
double T2 = T*T;
179+
double dr = PI/180; // degree to radian
180+
double M = 357.52910 + 35999.05030*T - 0.0001559*T2 - 0.00000048*T*T2; // mean anomaly, degree
181+
double L0 = 280.46645 + 36000.76983*T + 0.0003032*T2; // mean longitude, degree
182+
double DL = (1.914600 - 0.004817*T - 0.000014*T2)*Math.sin(dr*M);
183+
DL = DL + (0.019993 - 0.000101*T)*Math.sin(dr*2*M) + 0.000290*Math.sin(dr*3*M);
184+
double L = L0 + DL; // true longitude, degree
185+
L = L*dr;
186+
L = L - PI*2*(INT(L/(PI*2))); // Normalize to (0, 2*PI)
187+
return L;
188+
}
189+
190+
public static int[] LunarMonth11(int Y) {
191+
double off = LocalToJD(31, 12, Y) - 2415021.076998695;
192+
int k = INT(off / 29.530588853);
193+
double jd = NewMoon(k);
194+
int[] ret = LocalFromJD(jd);
195+
double sunLong = SunLongitude(LocalToJD(ret[0], ret[1], ret[2])); // sun longitude at local midnight
196+
if (sunLong > 3*PI/2) {
197+
jd = NewMoon(k-1);
198+
}
199+
return LocalFromJD(jd);
200+
}
201+
202+
public static int[] UniversalFromJD(double JD) {
203+
int Z, A, alpha, B, C, D, E, dd, mm, yyyy;
204+
double F;
205+
Z = INT(JD+0.5);
206+
F = (JD+0.5)-Z;
207+
if (Z < 2299161) {
208+
A = Z;
209+
} else {
210+
alpha = INT((Z-1867216.25)/36524.25);
211+
A = Z + 1 + alpha - INT(alpha/4);
212+
}
213+
B = A + 1524;
214+
C = INT( (B-122.1)/365.25);
215+
D = INT( 365.25*C );
216+
E = INT( (B-D)/30.6001 );
217+
dd = INT(B - D - INT(30.6001*E) + F);
218+
if (E < 14) {
219+
mm = E - 1;
220+
} else {
221+
mm = E - 13;
222+
}
223+
if (mm < 3) {
224+
yyyy = C - 4715;
225+
} else {
226+
yyyy = C - 4716;
227+
}
228+
return new int[]{dd, mm, yyyy};
229+
}
230+
231+
public static int[] LocalFromJD(double JD) {
232+
return UniversalFromJD(JD + LOCAL_TIMEZONE/24.0);
233+
}
234+
235+
public static double NewMoon(int k) {
236+
double T = k/1236.85;
237+
double T2 = T * T;
238+
double T3 = T2 * T;
239+
double dr = PI/180;
240+
double Jd1 = 2415020.75933 + 29.53058868*k + 0.0001178*T2 - 0.000000155*T3;
241+
Jd1 = Jd1 + 0.00033*Math.sin((166.56 + 132.87*T - 0.009173*T2)*dr);
242+
double M = 359.2242 + 29.10535608*k - 0.0000333*T2 - 0.00000347*T3;
243+
double Mpr = 306.0253 + 385.81691806*k + 0.0107306*T2 + 0.00001236*T3;
244+
double F = 21.2964 + 390.67050646*k - 0.0016528*T2 - 0.00000239*T3;
245+
double C1=(0.1734 - 0.000393*T)*Math.sin(M*dr) + 0.0021*Math.sin(2*dr*M);
246+
C1 = C1 - 0.4068*Math.sin(Mpr*dr) + 0.0161*Math.sin(dr*2*Mpr);
247+
C1 = C1 - 0.0004*Math.sin(dr*3*Mpr);
248+
C1 = C1 + 0.0104*Math.sin(dr*2*F) - 0.0051*Math.sin(dr*(M+Mpr));
249+
C1 = C1 - 0.0074*Math.sin(dr*(M-Mpr)) + 0.0004*Math.sin(dr*(2*F+M));
250+
C1 = C1 - 0.0004*Math.sin(dr*(2*F-M)) - 0.0006*Math.sin(dr*(2*F+Mpr));
251+
C1 = C1 + 0.0010*Math.sin(dr*(2*F-Mpr)) + 0.0005*Math.sin(dr*(2*Mpr+M));
252+
double deltat;
253+
if (T < -11) {
254+
deltat= 0.001 + 0.000839*T + 0.0002261*T2 - 0.00000845*T3 - 0.000000081*T*T3;
255+
} else {
256+
deltat= -0.000278 + 0.000265*T + 0.000262*T2;
257+
};
258+
double JdNew = Jd1 + C1 - deltat;
259+
return JdNew;
260+
}
261+
262+
public static int[][] LunarYear(int Y) {
263+
int[][] ret = null;
264+
int[] month11A = LunarMonth11(Y-1);
265+
double jdMonth11A = LocalToJD(month11A[0], month11A[1], month11A[2]);
266+
int k = (int)Math.floor(0.5 + (jdMonth11A - 2415021.076998695) / 29.530588853);
267+
int[] month11B = LunarMonth11(Y);
268+
double off = LocalToJD(month11B[0], month11B[1], month11B[2]) - jdMonth11A;
269+
boolean leap = off > 365.0;
270+
if (!leap) {
271+
ret = new int[13][5];
272+
} else {
273+
ret = new int[14][5];
274+
}
275+
ret[0] = new int[]{month11A[0], month11A[1], month11A[2], 0, 0};
276+
ret[ret.length - 1] = new int[]{month11B[0], month11B[1], month11B[2], 0, 0};
277+
for (int i = 1; i < ret.length - 1; i++) {
278+
double nm = NewMoon(k+i);
279+
int[] a = LocalFromJD(nm);
280+
ret[i] = new int[]{a[0], a[1], a[2], 0, 0};
281+
}
282+
for (int i = 0; i < ret.length; i++) {
283+
ret[i][3] = MOD(i + 11, 12);
284+
}
285+
if (leap) {
286+
initLeapYear(ret);
287+
}
288+
return ret;
289+
}
290+
291+
292+
static void initLeapYear(int[][] ret) {
293+
double[] sunLongitudes = new double[ret.length];
294+
for (int i = 0; i < ret.length; i++) {
295+
int[] a = ret[i];
296+
double jdAtMonthBegin = LocalToJD(a[0], a[1], a[2]);
297+
sunLongitudes[i] = SunLongitude(jdAtMonthBegin);
298+
}
299+
boolean found = false;
300+
for (int i = 0; i < ret.length; i++) {
301+
if (found) {
302+
ret[i][3] = MOD(i+10, 12);
303+
continue;
304+
}
305+
double sl1 = sunLongitudes[i];
306+
double sl2 = sunLongitudes[i+1];
307+
boolean hasMajorTerm = Math.floor(sl1/PI*6) != Math.floor(sl2/PI*6);
308+
if (!hasMajorTerm) {
309+
found = true;
310+
ret[i][4] = 1;
311+
ret[i][3] = MOD(i+10, 12);
312+
}
313+
}
314+
}
315+
316+
public static double UniversalToJD(int D, int M, int Y) {
317+
double JD;
318+
if (Y > 1582 || (Y == 1582 && M > 10) || (Y == 1582 && M == 10 && D > 14)) {
319+
JD = 367*Y - INT(7*(Y+INT((M+9)/12))/4) - INT(3*(INT((Y+(M-9)/7)/100)+1)/4) + INT(275*M/9)+D+1721028.5;
320+
} else {
321+
JD = 367*Y - INT(7*(Y+5001+INT((M-9)/7))/4) + INT(275*M/9)+D+1729776.5;
322+
}
323+
return JD;
324+
}
325+
326+
public static double LocalToJD(int D, int M, int Y) {
327+
return UniversalToJD(D, M, Y) - LOCAL_TIMEZONE/24.0;
328+
}
329+
330+
331+
// chuyen doi duong lich sang am lich.
332+
public int[] getLunar() {
333+
int yy = this.year;
334+
int[][] ly = LunarYear(this.year);
335+
int[] month11 = ly[ly.length - 1];
336+
double jdToday = LocalToJD(this.day, this.month, this.year);
337+
double jdMonth11 = LocalToJD(month11[0], month11[1], month11[2]);
338+
if (jdToday >= jdMonth11) {
339+
ly = LunarYear(this.year + 1);
340+
yy = this.year + 1;
341+
}
342+
int i = ly.length - 1;
343+
while (jdToday < LocalToJD(ly[i][0], ly[i][1], ly[i][2])) {
344+
i--;
345+
}
346+
int dd = (int)(jdToday - LocalToJD(ly[i][0], ly[i][1], ly[i][2])) + 1;
347+
int mm = ly[i][3];
348+
if (mm >= 11) {
349+
yy--;
350+
}
351+
return new int[] {dd, mm, yy, ly[i][4]};
352+
}
353+
354+
355+
// chuyen doi am lich sang duong lich. leap ? 1 : 0
356+
public static int[] getSolar(int D, int M, int Y, int leap) {
357+
int yy = Y;
358+
if (M >= 11) {
359+
yy = Y+1;
360+
}
361+
int[][] lunarYear = LunarYear(yy);
362+
int[] lunarMonth = null;
363+
for (int i = 0; i < lunarYear.length; i++) {
364+
int[] lm = lunarYear[i];
365+
if (lm[3] == M && lm[4] == leap) {
366+
lunarMonth = lm;
367+
break;
368+
}
369+
}
370+
if (lunarMonth != null) {
371+
double jd = LocalToJD(lunarMonth[0], lunarMonth[1], lunarMonth[2]);
372+
return LocalFromJD(jd + D - 1);
373+
} else {
374+
throw new RuntimeException("Incorrect input!");
375+
}
376+
}
377+
378+
379+
380+
}

0 commit comments

Comments
 (0)